From c73b63c787b2c383953d2946b34ce7066d30b8e6 Mon Sep 17 00:00:00 2001 From: nfebe Date: Tue, 5 May 2026 11:05:41 +0100 Subject: [PATCH] fix(files_sharing): Hide incompatible actions in pending and deleted share views Pending and deleted share entries are not mounted into the user's filesystem, so generic file operations like delete, download, or rename cannot succeed and produce a misleading "file is not available" error. Affected actions now opt out of these views, leaving only accept and reject (pending) and restore (deleted) as available row operations. --- apps/files/src/actions/convertAction.ts | 5 ++++- apps/files/src/actions/deleteAction.ts | 4 ++++ apps/files/src/actions/downloadAction.ts | 4 ++++ apps/files/src/actions/favoriteAction.ts | 6 +++++- apps/files/src/actions/moveOrCopyAction.ts | 3 +++ apps/files/src/actions/openFolderAction.ts | 6 +++++- apps/files/src/actions/openLocallyAction.ts | 6 +++++- apps/files/src/actions/renameAction.ts | 4 ++++ apps/files/src/actions/sidebarAction.ts | 6 +++++- apps/files/src/actions/viewInFolderAction.ts | 4 ++++ apps/files_sharing/src/files_actions/sharingStatusAction.ts | 6 +++++- 11 files changed, 48 insertions(+), 6 deletions(-) diff --git a/apps/files/src/actions/convertAction.ts b/apps/files/src/actions/convertAction.ts index 9443809ea0aa6..d4754fc2ab57b 100644 --- a/apps/files/src/actions/convertAction.ts +++ b/apps/files/src/actions/convertAction.ts @@ -31,11 +31,14 @@ export function registerConvertActions() { id: `convert-${from}-${to}`, displayName: () => t('files', 'Save as {displayName}', { displayName }), iconSvgInline: () => generateIconSvg(to), - enabled: ({ nodes, folder }) => { + enabled: ({ nodes, folder, view }) => { if (isPublicShare() && !(folder.permissions & Permission.CREATE)) { // cannot create the converted file in a public share if we don't have create permissions return false } + if (view.id === 'pendingshares' || view.id === 'deletedshares') { + return false + } // Check that all nodes have the same mime type return nodes.every((node) => from === node.mime) }, diff --git a/apps/files/src/actions/deleteAction.ts b/apps/files/src/actions/deleteAction.ts index 582820199ac56..0e8f65d33f71e 100644 --- a/apps/files/src/actions/deleteAction.ts +++ b/apps/files/src/actions/deleteAction.ts @@ -39,6 +39,10 @@ export const action: IFileAction = { }, enabled({ nodes, view }) { + if (view.id === 'pendingshares' || view.id === 'deletedshares') { + return false + } + if (view.id === TRASHBIN_VIEW_ID) { const config = loadState('files_trashbin', 'config', { allow_delete: true }) if (config.allow_delete === false) { diff --git a/apps/files/src/actions/downloadAction.ts b/apps/files/src/actions/downloadAction.ts index 63f943ddcedb3..d62867a2fcedd 100644 --- a/apps/files/src/actions/downloadAction.ts +++ b/apps/files/src/actions/downloadAction.ts @@ -29,6 +29,10 @@ export const action: IFileAction = { return false } + if (view.id === 'pendingshares' || view.id === 'deletedshares') { + return false + } + // We can only download dav files and folders. if (nodes.some((node) => !node.isDavResource)) { return false diff --git a/apps/files/src/actions/favoriteAction.ts b/apps/files/src/actions/favoriteAction.ts index f3b109871b2f0..c4ff7daca6f6d 100644 --- a/apps/files/src/actions/favoriteAction.ts +++ b/apps/files/src/actions/favoriteAction.ts @@ -35,12 +35,16 @@ export const action: IFileAction = { : StarSvg }, - enabled({ nodes }) { + enabled({ nodes, view }) { // Not enabled for public shares if (isPublicShare()) { return false } + if (view.id === 'pendingshares' || view.id === 'deletedshares') { + return false + } + // We can only favorite nodes if they are located in files return nodes.every((node) => node.root?.startsWith?.('/files')) // and we have permissions diff --git a/apps/files/src/actions/moveOrCopyAction.ts b/apps/files/src/actions/moveOrCopyAction.ts index 68f00f48ce2ef..79f38c7b9b1aa 100644 --- a/apps/files/src/actions/moveOrCopyAction.ts +++ b/apps/files/src/actions/moveOrCopyAction.ts @@ -49,6 +49,9 @@ export const action: IFileAction = { if (view.id === 'public-file-share') { return false } + if (view.id === 'pendingshares' || view.id === 'deletedshares') { + return false + } // We only support moving/copying files within the user folder if (!nodes.every((node) => node.root?.startsWith('/files/'))) { return false diff --git a/apps/files/src/actions/openFolderAction.ts b/apps/files/src/actions/openFolderAction.ts index 29ec4efc7b233..4b02d30042ae5 100644 --- a/apps/files/src/actions/openFolderAction.ts +++ b/apps/files/src/actions/openFolderAction.ts @@ -22,12 +22,16 @@ export const action: IFileAction = { }, iconSvgInline: () => FolderSvg, - enabled({ nodes }) { + enabled({ nodes, view }) { // Only works on single node if (nodes.length !== 1 || !nodes[0]) { return false } + if (view.id === 'pendingshares' || view.id === 'deletedshares') { + return false + } + const node = nodes[0] if (!node.isDavResource) { return false diff --git a/apps/files/src/actions/openLocallyAction.ts b/apps/files/src/actions/openLocallyAction.ts index 2afc168333ce2..8466fdf1ea484 100644 --- a/apps/files/src/actions/openLocallyAction.ts +++ b/apps/files/src/actions/openLocallyAction.ts @@ -23,7 +23,7 @@ export const action: IFileAction = { iconSvgInline: () => LaptopSvg, // Only works on single files - enabled({ nodes }) { + enabled({ nodes, view }) { // Only works on single node if (nodes.length !== 1 || !nodes[0]) { return false @@ -34,6 +34,10 @@ export const action: IFileAction = { return false } + if (view.id === 'pendingshares' || view.id === 'deletedshares') { + return false + } + return isSyncable(nodes[0]!) }, diff --git a/apps/files/src/actions/renameAction.ts b/apps/files/src/actions/renameAction.ts index 28b2bcd29a853..43000292afe95 100644 --- a/apps/files/src/actions/renameAction.ts +++ b/apps/files/src/actions/renameAction.ts @@ -30,6 +30,10 @@ export const action: IFileAction = { return false } + if (view.id === 'pendingshares' || view.id === 'deletedshares') { + return false + } + const node = nodes[0] const filesStore = useFilesStore(getPinia()) const parentNode = node.dirname === '/' diff --git a/apps/files/src/actions/sidebarAction.ts b/apps/files/src/actions/sidebarAction.ts index 1449bb414acf4..860ccdf21f8a5 100644 --- a/apps/files/src/actions/sidebarAction.ts +++ b/apps/files/src/actions/sidebarAction.ts @@ -19,7 +19,7 @@ export const action: IFileAction = { iconSvgInline: () => InformationSvg, // Sidebar currently supports user folder only, /files/USER - enabled: ({ nodes }) => { + enabled: ({ nodes, view }) => { const node = nodes[0] if (nodes.length !== 1 || !node) { return false @@ -34,6 +34,10 @@ export const action: IFileAction = { return false } + if (view.id === 'pendingshares' || view.id === 'deletedshares') { + return false + } + return node.root.startsWith('/files/') && node.permissions !== Permission.NONE }, diff --git a/apps/files/src/actions/viewInFolderAction.ts b/apps/files/src/actions/viewInFolderAction.ts index ea86e1f6e508a..7319e651bd865 100644 --- a/apps/files/src/actions/viewInFolderAction.ts +++ b/apps/files/src/actions/viewInFolderAction.ts @@ -28,6 +28,10 @@ export const action: IFileAction = { return false } + if (view.id === 'pendingshares' || view.id === 'deletedshares') { + return false + } + // Only works on single node if (nodes.length !== 1 || !nodes[0]) { return false diff --git a/apps/files_sharing/src/files_actions/sharingStatusAction.ts b/apps/files_sharing/src/files_actions/sharingStatusAction.ts index 086d507ad4953..600d558a95aa7 100644 --- a/apps/files_sharing/src/files_actions/sharingStatusAction.ts +++ b/apps/files_sharing/src/files_actions/sharingStatusAction.ts @@ -105,7 +105,7 @@ export const action: IFileAction = { return AccountPlusSvg }, - enabled({ nodes }) { + enabled({ nodes, view }) { if (nodes.length !== 1) { return false } @@ -115,6 +115,10 @@ export const action: IFileAction = { return false } + if (view.id === 'pendingshares' || view.id === 'deletedshares') { + return false + } + const node = nodes[0]! const shareTypes = node.attributes?.['share-types'] const isMixed = Array.isArray(shareTypes) && shareTypes.length > 0