Skip to content

Commit 8946045

Browse files
committed
fix(files): cancel move-copy action should not be handled as an error
Instead we should just show an information message why the file is not moved / copied. Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
1 parent f645c9b commit 8946045

1 file changed

Lines changed: 32 additions & 13 deletions

File tree

apps/files/src/actions/moveOrCopyAction.ts

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import type { FileStat, ResponseDataDetailed } from 'webdav'
88
import type { MoveCopyResult } from './moveOrCopyActionUtils'
99

1010
import { isAxiosError } from '@nextcloud/axios'
11-
import { FilePickerClosed, getFilePickerBuilder, showError } from '@nextcloud/dialogs'
11+
import { FilePickerClosed, getFilePickerBuilder, showError, showInfo } from '@nextcloud/dialogs'
1212
import { emit } from '@nextcloud/event-bus'
1313
import { FileAction, FileType, NodeStatus, davGetClient, davRootPath, davResultToNode, davGetDefaultPropfind, getUniqueName, Permission } from '@nextcloud/files'
1414
import { translate as t } from '@nextcloud/l10n'
@@ -167,12 +167,17 @@ export const handleCopyMoveNodeTo = async (node: Node, destination: Folder, meth
167167

168168
/**
169169
* Open a file picker for the given action
170-
* @param {MoveCopyAction} action The action to open the file picker for
171-
* @param {string} dir The directory to start the file picker in
172-
* @param {Node[]} nodes The nodes to move/copy
173-
* @return {Promise<MoveCopyResult>} The picked destination
170+
* @param action The action to open the file picker for
171+
* @param dir The directory to start the file picker in
172+
* @param nodes The nodes to move/copy
173+
* @return The picked destination or false if cancelled by user
174174
*/
175-
const openFilePickerForAction = async (action: MoveCopyAction, dir = '/', nodes: Node[]): Promise<MoveCopyResult> => {
175+
async function openFilePickerForAction(
176+
action: MoveCopyAction,
177+
dir = '/',
178+
nodes: Node[],
179+
): Promise<MoveCopyResult | false> {
180+
const { resolve, reject, promise } = Promise.withResolvers<MoveCopyResult | false>()
176181
const fileIDs = nodes.map(node => node.fileid).filter(Boolean)
177182
const filePicker = getFilePickerBuilder(t('files', 'Choose destination'))
178183
.allowDirectories(true)
@@ -183,9 +188,7 @@ const openFilePickerForAction = async (action: MoveCopyAction, dir = '/', nodes:
183188
.setMimeTypeFilter([])
184189
.setMultiSelect(false)
185190
.startAt(dir)
186-
187-
return new Promise((resolve, reject) => {
188-
filePicker.setButtonFactory((selection: Node[], path: string) => {
191+
.setButtonFactory((selection: Node[], path: string) => {
189192
const buttons: IFilePickerButton[] = []
190193
const target = basename(path)
191194

@@ -234,17 +237,19 @@ const openFilePickerForAction = async (action: MoveCopyAction, dir = '/', nodes:
234237

235238
return buttons
236239
})
240+
.build()
237241

238-
const picker = filePicker.build()
239-
picker.pick().catch((error) => {
242+
filePicker.pick()
243+
.catch((error: Error) => {
240244
logger.debug(error as Error)
241245
if (error instanceof FilePickerClosed) {
242-
reject(new Error(t('files', 'Cancelled move or copy operation')))
246+
resolve(false)
243247
} else {
244248
reject(new Error(t('files', 'Move or copy operation failed')))
245249
}
246250
})
247-
})
251+
252+
return promise
248253
}
249254

250255
export const action = new FileAction({
@@ -277,6 +282,11 @@ export const action = new FileAction({
277282
logger.error(e as Error)
278283
return false
279284
}
285+
if (result === false) {
286+
showInfo(t('files', 'Cancelled move or copy of "{filename}".', { filename: node.displayname }))
287+
return null
288+
}
289+
280290
try {
281291
await handleCopyMoveNodeTo(node, result.destination, result.action)
282292
return true
@@ -293,6 +303,15 @@ export const action = new FileAction({
293303
async execBatch(nodes: Node[], view: View, dir: string) {
294304
const action = getActionForNodes(nodes)
295305
const result = await openFilePickerForAction(action, dir, nodes)
306+
// Handle cancellation silently
307+
if (result === false) {
308+
showInfo(nodes.length === 1
309+
? t('files', 'Cancelled move or copy of "{filename}".', { filename: nodes[0].displayname })
310+
: t('files', 'Cancelled move or copy operation')
311+
)
312+
return nodes.map(() => null)
313+
}
314+
296315
const promises = nodes.map(async node => {
297316
try {
298317
await handleCopyMoveNodeTo(node, result.destination, result.action)

0 commit comments

Comments
 (0)