From e1bf0d73b59bb6a5a8a4404e2a2c4528d4b72566 Mon Sep 17 00:00:00 2001 From: Isaiah Odhner Date: Thu, 11 Apr 2024 23:51:38 -0400 Subject: [PATCH] Prompt to save changes when clicking File > Exit I thought I tested this, but perhaps I accidentally tested clicking the close button instead, since instinctively/ideally, that's just an easier way of accessing the same function. It should also prompt before redirecting to 98.js.org. --- src/menus.js | 60 +++++++++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/src/menus.js b/src/menus.js index 1ea05b2a..3e88a7e5 100644 --- a/src/menus.js +++ b/src/menus.js @@ -4,7 +4,7 @@ // import { available_languages, get_iso_language_name, get_language, get_language_emoji, get_language_endonym, localize, set_language } from "./app-localization.js"; import { show_edit_colors_window } from "./edit-colors.js"; import { palette_formats } from "./file-format-data.js"; -import { change_url_param, choose_file_to_paste, clear, delete_selection, deselect, edit_copy, edit_cut, edit_paste, file_load_from_url, file_new, file_open, file_save, file_save_as, image_attributes, image_flip_and_rotate, image_invert_colors, image_stretch_and_skew, redo, render_history_as_gif, sanity_check_blob, save_selection_to_file, select_all, set_magnification, show_about_paint, show_custom_zoom_window, show_document_history, show_file_format_errors, show_multi_user_setup_dialog, show_news, toggle_grid, toggle_thumbnail, undo, view_bitmap } from "./functions.js"; +import { are_you_sure, change_url_param, choose_file_to_paste, clear, delete_selection, deselect, edit_copy, edit_cut, edit_paste, file_load_from_url, file_new, file_open, file_save, file_save_as, image_attributes, image_flip_and_rotate, image_invert_colors, image_stretch_and_skew, redo, render_history_as_gif, sanity_check_blob, save_selection_to_file, select_all, set_magnification, show_about_paint, show_custom_zoom_window, show_document_history, show_file_format_errors, show_multi_user_setup_dialog, show_news, toggle_grid, toggle_thumbnail, undo, view_bitmap } from "./functions.js"; import { show_help } from "./help.js"; import { $G, get_rgba_from_color } from "./helpers.js"; import { show_imgur_uploader } from "./imgur.js"; @@ -225,35 +225,37 @@ const menus = { "exit application", "exit paint", "close paint window", ], action: () => { - // Note: For a Chrome PWA, window.close() is allowed only if there is only one history entry. - // I could make it try to close the window and then navigate to the official web desktop if it fails, - // but that would be inconsistent, as it wouldn't close the window after using File > New or File > Open. - // I could make it so that it uses replaceState when opening a new document (starting a new session); - // that would prevent you from using Alt+Left to go back to the previous document, but that may be acceptable - // for a desktop app experience, where the back button is already hidden. - // That said, if you just installed the PWA, it will have history already (even if just the New Tab page), - // as the tab is converted to a window, and in that case, - // it would be unable to close, again being inconsistent, but less so. - // (If on PWA install, the app could open a fresh new window and close itself, it could work from the start, - // but if we try to do that, we'll be back at square one, trying to close a window with history.) - try { - // API contract is containing page can override window.close() - // Note that e.g. (()=>{}).bind().toString() gives "function () { [native code] }" - // so the window.close() must not use bind() (not that that's common practice anyway) - const close_overridden = frameElement && window.close && !/\{\s*\[native code\]\s*\}/.test(window.close.toString()); - if (close_overridden || window.is_electron_app) { - window.close(); - return; + are_you_sure(() => { + // Note: For a Chrome PWA, window.close() is allowed only if there is only one history entry. + // I could make it try to close the window and then navigate to the official web desktop if it fails, + // but that would be inconsistent, as it wouldn't close the window after using File > New or File > Open. + // I could make it so that it uses replaceState when opening a new document (starting a new session); + // that would prevent you from using Alt+Left to go back to the previous document, but that may be acceptable + // for a desktop app experience, where the back button is already hidden. + // That said, if you just installed the PWA, it will have history already (even if just the New Tab page), + // as the tab is converted to a window, and in that case, + // it would be unable to close, again being inconsistent, but less so. + // (If on PWA install, the app could open a fresh new window and close itself, it could work from the start, + // but if we try to do that, we'll be back at square one, trying to close a window with history.) + try { + // API contract is containing page can override window.close() + // Note that e.g. (()=>{}).bind().toString() gives "function () { [native code] }" + // so the window.close() must not use bind() (not that that's common practice anyway) + const close_overridden = frameElement && window.close && !/\{\s*\[native code\]\s*\}/.test(window.close.toString()); + if (close_overridden || window.is_electron_app) { + window.close(); + return; + } + } catch (e) { + // In a cross-origin iframe, most likely + // @TODO: establish postMessage API } - } catch (e) { - // In a cross-origin iframe, most likely - // @TODO: establish postMessage API - } - // In a cross-origin iframe, or same origin but without custom close(), or top level: - // Not all browsers support close() for closing a tab, - // so redirect instead. Exit to the official web desktop. - // @ts-ignore - window.location = "https://98.js.org/"; + // In a cross-origin iframe, or same origin but without custom close(), or top level: + // Not all browsers support close() for closing a tab, + // so redirect instead. Exit to the official web desktop. + // @ts-ignore + window.location = "https://98.js.org/"; + }); }, description: localize("Quits Paint."), }