diff options
author | Ferdinand Thiessen <opensource@fthiessen.de> | 2024-09-11 22:29:31 +0200 |
---|---|---|
committer | Ferdinand Thiessen <opensource@fthiessen.de> | 2024-10-16 17:51:14 +0200 |
commit | c11ee996848e44329f213107b7a94767c5befd6f (patch) | |
tree | 7fa0cb67577cee154ca0e1d7b1e40173d3f2132f /apps/files/src | |
parent | 4f0cbff7e4e982c710cd1688398687ad9e732701 (diff) | |
download | nextcloud-server-c11ee996848e44329f213107b7a94767c5befd6f.tar.gz nextcloud-server-c11ee996848e44329f213107b7a94767c5befd6f.zip |
fix(files): Add more visual move / copy notificationbackport/47910/stable28
* Resolves: https://github.com/nextcloud/server/issues/46645
This adds loading toast notification while the move operation is running.
Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
Diffstat (limited to 'apps/files/src')
-rw-r--r-- | apps/files/src/actions/moveOrCopyAction.ts | 28 | ||||
-rw-r--r-- | apps/files/src/components/FileEntryMixin.ts | 3 | ||||
-rw-r--r-- | apps/files/src/views/FilesList.vue | 7 |
3 files changed, 35 insertions, 3 deletions
diff --git a/apps/files/src/actions/moveOrCopyAction.ts b/apps/files/src/actions/moveOrCopyAction.ts index 6b6bc5a255e..9fe8e018ff7 100644 --- a/apps/files/src/actions/moveOrCopyAction.ts +++ b/apps/files/src/actions/moveOrCopyAction.ts @@ -25,7 +25,7 @@ import type { IFilePickerButton } from '@nextcloud/dialogs' import type { FileStat, ResponseDataDetailed } from 'webdav' import type { MoveCopyResult } from './moveOrCopyActionUtils' -import { FilePickerClosed, getFilePickerBuilder, showError, showInfo } from '@nextcloud/dialogs' +import { FilePickerClosed, getFilePickerBuilder, showError, showInfo, TOAST_PERMANENT_TIMEOUT } from '@nextcloud/dialogs' import { emit } from '@nextcloud/event-bus' import { FileAction, FileType, NodeStatus, davGetClient, davRootPath, davResultToNode, davGetDefaultPropfind, getUniqueName } from '@nextcloud/files' import { translate as t } from '@nextcloud/l10n' @@ -60,6 +60,28 @@ const getActionForNodes = (nodes: Node[]): MoveCopyAction => { } /** + * Create a loading notification toast + * @param mode The move or copy mode + * @param source Name of the node that is copied / moved + * @param destination Destination path + * @return {() => void} Function to hide the notification + */ +function createLoadingNotification(mode: MoveCopyAction, source: string, destination: string): () => void { + const text = mode === MoveCopyAction.MOVE ? t('files', 'Moving "{source}" to "{destination}" …', { source, destination }) : t('files', 'Copying "{source}" to "{destination}" …', { source, destination }) + + let toast: ReturnType<typeof showInfo>|undefined + toast = showInfo( + `<span class="icon icon-loading-small toast-loading-icon"></span> ${text}`, + { + isHTML: true, + timeout: TOAST_PERMANENT_TIMEOUT, + onRemove: () => { toast?.hideToast(); toast = undefined }, + }, + ) + return () => toast && toast.hideToast() +} + +/** * Handle the copy/move of a node to a destination * This can be imported and used by other scripts/components on server * @param {Node} node The node to copy/move @@ -99,6 +121,7 @@ export const handleCopyMoveNodeTo = async (node: Node, destination: Folder, meth // Set loading state Vue.set(node, 'status', NodeStatus.LOADING) + const actionFinished = createLoadingNotification(method, node.basename, destination.path) const queue = getQueue() return await queue.add(async () => { @@ -181,7 +204,8 @@ export const handleCopyMoveNodeTo = async (node: Node, destination: Folder, meth logger.debug(error as Error) throw new Error() } finally { - Vue.set(node, 'status', undefined) + Vue.set(node, 'status', '') + actionFinished() } }) } diff --git a/apps/files/src/components/FileEntryMixin.ts b/apps/files/src/components/FileEntryMixin.ts index 4c88cba00b8..83a68bfcf23 100644 --- a/apps/files/src/components/FileEntryMixin.ts +++ b/apps/files/src/components/FileEntryMixin.ts @@ -87,8 +87,9 @@ export default defineComponent({ uniqueId() { return hashCode(this.source.source) }, + isLoading() { - return this.source.status === NodeStatus.LOADING + return this.source.status === NodeStatus.LOADING || this.loading !== '' }, /** diff --git a/apps/files/src/views/FilesList.vue b/apps/files/src/views/FilesList.vue index 7121e40c7db..ba206aacad1 100644 --- a/apps/files/src/views/FilesList.vue +++ b/apps/files/src/views/FilesList.vue @@ -660,6 +660,13 @@ export default defineComponent({ </script> <style scoped lang="scss"> +:global(.toast-loading-icon) { + // Reduce start margin (it was made for text but this is an icon) + margin-inline-start: -4px; + // 16px icon + 5px on both sides + min-width: 26px; +} + .app-content { // Virtual list needs to be full height and is scrollable display: flex; |