From 5bbb8506fc24881faca803cca13f96466f746b80 Mon Sep 17 00:00:00 2001 From: skjnldsv Date: Fri, 24 Jul 2026 10:58:59 +0200 Subject: [PATCH 1/3] feat(files_sharing): add hidden killswitch for the new sharing dialog Add a hidden appconfig `files_sharing sharing_dialog_enabled` (BOOL, default true) surfaced to the sidebar via initial state. When enabled the sidebar uses the new unified sharing dialog; setting it to false temporarily restores the legacy inline sharing UI. Assisted-by: ClaudeCode:claude-opus-4-8 Signed-off-by: skjnldsv --- apps/files_sharing/lib/Config/ConfigLexicon.php | 5 +++++ apps/files_sharing/lib/Listener/LoadSidebarListener.php | 3 +++ apps/files_sharing/src/services/ConfigService.ts | 9 +++++++++ 3 files changed, 17 insertions(+) diff --git a/apps/files_sharing/lib/Config/ConfigLexicon.php b/apps/files_sharing/lib/Config/ConfigLexicon.php index c0f57a932bba3..efa3817a46943 100644 --- a/apps/files_sharing/lib/Config/ConfigLexicon.php +++ b/apps/files_sharing/lib/Config/ConfigLexicon.php @@ -26,6 +26,7 @@ class ConfigLexicon implements ILexicon { public const EXCLUDE_RESHARE_FROM_EDIT = 'shareapi_exclude_reshare_from_edit'; public const UPDATE_CUTOFF_TIME = 'update_cutoff_time'; public const USER_NEEDS_SHARE_REFRESH = 'user_needs_share_refresh'; + public const SHARING_DIALOG_ENABLED = 'sharing_dialog_enabled'; #[\Override] public function getStrictness(): Strictness { @@ -40,6 +41,10 @@ public function getAppConfigs(): array { new Entry(self::EXCLUDE_RESHARE_FROM_EDIT, ValueType::BOOL, false, 'Exclude reshare permission from "Allow editing" bundled permissions'), new Entry(self::UPDATE_CUTOFF_TIME, ValueType::FLOAT, 3.0, 'Maximum time in second during which we update the share data immediately before switching to only marking the user'), + + // Hidden killswitch: enables the new unified sharing dialog UI in the sidebar. + // Set to false to temporarily restore the legacy sharing inputs and menus. + new Entry(self::SHARING_DIALOG_ENABLED, ValueType::BOOL, true, 'Use the new unified sharing dialog in the files sidebar instead of the legacy inline UI', true), ]; } diff --git a/apps/files_sharing/lib/Listener/LoadSidebarListener.php b/apps/files_sharing/lib/Listener/LoadSidebarListener.php index e6a30a5688173..b6b0e25cef9b1 100644 --- a/apps/files_sharing/lib/Listener/LoadSidebarListener.php +++ b/apps/files_sharing/lib/Listener/LoadSidebarListener.php @@ -47,8 +47,11 @@ public function handle(Event $event): void { $showExternalSharing = $appConfig->getValueBool('files_sharing', 'outgoing_server2server_share_enabled', true) || $appConfig->getValueBool('core', 'shareapi_allow_links', true); + $sharingDialogEnabled = $appConfig->getValueBool('files_sharing', ConfigLexicon::SHARING_DIALOG_ENABLED, true); + $this->initialState->provideInitialState('showFederatedSharesAsInternal', $showFederatedAsInternal); $this->initialState->provideInitialState('showFederatedSharesToTrustedServersAsInternal', $showFederatedToTrustedAsInternal); $this->initialState->provideInitialState('showExternalSharing', $showExternalSharing); + $this->initialState->provideInitialState('sharingDialogEnabled', $sharingDialogEnabled); } } diff --git a/apps/files_sharing/src/services/ConfigService.ts b/apps/files_sharing/src/services/ConfigService.ts index 7d3a24672ea6a..320fb8e359d37 100644 --- a/apps/files_sharing/src/services/ConfigService.ts +++ b/apps/files_sharing/src/services/ConfigService.ts @@ -344,4 +344,13 @@ export default class Config { get showExternalSharing(): boolean { return loadState('files_sharing', 'showExternalSharing', true) } + + /** + * Whether the new unified sharing dialog replaces the legacy inline sharing UI. + * Hidden killswitch (appconfig files_sharing sharing_dialog_enabled); set to + * false to temporarily restore the legacy inputs and menus. + */ + get sharingDialogEnabled(): boolean { + return loadState('files_sharing', 'sharingDialogEnabled', true) + } } From 9a6f84019053d563c321bd9d33b98f8a5c45b0f0 Mon Sep 17 00:00:00 2001 From: skjnldsv Date: Fri, 24 Jul 2026 10:59:11 +0200 Subject: [PATCH 2/3] feat(files_sharing): use the unified sharing dialog in the sidebar Gated by the sharing_dialog_enabled killswitch (default on): - SharingTab: hide both legacy SharingInputs, add a single Share button that opens the new dialog to create a share. - SharingEntry (internal): replace the details 3-dots button with an Edit + Delete dual button and hide the quick-share permission select. - SharingEntryLink: hide the quick-share select and route Customize link to the new dialog. Edit opens the share in the new dialog by id (resolved via the upcoming legacy->unified bridge). The legacy UI stays intact behind the killswitch. Assisted-by: ClaudeCode:claude-opus-4-8 Signed-off-by: skjnldsv --- .../src/components/SharingEntry.vue | 43 ++++++++++++++++++- .../src/components/SharingEntryLink.vue | 25 ++++++++++- .../src/services/SharingDialog.ts | 28 ++++++++++++ apps/files_sharing/src/views/SharingTab.vue | 31 ++++++++++++- 4 files changed, 123 insertions(+), 4 deletions(-) create mode 100644 apps/files_sharing/src/services/SharingDialog.ts diff --git a/apps/files_sharing/src/components/SharingEntry.vue b/apps/files_sharing/src/components/SharingEntry.vue index 24b7b3f9da6e5..e5540e9f97b22 100644 --- a/apps/files_sharing/src/components/SharingEntry.vue +++ b/apps/files_sharing/src/components/SharingEntry.vue @@ -28,13 +28,14 @@ + + @@ -52,11 +76,15 @@ import { ShareType } from '@nextcloud/sharing' import NcAvatar from '@nextcloud/vue/components/NcAvatar' import NcButton from '@nextcloud/vue/components/NcButton' import NcSelect from '@nextcloud/vue/components/NcSelect' +import DeleteIcon from 'vue-material-design-icons/Delete.vue' import DotsHorizontalIcon from 'vue-material-design-icons/DotsHorizontal.vue' +import PencilIcon from 'vue-material-design-icons/Pencil.vue' import ShareExpiryTime from './ShareExpiryTime.vue' import SharingEntryQuickShareSelect from './SharingEntryQuickShareSelect.vue' import ShareDetails from '../mixins/ShareDetails.js' import SharesMixin from '../mixins/SharesMixin.js' +import { openShareEditDialog } from '../services/SharingDialog.ts' +import logger from '../services/logger.ts' export default { name: 'SharingEntry', @@ -64,7 +92,9 @@ export default { components: { NcButton, NcAvatar, + DeleteIcon, DotsHorizontalIcon, + PencilIcon, NcSelect, ShareExpiryTime, SharingEntryQuickShareSelect, @@ -130,6 +160,17 @@ export default { }, methods: { + /** + * Open the unified sharing dialog to edit this share. + */ + async openEditDialog() { + try { + await openShareEditDialog(this.share.id, this.fileInfo.node) + } catch (error) { + logger.error('Failed to open the sharing dialog', { error }) + } + }, + /** * Save potential changed data on menu close */ diff --git a/apps/files_sharing/src/components/SharingEntryLink.vue b/apps/files_sharing/src/components/SharingEntryLink.vue index 7e2c22713e2d7..f10dbdd1316d8 100644 --- a/apps/files_sharing/src/components/SharingEntryLink.vue +++ b/apps/files_sharing/src/components/SharingEntryLink.vue @@ -21,7 +21,7 @@ {{ subtitle }}

@@ -152,6 +152,7 @@ { + return openSharingDialog(node) +} + +/** + * Open the unified sharing dialog to edit an existing share. + * + * @param shareId The share id (mapped to the unified API by the legacy bridge) + * @param node The backing node, used for the dialog title + */ +export async function openShareEditDialog(shareId: string | number, node?: Node): Promise { + const share = await getShare(String(shareId)) + return share.showDialog(node) +} diff --git a/apps/files_sharing/src/views/SharingTab.vue b/apps/files_sharing/src/views/SharingTab.vue index 0463a9969d28f..ed22cf04e867d 100644 --- a/apps/files_sharing/src/views/SharingTab.vue +++ b/apps/files_sharing/src/views/SharingTab.vue @@ -27,6 +27,19 @@ + + +

{{ t('files_sharing', 'Internal shares') }}

@@ -48,7 +61,7 @@
Date: Fri, 24 Jul 2026 12:11:03 +0200 Subject: [PATCH 3/3] feat(files_sharing): confirm before deleting a share from the sidebar The new Delete dual-button deleted immediately. Add a confirmation dialog so the destructive action is not one accidental click away. Assisted-by: ClaudeCode:claude-opus-4-8 Signed-off-by: skjnldsv --- .../src/components/SharingEntry.vue | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/apps/files_sharing/src/components/SharingEntry.vue b/apps/files_sharing/src/components/SharingEntry.vue index e5540e9f97b22..58572fa653bea 100644 --- a/apps/files_sharing/src/components/SharingEntry.vue +++ b/apps/files_sharing/src/components/SharingEntry.vue @@ -62,7 +62,7 @@ class="sharing-entry__action" :aria-label="t('files_sharing', 'Delete share')" variant="tertiary" - @click="onDelete"> + @click="confirmDelete"> @@ -72,6 +72,7 @@