prompt user when there are unsaved changes, #1692

This commit is contained in:
zadam 2021-02-27 23:39:02 +01:00
parent 02016ed031
commit 78e48095e6
5 changed files with 64 additions and 8 deletions

View File

@ -12,6 +12,7 @@ import keyboardActionsService from "./keyboard_actions.js";
import MobileScreenSwitcherExecutor from "../widgets/mobile_widgets/mobile_screen_switcher.js";
import MainTreeExecutors from "./main_tree_executors.js";
import protectedSessionHolder from "./protected_session_holder.js";
import toast from "./toast.js";
class AppContext extends Component {
constructor(isMainWindow) {
@ -19,6 +20,7 @@ class AppContext extends Component {
this.isMainWindow = isMainWindow;
this.executors = [];
this.beforeUnloadListeners = [];
}
setLayout(layout) {
@ -104,6 +106,15 @@ class AppContext extends Component {
getComponentByEl(el) {
return $(el).closest(".component").prop('component');
}
addBeforeUnloadListener(obj) {
if (typeof WeakRef !== "function") {
// older browsers don't support WeakRef
return;
}
this.beforeUnloadListeners.push(new WeakRef(obj));
}
}
const appContext = new AppContext(window.glob.isMainWindow);
@ -112,7 +123,29 @@ const appContext = new AppContext(window.glob.isMainWindow);
$(window).on('beforeunload', () => {
protectedSessionHolder.resetSessionCookie();
appContext.triggerEvent('beforeUnload');
let allSaved = true;
appContext.beforeUnloadListeners = appContext.beforeUnloadListeners.filter(wr => !!wr.deref());
for (const weakRef of appContext.beforeUnloadListeners) {
const component = weakRef.deref();
if (!component) {
continue;
}
if (!component.beforeUnloadEvent()) {
console.log(`Component ${component.componentId} is not finished saving its state.`);
toast.showMessage("Please wait for a couple of seconds for the save to finish, then you can try again.", 10000);
allSaved = false;
}
}
if (!allSaved) {
return "some string";
}
});
function isNotePathInAddress() {

View File

@ -15,11 +15,27 @@ export default class SpacedUpdate {
async updateNowIfNecessary() {
if (this.changed) {
this.changed = false;
await this.updater();
this.changed = false; // optimistic...k
try {
await this.updater();
}
catch (e) {
this.changed = true;
throw e;
}
}
}
isAllSavedAndTriggerUpdate() {
const allSaved = !this.changed;
this.updateNowIfNecessary();
return allSaved;
}
triggerUpdate() {
if (!this.changed) {
return;

View File

@ -27,6 +27,8 @@ export default class TabManager extends Component {
openTabs: JSON.stringify(openTabs)
});
});
appContext.addBeforeUnloadListener(this);
}
/** @type {TabContext[]} */
@ -329,6 +331,8 @@ export default class TabManager extends Component {
beforeUnloadEvent() {
this.tabsUpdate.updateNowIfNecessary();
return true; // don't block closing the tab, this metadata is not that important
}
openNewTabCommand() {

View File

@ -54,8 +54,6 @@ export default class NoteDetailWidget extends TabAwareWidget {
this.typeWidgets = {};
const updateInterval = utils.isDesktop() ? 1000 : 5000;
this.spacedUpdate = new SpacedUpdate(async () => {
const {note} = this.tabContext;
const {noteId} = note;
@ -66,7 +64,9 @@ export default class NoteDetailWidget extends TabAwareWidget {
protectedSessionHolder.touchProtectedSessionIfNecessary(note);
await server.put('notes/' + noteId, dto, this.componentId);
}, updateInterval);
});
appContext.addBeforeUnloadListener(this);
}
isEnabled() {
@ -295,7 +295,7 @@ export default class NoteDetailWidget extends TabAwareWidget {
}
beforeUnloadEvent() {
this.spacedUpdate.updateNowIfNecessary();
return this.spacedUpdate.isAllSavedAndTriggerUpdate();
}
textPreviewDisabledEvent({tabContext}) {

View File

@ -3,6 +3,7 @@ import utils from "../services/utils.js";
import protectedSessionHolder from "../services/protected_session_holder.js";
import server from "../services/server.js";
import SpacedUpdate from "../services/spaced_update.js";
import appContext from "../services/app_context.js";
const TPL = `
<div class="note-title-container">
@ -37,6 +38,8 @@ export default class NoteTitleWidget extends TabAwareWidget {
await server.put(`notes/${this.noteId}/change-title`, {title});
});
appContext.addBeforeUnloadListener(this);
}
doRender() {
@ -101,6 +104,6 @@ export default class NoteTitleWidget extends TabAwareWidget {
}
beforeUnloadEvent() {
this.spacedUpdate.updateNowIfNecessary();
return this.spacedUpdate.isAllSavedAndTriggerUpdate();
}
}