diff --git a/src/gui/src/IPC.js b/src/gui/src/IPC.js index f76ccd20c..6d7e35866 100644 --- a/src/gui/src/IPC.js +++ b/src/gui/src/IPC.js @@ -1315,6 +1315,13 @@ const ipc_listener = async (event, handled) => { $(el_filedialog_window).close(); window.show_save_account_notice_if_needed(); }; + + const tell_caller_its_cancelled = async () => { + target_iframe.contentWindow.postMessage({ + msg: "fileSaveCancelled", + original_msg_id: msg_id, + }, '*'); + }; const write_file_tell_caller_and_update_views = async ({ target_path, el_filedialog_window, @@ -1468,6 +1475,7 @@ const ipc_listener = async (event, handled) => { iframe_msg_uid: msg_id, center: true, initiating_app_uuid: app_uuid, + onDialogCancel: () => tell_caller_its_cancelled(), onSaveFileDialogSave: async function(target_path, el_filedialog_window){ $(el_filedialog_window).find('.window-disable-mask, .busy-indicator').show(); let busy_init_ts = Date.now(); diff --git a/src/gui/src/UI/UIWindow.js b/src/gui/src/UI/UIWindow.js index e7627d033..3fa4f8349 100644 --- a/src/gui/src/UI/UIWindow.js +++ b/src/gui/src/UI/UIWindow.js @@ -896,6 +896,7 @@ async function UIWindow(options) { $(`.window[data-element_uuid="${options.parent_uuid}"]`).find('.window-disable-mask').hide(); $(el_window).close(); }) + if ( options.onDialogCancel ) options.onDialogCancel.call(el_window); }) } diff --git a/src/puter-js/src/modules/UI.js b/src/puter-js/src/modules/UI.js index 7192e7d8b..fb28d4498 100644 --- a/src/puter-js/src/modules/UI.js +++ b/src/puter-js/src/modules/UI.js @@ -1,6 +1,9 @@ import FSItem from './FSItem.js'; import PuterDialog from './PuterDialog.js'; import EventListener from '../lib/EventListener.js'; +import putility from '@heyputer/putility'; + +const FILE_SAVE_CANCELLED = Symbol('FILE_SAVE_CANCELLED'); // AppConnection provides an API for interacting with another app. // It's returned by UI methods, and cannot be constructed directly by user code. @@ -467,6 +470,10 @@ class UI extends EventListener { // execute callback this.#callbackFunctions[e.data.original_msg_id](new FSItem(e.data.saved_file)); } + else if(e.data.msg === "fileSaveCancelled"){ + // execute callback + this.#callbackFunctions[e.data.original_msg_id](FILE_SAVE_CANCELLED); + } else{ // execute callback this.#callbackFunctions[e.data.original_msg_id](e.data); @@ -726,7 +733,8 @@ class UI extends EventListener { } showSaveFilePicker = function(content, suggestedName, type){ - return new Promise((resolve, reject) => { + const undefinedOnCancel = new putility.libs.promise.TeePromise(); + const resolveOnlyPromise = new Promise((resolve, reject) => { if (!globalThis.open) { return reject("This API is not compatible in Web Workers."); } @@ -782,8 +790,20 @@ class UI extends EventListener { 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width='+w+', height='+h+', top='+top+', left='+left); } //register callback - this.#callbackFunctions[msg_id] = resolve; - }) + this.#callbackFunctions[msg_id] = (maybe_result) => { + // Only resolve cancel events if this was called with `.undefinedOnCancel` + if ( maybe_result === FILE_SAVE_CANCELLED ) { + undefinedOnCancel.resolve(undefined); + return; + } + undefinedOnCancel.resolve(maybe_result); + resolve(maybe_result); + }; + }); + + resolveOnlyPromise.undefinedOnCancel = undefinedOnCancel; + + return resolveOnlyPromise; } setWindowTitle = function(title, window_id, callback) {