diff options
author | skjnldsv <skjnldsv@protonmail.com> | 2024-12-12 10:50:39 +0100 |
---|---|---|
committer | Christopher Ng <chrng8@gmail.com> | 2024-12-12 10:08:38 -0800 |
commit | 34299e6a5d9bcbdb6af0d49da26e85f236701349 (patch) | |
tree | 3a949144acd49e42a2632e3e162bf3282372829e /apps | |
parent | 9c08d3b0b8cd0f2443d81e82eb5b50731fd92f9f (diff) | |
download | nextcloud-server-34299e6a5d9bcbdb6af0d49da26e85f236701349.tar.gz nextcloud-server-34299e6a5d9bcbdb6af0d49da26e85f236701349.zip |
fix(files): protect filelist actions with try...catch
Signed-off-by: skjnldsv <skjnldsv@protonmail.com>
Diffstat (limited to 'apps')
-rw-r--r-- | apps/files/src/views/FilesList.vue | 53 | ||||
-rw-r--r-- | apps/files_trashbin/src/fileListActions/emptyTrashAction.ts | 7 |
2 files changed, 50 insertions, 10 deletions
diff --git a/apps/files/src/views/FilesList.vue b/apps/files/src/views/FilesList.vue index 4f7945881d9..d4f58b53a65 100644 --- a/apps/files/src/views/FilesList.vue +++ b/apps/files/src/views/FilesList.vue @@ -44,13 +44,15 @@ force-name> <NcActionButton v-for="action in enabledFileListActions" :key="action.id" + :disabled="!!loadingAction" close-after-click - @click="action.exec(currentView, dirContents, currentFolder)"> + @click="execFileListAction(action)"> <template #icon> - <NcIconSvgWrapper v-if="action.iconSvgInline !== undefined" + <NcLoadingIcon v-if="loadingAction === action.id" :size="18" /> + <NcIconSvgWrapper v-else-if="action.iconSvgInline !== undefined && currentView" :svg="action.iconSvgInline(currentView)" /> </template> - {{ action.displayName(currentView) }} + {{ actionDisplayName(action) }} </NcActionButton> </NcActions> @@ -132,7 +134,7 @@ </template> <script lang="ts"> -import type { ContentsWithRoot, Folder, INode } from '@nextcloud/files' +import type { ContentsWithRoot, FileListAction, Folder, INode } from '@nextcloud/files' import type { Upload } from '@nextcloud/upload' import type { CancelablePromise } from 'cancelable-promise' import type { ComponentPublicInstance } from 'vue' @@ -144,7 +146,7 @@ import { emit, subscribe, unsubscribe } from '@nextcloud/event-bus' import { Node, Permission, sortNodes, getFileListActions } from '@nextcloud/files' import { translate as t } from '@nextcloud/l10n' import { join, dirname, normalize } from 'path' -import { showError, showWarning } from '@nextcloud/dialogs' +import { showError, showSuccess, showWarning } from '@nextcloud/dialogs' import { ShareType } from '@nextcloud/sharing' import { UploadPicker, UploadStatus } from '@nextcloud/upload' import { loadState } from '@nextcloud/initial-state' @@ -258,6 +260,7 @@ export default defineComponent({ data() { return { loading: true, + loadingAction: null as string | null, error: null as string | null, promise: null as CancelablePromise<ContentsWithRoot> | Promise<ContentsWithRoot> | null, @@ -437,6 +440,10 @@ export default defineComponent({ }, enabledFileListActions() { + if (!this.currentView || !this.currentFolder) { + return [] + } + const actions = getFileListActions() const enabledActions = actions .filter(action => { @@ -446,7 +453,7 @@ export default defineComponent({ return action.enabled( this.currentView!, this.dirContents, - { folder: this.currentFolder! }, + this.currentFolder as Folder, ) }) .toSorted((a, b) => a.order - b.order) @@ -714,6 +721,40 @@ export default defineComponent({ } this.dirContentsFiltered = nodes }, + + actionDisplayName(action: FileListAction): string { + let displayName = action.id + try { + displayName = action.displayName(this.currentView!) + } catch (error) { + logger.error('Error while getting action display name', { action, error }) + } + return displayName + }, + + async execFileListAction(action: FileListAction) { + this.loadingAction = action.id + + const displayName = this.actionDisplayName(action) + try { + const success = await action.exec(this.source, this.dirContents, this.currentDir) + // If the action returns null, we stay silent + if (success === null || success === undefined) { + return + } + + if (success) { + showSuccess(t('files', '"{displayName}" action executed successfully', { displayName })) + return + } + showError(t('files', '"{displayName}" action failed', { displayName })) + } catch (error) { + logger.error('Error while executing action', { action, error }) + showError(t('files', '"{displayName}" action failed', { displayName })) + } finally { + this.loadingAction = null + } + }, }, }) </script> diff --git a/apps/files_trashbin/src/fileListActions/emptyTrashAction.ts b/apps/files_trashbin/src/fileListActions/emptyTrashAction.ts index b0a2fbdd2c2..9c45d6a8565 100644 --- a/apps/files_trashbin/src/fileListActions/emptyTrashAction.ts +++ b/apps/files_trashbin/src/fileListActions/emptyTrashAction.ts @@ -2,8 +2,7 @@ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ - -import type { Node } from '@nextcloud/files' +import type { Node, View, Folder } from '@nextcloud/files' import PQueue from 'p-queue' import { FileListAction } from '@nextcloud/files' @@ -73,14 +72,14 @@ export const emptyTrashAction = new FileListAction({ displayName: () => t('files_trashbin', 'Empty deleted files'), order: 0, - enabled: (view, nodes, folder) => { + enabled(view: View, nodes: Node[], folder: Folder) { if (view.id !== 'trashbin') { return false } return nodes.length > 0 && folder.path === '/' }, - exec: async (view, nodes) => { + async exec(view: View, nodes: Node[]) { const dialog = getDialogBuilder(t('files_trashbin', 'Confirm permanent deletion')) .setSeverity(DialogSeverity.Warning) // TODO Add note for groupfolders |