@@ -8,7 +8,7 @@ import type { FileStat, ResponseDataDetailed } from 'webdav'
88import type { MoveCopyResult } from './moveOrCopyActionUtils'
99
1010import { isAxiosError } from '@nextcloud/axios'
11- import { FilePickerClosed , getFilePickerBuilder , showError } from '@nextcloud/dialogs'
11+ import { FilePickerClosed , getFilePickerBuilder , showError , showInfo } from '@nextcloud/dialogs'
1212import { emit } from '@nextcloud/event-bus'
1313import { FileAction , FileType , NodeStatus , davGetClient , davRootPath , davResultToNode , davGetDefaultPropfind , getUniqueName , Permission } from '@nextcloud/files'
1414import { 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
250255export 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