diff --git a/src/gui/src/IPC.js b/src/gui/src/IPC.js index 3de9e5a57..f76ccd20c 100644 --- a/src/gui/src/IPC.js +++ b/src/gui/src/IPC.js @@ -1382,32 +1382,68 @@ const ipc_listener = async (event, handled) => { $(el_filedialog_window).find('.window-disable-mask, .busy-indicator').hide(); }; - const handle_move_save = async ({ source_path, target_path, el_filedialog_window }) => { + const handle_move_save = async ({ + // when 'source_path' has a value, 'save_type' is checked to determine + // if a fs.move() or fs.copy() needs to be performed. + save_type, + + source_path, target_path, el_filedialog_window, + }) => { // source path must be in appdata directory const stat_info = await puter.fs.stat(source_path); - if ( ! stat_info.appdata_app ) { - await puter.ui.alert(`the app ${app_uuid} attempted to ` + - `move data owned by the user illegaly`); - return; + if ( ! stat_info.appdata_app || stat_info.appdata_app !== app_uuid ) { + const source_file_owner = stat_info?.appdata_app ?? 'the user'; + if ( stat_info.appdata_app && stat_info.appdata_app !== app_uuid ) { + await UIAlert({ + message: `apps are prohibited from accessing AppData of other apps` + }); + return; + } + if ( save_type === 'move' ) { + await UIAlert({ + message: `the app ${app_name} tried to illegally move a file owned by ${source_file_owner}`, + }); + return; + } + + const alert_resp = await UIAlert({ + message: `the app ${app_name} is trying to copy ${source_path}; is this okay?`, + buttons: [ + { + label: i18n('yes'), + value: true, + type: 'primary', + }, + { + label: i18n('no'), + value: false, + type: 'secondary', + }, + ] + }); + + // `alert_resp` will be `"false"`, but this check is forward-compatible + // with a version of UIAlert that returns `false`. + if ( ! alert_resp || alert_resp === 'false' ) return; } - if ( stat_info.appdata_app !== app_uuid ) { - await puter.ui.alert(`the app ${app_uuid} attempted to ` + - `move data owned by ${stat_info.appdata_app}`); - return; - } - - console.log('supposedly we\'re writing this file now'); - let node; const written = await window.handle_same_name_exists({ action: async ({ overwrite }) => { if ( overwrite ) { await puter.fs.delete(target_path); } - await puter.fs.move(source_path, target_path); + + if ( save_type === 'copy' ) { + const target_dir = path.dirname(target_path); + const new_name = path.basename(target_path); + await puter.fs.copy(source_path, target_dir, { + newName: new_name, + }); + } else { + await puter.fs.move(source_path, target_path); + } node = await puter.fs.stat(target_path); - console.log('the move operation just happened', { node }); }, parent_uuid: $(el_filedialog_window).attr('data-element_uuid'), }); @@ -1441,6 +1477,7 @@ const ipc_listener = async (event, handled) => { done = await handle_url_save({ target_path }); } else if ( event.data.source_path ) { done = await handle_move_save({ + save_type: event.data.save_type, source_path: event.data.source_path, target_path, }); diff --git a/src/puter-js/src/modules/UI.js b/src/puter-js/src/modules/UI.js index ade763ff5..7192e7d8b 100644 --- a/src/puter-js/src/modules/UI.js +++ b/src/puter-js/src/modules/UI.js @@ -735,13 +735,14 @@ class UI extends EventListener { type = 'url'; } const url = type === 'url' ? content.toString() : undefined; - const source_path = type === 'move' ? content : undefined; - + const source_path = ['move','copy'].includes(type) ? content : undefined; + if(this.env === 'app'){ this.messageTarget?.postMessage({ msg: "showSaveFilePicker", appInstanceID: this.appInstanceID, content: url ? undefined : content, + save_type: type, url, source_path, suggestedName: suggestedName ?? '',