diff --git a/platforms/file-manager/.gitignore b/platforms/file-manager/.gitignore new file mode 100644 index 000000000..8ee847558 --- /dev/null +++ b/platforms/file-manager/.gitignore @@ -0,0 +1 @@ +.svelte-kit diff --git a/platforms/file-manager/.svelte-kit/ambient.d.ts b/platforms/file-manager/.svelte-kit/ambient.d.ts deleted file mode 100644 index a7344e26e..000000000 --- a/platforms/file-manager/.svelte-kit/ambient.d.ts +++ /dev/null @@ -1,400 +0,0 @@ - -// this file is generated — do not edit it - - -/// - -/** - * Environment variables [loaded by Vite](https://vitejs.dev/guide/env-and-mode.html#env-files) from `.env` files and `process.env`. Like [`$env/dynamic/private`](https://svelte.dev/docs/kit/$env-dynamic-private), this module cannot be imported into client-side code. This module only includes variables that _do not_ begin with [`config.kit.env.publicPrefix`](https://svelte.dev/docs/kit/configuration#env) _and do_ start with [`config.kit.env.privatePrefix`](https://svelte.dev/docs/kit/configuration#env) (if configured). - * - * _Unlike_ [`$env/dynamic/private`](https://svelte.dev/docs/kit/$env-dynamic-private), the values exported from this module are statically injected into your bundle at build time, enabling optimisations like dead code elimination. - * - * ```ts - * import { API_KEY } from '$env/static/private'; - * ``` - * - * Note that all environment variables referenced in your code should be declared (for example in an `.env` file), even if they don't have a value until the app is deployed: - * - * ``` - * MY_FEATURE_FLAG="" - * ``` - * - * You can override `.env` values from the command line like so: - * - * ```sh - * MY_FEATURE_FLAG="enabled" npm run dev - * ``` - */ -declare module '$env/static/private' { - export const NEO4J_URI: string; - export const NEO4J_USER: string; - export const NEO4J_PASSWORD: string; - export const REGISTRY_ENTROPY_KEY_JWK: string; - export const ENCRYPTION_PASSWORD: string; - export const W3ID: string; - export const REGISTRY_DATABASE_URL: string; - export const REGISTRY_SHARED_SECRET: string; - export const PROVISIONER_DATABASE_URL: string; - export const VERIFF_HMAC_KEY: string; - export const DUPLICATES_POLICY: string; - export const IP_ADDR: string; - export const PICTIQUE_DATABASE_URL: string; - export const PICTIQUE_MAPPING_DB_PATH: string; - export const BLABSY_MAPPING_DB_PATH: string; - export const DREAMSYNC_MAPPING_DB_PATH: string; - export const GROUP_CHARTER_MAPPING_DB_PATH: string; - export const CERBERUS_MAPPING_DB_PATH: string; - export const GOOGLE_APPLICATION_CREDENTIALS: string; - export const GROUP_CHARTER_DATABASE_URL: string; - export const CERBERUS_DATABASE_URL: string; - export const EVOTING_DATABASE_URL: string; - export const EVOTING_MAPPING_DB_PATH: string; - export const OPENAI_API_KEY: string; - export const NOTIFICATION_SHARED_SECRET: string; - export const DREAMSYNC_DATABASE_URL: string; - export const VITE_DREAMSYNC_BASE_URL: string; - export const ECURRENCY_DATABASE_URL: string; - export const ECURRENCY_MAPPING_DB_PATH: string; - export const VITE_ECURRENCY_BASE_URL: string; - export const JWT_SECRET: string; - export const EREPUTATION_DATABASE_URL: string; - export const EREPUTATION_MAPPING_DB_PATH: string; - export const VITE_EREPUTATION_BASE_URL: string; - export const ESIGNER_DATABASE_URL: string; - export const ESIGNER_MAPPING_DB_PATH: string; - export const FILE_MANAGER_DATABASE_URL: string; - export const FILE_MANAGER_MAPPING_DB_PATH: string; - export const LOAD_TEST_USER_COUNT: string; - export const SHELL: string; - export const LSCOLORS: string; - export const npm_command: string; - export const USER_ZDOTDIR: string; - export const COLORTERM: string; - export const TERM_PROGRAM_VERSION: string; - export const npm_config_optional: string; - export const FNM_ARCH: string; - export const npm_config_npm_globalconfig: string; - export const NODE: string; - export const JAVA_HOME: string; - export const QT_LOGGING_RULES: string; - export const npm_config_verify_deps_before_run: string; - export const npm_config__jsr_registry: string; - export const CLOJURE_HOME: string; - export const MEMORY_PRESSURE_WRITE: string; - export const FNM_NODE_DIST_MIRROR: string; - export const npm_config_strict_peer_dependencies: string; - export const DESKTOP_SESSION: string; - export const NO_AT_BRIDGE: string; - export const npm_config_globalconfig: string; - export const EDITOR: string; - export const XDG_SEAT: string; - export const PWD: string; - export const XDG_SESSION_DESKTOP: string; - export const LOGNAME: string; - export const QT_QPA_PLATFORMTHEME: string; - export const XDG_SESSION_TYPE: string; - export const SYSTEMD_EXEC_PID: string; - export const VSCODE_GIT_ASKPASS_NODE: string; - export const TERMINAL: string; - export const QT_QPA_PLATFORMTHEME_QT6: string; - export const DMS_SOCKET: string; - export const MOTD_SHOWN: string; - export const VSCODE_INJECTION: string; - export const GDM_LANG: string; - export const HOME: string; - export const USERNAME: string; - export const LANG: string; - export const FNM_COREPACK_ENABLED: string; - export const LS_COLORS: string; - export const XDG_CURRENT_DESKTOP: string; - export const npm_package_version: string; - export const MESA_GLSL_CACHE_MAX_SIZE: string; - export const MEMORY_PRESSURE_WATCH: string; - export const STARSHIP_SHELL: string; - export const WAYLAND_DISPLAY: string; - export const GIT_ASKPASS: string; - export const VSCODE_GIT_IPC_AUTH_TOKEN: string; - export const INVOCATION_ID: string; - export const pnpm_config_verify_deps_before_run: string; - export const NIRI_SOCKET: string; - export const MANAGERPID: string; - export const DMS_DISABLE_HOT_RELOAD: string; - export const INIT_CWD: string; - export const CHROME_DESKTOP: string; - export const STARSHIP_SESSION_KEY: string; - export const QT_QPA_PLATFORM: string; - export const npm_lifecycle_script: string; - export const VSCODE_GIT_ASKPASS_EXTRA_ARGS: string; - export const XDG_SESSION_CLASS: string; - export const ANDROID_HOME: string; - export const TERM: string; - export const npm_package_name: string; - export const ZSH: string; - export const ZDOTDIR: string; - export const USER: string; - export const npm_config_frozen_lockfile: string; - export const NDK_HOME: string; - export const VSCODE_GIT_IPC_HANDLE: string; - export const DISPLAY: string; - export const npm_lifecycle_event: string; - export const SHLVL: string; - export const PAGER: string; - export const npm_config_manage_package_manager_versions: string; - export const FNM_VERSION_FILE_STRATEGY: string; - export const XDG_VTNR: string; - export const XDG_SESSION_ID: string; - export const MANAGERPIDFDID: string; - export const npm_config_user_agent: string; - export const PNPM_SCRIPT_SRC_DIR: string; - export const npm_execpath: string; - export const XDG_RUNTIME_DIR: string; - export const FNM_RESOLVE_ENGINES: string; - export const mesa_glthread: string; - export const DMS_DEFAULT_LAUNCH_PREFIX: string; - export const NODE_PATH: string; - export const DEBUGINFOD_URLS: string; - export const npm_package_json: string; - export const VSCODE_GIT_ASKPASS_MAIN: string; - export const JOURNAL_STREAM: string; - export const GDK_BACKEND: string; - export const PATH: string; - export const npm_config_node_gyp: string; - export const GDMSESSION: string; - export const ORIGINAL_XDG_CURRENT_DESKTOP: string; - export const DBUS_SESSION_BUS_ADDRESS: string; - export const MAIL: string; - export const npm_config_registry: string; - export const MESA_SHADER_CACHE_DIR: string; - export const FNM_DIR: string; - export const FNM_MULTISHELL_PATH: string; - export const npm_node_execpath: string; - export const FNM_LOGLEVEL: string; - export const OLDPWD: string; - export const TERM_PROGRAM: string; - export const CURSOR_TRACE_ID: string; -} - -/** - * Similar to [`$env/static/private`](https://svelte.dev/docs/kit/$env-static-private), except that it only includes environment variables that begin with [`config.kit.env.publicPrefix`](https://svelte.dev/docs/kit/configuration#env) (which defaults to `PUBLIC_`), and can therefore safely be exposed to client-side code. - * - * Values are replaced statically at build time. - * - * ```ts - * import { PUBLIC_BASE_URL } from '$env/static/public'; - * ``` - */ -declare module '$env/static/public' { - export const PUBLIC_EVAULT_SERVER_URI: string; - export const PUBLIC_VERIFF_KEY: string; - export const PUBLIC_REGISTRY_URL: string; - export const PUBLIC_PROVISIONER_URL: string; - export const PUBLIC_PICTIQUE_URL: string; - export const PUBLIC_PICTIQUE_BASE_URL: string; - export const PUBLIC_BLABSY_URL: string; - export const PUBLIC_BLABSY_BASE_URL: string; - export const PUBLIC_GROUP_CHARTER_BASE_URL: string; - export const PUBLIC_CERBERUS_BASE_URL: string; - export const PUBLIC_EVOTING_BASE_URL: string; - export const PUBLIC_EVOTING_URL: string; - export const PUBLIC_APP_STORE_EID_WALLET: string; - export const PUBLIC_PLAY_STORE_EID_WALLET: string; - export const PUBLIC_ESIGNER_BASE_URL: string; - export const PUBLIC_FILE_MANAGER_BASE_URL: string; -} - -/** - * This module provides access to runtime environment variables, as defined by the platform you're running on. For example if you're using [`adapter-node`](https://github.com/sveltejs/kit/tree/main/packages/adapter-node) (or running [`vite preview`](https://svelte.dev/docs/kit/cli)), this is equivalent to `process.env`. This module only includes variables that _do not_ begin with [`config.kit.env.publicPrefix`](https://svelte.dev/docs/kit/configuration#env) _and do_ start with [`config.kit.env.privatePrefix`](https://svelte.dev/docs/kit/configuration#env) (if configured). - * - * This module cannot be imported into client-side code. - * - * ```ts - * import { env } from '$env/dynamic/private'; - * console.log(env.DEPLOYMENT_SPECIFIC_VARIABLE); - * ``` - * - * > [!NOTE] In `dev`, `$env/dynamic` always includes environment variables from `.env`. In `prod`, this behavior will depend on your adapter. - */ -declare module '$env/dynamic/private' { - export const env: { - NEO4J_URI: string; - NEO4J_USER: string; - NEO4J_PASSWORD: string; - REGISTRY_ENTROPY_KEY_JWK: string; - ENCRYPTION_PASSWORD: string; - W3ID: string; - REGISTRY_DATABASE_URL: string; - REGISTRY_SHARED_SECRET: string; - PROVISIONER_DATABASE_URL: string; - VERIFF_HMAC_KEY: string; - DUPLICATES_POLICY: string; - IP_ADDR: string; - PICTIQUE_DATABASE_URL: string; - PICTIQUE_MAPPING_DB_PATH: string; - BLABSY_MAPPING_DB_PATH: string; - DREAMSYNC_MAPPING_DB_PATH: string; - GROUP_CHARTER_MAPPING_DB_PATH: string; - CERBERUS_MAPPING_DB_PATH: string; - GOOGLE_APPLICATION_CREDENTIALS: string; - GROUP_CHARTER_DATABASE_URL: string; - CERBERUS_DATABASE_URL: string; - EVOTING_DATABASE_URL: string; - EVOTING_MAPPING_DB_PATH: string; - OPENAI_API_KEY: string; - NOTIFICATION_SHARED_SECRET: string; - DREAMSYNC_DATABASE_URL: string; - VITE_DREAMSYNC_BASE_URL: string; - ECURRENCY_DATABASE_URL: string; - ECURRENCY_MAPPING_DB_PATH: string; - VITE_ECURRENCY_BASE_URL: string; - JWT_SECRET: string; - EREPUTATION_DATABASE_URL: string; - EREPUTATION_MAPPING_DB_PATH: string; - VITE_EREPUTATION_BASE_URL: string; - ESIGNER_DATABASE_URL: string; - ESIGNER_MAPPING_DB_PATH: string; - FILE_MANAGER_DATABASE_URL: string; - FILE_MANAGER_MAPPING_DB_PATH: string; - LOAD_TEST_USER_COUNT: string; - SHELL: string; - LSCOLORS: string; - npm_command: string; - USER_ZDOTDIR: string; - COLORTERM: string; - TERM_PROGRAM_VERSION: string; - npm_config_optional: string; - FNM_ARCH: string; - npm_config_npm_globalconfig: string; - NODE: string; - JAVA_HOME: string; - QT_LOGGING_RULES: string; - npm_config_verify_deps_before_run: string; - npm_config__jsr_registry: string; - CLOJURE_HOME: string; - MEMORY_PRESSURE_WRITE: string; - FNM_NODE_DIST_MIRROR: string; - npm_config_strict_peer_dependencies: string; - DESKTOP_SESSION: string; - NO_AT_BRIDGE: string; - npm_config_globalconfig: string; - EDITOR: string; - XDG_SEAT: string; - PWD: string; - XDG_SESSION_DESKTOP: string; - LOGNAME: string; - QT_QPA_PLATFORMTHEME: string; - XDG_SESSION_TYPE: string; - SYSTEMD_EXEC_PID: string; - VSCODE_GIT_ASKPASS_NODE: string; - TERMINAL: string; - QT_QPA_PLATFORMTHEME_QT6: string; - DMS_SOCKET: string; - MOTD_SHOWN: string; - VSCODE_INJECTION: string; - GDM_LANG: string; - HOME: string; - USERNAME: string; - LANG: string; - FNM_COREPACK_ENABLED: string; - LS_COLORS: string; - XDG_CURRENT_DESKTOP: string; - npm_package_version: string; - MESA_GLSL_CACHE_MAX_SIZE: string; - MEMORY_PRESSURE_WATCH: string; - STARSHIP_SHELL: string; - WAYLAND_DISPLAY: string; - GIT_ASKPASS: string; - VSCODE_GIT_IPC_AUTH_TOKEN: string; - INVOCATION_ID: string; - pnpm_config_verify_deps_before_run: string; - NIRI_SOCKET: string; - MANAGERPID: string; - DMS_DISABLE_HOT_RELOAD: string; - INIT_CWD: string; - CHROME_DESKTOP: string; - STARSHIP_SESSION_KEY: string; - QT_QPA_PLATFORM: string; - npm_lifecycle_script: string; - VSCODE_GIT_ASKPASS_EXTRA_ARGS: string; - XDG_SESSION_CLASS: string; - ANDROID_HOME: string; - TERM: string; - npm_package_name: string; - ZSH: string; - ZDOTDIR: string; - USER: string; - npm_config_frozen_lockfile: string; - NDK_HOME: string; - VSCODE_GIT_IPC_HANDLE: string; - DISPLAY: string; - npm_lifecycle_event: string; - SHLVL: string; - PAGER: string; - npm_config_manage_package_manager_versions: string; - FNM_VERSION_FILE_STRATEGY: string; - XDG_VTNR: string; - XDG_SESSION_ID: string; - MANAGERPIDFDID: string; - npm_config_user_agent: string; - PNPM_SCRIPT_SRC_DIR: string; - npm_execpath: string; - XDG_RUNTIME_DIR: string; - FNM_RESOLVE_ENGINES: string; - mesa_glthread: string; - DMS_DEFAULT_LAUNCH_PREFIX: string; - NODE_PATH: string; - DEBUGINFOD_URLS: string; - npm_package_json: string; - VSCODE_GIT_ASKPASS_MAIN: string; - JOURNAL_STREAM: string; - GDK_BACKEND: string; - PATH: string; - npm_config_node_gyp: string; - GDMSESSION: string; - ORIGINAL_XDG_CURRENT_DESKTOP: string; - DBUS_SESSION_BUS_ADDRESS: string; - MAIL: string; - npm_config_registry: string; - MESA_SHADER_CACHE_DIR: string; - FNM_DIR: string; - FNM_MULTISHELL_PATH: string; - npm_node_execpath: string; - FNM_LOGLEVEL: string; - OLDPWD: string; - TERM_PROGRAM: string; - CURSOR_TRACE_ID: string; - [key: `PUBLIC_${string}`]: undefined; - [key: `${string}`]: string | undefined; - } -} - -/** - * Similar to [`$env/dynamic/private`](https://svelte.dev/docs/kit/$env-dynamic-private), but only includes variables that begin with [`config.kit.env.publicPrefix`](https://svelte.dev/docs/kit/configuration#env) (which defaults to `PUBLIC_`), and can therefore safely be exposed to client-side code. - * - * Note that public dynamic environment variables must all be sent from the server to the client, causing larger network requests — when possible, use `$env/static/public` instead. - * - * ```ts - * import { env } from '$env/dynamic/public'; - * console.log(env.PUBLIC_DEPLOYMENT_SPECIFIC_VARIABLE); - * ``` - */ -declare module '$env/dynamic/public' { - export const env: { - PUBLIC_EVAULT_SERVER_URI: string; - PUBLIC_VERIFF_KEY: string; - PUBLIC_REGISTRY_URL: string; - PUBLIC_PROVISIONER_URL: string; - PUBLIC_PICTIQUE_URL: string; - PUBLIC_PICTIQUE_BASE_URL: string; - PUBLIC_BLABSY_URL: string; - PUBLIC_BLABSY_BASE_URL: string; - PUBLIC_GROUP_CHARTER_BASE_URL: string; - PUBLIC_CERBERUS_BASE_URL: string; - PUBLIC_EVOTING_BASE_URL: string; - PUBLIC_EVOTING_URL: string; - PUBLIC_APP_STORE_EID_WALLET: string; - PUBLIC_PLAY_STORE_EID_WALLET: string; - PUBLIC_ESIGNER_BASE_URL: string; - PUBLIC_FILE_MANAGER_BASE_URL: string; - [key: `PUBLIC_${string}`]: string | undefined; - } -} diff --git a/platforms/file-manager/.svelte-kit/generated/client/app.js b/platforms/file-manager/.svelte-kit/generated/client/app.js deleted file mode 100644 index bc4c6a1c1..000000000 --- a/platforms/file-manager/.svelte-kit/generated/client/app.js +++ /dev/null @@ -1,40 +0,0 @@ -export { matchers } from './matchers.js'; - -export const nodes = [ - () => import('./nodes/0'), - () => import('./nodes/1'), - () => import('./nodes/2'), - () => import('./nodes/3'), - () => import('./nodes/4'), - () => import('./nodes/5'), - () => import('./nodes/6'), - () => import('./nodes/7'), - () => import('./nodes/8') -]; - -export const server_loads = []; - -export const dictionary = { - "/": [3], - "/(auth)/auth": [4], - "/(auth)/deeplink-login": [5], - "/(protected)/files": [6,[2]], - "/(protected)/files/[id]": [7,[2]], - "/(protected)/storage": [8,[2]] - }; - -export const hooks = { - handleError: (({ error }) => { console.error(error) }), - - reroute: (() => {}), - transport: {} -}; - -export const decoders = Object.fromEntries(Object.entries(hooks.transport).map(([k, v]) => [k, v.decode])); -export const encoders = Object.fromEntries(Object.entries(hooks.transport).map(([k, v]) => [k, v.encode])); - -export const hash = false; - -export const decode = (type, value) => decoders[type](value); - -export { default as root } from '../root.js'; \ No newline at end of file diff --git a/platforms/file-manager/.svelte-kit/generated/client/matchers.js b/platforms/file-manager/.svelte-kit/generated/client/matchers.js deleted file mode 100644 index f6bd30a4e..000000000 --- a/platforms/file-manager/.svelte-kit/generated/client/matchers.js +++ /dev/null @@ -1 +0,0 @@ -export const matchers = {}; \ No newline at end of file diff --git a/platforms/file-manager/.svelte-kit/generated/client/nodes/0.js b/platforms/file-manager/.svelte-kit/generated/client/nodes/0.js deleted file mode 100644 index fed1375f7..000000000 --- a/platforms/file-manager/.svelte-kit/generated/client/nodes/0.js +++ /dev/null @@ -1 +0,0 @@ -export { default as component } from "../../../../src/routes/+layout.svelte"; \ No newline at end of file diff --git a/platforms/file-manager/.svelte-kit/generated/client/nodes/1.js b/platforms/file-manager/.svelte-kit/generated/client/nodes/1.js deleted file mode 100644 index 635016f9c..000000000 --- a/platforms/file-manager/.svelte-kit/generated/client/nodes/1.js +++ /dev/null @@ -1 +0,0 @@ -export { default as component } from "../../../../../../node_modules/.pnpm/@sveltejs+kit@2.49.2_@opentelemetry+api@1.9.0_@sveltejs+vite-plugin-svelte@5.1.1_svelte_f2289347040f8edd51fabc9e5c8ef0b5/node_modules/@sveltejs/kit/src/runtime/components/svelte-5/error.svelte"; \ No newline at end of file diff --git a/platforms/file-manager/.svelte-kit/generated/client/nodes/2.js b/platforms/file-manager/.svelte-kit/generated/client/nodes/2.js deleted file mode 100644 index e899b5cfd..000000000 --- a/platforms/file-manager/.svelte-kit/generated/client/nodes/2.js +++ /dev/null @@ -1 +0,0 @@ -export { default as component } from "../../../../src/routes/(protected)/+layout.svelte"; \ No newline at end of file diff --git a/platforms/file-manager/.svelte-kit/generated/client/nodes/3.js b/platforms/file-manager/.svelte-kit/generated/client/nodes/3.js deleted file mode 100644 index 1cb4f8552..000000000 --- a/platforms/file-manager/.svelte-kit/generated/client/nodes/3.js +++ /dev/null @@ -1 +0,0 @@ -export { default as component } from "../../../../src/routes/+page.svelte"; \ No newline at end of file diff --git a/platforms/file-manager/.svelte-kit/generated/client/nodes/4.js b/platforms/file-manager/.svelte-kit/generated/client/nodes/4.js deleted file mode 100644 index 773b48116..000000000 --- a/platforms/file-manager/.svelte-kit/generated/client/nodes/4.js +++ /dev/null @@ -1 +0,0 @@ -export { default as component } from "../../../../src/routes/(auth)/auth/+page.svelte"; \ No newline at end of file diff --git a/platforms/file-manager/.svelte-kit/generated/client/nodes/5.js b/platforms/file-manager/.svelte-kit/generated/client/nodes/5.js deleted file mode 100644 index 2b85113b9..000000000 --- a/platforms/file-manager/.svelte-kit/generated/client/nodes/5.js +++ /dev/null @@ -1 +0,0 @@ -export { default as component } from "../../../../src/routes/(auth)/deeplink-login/+page.svelte"; \ No newline at end of file diff --git a/platforms/file-manager/.svelte-kit/generated/client/nodes/6.js b/platforms/file-manager/.svelte-kit/generated/client/nodes/6.js deleted file mode 100644 index 5362e6dbe..000000000 --- a/platforms/file-manager/.svelte-kit/generated/client/nodes/6.js +++ /dev/null @@ -1 +0,0 @@ -export { default as component } from "../../../../src/routes/(protected)/files/+page.svelte"; \ No newline at end of file diff --git a/platforms/file-manager/.svelte-kit/generated/client/nodes/7.js b/platforms/file-manager/.svelte-kit/generated/client/nodes/7.js deleted file mode 100644 index 8bd5dab8a..000000000 --- a/platforms/file-manager/.svelte-kit/generated/client/nodes/7.js +++ /dev/null @@ -1 +0,0 @@ -export { default as component } from "../../../../src/routes/(protected)/files/[id]/+page.svelte"; \ No newline at end of file diff --git a/platforms/file-manager/.svelte-kit/generated/client/nodes/8.js b/platforms/file-manager/.svelte-kit/generated/client/nodes/8.js deleted file mode 100644 index dca40a712..000000000 --- a/platforms/file-manager/.svelte-kit/generated/client/nodes/8.js +++ /dev/null @@ -1 +0,0 @@ -export { default as component } from "../../../../src/routes/(protected)/storage/+page.svelte"; \ No newline at end of file diff --git a/platforms/file-manager/.svelte-kit/generated/root.js b/platforms/file-manager/.svelte-kit/generated/root.js deleted file mode 100644 index 4d1e8929f..000000000 --- a/platforms/file-manager/.svelte-kit/generated/root.js +++ /dev/null @@ -1,3 +0,0 @@ -import { asClassComponent } from 'svelte/legacy'; -import Root from './root.svelte'; -export default asClassComponent(Root); \ No newline at end of file diff --git a/platforms/file-manager/.svelte-kit/generated/root.svelte b/platforms/file-manager/.svelte-kit/generated/root.svelte deleted file mode 100644 index 1c16fc867..000000000 --- a/platforms/file-manager/.svelte-kit/generated/root.svelte +++ /dev/null @@ -1,80 +0,0 @@ - - - - -{#if constructors[1]} - {@const Pyramid_0 = constructors[0]} - - - {#if constructors[2]} - {@const Pyramid_1 = constructors[1]} - - - - - - - {:else} - {@const Pyramid_1 = constructors[1]} - - - - {/if} - - -{:else} - {@const Pyramid_0 = constructors[0]} - - - -{/if} - -{#if mounted} -
- {#if navigated} - {title} - {/if} -
-{/if} \ No newline at end of file diff --git a/platforms/file-manager/.svelte-kit/generated/server/internal.js b/platforms/file-manager/.svelte-kit/generated/server/internal.js deleted file mode 100644 index fe43d0868..000000000 --- a/platforms/file-manager/.svelte-kit/generated/server/internal.js +++ /dev/null @@ -1,53 +0,0 @@ - -import root from '../root.js'; -import { set_building, set_prerendering } from '__sveltekit/environment'; -import { set_assets } from '$app/paths/internal/server'; -import { set_manifest, set_read_implementation } from '__sveltekit/server'; -import { set_private_env, set_public_env } from '../../../../../node_modules/.pnpm/@sveltejs+kit@2.49.2_@opentelemetry+api@1.9.0_@sveltejs+vite-plugin-svelte@5.1.1_svelte_f2289347040f8edd51fabc9e5c8ef0b5/node_modules/@sveltejs/kit/src/runtime/shared-server.js'; - -export const options = { - app_template_contains_nonce: false, - async: false, - csp: {"mode":"auto","directives":{"upgrade-insecure-requests":false,"block-all-mixed-content":false},"reportOnly":{"upgrade-insecure-requests":false,"block-all-mixed-content":false}}, - csrf_check_origin: true, - csrf_trusted_origins: [], - embedded: false, - env_public_prefix: 'PUBLIC_', - env_private_prefix: '', - hash_routing: false, - hooks: null, // added lazily, via `get_hooks` - preload_strategy: "modulepreload", - root, - service_worker: false, - service_worker_options: undefined, - templates: { - app: ({ head, body, assets, nonce, env }) => "\n\n\t\n\t\t\n\t\t\n\t\t" + head + "\n\t\n\t\n\t\t
" + body + "
\n\t\n\n\n", - error: ({ status, message }) => "\n\n\t\n\t\t\n\t\t" + message + "\n\n\t\t\n\t\n\t\n\t\t
\n\t\t\t" + status + "\n\t\t\t
\n\t\t\t\t

" + message + "

\n\t\t\t
\n\t\t
\n\t\n\n" - }, - version_hash: "1oo11i4" -}; - -export async function get_hooks() { - let handle; - let handleFetch; - let handleError; - let handleValidationError; - let init; - - - let reroute; - let transport; - - - return { - handle, - handleFetch, - handleError, - handleValidationError, - init, - reroute, - transport - }; -} - -export { set_assets, set_building, set_manifest, set_prerendering, set_private_env, set_public_env, set_read_implementation }; diff --git a/platforms/file-manager/.svelte-kit/non-ambient.d.ts b/platforms/file-manager/.svelte-kit/non-ambient.d.ts deleted file mode 100644 index 18196732d..000000000 --- a/platforms/file-manager/.svelte-kit/non-ambient.d.ts +++ /dev/null @@ -1,48 +0,0 @@ - -// this file is generated — do not edit it - - -declare module "svelte/elements" { - export interface HTMLAttributes { - 'data-sveltekit-keepfocus'?: true | '' | 'off' | undefined | null; - 'data-sveltekit-noscroll'?: true | '' | 'off' | undefined | null; - 'data-sveltekit-preload-code'?: - | true - | '' - | 'eager' - | 'viewport' - | 'hover' - | 'tap' - | 'off' - | undefined - | null; - 'data-sveltekit-preload-data'?: true | '' | 'hover' | 'tap' | 'off' | undefined | null; - 'data-sveltekit-reload'?: true | '' | 'off' | undefined | null; - 'data-sveltekit-replacestate'?: true | '' | 'off' | undefined | null; - } -} - -export {}; - - -declare module "$app/types" { - export interface AppTypes { - RouteId(): "/(protected)" | "/(auth)" | "/" | "/(auth)/auth" | "/(auth)/deeplink-login" | "/(protected)/files" | "/(protected)/files/[id]" | "/(protected)/storage"; - RouteParams(): { - "/(protected)/files/[id]": { id: string } - }; - LayoutParams(): { - "/(protected)": { id?: string }; - "/(auth)": Record; - "/": { id?: string }; - "/(auth)/auth": Record; - "/(auth)/deeplink-login": Record; - "/(protected)/files": { id?: string }; - "/(protected)/files/[id]": { id: string }; - "/(protected)/storage": Record - }; - Pathname(): "/" | "/auth" | "/auth/" | "/deeplink-login" | "/deeplink-login/" | "/files" | "/files/" | `/files/${string}` & {} | `/files/${string}/` & {} | "/storage" | "/storage/"; - ResolvedPathname(): `${"" | `/${string}`}${ReturnType}`; - Asset(): "/android-chrome-192x192.png" | "/android-chrome-512x512.png" | "/apple-touch-icon.png" | "/favicon-16x16.png" | "/favicon-32x32.png" | "/favicon.ico" | "/site.webmanifest" | string & {}; - } -} \ No newline at end of file diff --git a/platforms/file-manager/.svelte-kit/tsconfig.json b/platforms/file-manager/.svelte-kit/tsconfig.json deleted file mode 100644 index 64aad0734..000000000 --- a/platforms/file-manager/.svelte-kit/tsconfig.json +++ /dev/null @@ -1,52 +0,0 @@ -{ - "compilerOptions": { - "paths": { - "$lib": [ - "../src/lib" - ], - "$lib/*": [ - "../src/lib/*" - ], - "$app/types": [ - "./types/index.d.ts" - ] - }, - "rootDirs": [ - "..", - "./types" - ], - "verbatimModuleSyntax": true, - "isolatedModules": true, - "lib": [ - "esnext", - "DOM", - "DOM.Iterable" - ], - "moduleResolution": "bundler", - "module": "esnext", - "noEmit": true, - "target": "esnext" - }, - "include": [ - "ambient.d.ts", - "non-ambient.d.ts", - "./types/**/$types.d.ts", - "../vite.config.js", - "../vite.config.ts", - "../src/**/*.js", - "../src/**/*.ts", - "../src/**/*.svelte", - "../tests/**/*.js", - "../tests/**/*.ts", - "../tests/**/*.svelte" - ], - "exclude": [ - "../node_modules/**", - "../src/service-worker.js", - "../src/service-worker/**/*.js", - "../src/service-worker.ts", - "../src/service-worker/**/*.ts", - "../src/service-worker.d.ts", - "../src/service-worker/**/*.d.ts" - ] -} \ No newline at end of file diff --git a/platforms/file-manager/.svelte-kit/types/route_meta_data.json b/platforms/file-manager/.svelte-kit/types/route_meta_data.json deleted file mode 100644 index 02013f92b..000000000 --- a/platforms/file-manager/.svelte-kit/types/route_meta_data.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "/(protected)": [], - "/": [], - "/(auth)/auth": [], - "/(auth)/deeplink-login": [], - "/(protected)/files": [], - "/(protected)/files/[id]": [], - "/(protected)/storage": [] -} \ No newline at end of file diff --git a/platforms/file-manager/.svelte-kit/types/src/routes/$types.d.ts b/platforms/file-manager/.svelte-kit/types/src/routes/$types.d.ts deleted file mode 100644 index 0e17612b4..000000000 --- a/platforms/file-manager/.svelte-kit/types/src/routes/$types.d.ts +++ /dev/null @@ -1,24 +0,0 @@ -import type * as Kit from '@sveltejs/kit'; - -type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; -// @ts-ignore -type MatcherParam = M extends (param : string) => param is infer U ? U extends string ? U : string : string; -type RouteParams = { }; -type RouteId = '/'; -type MaybeWithVoid = {} extends T ? T | void : T; -export type RequiredKeys = { [K in keyof T]-?: {} extends { [P in K]: T[K] } ? never : K; }[keyof T]; -type OutputDataShape = MaybeWithVoid> & Partial> & Record> -type EnsureDefined = T extends null | undefined ? {} : T; -type OptionalUnion, A extends keyof U = U extends U ? keyof U : never> = U extends unknown ? { [P in Exclude]?: never } & U : never; -export type Snapshot = Kit.Snapshot; -type PageParentData = EnsureDefined; -type LayoutRouteId = RouteId | "/" | "/(auth)/auth" | "/(auth)/deeplink-login" | "/(protected)/files" | "/(protected)/files/[id]" | "/(protected)/storage" | null -type LayoutParams = RouteParams & { id?: string } -type LayoutParentData = EnsureDefined<{}>; - -export type PageServerData = null; -export type PageData = Expand; -export type PageProps = { params: RouteParams; data: PageData } -export type LayoutServerData = null; -export type LayoutData = Expand; -export type LayoutProps = { params: LayoutParams; data: LayoutData; children: import("svelte").Snippet } \ No newline at end of file diff --git a/platforms/file-manager/.svelte-kit/types/src/routes/(auth)/auth/$types.d.ts b/platforms/file-manager/.svelte-kit/types/src/routes/(auth)/auth/$types.d.ts deleted file mode 100644 index b22693e94..000000000 --- a/platforms/file-manager/.svelte-kit/types/src/routes/(auth)/auth/$types.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type * as Kit from '@sveltejs/kit'; - -type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; -// @ts-ignore -type MatcherParam = M extends (param : string) => param is infer U ? U extends string ? U : string : string; -type RouteParams = { }; -type RouteId = '/(auth)/auth'; -type MaybeWithVoid = {} extends T ? T | void : T; -export type RequiredKeys = { [K in keyof T]-?: {} extends { [P in K]: T[K] } ? never : K; }[keyof T]; -type OutputDataShape = MaybeWithVoid> & Partial> & Record> -type EnsureDefined = T extends null | undefined ? {} : T; -type OptionalUnion, A extends keyof U = U extends U ? keyof U : never> = U extends unknown ? { [P in Exclude]?: never } & U : never; -export type Snapshot = Kit.Snapshot; -type PageParentData = EnsureDefined; - -export type PageServerData = null; -export type PageData = Expand; -export type PageProps = { params: RouteParams; data: PageData } \ No newline at end of file diff --git a/platforms/file-manager/.svelte-kit/types/src/routes/(auth)/deeplink-login/$types.d.ts b/platforms/file-manager/.svelte-kit/types/src/routes/(auth)/deeplink-login/$types.d.ts deleted file mode 100644 index d6aa873d8..000000000 --- a/platforms/file-manager/.svelte-kit/types/src/routes/(auth)/deeplink-login/$types.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type * as Kit from '@sveltejs/kit'; - -type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; -// @ts-ignore -type MatcherParam = M extends (param : string) => param is infer U ? U extends string ? U : string : string; -type RouteParams = { }; -type RouteId = '/(auth)/deeplink-login'; -type MaybeWithVoid = {} extends T ? T | void : T; -export type RequiredKeys = { [K in keyof T]-?: {} extends { [P in K]: T[K] } ? never : K; }[keyof T]; -type OutputDataShape = MaybeWithVoid> & Partial> & Record> -type EnsureDefined = T extends null | undefined ? {} : T; -type OptionalUnion, A extends keyof U = U extends U ? keyof U : never> = U extends unknown ? { [P in Exclude]?: never } & U : never; -export type Snapshot = Kit.Snapshot; -type PageParentData = EnsureDefined; - -export type PageServerData = null; -export type PageData = Expand; -export type PageProps = { params: RouteParams; data: PageData } \ No newline at end of file diff --git a/platforms/file-manager/.svelte-kit/types/src/routes/(protected)/$types.d.ts b/platforms/file-manager/.svelte-kit/types/src/routes/(protected)/$types.d.ts deleted file mode 100644 index e8086f73e..000000000 --- a/platforms/file-manager/.svelte-kit/types/src/routes/(protected)/$types.d.ts +++ /dev/null @@ -1,20 +0,0 @@ -import type * as Kit from '@sveltejs/kit'; - -type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; -// @ts-ignore -type MatcherParam = M extends (param : string) => param is infer U ? U extends string ? U : string : string; -type RouteParams = { }; -type RouteId = '/(protected)'; -type MaybeWithVoid = {} extends T ? T | void : T; -export type RequiredKeys = { [K in keyof T]-?: {} extends { [P in K]: T[K] } ? never : K; }[keyof T]; -type OutputDataShape = MaybeWithVoid> & Partial> & Record> -type EnsureDefined = T extends null | undefined ? {} : T; -type OptionalUnion, A extends keyof U = U extends U ? keyof U : never> = U extends unknown ? { [P in Exclude]?: never } & U : never; -export type Snapshot = Kit.Snapshot; -type LayoutRouteId = RouteId | "/(protected)/files" | "/(protected)/files/[id]" | "/(protected)/storage" -type LayoutParams = RouteParams & { id?: string } -type LayoutParentData = EnsureDefined; - -export type LayoutServerData = null; -export type LayoutData = Expand; -export type LayoutProps = { params: LayoutParams; data: LayoutData; children: import("svelte").Snippet } \ No newline at end of file diff --git a/platforms/file-manager/.svelte-kit/types/src/routes/(protected)/files/$types.d.ts b/platforms/file-manager/.svelte-kit/types/src/routes/(protected)/files/$types.d.ts deleted file mode 100644 index 9a8701d2d..000000000 --- a/platforms/file-manager/.svelte-kit/types/src/routes/(protected)/files/$types.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type * as Kit from '@sveltejs/kit'; - -type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; -// @ts-ignore -type MatcherParam = M extends (param : string) => param is infer U ? U extends string ? U : string : string; -type RouteParams = { }; -type RouteId = '/(protected)/files'; -type MaybeWithVoid = {} extends T ? T | void : T; -export type RequiredKeys = { [K in keyof T]-?: {} extends { [P in K]: T[K] } ? never : K; }[keyof T]; -type OutputDataShape = MaybeWithVoid> & Partial> & Record> -type EnsureDefined = T extends null | undefined ? {} : T; -type OptionalUnion, A extends keyof U = U extends U ? keyof U : never> = U extends unknown ? { [P in Exclude]?: never } & U : never; -export type Snapshot = Kit.Snapshot; -type PageParentData = Omit, keyof import('../$types.js').LayoutData> & EnsureDefined; - -export type PageServerData = null; -export type PageData = Expand; -export type PageProps = { params: RouteParams; data: PageData } \ No newline at end of file diff --git a/platforms/file-manager/.svelte-kit/types/src/routes/(protected)/files/[id]/$types.d.ts b/platforms/file-manager/.svelte-kit/types/src/routes/(protected)/files/[id]/$types.d.ts deleted file mode 100644 index 70863a49e..000000000 --- a/platforms/file-manager/.svelte-kit/types/src/routes/(protected)/files/[id]/$types.d.ts +++ /dev/null @@ -1,19 +0,0 @@ -import type * as Kit from '@sveltejs/kit'; - -type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; -// @ts-ignore -type MatcherParam = M extends (param : string) => param is infer U ? U extends string ? U : string : string; -type RouteParams = { id: string }; -type RouteId = '/(protected)/files/[id]'; -type MaybeWithVoid = {} extends T ? T | void : T; -export type RequiredKeys = { [K in keyof T]-?: {} extends { [P in K]: T[K] } ? never : K; }[keyof T]; -type OutputDataShape = MaybeWithVoid> & Partial> & Record> -type EnsureDefined = T extends null | undefined ? {} : T; -type OptionalUnion, A extends keyof U = U extends U ? keyof U : never> = U extends unknown ? { [P in Exclude]?: never } & U : never; -export type Snapshot = Kit.Snapshot; -type PageParentData = Omit, keyof import('../../$types.js').LayoutData> & EnsureDefined; - -export type EntryGenerator = () => Promise> | Array; -export type PageServerData = null; -export type PageData = Expand; -export type PageProps = { params: RouteParams; data: PageData } \ No newline at end of file diff --git a/platforms/file-manager/.svelte-kit/types/src/routes/(protected)/storage/$types.d.ts b/platforms/file-manager/.svelte-kit/types/src/routes/(protected)/storage/$types.d.ts deleted file mode 100644 index 57a1d473c..000000000 --- a/platforms/file-manager/.svelte-kit/types/src/routes/(protected)/storage/$types.d.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type * as Kit from '@sveltejs/kit'; - -type Expand = T extends infer O ? { [K in keyof O]: O[K] } : never; -// @ts-ignore -type MatcherParam = M extends (param : string) => param is infer U ? U extends string ? U : string : string; -type RouteParams = { }; -type RouteId = '/(protected)/storage'; -type MaybeWithVoid = {} extends T ? T | void : T; -export type RequiredKeys = { [K in keyof T]-?: {} extends { [P in K]: T[K] } ? never : K; }[keyof T]; -type OutputDataShape = MaybeWithVoid> & Partial> & Record> -type EnsureDefined = T extends null | undefined ? {} : T; -type OptionalUnion, A extends keyof U = U extends U ? keyof U : never> = U extends unknown ? { [P in Exclude]?: never } & U : never; -export type Snapshot = Kit.Snapshot; -type PageParentData = Omit, keyof import('../$types.js').LayoutData> & EnsureDefined; - -export type PageServerData = null; -export type PageData = Expand; -export type PageProps = { params: RouteParams; data: PageData } \ No newline at end of file diff --git a/platforms/file-manager/package.json b/platforms/file-manager/package.json index f88e0ce7c..224fc2175 100644 --- a/platforms/file-manager/package.json +++ b/platforms/file-manager/package.json @@ -38,9 +38,9 @@ "dependencies": { "@sveltejs/adapter-node": "^5.2.12", "axios": "^1.6.7", + "jszip": "^3.10.1", "svelte-qrcode": "^1.0.1", "svelte-qrcode-action": "^1.0.2", "tailwind-merge": "^3.0.2" } } - diff --git a/platforms/file-manager/src/routes/(protected)/files/+page.svelte b/platforms/file-manager/src/routes/(protected)/files/+page.svelte index 4888980b2..bc6169f3e 100644 --- a/platforms/file-manager/src/routes/(protected)/files/+page.svelte +++ b/platforms/file-manager/src/routes/(protected)/files/+page.svelte @@ -28,6 +28,7 @@ } from "$lib/stores/folders"; import { toast } from "$lib/stores/toast"; import { apiClient } from "$lib/utils/axios"; + import JSZip from "jszip"; import { onMount } from "svelte"; import { get } from "svelte/store"; @@ -136,6 +137,37 @@ let uploadModalDragOver = $state(false); let previewFile = $state(null); let previewUrl = $state(null); + let downloadUrl = $state(null); + + // Multi-file selection for download + const DOWNLOAD_BATCH_SIZE = 3; // Number of concurrent downloads + let selectedFileIds = $state>(new Set()); + + // Download modal state + let showDownloadModal = $state(false); + let downloadProgress = $state<{ + currentFile: string; + currentFileIndex: number; + totalFiles: number; + fileProgress: number; // 0-100 for current file + overallProgress: number; // 0-100 for all files + status: "preparing" | "downloading" | "zipping" | "complete" | "error"; + errorMessage?: string; + downloadedFiles: Array<{ + name: string; + size: number; + status: "done" | "downloading" | "pending" | "error"; + errorMessage?: string; + }>; + }>({ + currentFile: "", + currentFileIndex: 0, + totalFiles: 0, + fileProgress: 0, + overallProgress: 0, + status: "preparing", + downloadedFiles: [], + }); let breadcrumbs = $state>([ { id: null, name: "My Files" }, ]); @@ -715,6 +747,7 @@ async function navigateToFolder(folderId: string | null) { currentFolderId = folderId; + clearSelection(); // Clear selection when navigating updateUrlFromState(); await loadFiles(); await updateBreadcrumbs(); @@ -724,6 +757,7 @@ if (currentView === view) return; // Don't reload if already on this view currentView = view; currentFolderId = null; // Reset to root when switching views + clearSelection(); // Clear selection when switching views updateUrlFromState(); await loadFiles(); // Reload files when switching views await updateBreadcrumbs(); // Update breadcrumbs with correct root name @@ -787,6 +821,7 @@ // Add auth token as query parameter for img/iframe tags const token = localStorage.getItem("file_manager_auth_token"); previewUrl = `${API_BASE_URL}/api/files/${file.id}/preview?token=${token || ""}`; + downloadUrl = `${API_BASE_URL}/api/files/${file.id}/download?token=${token || ""}`; return; } // If not previewable, go to detail page @@ -796,6 +831,7 @@ function closePreview() { previewFile = null; previewUrl = null; + downloadUrl = null; } function getFileIcon(mimeType: string): string { @@ -891,6 +927,324 @@ ); }); }); + + // Multi-file selection derived states + const selectableFiles = $derived( + allItems.filter((item) => item.type === "file"), + ); + const allFilesSelected = $derived( + selectableFiles.length > 0 && + selectableFiles.every((f) => selectedFileIds.has(f.id)), + ); + + function toggleFileSelection(fileId: string, event: Event) { + event.stopPropagation(); + const newSet = new Set(selectedFileIds); + if (newSet.has(fileId)) { + newSet.delete(fileId); + } else { + newSet.add(fileId); + } + selectedFileIds = newSet; + } + + function toggleSelectAll(event: Event) { + event.stopPropagation(); + if (allFilesSelected) { + // Deselect all + selectedFileIds = new Set(); + } else { + // Select all files + const newSet = new Set(); + for (const file of selectableFiles) { + newSet.add(file.id); + } + selectedFileIds = newSet; + } + } + + function clearSelection() { + selectedFileIds = new Set(); + } + + function resetDownloadProgress() { + downloadProgress = { + currentFile: "", + currentFileIndex: 0, + totalFiles: 0, + fileProgress: 0, + overallProgress: 0, + status: "preparing", + downloadedFiles: [], + }; + } + + async function downloadSelectedFiles() { + if (selectedFileIds.size === 0) return; + + const token = localStorage.getItem("file_manager_auth_token"); + const filesToDownload = selectableFiles.filter((f) => + selectedFileIds.has(f.id), + ); + + // Guard against stale selection - no matching files found + if (filesToDownload.length === 0) { + toast.info("No selected files found"); + clearSelection(); + return; + } + + // If only one file, download directly without zipping + if (filesToDownload.length === 1) { + const file = filesToDownload[0]; + const url = `${API_BASE_URL}/api/files/${file.id}/download?token=${token || ""}`; + const link = document.createElement("a"); + link.href = url; + link.download = file.displayName || file.name; + link.style.display = "none"; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + toast.success("Download started"); + clearSelection(); + return; + } + + // Show download modal for multiple files + showDownloadModal = true; + resetDownloadProgress(); + + downloadProgress = { + ...downloadProgress, + totalFiles: filesToDownload.length, + status: "preparing", + downloadedFiles: filesToDownload.map((f) => ({ + name: f.displayName || f.name, + size: f.size, + status: "pending" as const, + })), + }; + + try { + const zip = new JSZip(); + const downloadedBlobs: Array<{ name: string; blob: Blob }> = []; + + // Download files in batches + for ( + let i = 0; + i < filesToDownload.length; + i += DOWNLOAD_BATCH_SIZE + ) { + const batch = filesToDownload.slice(i, i + DOWNLOAD_BATCH_SIZE); + + // Mark batch files as downloading + downloadProgress = { + ...downloadProgress, + status: "downloading", + downloadedFiles: downloadProgress.downloadedFiles.map( + (f, idx) => ({ + ...f, + status: + idx >= i && idx < i + batch.length + ? ("downloading" as const) + : f.status, + }), + ), + }; + + // Download batch in parallel + const batchPromises = batch.map(async (file, batchIdx) => { + const globalIdx = i + batchIdx; + const url = `${API_BASE_URL}/api/files/${file.id}/download?token=${token || ""}`; + + const response = await fetch(url); + if (!response.ok) { + throw new Error(`HTTP ${response.status}: Failed to download`); + } + + const blob = await response.blob(); + return { name: file.displayName || file.name, blob, globalIdx }; + }); + + const settledResults = await Promise.allSettled(batchPromises); + + // Process each settled result + for (let batchIdx = 0; batchIdx < settledResults.length; batchIdx++) { + const result = settledResults[batchIdx]; + const globalIdx = i + batchIdx; + const file = batch[batchIdx]; + const fileName = file.displayName || file.name; + + if (result.status === "fulfilled") { + // Success - add to downloadedBlobs and mark as done + downloadedBlobs.push({ name: result.value.name, blob: result.value.blob }); + + downloadProgress = { + ...downloadProgress, + currentFile: fileName, + currentFileIndex: globalIdx + 1, + overallProgress: Math.round( + ((globalIdx + 1) / filesToDownload.length) * 80, + ), // 80% for downloads, 20% for zipping + downloadedFiles: + downloadProgress.downloadedFiles.map( + (f, idx) => + idx === globalIdx + ? { ...f, status: "done" as const } + : f, + ), + }; + } else { + // Failed - log error and mark as error + const errorMessage = result.reason instanceof Error + ? result.reason.message + : "Unknown error"; + console.error(`Error downloading ${fileName}:`, result.reason); + + downloadProgress = { + ...downloadProgress, + currentFile: fileName, + currentFileIndex: globalIdx + 1, + overallProgress: Math.round( + ((globalIdx + 1) / filesToDownload.length) * 80, + ), + downloadedFiles: + downloadProgress.downloadedFiles.map( + (f, idx) => + idx === globalIdx + ? { ...f, status: "error" as const, errorMessage } + : f, + ), + }; + } + } + } + + // Count successful and failed downloads + const failedCount = downloadProgress.downloadedFiles.filter( + (f) => f.status === "error" + ).length; + const successCount = downloadedBlobs.length; + + // Check if all downloads failed + if (successCount === 0) { + downloadProgress = { + ...downloadProgress, + status: "error", + overallProgress: 100, + errorMessage: `All ${failedCount} file(s) failed to download`, + }; + return; + } + + // Zipping phase + downloadProgress = { + ...downloadProgress, + status: "zipping", + currentFile: "Creating zip file...", + overallProgress: 85, + }; + + // Add all successfully downloaded files to zip with unique filenames + const usedFilenames = new Set(); + + function getUniqueFilename(originalName: string): string { + if (!usedFilenames.has(originalName)) { + usedFilenames.add(originalName); + return originalName; + } + + // Split name into base and extension + const lastDotIndex = originalName.lastIndexOf('.'); + const hasExtension = lastDotIndex > 0 && lastDotIndex < originalName.length - 1; + const baseName = hasExtension ? originalName.slice(0, lastDotIndex) : originalName; + const extension = hasExtension ? originalName.slice(lastDotIndex) : ''; + + // Find a unique name by incrementing suffix + let counter = 1; + let uniqueName = `${baseName} (${counter})${extension}`; + while (usedFilenames.has(uniqueName)) { + counter++; + uniqueName = `${baseName} (${counter})${extension}`; + } + + usedFilenames.add(uniqueName); + return uniqueName; + } + + for (const { name, blob } of downloadedBlobs) { + const uniqueName = getUniqueFilename(name); + zip.file(uniqueName, blob); + } + + downloadProgress = { + ...downloadProgress, + overallProgress: 95, + }; + + // Generate zip file + const zipBlob = await zip.generateAsync({ + type: "blob", + compression: "DEFLATE", + compressionOptions: { level: 1 }, + }); + + downloadProgress = { + ...downloadProgress, + status: "complete", + overallProgress: 100, + currentFile: failedCount > 0 + ? `Download ready (${failedCount} file(s) failed)` + : "Download ready!", + }; + + // Trigger download of the zip file + const zipUrl = URL.createObjectURL(zipBlob); + const link = document.createElement("a"); + link.href = zipUrl; + const timestamp = new Date().toISOString().slice(0, 10); + link.download = `files-${timestamp}.zip`; + link.style.display = "none"; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + + // Delay revoking the object URL to ensure the download starts + // Some browsers may cancel the download if revoked immediately + setTimeout(() => { + URL.revokeObjectURL(zipUrl); + }, 500); + + // Close modal after a short delay (longer if there were failures) + setTimeout(() => { + showDownloadModal = false; + resetDownloadProgress(); + clearSelection(); + }, failedCount > 0 ? 3000 : 1500); + + // Show appropriate toast message + if (failedCount > 0) { + toast.success(`Downloaded ${successCount} of ${filesToDownload.length} files as zip (${failedCount} failed)`); + } else { + toast.success(`Downloaded ${successCount} files as zip`); + } + } catch (error) { + console.error("Download error:", error); + downloadProgress = { + ...downloadProgress, + status: "error", + errorMessage: + error instanceof Error + ? error.message + : "Failed to download files", + }; + } + } + + function cancelDownload() { + showDownloadModal = false; + resetDownloadProgress(); + }
@@ -919,6 +1273,49 @@
+ {#if selectedFileIds.size > 0} + + + {/if} {#if currentView === "my-files"}
{/if} + + {#if selectedFileIds.size > 0} +
+
+ + {selectedFileIds.size} + {selectedFileIds.size === 1 ? "file" : "files"} selected + +
+
+ +
+
+ {/if} +
- + + @@ -1066,6 +1498,9 @@ class="hover:bg-gray-50 transition-colors cursor-pointer {item.type === 'folder' ? '' + : ''} {item.type === 'file' && + selectedFileIds.has(item.id) + ? 'bg-blue-50' : ''}" onclick={(e) => { e.stopPropagation(); @@ -1076,6 +1511,23 @@ } }} > + +
+ 0} + disabled={selectableFiles.length === 0} + onclick={toggleSelectAll} + class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 cursor-pointer disabled:cursor-not-allowed disabled:opacity-50" + title={allFilesSelected + ? "Deselect all" + : "Select all files"} + /> + Name Size Modified + {#if item.type === "file"} + + toggleFileSelection(item.id, e)} + class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 cursor-pointer" + title="Select for download" + /> + {/if} + @@ -1982,7 +2434,7 @@ {/if} {/if} + + +{#if showDownloadModal} +
{ + if ( + e.target === e.currentTarget && + downloadProgress.status !== "downloading" && + downloadProgress.status !== "zipping" + ) { + cancelDownload(); + } + }} + > +
e.stopPropagation()} + > + +
+

+ {#if downloadProgress.status === "preparing"} + Preparing Download... + {:else if downloadProgress.status === "downloading"} + Downloading Files + {:else if downloadProgress.status === "zipping"} + Creating Zip File + {:else if downloadProgress.status === "complete"} + Download Complete! + {:else if downloadProgress.status === "error"} + Download Failed + {/if} +

+ {#if downloadProgress.status !== "downloading" && downloadProgress.status !== "zipping"} + + {/if} +
+ + +
+ {#if downloadProgress.status === "error"} +
+ + + + {downloadProgress.errorMessage} +
+ {:else if downloadProgress.status === "complete"} + {@const hasFailures = downloadProgress.downloadedFiles.some(f => f.status === "error")} +
+ + {#if hasFailures} + + {:else} + + {/if} + + {downloadProgress.currentFile} +
+ {:else} +

+ {#if downloadProgress.status === "downloading"} + Downloading file {downloadProgress.currentFileIndex} of + {downloadProgress.totalFiles} + {:else if downloadProgress.status === "zipping"} + Compressing {downloadProgress.totalFiles} files into a + zip... + {:else} + Please wait while we prepare your download... + {/if} +

+ {#if downloadProgress.currentFile && downloadProgress.status === "downloading"} +

+ Current: {downloadProgress.currentFile} +

+ {/if} + {/if} +
+ + +
+
+ Overall Progress + {downloadProgress.overallProgress}% +
+
+
+
+
+ + + {#if downloadProgress.downloadedFiles.length > 0} +
+
+ {#each downloadProgress.downloadedFiles as file, idx} +
+ +
+ {#if file.status === "done"} + + + + {:else if file.status === "downloading"} +
+ {:else if file.status === "error"} + + + + {:else} +
+ {/if} +
+ +
+ + {file.name} + + {#if file.status === "error" && file.errorMessage} + + {file.errorMessage} + + {/if} +
+ + + {formatFileSize(file.size)} + +
+ {/each} +
+
+ {/if} + + + {#if downloadProgress.status === "downloading" || downloadProgress.status === "zipping"} +
+
+ + + +

+ Please don't close this window or navigate away + while the download is in progress. +

+
+
+ {/if} + + +
+ {#if downloadProgress.status === "error"} + + + {:else if downloadProgress.status === "complete"} + + {/if} +
+
+
+{/if} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4ca51984a..261d08a01 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -2377,6 +2377,9 @@ importers: axios: specifier: ^1.6.7 version: 1.13.2 + jszip: + specifier: ^3.10.1 + version: 3.10.1 svelte-qrcode: specifier: ^1.0.1 version: 1.0.1 @@ -6617,7 +6620,7 @@ packages: '@mui/base@5.0.0-beta.40': resolution: {integrity: sha512-I/lGHztkCzvwlXpjD2+SNmvNQvB4227xBXhISPjEaJUXGImOQ9f3D2Yj/T3KasSI/h0MLWy74X0J6clhPmsRbQ==} engines: {node: '>=12.0.0'} - deprecated: This package has been replaced by @base-ui-components/react + deprecated: This package has been replaced by @base-ui/react peerDependencies: '@types/react': 18.3.27 react: 18.3.1 @@ -13117,6 +13120,9 @@ packages: engines: {node: '>=16.x'} hasBin: true + immediate@3.0.6: + resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} + immutable@3.7.6: resolution: {integrity: sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw==} engines: {node: '>=0.8.0'} @@ -13910,6 +13916,9 @@ packages: resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} engines: {node: '>=4.0'} + jszip@3.10.1: + resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==} + jwa@1.4.2: resolution: {integrity: sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==} @@ -13994,6 +14003,9 @@ packages: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} + lie@3.3.0: + resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==} + light-my-request@5.14.0: resolution: {integrity: sha512-aORPWntbpH5esaYpGOOmri0OHDOe3wC5M2MQxZ9dvMLZm6DnaAn0kJlcbU9hwsQgLzmZyReKwFwwPkR+nHu5kA==} @@ -17501,10 +17513,12 @@ packages: tar@6.2.1: resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} engines: {node: '>=10'} + deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exhorbitant rates) by contacting i@izs.me tar@7.5.2: resolution: {integrity: sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==} engines: {node: '>=18'} + deprecated: Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exhorbitant rates) by contacting i@izs.me teeny-request@9.0.0: resolution: {integrity: sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g==} @@ -31916,6 +31930,8 @@ snapshots: image-size@2.0.2: {} + immediate@3.0.6: {} + immutable@3.7.6: {} immutable@5.1.4: {} @@ -33197,6 +33213,13 @@ snapshots: object.assign: 4.1.7 object.values: 1.2.1 + jszip@3.10.1: + dependencies: + lie: 3.3.0 + pako: 1.0.11 + readable-stream: 2.3.8 + setimmediate: 1.0.5 + jwa@1.4.2: dependencies: buffer-equal-constant-time: 1.0.1 @@ -33293,6 +33316,10 @@ snapshots: prelude-ls: 1.2.1 type-check: 0.4.0 + lie@3.3.0: + dependencies: + immediate: 3.0.6 + light-my-request@5.14.0: dependencies: cookie: 0.7.2