mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-03 20:06:08 +01:00 
			
		
		
		
	saving note detail
This commit is contained in:
		@@ -27,8 +27,6 @@ async function openInTab(notePath, activate) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function switchToNote(notePath) {
 | 
			
		||||
    await saveNotesIfChanged();
 | 
			
		||||
 | 
			
		||||
    await loadNoteDetail(notePath);
 | 
			
		||||
 | 
			
		||||
    appContext.openTabsChanged();
 | 
			
		||||
@@ -38,15 +36,6 @@ function onNoteChange(func) {
 | 
			
		||||
    return appContext.getActiveTabContext().getComponent().onNoteChange(func);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function saveNotesIfChanged() {
 | 
			
		||||
    for (const ctx of appContext.getTabContexts()) {
 | 
			
		||||
        await ctx.saveNoteIfChanged();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // make sure indicator is visible in a case there was some race condition.
 | 
			
		||||
    $savedIndicator.fadeIn();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getActiveEditor() {
 | 
			
		||||
    const activeTabContext = appContext.getActiveTabContext();
 | 
			
		||||
 | 
			
		||||
@@ -210,10 +199,9 @@ function noteChanged() {
 | 
			
		||||
 | 
			
		||||
// this makes sure that when user e.g. reloads the page or navigates away from the page, the note's content is saved
 | 
			
		||||
// this sends the request asynchronously and doesn't wait for result
 | 
			
		||||
// FIXME
 | 
			
		||||
$(window).on('beforeunload', () => { saveNotesIfChanged(); }); // don't convert to short form, handler doesn't like returned promise
 | 
			
		||||
 | 
			
		||||
setInterval(saveNotesIfChanged, 3000);
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
    reload,
 | 
			
		||||
    openInTab,
 | 
			
		||||
@@ -222,7 +210,6 @@ export default {
 | 
			
		||||
    loadNoteDetail,
 | 
			
		||||
    focusOnTitle,
 | 
			
		||||
    focusAndSelectTitle,
 | 
			
		||||
    saveNotesIfChanged,
 | 
			
		||||
    onNoteChange,
 | 
			
		||||
    addDetailLoadedListener,
 | 
			
		||||
    getActiveEditor,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										36
									
								
								src/public/javascripts/services/spaced_update.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/public/javascripts/services/spaced_update.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,36 @@
 | 
			
		||||
export default class SpacedUpdate {
 | 
			
		||||
    constructor(updater, updateInterval = 1000) {
 | 
			
		||||
        this.updater = updater;
 | 
			
		||||
        this.lastUpdated = Date.now();
 | 
			
		||||
        this.changed = false;
 | 
			
		||||
        this.updateInterval = updateInterval;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    scheduleUpdate() {
 | 
			
		||||
        this.changed = true;
 | 
			
		||||
        setTimeout(() => this.triggerUpdate())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async updateNowIfNecessary() {
 | 
			
		||||
        if (this.changed) {
 | 
			
		||||
            this.changed = false;
 | 
			
		||||
            await this.updater();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    triggerUpdate() {
 | 
			
		||||
        if (!this.changed) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (Date.now() - this.lastUpdated > this.updateInterval) {
 | 
			
		||||
            this.updater();
 | 
			
		||||
            this.lastUpdated = Date.now();
 | 
			
		||||
            this.changed = false;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            // update not triggered but changes are still pending so we need to schedule another check
 | 
			
		||||
            this.scheduleUpdate();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -26,7 +26,6 @@ class TabContext extends Component {
 | 
			
		||||
 | 
			
		||||
        this.tabRow = tabRow;
 | 
			
		||||
        this.tabId = state.tabId || utils.randomString(4);
 | 
			
		||||
        this.$tab = $(this.tabRow.addTab(this.tabId));
 | 
			
		||||
        this.state = state;
 | 
			
		||||
 | 
			
		||||
        this.attributes = new Attributes(this.appContext, this);
 | 
			
		||||
 
 | 
			
		||||
@@ -374,6 +374,7 @@ async function createNote(node, parentNoteId, target, extraOptions = {}) {
 | 
			
		||||
        window.cutToNote.removeSelection();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // FIXME
 | 
			
		||||
    await noteDetailService.saveNotesIfChanged();
 | 
			
		||||
 | 
			
		||||
    noteDetailService.addDetailLoadedListener(note.noteId, noteDetailService.focusAndSelectTitle);
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,8 @@ import TabAwareWidget from "./tab_aware_widget.js";
 | 
			
		||||
import utils from "../services/utils.js";
 | 
			
		||||
import protectedSessionHolder from "../services/protected_session_holder.js";
 | 
			
		||||
import appContext from "../services/app_context.js";
 | 
			
		||||
import SpacedUpdate from "../services/spaced_update.js";
 | 
			
		||||
import server from "../services/server.js";
 | 
			
		||||
 | 
			
		||||
const TPL = `
 | 
			
		||||
<div class="note-detail">
 | 
			
		||||
@@ -32,6 +34,19 @@ export default class NoteDetailWidget extends TabAwareWidget {
 | 
			
		||||
 | 
			
		||||
        this.typeWidgets = {};
 | 
			
		||||
        this.typeWidgetPromises = {};
 | 
			
		||||
 | 
			
		||||
        this.spacedUpdate = new SpacedUpdate(async () => {
 | 
			
		||||
            const note = this.tabContext.note;
 | 
			
		||||
            note.content = this.getTypeWidget().getContent();
 | 
			
		||||
 | 
			
		||||
            const resp = await server.put('notes/' + note.noteId, note.dto);
 | 
			
		||||
 | 
			
		||||
            // FIXME: minor - does not propagate to other tab contexts with this note though
 | 
			
		||||
            note.dateModified = resp.dateModified;
 | 
			
		||||
            note.utcDateModified = resp.utcDateModified;
 | 
			
		||||
 | 
			
		||||
            this.trigger('noteChangesSaved', {noteId: note.noteId})
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    doRender() {
 | 
			
		||||
@@ -114,12 +129,14 @@ export default class NoteDetailWidget extends TabAwareWidget {
 | 
			
		||||
    async initWidgetType(type) {
 | 
			
		||||
        const clazz = await import(typeWidgetClasses[type]);
 | 
			
		||||
 | 
			
		||||
        this.typeWidgets[this.type] = new clazz.default(this.appContext);
 | 
			
		||||
        this.children.push(this.typeWidgets[this.type]);
 | 
			
		||||
        const typeWidget = this.typeWidgets[this.type] = new clazz.default(this.appContext);
 | 
			
		||||
        this.children.push(typeWidget);
 | 
			
		||||
 | 
			
		||||
        this.$widget.append(this.typeWidgets[this.type].render());
 | 
			
		||||
        this.$widget.append(typeWidget.render());
 | 
			
		||||
 | 
			
		||||
        this.typeWidgets[this.type].eventReceived('setTabContext', {tabContext: this.tabContext});
 | 
			
		||||
        typeWidget.onNoteChange(() => this.spacedUpdate.scheduleUpdate());
 | 
			
		||||
 | 
			
		||||
        typeWidget.eventReceived('setTabContext', {tabContext: this.tabContext});
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getWidgetType(disableAutoBook) {
 | 
			
		||||
@@ -153,4 +170,16 @@ export default class NoteDetailWidget extends TabAwareWidget {
 | 
			
		||||
            widget.focus();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async beforeNoteSwitchListener({tabId}) {
 | 
			
		||||
        if (this.isTab(tabId)) {
 | 
			
		||||
            await this.spacedUpdate.updateNowIfNecessary();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async beforeTabRemoveListener({tabId}) {
 | 
			
		||||
        if (this.isTab(tabId)) {
 | 
			
		||||
            await this.spacedUpdate.updateNowIfNecessary();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -3,6 +3,7 @@ import utils from "../services/utils.js";
 | 
			
		||||
import protectedSessionHolder from "../services/protected_session_holder.js";
 | 
			
		||||
import treeCache from "../services/tree_cache.js";
 | 
			
		||||
import server from "../services/server.js";
 | 
			
		||||
import SpacedUpdate from "../services/spaced_update.js";
 | 
			
		||||
 | 
			
		||||
const TPL = `
 | 
			
		||||
<div class="note-title-container">
 | 
			
		||||
@@ -24,43 +25,6 @@ const TPL = `
 | 
			
		||||
    <input autocomplete="off" value="" class="note-title" tabindex="1">
 | 
			
		||||
</div>`;
 | 
			
		||||
 | 
			
		||||
class SpacedUpdate {
 | 
			
		||||
    constructor(updater, updateInterval = 1000) {
 | 
			
		||||
        this.updater = updater;
 | 
			
		||||
        this.lastUpdated = Date.now();
 | 
			
		||||
        this.changed = false;
 | 
			
		||||
        this.updateInterval = updateInterval;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    scheduleUpdate() {
 | 
			
		||||
        this.changed = true;
 | 
			
		||||
        setTimeout(() => this.triggerUpdate())
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async updateNowIfNecessary() {
 | 
			
		||||
        if (this.changed) {
 | 
			
		||||
            this.changed = false;
 | 
			
		||||
            await this.updater();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    triggerUpdate() {
 | 
			
		||||
        if (!this.changed) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (Date.now() - this.lastUpdated > this.updateInterval) {
 | 
			
		||||
            this.updater();
 | 
			
		||||
            this.lastUpdated = Date.now();
 | 
			
		||||
            this.changed = false;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            // update not triggered but changes are still pending so we need to schedule another check
 | 
			
		||||
            this.scheduleUpdate();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default class NoteTitleWidget extends TabAwareWidget {
 | 
			
		||||
    constructor(appContext) {
 | 
			
		||||
        super(appContext);
 | 
			
		||||
 
 | 
			
		||||
@@ -109,6 +109,7 @@ class CodeTypeWidget extends TypeWidget {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // make sure note is saved so we load latest changes
 | 
			
		||||
        // FIXME
 | 
			
		||||
        await noteDetailService.saveNotesIfChanged();
 | 
			
		||||
 | 
			
		||||
        if (this.tabContext.note.mime.endsWith("env=frontend")) {
 | 
			
		||||
@@ -122,7 +123,9 @@ class CodeTypeWidget extends TypeWidget {
 | 
			
		||||
        toastService.showMessage("Note executed");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    onNoteChange(func) {
 | 
			
		||||
    async onNoteChange(func) {
 | 
			
		||||
        await this.initialized;
 | 
			
		||||
 | 
			
		||||
        this.codeEditor.on('change', func);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,7 @@ class NoteDetailSearch {
 | 
			
		||||
        this.$refreshButton = ctx.$tabContent.find('.note-detail-search-refresh-results-button');
 | 
			
		||||
 | 
			
		||||
        this.$refreshButton.on('click', async () => {
 | 
			
		||||
            // FIXME
 | 
			
		||||
            await noteDetailService.saveNotesIfChanged();
 | 
			
		||||
 | 
			
		||||
            await searchNotesService.refreshSearch();
 | 
			
		||||
 
 | 
			
		||||
@@ -174,7 +174,9 @@ class TextTypeWidget extends TypeWidget {
 | 
			
		||||
        return this.textEditor;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    onNoteChange(func) {
 | 
			
		||||
    async onNoteChange(func) {
 | 
			
		||||
        await this.initialized;
 | 
			
		||||
 | 
			
		||||
        this.textEditor.model.document.on('change:data', func);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user