mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-04 05:28:59 +01:00 
			
		
		
		
	clean up tree service WIP
This commit is contained in:
		
							parent
							
								
									d5ae3802d1
								
							
						
					
					
						commit
						b63ecba695
					
				@ -135,7 +135,7 @@ macInit.init();
 | 
			
		||||
 | 
			
		||||
searchNotesService.init(); // should be in front of treeService since that one manipulates address bar hash
 | 
			
		||||
 | 
			
		||||
appContext.showWidgets();
 | 
			
		||||
appContext.start();
 | 
			
		||||
 | 
			
		||||
noteTooltipService.setupGlobalTooltip();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
import treeService from '../services/tree.js';
 | 
			
		||||
import searchNotesService from '../services/search_notes.js';
 | 
			
		||||
import noteAutocompleteService from '../services/note_autocomplete.js';
 | 
			
		||||
import utils from "../services/utils.js";
 | 
			
		||||
import appContext from "../services/app_context.js";
 | 
			
		||||
 | 
			
		||||
const $dialog = $("#jump-to-note-dialog");
 | 
			
		||||
const $autoComplete = $("#jump-to-note-autocomplete");
 | 
			
		||||
@ -22,7 +22,7 @@ export async function showDialog() {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            treeService.activateNote(suggestion.path);
 | 
			
		||||
            appContext.getActiveTabContext().setNote(suggestion.path);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    noteAutocompleteService.showRecentNotes($autoComplete);
 | 
			
		||||
 | 
			
		||||
@ -3,6 +3,7 @@ import utils from '../services/utils.js';
 | 
			
		||||
import server from '../services/server.js';
 | 
			
		||||
import treeService from "../services/tree.js";
 | 
			
		||||
import treeCache from "../services/tree_cache.js";
 | 
			
		||||
import appContext from "../services/app_context.js";
 | 
			
		||||
 | 
			
		||||
const $dialog = $("#recent-changes-dialog");
 | 
			
		||||
const $content = $("#recent-changes-content");
 | 
			
		||||
@ -54,7 +55,7 @@ export async function showDialog() {
 | 
			
		||||
 | 
			
		||||
                                await treeCache.reloadNotes([change.noteId]);
 | 
			
		||||
 | 
			
		||||
                                treeService.activateNote(change.noteId);
 | 
			
		||||
                                appContext.getActiveTabContext().setNote(change.noteId);
 | 
			
		||||
                            }
 | 
			
		||||
                        });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -42,8 +42,13 @@ class AppContext {
 | 
			
		||||
        this.activeTabId = null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    showWidgets() {
 | 
			
		||||
    start() {
 | 
			
		||||
        this.showWidgets();
 | 
			
		||||
 | 
			
		||||
        bundleService.executeStartupBundles();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    showWidgets() {
 | 
			
		||||
        this.tabRow = new TabRowWidget(this);
 | 
			
		||||
 | 
			
		||||
        const topPaneWidgets = [
 | 
			
		||||
@ -247,18 +252,22 @@ class AppContext {
 | 
			
		||||
        await tabContext.setNote(noteId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async filterTabs(noteId) {
 | 
			
		||||
    hoistedNoteChangedListener({hoistedNoteId}) {
 | 
			
		||||
        if (hoistedNoteId === 'root') {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (const tc of this.tabContexts) {
 | 
			
		||||
            if (tc.notePath && !tc.notePath.split("/").includes(noteId)) {
 | 
			
		||||
            if (tc.notePath && !tc.notePath.split("/").includes(hoistedNoteId)) {
 | 
			
		||||
                this.tabRow.removeTab(tc.tabId);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.tabContexts.length === 0) {
 | 
			
		||||
            this.openAndActivateEmptyTab()
 | 
			
		||||
            this.openAndActivateEmptyTab();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        await this.saveOpenTabs();
 | 
			
		||||
        this.saveOpenTabs();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async saveOpenTabs() {
 | 
			
		||||
 | 
			
		||||
@ -38,7 +38,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
 | 
			
		||||
    this.tabContext = tabContext;
 | 
			
		||||
 | 
			
		||||
    /** @property {CollapsibleWidget} */
 | 
			
		||||
    this.StandardWidget = CollapsibleWidget;
 | 
			
		||||
    this.CollapsibleWidget = CollapsibleWidget;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Activates note in the tree and in the note detail.
 | 
			
		||||
@ -47,14 +47,8 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
 | 
			
		||||
     * @param {string} notePath (or noteId)
 | 
			
		||||
     * @returns {Promise<void>}
 | 
			
		||||
     */
 | 
			
		||||
    this.activateNote = async (notePath, noteLoadedListener) => {
 | 
			
		||||
        await treeService.activateNote(notePath, async () => {
 | 
			
		||||
            await appContext.getMainNoteTree().scrollToActiveNoteListener();
 | 
			
		||||
 | 
			
		||||
            if (noteLoadedListener) {
 | 
			
		||||
                noteLoadedListener();
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    this.activateNote = async notePath => {
 | 
			
		||||
        await appContext.getActiveTabContext().setNote(notePath);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -66,7 +60,8 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
 | 
			
		||||
    this.activateNewNote = async notePath => {
 | 
			
		||||
        await ws.waitForMaxKnownSyncId();
 | 
			
		||||
 | 
			
		||||
        await treeService.activateNote(notePath, () => appContext.trigger('focusAndSelectTitle'));
 | 
			
		||||
        await appContext.getActiveTabContext().setNote(notePath);
 | 
			
		||||
        appContext.trigger('focusAndSelectTitle');
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,7 @@
 | 
			
		||||
import optionsService from './options.js';
 | 
			
		||||
import server from "./server.js";
 | 
			
		||||
import appContext from "./app_context.js";
 | 
			
		||||
import treeService from "./tree.js";
 | 
			
		||||
 | 
			
		||||
let hoistedNoteId = 'root';
 | 
			
		||||
 | 
			
		||||
@ -19,15 +20,11 @@ async function getHoistedNoteId() {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function setHoistedNoteId(noteId) {
 | 
			
		||||
    if (noteId !== 'root') {
 | 
			
		||||
        await appContext.filterTabs(noteId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    hoistedNoteId = noteId;
 | 
			
		||||
 | 
			
		||||
    await server.put('options/hoistedNoteId/' + noteId);
 | 
			
		||||
 | 
			
		||||
    appContext.trigger('hoistedNoteChanged');
 | 
			
		||||
    appContext.trigger('hoistedNoteChanged', {hoistedNoteId});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function unhoist() {
 | 
			
		||||
@ -44,11 +41,38 @@ async function isRootNode(node) {
 | 
			
		||||
        || node.data.noteId === await getHoistedNoteId();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function checkNoteAccess(notePath) {
 | 
			
		||||
    // notePath argument can contain only noteId which is not good when hoisted since
 | 
			
		||||
    // then we need to check the whole note path
 | 
			
		||||
    const runNotePath = await treeService.getRunPath(notePath);
 | 
			
		||||
 | 
			
		||||
    if (!runNotePath) {
 | 
			
		||||
        console.log("Cannot activate " + notePath);
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const hoistedNoteId = await getHoistedNoteId();
 | 
			
		||||
 | 
			
		||||
    if (hoistedNoteId !== 'root' && !runNotePath.includes(hoistedNoteId)) {
 | 
			
		||||
        const confirmDialog = await import('../dialogs/confirm.js');
 | 
			
		||||
 | 
			
		||||
        if (!await confirmDialog.confirm("Requested note is outside of hoisted note subtree and you must unhoist to access the note. Do you want to proceed with unhoisting?")) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // unhoist so we can activate the note
 | 
			
		||||
        await unhoist();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
    getHoistedNoteId,
 | 
			
		||||
    getHoistedNoteNoPromise,
 | 
			
		||||
    setHoistedNoteId,
 | 
			
		||||
    unhoist,
 | 
			
		||||
    isTopLevelNode,
 | 
			
		||||
    isRootNode
 | 
			
		||||
    isRootNode,
 | 
			
		||||
    checkNoteAccess
 | 
			
		||||
}
 | 
			
		||||
@ -67,9 +67,7 @@ ws.subscribeToMessages(async message => {
 | 
			
		||||
        appContext.trigger('reloadNotes', {noteIds: [message.result.parentNoteId]});
 | 
			
		||||
 | 
			
		||||
        if (message.result.importedNoteId) {
 | 
			
		||||
            const node = await treeService.activateNote(message.result.importedNoteId);
 | 
			
		||||
 | 
			
		||||
            node.setExpanded(true);
 | 
			
		||||
            await appContext.getActiveTabContext.setNote(message.result.importedNoteId);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
@ -26,7 +26,7 @@ server.get('keyboard-shortcuts-for-notes').then(shortcutForNotes => {
 | 
			
		||||
		utils.bindGlobalShortcut(shortcut, async () => {
 | 
			
		||||
			const treeService = (await import("./tree.js")).default;
 | 
			
		||||
 | 
			
		||||
			treeService.activateNote(shortcutForNotes[shortcut]);
 | 
			
		||||
			appContext.getActiveTabContext().setNote(shortcutForNotes[shortcut]);
 | 
			
		||||
		});
 | 
			
		||||
	}
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
@ -79,8 +79,6 @@ async function protectNoteAndSendToServer() {
 | 
			
		||||
    note.isProtected = true;
 | 
			
		||||
 | 
			
		||||
    await appContext.getActiveTabContext().saveNote();
 | 
			
		||||
 | 
			
		||||
    treeService.setProtected(note.noteId, note.isProtected);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function unprotectNoteAndSendToServer() {
 | 
			
		||||
@ -104,8 +102,6 @@ async function unprotectNoteAndSendToServer() {
 | 
			
		||||
    activeNote.isProtected = false;
 | 
			
		||||
 | 
			
		||||
    await appContext.getActiveTabContext().saveNote();
 | 
			
		||||
 | 
			
		||||
    treeService.setProtected(activeNote.noteId, activeNote.isProtected);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function protectSubtree(noteId, protect) {
 | 
			
		||||
 | 
			
		||||
@ -7,6 +7,7 @@ import appContext from "./app_context.js";
 | 
			
		||||
import treeService from "./tree.js";
 | 
			
		||||
import Component from "../widgets/component.js";
 | 
			
		||||
import treeCache from "./tree_cache.js";
 | 
			
		||||
import hoistedNoteService from "./hoisted_note.js";
 | 
			
		||||
 | 
			
		||||
let showSidebarInNewTab = true;
 | 
			
		||||
 | 
			
		||||
@ -42,6 +43,10 @@ class TabContext extends Component {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (await hoistedNoteService.checkNoteAccess(notePath) === false) {
 | 
			
		||||
            return; // note is outside of hoisted subtree and user chose not to unhoist
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        await this.trigger('beforeNoteSwitch', {tabId: this.tabId}, true);
 | 
			
		||||
 | 
			
		||||
        this.notePath = notePath;
 | 
			
		||||
@ -73,6 +78,7 @@ class TabContext extends Component {
 | 
			
		||||
            tabId: this.tabId,
 | 
			
		||||
            notePath: this.notePath
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.trigger('openTabsChanged');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -10,73 +10,6 @@ import optionsService from "../services/options.js";
 | 
			
		||||
import bundle from "./bundle.js";
 | 
			
		||||
import appContext from "./app_context.js";
 | 
			
		||||
 | 
			
		||||
let setFrontendAsLoaded;
 | 
			
		||||
const frontendLoaded = new Promise(resolve => { setFrontendAsLoaded = resolve; });
 | 
			
		||||
 | 
			
		||||
async function setPrefix(branchId, prefix) {
 | 
			
		||||
    utils.assertArguments(branchId);
 | 
			
		||||
 | 
			
		||||
    const branch = treeCache.getBranch(branchId);
 | 
			
		||||
 | 
			
		||||
    branch.prefix = prefix;
 | 
			
		||||
 | 
			
		||||
    for (const node of await appContext.getMainNoteTree().getNodesByBranchId(branchId)) {
 | 
			
		||||
        await setNodeTitleWithPrefix(node);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function setNodeTitleWithPrefix(node) {
 | 
			
		||||
    const noteTitle = await getNoteTitle(node.data.noteId);
 | 
			
		||||
    const branch = treeCache.getBranch(node.data.branchId);
 | 
			
		||||
 | 
			
		||||
    const prefix = branch.prefix;
 | 
			
		||||
 | 
			
		||||
    const title = (prefix ? (prefix + " - ") : "") + noteTitle;
 | 
			
		||||
 | 
			
		||||
    node.setTitle(utils.escapeHtml(title));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FIXME: unused?
 | 
			
		||||
/** @return {FancytreeNode} */
 | 
			
		||||
async function activateNote(notePath, noteLoadedListener) {
 | 
			
		||||
    utils.assertArguments(notePath);
 | 
			
		||||
 | 
			
		||||
    // notePath argument can contain only noteId which is not good when hoisted since
 | 
			
		||||
    // then we need to check the whole note path
 | 
			
		||||
    const runNotePath = await getRunPath(notePath);
 | 
			
		||||
 | 
			
		||||
    if (!runNotePath) {
 | 
			
		||||
        console.log("Cannot activate " + notePath);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const hoistedNoteId = await hoistedNoteService.getHoistedNoteId();
 | 
			
		||||
 | 
			
		||||
    if (hoistedNoteId !== 'root' && !runNotePath.includes(hoistedNoteId)) {
 | 
			
		||||
        const confirmDialog = await import('../dialogs/confirm.js');
 | 
			
		||||
 | 
			
		||||
        if (!await confirmDialog.confirm("Requested note is outside of hoisted note subtree. Do you want to unhoist?")) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // unhoist so we can activate the note
 | 
			
		||||
        await hoistedNoteService.unhoist();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    utils.closeActiveDialog();
 | 
			
		||||
 | 
			
		||||
    const node = await appContext.getMainNoteTree().expandToNote(notePath);
 | 
			
		||||
 | 
			
		||||
    if (noteLoadedListener) {
 | 
			
		||||
        // FIXME
 | 
			
		||||
        noteDetailService.addDetailLoadedListener(node.data.noteId, noteLoadedListener);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    await node.setActive(true);
 | 
			
		||||
 | 
			
		||||
    return node;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Accepts notePath which might or might not be valid and returns an existing path as close to the original
 | 
			
		||||
 * notePath as possible.
 | 
			
		||||
@ -274,8 +207,6 @@ async function treeInitialized() {
 | 
			
		||||
    // previous opening triggered task to save tab changes but these are bogus changes (this is init)
 | 
			
		||||
    // so we'll cancel it
 | 
			
		||||
    appContext.clearOpenTabsTask();
 | 
			
		||||
 | 
			
		||||
    setFrontendAsLoaded();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function isNotePathInAddress() {
 | 
			
		||||
@ -292,13 +223,6 @@ function getHashValueFromAddress() {
 | 
			
		||||
    return str.split("-");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function setProtected(noteId, isProtected) {
 | 
			
		||||
    appContext.getMainNoteTree().getNodesByNoteId(noteId).map(node => {
 | 
			
		||||
        node.data.isProtected = isProtected;
 | 
			
		||||
        node.toggleClass("protected", isProtected);
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
async function createNewTopLevelNote() {
 | 
			
		||||
    const hoistedNoteId = await hoistedNoteService.getHoistedNoteId();
 | 
			
		||||
 | 
			
		||||
@ -580,12 +504,7 @@ async function getNotePathTitle(notePath) {
 | 
			
		||||
    return titlePath.join(' / ');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
frontendLoaded.then(bundle.executeStartupBundles);
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
    setProtected,
 | 
			
		||||
    activateNote,
 | 
			
		||||
    setPrefix,
 | 
			
		||||
    createNote,
 | 
			
		||||
    sortAlphabetically,
 | 
			
		||||
    treeInitialized,
 | 
			
		||||
@ -594,7 +513,6 @@ export default {
 | 
			
		||||
    createNewTopLevelNote,
 | 
			
		||||
    duplicateNote,
 | 
			
		||||
    getRunPath,
 | 
			
		||||
    setNodeTitleWithPrefix,
 | 
			
		||||
    getParentProtectedStatus,
 | 
			
		||||
    getNotePath,
 | 
			
		||||
    getNoteIdFromNotePath,
 | 
			
		||||
 | 
			
		||||
@ -4,6 +4,7 @@ import utils from "../services/utils.js";
 | 
			
		||||
import dateNoteService from "../services/date_notes.js";
 | 
			
		||||
import treeService from "../services/tree.js";
 | 
			
		||||
import server from "../services/server.js";
 | 
			
		||||
import appContext from "../services/app_context.js";
 | 
			
		||||
 | 
			
		||||
const TPL = `
 | 
			
		||||
<div class="calendar-widget">
 | 
			
		||||
@ -58,7 +59,7 @@ export default class CalendarWidget extends CollapsibleWidget {
 | 
			
		||||
            const note = await dateNoteService.getDateNote(date);
 | 
			
		||||
 | 
			
		||||
            if (note) {
 | 
			
		||||
                treeService.activateNote(note.noteId);
 | 
			
		||||
                appContext.getActiveTabContext().setNote(note.noteId);
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                alert("Cannot find day note");
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,7 @@
 | 
			
		||||
import noteAutocompleteService from '../../services/note_autocomplete.js';
 | 
			
		||||
import treeService from "../../services/tree.js";
 | 
			
		||||
import TypeWidget from "./type_widget.js";
 | 
			
		||||
import appContext from "../../services/app_context.js";
 | 
			
		||||
 | 
			
		||||
const TPL = `
 | 
			
		||||
<div class="note-detail-empty note-detail-printable">
 | 
			
		||||
@ -27,7 +28,7 @@ export default class EmptyTypeWidget extends TypeWidget {
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                treeService.activateNote(suggestion.path);
 | 
			
		||||
                appContext.getActiveTabContext().setNote(suggestion.path);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
        noteAutocompleteService.showRecentNotes(this.$autoComplete);
 | 
			
		||||
 | 
			
		||||
@ -4,6 +4,7 @@ import noteAutocompleteService from '../../services/note_autocomplete.js';
 | 
			
		||||
import mimeTypesService from '../../services/mime_types.js';
 | 
			
		||||
import TypeWidget from "./type_widget.js";
 | 
			
		||||
import utils from "../../services/utils.js";
 | 
			
		||||
import appContext from "../../services/app_context.js";
 | 
			
		||||
 | 
			
		||||
const ENABLE_INSPECTOR = false;
 | 
			
		||||
 | 
			
		||||
@ -90,7 +91,7 @@ export default class TextTypeWidget extends TypeWidget {
 | 
			
		||||
            if (match) {
 | 
			
		||||
                const noteId = match[1];
 | 
			
		||||
 | 
			
		||||
                treeService.activateNote(noteId);
 | 
			
		||||
                appContext.getActiveTabContext().setNote(noteId);
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                window.open(src, '_blank');
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user