mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-03 20:06:08 +01:00 
			
		
		
		
	protection against text note initialization race conditions
This commit is contained in:
		@@ -201,17 +201,13 @@ async function loadNoteDetail(origNotePath, options = {}) {
 | 
			
		||||
    const newTab = !!options.newTab;
 | 
			
		||||
    const activate = !!options.activate;
 | 
			
		||||
 | 
			
		||||
    const notePath = await treeService.resolveNotePath(origNotePath);
 | 
			
		||||
    let notePath = await treeService.resolveNotePath(origNotePath);
 | 
			
		||||
 | 
			
		||||
    if (!notePath) {
 | 
			
		||||
        console.error(`Cannot resolve note path ${origNotePath}`);
 | 
			
		||||
 | 
			
		||||
        // fallback to display something
 | 
			
		||||
        if (tabContexts.length === 0) {
 | 
			
		||||
            await openEmptyTab();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return;
 | 
			
		||||
        notePath = 'root';
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const noteId = treeUtils.getNoteIdFromNotePath(notePath);
 | 
			
		||||
 
 | 
			
		||||
@@ -47,6 +47,7 @@ class NoteDetailText {
 | 
			
		||||
        this.ctx = ctx;
 | 
			
		||||
        this.$component = ctx.$tabContent.find('.note-detail-text');
 | 
			
		||||
        this.$editorEl = this.$component.find('.note-detail-text-editor');
 | 
			
		||||
        this.textEditorPromise = null;
 | 
			
		||||
        this.textEditor = null;
 | 
			
		||||
 | 
			
		||||
        this.$component.on("dblclick", "img", e => {
 | 
			
		||||
@@ -67,44 +68,12 @@ class NoteDetailText {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async render() {
 | 
			
		||||
        if (!this.textEditor) {
 | 
			
		||||
            await libraryLoader.requireLibrary(libraryLoader.CKEDITOR);
 | 
			
		||||
 | 
			
		||||
            const codeBlockLanguages =
 | 
			
		||||
                (await mimeTypesService.getMimeTypes())
 | 
			
		||||
                    .filter(mt => mt.enabled)
 | 
			
		||||
                    .map(mt => {
 | 
			
		||||
                        return {
 | 
			
		||||
                            language: mt.mime.toLowerCase().replace(/[\W_]+/g,"-"),
 | 
			
		||||
                            label: mt.title
 | 
			
		||||
                        }
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
            // CKEditor since version 12 needs the element to be visible before initialization. At the same time
 | 
			
		||||
            // we want to avoid flicker - i.e. show editor only once everything is ready. That's why we have separate
 | 
			
		||||
            // display of $component in both branches.
 | 
			
		||||
            this.$component.show();
 | 
			
		||||
 | 
			
		||||
            // textEditor might have been initialized during previous await so checking again
 | 
			
		||||
            // looks like double initialization can freeze CKEditor pretty badly
 | 
			
		||||
            if (!this.textEditor) {
 | 
			
		||||
                this.textEditor = await BalloonEditor.create(this.$editorEl[0], {
 | 
			
		||||
                    placeholder: "Type the content of your note here ...",
 | 
			
		||||
                    mention: mentionSetup,
 | 
			
		||||
                    codeBlock: {
 | 
			
		||||
                        languages: codeBlockLanguages
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                if (glob.isDev && ENABLE_INSPECTOR) {
 | 
			
		||||
                    await import('../../libraries/ckeditor/inspector.js');
 | 
			
		||||
                    CKEditorInspector.attach(this.textEditor);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                this.onNoteChange(() => this.ctx.noteChanged());
 | 
			
		||||
            }
 | 
			
		||||
        if (!this.textEditorPromise) {
 | 
			
		||||
            this.textEditorPromise = this.initEditor();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        await this.textEditorPromise;
 | 
			
		||||
 | 
			
		||||
        // lazy loading above can take time and tab might have been already switched to another note
 | 
			
		||||
        if (this.ctx.note && this.ctx.note.type === 'text') {
 | 
			
		||||
            this.textEditor.isReadOnly = await this.isReadOnly();
 | 
			
		||||
@@ -115,6 +84,42 @@ class NoteDetailText {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async initEditor() {
 | 
			
		||||
        await libraryLoader.requireLibrary(libraryLoader.CKEDITOR);
 | 
			
		||||
 | 
			
		||||
        const codeBlockLanguages =
 | 
			
		||||
            (await mimeTypesService.getMimeTypes())
 | 
			
		||||
                .filter(mt => mt.enabled)
 | 
			
		||||
                .map(mt => {
 | 
			
		||||
                    return {
 | 
			
		||||
                        language: mt.mime.toLowerCase().replace(/[\W_]+/g,"-"),
 | 
			
		||||
                        label: mt.title
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
        // CKEditor since version 12 needs the element to be visible before initialization. At the same time
 | 
			
		||||
        // we want to avoid flicker - i.e. show editor only once everything is ready. That's why we have separate
 | 
			
		||||
        // display of $component in both branches.
 | 
			
		||||
        this.$component.show();
 | 
			
		||||
 | 
			
		||||
        const textEditorInstance = await BalloonEditor.create(this.$editorEl[0], {
 | 
			
		||||
            placeholder: "Type the content of your note here ...",
 | 
			
		||||
            mention: mentionSetup,
 | 
			
		||||
            codeBlock: {
 | 
			
		||||
                languages: codeBlockLanguages
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        if (glob.isDev && ENABLE_INSPECTOR) {
 | 
			
		||||
            await import('../../libraries/ckeditor/inspector.js');
 | 
			
		||||
            CKEditorInspector.attach(textEditorInstance);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.textEditor = textEditorInstance;
 | 
			
		||||
 | 
			
		||||
        this.onNoteChange(() => this.ctx.noteChanged());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getContent() {
 | 
			
		||||
        const content = this.textEditor.getData();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user