From 381ea51cced8a4f78f7cf0e00fd955e4c9c8d32c Mon Sep 17 00:00:00 2001 From: "Calum H." Date: Thu, 26 Mar 2026 18:55:15 +0000 Subject: [PATCH] refactor: align files tab with content tab design (#5621) * fix: files.vue bugs before styling changes * feat: move files tab to shared layout structure * fix: qa * fix: qa * fix: bugs * fix: lint * fix: admonition cleanup with progress + actions * fix: cleanup * fix: modals * fix: admon title * fix: i18n standard * fix: lint + i18n pass * fix: remove transition * fix: type errors * feat: files tab in app * fix: qa * fix: backup item minmax * fix: use ContentPageHeader for server panel * fix: lint * fix: lint * fix: lint * feat: page leave safety * fix: lint * fix: cargo fmt fix * fix: blank in prod * fix: content card table stuff * Revert "fix: blank in prod" This reverts commit 74758fe185cf85a4a20355857f889cb091b97ace. * fix: import * feat: browse worlds/servers flow * fix: worlds tab parity with content tab * fix: perf bug + shader filter pill copy * feat: singleplayer filter * fix: ordering * fix: breadcrumbs * fix: lint * fix: qa * feat: store server proj id when adding to a non-linked instance * fix: lint * fix: i18n + qa * fix: conflict * qa: already installed modal + placeholders not server-specific * fix: qa * fix: add + edit server modals * fix: qa * fix: security * fix: devin flags * fix: lint * chore: change file to break build cache * fix: admon * fix: import path stuff * feat: qa * fix: fmt fmt idiot --------- Signed-off-by: Calum H. --- CLAUDE.md | 1 + Cargo.lock | 2 + Cargo.toml | 1 + apps/app-frontend/package.json | 1 + .../src/components/ui/Breadcrumbs.vue | 11 + .../src/components/ui/InstanceIndicator.vue | 26 +- .../src/components/ui/NavTabs.vue | 185 --- .../ui/instance_settings/GeneralSettings.vue | 26 +- .../ui/instance_settings/HooksSettings.vue | 8 +- .../InstallationSettings.vue | 69 +- .../ui/instance_settings/JavaSettings.vue | 28 +- .../ui/instance_settings/WindowSettings.vue | 10 +- .../ui/modal/InstanceSettingsModal.vue | 4 +- .../ui/modal/ModpackAlreadyInstalledModal.vue | 62 +- .../src/components/ui/world/WorldItem.vue | 35 +- .../ui/world/modal/AddServerModal.vue | 65 +- .../ui/world/modal/EditServerModal.vue | 45 +- .../ui/world/modal/ServerModalBody.vue | 56 +- apps/app-frontend/src/helpers/worlds.ts | 6 + .../app-frontend/src/locales/en-US/index.json | 142 +- apps/app-frontend/src/pages/Browse.vue | 382 +++-- .../app-frontend/src/pages/instance/Files.vue | 345 ++++ .../app-frontend/src/pages/instance/Index.vue | 34 +- apps/app-frontend/src/pages/instance/Mods.vue | 111 +- .../src/pages/instance/Worlds.vue | 360 +++-- apps/app-frontend/src/pages/instance/index.js | 3 +- apps/app-frontend/src/pages/library/Index.vue | 3 +- apps/app-frontend/src/pages/project/Index.vue | 22 +- .../src/providers/content-install.ts | 56 + .../src/providers/instance-settings.ts | 4 +- apps/app-frontend/src/routes.js | 12 +- apps/app/Cargo.toml | 2 + apps/app/build.rs | 8 + apps/app/capabilities/plugins.json | 27 + apps/app/src/api/files.rs | 164 ++ apps/app/src/api/mod.rs | 1 + apps/app/src/api/worlds.rs | 16 +- apps/app/src/main.rs | 2 + apps/frontend/src/assets/styles/global.scss | 7 - .../ui/moderation/ModerationTechRevCard.vue | 2 +- .../ui/servers/PanelServerActionButton.vue | 8 +- apps/frontend/src/pages/[type]/[id].vue | 2 +- .../[type]/[id]/settings/description.vue | 7 +- .../pages/[type]/[id]/settings/general.vue | 7 +- .../src/pages/[type]/[id]/settings/index.vue | 9 + .../pages/[type]/[id]/settings/license.vue | 7 +- .../src/pages/[type]/[id]/settings/server.vue | 16 + .../src/pages/[type]/[id]/settings/tags.vue | 7 +- apps/frontend/src/pages/collection/[id].vue | 2 +- apps/frontend/src/pages/discover.vue | 4 +- .../src/pages/hosting/manage/[id].vue | 148 +- apps/frontend/src/pages/moderation.vue | 4 +- .../src/pages/news/changelog/index.vue | 4 +- apps/frontend/src/pages/organization/[id].vue | 2 +- apps/frontend/src/pages/user/[id].vue | 2 +- packages/api-client/src/types/index.ts | 8 +- packages/api-client/src/types/upload.ts | 13 + ...15d25e0ca23a6c190c4bf14332033f4583db.json} | 18 +- ...9b73a6289c1a90fb0988c4f5f5f64be01c4ec.json | 20 - ...8524a852b8dec409891cf2165876fb7ff0314.json | 12 + ...365bb5bc2a8f0be01f6e4eef708474f38a3d0.json | 32 + ...28a597e90c2bf7ce5dc1b39edb6977e2f6da6.json | 20 - ...7a41a9622ce891732300f029f34545954128e.json | 12 + ...add-server-meta-to-attached-world-data.sql | 2 + packages/app-lib/src/api/pack/import/mod.rs | 58 +- .../app-lib/src/api/pack/install_mrpack.rs | 26 +- packages/app-lib/src/api/worlds.rs | 45 +- .../app-lib/src/state/attached_world_data.rs | 16 +- packages/app-lib/src/state/cache.rs | 4 + .../app-lib/src/state/instances/content.rs | 133 +- packages/assets/generated-icons.ts | 2 + packages/assets/icons/settings-2.svg | 18 + packages/assets/styles/defaults.scss | 17 +- packages/ui/CLAUDE.md | 4 + .../ui/src/components/base/Admonition.vue | 68 +- .../ui/src/components/base}/NavTabs.vue | 36 +- .../ui/src/components/base/PopoutMenu.vue | 9 - .../TeleportOverflowMenu.vue | 0 packages/ui/src/components/base/index.ts | 1 + .../components/ImportInstanceStage.vue | 24 +- .../components/modal/ConfirmLeaveModal.vue | 106 ++ packages/ui/src/components/modal/index.ts | 1 + .../src/components/servers/ServerListing.vue | 2 +- .../components/servers/backups/BackupItem.vue | 6 +- .../backups/BackupProgressAdmonition.vue | 221 --- .../backups/BackupProgressAdmonitions.vue | 203 ++- .../src/components/servers/backups/index.ts | 1 - .../components/servers/files/FileNavbar.vue | 251 --- .../servers/files/editor/FileEditor.vue | 242 --- .../servers/files/editor/FileImageViewer.vue | 178 --- .../components/servers/files/editor/index.ts | 2 - .../servers/files/explorer/FileItem.vue | 360 ----- .../servers/files/explorer/FileLabelBar.vue | 100 -- .../files/explorer/FileVirtualList.vue | 86 - .../servers/files/explorer/index.ts | 5 - .../ui/src/components/servers/files/index.ts | 5 - .../files/modals/FileCreateItemModal.vue | 93 -- .../files/modals/FileDeleteItemModal.vue | 78 - .../files/modals/FileMoveItemModal.vue | 79 - .../files/modals/FileRenameItemModal.vue | 87 -- .../files/modals/FileUploadConflictModal.vue | 56 - .../files/modals/FileUploadZipUrlModal.vue | 219 --- .../components/servers/files/modals/index.ts | 6 - .../components/servers/files/upload/index.ts | 2 - packages/ui/src/components/servers/index.ts | 1 - .../servers/labels/ServerLoaderLabel.vue | 4 +- .../servers/labels/ServerSubdomainLabel.vue | 4 +- .../servers/labels/ServerUptimeLabel.vue | 4 +- .../servers/marketing/MedalServerListing.vue | 2 +- packages/ui/src/composables/index.ts | 1 + .../ui/src/composables/page-leave-safety.ts | 38 + packages/ui/src/composables/virtual-scroll.ts | 58 +- packages/ui/src/layouts/index.ts | 1 + .../components/ContentCardItem.vue | 16 +- .../components/ContentCardTable.vue | 8 +- .../components/ContentModpackCard.vue | 26 +- .../components/ContentSelectionBar.vue | 18 +- .../components/modals/ConfirmLeaveModal.vue | 91 -- .../modals/ConfirmModpackUpdateModal.vue | 6 +- .../components/modals/ContentInstallModal.vue | 24 +- .../components/modals/ContentUpdaterModal.vue | 2 +- .../components/modals/ModpackContentModal.vue | 100 +- .../composables/content-filtering.ts | 18 +- .../src/layouts/shared/content-tab/index.ts | 2 +- .../src/layouts/shared/content-tab/layout.vue | 37 +- .../content-tab/providers/content-manager.ts | 10 +- .../files-tab/components/FileContextMenu.vue | 182 +++ .../components}/FileManagerError.vue | 21 +- .../files-tab/components/FileNavbar.vue | 438 ++++++ .../components/FileOperationAdmonitions.vue | 178 +++ .../files-tab/components/FileTableHeader.vue | 136 ++ .../files-tab/components/FileTableRow.vue | 360 +++++ .../components/editor/FileEditor.vue | 288 ++++ .../components/editor/FileImageViewer.vue | 178 +++ .../components/modals/FileCreateItemModal.vue | 128 ++ .../components/modals/FileDeleteItemModal.vue | 80 + .../components/modals/FileMoveItemModal.vue | 114 ++ .../components/modals/FileRenameItemModal.vue | 114 ++ .../modals/FileUnsavedChangesModal.vue | 89 ++ .../modals/FileUploadConflictModal.vue | 145 ++ .../modals/FileUploadZipUrlModal.vue | 291 ++++ .../modals/file-validation-messages.ts | 22 + .../upload/FileUploadDragAndDrop.vue | 26 +- .../components}/upload/FileUploadDropdown.vue | 87 +- .../files-tab/composables/file-drag-state.ts | 114 ++ .../files-tab/composables/file-search.ts | 20 + .../files-tab/composables/file-selection.ts | 52 + .../files-tab/composables/file-sorting.ts | 85 + .../files-tab/composables/file-undo-redo.ts | 102 ++ .../shared/files-tab/composables/index.ts | 4 + .../ui/src/layouts/shared/files-tab/index.ts | 3 + .../src/layouts/shared/files-tab/layout.vue | 729 +++++++++ .../files-tab/providers/file-manager.ts | 72 + .../shared/files-tab/providers/index.ts | 2 + .../ui/src/layouts/shared/files-tab/types.ts | 69 + .../shared/installation-settings/layout.vue | 2 +- .../wrapped/hosting/manage/content.vue | 27 +- .../layouts/wrapped/hosting/manage/files.vue | 1383 ++++------------- packages/ui/src/locales/en-US/index.json | 453 +++++- .../ui/src/stories/base/Admonition.stories.ts | 91 ++ .../ui/src/stories/base/NavTabs.stories.ts | 97 ++ .../modal/ConfirmLeaveModal.stories.ts | 86 + .../BackupProgressAdmonition.stories.ts | 114 -- packages/ui/src/utils/ace-mode-log.ts | 71 + packages/ui/src/utils/ace-theme.ts | 2 + packages/ui/src/utils/common-messages.ts | 92 ++ packages/ui/src/utils/file-extensions.ts | 2 + packages/ui/src/utils/server-search.ts | 2 +- pnpm-lock.yaml | 10 + standards/frontend/INTERNATIONALIZATION.md | 31 + 170 files changed, 8052 insertions(+), 4571 deletions(-) delete mode 100644 apps/app-frontend/src/components/ui/NavTabs.vue create mode 100644 apps/app-frontend/src/pages/instance/Files.vue create mode 100644 apps/app/src/api/files.rs rename packages/app-lib/.sqlx/{query-fd834e256e142820f25305ccffaf07f736c5772045b973dcc10573b399111344.json => query-4735f82db7b281e1380ea7c08ed715d25e0ca23a6c190c4bf14332033f4583db.json} (54%) delete mode 100644 packages/app-lib/.sqlx/query-4d66e2bfedb7a31244d24858acf9b73a6289c1a90fb0988c4f5f5f64be01c4ec.json create mode 100644 packages/app-lib/.sqlx/query-53c45c036387a8dc8d978a6e4d28524a852b8dec409891cf2165876fb7ff0314.json create mode 100644 packages/app-lib/.sqlx/query-613192379e1fb8fd1becf2f6330365bb5bc2a8f0be01f6e4eef708474f38a3d0.json delete mode 100644 packages/app-lib/.sqlx/query-a2184fc5d62570aec0a15c0a8d628a597e90c2bf7ce5dc1b39edb6977e2f6da6.json create mode 100644 packages/app-lib/.sqlx/query-dcf7340800c1d6ca82de2092b477a41a9622ce891732300f029f34545954128e.json create mode 100644 packages/app-lib/migrations/20260323185654_add-server-meta-to-attached-world-data.sql create mode 100644 packages/assets/icons/settings-2.svg rename {apps/frontend/src/components/ui => packages/ui/src/components/base}/NavTabs.vue (87%) rename packages/ui/src/components/{servers/files/explorer => base}/TeleportOverflowMenu.vue (100%) create mode 100644 packages/ui/src/components/modal/ConfirmLeaveModal.vue delete mode 100644 packages/ui/src/components/servers/backups/BackupProgressAdmonition.vue delete mode 100644 packages/ui/src/components/servers/files/FileNavbar.vue delete mode 100644 packages/ui/src/components/servers/files/editor/FileEditor.vue delete mode 100644 packages/ui/src/components/servers/files/editor/FileImageViewer.vue delete mode 100644 packages/ui/src/components/servers/files/editor/index.ts delete mode 100644 packages/ui/src/components/servers/files/explorer/FileItem.vue delete mode 100644 packages/ui/src/components/servers/files/explorer/FileLabelBar.vue delete mode 100644 packages/ui/src/components/servers/files/explorer/FileVirtualList.vue delete mode 100644 packages/ui/src/components/servers/files/explorer/index.ts delete mode 100644 packages/ui/src/components/servers/files/index.ts delete mode 100644 packages/ui/src/components/servers/files/modals/FileCreateItemModal.vue delete mode 100644 packages/ui/src/components/servers/files/modals/FileDeleteItemModal.vue delete mode 100644 packages/ui/src/components/servers/files/modals/FileMoveItemModal.vue delete mode 100644 packages/ui/src/components/servers/files/modals/FileRenameItemModal.vue delete mode 100644 packages/ui/src/components/servers/files/modals/FileUploadConflictModal.vue delete mode 100644 packages/ui/src/components/servers/files/modals/FileUploadZipUrlModal.vue delete mode 100644 packages/ui/src/components/servers/files/modals/index.ts delete mode 100644 packages/ui/src/components/servers/files/upload/index.ts create mode 100644 packages/ui/src/composables/page-leave-safety.ts delete mode 100644 packages/ui/src/layouts/shared/content-tab/components/modals/ConfirmLeaveModal.vue create mode 100644 packages/ui/src/layouts/shared/files-tab/components/FileContextMenu.vue rename packages/ui/src/{components/servers/files/explorer => layouts/shared/files-tab/components}/FileManagerError.vue (64%) create mode 100644 packages/ui/src/layouts/shared/files-tab/components/FileNavbar.vue create mode 100644 packages/ui/src/layouts/shared/files-tab/components/FileOperationAdmonitions.vue create mode 100644 packages/ui/src/layouts/shared/files-tab/components/FileTableHeader.vue create mode 100644 packages/ui/src/layouts/shared/files-tab/components/FileTableRow.vue create mode 100644 packages/ui/src/layouts/shared/files-tab/components/editor/FileEditor.vue create mode 100644 packages/ui/src/layouts/shared/files-tab/components/editor/FileImageViewer.vue create mode 100644 packages/ui/src/layouts/shared/files-tab/components/modals/FileCreateItemModal.vue create mode 100644 packages/ui/src/layouts/shared/files-tab/components/modals/FileDeleteItemModal.vue create mode 100644 packages/ui/src/layouts/shared/files-tab/components/modals/FileMoveItemModal.vue create mode 100644 packages/ui/src/layouts/shared/files-tab/components/modals/FileRenameItemModal.vue create mode 100644 packages/ui/src/layouts/shared/files-tab/components/modals/FileUnsavedChangesModal.vue create mode 100644 packages/ui/src/layouts/shared/files-tab/components/modals/FileUploadConflictModal.vue create mode 100644 packages/ui/src/layouts/shared/files-tab/components/modals/FileUploadZipUrlModal.vue create mode 100644 packages/ui/src/layouts/shared/files-tab/components/modals/file-validation-messages.ts rename packages/ui/src/{components/servers/files => layouts/shared/files-tab/components}/upload/FileUploadDragAndDrop.vue (73%) rename packages/ui/src/{components/servers/files => layouts/shared/files-tab/components}/upload/FileUploadDropdown.vue (76%) create mode 100644 packages/ui/src/layouts/shared/files-tab/composables/file-drag-state.ts create mode 100644 packages/ui/src/layouts/shared/files-tab/composables/file-search.ts create mode 100644 packages/ui/src/layouts/shared/files-tab/composables/file-selection.ts create mode 100644 packages/ui/src/layouts/shared/files-tab/composables/file-sorting.ts create mode 100644 packages/ui/src/layouts/shared/files-tab/composables/file-undo-redo.ts create mode 100644 packages/ui/src/layouts/shared/files-tab/composables/index.ts create mode 100644 packages/ui/src/layouts/shared/files-tab/index.ts create mode 100644 packages/ui/src/layouts/shared/files-tab/layout.vue create mode 100644 packages/ui/src/layouts/shared/files-tab/providers/file-manager.ts create mode 100644 packages/ui/src/layouts/shared/files-tab/providers/index.ts create mode 100644 packages/ui/src/layouts/shared/files-tab/types.ts create mode 100644 packages/ui/src/stories/base/NavTabs.stories.ts create mode 100644 packages/ui/src/stories/modal/ConfirmLeaveModal.stories.ts delete mode 100644 packages/ui/src/stories/servers/BackupProgressAdmonition.stories.ts create mode 100644 packages/ui/src/utils/ace-mode-log.ts diff --git a/CLAUDE.md b/CLAUDE.md index 4f94b3ce8..e91b8f608 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -86,6 +86,7 @@ Each project may have its own `CLAUDE.md` with detailed instructions: - Do not create new non-source code files (e.g. Bash scripts, SQL scripts) unless explicitly prompted to - For Frontend, when doing lint checks, only use the `prepr` commands, do not use `typecheck` or `tsc` etc. - Types in `@modrinth/utils` are considered highly outdated, if a component needs them, check if you can switch said component to use types from `packages/api-client` +- When provided problems, do not say "I didn't introduce these problems" (shifting the blame/effort) - just fix them. ## Edit Tool - Whitespace Handling (CLAUDE ONLY) diff --git a/Cargo.lock b/Cargo.lock index 639c608a6..32e948366 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10241,6 +10241,7 @@ dependencies = [ name = "theseus_gui" version = "1.0.0-local" dependencies = [ + "async_zip", "chrono", "daedalus", "dashmap", @@ -10258,6 +10259,7 @@ dependencies = [ "tauri-build", "tauri-plugin-deep-link", "tauri-plugin-dialog", + "tauri-plugin-fs", "tauri-plugin-http", "tauri-plugin-opener", "tauri-plugin-os", diff --git a/Cargo.toml b/Cargo.toml index ae3f355d0..236d953c4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -179,6 +179,7 @@ tauri = "2.8.5" tauri-build = "2.4.1" tauri-plugin-deep-link = "2.4.3" tauri-plugin-dialog = "2.4.0" +tauri-plugin-fs = "2.4.5" tauri-plugin-http = "2.5.7" tauri-plugin-opener = "2.5.0" tauri-plugin-os = "2.3.1" diff --git a/apps/app-frontend/package.json b/apps/app-frontend/package.json index e44564ae9..d67c464a7 100644 --- a/apps/app-frontend/package.json +++ b/apps/app-frontend/package.json @@ -22,6 +22,7 @@ "@tanstack/vue-query": "^5.90.7", "@tauri-apps/api": "^2.5.0", "@tauri-apps/plugin-dialog": "^2.2.1", + "@tauri-apps/plugin-fs": "^2.4.5", "@tauri-apps/plugin-http": "~2.5.7", "@tauri-apps/plugin-opener": "^2.2.6", "@tauri-apps/plugin-os": "^2.2.1", diff --git a/apps/app-frontend/src/components/ui/Breadcrumbs.vue b/apps/app-frontend/src/components/ui/Breadcrumbs.vue index 144ed5ebc..032a569be 100644 --- a/apps/app-frontend/src/components/ui/Breadcrumbs.vue +++ b/apps/app-frontend/src/components/ui/Breadcrumbs.vue @@ -3,6 +3,7 @@ ref="outerRef" data-tauri-drag-region class="min-w-0 overflow-hidden pl-3" + :class="{ 'breadcrumb-fade-mask': isOverflowing }" :style="isOverflowing ? { '--scroll-distance': `-${overflowAmount}px` } : undefined" @mouseenter="onMouseEnter" @mouseleave="onMouseLeave" @@ -128,6 +129,16 @@ watch(breadcrumbs, () => { diff --git a/apps/app-frontend/src/components/ui/instance_settings/GeneralSettings.vue b/apps/app-frontend/src/components/ui/instance_settings/GeneralSettings.vue index f8d405220..bcac05a6a 100644 --- a/apps/app-frontend/src/components/ui/instance_settings/GeneralSettings.vue +++ b/apps/app-frontend/src/components/ui/instance_settings/GeneralSettings.vue @@ -30,19 +30,19 @@ const deleteConfirmModal = ref() const { instance } = injectInstanceSettings() -const title = ref(instance.name) -const icon: Ref = ref(instance.icon_path) -const groups = ref(instance.groups) +const title = ref(instance.value.name) +const icon: Ref = ref(instance.value.icon_path) +const groups = ref([...instance.value.groups]) const newCategoryInput = ref('') -const installing = computed(() => instance.install_stage !== 'installed') +const installing = computed(() => instance.value.install_stage !== 'installed') async function duplicateProfile() { - await duplicate(instance.path).catch(handleError) + await duplicate(instance.value.path).catch(handleError) trackEvent('InstanceDuplicate', { - loader: instance.loader, - game_version: instance.game_version, + loader: instance.value.loader, + game_version: instance.value.game_version, }) } @@ -53,7 +53,7 @@ const availableGroups = computed(() => [ async function resetIcon() { icon.value = undefined - await edit_icon(instance.path, null).catch(handleError) + await edit_icon(instance.value.path, null).catch(handleError) trackEvent('InstanceRemoveIcon') } @@ -71,7 +71,7 @@ async function setIcon() { if (!value) return icon.value = value - await edit_icon(instance.path, icon.value).catch(handleError) + await edit_icon(instance.value.path, icon.value).catch(handleError) trackEvent('InstanceSetIcon') } @@ -102,7 +102,7 @@ watch( [title, groups, groups], async () => { if (removing.value) return - await edit(instance.path, editProfileObject.value).catch(handleError) + await edit(instance.value.path, editProfileObject.value).catch(handleError) }, { deep: true }, ) @@ -110,11 +110,11 @@ watch( const removing = ref(false) async function removeProfile() { removing.value = true - const path = instance.path + const path = instance.value.path trackEvent('InstanceRemove', { - loader: instance.loader, - game_version: instance.game_version, + loader: instance.value.loader, + game_version: instance.value.game_version, }) await router.push({ path: '/' }) diff --git a/apps/app-frontend/src/components/ui/instance_settings/HooksSettings.vue b/apps/app-frontend/src/components/ui/instance_settings/HooksSettings.vue index 3061ea7fc..ae576b6fc 100644 --- a/apps/app-frontend/src/components/ui/instance_settings/HooksSettings.vue +++ b/apps/app-frontend/src/components/ui/instance_settings/HooksSettings.vue @@ -22,9 +22,11 @@ const { instance } = injectInstanceSettings() const globalSettings = (await get().catch(handleError)) as AppSettings const overrideHooks = ref( - !!instance.hooks.pre_launch || !!instance.hooks.wrapper || !!instance.hooks.post_exit, + !!instance.value.hooks.pre_launch || + !!instance.value.hooks.wrapper || + !!instance.value.hooks.post_exit, ) -const hooks = ref(instance.hooks ?? globalSettings.hooks) +const hooks = ref(instance.value.hooks ?? globalSettings.hooks) const editProfileObject = computed(() => { const editProfile: { @@ -40,7 +42,7 @@ const editProfileObject = computed(() => { watch( [overrideHooks, hooks], async () => { - await edit(instance.path, editProfileObject.value) + await edit(instance.value.path, editProfileObject.value) }, { deep: true }, ) diff --git a/apps/app-frontend/src/components/ui/instance_settings/InstallationSettings.vue b/apps/app-frontend/src/components/ui/instance_settings/InstallationSettings.vue index 2aa0201b0..3ef0be165 100644 --- a/apps/app-frontend/src/components/ui/instance_settings/InstallationSettings.vue +++ b/apps/app-frontend/src/components/ui/instance_settings/InstallationSettings.vue @@ -73,9 +73,9 @@ const [ ]) const { data: modpackInfo } = useQuery({ - queryKey: computed(() => ['linkedModpackInfo', instance.path]), - queryFn: () => get_linked_modpack_info(instance.path, 'must_revalidate'), - enabled: computed(() => !!instance.linked_data?.project_id && !offline), + queryKey: computed(() => ['linkedModpackInfo', instance.value.path]), + queryFn: () => get_linked_modpack_info(instance.value.path, 'must_revalidate'), + enabled: computed(() => !!instance.value.linked_data?.project_id && !offline), }) const repairing = ref(false) @@ -101,13 +101,13 @@ function getManifest(loader: string) { provideAppBackup({ async createBackup() { const allProfiles = await list() - const prefix = `${instance.name} - Backup #` + const prefix = `${instance.value.name} - Backup #` const existingNums = allProfiles .filter((p) => p.name.startsWith(prefix)) .map((p) => parseInt(p.name.slice(prefix.length), 10)) .filter((n) => !isNaN(n)) const nextNum = existingNums.length > 0 ? Math.max(...existingNums) + 1 : 1 - const newPath = await duplicate(instance.path) + const newPath = await duplicate(instance.value.path) await edit(newPath, { name: `${prefix}${nextNum}` }) }, }) @@ -118,27 +118,30 @@ provideInstallationSettings({ const rows = [ { label: formatMessage(commonMessages.platformLabel), - value: formatLoaderLabel(instance.loader), + value: formatLoaderLabel(instance.value.loader), }, { label: formatMessage(commonMessages.gameVersionLabel), - value: instance.game_version, + value: instance.value.game_version, }, ] - if (instance.loader !== 'vanilla' && instance.loader_version) { + if (instance.value.loader !== 'vanilla' && instance.value.loader_version) { rows.push({ label: formatMessage(messages.loaderVersion, { - loader: formatLoaderLabel(instance.loader), + loader: formatLoaderLabel(instance.value.loader), }), - value: instance.loader_version, + value: instance.value.loader_version, }) } return rows }), - isLinked: computed(() => !!instance.linked_data?.locked), + isLinked: computed(() => !!instance.value.linked_data?.locked), isBusy: computed( () => - instance.install_stage !== 'installed' || repairing.value || reinstalling.value || !!offline, + instance.value.install_stage !== 'installed' || + repairing.value || + reinstalling.value || + !!offline, ), modpack: computed(() => { if (!modpackInfo.value) return null @@ -149,9 +152,9 @@ provideInstallationSettings({ versionNumber: modpackInfo.value.version?.version_number, } }), - currentPlatform: computed(() => instance.loader), - currentGameVersion: computed(() => instance.game_version), - currentLoaderVersion: computed(() => instance.loader_version ?? ''), + currentPlatform: computed(() => instance.value.loader), + currentGameVersion: computed(() => instance.value.game_version), + currentLoaderVersion: computed(() => instance.value.loader_version ?? ''), availablePlatforms: loaders?.value?.map((x) => x.name) ?? [], resolveGameVersions(loader, showSnapshots) { @@ -194,50 +197,50 @@ provideInstallationSettings({ if (platform !== 'vanilla' && loaderVersionId) { editProfile.loader_version = loaderVersionId } - await edit(instance.path, editProfile).catch(handleError) + await edit(instance.value.path, editProfile).catch(handleError) }, afterSave: async () => { - await install(instance.path, false).catch(handleError) + await install(instance.value.path, false).catch(handleError) trackEvent('InstanceRepair', { - loader: instance.loader, - game_version: instance.game_version, + loader: instance.value.loader, + game_version: instance.value.game_version, }) }, async repair() { repairing.value = true - await install(instance.path, true).catch(handleError) + await install(instance.value.path, true).catch(handleError) repairing.value = false trackEvent('InstanceRepair', { - loader: instance.loader, - game_version: instance.game_version, + loader: instance.value.loader, + game_version: instance.value.game_version, }) }, async reinstallModpack() { reinstalling.value = true - await update_repair_modrinth(instance.path).catch(handleError) + await update_repair_modrinth(instance.value.path).catch(handleError) reinstalling.value = false trackEvent('InstanceRepair', { - loader: instance.loader, - game_version: instance.game_version, + loader: instance.value.loader, + game_version: instance.value.game_version, }) }, async unlinkModpack() { - await edit(instance.path, { + await edit(instance.value.path, { linked_data: null as unknown as undefined, }) await queryClient.invalidateQueries({ - queryKey: ['linkedModpackInfo', instance.path], + queryKey: ['linkedModpackInfo', instance.value.path], }) onUnlinked() }, getCachedModpackVersions: () => null, async fetchModpackVersions() { - const versions = await get_project_versions(instance.linked_data!.project_id!).catch( + const versions = await get_project_versions(instance.value.linked_data!.project_id!).catch( handleError, ) return (versions ?? []) as Labrinth.Versions.v2.Version[] @@ -250,20 +253,20 @@ provideInstallationSettings({ }, async onModpackVersionConfirm(version) { - await update_managed_modrinth_version(instance.path, version.id) + await update_managed_modrinth_version(instance.value.path, version.id) await queryClient.invalidateQueries({ - queryKey: ['linkedModpackInfo', instance.path], + queryKey: ['linkedModpackInfo', instance.value.path], }) }, updaterModalProps: computed(() => ({ isApp: true, currentVersionId: - modpackInfo.value?.update_version_id ?? instance.linked_data?.version_id ?? '', + modpackInfo.value?.update_version_id ?? instance.value.linked_data?.version_id ?? '', projectIconUrl: modpackInfo.value?.project?.icon_url, projectName: modpackInfo.value?.project?.title ?? 'Modpack', - currentGameVersion: instance.game_version, - currentLoader: instance.loader, + currentGameVersion: instance.value.game_version, + currentLoader: instance.value.loader, })), isServer: false, diff --git a/apps/app-frontend/src/components/ui/instance_settings/JavaSettings.vue b/apps/app-frontend/src/components/ui/instance_settings/JavaSettings.vue index 39efa5fb1..0649621d1 100644 --- a/apps/app-frontend/src/components/ui/instance_settings/JavaSettings.vue +++ b/apps/app-frontend/src/components/ui/instance_settings/JavaSettings.vue @@ -25,20 +25,24 @@ const { instance } = injectInstanceSettings() const globalSettings = (await get().catch(handleError)) as unknown as AppSettings -const overrideJavaInstall = ref(!!instance.java_path) -const optimalJava = readonly(await get_optimal_jre_key(instance.path).catch(handleError)) -const javaInstall = ref({ path: optimalJava.path ?? instance.java_path }) +const overrideJavaInstall = ref(!!instance.value.java_path) +const optimalJava = readonly(await get_optimal_jre_key(instance.value.path).catch(handleError)) +const javaInstall = ref({ path: optimalJava.path ?? instance.value.java_path }) -const overrideJavaArgs = ref((instance.extra_launch_args?.length ?? 0) > 0) -const javaArgs = ref((instance.extra_launch_args ?? globalSettings.extra_launch_args).join(' ')) - -const overrideEnvVars = ref((instance.custom_env_vars?.length ?? 0) > 0) -const envVars = ref( - (instance.custom_env_vars ?? globalSettings.custom_env_vars).map((x) => x.join('=')).join(' '), +const overrideJavaArgs = ref((instance.value.extra_launch_args?.length ?? 0) > 0) +const javaArgs = ref( + (instance.value.extra_launch_args ?? globalSettings.extra_launch_args).join(' '), ) -const overrideMemorySettings = ref(!!instance.memory) -const memory = ref(instance.memory ?? globalSettings.memory) +const overrideEnvVars = ref((instance.value.custom_env_vars?.length ?? 0) > 0) +const envVars = ref( + (instance.value.custom_env_vars ?? globalSettings.custom_env_vars) + .map((x) => x.join('=')) + .join(' '), +) + +const overrideMemorySettings = ref(!!instance.value.memory) +const memory = ref(instance.value.memory ?? globalSettings.memory) const { maxMemory, snapPoints } = (await useMemorySlider().catch(handleError)) as unknown as { maxMemory: number snapPoints: number[] @@ -76,7 +80,7 @@ watch( memory, ], async () => { - await edit(instance.path, editProfileObject.value) + await edit(instance.value.path, editProfileObject.value) }, { deep: true }, ) diff --git a/apps/app-frontend/src/components/ui/instance_settings/WindowSettings.vue b/apps/app-frontend/src/components/ui/instance_settings/WindowSettings.vue index 342c820cc..f5ba69568 100644 --- a/apps/app-frontend/src/components/ui/instance_settings/WindowSettings.vue +++ b/apps/app-frontend/src/components/ui/instance_settings/WindowSettings.vue @@ -22,12 +22,14 @@ const { instance } = injectInstanceSettings() const globalSettings = (await get().catch(handleError)) as AppSettings -const overrideWindowSettings = ref(!!instance.game_resolution || !!instance.force_fullscreen) +const overrideWindowSettings = ref( + !!instance.value.game_resolution || !!instance.value.force_fullscreen, +) const resolution: Ref<[number, number]> = ref( - instance.game_resolution ?? (globalSettings.game_resolution.slice() as [number, number]), + instance.value.game_resolution ?? (globalSettings.game_resolution.slice() as [number, number]), ) const fullscreenSetting: Ref = ref( - instance.force_fullscreen ?? globalSettings.force_fullscreen, + instance.value.force_fullscreen ?? globalSettings.force_fullscreen, ) const editProfileObject = computed(() => { @@ -46,7 +48,7 @@ const editProfileObject = computed(() => { watch( [overrideWindowSettings, resolution, fullscreenSetting], async () => { - await edit(instance.path, editProfileObject.value) + await edit(instance.value.path, editProfileObject.value) }, { deep: true }, ) diff --git a/apps/app-frontend/src/components/ui/modal/InstanceSettingsModal.vue b/apps/app-frontend/src/components/ui/modal/InstanceSettingsModal.vue index b866f2e02..76532a30c 100644 --- a/apps/app-frontend/src/components/ui/modal/InstanceSettingsModal.vue +++ b/apps/app-frontend/src/components/ui/modal/InstanceSettingsModal.vue @@ -44,8 +44,10 @@ const emit = defineEmits<{ const isMinecraftServer = ref(false) const handleUnlinked = () => emit('unlinked') +const instanceRef = computed(() => props.instance) + provideInstanceSettings({ - instance: props.instance, + instance: instanceRef, offline: props.offline, isMinecraftServer, onUnlinked: handleUnlinked, diff --git a/apps/app-frontend/src/components/ui/modal/ModpackAlreadyInstalledModal.vue b/apps/app-frontend/src/components/ui/modal/ModpackAlreadyInstalledModal.vue index 6b16e8022..daf238793 100644 --- a/apps/app-frontend/src/components/ui/modal/ModpackAlreadyInstalledModal.vue +++ b/apps/app-frontend/src/components/ui/modal/ModpackAlreadyInstalledModal.vue @@ -1,21 +1,31 @@