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 @@
@@ -160,6 +161,16 @@
{{ t('files_sharing', 'Customize link') }}
+
+
+
+
+ {{ t('files_sharing', 'Customize link') }}
+
{
+ 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', 'Share') }}
+
+
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 @@