moved tab management to app context

This commit is contained in:
zadam 2020-01-12 12:30:30 +01:00
parent 61474defff
commit 5e11840137
19 changed files with 235 additions and 231 deletions

View File

@ -61,7 +61,7 @@ window.glob.noteChanged = noteDetailService.noteChanged;
window.glob.refreshTree = treeService.reload;
// required for ESLint plugin
window.glob.getActiveTabNote = noteDetailService.getActiveTabNote;
window.glob.getActiveTabNote = appContext.getActiveTabNote;
window.glob.requireLibrary = libraryLoader.requireLibrary;
window.glob.ESLINT = libraryLoader.ESLINT;
@ -145,7 +145,7 @@ async function printActiveNote() {
return;
}
const $tabContext = noteDetailService.getActiveTabContext();
const $tabContext = appContext.getActiveTabContext();
if (!$tabContext) {
return;
}

View File

@ -93,7 +93,7 @@ function AttributesModel() {
}
this.loadAttributes = async function() {
const noteId = noteDetailService.getActiveTabNoteId();
const noteId = appContext.getActiveTabNoteId();
const attributes = await server.get('notes/' + noteId + '/attributes');
@ -139,7 +139,7 @@ function AttributesModel() {
self.updateAttributePositions();
const noteId = noteDetailService.getActiveTabNoteId();
const noteId = appContext.getActiveTabNoteId();
const attributesToSave = self.ownedAttributes()
.map(attribute => attribute())
@ -171,7 +171,7 @@ function AttributesModel() {
toastService.showMessage("Attributes have been saved.");
const ctx = noteDetailService.getActiveTabContext();
const ctx = appContext.getActiveTabContext();
ctx.attributes.refreshAttributes();

View File

@ -31,7 +31,7 @@ export async function showDialog() {
}
$dialog.on('shown.bs.modal', () => {
const note = noteDetailService.getActiveTabNote();
const note = appContext.getActiveTabNote();
linkMapService = new LinkMapService(note, $linkMapContainer, getOptions());
linkMapService.render();

View File

@ -26,7 +26,7 @@ async function convertMarkdownToHtml(text) {
}
export async function importMarkdownInline() {
if (noteDetailService.getActiveTabNoteType() !== 'text') {
if (appContext.getActiveTabNoteType() !== 'text') {
return;
}

View File

@ -16,7 +16,7 @@ export function showDialog() {
$dialog.modal();
const activeNote = noteDetailService.getActiveTabNote();
const activeNote = appContext.getActiveTabNote();
$noteId.text(activeNote.noteId);
$dateCreated.text(activeNote.dateCreated);

View File

@ -25,7 +25,7 @@ let note;
let noteRevisionId;
export async function showCurrentNoteRevisions() {
await showNoteRevisionsDialog(noteDetailService.getActiveTabNoteId());
await showNoteRevisionsDialog(appContext.getActiveTabNoteId());
}
export async function showNoteRevisionsDialog(noteId, noteRevisionId) {
@ -42,7 +42,7 @@ async function loadNoteRevisions(noteId, noteRevId) {
$list.empty();
$content.empty();
note = noteDetailService.getActiveTabNote();
note = appContext.getActiveTabNote();
revisionItems = await server.get(`notes/${noteId}/revisions`);
for (const item of revisionItems) {

View File

@ -11,7 +11,7 @@ export function showDialog() {
$dialog.modal();
const noteText = noteDetailService.getActiveTabNote().content;
const noteText = appContext.getActiveTabNote().content;
$noteSource.text(formatHtml(noteText));
}

View File

@ -2,10 +2,16 @@ import GlobalButtonsWidget from "../widgets/global_buttons.js";
import SearchBoxWidget from "../widgets/search_box.js";
import SearchResultsWidget from "../widgets/search_results.js";
import NoteTreeWidget from "../widgets/note_tree.js";
import tabRow from "./tab_row.js";
import treeService from "./tree.js";
import noteDetailService from "./note_detail.js";
import TabContext from "./tab_context.js";
class AppContext {
constructor() {
this.widgets = [];
/** @type {TabContext[]} */
this.tabContexts = [];
}
trigger(name, data) {
@ -14,6 +20,97 @@ class AppContext {
}
}
/** @return {TabContext[]} */
getTabContexts() {
return this.tabContexts;
}
/** @returns {TabContext} */
getActiveTabContext() {
const activeTabEl = tabRow.activeTabEl;
if (!activeTabEl) {
return null;
}
const tabId = activeTabEl.getAttribute('data-tab-id');
return this.tabContexts.find(tc => tc.tabId === tabId);
}
/** @returns {string|null} */
getActiveTabNotePath() {
const activeContext = this.getActiveTabContext();
return activeContext ? activeContext.notePath : null;
}
/** @return {NoteFull} */
getActiveTabNote() {
const activeContext = this.getActiveTabContext();
return activeContext ? activeContext.note : null;
}
/** @return {string|null} */
getActiveTabNoteId() {
const activeNote = this.getActiveTabNote();
return activeNote ? activeNote.noteId : null;
}
/** @return {string|null} */
getActiveTabNoteType() {
const activeNote = this.getActiveTabNote();
return activeNote ? activeNote.type : null;
}
async switchToTab(tabId, notePath) {
const tabContext = this.tabContexts.find(tc => tc.tabId === tabId);
if (!tabContext) {
await noteDetailService.loadNoteDetail(notePath, {
newTab: true,
activate: true
});
} else {
await tabContext.activate();
if (notePath && tabContext.notePath !== notePath) {
await treeService.activateNote(notePath);
}
}
}
async showTab(tabId) {
for (const ctx of this.tabContexts) {
if (ctx.tabId === tabId) {
await ctx.show();
} else {
ctx.hide();
}
}
const oldActiveNode = this.getMainNoteTree().getActiveNode();
if (oldActiveNode) {
oldActiveNode.setActive(false);
}
const newActiveTabContext = this.getActiveTabContext();
if (newActiveTabContext && newActiveTabContext.notePath) {
const newActiveNode = await this.getMainNoteTree().getNodeFromPath(newActiveTabContext.notePath);
if (newActiveNode) {
if (!newActiveNode.isVisible()) {
await this.getMainNoteTree().expandToNote(newActiveTabContext.notePath);
}
newActiveNode.setActive(true, {noEvents: true});
}
}
}
showWidgets() {
const $leftPane = $("#left-pane");
@ -39,8 +136,68 @@ class AppContext {
getMainNoteTree() {
return this.noteTreeWidget;
}
getTab(newTab, state) {
if (!this.getActiveTabContext() || newTab) {
// if it's a new tab explicitly by user then it's in background
const ctx = new TabContext(tabRow, state);
this.tabContexts.push(ctx);
return ctx;
} else {
return this.getActiveTabContext();
}
}
async reloadAllTabs() {
for (const tabContext of this.tabContexts) {
await this.reloadTab(tabContext);
}
}
async refreshTabs(sourceTabId, noteId) {
for (const tc of this.tabContexts) {
if (tc.noteId === noteId && tc.tabId !== sourceTabId) {
await this.reloadTab(tc);
}
}
}
async reloadTab(tc) {
if (tc.note) {
noteDetailService.reloadNote(tc);
}
}
async openEmptyTab() {
const ctx = new TabContext(tabRow);
this.tabContexts.push(ctx);
await tabRow.activateTab(ctx.$tab[0]);
}
}
const appContext = new AppContext();
tabRow.addListener('newTab', () => appContext.openEmptyTab());
tabRow.addListener('activeTabChange', async ({ detail }) => {
const tabId = detail.tabEl.getAttribute('data-tab-id');
await appContext.showTab(tabId);
});
tabRow.addListener('tabRemove', async ({ detail }) => {
const tabId = detail.tabEl.getAttribute('data-tab-id');
appContext.tabContexts.filter(nc => nc.tabId === tabId)
.forEach(tc => tc.remove());
appContext.tabContexts = appContext.tabContexts.filter(nc => nc.tabId !== tabId);
if (appContext.tabContexts.length === 0) {
appContext.openEmptyTab();
}
});
export default appContext;

View File

@ -284,6 +284,8 @@ function registerEntrypoints() {
searchNotesService.searchInSubtree(node.data.noteId);
});
keyboardActionService.setGlobalActionHandler('CollapseTree', () => appContext.getMainNoteTree().collapseTree());
}
export default {

View File

@ -286,7 +286,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
* @method
* @returns {Promise<void>}
*/
this.refreshAllTabs = noteDetailService.reloadAllTabs;
this.refreshAllTabs = appContext.reloadAllTabs;
/**
* Create note link (jQuery object) for given note.
@ -309,7 +309,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
* @method
* @returns {NoteFull} active note (loaded into right pane)
*/
this.getActiveTabNote = noteDetailService.getActiveTabNote;
this.getActiveTabNote = appContext.getActiveTabNote;
/**
* See https://ckeditor.com/docs/ckeditor5/latest/api/module_core_editor_editor-Editor.html for a documentation on the returned instance.
@ -323,7 +323,7 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte
* @method
* @returns {Promise<string|null>} returns note path of active note or null if there isn't active note
*/
this.getActiveTabNotePath = noteDetailService.getActiveTabNotePath;
this.getActiveTabNotePath = appContext.getActiveTabNotePath;
/**
* This method checks whether user navigated away from the note from which the scripts has been started.

View File

@ -30,7 +30,7 @@ async function setHoistedNoteId(noteId) {
await tree.reload();
const activeTabContext = noteDetailService.getActiveTabContext();
const activeTabContext = appContext.getActiveTabContext();
if (activeTabContext) {
await tree.activateNote(activeTabContext.notePath);

View File

@ -8,7 +8,7 @@ const SELECTED_PATH_KEY = "data-note-path";
async function autocompleteSource(term, cb) {
const result = await server.get('autocomplete'
+ '?query=' + encodeURIComponent(term)
+ '&activeNoteId=' + noteDetailService.getActiveTabNoteId());
+ '&activeNoteId=' + appContext.getActiveTabNoteId());
if (result.length === 0) {
result.push({

View File

@ -4,7 +4,6 @@ import server from './server.js';
import ws from "./ws.js";
import treeCache from "./tree_cache.js";
import NoteFull from "../entities/note_full.js";
import utils from "./utils.js";
import contextMenuService from "./context_menu.js";
import treeUtils from "./tree_utils.js";
import tabRow from "./tab_row.js";
@ -19,21 +18,13 @@ let detailLoadedListeners = [];
async function reload() {
// no saving here
await loadNoteDetail(getActiveTabContext().notePath);
await loadNoteDetail(appContext.getActiveTabNotePath());
}
async function reloadTab(tabContext) {
if (tabContext.note) {
const note = await loadNote(tabContext.note.noteId);
async function reloadNote(tabContext) {
const note = await loadNote(tabContext.note.noteId);
await loadNoteDetailToContext(tabContext, note, tabContext.notePath);
}
}
async function reloadAllTabs() {
for (const tabContext of tabContexts) {
await reloadTab(tabContext);
}
await loadNoteDetailToContext(tabContext, note, tabContext.notePath);
}
async function openInTab(notePath, activate) {
@ -53,7 +44,7 @@ function onNoteChange(func) {
}
async function saveNotesIfChanged() {
for (const ctx of tabContexts) {
for (const ctx of appContext.getTabContexts()) {
await ctx.saveNoteIfChanged();
}
@ -61,9 +52,6 @@ async function saveNotesIfChanged() {
$savedIndicator.fadeIn();
}
/** @type {TabContext[]} */
let tabContexts = [];
function getActiveEditor() {
const activeTabContext = getActiveTabContext();
@ -91,98 +79,6 @@ async function activateOrOpenNote(noteId) {
});
}
/** @return {TabContext[]} */
function getTabContexts() {
return tabContexts;
}
/** @returns {TabContext} */
function getActiveTabContext() {
const activeTabEl = tabRow.activeTabEl;
if (!activeTabEl) {
return null;
}
const tabId = activeTabEl.getAttribute('data-tab-id');
return tabContexts.find(tc => tc.tabId === tabId);
}
/** @returns {string|null} */
function getActiveTabNotePath() {
const activeContext = getActiveTabContext();
return activeContext ? activeContext.notePath : null;
}
/** @return {NoteFull} */
function getActiveTabNote() {
const activeContext = getActiveTabContext();
return activeContext ? activeContext.note : null;
}
/** @return {string|null} */
function getActiveTabNoteId() {
const activeNote = getActiveTabNote();
return activeNote ? activeNote.noteId : null;
}
/** @return {string|null} */
function getActiveTabNoteType() {
const activeNote = getActiveTabNote();
return activeNote ? activeNote.type : null;
}
async function switchToTab(tabId, notePath) {
const tabContext = tabContexts.find(tc => tc.tabId === tabId);
if (!tabContext) {
await loadNoteDetail(notePath, {
newTab: true,
activate: true
});
} else {
await tabContext.activate();
if (notePath && tabContext.notePath !== notePath) {
await treeService.activateNote(notePath);
}
}
}
async function showTab(tabId) {
for (const ctx of tabContexts) {
if (ctx.tabId === tabId) {
await ctx.show();
}
else {
ctx.hide();
}
}
const oldActiveNode = appContext.getMainNoteTree().getActiveNode();
if (oldActiveNode) {
oldActiveNode.setActive(false);
}
const newActiveTabContext = getActiveTabContext();
if (newActiveTabContext && newActiveTabContext.notePath) {
const newActiveNode = await appContext.getMainNoteTree().getNodeFromPath(newActiveTabContext.notePath);
if (newActiveNode) {
if (!newActiveNode.isVisible()) {
await appContext.getMainNoteTree().expandToNote(newActiveTabContext.notePath);
}
newActiveNode.setActive(true, {noEvents: true});
}
}
}
/**
* @param {TabContext} ctx
* @param {NoteFull} note
@ -211,16 +107,7 @@ async function loadNoteDetail(origNotePath, options = {}) {
const noteId = treeUtils.getNoteIdFromNotePath(notePath);
const loadedNote = await loadNote(noteId);
let ctx;
if (!getActiveTabContext() || newTab) {
// if it's a new tab explicitly by user then it's in background
ctx = new TabContext(tabRow, options.state);
tabContexts.push(ctx);
}
else {
ctx = getActiveTabContext();
}
const ctx = appContext.getTab(newTab, options.state);
// we will try to render the new note only if it's still the active one in the tree
// this is useful when user quickly switches notes (by e.g. holding down arrow) so that we don't
@ -281,14 +168,6 @@ async function noteDeleted(noteId) {
}
}
async function refreshTabs(sourceTabId, noteId) {
for (const tc of tabContexts) {
if (tc.noteId === noteId && tc.tabId !== sourceTabId) {
await reloadTab(tc);
}
}
}
function focusOnTitle() {
getActiveTabContext().$noteTitle.trigger('focus');
}
@ -337,12 +216,12 @@ ws.subscribeToOutsideSyncMessages(syncData => {
.forEach(sync => noteIdsToRefresh.add(sync.noteId));
for (const noteId of noteIdsToRefresh) {
refreshTabs(null, noteId);
appContext.refreshTabs(null, noteId);
}
});
ws.subscribeToAllSyncMessages(syncData => {
for (const tc of tabContexts) {
for (const tc of appContext.tabContexts) {
tc.eventReceived('syncData', syncData);
}
});
@ -371,34 +250,6 @@ $tabContentsContainer.on("drop", async e => {
});
});
async function openEmptyTab() {
const ctx = new TabContext(tabRow);
tabContexts.push(ctx);
await tabRow.activateTab(ctx.$tab[0]);
}
tabRow.addListener('newTab', openEmptyTab);
tabRow.addListener('activeTabChange', async ({ detail }) => {
const tabId = detail.tabEl.getAttribute('data-tab-id');
await showTab(tabId);
});
tabRow.addListener('tabRemove', async ({ detail }) => {
const tabId = detail.tabEl.getAttribute('data-tab-id');
tabContexts.filter(nc => nc.tabId === tabId)
.forEach(tc => tc.remove());
tabContexts = tabContexts.filter(nc => nc.tabId !== tabId);
if (tabContexts.length === 0) {
openEmptyTab();
}
});
$(tabRow.el).on('contextmenu', '.note-tab', e => {
e.preventDefault();
@ -473,7 +324,7 @@ async function saveOpenTabs() {
for (const tabEl of tabRow.tabEls) {
const tabId = tabEl.getAttribute('data-tab-id');
const tabContext = tabContexts.find(tc => tc.tabId === tabId);
const tabContext = appContext.getTabContexts().find(tc => tc.tabId === tabId);
if (tabContext) {
const tabState = tabContext.getTabState();
@ -505,7 +356,6 @@ setInterval(saveNotesIfChanged, 3000);
export default {
reload,
reloadAllTabs,
openInTab,
switchToNote,
loadNote,
@ -515,20 +365,12 @@ export default {
saveNotesIfChanged,
onNoteChange,
addDetailLoadedListener,
switchToTab,
getTabContexts,
getActiveTabContext,
getActiveTabNotePath,
getActiveTabNote,
getActiveTabNoteType,
getActiveTabNoteId,
getActiveEditor,
activateOrOpenNote,
clearOpenTabsTask,
filterTabs,
openEmptyTab,
noteDeleted,
refreshTabs,
noteChanged,
openTabsChanged
openTabsChanged,
reloadNote
};

View File

@ -5,6 +5,7 @@ import server from './server.js';
import protectedSessionHolder from './protected_session_holder.js';
import toastService from "./toast.js";
import ws from "./ws.js";
import appContext from "./app_context.js";
const $enterProtectedSessionButton = $("#enter-protected-session-button");
const $leaveProtectedSessionButton = $("#leave-protected-session-button");
@ -50,7 +51,7 @@ async function setupProtectedSession(password) {
await treeService.reload();
// it's important that tree has been already reloaded at this point since detail also uses tree cache (for book)
await noteDetailService.reloadAllTabs();
await appContext.reloadAllTabs();
if (protectedSessionDeferred !== null) {
import("../dialogs/protected_session.js").then(dialog => dialog.close());
@ -72,16 +73,16 @@ async function enterProtectedSessionOnServer(password) {
}
async function protectNoteAndSendToServer() {
if (!noteDetailService.getActiveTabNote() || noteDetailService.getActiveTabNote().isProtected) {
if (!appContext.getActiveTabNote() || appContext.getActiveTabNote().isProtected) {
return;
}
await enterProtectedSession();
const note = noteDetailService.getActiveTabNote();
const note = appContext.getActiveTabNote();
note.isProtected = true;
await noteDetailService.getActiveTabContext().saveNote();
await appContext.getActiveTabContext().saveNote();
treeService.setProtected(note.noteId, note.isProtected);
@ -89,7 +90,7 @@ async function protectNoteAndSendToServer() {
}
async function unprotectNoteAndSendToServer() {
const activeNote = noteDetailService.getActiveTabNote();
const activeNote = appContext.getActiveTabNote();
if (!activeNote.isProtected) {
toastService.showAndLogError(`Note ${activeNote.noteId} is not protected`);
@ -108,7 +109,7 @@ async function unprotectNoteAndSendToServer() {
activeNote.isProtected = false;
await noteDetailService.getActiveTabContext().saveNote();
await appContext.getActiveTabContext().saveNote();
treeService.setProtected(activeNote.noteId, activeNote.isProtected);

View File

@ -38,7 +38,7 @@ $showSidebarButton.on('click', async () => {
await server.put('options/rightPaneVisible/true');
const {sidebar} = noteDetailService.getActiveTabContext();
const {sidebar} = appContext.getActiveTabContext();
await sidebar.noteLoaded();
sidebar.show();
});

View File

@ -11,6 +11,7 @@ import protectedSessionService from "./protected_session.js";
import optionsService from "./options.js";
import linkService from "./link.js";
import Sidebar from "./sidebar.js";
import appContext from "./app_context.js";
const $tabContentsContainer = $("#note-tab-container");
@ -360,7 +361,7 @@ class TabContext {
if (this.isNoteChanged) {
await this.saveNote();
noteDetailService.refreshTabs(this.tabId, this.note.noteId);
appContext.refreshTabs(this.tabId, this.note.noteId);
}
}

View File

@ -215,7 +215,7 @@ function getSelectedNodes(stopOnParents = false) {
}
async function treeInitialized() {
if (noteDetailService.getTabContexts().length > 0) {
if (appContext.getTabContexts().length > 0) {
// this is just tree reload - tabs are already in place
return;
}
@ -369,7 +369,7 @@ async function createNote(node, parentNoteId, target, extraOptions = {}) {
extraOptions.isProtected = false;
}
if (noteDetailService.getActiveTabNoteType() !== 'text') {
if (appContext.getActiveTabNoteType() !== 'text') {
extraOptions.saveSelection = false;
}
@ -560,31 +560,10 @@ async function reloadNotes(noteIds, activateNotePath = null) {
await treeCache.reloadNotes(noteIds);
if (!activateNotePath) {
activateNotePath = noteDetailService.getActiveTabNotePath();
activateNotePath = appContext.getActiveTabNotePath();
}
for (const noteId of noteIds) {
for (const node of appContext.getMainNoteTree().getNodesByNoteId(noteId)) {
const branch = treeCache.getBranch(node.data.branchId, true);
if (!branch) {
node.remove();
}
else {
await node.load(true);
await appContext.getMainNoteTree().checkFolderStatus(node);
}
}
}
if (activateNotePath) {
const node = await appContext.getMainNoteTree().getNodeFromPath(activateNotePath);
if (node && !node.isActive()) {
await node.setActive(true);
}
}
appContext.trigger('notesReloaded', { noteIds, activateNotePath });
}
window.glob.cutIntoNote = () => createNoteInto(true);
@ -599,7 +578,7 @@ $(window).bind('hashchange', async function() {
if (isNotePathInAddress()) {
const [notePath, tabId] = getHashValueFromAddress();
noteDetailService.switchToTab(tabId, notePath);
appContext.switchToTab(tabId, notePath);
}
});

View File

@ -1,7 +1,6 @@
import BasicWidget from "./basic_widget.js";
import hoistedNoteService from "../services/hoisted_note.js";
import searchNotesService from "../services/search_notes.js";
import keyboardActionService from "../services/keyboard_actions.js";
import treeService from "../services/tree.js";
import treeUtils from "../services/tree_utils.js";
import noteDetailService from "../services/note_detail.js";
@ -13,10 +12,11 @@ import treeBuilder from "../services/tree_builder.js";
import TreeContextMenu from "../services/tree_context_menu.js";
import treeChangesService from "../services/branches.js";
import ws from "../services/ws.js";
import appContext from "../services/app_context.js";
const TPL = `
<style>
#tree {
.tree {
overflow: auto;
flex-grow: 1;
flex-shrink: 1;
@ -26,7 +26,7 @@ const TPL = `
}
</style>
<div id="tree"></div>
<div class="tree"></div>
`;
export default class NoteTreeWidget extends BasicWidget {
@ -39,7 +39,7 @@ export default class NoteTreeWidget extends BasicWidget {
async doRender($widget) {
$widget.append($(TPL));
const $tree = $widget.find('#tree');
const $tree = $widget.find('.tree');
const treeData = await treeService.loadTreeData();
@ -48,9 +48,6 @@ export default class NoteTreeWidget extends BasicWidget {
$tree.on("click", ".unhoist-button", hoistedNoteService.unhoist);
$tree.on("click", ".refresh-search-button", searchNotesService.refreshSearch);
// FIXME this does not belong here ...
keyboardActionService.setGlobalActionHandler('CollapseTree', () => this.collapseTree()); // don't use shortened form since collapseTree() accepts argument
// fancytree doesn't support middle click so this is a way to support it
$widget.on('mousedown', '.fancytree-title', e => {
if (e.which === 2) {
@ -154,7 +151,7 @@ export default class NoteTreeWidget extends BasicWidget {
if (dataTransfer && dataTransfer.files && dataTransfer.files.length > 0) {
const files = [...dataTransfer.files]; // chrome has issue that dataTransfer.files empties after async operation
const importService = await import('./import.js');
const importService = await import('../services/import.js');
importService.uploadFiles(node.data.noteId, files, {
safeImport: true,
@ -231,7 +228,7 @@ export default class NoteTreeWidget extends BasicWidget {
return false; // blocks default browser right click menu
});
this.tree = $.ui.fancytree.getTree("#tree");
this.tree = $.ui.fancytree.getTree($tree);
}
/** @return {FancytreeNode[]} */
@ -286,7 +283,7 @@ export default class NoteTreeWidget extends BasicWidget {
// FIXME since this operates on note details tab context it seems it does not really belong here
async scrollToActiveNote() {
const activeContext = noteDetailService.getActiveTabContext();
const activeContext = appContext.getActiveTabContext();
if (activeContext && activeContext.notePath) {
this.tree.setFocus();
@ -405,4 +402,29 @@ export default class NoteTreeWidget extends BasicWidget {
createTopLevelNoteListener() { treeService.createNewTopLevelNote(); }
collapseTreeListener() { this.collapseTree(); }
async notesReloadedListener({ noteIds, activateNotePath }) {
for (const noteId of noteIds) {
for (const node of this.getNodesByNoteId(noteId)) {
const branch = treeCache.getBranch(node.data.branchId, true);
if (!branch) {
node.remove();
}
else {
await node.load(true);
await this.checkFolderStatus(node);
}
}
}
if (activateNotePath) {
const node = await this.getNodeFromPath(activateNotePath);
if (node && !node.isActive()) {
await node.setActive(true);
}
}
}
}

View File

@ -23,12 +23,12 @@ html, body {
margin: 0 10px 0 16px;
}
#tree {
.tree {
width: 100%;
overflow: auto;
}
#tree .action-button {
.tree .action-button {
position: relative;
top: -5px;
margin-left: 10px;