diff --git a/apps/files/src/components/FileEntry/FileEntryActions.vue b/apps/files/src/components/FileEntry/FileEntryActions.vue index 597fbc5a0826d..8d5bc0bf4ec20 100644 --- a/apps/files/src/components/FileEntry/FileEntryActions.vue +++ b/apps/files/src/components/FileEntry/FileEntryActions.vue @@ -179,7 +179,14 @@ export default defineComponent({ if (this.filesListWidth < 768 || this.gridMode) { return [] } - return this.enabledFileActions.filter(action => action?.inline?.(this.source, this.currentView)) + return this.enabledFileActions.filter(action => { + try { + return action?.inline?.(this.source, this.currentView) + } catch (error) { + logger.error('Error while checking if action is inline', { action, error }) + return false + } + }) }, // Enabled action that are displayed inline with a custom render function @@ -252,13 +259,19 @@ export default defineComponent({ methods: { actionDisplayName(action: FileAction) { - if ((this.gridMode || (this.filesListWidth < 768 && action.inline)) && typeof action.title === 'function') { - // if an inline action is rendered in the menu for - // lack of space we use the title first if defined - const title = action.title([this.source], this.currentView) - if (title) return title + try { + if ((this.gridMode || (this.filesListWidth < 768 && action.inline)) && typeof action.title === 'function') { + // if an inline action is rendered in the menu for + // lack of space we use the title first if defined + const title = action.title([this.source], this.currentView) + if (title) return title + } + return action.displayName([this.source], this.currentView) + } catch (error) { + logger.error('Error while getting action display name', { action, error }) + // Not ideal, but better than nothing + return action.id } - return action.displayName([this.source], this.currentView) }, async onActionClick(action, isSubmenu = false) { @@ -273,7 +286,13 @@ export default defineComponent({ return } - const displayName = action.displayName([this.source], this.currentView) + let displayName = action.id + try { + displayName = action.displayName([this.source], this.currentView) + } catch (error) { + logger.error('Error while getting action display name', { action, error }) + } + try { // Set the loading marker this.$emit('update:loading', action.id) @@ -291,8 +310,8 @@ export default defineComponent({ return } showError(t('files', '"{displayName}" action failed', { displayName })) - } catch (e) { - logger.error('Error while executing action', { action, e }) + } catch (error) { + logger.error('Error while executing action', { action, error }) showError(t('files', '"{displayName}" action failed', { displayName })) } finally { // Reset the loading marker diff --git a/apps/files/src/components/FileEntryMixin.ts b/apps/files/src/components/FileEntryMixin.ts index 7b0d875c88049..9f973d2affa12 100644 --- a/apps/files/src/components/FileEntryMixin.ts +++ b/apps/files/src/components/FileEntryMixin.ts @@ -23,15 +23,15 @@ import type { PropType } from 'vue' import type { FileSource } from '../types.ts' -import { showError } from '@nextcloud/dialogs' +import { extname } from 'path' import { FileType, Permission, Folder, File as NcFile, NodeStatus, Node, getFileActions } from '@nextcloud/files' -import { translate as t } from '@nextcloud/l10n' import { generateUrl } from '@nextcloud/router' import { vOnClickOutside } from '@vueuse/components' import { extname } from 'path' import Vue, { defineComponent } from 'vue' import { action as sidebarAction } from '../actions/sidebarAction.ts' +import { dataTransferToFileTree, onDropExternalFiles, onDropInternalFiles } from '../services/DropService.ts' import { getDragAndDropPreview } from '../utils/dragUtils.ts' import { hashCode } from '../utils/hashUtils.ts' import { dataTransferToFileTree, onDropExternalFiles, onDropInternalFiles } from '../services/DropService.ts' @@ -193,7 +193,20 @@ export default defineComponent({ } return actions - .filter(action => !action.enabled || action.enabled([this.source], this.currentView)) + .filter(action => { + if (!action.enabled) { + return true + } + + // In case something goes wrong, since we don't want to break + // the entire list, we filter out actions that throw an error. + try { + return action.enabled([this.source], this.currentView) + } catch (error) { + logger.error('Error while checking action', { action, error }) + return false + } + }) .sort((a, b) => (a.order || 0) - (b.order || 0)) },