From 741c44a02aeed9dc7fc3b6398af9bedb4f31beff Mon Sep 17 00:00:00 2001 From: Grigory Vodyanov Date: Wed, 2 Sep 2026 17:52:21 +0200 Subject: [PATCH 1/7] feat(vue3): drop the unused v-tooltip plugin The directive was registered globally in the entry point but never used in a template or stylesheet. @nextcloud/vue 9 removes its own tooltip directive anyway, so there is nothing to migrate to later. Assisted-by: ClaudeCode:claude-opus-5 Signed-off-by: Grigory Vodyanov --- package-lock.json | 22 ---------------------- package.json | 1 - src/main.js | 2 -- 3 files changed, 25 deletions(-) diff --git a/package-lock.json b/package-lock.json index c934c0ee35..4778b048ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -55,7 +55,6 @@ "raw-loader": "^4.0.2", "stylelint": "^17.14.1", "uuid": "^14.0.2", - "v-tooltip": "^2.1.3", "vue": "^2.7.16", "vue-autosize": "^1.0.2", "vue-dndrop": "^1.3.4", @@ -14035,16 +14034,6 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/popper.js": { - "version": "1.16.1", - "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", - "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==", - "deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" - } - }, "node_modules/possible-typed-array-names": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", @@ -17523,17 +17512,6 @@ "uuid": "dist-node/bin/uuid" } }, - "node_modules/v-tooltip": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/v-tooltip/-/v-tooltip-2.1.3.tgz", - "integrity": "sha512-xXngyxLQTOx/yUEy50thb8te7Qo4XU6h4LZB6cvEfVd9mnysUxLEoYwGWDdqR+l69liKsy3IPkdYff3J1gAJ5w==", - "dependencies": { - "@babel/runtime": "^7.13.10", - "lodash": "^4.17.21", - "popper.js": "^1.16.1", - "vue-resize": "^1.0.1" - } - }, "node_modules/vanilla-colorful": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/vanilla-colorful/-/vanilla-colorful-0.7.2.tgz", diff --git a/package.json b/package.json index fb3ada3b9f..2f0709742e 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,6 @@ "raw-loader": "^4.0.2", "stylelint": "^17.14.1", "uuid": "^14.0.2", - "v-tooltip": "^2.1.3", "vue": "^2.7.16", "vue-autosize": "^1.0.2", "vue-dndrop": "^1.3.4", diff --git a/src/main.js b/src/main.js index bc815d8fbf..712a2bb2a2 100644 --- a/src/main.js +++ b/src/main.js @@ -7,7 +7,6 @@ import { getRequestToken } from '@nextcloud/auth' import { registerDavProperty } from '@nextcloud/files' import { generateFilePath } from '@nextcloud/router' import { createPinia, PiniaVuePlugin } from 'pinia' -import vToolTip from 'v-tooltip' import Vue from 'vue' import VueShortKey from 'vue-shortkey' import App from './App.vue' @@ -27,7 +26,6 @@ const pinia = createPinia() Vue.mixin(Nextcloud) Vue.use(VueShortKey, { prevent: ['input', 'div', 'textarea'] }) -Vue.use(vToolTip) registerDavProperty('nc:share-attributes', { nc: 'http://nextcloud.org/ns' }) From 065fe2e912aaf925e8b423670e429eba82e223cb Mon Sep 17 00:00:00 2001 From: Grigory Vodyanov Date: Wed, 2 Sep 2026 17:52:30 +0200 Subject: [PATCH 2/7] feat(vue3): swap the isMobile mixin for useIsMobile The isMobile mixin is deprecated and removed in @nextcloud/vue 9. Both read the same module-level ref, so this is behaviour-identical on 8.41. Assisted-by: ClaudeCode:claude-opus-5 Signed-off-by: Grigory Vodyanov --- src/components/MailboxThread.vue | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/components/MailboxThread.vue b/src/components/MailboxThread.vue index 02e492eca3..1dd0907624 100644 --- a/src/components/MailboxThread.vue +++ b/src/components/MailboxThread.vue @@ -200,7 +200,8 @@ - diff --git a/src/components/mailFilter/ActionFileinto.vue b/src/components/mailFilter/ActionFileinto.vue index a73286c04d..0992b37d55 100644 --- a/src/components/mailFilter/ActionFileinto.vue +++ b/src/components/mailFilter/ActionFileinto.vue @@ -54,11 +54,7 @@ export default { diff --git a/src/tests/unit/components/MailboxInlinePicker.vue.spec.js b/src/tests/unit/components/MailboxInlinePicker.vue.spec.js new file mode 100644 index 0000000000..69969e72c8 --- /dev/null +++ b/src/tests/unit/components/MailboxInlinePicker.vue.spec.js @@ -0,0 +1,71 @@ +/** + * SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import { createTestingPinia } from '@pinia/testing' +import { createLocalVue, shallowMount } from '@vue/test-utils' +import { PiniaVuePlugin, setActivePinia } from 'pinia' +import MailboxInlinePicker from '../../../components/MailboxInlinePicker.vue' +import Nextcloud from '../../../mixins/Nextcloud.js' +import useMainStore from '../../../store/mainStore.js' + +const localVue = createLocalVue() +localVue.use(PiniaVuePlugin) +localVue.mixin(Nextcloud) + +describe('MailboxInlinePicker', () => { + let store + + const mount = () => shallowMount(MailboxInlinePicker, { + propsData: { + account: { accountId: 1 }, + }, + localVue, + }) + + beforeEach(() => { + setActivePinia(createTestingPinia()) + store = useMainStore() + }) + + it('flattens nested mailboxes into indented options', () => { + store.getMailboxes = vi.fn().mockReturnValue([ + { databaseId: 1, displayName: 'INBOX' }, + { databaseId: 4, displayName: 'Sent' }, + ]) + store.getSubMailboxes = vi.fn().mockImplementation((id) => { + switch (id) { + case 1: + return [{ databaseId: 2, displayName: 'Archive' }] + case 2: + return [{ databaseId: 3, displayName: '2020' }] + default: + return [] + } + }) + + const view = mount() + + expect(view.vm.mailboxes).toEqual([ + { id: 1, label: 'INBOX', depth: 0 }, + { id: 2, label: 'Archive', depth: 1 }, + { id: 3, label: '2020', depth: 2 }, + { id: 4, label: 'Sent', depth: 0 }, + ]) + }) + + it('skips mailboxes the user may not insert into', () => { + store.getMailboxes = vi.fn().mockReturnValue([ + { databaseId: 1, displayName: 'INBOX' }, + { databaseId: 2, displayName: 'Shared', myAcls: 'lr' }, + ]) + store.getSubMailboxes = vi.fn().mockReturnValue([]) + + const view = mount() + + expect(view.vm.mailboxes).toEqual([ + { id: 1, label: 'INBOX', depth: 0 }, + ]) + }) +}) From aa1a500ffb0de6a17a755d634e19965791b773cd Mon Sep 17 00:00:00 2001 From: Grigory Vodyanov Date: Wed, 2 Sep 2026 17:53:01 +0200 Subject: [PATCH 7/7] feat(vue3): replace vue-tabs-component with NcRadioGroup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit vue-tabs-component is Vue-2-only. NcTabs does not exist in the 8.x line and 8.41 is its last release, so the tabs become a segmented control — the same NcRadioGroup pattern the app settings dialog already uses. Panels stay mounted under v-show, matching what the tabs library did, and the manual-mode prefill becomes an immediate watcher because the library used to emit its changed event once on mount. Most of the diff is one tab level of re-indentation from dropping the Tabs wrapper; git diff -w shows the actual change. Assisted-by: ClaudeCode:claude-opus-5 Signed-off-by: Grigory Vodyanov --- package-lock.json | 9 - package.json | 1 - src/components/AccountForm.vue | 496 ++++++++++++++++----------------- 3 files changed, 239 insertions(+), 267 deletions(-) diff --git a/package-lock.json b/package-lock.json index d958c34def..9151b8b9b1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -60,7 +60,6 @@ "vue-material-design-icons": "^5.3.1", "vue-router": "^3.6.5", "vue-shortkey": "^3.1.7", - "vue-tabs-component": "^1.5.0", "webdav": "5.10.0" }, "devDependencies": { @@ -17941,14 +17940,6 @@ "node": ">=4.0.0" } }, - "node_modules/vue-tabs-component": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/vue-tabs-component/-/vue-tabs-component-1.5.0.tgz", - "integrity": "sha512-ld4p+hv49Fimw+zv/7GQqMhbjAHjpbWF3UiJtmMaSnvLKbsB1ysfs9dQH0SZ8NvdYpqqKay/VLIqR9yXgse1Sg==", - "peerDependencies": { - "vue": "^2.3.0" - } - }, "node_modules/vue-template-compiler": { "version": "2.7.16", "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz", diff --git a/package.json b/package.json index b4682a5765..b61e2659c3 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,6 @@ "vue-material-design-icons": "^5.3.1", "vue-router": "^3.6.5", "vue-shortkey": "^3.1.7", - "vue-tabs-component": "^1.5.0", "webdav": "5.10.0" }, "devDependencies": { diff --git a/src/components/AccountForm.vue b/src/components/AccountForm.vue index b48e25995e..287f590736 100644 --- a/src/components/AccountForm.vue +++ b/src/components/AccountForm.vue @@ -4,234 +4,236 @@ -->