mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-04 05:28:59 +01:00 
			
		
		
		
	prompt user when there are unsaved changes, #1692
This commit is contained in:
		
							parent
							
								
									02016ed031
								
							
						
					
					
						commit
						78e48095e6
					
				@ -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() {
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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() {
 | 
			
		||||
 | 
			
		||||
@ -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}) {
 | 
			
		||||
 | 
			
		||||
@ -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();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user