From 16766be82f5bb2f6e48045984b43a87bf5284649 Mon Sep 17 00:00:00 2001 From: Prospector <6166773+Prospector@users.noreply.github.com> Date: Wed, 7 May 2025 19:08:38 -0700 Subject: [PATCH] Add server unzipping (#3622) * Initial unzipping feature * Remove explicit backup provider naming from frontend * CF placeholder * Use regex for CF links * Lint * Add unzip warning for conflicting files, fix hydration error * Adjust conflict modal ui * Fix old queued ops sticking around, remove conflict warning * Add vscode "editor.detectIndentation": true --- .vscode/settings.json | 1 + apps/frontend/.env.prod | 4 + apps/frontend/.env.staging | 4 + .../src/components/ui/Notifications.vue | 169 +++++++++---- .../src/components/ui/servers/FileItem.vue | 25 +- .../components/ui/servers/FileVirtualList.vue | 11 +- .../ui/servers/FilesBrowseNavbar.vue | 27 ++- .../ui/servers/FilesUploadConflictModal.vue | 56 +++++ .../ui/servers/FilesUploadDropdown.vue | 166 ++++++------- .../ui/servers/FilesUploadZipUrlModal.vue | 159 ++++++++++++ .../ui/servers/TeleportOverflowMenu.vue | 142 ++++++----- apps/frontend/src/composables/notifs.js | 2 + apps/frontend/src/composables/pyroServers.ts | 188 ++++++++++++--- apps/frontend/src/pages/servers/index.vue | 2 +- .../src/pages/servers/manage/[id].vue | 34 +++ .../src/pages/servers/manage/[id]/backups.vue | 3 +- .../src/pages/servers/manage/[id]/files.vue | 228 +++++++++++++++++- apps/frontend/src/types/servers.ts | 42 +++- packages/assets/external/curseforge.svg | 1 + packages/assets/icons/file-archive.svg | 1 + packages/assets/index.ts | 4 + .../ui/src/components/base/ButtonStyled.vue | 23 +- .../ui/src/components/base/ProgressBar.vue | 5 +- 23 files changed, 1042 insertions(+), 255 deletions(-) create mode 100644 apps/frontend/.env.prod create mode 100644 apps/frontend/.env.staging create mode 100644 apps/frontend/src/components/ui/servers/FilesUploadConflictModal.vue create mode 100644 apps/frontend/src/components/ui/servers/FilesUploadZipUrlModal.vue create mode 100644 packages/assets/external/curseforge.svg create mode 100644 packages/assets/icons/file-archive.svg diff --git a/.vscode/settings.json b/.vscode/settings.json index fbe97bcf7..9caec96a4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -2,6 +2,7 @@ "prettier.endOfLine": "lf", "editor.formatOnSave": true, "eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"], + "editor.detectIndentation": true, "editor.codeActionsOnSave": { "source.fixAll.eslint": "explicit" } diff --git a/apps/frontend/.env.prod b/apps/frontend/.env.prod new file mode 100644 index 000000000..8aebc57d5 --- /dev/null +++ b/apps/frontend/.env.prod @@ -0,0 +1,4 @@ +BASE_URL=https://api.modrinth.com/v2/ +BROWSER_BASE_URL=https://api.modrinth.com/v2/ +PYRO_BASE_URL=https://archon.modrinth.com +PROD_OVERRIDE=true diff --git a/apps/frontend/.env.staging b/apps/frontend/.env.staging new file mode 100644 index 000000000..3dd5f73d3 --- /dev/null +++ b/apps/frontend/.env.staging @@ -0,0 +1,4 @@ +BASE_URL=https://staging-api.modrinth.com/v2/ +BROWSER_BASE_URL=https://staging-api.modrinth.com/v2/ +PYRO_BASE_URL=https://staging-archon.modrinth.com +PROD_OVERRIDE=true diff --git a/apps/frontend/src/components/ui/Notifications.vue b/apps/frontend/src/components/ui/Notifications.vue index fc2ed6ec3..563cf23f4 100644 --- a/apps/frontend/src/components/ui/Notifications.vue +++ b/apps/frontend/src/components/ui/Notifications.vue @@ -1,85 +1,140 @@ diff --git a/apps/frontend/src/components/ui/servers/FileItem.vue b/apps/frontend/src/components/ui/servers/FileItem.vue index 6d269d8f7..5889503b6 100644 --- a/apps/frontend/src/components/ui/servers/FileItem.vue +++ b/apps/frontend/src/components/ui/servers/FileItem.vue @@ -53,6 +53,7 @@ + @@ -73,6 +74,8 @@ import { FolderOpenIcon, FileIcon, RightArrowIcon, + PackageOpenIcon, + FileArchiveIcon, } from "@modrinth/assets"; import { computed, shallowRef, ref } from "vue"; import { renderToString } from "vue/server-renderer"; @@ -99,15 +102,14 @@ interface FileItemProps { const props = defineProps(); const emit = defineEmits<{ - (e: "rename", item: { name: string; type: string; path: string }): void; - (e: "move", item: { name: string; type: string; path: string }): void; + ( + e: "rename" | "move" | "download" | "delete" | "edit" | "extract", + item: { name: string; type: string; path: string }, + ): void; ( e: "moveDirectTo", item: { name: string; type: string; path: string; destination: string }, ): void; - (e: "download", item: { name: string; type: string; path: string }): void; - (e: "delete", item: { name: string; type: string; path: string }): void; - (e: "edit", item: { name: string; type: string; path: string }): void; (e: "contextmenu", x: number, y: number): void; }>(); @@ -143,6 +145,7 @@ const codeExtensions = Object.freeze([ const textExtensions = Object.freeze(["txt", "md", "log", "cfg", "conf", "properties", "ini"]); const imageExtensions = Object.freeze(["png", "jpg", "jpeg", "gif", "svg", "webp"]); +const supportedArchiveExtensions = Object.freeze(["zip"]); const units = Object.freeze(["B", "KB", "MB", "GB", "TB", "PB", "EB"]); const route = shallowRef(useRoute()); @@ -156,7 +159,18 @@ const containerClasses = computed(() => [ const fileExtension = computed(() => props.name.split(".").pop()?.toLowerCase() || ""); +const isZip = computed(() => fileExtension.value === "zip"); + const menuOptions = computed(() => [ + { + id: "extract", + shown: isZip.value, + action: () => emit("extract", { name: props.name, type: props.type, path: props.path }), + }, + { + divider: true, + shown: isZip.value, + }, { id: "rename", action: () => emit("rename", { name: props.name, type: props.type, path: props.path }), @@ -189,6 +203,7 @@ const iconComponent = computed(() => { if (codeExtensions.includes(ext)) return UiServersIconsCodeFileIcon; if (textExtensions.includes(ext)) return UiServersIconsTextFileIcon; if (imageExtensions.includes(ext)) return UiServersIconsImageFileIcon; + if (supportedArchiveExtensions.includes(ext)) return FileArchiveIcon; return FileIcon; }); diff --git a/apps/frontend/src/components/ui/servers/FileVirtualList.vue b/apps/frontend/src/components/ui/servers/FileVirtualList.vue index 56125d76b..ecc38ce75 100644 --- a/apps/frontend/src/components/ui/servers/FileVirtualList.vue +++ b/apps/frontend/src/components/ui/servers/FileVirtualList.vue @@ -30,6 +30,7 @@ :size="item.size" @delete="$emit('delete', item)" @rename="$emit('rename', item)" + @extract="$emit('extract', item)" @download="$emit('download', item)" @move="$emit('move', item)" @move-direct-to="$emit('moveDirectTo', $event)" @@ -49,14 +50,12 @@ const props = defineProps<{ }>(); const emit = defineEmits<{ - (e: "delete", item: any): void; - (e: "rename", item: any): void; - (e: "download", item: any): void; - (e: "move", item: any): void; - (e: "edit", item: any): void; + ( + e: "delete" | "rename" | "download" | "move" | "edit" | "moveDirectTo" | "extract", + item: any, + ): void; (e: "contextmenu", item: any, x: number, y: number): void; (e: "loadMore"): void; - (e: "moveDirectTo", item: any): void; }>(); const ITEM_HEIGHT = 61; diff --git a/apps/frontend/src/components/ui/servers/FilesBrowseNavbar.vue b/apps/frontend/src/components/ui/servers/FilesBrowseNavbar.vue index c2e5e70a4..5f9f1afea 100644 --- a/apps/frontend/src/components/ui/servers/FilesBrowseNavbar.vue +++ b/apps/frontend/src/components/ui/servers/FilesBrowseNavbar.vue @@ -117,7 +117,8 @@ - $emit('create', 'file') }, { id: 'directory', action: () => $emit('create', 'directory') }, { id: 'upload', action: () => $emit('upload') }, + { divider: true }, + { id: 'upload-zip', shown: false, action: () => $emit('upload-zip') }, + { id: 'install-from-url', action: () => $emit('unzip-from-url', false) }, + { id: 'install-cf-pack', action: () => $emit('unzip-from-url', true) }, ]" > + + + + @@ -140,6 +154,9 @@ diff --git a/apps/frontend/src/components/ui/servers/FilesUploadDropdown.vue b/apps/frontend/src/components/ui/servers/FilesUploadDropdown.vue index 4841ea53c..14d8ca346 100644 --- a/apps/frontend/src/components/ui/servers/FilesUploadDropdown.vue +++ b/apps/frontend/src/components/ui/servers/FilesUploadDropdown.vue @@ -1,101 +1,105 @@