mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 02:16:05 +01:00 
			
		
		
		
	refactoring of note detail API
This commit is contained in:
		| @@ -174,8 +174,7 @@ function AttributesModel() { | |||||||
|  |  | ||||||
|         appContext.getActiveTabContext().attributes.refreshAttributes(); |         appContext.getActiveTabContext().attributes.refreshAttributes(); | ||||||
|  |  | ||||||
|         // reload |         // FIXME detail should be also reloaded | ||||||
|         noteDetailService.reload(); |  | ||||||
|         appContext.trigger('reloadTree'); |         appContext.trigger('reloadTree'); | ||||||
|     }; |     }; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -62,7 +62,6 @@ async function showTree() { | |||||||
|  |  | ||||||
|             const notePath = await treeUtils.getNotePath(node); |             const notePath = await treeUtils.getNotePath(node); | ||||||
|  |  | ||||||
|             noteDetailService.switchToNote(notePath); |  | ||||||
|         }, |         }, | ||||||
|         expand: (event, data) => treeService.setExpandedToServer(data.node.data.branchId, true), |         expand: (event, data) => treeService.setExpandedToServer(data.node.data.branchId, true), | ||||||
|         collapse: (event, data) => treeService.setExpandedToServer(data.node.data.branchId, false), |         collapse: (event, data) => treeService.setExpandedToServer(data.node.data.branchId, false), | ||||||
|   | |||||||
| @@ -216,21 +216,12 @@ class AppContext { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     async switchToTab(tabId, notePath) { |     async switchToTab(tabId, notePath) { | ||||||
|         const tabContext = this.tabContexts.find(tc => tc.tabId === tabId); |         const tabContext = this.tabContexts.find(tc => tc.tabId === tabId) | ||||||
|  |                          || this.openEmptyTab(); | ||||||
|  |  | ||||||
|         if (!tabContext) { |         this.activateTab(tabContext.tabId); | ||||||
|             await noteDetailService.loadNoteDetail(notePath, { |  | ||||||
|                 newTab: true, |  | ||||||
|                 activate: true |  | ||||||
|             }); |  | ||||||
|         } else { |  | ||||||
|             await this.activateTab(tabContext.tabId); |  | ||||||
|  |  | ||||||
|             if (notePath && tabContext.notePath !== notePath) { |  | ||||||
|         await tabContext.setNote(notePath); |         await tabContext.setNote(notePath); | ||||||
|     } |     } | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * @return {NoteTreeWidget} |      * @return {NoteTreeWidget} | ||||||
| @@ -252,18 +243,6 @@ class AppContext { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async reloadAllTabs() { |  | ||||||
|         for (const tabContext of this.tabContexts) { |  | ||||||
|             await this.reloadTab(tabContext); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     async reloadTab(tc) { |  | ||||||
|         if (tc.note) { |  | ||||||
|             noteDetailService.reloadNote(tc); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     async openAndActivateEmptyTab() { |     async openAndActivateEmptyTab() { | ||||||
|         const tabContext = this.openEmptyTab(); |         const tabContext = this.openEmptyTab(); | ||||||
|  |  | ||||||
| @@ -278,6 +257,20 @@ class AppContext { | |||||||
|         return tabContext; |         return tabContext; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     async activateOrOpenNote(noteId) { | ||||||
|  |         for (const tabContext of this.getTabContexts()) { | ||||||
|  |             if (tabContext.note && tabContext.note.noteId === noteId) { | ||||||
|  |                 await tabContext.activate(); | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         // if no tab with this note has been found we'll create new tab | ||||||
|  |  | ||||||
|  |         const tabContext = this.openEmptyTab(); | ||||||
|  |         await tabContext.setNote(noteId); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     async filterTabs(noteId) { |     async filterTabs(noteId) { | ||||||
|         for (const tc of this.tabContexts) { |         for (const tc of this.tabContexts) { | ||||||
|             if (tc.notePath && !tc.notePath.split("/").includes(noteId)) { |             if (tc.notePath && !tc.notePath.split("/").includes(noteId)) { | ||||||
| @@ -318,7 +311,7 @@ class AppContext { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     openTabsChanged() { |     openTabsChangedListener() { | ||||||
|         // we don't want to send too many requests with tab changes so we always schedule task to do this in 1 seconds, |         // we don't want to send too many requests with tab changes so we always schedule task to do this in 1 seconds, | ||||||
|         // but if there's any change in between, we cancel the old one and schedule new one |         // but if there's any change in between, we cancel the old one and schedule new one | ||||||
|         // so effectively we kind of wait until user stopped e.g. quickly switching tabs |         // so effectively we kind of wait until user stopped e.g. quickly switching tabs | ||||||
| @@ -327,7 +320,7 @@ class AppContext { | |||||||
|         this.tabsChangedTaskId = setTimeout(() => this.saveOpenTabs(), 1000); |         this.tabsChangedTaskId = setTimeout(() => this.saveOpenTabs(), 1000); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async activateTab(tabId) { |     activateTab(tabId) { | ||||||
|         this.activeTabId = tabId; |         this.activeTabId = tabId; | ||||||
|  |  | ||||||
|         this.trigger('activeTabChanged', { tabId: this.activeTabId }); |         this.trigger('activeTabChanged', { tabId: this.activeTabId }); | ||||||
| @@ -364,11 +357,11 @@ class AppContext { | |||||||
|  |  | ||||||
|         this.tabContexts = this.tabContexts.filter(tc => tc.tabId === tabId); |         this.tabContexts = this.tabContexts.filter(tc => tc.tabId === tabId); | ||||||
|  |  | ||||||
|         this.openTabsChanged(); |         this.openTabsChangedListener(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     tabReorderListener() { |     tabReorderListener() { | ||||||
|         this.openTabsChanged(); |         this.openTabsChangedListener(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     noteChangesSavedListener() { |     noteChangesSavedListener() { | ||||||
|   | |||||||
| @@ -78,7 +78,9 @@ export default class Entrypoints extends Component { | |||||||
|  |  | ||||||
|         await treeService.expandToNote(note.noteId); |         await treeService.expandToNote(note.noteId); | ||||||
|  |  | ||||||
|         await noteDetailService.openInTab(note.noteId, true); |         const tabContext = appContext.openEmptyTab(); | ||||||
|  |         appContext.activateTab(tabContext.tabId); | ||||||
|  |         await tabContext.setNote(note.noteId); | ||||||
|  |  | ||||||
|         noteDetailService.focusAndSelectTitle(); |         noteDetailService.focusAndSelectTitle(); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -272,22 +272,6 @@ function FrontendScriptApi(startNote, currentNote, originEntity = null, tabConte | |||||||
|      */ |      */ | ||||||
|     this.refreshTree = treeService.reload; |     this.refreshTree = treeService.reload; | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Refresh active tab |  | ||||||
|      * |  | ||||||
|      * @method |  | ||||||
|      * @returns {Promise<void>} |  | ||||||
|      */ |  | ||||||
|     this.refreshActiveTab = noteDetailService.reload; |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * Refresh current tab |  | ||||||
|      * |  | ||||||
|      * @method |  | ||||||
|      * @returns {Promise<void>} |  | ||||||
|      */ |  | ||||||
|     this.refreshAllTabs = appContext.reloadAllTabs; |  | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * Create note link (jQuery object) for given note. |      * Create note link (jQuery object) for given note. | ||||||
|      * |      * | ||||||
|   | |||||||
| @@ -79,10 +79,13 @@ function goToLink(e) { | |||||||
|  |  | ||||||
|     if (notePath) { |     if (notePath) { | ||||||
|         if ((e.which === 1 && e.ctrlKey) || e.which === 2) { |         if ((e.which === 1 && e.ctrlKey) || e.which === 2) { | ||||||
|             noteDetailService.openInTab(notePath, false); |             const tabContext = appContext.openEmptyTab(); | ||||||
|  |             appContext.activateTab(tabContext.tabId); | ||||||
|  |             tabContext.setNote(notePath); | ||||||
|         } |         } | ||||||
|         else if (e.which === 1) { |         else if (e.which === 1) { | ||||||
|             treeService.activateNote(notePath); |             const activeTabContext = appContext.getActiveTabContext(); | ||||||
|  |             activeTabContext.setNote(notePath) | ||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
|             return false; |             return false; | ||||||
| @@ -118,7 +121,9 @@ function newTabContextMenu(e) { | |||||||
|         }, |         }, | ||||||
|         selectContextMenuItem: (e, cmd) => { |         selectContextMenuItem: (e, cmd) => { | ||||||
|             if (cmd === 'openNoteInNewTab') { |             if (cmd === 'openNoteInNewTab') { | ||||||
|                 noteDetailService.loadNoteDetail(notePath.split("/").pop(), { newTab: true }); |                 const tabContext = appContext.openEmptyTab(); | ||||||
|  |                 tabContext.setNote(notePath); | ||||||
|  |                 appContext.activateTab(tabContext.tabId); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     }); |     }); | ||||||
| @@ -138,7 +143,9 @@ $(document).on('mousedown', '.note-detail-text a', function (e) { | |||||||
|         e.preventDefault(); |         e.preventDefault(); | ||||||
|  |  | ||||||
|         if (notePath) { |         if (notePath) { | ||||||
|             noteDetailService.loadNoteDetail(notePath, {newTab: true}); |             const tabContext = appContext.openEmptyTab(); | ||||||
|  |             tabContext.setNote(notePath); | ||||||
|  |             appContext.activateTab(tabContext.tabId); | ||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
|             const address = $link.attr('href'); |             const address = $link.attr('href'); | ||||||
|   | |||||||
| @@ -1,35 +1,9 @@ | |||||||
| import treeService from './tree.js'; |  | ||||||
| import TabContext from './tab_context.js'; |  | ||||||
| import server from './server.js'; | import server from './server.js'; | ||||||
| import ws from "./ws.js"; | import ws from "./ws.js"; | ||||||
| import treeCache from "./tree_cache.js"; | import treeCache from "./tree_cache.js"; | ||||||
| import NoteFull from "../entities/note_full.js"; | import NoteFull from "../entities/note_full.js"; | ||||||
| import treeUtils from "./tree_utils.js"; |  | ||||||
| import tabRow from "../widgets/tab_row.js"; |  | ||||||
| import appContext from "./app_context.js"; | import appContext from "./app_context.js"; | ||||||
|  |  | ||||||
| let detailLoadedListeners = []; |  | ||||||
|  |  | ||||||
| async function reload() { |  | ||||||
|     // no saving here |  | ||||||
|  |  | ||||||
|     await loadNoteDetail(appContext.getActiveTabNotePath()); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| async function reloadNote(tabContext) { |  | ||||||
|     await loadNoteDetailToContext(tabContext, tabContext.notePath); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| async function openInTab(notePath, activate) { |  | ||||||
|     await loadNoteDetail(notePath, { newTab: true, activate }); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| async function switchToNote(notePath) { |  | ||||||
|     await loadNoteDetail(notePath); |  | ||||||
|  |  | ||||||
|     appContext.openTabsChanged(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function getActiveEditor() { | function getActiveEditor() { | ||||||
|     const activeTabContext = appContext.getActiveTabContext(); |     const activeTabContext = appContext.getActiveTabContext(); | ||||||
|  |  | ||||||
| @@ -41,73 +15,6 @@ function getActiveEditor() { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| async function activateOrOpenNote(noteId) { |  | ||||||
|     for (const tabContext of appContext.getTabContexts()) { |  | ||||||
|         if (tabContext.note && tabContext.note.noteId === noteId) { |  | ||||||
|             await tabContext.activate(); |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // if no tab with this note has been found we'll create new tab |  | ||||||
|  |  | ||||||
|     await loadNoteDetail(noteId, { |  | ||||||
|         newTab: true, |  | ||||||
|         activate: true |  | ||||||
|     }); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @param {TabContext} ctx |  | ||||||
|  * @param {string} notePath |  | ||||||
|  */ |  | ||||||
| async function loadNoteDetailToContext(ctx, notePath) { |  | ||||||
|     await ctx.setNote(notePath); |  | ||||||
|  |  | ||||||
|     appContext.openTabsChanged(); |  | ||||||
|  |  | ||||||
|     fireDetailLoaded(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| async function loadNoteDetail(origNotePath, options = {}) { |  | ||||||
|     const newTab = !!options.newTab; |  | ||||||
|     const activate = !!options.activate; |  | ||||||
|  |  | ||||||
|     let notePath = await treeService.resolveNotePath(origNotePath); |  | ||||||
|  |  | ||||||
|     if (!notePath) { |  | ||||||
|         console.error(`Cannot resolve note path ${origNotePath}`); |  | ||||||
|  |  | ||||||
|         // fallback to display something |  | ||||||
|         notePath = 'root'; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     const noteId = treeUtils.getNoteIdFromNotePath(notePath); |  | ||||||
|     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 |  | ||||||
|     // try to render all those loaded notes one after each other. This only guarantees that correct note |  | ||||||
|     // will be displayed independent of timing |  | ||||||
|     const currentTreeNode = appContext.getMainNoteTree().getActiveNode(); |  | ||||||
|     if (!newTab && currentTreeNode && currentTreeNode.data.noteId !== noteId) { |  | ||||||
|         return; |  | ||||||
|     } |  | ||||||
|      |  | ||||||
|     const loadPromise = loadNoteDetailToContext(ctx, notePath).then(() => { |  | ||||||
|         if (activate) { |  | ||||||
|             return appContext.activateTab(ctx.tabId); |  | ||||||
|         } |  | ||||||
|         else { |  | ||||||
|             return Promise.resolve(); |  | ||||||
|         } |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     if (!options.async) { |  | ||||||
|         await loadPromise; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| async function loadNote(noteId) { | async function loadNote(noteId) { | ||||||
|     const row = await server.get('notes/' + noteId); |     const row = await server.get('notes/' + noteId); | ||||||
|  |  | ||||||
| @@ -116,49 +23,12 @@ async function loadNote(noteId) { | |||||||
|     return new NoteFull(treeCache, row, noteShort); |     return new NoteFull(treeCache, row, noteShort); | ||||||
| } | } | ||||||
|  |  | ||||||
| async function noteDeleted(noteId) { |  | ||||||
|     for (const tc of appContext.getTabContexts()) { |  | ||||||
|         // not removing active even if it contains deleted note since that one will move to another note (handled by deletion logic) |  | ||||||
|         // and we would lose tab context state (e.g. sidebar visibility) |  | ||||||
|         if (!tc.isActive() && tc.notePath && tc.notePath.split("/").includes(noteId)) { |  | ||||||
|             tabRow.removeTab(tc.tabId); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function focusOnTitle() { | function focusOnTitle() { | ||||||
|     appContext.getActiveTabContext().$noteTitle.trigger('focus'); |     appContext.trigger('focusOnTitle'); | ||||||
| } | } | ||||||
|  |  | ||||||
| function focusAndSelectTitle() { | function focusAndSelectTitle() { | ||||||
|     appContext.getActiveTabContext() |     appContext.trigger('focusAndSelectTitle'); | ||||||
|         .$noteTitle |  | ||||||
|             .trigger('focus') |  | ||||||
|             .trigger('select'); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Since detail loading may take some time and user might just browse through the notes using UP-DOWN keys, |  | ||||||
|  * we intentionally decouple activation of the note in the tree and full load of the note so just avaiting on |  | ||||||
|  * fancytree's activate() won't wait for the full load. |  | ||||||
|  * |  | ||||||
|  * This causes an issue where in some cases you want to do some action after detail is loaded. For this reason |  | ||||||
|  * we provide the listeners here which will be triggered after the detail is loaded and if the loaded note |  | ||||||
|  * is the one registered in the listener. |  | ||||||
|  */ |  | ||||||
| function addDetailLoadedListener(noteId, callback) { |  | ||||||
|     detailLoadedListeners.push({ noteId, callback }); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| function fireDetailLoaded() { |  | ||||||
|     for (const {noteId, callback} of detailLoadedListeners) { |  | ||||||
|         if (noteId === appContext.getActiveTabNoteId()) { |  | ||||||
|             callback(); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // all the listeners are one time only |  | ||||||
|     detailLoadedListeners = []; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| ws.subscribeToOutsideSyncMessages(syncData => { | ws.subscribeToOutsideSyncMessages(syncData => { | ||||||
| @@ -199,17 +69,9 @@ $(window).on('beforeunload', () => { | |||||||
|  }); |  }); | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
|     reload, |  | ||||||
|     openInTab, |  | ||||||
|     switchToNote, |  | ||||||
|     loadNote, |     loadNote, | ||||||
|     loadNoteDetail, |  | ||||||
|     focusOnTitle, |     focusOnTitle, | ||||||
|     focusAndSelectTitle, |     focusAndSelectTitle, | ||||||
|     addDetailLoadedListener, |  | ||||||
|     getActiveEditor, |     getActiveEditor, | ||||||
|     activateOrOpenNote, |     noteChanged | ||||||
|     noteDeleted, |  | ||||||
|     noteChanged, |  | ||||||
|     reloadNote |  | ||||||
| }; | }; | ||||||
| @@ -109,17 +109,12 @@ async function unprotectNoteAndSendToServer() { | |||||||
|     await appContext.getActiveTabContext().saveNote(); |     await appContext.getActiveTabContext().saveNote(); | ||||||
|  |  | ||||||
|     treeService.setProtected(activeNote.noteId, activeNote.isProtected); |     treeService.setProtected(activeNote.noteId, activeNote.isProtected); | ||||||
|  |  | ||||||
|     await noteDetailService.reload(); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| async function protectSubtree(noteId, protect) { | async function protectSubtree(noteId, protect) { | ||||||
|     await enterProtectedSession(); |     await enterProtectedSession(); | ||||||
|  |  | ||||||
|     await server.put('notes/' + noteId + "/protect/" + (protect ? 1 : 0)); |     await server.put('notes/' + noteId + "/protect/" + (protect ? 1 : 0)); | ||||||
|  |  | ||||||
|     treeService.reload(); |  | ||||||
|     noteDetailService.reload(); |  | ||||||
| } | } | ||||||
|  |  | ||||||
| function makeToast(message, protectingLabel, text) { | function makeToast(message, protectingLabel, text) { | ||||||
|   | |||||||
| @@ -8,6 +8,7 @@ import appContext from "./app_context.js"; | |||||||
| import treeUtils from "./tree_utils.js"; | import treeUtils from "./tree_utils.js"; | ||||||
| import noteDetailService from "./note_detail.js"; | import noteDetailService from "./note_detail.js"; | ||||||
| import Component from "../widgets/component.js"; | import Component from "../widgets/component.js"; | ||||||
|  | import treeService from "./tree.js"; | ||||||
|  |  | ||||||
| let showSidebarInNewTab = true; | let showSidebarInNewTab = true; | ||||||
|  |  | ||||||
| @@ -35,7 +36,19 @@ class TabContext extends Component { | |||||||
|         this.trigger('tabOpened', {tabId: this.tabId}); |         this.trigger('tabOpened', {tabId: this.tabId}); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async setNote(notePath) { |     async setNote(inputNotePath) { | ||||||
|  |         const notePath = await treeService.resolveNotePath(inputNotePath); | ||||||
|  |  | ||||||
|  |         if (!notePath) { | ||||||
|  |             console.error(`Cannot resolve note path ${inputNotePath}`); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         if (notePath === this.notePath) { | ||||||
|  |             console.log(`Setting existing notePath ${notePath} so ignoring ...`); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         await this.trigger('beforeNoteSwitch', {tabId: this.tabId}, true); |         await this.trigger('beforeNoteSwitch', {tabId: this.tabId}, true); | ||||||
|  |  | ||||||
|         this.notePath = notePath; |         this.notePath = notePath; | ||||||
| @@ -64,6 +77,7 @@ class TabContext extends Component { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         this.trigger('tabNoteSwitched', {tabId: this.tabId}); |         this.trigger('tabNoteSwitched', {tabId: this.tabId}); | ||||||
|  |         this.trigger('openTabsChanged'); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async remove() { |     async remove() { | ||||||
| @@ -113,7 +127,16 @@ class TabContext extends Component { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     stateChanged() { |     stateChanged() { | ||||||
|         appContext.openTabsChanged(); |         appContext.openTabsChangedListener(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     noteDeletedListener({noteId}) { | ||||||
|  |         if (this.note && noteId === this.note.noteId) { | ||||||
|  |             this.note = null; | ||||||
|  |             this.notePath = null; | ||||||
|  |  | ||||||
|  |             this.trigger('tabNoteSwitched', {tabId: this.tabId}); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -263,12 +263,12 @@ async function treeInitialized() { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     for (const tab of filteredTabs) { |     for (const tab of filteredTabs) { | ||||||
|         await noteDetailService.loadNoteDetail(tab.notePath, { |         const tabContext = appContext.openEmptyTab(); | ||||||
|             state: tab, |         tabContext.setNote(tab.notePath); | ||||||
|             newTab: true, |  | ||||||
|             activate: tab.active, |         if (tab.active) { | ||||||
|             async: true // faster initial load |             appContext.activateTab(tabContext.tabId); | ||||||
|         }); |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // previous opening triggered task to save tab changes but these are bogus changes (this is init) |     // previous opening triggered task to save tab changes but these are bogus changes (this is init) | ||||||
| @@ -446,7 +446,7 @@ ws.subscribeToMessages(message => { | |||||||
|        reload(); |        reload(); | ||||||
|    } |    } | ||||||
|    else if (message.type === 'open-note') { |    else if (message.type === 'open-note') { | ||||||
|        noteDetailService.activateOrOpenNote(message.noteId); |        appContext.activateOrOpenNote(message.noteId); | ||||||
|  |  | ||||||
|        if (utils.isElectron()) { |        if (utils.isElectron()) { | ||||||
|            const currentWindow = require("electron").remote.getCurrentWindow(); |            const currentWindow = require("electron").remote.getCurrentWindow(); | ||||||
|   | |||||||
| @@ -104,7 +104,9 @@ class TreeContextMenu { | |||||||
|         const notePath = await treeUtils.getNotePath(this.node); |         const notePath = await treeUtils.getNotePath(this.node); | ||||||
|  |  | ||||||
|         if (cmd === 'openInTab') { |         if (cmd === 'openInTab') { | ||||||
|             noteDetailService.openInTab(notePath, false); |             const tabContext = appContext.openEmptyTab(); | ||||||
|  |             appContext.activateTab(tabContext.tabId); | ||||||
|  |             tabContext.setNote(notePath); | ||||||
|         } |         } | ||||||
|         else if (cmd.startsWith("insertNoteAfter")) { |         else if (cmd.startsWith("insertNoteAfter")) { | ||||||
|             const parentNoteId = this.node.data.parentNoteId; |             const parentNoteId = this.node.data.parentNoteId; | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ import protectedSessionHolder from "../services/protected_session_holder.js"; | |||||||
| import treeCache from "../services/tree_cache.js"; | import treeCache from "../services/tree_cache.js"; | ||||||
| import server from "../services/server.js"; | import server from "../services/server.js"; | ||||||
| import SpacedUpdate from "../services/spaced_update.js"; | import SpacedUpdate from "../services/spaced_update.js"; | ||||||
|  | import appContext from "../services/app_context.js"; | ||||||
|  |  | ||||||
| const TPL = ` | const TPL = ` | ||||||
| <div class="note-title-container"> | <div class="note-title-container"> | ||||||
| @@ -107,4 +108,18 @@ export default class NoteTitleWidget extends TabAwareWidget { | |||||||
|             await this.spacedUpdate.updateNowIfNecessary(); |             await this.spacedUpdate.updateNowIfNecessary(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     focusOnTitleListener() { | ||||||
|  |         if (this.tabContext && this.tabContext.isActive()) { | ||||||
|  |             this.$noteTitle.trigger('focus'); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     focusAndSelectTitleListener() { | ||||||
|  |         if (this.tabContext && this.tabContext.isActive()) { | ||||||
|  |             this.$noteTitle | ||||||
|  |                 .trigger('focus') | ||||||
|  |                 .trigger('select'); | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
| @@ -53,7 +53,8 @@ export default class NoteTreeWidget extends TabAwareWidget { | |||||||
|  |  | ||||||
|                 treeUtils.getNotePath(node).then(notePath => { |                 treeUtils.getNotePath(node).then(notePath => { | ||||||
|                     if (notePath) { |                     if (notePath) { | ||||||
|                         noteDetailService.openInTab(notePath, false); |                         const tabContext = appContext.openEmptyTab(); | ||||||
|  |                         tabContext.setNote(notePath); | ||||||
|                     } |                     } | ||||||
|                 }); |                 }); | ||||||
|  |  | ||||||
| @@ -87,7 +88,9 @@ export default class NoteTreeWidget extends TabAwareWidget { | |||||||
|                         node.setFocus(true); |                         node.setFocus(true); | ||||||
|                     } |                     } | ||||||
|                     else if (event.ctrlKey) { |                     else if (event.ctrlKey) { | ||||||
|                         noteDetailService.loadNoteDetail(node.data.noteId, { newTab: true }); |                         const tabContext = appContext.openEmptyTab(); | ||||||
|  |                         treeUtils.getNotePath(node).then(notePath => tabContext.setNote(notePath)); | ||||||
|  |                         appContext.activateTab(tabContext.tabId); | ||||||
|                     } |                     } | ||||||
|                     else { |                     else { | ||||||
|                         node.setActive(); |                         node.setActive(); | ||||||
|   | |||||||
| @@ -130,9 +130,6 @@ export default class NoteTypeWidget extends TabAwareWidget { | |||||||
|  |  | ||||||
|         await noteDetailService.reload(); |         await noteDetailService.reload(); | ||||||
|  |  | ||||||
|         // for the note icon to be updated in the tree |  | ||||||
|         await treeService.reload(); |  | ||||||
|  |  | ||||||
|         this.update(); |         this.update(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -85,7 +85,7 @@ export default class SearchBoxWidget extends BasicWidget { | |||||||
|  |  | ||||||
|         this.$saveSearchButton.on('click', () => this.saveSearch()); |         this.$saveSearchButton.on('click', () => this.saveSearch()); | ||||||
|  |  | ||||||
|         this.$closeSearchButton.on('click', () => this.hideSearchListener()); |         this.$closeSearchButton.on('click', () => this.trigger('hideSearch')); | ||||||
|  |  | ||||||
|         return this.$widget; |         return this.$widget; | ||||||
|     } |     } | ||||||
| @@ -159,6 +159,8 @@ export default class SearchBoxWidget extends BasicWidget { | |||||||
|         this.resetSearchListener(); |         this.resetSearchListener(); | ||||||
|  |  | ||||||
|         this.$searchBox.slideUp(); |         this.$searchBox.slideUp(); | ||||||
|  |  | ||||||
|  |         this.trigger('hideSearchResults'); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     toggleSearchListener() { |     toggleSearchListener() { | ||||||
| @@ -167,7 +169,6 @@ export default class SearchBoxWidget extends BasicWidget { | |||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
|             this.hideSearchListener(); |             this.hideSearchListener(); | ||||||
|             this.trigger('hideSearchResults'); |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -34,6 +34,8 @@ export default class SearchResultsWidget extends BasicWidget { | |||||||
|         this.$searchResults = this.$widget; |         this.$searchResults = this.$widget; | ||||||
|         this.$searchResultsInner = this.$widget.find(".search-results-inner"); |         this.$searchResultsInner = this.$widget.find(".search-results-inner"); | ||||||
|  |  | ||||||
|  |         this.toggle(false); | ||||||
|  |  | ||||||
|         return this.$widget; |         return this.$widget; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -20,6 +20,10 @@ export default class TabCachingWidget extends TabAwareWidget { | |||||||
|             widget.toggle(false); |             widget.toggle(false); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         if (!this.tabContext) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         let widget = this.widgets[this.tabContext.tabId]; |         let widget = this.widgets[this.tabContext.tabId]; | ||||||
|  |  | ||||||
|         if (!widget) { |         if (!widget) { | ||||||
| @@ -31,8 +35,6 @@ export default class TabCachingWidget extends TabAwareWidget { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         widget.toggle(true); |         widget.toggle(true); | ||||||
|  |  | ||||||
|         return false; // stop propagation to children |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     tabRemovedListener({tabId}) { |     tabRemovedListener({tabId}) { | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ import contextMenuWidget from "../../services/context_menu.js"; | |||||||
| import toastService from "../../services/toast.js"; | import toastService from "../../services/toast.js"; | ||||||
| import attributeAutocompleteService from "../../services/attribute_autocomplete.js"; | import attributeAutocompleteService from "../../services/attribute_autocomplete.js"; | ||||||
| import TypeWidget from "./type_widget.js"; | import TypeWidget from "./type_widget.js"; | ||||||
|  | import appContext from "../../services/app_context.js"; | ||||||
|  |  | ||||||
| const uniDirectionalOverlays = [ | const uniDirectionalOverlays = [ | ||||||
|     [ "Arrow", { |     [ "Arrow", { | ||||||
| @@ -196,7 +197,8 @@ export default class RelationMapTypeWidget extends TypeWidget { | |||||||
|         const noteId = this.idToNoteId($noteBox.prop("id")); |         const noteId = this.idToNoteId($noteBox.prop("id")); | ||||||
|  |  | ||||||
|         if (cmd === "open-in-new-tab") { |         if (cmd === "open-in-new-tab") { | ||||||
|             noteDetailService.openInTab(noteId, false); |             const tabContext = appContext.openEmptyTab(); | ||||||
|  |             tabContext.setNote(noteId); | ||||||
|         } |         } | ||||||
|         else if (cmd === "remove") { |         else if (cmd === "remove") { | ||||||
|             const confirmDialog = await import('../../dialogs/confirm.js'); |             const confirmDialog = await import('../../dialogs/confirm.js'); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user