From 81a68d8544b59b0fd35a6dea007e4377291fd4ab Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Mon, 17 Nov 2025 16:33:52 +0100 Subject: [PATCH 01/12] feat: provide `NcUploadPicker` previously contained in `@nextcloud/upload` Signed-off-by: Ferdinand Thiessen --- l10n/messages.pot | 27 + package-lock.json | 295 ++++++++- package.json | 4 + .../NcUploadPicker/NcUploadPicker.vue | 590 ++++++++++++++++++ src/components/NcUploadPicker/index.ts | 6 + 5 files changed, 894 insertions(+), 28 deletions(-) create mode 100644 src/components/NcUploadPicker/NcUploadPicker.vue create mode 100644 src/components/NcUploadPicker/index.ts diff --git a/l10n/messages.pot b/l10n/messages.pot index 3cd4247e04..2fdc00785e 100644 --- a/l10n/messages.pot +++ b/l10n/messages.pot @@ -40,6 +40,9 @@ msgstr "" msgid "Anything shared with the same group of people will show up here" msgstr "" +msgid "assembling" +msgstr "" + msgid "Avatar of {displayName}" msgstr "" @@ -79,6 +82,9 @@ msgstr "" msgid "Cancel changes" msgstr "" +msgid "Cancel uploads" +msgstr "" + msgid "Change name" msgstr "" @@ -130,6 +136,9 @@ msgstr "" msgid "Copy to clipboard" msgstr "" +msgid "Create new" +msgstr "" + #. TRANSLATORS: Ctrl key on keyboard (Windows/Linux) msgid "Ctrl" msgstr "" @@ -308,6 +317,9 @@ msgstr "" msgid "Neutral skin color" msgstr "" +msgid "New" +msgstr "" + msgid "Next" msgstr "" @@ -387,6 +399,9 @@ msgstr "" msgid "Pause slideshow" msgstr "" +msgid "paused" +msgstr "" + msgid "People & Body" msgstr "" @@ -582,6 +597,9 @@ msgstr "" msgid "Undo changes" msgstr "" +msgid "Upload" +msgstr "" + msgid "Upload file" msgstr "" @@ -591,6 +609,15 @@ msgstr "" msgid "Upload folder" msgstr "" +msgid "Upload folders" +msgstr "" + +msgid "Upload from device" +msgstr "" + +msgid "Upload progress" +msgstr "" + msgid "Uploading …" msgstr "" diff --git a/package-lock.json b/package-lock.json index 5a44a3806c..96d552fee2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -100,6 +100,10 @@ }, "engines": { "node": "^20.11.0 || ^22 || ^24" + }, + "optionalDependencies": { + "@nextcloud/dialogs": "^7.4.0", + "@nextcloud/files": "^4.1.0-beta.0" } }, "node_modules/@asamuzakjp/css-color": { @@ -3413,7 +3417,7 @@ "version": "7.4.47", "resolved": "https://registry.npmjs.org/@mdi/js/-/js-7.4.47.tgz", "integrity": "sha512-KPnNOtm5i2pMabqZxpUz7iQf+mfrYZyKCZ8QNz85czgEt7cuHcGorWfdzUMWYA0SD+a6Hn4FmJ+YhzzzjkTZrQ==", - "dev": true, + "devOptional": true, "license": "Apache-2.0" }, "node_modules/@mdi/svg": { @@ -3643,6 +3647,98 @@ "node": "^20.0.0 || ^22.0.0 || ^24.0.0" } }, + "node_modules/@nextcloud/dialogs": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/@nextcloud/dialogs/-/dialogs-7.4.0.tgz", + "integrity": "sha512-XAkRls7T1xIxH+E7ArW5+gY0CrqebT+3Pxo30u7XBc21UNgc8vhl4mv5SRiDe9OgSK6/QI0bPNMvCasSaSSVpA==", + "license": "AGPL-3.0-or-later", + "optional": true, + "dependencies": { + "@mdi/js": "^7.4.47", + "@nextcloud/auth": "^2.6.0", + "@nextcloud/axios": "^2.6.0", + "@nextcloud/browser-storage": "^0.5.0", + "@nextcloud/event-bus": "^3.3.3", + "@nextcloud/files": "^4.0.0", + "@nextcloud/initial-state": "^3.0.0", + "@nextcloud/l10n": "^3.4.1", + "@nextcloud/paths": "^3.1.0", + "@nextcloud/router": "^3.1.0", + "@nextcloud/sharing": "^0.4.0", + "@nextcloud/vue": "^9.8.0", + "@types/toastify-js": "^1.12.4", + "@vueuse/core": "^14.3.0", + "p-queue": "^9.1.2", + "toastify-js": "^1.12.0", + "vue": "^3.5.34", + "webdav": "^5.10.0" + }, + "engines": { + "node": "^20 || ^22 || ^24" + } + }, + "node_modules/@nextcloud/dialogs/node_modules/@nextcloud/files": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-4.0.0.tgz", + "integrity": "sha512-TmecnZIS+PGWGtRh7RpGEboCT4K6iTbHULUcfR6hs3eEzjDVsCc1Ldf8popGY/70lbpdlfYle8xbXnPIo3qaXA==", + "license": "AGPL-3.0-or-later", + "optional": true, + "dependencies": { + "@nextcloud/auth": "^2.5.3", + "@nextcloud/capabilities": "^1.2.1", + "@nextcloud/l10n": "^3.4.1", + "@nextcloud/logger": "^3.0.3", + "@nextcloud/paths": "^3.0.0", + "@nextcloud/router": "^3.1.0", + "@nextcloud/sharing": "^0.3.0", + "is-svg": "^6.1.0", + "typescript-event-target": "^1.1.2", + "webdav": "^5.9.0" + }, + "engines": { + "node": "^24.0.0" + } + }, + "node_modules/@nextcloud/dialogs/node_modules/@nextcloud/files/node_modules/@nextcloud/files": { + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-3.12.2.tgz", + "integrity": "sha512-vBo8tf3Xh6efiF8CrEo3pKj9AtvAF6RdDGO1XKL65IxV8+UUd9Uxl2lUExHlzoDRRczCqfGfaWfRRaFhYqce5Q==", + "license": "AGPL-3.0-or-later", + "optional": true, + "dependencies": { + "@nextcloud/auth": "^2.5.3", + "@nextcloud/capabilities": "^1.2.1", + "@nextcloud/l10n": "^3.4.1", + "@nextcloud/logger": "^3.0.3", + "@nextcloud/paths": "^3.0.0", + "@nextcloud/router": "^3.1.0", + "@nextcloud/sharing": "^0.3.0", + "cancelable-promise": "^4.3.1", + "is-svg": "^6.1.0", + "typescript-event-target": "^1.1.1", + "webdav": "^5.8.0" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || ^24.0.0" + } + }, + "node_modules/@nextcloud/dialogs/node_modules/@nextcloud/files/node_modules/@nextcloud/sharing": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@nextcloud/sharing/-/sharing-0.3.0.tgz", + "integrity": "sha512-kV7qeUZvd1fTKeFyH+W5Qq5rNOqG9rLATZM3U9MBxWXHJs3OxMqYQb8UQ3NYONzsX3zDGJmdQECIGHm1ei2sCA==", + "license": "GPL-3.0-or-later", + "optional": true, + "dependencies": { + "@nextcloud/initial-state": "^3.0.0", + "is-svg": "^6.1.0" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || ^24.0.0" + }, + "optionalDependencies": { + "@nextcloud/files": "^3.12.0" + } + }, "node_modules/@nextcloud/eslint-config": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/@nextcloud/eslint-config/-/eslint-config-9.0.1.tgz", @@ -3731,43 +3827,28 @@ } }, "node_modules/@nextcloud/files": { - "version": "3.12.2", - "resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-3.12.2.tgz", - "integrity": "sha512-vBo8tf3Xh6efiF8CrEo3pKj9AtvAF6RdDGO1XKL65IxV8+UUd9Uxl2lUExHlzoDRRczCqfGfaWfRRaFhYqce5Q==", + "version": "4.1.0-beta.0", + "resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-4.1.0-beta.0.tgz", + "integrity": "sha512-0V6yO3yVUkYb5hzo4FAl1Rp/ysSr6D56fvq+5W/mhIoha0hTecfvx05Q+yzQJAziCBxLeMrWIuXrY4epDE/rZQ==", "license": "AGPL-3.0-or-later", "optional": true, "dependencies": { - "@nextcloud/auth": "^2.5.3", + "@nextcloud/auth": "^2.6.0", + "@nextcloud/axios": "^2.6.0", "@nextcloud/capabilities": "^1.2.1", "@nextcloud/l10n": "^3.4.1", "@nextcloud/logger": "^3.0.3", - "@nextcloud/paths": "^3.0.0", + "@nextcloud/paths": "^3.1.0", "@nextcloud/router": "^3.1.0", - "@nextcloud/sharing": "^0.3.0", - "cancelable-promise": "^4.3.1", + "@nextcloud/sharing": "^0.4.0", + "axios-retry": "^4.5.0", "is-svg": "^6.1.0", - "typescript-event-target": "^1.1.1", - "webdav": "^5.8.0" - }, - "engines": { - "node": "^20.0.0 || ^22.0.0 || ^24.0.0" - } - }, - "node_modules/@nextcloud/files/node_modules/@nextcloud/sharing": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@nextcloud/sharing/-/sharing-0.3.0.tgz", - "integrity": "sha512-kV7qeUZvd1fTKeFyH+W5Qq5rNOqG9rLATZM3U9MBxWXHJs3OxMqYQb8UQ3NYONzsX3zDGJmdQECIGHm1ei2sCA==", - "license": "GPL-3.0-or-later", - "optional": true, - "dependencies": { - "@nextcloud/initial-state": "^3.0.0", - "is-svg": "^6.1.0" + "p-queue": "^9.3.0", + "typescript-event-target": "^1.1.2", + "webdav": "^5.10.0" }, "engines": { - "node": "^20.0.0 || ^22.0.0 || ^24.0.0" - }, - "optionalDependencies": { - "@nextcloud/files": "^3.12.0" + "node": "^24.0.0 || >=26.0.0" } }, "node_modules/@nextcloud/initial-state": { @@ -3845,6 +3926,68 @@ "@nextcloud/files": "^3.12.2 || ^4.0.0" } }, + "node_modules/@nextcloud/sharing/node_modules/@nextcloud/files": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-4.0.0.tgz", + "integrity": "sha512-TmecnZIS+PGWGtRh7RpGEboCT4K6iTbHULUcfR6hs3eEzjDVsCc1Ldf8popGY/70lbpdlfYle8xbXnPIo3qaXA==", + "license": "AGPL-3.0-or-later", + "optional": true, + "dependencies": { + "@nextcloud/auth": "^2.5.3", + "@nextcloud/capabilities": "^1.2.1", + "@nextcloud/l10n": "^3.4.1", + "@nextcloud/logger": "^3.0.3", + "@nextcloud/paths": "^3.0.0", + "@nextcloud/router": "^3.1.0", + "@nextcloud/sharing": "^0.3.0", + "is-svg": "^6.1.0", + "typescript-event-target": "^1.1.2", + "webdav": "^5.9.0" + }, + "engines": { + "node": "^24.0.0" + } + }, + "node_modules/@nextcloud/sharing/node_modules/@nextcloud/sharing": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@nextcloud/sharing/-/sharing-0.3.0.tgz", + "integrity": "sha512-kV7qeUZvd1fTKeFyH+W5Qq5rNOqG9rLATZM3U9MBxWXHJs3OxMqYQb8UQ3NYONzsX3zDGJmdQECIGHm1ei2sCA==", + "license": "GPL-3.0-or-later", + "optional": true, + "dependencies": { + "@nextcloud/initial-state": "^3.0.0", + "is-svg": "^6.1.0" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || ^24.0.0" + }, + "optionalDependencies": { + "@nextcloud/files": "^3.12.0" + } + }, + "node_modules/@nextcloud/sharing/node_modules/@nextcloud/sharing/node_modules/@nextcloud/files": { + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-3.12.2.tgz", + "integrity": "sha512-vBo8tf3Xh6efiF8CrEo3pKj9AtvAF6RdDGO1XKL65IxV8+UUd9Uxl2lUExHlzoDRRczCqfGfaWfRRaFhYqce5Q==", + "license": "AGPL-3.0-or-later", + "optional": true, + "dependencies": { + "@nextcloud/auth": "^2.5.3", + "@nextcloud/capabilities": "^1.2.1", + "@nextcloud/l10n": "^3.4.1", + "@nextcloud/logger": "^3.0.3", + "@nextcloud/paths": "^3.0.0", + "@nextcloud/router": "^3.1.0", + "@nextcloud/sharing": "^0.3.0", + "cancelable-promise": "^4.3.1", + "is-svg": "^6.1.0", + "typescript-event-target": "^1.1.1", + "webdav": "^5.8.0" + }, + "engines": { + "node": "^20.0.0 || ^22.0.0 || ^24.0.0" + } + }, "node_modules/@nextcloud/stylelint-config": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/@nextcloud/stylelint-config/-/stylelint-config-3.2.2.tgz", @@ -3904,6 +4047,62 @@ "vite": "^7.3.6" } }, + "node_modules/@nextcloud/vue": { + "version": "9.8.2", + "resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-9.8.2.tgz", + "integrity": "sha512-bkU6E/AyMXzNHk4BnUCL8QGfpT0BZkS7fooKhClHa9VK8wR6Mml/yO6/1Nd+E71dEiDKJP8B7TsvEXgytZsVQQ==", + "license": "AGPL-3.0-or-later", + "optional": true, + "dependencies": { + "@ckpack/vue-color": "^1.6.0", + "@floating-ui/dom": "^1.7.6", + "@nextcloud/auth": "^2.6.0", + "@nextcloud/axios": "^2.6.0", + "@nextcloud/browser-storage": "^0.5.0", + "@nextcloud/capabilities": "^1.2.1", + "@nextcloud/event-bus": "^3.3.3", + "@nextcloud/initial-state": "^3.0.0", + "@nextcloud/l10n": "^3.4.1", + "@nextcloud/logger": "^3.0.3", + "@nextcloud/router": "^3.1.0", + "@nextcloud/sharing": "^0.4.0", + "@nextcloud/vue-select": "^4.1.0", + "@vuepic/vue-datepicker": "^11.0.3", + "@vueuse/components": "^14.3.0", + "@vueuse/core": "^14.3.0", + "blurhash": "^2.0.5", + "clone": "^2.1.2", + "debounce": "^3.0.0", + "dompurify": "^3.4.7", + "emoji-mart-vue-fast": "^15.0.5", + "escape-html": "^1.0.3", + "floating-vue": "^5.2.2", + "focus-trap": "^8.2.1", + "linkifyjs": "^4.3.3", + "mdast-util-to-string": "^4.0.0", + "p-queue": "^9.3.0", + "rehype-external-links": "^3.0.0", + "rehype-highlight": "^7.0.2", + "rehype-react": "^8.0.0", + "remark-breaks": "^4.0.0", + "remark-parse": "^11.0.0", + "remark-rehype": "^11.1.2", + "remark-unlink-protocols": "^1.0.0", + "splitpanes": "^4.0.4", + "striptags": "^3.2.0", + "tabbable": "^6.4.0", + "tributejs": "^5.1.3", + "ts-md5": "^2.0.1", + "unified": "^11.0.5", + "unist-builder": "^4.0.0", + "unist-util-visit-parents": "^6.0.2", + "vue": "^3.5.18", + "vue-router": "^5.0.7" + }, + "engines": { + "node": "^20.11.0 || ^22 || ^24" + } + }, "node_modules/@nextcloud/vue-select": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/@nextcloud/vue-select/-/vue-select-4.1.0.tgz", @@ -5693,6 +5892,13 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/toastify-js": { + "version": "1.12.4", + "resolved": "https://registry.npmjs.org/@types/toastify-js/-/toastify-js-1.12.4.tgz", + "integrity": "sha512-zfZHU4tKffPCnZRe7pjv/eFKzTVHozKewFCKaCjZ4gFinKgJRz/t0bkZiMCXJxPhv/ZoeDGNOeRD09R0kQZ/nw==", + "license": "MIT", + "optional": true + }, "node_modules/@types/trusted-types": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", @@ -7511,6 +7717,19 @@ "proxy-from-env": "^2.1.0" } }, + "node_modules/axios-retry": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-4.5.0.tgz", + "integrity": "sha512-aR99oXhpEDGo0UuAlYcn2iGRds30k366Zfa05XWScR9QaQD4JYiP3/1Qt1u7YlefUOK+cn0CcwoL1oefavQUlQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "is-retry-allowed": "^2.2.0" + }, + "peerDependencies": { + "axios": "0.x || 1.x" + } + }, "node_modules/babel-loader": { "version": "9.2.1", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.2.1.tgz", @@ -15127,6 +15346,19 @@ "node": ">=0.10.0" } }, + "node_modules/is-retry-allowed": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-2.2.0.tgz", + "integrity": "sha512-XVm7LOeLpTW4jV19QSH38vkswxoLud8sQ57YwJVTPWdiaI9I8keEhGFpBlslyVsgdQy4Opg8QOLb8YRgsyZiQg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-root": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", @@ -24896,6 +25128,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/toastify-js": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/toastify-js/-/toastify-js-1.12.0.tgz", + "integrity": "sha512-HeMHCO9yLPvP9k0apGSdPUWrUbLnxUKNFzgUoZp1PHCLploIX/4DSQ7V8H25ef+h4iO9n0he7ImfcndnN6nDrQ==", + "license": "MIT", + "optional": true + }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", diff --git a/package.json b/package.json index 020a9246de..96f6579262 100644 --- a/package.json +++ b/package.json @@ -164,6 +164,10 @@ "webpack": "^5.110.3", "webpack-merge": "^6.0.1" }, + "optionalDependencies": { + "@nextcloud/dialogs": "^7.4.0", + "@nextcloud/files": "^4.1.0-beta.0" + }, "engines": { "node": "^20.11.0 || ^22 || ^24" }, diff --git a/src/components/NcUploadPicker/NcUploadPicker.vue b/src/components/NcUploadPicker/NcUploadPicker.vue new file mode 100644 index 0000000000..7846815e2a --- /dev/null +++ b/src/components/NcUploadPicker/NcUploadPicker.vue @@ -0,0 +1,590 @@ + + + + + + + + + +## Requirements + +To use the `NcUploadPicker` component, you need to install the following packages: +- `@nextcloud/dialogs` +- `@nextcloud/files` + +## Usage + +**TODO**: Add usage example here + diff --git a/src/components/NcUploadPicker/index.ts b/src/components/NcUploadPicker/index.ts new file mode 100644 index 0000000000..513b7c5ad0 --- /dev/null +++ b/src/components/NcUploadPicker/index.ts @@ -0,0 +1,6 @@ +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +export { default } from './NcUploadPicker.vue' From aa429525ba7eb1a866437eddaf69f47d31a0c6ab Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Mon, 17 Nov 2025 16:34:53 +0100 Subject: [PATCH 02/12] chore: drop hotkey handling - this should be handled by each app Signed-off-by: Ferdinand Thiessen --- src/components/NcUploadPicker/NcUploadPicker.vue | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/components/NcUploadPicker/NcUploadPicker.vue b/src/components/NcUploadPicker/NcUploadPicker.vue index 7846815e2a..52393f40c5 100644 --- a/src/components/NcUploadPicker/NcUploadPicker.vue +++ b/src/components/NcUploadPicker/NcUploadPicker.vue @@ -188,7 +188,6 @@ import NcActionSeparator from '../NcActionSeparator/NcActionSeparator.vue' import NcButton from '../NcButton/NcButton.vue' import NcIconSvgWrapper from '../NcIconSvgWrapper/NcIconSvgWrapper.vue' import NcProgressBar from '../NcProgressBar/NcProgressBar.vue' -import { useHotKey } from '../../composables/useHotKey/index.ts' import { t } from '../../l10n.ts' import { logger } from '../../utils/logger.ts' @@ -390,18 +389,6 @@ export default defineComponent({ // Update data on upload progress this.uploadManager.addNotifier(this.onUploadCompletion) - // Register hotkeys - useHotKey('u', this.onKeyDown, { - stop: true, - prevent: true, - shift: true, - }) - - useHotKey('Escape', this.onKeyDown, { - stop: true, - prevent: true, - }) - logger.debug('UploadPicker initialised') }, From 6e48466748c3dbbd240b9dd1a8392da63b643df1 Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Mon, 17 Nov 2025 17:20:15 +0100 Subject: [PATCH 03/12] refactor(NcUploadPicker): migrate component to script-setup Signed-off-by: Ferdinand Thiessen --- .../NcUploadPicker/NcUploadPicker.vue | 548 ++++++++---------- 1 file changed, 246 insertions(+), 302 deletions(-) diff --git a/src/components/NcUploadPicker/NcUploadPicker.vue b/src/components/NcUploadPicker/NcUploadPicker.vue index 52393f40c5..96b103f44a 100644 --- a/src/components/NcUploadPicker/NcUploadPicker.vue +++ b/src/components/NcUploadPicker/NcUploadPicker.vue @@ -168,15 +168,16 @@ - From 7aeca13dc00b3566313e4d18f893677293c678cc Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Sun, 28 Jun 2026 00:06:05 +0200 Subject: [PATCH 07/12] refactor(NcUploadPicker): migrate to nextcloud-files v4.1.0 Signed-off-by: Ferdinand Thiessen --- l10n/messages.pot | 8 +- package-lock.json | 282 ++++++------ package.json | 14 +- src/components/NcFilePicker/NcFilePicker.vue | 1 + .../NcUploadPicker/NcUploadPicker.vue | 431 +++++++++--------- src/components/NcUploadPicker/index.ts | 6 + src/components/index.ts | 1 + 7 files changed, 381 insertions(+), 362 deletions(-) diff --git a/l10n/messages.pot b/l10n/messages.pot index fe532bd6c2..48c10dc4d9 100644 --- a/l10n/messages.pot +++ b/l10n/messages.pot @@ -40,6 +40,7 @@ msgstr "" msgid "Anything shared with the same group of people will show up here" msgstr "" +#. TRANSLATORS: State of the current upload - chunks of the uploaded files are being assembled into the final file msgid "assembling" msgstr "" @@ -136,9 +137,6 @@ msgstr "" msgid "Copy to clipboard" msgstr "" -msgid "Create new" -msgstr "" - #. TRANSLATORS: Ctrl key on keyboard (Windows/Linux) msgid "Ctrl" msgstr "" @@ -204,6 +202,9 @@ msgstr "" msgid "Escape" msgstr "" +msgid "Estimating …" +msgstr "" + msgid "External documentation" msgstr "" @@ -399,6 +400,7 @@ msgstr "" msgid "Pause slideshow" msgstr "" +#. TRANSLATORS: State of the current upload - it is paused msgid "paused" msgstr "" diff --git a/package-lock.json b/package-lock.json index 96d552fee2..eab073c543 100644 --- a/package-lock.json +++ b/package-lock.json @@ -63,7 +63,9 @@ "@mdi/svg": "^7.4.47", "@nextcloud/babel-config": "^1.3.0", "@nextcloud/browserslist-config": "^3.1.2", + "@nextcloud/dialogs": "^7.5.0", "@nextcloud/eslint-config": "^9.0.1", + "@nextcloud/files": "^4.1.0-beta.2", "@nextcloud/stylelint-config": "^3.2.2", "@nextcloud/vite-config": "^2.5.0", "@nextcloud/webpack-vue-config": "github:nextcloud/webpack-vue-config#vue3", @@ -101,9 +103,17 @@ "engines": { "node": "^20.11.0 || ^22 || ^24" }, - "optionalDependencies": { + "peerDependencies": { "@nextcloud/dialogs": "^7.4.0", - "@nextcloud/files": "^4.1.0-beta.0" + "@nextcloud/files": "^4.1.0-beta.2" + }, + "peerDependenciesMeta": { + "@nextcloud/dialogs": { + "optional": true + }, + "@nextcloud/files": { + "optional": true + } } }, "node_modules/@asamuzakjp/css-color": { @@ -510,12 +520,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", - "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz", + "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==", "license": "MIT", "dependencies": { - "@babel/types": "^7.29.7" + "@babel/types": "^7.29.8" }, "bin": { "parser": "bin/babel-parser.js" @@ -1819,9 +1829,9 @@ } }, "node_modules/@babel/types": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", - "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.29.7", @@ -1858,8 +1868,8 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/@buttercup/fetch/-/fetch-0.2.1.tgz", "integrity": "sha512-sCgECOx8wiqY8NN1xN22BqqKzXYIG2AicNLlakOAI4f0WgyLVUbAigMf8CZhBtJxdudTcB1gD5lciqi44jwJvg==", + "devOptional": true, "license": "MIT", - "optional": true, "optionalDependencies": { "node-fetch": "^3.3.0" } @@ -3417,7 +3427,7 @@ "version": "7.4.47", "resolved": "https://registry.npmjs.org/@mdi/js/-/js-7.4.47.tgz", "integrity": "sha512-KPnNOtm5i2pMabqZxpUz7iQf+mfrYZyKCZ8QNz85czgEt7cuHcGorWfdzUMWYA0SD+a6Hn4FmJ+YhzzzjkTZrQ==", - "devOptional": true, + "dev": true, "license": "Apache-2.0" }, "node_modules/@mdi/svg": { @@ -3648,16 +3658,17 @@ } }, "node_modules/@nextcloud/dialogs": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@nextcloud/dialogs/-/dialogs-7.4.0.tgz", - "integrity": "sha512-XAkRls7T1xIxH+E7ArW5+gY0CrqebT+3Pxo30u7XBc21UNgc8vhl4mv5SRiDe9OgSK6/QI0bPNMvCasSaSSVpA==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@nextcloud/dialogs/-/dialogs-7.5.0.tgz", + "integrity": "sha512-2gmv0V3ObphxRd7ZvXwTsPvn/XSf2vummdXb2LRFpkoSamWbk+41SWv7cnDQPC+Ve9p46WebDuqyG+wbefkhEw==", + "dev": true, "license": "AGPL-3.0-or-later", - "optional": true, "dependencies": { "@mdi/js": "^7.4.47", "@nextcloud/auth": "^2.6.0", "@nextcloud/axios": "^2.6.0", "@nextcloud/browser-storage": "^0.5.0", + "@nextcloud/capabilities": "^1.2.1", "@nextcloud/event-bus": "^3.3.3", "@nextcloud/files": "^4.0.0", "@nextcloud/initial-state": "^3.0.0", @@ -3665,12 +3676,10 @@ "@nextcloud/paths": "^3.1.0", "@nextcloud/router": "^3.1.0", "@nextcloud/sharing": "^0.4.0", - "@nextcloud/vue": "^9.8.0", - "@types/toastify-js": "^1.12.4", - "@vueuse/core": "^14.3.0", - "p-queue": "^9.1.2", - "toastify-js": "^1.12.0", - "vue": "^3.5.34", + "@nextcloud/vue": "^9.9.0", + "@vueuse/core": "^14.4.0", + "p-queue": "^9.3.3", + "vue": "^3.5.41", "webdav": "^5.10.0" }, "engines": { @@ -3681,8 +3690,8 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-4.0.0.tgz", "integrity": "sha512-TmecnZIS+PGWGtRh7RpGEboCT4K6iTbHULUcfR6hs3eEzjDVsCc1Ldf8popGY/70lbpdlfYle8xbXnPIo3qaXA==", + "dev": true, "license": "AGPL-3.0-or-later", - "optional": true, "dependencies": { "@nextcloud/auth": "^2.5.3", "@nextcloud/capabilities": "^1.2.1", @@ -3703,6 +3712,7 @@ "version": "3.12.2", "resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-3.12.2.tgz", "integrity": "sha512-vBo8tf3Xh6efiF8CrEo3pKj9AtvAF6RdDGO1XKL65IxV8+UUd9Uxl2lUExHlzoDRRczCqfGfaWfRRaFhYqce5Q==", + "dev": true, "license": "AGPL-3.0-or-later", "optional": true, "dependencies": { @@ -3726,8 +3736,8 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/@nextcloud/sharing/-/sharing-0.3.0.tgz", "integrity": "sha512-kV7qeUZvd1fTKeFyH+W5Qq5rNOqG9rLATZM3U9MBxWXHJs3OxMqYQb8UQ3NYONzsX3zDGJmdQECIGHm1ei2sCA==", + "dev": true, "license": "GPL-3.0-or-later", - "optional": true, "dependencies": { "@nextcloud/initial-state": "^3.0.0", "is-svg": "^6.1.0" @@ -3827,11 +3837,11 @@ } }, "node_modules/@nextcloud/files": { - "version": "4.1.0-beta.0", - "resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-4.1.0-beta.0.tgz", - "integrity": "sha512-0V6yO3yVUkYb5hzo4FAl1Rp/ysSr6D56fvq+5W/mhIoha0hTecfvx05Q+yzQJAziCBxLeMrWIuXrY4epDE/rZQ==", + "version": "4.1.0-beta.2", + "resolved": "https://registry.npmjs.org/@nextcloud/files/-/files-4.1.0-beta.2.tgz", + "integrity": "sha512-tJlhPT8oAmdgyYJtrh4ufrRXfFS+LRZzZdTio64S8izTBXML0Gu/7PVUcOUglY0x/fFgUS5euc0GwNsZZecjbw==", + "dev": true, "license": "AGPL-3.0-or-later", - "optional": true, "dependencies": { "@nextcloud/auth": "^2.6.0", "@nextcloud/axios": "^2.6.0", @@ -3843,7 +3853,7 @@ "@nextcloud/sharing": "^0.4.0", "axios-retry": "^4.5.0", "is-svg": "^6.1.0", - "p-queue": "^9.3.0", + "p-queue": "^9.3.3", "typescript-event-target": "^1.1.2", "webdav": "^5.10.0" }, @@ -3892,8 +3902,8 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/@nextcloud/paths/-/paths-3.1.0.tgz", "integrity": "sha512-vtFYA/kthaUDzu6KejTOL1OwnOy7/yynq5zdB/UBpYacAWjUX5Ddh4OMWx3rEavkBJ9/QGhrFryNJLjNfe8OQA==", + "devOptional": true, "license": "GPL-3.0-or-later", - "optional": true, "engines": { "node": "^20.0.0 || ^22.0.0 || ^24.0.0" } @@ -4048,14 +4058,14 @@ } }, "node_modules/@nextcloud/vue": { - "version": "9.8.2", - "resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-9.8.2.tgz", - "integrity": "sha512-bkU6E/AyMXzNHk4BnUCL8QGfpT0BZkS7fooKhClHa9VK8wR6Mml/yO6/1Nd+E71dEiDKJP8B7TsvEXgytZsVQQ==", + "version": "9.11.0", + "resolved": "https://registry.npmjs.org/@nextcloud/vue/-/vue-9.11.0.tgz", + "integrity": "sha512-LRsyU9Mxs0b2xWqbxygps8O7/i1z4QhNQD9/QDni+VqFY3V0N95mAgmKJm6vfoFuxTAMXERp9bjqFn3UV542gw==", + "dev": true, "license": "AGPL-3.0-or-later", - "optional": true, "dependencies": { "@ckpack/vue-color": "^1.6.0", - "@floating-ui/dom": "^1.7.6", + "@floating-ui/dom": "^1.8.0", "@nextcloud/auth": "^2.6.0", "@nextcloud/axios": "^2.6.0", "@nextcloud/browser-storage": "^0.5.0", @@ -4068,19 +4078,19 @@ "@nextcloud/sharing": "^0.4.0", "@nextcloud/vue-select": "^4.1.0", "@vuepic/vue-datepicker": "^11.0.3", - "@vueuse/components": "^14.3.0", - "@vueuse/core": "^14.3.0", + "@vueuse/components": "^14.4.0", + "@vueuse/core": "^14.4.0", "blurhash": "^2.0.5", "clone": "^2.1.2", "debounce": "^3.0.0", - "dompurify": "^3.4.7", + "dompurify": "^3.4.14", "emoji-mart-vue-fast": "^15.0.5", "escape-html": "^1.0.3", "floating-vue": "^5.2.2", - "focus-trap": "^8.2.1", + "focus-trap": "^8.2.2", "linkifyjs": "^4.3.3", "mdast-util-to-string": "^4.0.0", - "p-queue": "^9.3.0", + "p-queue": "^9.3.3", "rehype-external-links": "^3.0.0", "rehype-highlight": "^7.0.2", "rehype-react": "^8.0.0", @@ -4097,7 +4107,7 @@ "unist-builder": "^4.0.0", "unist-util-visit-parents": "^6.0.2", "vue": "^3.5.18", - "vue-router": "^5.0.7" + "vue-router": "^5.2.0" }, "engines": { "node": "^20.11.0 || ^22 || ^24" @@ -5892,13 +5902,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/toastify-js": { - "version": "1.12.4", - "resolved": "https://registry.npmjs.org/@types/toastify-js/-/toastify-js-1.12.4.tgz", - "integrity": "sha512-zfZHU4tKffPCnZRe7pjv/eFKzTVHozKewFCKaCjZ4gFinKgJRz/t0bkZiMCXJxPhv/ZoeDGNOeRD09R0kQZ/nw==", - "license": "MIT", - "optional": true - }, "node_modules/@types/trusted-types": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", @@ -6512,13 +6515,13 @@ } }, "node_modules/@vue/compiler-core": { - "version": "3.5.34", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.34.tgz", - "integrity": "sha512-s9cLyK5mLcvZ4Agva5QgRsQyLKvts9WbU9DB6NqiZkkGEdwmcEiylj5Jbwkp680drF/NNCV8OlAJSe+yMLxaJw==", + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.41.tgz", + "integrity": "sha512-q0Xtv/F9w2YO/7htQhtiL+Ev2WCJbe5N2hc+XfgyKkEKqWpSxknmT8QOuGdEKNdjPq0c3F7rNpFkTo3Kfrm7pg==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.29.3", - "@vue/shared": "3.5.34", + "@babel/parser": "^7.29.8", + "@vue/shared": "3.5.41", "entities": "^7.0.1", "estree-walker": "^2.0.2", "source-map-js": "^1.2.1" @@ -6537,40 +6540,40 @@ } }, "node_modules/@vue/compiler-dom": { - "version": "3.5.34", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.34.tgz", - "integrity": "sha512-EbF/T++k0e2MMZlJsBhzK8Sgwt0HcIPOhzn1CTB/lv6sQcyk+OWf8YeiLxZp3ro7MbbLcAfAJ6sEvjFWuNgUCw==", + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.41.tgz", + "integrity": "sha512-oKacVfNglLvGjnS6BXOlGL7EyG2h8X03pqXCjzotRZUaXGjbrTJUnVAQjrCqUnS+lyu31nwQjZY/d817GmCnfw==", "license": "MIT", "dependencies": { - "@vue/compiler-core": "3.5.34", - "@vue/shared": "3.5.34" + "@vue/compiler-core": "3.5.41", + "@vue/shared": "3.5.41" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.5.34", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.34.tgz", - "integrity": "sha512-D/ihr6uZeIt6r+pVZf46RWT1fAsLFMbUP7k8G1VkiiWexriED9GrX3echHd4Abbt17zjlfiFJ8z7a3BxZOPNjg==", + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.41.tgz", + "integrity": "sha512-XJhip7R2wy6vX3knCxdZN4KracFaZUef58s1KYewqluedHIJaPIVfXoYT7MF1F8nCvv6k8bWWxDC8opMkg1VTQ==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.29.3", - "@vue/compiler-core": "3.5.34", - "@vue/compiler-dom": "3.5.34", - "@vue/compiler-ssr": "3.5.34", - "@vue/shared": "3.5.34", + "@babel/parser": "^7.29.8", + "@vue/compiler-core": "3.5.41", + "@vue/compiler-dom": "3.5.41", + "@vue/compiler-ssr": "3.5.41", + "@vue/shared": "3.5.41", "estree-walker": "^2.0.2", "magic-string": "^0.30.21", - "postcss": "^8.5.14", + "postcss": "^8.5.19", "source-map-js": "^1.2.1" } }, "node_modules/@vue/compiler-ssr": { - "version": "3.5.34", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.34.tgz", - "integrity": "sha512-cDtTHKibkThKGHH1SP+WdccquNRYQDFH6rRjQCqT9G2ltFAfoR5pUftpab/z+aM5mW9HLLVQW7hfKKQe/1GBeQ==", + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.41.tgz", + "integrity": "sha512-U3v5OejKEGqOI0Wy0+Sz7hGuIFZHA4LSXzrNM3IMIeDyJEBBfTpX26n3SDgToRpP2bLc9FfI2j/kSgcJ8Emq5A==", "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.34", - "@vue/shared": "3.5.34" + "@vue/compiler-dom": "3.5.41", + "@vue/shared": "3.5.41" } }, "node_modules/@vue/compiler-vue2": { @@ -6663,53 +6666,51 @@ } }, "node_modules/@vue/reactivity": { - "version": "3.5.34", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.34.tgz", - "integrity": "sha512-y9XDjCEuBp+98k+UL5dbYkh57AHU4o6cxZedOPXw3bmrZZYLQsVHguGurq7hVrPCSrQtrnz1f9dssyFr+dMXfQ==", + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.41.tgz", + "integrity": "sha512-rznsqKM0np0x18EjzF8x88MpEhdNsffbvFbckLL5+oUKz1BxAImEmO7J1ArRYSyo6aQaVoBDp7jEkT91OOxydA==", "license": "MIT", "dependencies": { - "@vue/shared": "3.5.34" + "@vue/shared": "3.5.41" } }, "node_modules/@vue/runtime-core": { - "version": "3.5.34", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.34.tgz", - "integrity": "sha512-mKeBYvu8tcMSLhypAHBmriUFfWXKTCF/23Z4jiCoYK3UtWepkliViNLuR90V9XOyD62mUxs9p1jsrpK3CCGIzw==", + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.41.tgz", + "integrity": "sha512-Vcry58hiAKwGen9Z1jUZE0feFsNArPCMOImYI8el48A9Idf6DuQYD0U05zZIF2Iad1hGhPSvcbBbAOhNr55fhg==", "license": "MIT", "dependencies": { - "@vue/reactivity": "3.5.34", - "@vue/shared": "3.5.34" + "@vue/reactivity": "3.5.41", + "@vue/shared": "3.5.41" } }, "node_modules/@vue/runtime-dom": { - "version": "3.5.34", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.34.tgz", - "integrity": "sha512-e8kZzERmCwUnBRVsgSQlAfrfU2rGoy0FFKPBXSlfEjc/O3KfA7QP0t1/2ZylrbchjmIKB4dPTd07A6WPr0eOrg==", + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.41.tgz", + "integrity": "sha512-3vVBahVBS9+U6cmXBLyb8nE6/yYo4J/CGI9eVFs3KiMc0YHuudwKyShTD65jtJy/L9PUUxNAFu4cj4LiJ0UFbw==", "license": "MIT", "dependencies": { - "@vue/reactivity": "3.5.34", - "@vue/runtime-core": "3.5.34", - "@vue/shared": "3.5.34", + "@vue/reactivity": "3.5.41", + "@vue/runtime-core": "3.5.41", + "@vue/shared": "3.5.41", "csstype": "^3.2.3" } }, "node_modules/@vue/server-renderer": { - "version": "3.5.34", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.34.tgz", - "integrity": "sha512-nHxmJoTrKsmrkbILRhkC9gY1G3moZbJTqCzDd7DOOzG5KH9oeJ0Unqrff5f9v0pW//jES05ZkJcNtfE8JjOIew==", + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.41.tgz", + "integrity": "sha512-n6hx/pNFfbD6SuyeuMVkvqox8bwf/ET9JlA/kAz/imw8sw++wkqKe2mHX5KutjPpbKE4Z56yTHszoOjGMI9igQ==", "license": "MIT", "dependencies": { - "@vue/compiler-ssr": "3.5.34", - "@vue/shared": "3.5.34" - }, - "peerDependencies": { - "vue": "3.5.34" + "@vue/compiler-ssr": "3.5.41", + "@vue/runtime-dom": "3.5.41", + "@vue/shared": "3.5.41" } }, "node_modules/@vue/shared": { - "version": "3.5.34", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.34.tgz", - "integrity": "sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==", + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.41.tgz", + "integrity": "sha512-IOnwSCma8j+9xJT6b8H0dEYidC80NsYmNMlZxRsukYcSoGaDBohog5hDxzeUXdFeGWFA++vWvxqOmrr96VlqMA==", "license": "MIT" }, "node_modules/@vue/test-utils": { @@ -7721,8 +7722,8 @@ "version": "4.5.0", "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-4.5.0.tgz", "integrity": "sha512-aR99oXhpEDGo0UuAlYcn2iGRds30k366Zfa05XWScR9QaQD4JYiP3/1Qt1u7YlefUOK+cn0CcwoL1oefavQUlQ==", + "dev": true, "license": "Apache-2.0", - "optional": true, "dependencies": { "is-retry-allowed": "^2.2.0" }, @@ -7854,8 +7855,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz", "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==", - "license": "MIT", - "optional": true + "devOptional": true, + "license": "MIT" }, "node_modules/base/node_modules/define-property": { "version": "1.0.0", @@ -8662,8 +8663,8 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/byte-length/-/byte-length-1.0.2.tgz", "integrity": "sha512-ovBpjmsgd/teRmgcPh23d4gJvxDoXtAzEL9xTfMU8Yc2kqCDb7L9jAG0XHl1nzuGl+h3ebCIF1i62UFyA9V/2Q==", - "license": "MIT", - "optional": true + "devOptional": true, + "license": "MIT" }, "node_modules/bytes": { "version": "3.1.2", @@ -9049,8 +9050,8 @@ "version": "0.0.2", "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", + "devOptional": true, "license": "BSD-3-Clause", - "optional": true, "engines": { "node": "*" } @@ -10261,8 +10262,8 @@ "version": "0.0.2", "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", + "devOptional": true, "license": "BSD-3-Clause", - "optional": true, "engines": { "node": "*" } @@ -10413,8 +10414,8 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "devOptional": true, "license": "MIT", - "optional": true, "engines": { "node": ">= 12" } @@ -12630,6 +12631,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "devOptional": true, "funding": [ { "type": "github", @@ -12641,7 +12643,6 @@ } ], "license": "MIT", - "optional": true, "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" @@ -13246,8 +13247,8 @@ "version": "4.0.10", "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "devOptional": true, "license": "MIT", - "optional": true, "dependencies": { "fetch-blob": "^3.1.2" }, @@ -14231,8 +14232,8 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/hot-patcher/-/hot-patcher-2.0.1.tgz", "integrity": "sha512-ECg1JFG0YzehicQaogenlcs2qg6WsXQsxtnbr1i696u5tLUjtJdQAh0u2g0Q5YV45f263Ta1GnUJsc8WIfJf4Q==", - "license": "MIT", - "optional": true + "devOptional": true, + "license": "MIT" }, "node_modules/hpack.js": { "version": "2.1.6", @@ -15350,8 +15351,8 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-2.2.0.tgz", "integrity": "sha512-XVm7LOeLpTW4jV19QSH38vkswxoLud8sQ57YwJVTPWdiaI9I8keEhGFpBlslyVsgdQy4Opg8QOLb8YRgsyZiQg==", + "dev": true, "license": "MIT", - "optional": true, "engines": { "node": ">=10" }, @@ -16068,8 +16069,8 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/layerr/-/layerr-3.0.0.tgz", "integrity": "sha512-tv754Ki2dXpPVApOrjTyRo4/QegVb9eVFq4mjqp4+NM5NaX7syQvN5BBNfV/ZpAHCEHV24XdUVrBAoka4jt3pA==", - "license": "MIT", - "optional": true + "devOptional": true, + "license": "MIT" }, "node_modules/leven": { "version": "2.1.0", @@ -16507,8 +16508,8 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", + "devOptional": true, "license": "BSD-3-Clause", - "optional": true, "dependencies": { "charenc": "0.0.2", "crypt": "0.0.2", @@ -16531,8 +16532,8 @@ "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "license": "MIT", - "optional": true + "devOptional": true, + "license": "MIT" }, "node_modules/mdast-squeeze-paragraphs": { "version": "6.0.0", @@ -18302,8 +18303,8 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/nested-property/-/nested-property-4.0.0.tgz", "integrity": "sha512-yFehXNWRs4cM0+dz7QxCd06hTbWbSkV0ISsqBfkntU6TOY4Qm3Q88fRRLOddkGh2Qq6dZvnKVAahfhjcUvLnyA==", - "license": "MIT", - "optional": true + "devOptional": true, + "license": "MIT" }, "node_modules/nice-try": { "version": "1.0.5", @@ -18337,6 +18338,7 @@ "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", "deprecated": "Use your platform's native DOMException instead", + "devOptional": true, "funding": [ { "type": "github", @@ -18348,7 +18350,6 @@ } ], "license": "MIT", - "optional": true, "engines": { "node": ">=10.5.0" } @@ -18357,8 +18358,8 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "devOptional": true, "license": "MIT", - "optional": true, "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", @@ -19315,8 +19316,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/path-posix/-/path-posix-1.0.0.tgz", "integrity": "sha512-1gJ0WpNIiYcQydgg3Ed8KzvIqTsDpNwq+cjBCssvBtuTWjEqY1AW+i+OepiEMqDCzyro9B2sLAe4RBPajMYFiA==", - "license": "ISC", - "optional": true + "devOptional": true, + "license": "ISC" }, "node_modules/path-scurry": { "version": "2.0.2", @@ -25128,13 +25129,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/toastify-js": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/toastify-js/-/toastify-js-1.12.0.tgz", - "integrity": "sha512-HeMHCO9yLPvP9k0apGSdPUWrUbLnxUKNFzgUoZp1PHCLploIX/4DSQ7V8H25ef+h4iO9n0he7ImfcndnN6nDrQ==", - "license": "MIT", - "optional": true - }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -25493,8 +25487,8 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/typescript-event-target/-/typescript-event-target-1.1.2.tgz", "integrity": "sha512-TvkrTUpv7gCPlcnSoEwUVUBwsdheKm+HF5u2tPAKubkIGMfovdSizCTaZRY/NhR8+Ijy8iZZUapbVQAsNrkFrw==", - "license": "MIT", - "optional": true + "devOptional": true, + "license": "MIT" }, "node_modules/ufo": { "version": "1.6.4", @@ -25964,8 +25958,8 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/url-join/-/url-join-5.0.0.tgz", "integrity": "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==", + "devOptional": true, "license": "MIT", - "optional": true, "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } @@ -26862,16 +26856,16 @@ "license": "MIT" }, "node_modules/vue": { - "version": "3.5.34", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.34.tgz", - "integrity": "sha512-WdLBG9gm02OgJIG9axd5Hpx0TFLdzVgfG2evFFu8Rur5O/IoGc5cMjnjh3tPL6GnRGsYvUhBSKVPYVcxRKpMCA==", + "version": "3.5.41", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.41.tgz", + "integrity": "sha512-2laE0p+aK+/AOPG/XL/WepOs/GlK755LJ1XECi9kDUrz1FKNw8rb2Xzlw9JS1rqEV55nb0ttsKxVlTCcd+R5cg==", "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.5.34", - "@vue/compiler-sfc": "3.5.34", - "@vue/runtime-dom": "3.5.34", - "@vue/server-renderer": "3.5.34", - "@vue/shared": "3.5.34" + "@vue/compiler-dom": "3.5.41", + "@vue/compiler-sfc": "3.5.41", + "@vue/runtime-dom": "3.5.41", + "@vue/server-renderer": "3.5.41", + "@vue/shared": "3.5.41" }, "peerDependencies": { "typescript": "*" @@ -29275,8 +29269,8 @@ "version": "3.3.3", "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "devOptional": true, "license": "MIT", - "optional": true, "engines": { "node": ">= 8" } @@ -29285,8 +29279,8 @@ "version": "5.10.0", "resolved": "https://registry.npmjs.org/webdav/-/webdav-5.10.0.tgz", "integrity": "sha512-fVPuRLtcduVGvSO7Tn/6TQCzIvI/g6BO/+xPRctCvi/GytYpjn4czxWbh4HsArsdom9qz9BI63k9/v2HBUui1A==", + "devOptional": true, "license": "MIT", - "optional": true, "dependencies": { "@buttercup/fetch": "^0.2.1", "base-64": "^1.0.0", @@ -29311,8 +29305,8 @@ "version": "2.1.4", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", + "devOptional": true, "license": "MIT", - "optional": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -29321,8 +29315,8 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "devOptional": true, "license": "BSD-2-Clause", - "optional": true, "engines": { "node": ">=0.12" }, @@ -29334,8 +29328,8 @@ "version": "9.0.9", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "devOptional": true, "license": "ISC", - "optional": true, "dependencies": { "brace-expansion": "^2.0.2" }, diff --git a/package.json b/package.json index 96f6579262..17eda66acd 100644 --- a/package.json +++ b/package.json @@ -129,7 +129,9 @@ "@mdi/svg": "^7.4.47", "@nextcloud/babel-config": "^1.3.0", "@nextcloud/browserslist-config": "^3.1.2", + "@nextcloud/dialogs": "^7.5.0", "@nextcloud/eslint-config": "^9.0.1", + "@nextcloud/files": "^4.1.0-beta.2", "@nextcloud/stylelint-config": "^3.2.2", "@nextcloud/vite-config": "^2.5.0", "@nextcloud/webpack-vue-config": "github:nextcloud/webpack-vue-config#vue3", @@ -164,9 +166,17 @@ "webpack": "^5.110.3", "webpack-merge": "^6.0.1" }, - "optionalDependencies": { + "peerDependencies": { "@nextcloud/dialogs": "^7.4.0", - "@nextcloud/files": "^4.1.0-beta.0" + "@nextcloud/files": "^4.1.0-beta.2" + }, + "peerDependenciesMeta": { + "@nextcloud/dialogs": { + "optional": true + }, + "@nextcloud/files": { + "optional": true + } }, "engines": { "node": "^20.11.0 || ^22 || ^24" diff --git a/src/components/NcFilePicker/NcFilePicker.vue b/src/components/NcFilePicker/NcFilePicker.vue index 3bf1a0dfef..8fa267fc02 100644 --- a/src/components/NcFilePicker/NcFilePicker.vue +++ b/src/components/NcFilePicker/NcFilePicker.vue @@ -129,6 +129,7 @@ defineSlots<{ defineExpose({ reset, + triggerPickFiles, }) const formElement = useTemplateRef('form') diff --git a/src/components/NcUploadPicker/NcUploadPicker.vue b/src/components/NcUploadPicker/NcUploadPicker.vue index b5691d7b15..af94cdc947 100644 --- a/src/components/NcUploadPicker/NcUploadPicker.vue +++ b/src/components/NcUploadPicker/NcUploadPicker.vue @@ -3,145 +3,32 @@ - SPDX-License-Identifier: AGPL-3.0-or-later --> - - + + +``` diff --git a/styleguide.config.cjs b/styleguide.config.cjs index 040a2177cb..6d850c68bd 100644 --- a/styleguide.config.cjs +++ b/styleguide.config.cjs @@ -64,6 +64,13 @@ module.exports = async () => { alias: { vue$: 'vue/dist/vue.esm-browser.js', }, + byDependency: { + // The code of the documentation examples is transpiled to CommonJS, + // so without the `import` condition ESM only packages - like `@nextcloud/files` - cannot be imported by them + commonjs: { + conditionNames: ['require', 'import', 'module', 'browser', 'default'], + }, + }, }, }), diff --git a/styleguide/global.requires.js b/styleguide/global.requires.js index 04a4f135e5..06a1be4e47 100644 --- a/styleguide/global.requires.js +++ b/styleguide/global.requires.js @@ -10,6 +10,7 @@ import { isA11yActivation } from '../src/functions/a11y/index.ts' import { spawnDialog } from '../src/functions/dialog/index.ts' import { emojiAddRecent, emojiSearch, EmojiSkinTone, getCurrentSkinTone, setCurrentSkinTone } from '../src/functions/emoji/index.ts' import { usernameToColor } from '../src/functions/usernameToColor/index.ts' +import { mockWebDav } from './webdav.mock.js' import 'regenerator-runtime/runtime.js' import 'core-js/stable/index.js' @@ -31,8 +32,13 @@ function mockRequests(error) { const { request, config } = error let data = null + // Failures without a response, like aborted requests, cannot be mocked + if (!request?.responseURL) { + return Promise.reject(error) + } + // Mock resolved link references for NcRichText - const resolveReferences = request.responseURL.match(/references\/resolvePublic/) + const resolveReferences = request.responseURL.match(/references\/resolve(Public)?\?/) if (resolveReferences) { const referenceValue = new URL(request.responseURL).searchParams.get('reference') data = { @@ -82,6 +88,9 @@ function mockRequests(error) { axios.interceptors.response.use((r) => r, (e) => mockRequests(e)) +// Fake the WebDAV endpoints used for uploading files +mockWebDav() + // app name fallback window.appName = 'nextcloud-vue' diff --git a/styleguide/webdav.mock.js b/styleguide/webdav.mock.js new file mode 100644 index 0000000000..b90e2ff016 --- /dev/null +++ b/styleguide/webdav.mock.js @@ -0,0 +1,142 @@ +/** + * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import axios from '@nextcloud/axios' + +/** Requests to this endpoint are answered by the fake WebDAV server */ +const DAV_ENDPOINT = /\/(remote|public)\.php\/dav\// + +/** Simulated transfer speed in bytes per second */ +const UPLOAD_SPEED = 4 * 1024 * 1024 + +/** Minimum duration of a simulated upload in milliseconds, so the progress stays visible for small files */ +const MIN_UPLOAD_DURATION = 2500 + +/** Delay between two simulated upload progress events in milliseconds */ +const PROGRESS_INTERVAL = 100 + +/** Simulated duration of assembling the chunks of a chunked upload in milliseconds */ +const ASSEMBLE_DURATION = 1500 + +/** Simulated duration of all other requests in milliseconds */ +const REQUEST_DURATION = 250 + +/** + * Fake the WebDAV endpoints used for uploading files. + * + * There is no Nextcloud server behind the styleguide, so all requests of the uploader + * (`@nextcloud/files/upload`, used by `NcUploadPicker`) are answered locally + * by simulating a slow but successful upload. + */ +export function mockWebDav() { + axios.interceptors.request.use((config) => { + if (DAV_ENDPOINT.test(config.url ?? '')) { + config.adapter = davAdapter + } + return config + }) +} + +/** + * Custom Axios adapter answering WebDAV requests without any network access. + * + * @param {object} config - The Axios request config + * @return {Promise} The simulated Axios response + */ +async function davAdapter(config) { + switch (config.method?.toUpperCase()) { + case 'HEAD': + // The upload destination exists, any other directory (e.g. an uploaded one) has to be created first + await wait(REQUEST_DURATION, config.signal) + return respond(config, config.url.endsWith('/') ? 200 : 404) + case 'PUT': + // Uploading a file or one chunk of it + await simulateUpload(config) + return respond(config, 201) + case 'MOVE': + // Assembling the chunks of a chunked upload + await wait(ASSEMBLE_DURATION, config.signal) + return respond(config, 204) + default: + // MKCOL to create a directory or the temporary workspace of a chunked upload + await wait(REQUEST_DURATION, config.signal) + return respond(config, 201) + } +} + +/** + * Simulate transferring the data of a request, including the upload progress events. + * + * @param {object} config - The Axios request config + */ +async function simulateUpload(config) { + const total = config.data?.size ?? 0 + const duration = Math.max(MIN_UPLOAD_DURATION, (total / UPLOAD_SPEED) * 1000) + const steps = Math.ceil(duration / PROGRESS_INTERVAL) + + let loaded = 0 + for (let step = 1; step <= steps; step++) { + await wait(PROGRESS_INTERVAL, config.signal) + const bytes = Math.round((total * step) / steps) - loaded + loaded += bytes + config.onUploadProgress?.({ bytes, loaded, total, lengthComputable: true }) + } +} + +/** + * Create the response of a simulated request. + * Just like Axios, responses with an error status are rejected. + * + * @param {object} config - The Axios request config + * @param {number} status - The HTTP status to respond with + * @return {object} The simulated Axios response + */ +function respond(config, status) { + const response = { + config, + data: '', + headers: {}, + request: { responseURL: config.url }, + status, + statusText: '', + } + + if (status >= 200 && status < 300) { + return response + } + + // Mimic an `AxiosError` so the failure is handled like the one of a real request + return Promise.reject(Object.assign(new Error(`Request failed with status code ${status}`), { + config, + isAxiosError: true, + request: response.request, + response, + status, + })) +} + +/** + * Wait for the given duration, but reject as soon as the request is aborted. + * + * @param {number} duration - Time to wait in milliseconds + * @param {AbortSignal} [signal] - Signal used to abort the request + * @return {Promise} + */ +function wait(duration, signal) { + if (signal?.aborted) { + return Promise.reject(signal.reason) + } + + const { promise, resolve, reject } = Promise.withResolvers() + const onAbort = () => reject(signal.reason) + + const timeout = setTimeout(resolve, duration) + signal?.addEventListener('abort', onAbort, { once: true }) + + return promise.finally(() => { + clearTimeout(timeout) + signal?.removeEventListener('abort', onAbort) + }) +} diff --git a/styleguide/window.js b/styleguide/window.js index f038bf97b5..c7181fabf1 100644 --- a/styleguide/window.js +++ b/styleguide/window.js @@ -6,6 +6,11 @@ // Global variables window._oc_webroot = '' +// Simulate a logged in user, this is what `getCurrentUser()` of `@nextcloud/auth` reads +document.head.setAttribute('data-user', 'admin') +document.head.setAttribute('data-user-displayname', 'Administrator') +window._oc_isadmin = true + window.OC = { debug: true, getCurrentUser() {