From 826c43463094bc8fcaaf5a6eeb0075d0ee7e0725 Mon Sep 17 00:00:00 2001 From: zadam Date: Sun, 9 Feb 2020 21:13:05 +0100 Subject: [PATCH] fixes in closing tabs and elsewhere --- package-lock.json | 2 +- src/public/javascripts/desktop.js | 1 + .../javascripts/services/app_context.js | 25 +------ .../javascripts/services/entrypoints.js | 2 +- src/public/javascripts/services/link.js | 6 +- .../javascripts/services/tab_context.js | 7 +- .../javascripts/services/tab_manager.js | 67 +++++++++++++------ src/public/javascripts/services/tree.js | 14 ++-- .../javascripts/services/tree_context_menu.js | 2 +- src/public/javascripts/widgets/calendar.js | 6 -- src/public/javascripts/widgets/note_tree.js | 17 +++-- src/public/javascripts/widgets/search_box.js | 3 + .../javascripts/widgets/tab_caching_widget.js | 3 + src/public/javascripts/widgets/tab_row.js | 20 +++--- .../widgets/type_widgets/relation_map.js | 2 +- 15 files changed, 94 insertions(+), 83 deletions(-) diff --git a/package-lock.json b/package-lock.json index 24030adef..f6d5ea951 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "trilium", - "version": "0.40.2", + "version": "0.40.3", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/src/public/javascripts/desktop.js b/src/public/javascripts/desktop.js index 38620c002..81cde1ae1 100644 --- a/src/public/javascripts/desktop.js +++ b/src/public/javascripts/desktop.js @@ -70,6 +70,7 @@ window.glob.refreshTree = treeService.reload; window.glob.getActiveTabNote = () => appContext.tabManager.getActiveTabNote(); window.glob.requireLibrary = libraryLoader.requireLibrary; window.glob.ESLINT = libraryLoader.ESLINT; +window.glob.appContext = appContext; // for debugging protectedSessionHolder.setProtectedSessionId(null); diff --git a/src/public/javascripts/services/app_context.js b/src/public/javascripts/services/app_context.js index ef1316675..94abda6a0 100644 --- a/src/public/javascripts/services/app_context.js +++ b/src/public/javascripts/services/app_context.js @@ -8,6 +8,7 @@ import utils from "./utils.js"; import ZoomService from "./zoom.js"; import Layout from "../widgets/layout.js"; import TabManager from "./tab_manager.js"; +import treeService from "./tree.js"; class AppContext { constructor(layout) { @@ -63,22 +64,6 @@ class AppContext { } } - hoistedNoteChangedListener({hoistedNoteId}) { - if (hoistedNoteId === 'root') { - return; - } - - for (const tc of this.tabManager.getTabContexts()) { - if (tc.notePath && !tc.notePath.split("/").includes(hoistedNoteId)) { - this.tabManager.removeTab(tc.tabId); - } - } - - if (this.tabManager.getTabContexts().length === 0) { - this.tabManager.openAndActivateEmptyTab(); - } - } - async protectedSessionStartedListener() { await treeCache.loadInitialTree(); @@ -103,15 +88,9 @@ function isNotePathInAddress() { || (notePath === '' && !!tabId); } -function getHashValueFromAddress() { - const str = document.location.hash ? document.location.hash.substr(1) : ""; // strip initial # - - return str.split("-"); -} - $(window).on('hashchange', function() { if (isNotePathInAddress()) { - const [notePath, tabId] = getHashValueFromAddress(); + const [notePath, tabId] = treeService.getHashValueFromAddress(); appContext.tabManager.switchToTab(tabId, notePath); } diff --git a/src/public/javascripts/services/entrypoints.js b/src/public/javascripts/services/entrypoints.js index 892adf134..be8efa8a2 100644 --- a/src/public/javascripts/services/entrypoints.js +++ b/src/public/javascripts/services/entrypoints.js @@ -70,7 +70,7 @@ export default class Entrypoints extends Component { await treeService.expandToNote(note.noteId); - const tabContext = appContext.openEmptyTab(); + const tabContext = appContext.tabManager.openEmptyTab(); appContext.tabManager.activateTab(tabContext.tabId); await tabContext.setNote(note.noteId); diff --git a/src/public/javascripts/services/link.js b/src/public/javascripts/services/link.js index 192d3b633..a4d72f203 100644 --- a/src/public/javascripts/services/link.js +++ b/src/public/javascripts/services/link.js @@ -77,7 +77,7 @@ function goToLink(e) { if (notePath) { if ((e.which === 1 && e.ctrlKey) || e.which === 2) { - const tabContext = appContext.openEmptyTab(); + const tabContext = appContext.tabManager.openEmptyTab(); appContext.tabManager.activateTab(tabContext.tabId); tabContext.setNote(notePath); } @@ -119,7 +119,7 @@ function newTabContextMenu(e) { }, selectContextMenuItem: (e, cmd) => { if (cmd === 'openNoteInNewTab') { - const tabContext = appContext.openEmptyTab(); + const tabContext = appContext.tabManager.openEmptyTab(); tabContext.setNote(notePath); appContext.tabManager.activateTab(tabContext.tabId); } @@ -141,7 +141,7 @@ $(document).on('mousedown', '.note-detail-text a', function (e) { e.preventDefault(); if (notePath) { - const tabContext = appContext.openEmptyTab(); + const tabContext = appContext.tabManager.openEmptyTab(); tabContext.setNote(notePath); appContext.tabManager.activateTab(tabContext.tabId); } diff --git a/src/public/javascripts/services/tab_context.js b/src/public/javascripts/services/tab_context.js index d81a2a4ea..ee9169283 100644 --- a/src/public/javascripts/services/tab_context.js +++ b/src/public/javascripts/services/tab_context.js @@ -12,13 +12,12 @@ import hoistedNoteService from "./hoisted_note.js"; class TabContext extends Component { /** * @param {AppContext} appContext - * @param {object} state + * @param {string|null} tabId */ - constructor(appContext, state = {}) { + constructor(appContext, tabId = null) { super(appContext); - this.tabId = state.tabId || utils.randomString(4); - this.state = state; + this.tabId = tabId || utils.randomString(4); this.trigger('newTabOpened', {tabId: this.tabId}); } diff --git a/src/public/javascripts/services/tab_manager.js b/src/public/javascripts/services/tab_manager.js index b866deae7..2101a9108 100644 --- a/src/public/javascripts/services/tab_manager.js +++ b/src/public/javascripts/services/tab_manager.js @@ -11,8 +11,6 @@ export default class TabManager extends Component { constructor(appContext) { super(appContext); - /** @type {TabContext[]} */ - this.tabContexts = []; this.activeTabId = null; this.tabsUpdate = new SpacedUpdate(async () => { @@ -26,6 +24,11 @@ export default class TabManager extends Component { }); } + /** @type {TabContext[]} */ + get tabContexts() { + return this.children; + } + async loadTabs() { const openTabs = options.getJson('openTabs') || []; @@ -85,7 +88,7 @@ export default class TabManager extends Component { await this.tabsUpdate.allowUpdateWithoutChange(async () => { for (const tab of filteredTabs) { - const tabContext = this.openEmptyTab(); + const tabContext = this.openEmptyTab(tab.tabId); await tabContext.setNote(tab.notePath); if (tab.active) { @@ -106,8 +109,19 @@ export default class TabManager extends Component { setCurrentNotePathToHash() { const activeTabContext = this.getActiveTabContext(); - if (activeTabContext && activeTabContext.notePath) { - document.location.hash = (activeTabContext.notePath || "") + "-" + activeTabContext.tabId; + if (activeTabContext + && activeTabContext.notePath !== treeService.getHashValueFromAddress()) { + const url = '#' + (activeTabContext.notePath || "") + "-" + activeTabContext.tabId; + + // using pushState instead of directly modifying document.location because it does not trigger hashchange + window.history.pushState(null, "", url); + + document.title = "Trilium Notes"; + + if (activeTabContext.note) { + // it helps navigating in history if note title is included in the title + document.title += " - " + activeTabContext.note.title; + } } } @@ -166,9 +180,8 @@ export default class TabManager extends Component { await this.activateTab(tabContext.tabId); } - openEmptyTab() { - const tabContext = new TabContext(this.appContext); - this.tabContexts.push(tabContext); + openEmptyTab(tabId) { + const tabContext = new TabContext(this.appContext, tabId); this.children.push(tabContext); return tabContext; } @@ -192,11 +205,9 @@ export default class TabManager extends Component { return; } - const oldActiveTabId = this.activeTabId; - this.activeTabId = tabId; - this.trigger('activeTabChanged', { oldActiveTabId, newActiveTabId: tabId }); + this.trigger('activeTabChanged'); this.tabsUpdate.scheduleUpdate(); @@ -204,7 +215,7 @@ export default class TabManager extends Component { } async removeTab(tabId) { - const tabContextToRemove = this.tabContexts.find(tc => tc.tabId === tabId); + const tabContextToRemove = this.getTabContextById(tabId); if (!tabContextToRemove) { return; @@ -212,14 +223,14 @@ export default class TabManager extends Component { await this.trigger('beforeTabRemove', {tabId}, true); - if (this.tabContexts.length === 1) { + if (this.tabContexts.length <= 1) { this.openAndActivateEmptyTab(); } else { this.activateNextTabListener(); } - this.children = this.tabContexts = this.tabContexts.filter(tc => tc.tabId === tabId); + this.children = this.children.filter(tc => tc.tabId !== tabId); this.trigger('tabRemoved', {tabId}); @@ -233,7 +244,7 @@ export default class TabManager extends Component { order[tabIdsInOrder[i]] = i; } - this.tabContexts.sort((a, b) => order[a.tabId] < order[b.tabId] ? -1 : 1); + this.children.sort((a, b) => order[a.tabId] < order[b.tabId] ? -1 : 1); this.tabsUpdate.scheduleUpdate(); } @@ -264,11 +275,29 @@ export default class TabManager extends Component { this.openAndActivateEmptyTab(); } - removeAllTabsListener() { - // TODO + async removeAllTabsListener() { + for (const tabIdToRemove of this.tabContexts.map(tc => tc.tabId)) { + await this.removeTab(tabIdToRemove); + } } - removeAllTabsExceptForThis() { - // TODO + async removeAllTabsExceptForThisListener({tabId}) { + for (const tabIdToRemove of this.tabContexts.map(tc => tc.tabId)) { + if (tabIdToRemove !== tabId) { + await this.removeTab(tabIdToRemove); + } + } + } + + async hoistedNoteChangedListener({hoistedNoteId}) { + if (hoistedNoteId === 'root') { + return; + } + + for (const tc of this.tabContexts.splice()) { + if (tc.notePath && !tc.notePath.split("/").includes(hoistedNoteId)) { + await this.removeTab(tc.tabId); + } + } } } \ No newline at end of file diff --git a/src/public/javascripts/services/tree.js b/src/public/javascripts/services/tree.js index 8271942f0..2df5d74bd 100644 --- a/src/public/javascripts/services/tree.js +++ b/src/public/javascripts/services/tree.js @@ -1,13 +1,8 @@ import ws from './ws.js'; -import protectedSessionHolder from './protected_session_holder.js'; import utils from './utils.js'; import server from './server.js'; import treeCache from './tree_cache.js'; -import toastService from "./toast.js"; -import treeBuilder from "./tree_builder.js"; import hoistedNoteService from '../services/hoisted_note.js'; -import optionsService from "../services/options.js"; -import bundle from "./bundle.js"; import appContext from "./app_context.js"; /** @@ -262,6 +257,12 @@ async function getNotePathTitle(notePath) { return titlePath.join(' / '); } +function getHashValueFromAddress() { + const str = document.location.hash ? document.location.hash.substr(1) : ""; // strip initial # + + return str.split("-"); +} + export default { sortAlphabetically, resolveNotePath, @@ -272,5 +273,6 @@ export default { getNoteIdFromNotePath, getNoteIdAndParentIdFromNotePath, getNoteTitle, - getNotePathTitle + getNotePathTitle, + getHashValueFromAddress }; \ No newline at end of file diff --git a/src/public/javascripts/services/tree_context_menu.js b/src/public/javascripts/services/tree_context_menu.js index 8e9a3bba1..a4f1b8bfd 100644 --- a/src/public/javascripts/services/tree_context_menu.js +++ b/src/public/javascripts/services/tree_context_menu.js @@ -102,7 +102,7 @@ class TreeContextMenu { const notePath = await treeService.getNotePath(this.node); if (cmd === 'openInTab') { - const tabContext = appContext.openEmptyTab(); + const tabContext = appContext.tabManager.openEmptyTab(); appContext.tabManager.activateTab(tabContext.tabId); tabContext.setNote(notePath); } diff --git a/src/public/javascripts/widgets/calendar.js b/src/public/javascripts/widgets/calendar.js index b03b48455..051622d0b 100644 --- a/src/public/javascripts/widgets/calendar.js +++ b/src/public/javascripts/widgets/calendar.js @@ -32,12 +32,6 @@ export default class CalendarWidget extends CollapsibleWidget { && this.note.hasOwnedLabel("dateNote"); } - setTabContextListener({tabContext}) { - super.setTabContextListener({tabContext}); - - console.log("set tab context", tabContext.tabId, "to", this.componentId); - } - async doRenderBody() { await libraryLoader.requireLibrary(libraryLoader.CALENDAR_WIDGET); diff --git a/src/public/javascripts/widgets/note_tree.js b/src/public/javascripts/widgets/note_tree.js index c1ebd0a6c..f0886b177 100644 --- a/src/public/javascripts/widgets/note_tree.js +++ b/src/public/javascripts/widgets/note_tree.js @@ -9,7 +9,6 @@ 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"; import TabAwareWidget from "./tab_aware_widget.js"; import server from "../services/server.js"; import noteCreateService from "../services/note_create.js"; @@ -51,7 +50,7 @@ export default class NoteTreeWidget extends TabAwareWidget { treeService.getNotePath(node).then(notePath => { if (notePath) { - const tabContext = appContext.openEmptyTab(); + const tabContext = this.tabManager.openEmptyTab(); tabContext.setNote(notePath); } }); @@ -86,9 +85,9 @@ export default class NoteTreeWidget extends TabAwareWidget { node.setFocus(true); } else if (event.ctrlKey) { - const tabContext = appContext.openEmptyTab(); + const tabContext = this.tabManager.openEmptyTab(); treeService.getNotePath(node).then(notePath => tabContext.setNote(notePath)); - appContext.tabManager.activateTab(tabContext.tabId); + this.tabManager.activateTab(tabContext.tabId); } else { node.setActive(); @@ -285,7 +284,7 @@ export default class NoteTreeWidget extends TabAwareWidget { } async scrollToActiveNoteListener() { - const activeContext = appContext.tabManager.getActiveTabContext(); + const activeContext = this.tabManager.getActiveTabContext(); if (activeContext && activeContext.notePath) { this.tree.setFocus(); @@ -409,6 +408,10 @@ export default class NoteTreeWidget extends TabAwareWidget { collapseTreeListener() { this.collapseTree(); } + isEnabled() { + return this.tabContext && this.tabContext.isActive(); + } + async refresh() { this.toggle(this.isEnabled()); @@ -467,7 +470,7 @@ export default class NoteTreeWidget extends TabAwareWidget { const notePath = await treeService.getNotePath(newActive); - appContext.tabManager.getActiveTabContext().setNote(notePath); + this.tabManager.getActiveTabContext().setNote(notePath); } node.remove(); @@ -527,7 +530,7 @@ export default class NoteTreeWidget extends TabAwareWidget { } } - const activateNotePath = appContext.tabManager.getActiveTabNotePath(); + const activateNotePath = this.tabManager.getActiveTabNotePath(); if (activateNotePath) { const node = await this.getNodeFromPath(activateNotePath); diff --git a/src/public/javascripts/widgets/search_box.js b/src/public/javascripts/widgets/search_box.js index ef88b6e4e..4c94e742a 100644 --- a/src/public/javascripts/widgets/search_box.js +++ b/src/public/javascripts/widgets/search_box.js @@ -4,6 +4,7 @@ import treeCache from "../services/tree_cache.js"; import toastService from "../services/toast.js"; import appContext from "../services/app_context.js"; import noteCreateService from "../services/note_create.js"; +import utils from "../services/utils.js"; const TPL = `