| 
									
										
										
										
											2022-12-01 13:07:23 +01:00
										 |  |  | import Component from "./component.js"; | 
					
						
							|  |  |  | import SpacedUpdate from "../services/spaced_update.js"; | 
					
						
							|  |  |  | import server from "../services/server.js"; | 
					
						
							|  |  |  | import options from "../services/options.js"; | 
					
						
							|  |  |  | import froca from "../services/froca.js"; | 
					
						
							|  |  |  | import treeService from "../services/tree.js"; | 
					
						
							|  |  |  | import utils from "../services/utils.js"; | 
					
						
							| 
									
										
										
										
											2021-05-22 12:35:41 +02:00
										 |  |  | import NoteContext from "./note_context.js"; | 
					
						
							| 
									
										
										
										
											2020-04-25 23:52:13 +02:00
										 |  |  | import appContext from "./app_context.js"; | 
					
						
							| 
									
										
										
										
											2022-02-09 21:21:17 +01:00
										 |  |  | import Mutex from "../utils/mutex.js"; | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | export default class TabManager extends Component { | 
					
						
							| 
									
										
										
										
											2020-02-27 10:03:14 +01:00
										 |  |  |     constructor() { | 
					
						
							|  |  |  |         super(); | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-09 21:21:17 +01:00
										 |  |  |         this.mutex = new Mutex(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-22 13:04:08 +02:00
										 |  |  |         this.activeNtxId = null; | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-09 22:03:24 +02:00
										 |  |  |         // elements are arrays of note contexts for each tab (one main context + subcontexts [splits])
 | 
					
						
							| 
									
										
										
										
											2021-10-09 21:20:12 +02:00
										 |  |  |         this.recentlyClosedTabs = []; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |         this.tabsUpdate = new SpacedUpdate(async () => { | 
					
						
							| 
									
										
										
										
											2020-04-25 23:52:13 +02:00
										 |  |  |             if (!appContext.isMainWindow) { | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-22 12:26:45 +02:00
										 |  |  |             const openTabs = this.noteContexts | 
					
						
							|  |  |  |                 .map(nc => nc.getTabState()) | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |                 .filter(t => !!t); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             await server.put('options', { | 
					
						
							|  |  |  |                 openTabs: JSON.stringify(openTabs) | 
					
						
							|  |  |  |             }); | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2021-02-27 23:39:02 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         appContext.addBeforeUnloadListener(this); | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-22 12:26:45 +02:00
										 |  |  |     /** @type {NoteContext[]} */ | 
					
						
							|  |  |  |     get noteContexts() { | 
					
						
							| 
									
										
										
										
											2020-02-09 21:13:05 +01:00
										 |  |  |         return this.children; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-22 12:26:45 +02:00
										 |  |  |     /** @type {NoteContext[]} */ | 
					
						
							|  |  |  |     get mainNoteContexts() { | 
					
						
							|  |  |  |         return this.noteContexts.filter(nc => !nc.mainNtxId) | 
					
						
							| 
									
										
										
										
											2021-05-20 23:13:34 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-04-25 23:52:13 +02:00
										 |  |  |     async loadTabs() { | 
					
						
							| 
									
										
										
										
											2022-12-14 10:00:33 +01:00
										 |  |  |         try { | 
					
						
							|  |  |  |             const tabsToOpen = appContext.isMainWindow | 
					
						
							|  |  |  |                 ? (options.getJson('openTabs') || []) | 
					
						
							|  |  |  |                 : []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             let filteredTabs = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // preload all notes at once
 | 
					
						
							|  |  |  |             await froca.getNotes([ | 
					
						
							| 
									
										
										
										
											2022-12-17 13:33:57 +01:00
										 |  |  |                     ...tabsToOpen.map(tab => treeService.getNoteIdFromNotePath(tab.notePath)), | 
					
						
							|  |  |  |                     ...tabsToOpen.map(tab => tab.hoistedNoteId), | 
					
						
							| 
									
										
										
										
											2022-12-14 10:00:33 +01:00
										 |  |  |             ], true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for (const openTab of tabsToOpen) { | 
					
						
							|  |  |  |                 if (openTab.notePath && !(treeService.getNoteIdFromNotePath(openTab.notePath) in froca.notes)) { | 
					
						
							|  |  |  |                     // note doesn't exist so don't try to open tab for it
 | 
					
						
							|  |  |  |                     continue; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (!(openTab.hoistedNoteId in froca.notes)) { | 
					
						
							|  |  |  |                     openTab.hoistedNoteId = 'root'; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 filteredTabs.push(openTab); | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-12-13 21:45:57 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-14 10:00:33 +01:00
										 |  |  |             if (utils.isMobile()) { | 
					
						
							|  |  |  |                 // mobile frontend doesn't have tabs so show only the active tab
 | 
					
						
							|  |  |  |                 filteredTabs = filteredTabs.filter(tab => tab.active); | 
					
						
							| 
									
										
										
										
											2022-12-13 21:45:57 +01:00
										 |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-31 23:20:11 +01:00
										 |  |  |             // resolve before opened tabs can change this
 | 
					
						
							|  |  |  |             const [notePathInUrl, ntxIdInUrl] = treeService.getHashValueFromAddress(); | 
					
						
							| 
									
										
										
										
											2022-12-22 23:38:57 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-31 23:20:11 +01:00
										 |  |  |             if (filteredTabs.length === 0) { | 
					
						
							| 
									
										
										
										
											2022-12-14 10:00:33 +01:00
										 |  |  |                 filteredTabs.push({ | 
					
						
							| 
									
										
										
										
											2023-01-31 23:20:11 +01:00
										 |  |  |                     notePath: notePathInUrl || 'root', | 
					
						
							| 
									
										
										
										
											2022-12-14 10:00:33 +01:00
										 |  |  |                     active: true, | 
					
						
							| 
									
										
										
										
											2023-04-03 23:47:24 +02:00
										 |  |  |                     hoistedNoteId: glob.extraHoistedNoteId || 'root', | 
					
						
							|  |  |  |                     viewScope: glob.extraViewScope || {} | 
					
						
							| 
									
										
										
										
											2022-12-14 10:00:33 +01:00
										 |  |  |                 }); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-14 10:00:33 +01:00
										 |  |  |             if (!filteredTabs.find(tab => tab.active)) { | 
					
						
							|  |  |  |                 filteredTabs[0].active = true; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-14 10:00:33 +01:00
										 |  |  |             await this.tabsUpdate.allowUpdateWithoutChange(async () => { | 
					
						
							|  |  |  |                 for (const tab of filteredTabs) { | 
					
						
							| 
									
										
										
										
											2023-02-14 16:06:49 +01:00
										 |  |  |                     await this.openContextWithNote(tab.notePath, { | 
					
						
							|  |  |  |                         activate: tab.active, | 
					
						
							|  |  |  |                         ntxId: tab.ntxId, | 
					
						
							|  |  |  |                         mainNtxId: tab.mainNtxId, | 
					
						
							|  |  |  |                         hoistedNoteId: tab.hoistedNoteId, | 
					
						
							| 
									
										
										
										
											2023-04-03 23:47:24 +02:00
										 |  |  |                         viewScope: tab.viewScope | 
					
						
							| 
									
										
										
										
											2023-02-14 16:06:49 +01:00
										 |  |  |                     }); | 
					
						
							| 
									
										
										
										
											2022-12-14 10:00:33 +01:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |             }); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-14 10:00:33 +01:00
										 |  |  |             // if there's notePath in the URL, make sure it's open and active
 | 
					
						
							| 
									
										
										
										
											2022-12-22 23:38:57 +01:00
										 |  |  |             // (useful, for e.g. opening clipped notes from clipper or opening link in an extra window)
 | 
					
						
							| 
									
										
										
										
											2023-01-31 23:20:11 +01:00
										 |  |  |             if (notePathInUrl) { | 
					
						
							|  |  |  |                 await appContext.tabManager.switchToNoteContext(ntxIdInUrl, notePathInUrl); | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-12-14 10:00:33 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |         catch (e) { | 
					
						
							| 
									
										
										
										
											2022-12-22 23:38:57 +01:00
										 |  |  |             logError(`Loading tabs '${options.get('openTabs')}' failed: ${e.message} ${e.stack}`); | 
					
						
							| 
									
										
										
										
											2022-12-13 16:57:46 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-14 10:00:33 +01:00
										 |  |  |             // try to recover
 | 
					
						
							|  |  |  |             await this.openEmptyTab(); | 
					
						
							| 
									
										
										
										
											2022-12-13 16:57:46 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-22 12:35:41 +02:00
										 |  |  |     noteSwitchedEvent({noteContext}) { | 
					
						
							| 
									
										
										
										
											2021-05-22 12:26:45 +02:00
										 |  |  |         if (noteContext.isActive()) { | 
					
						
							| 
									
										
										
										
											2020-02-08 21:23:42 +01:00
										 |  |  |             this.setCurrentNotePathToHash(); | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-02-08 21:23:42 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         this.tabsUpdate.scheduleUpdate(); | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-08 21:23:42 +01:00
										 |  |  |     setCurrentNotePathToHash() { | 
					
						
							| 
									
										
										
										
											2021-05-22 12:35:41 +02:00
										 |  |  |         const activeNoteContext = this.getActiveContext(); | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-03-08 17:17:18 +01:00
										 |  |  |         if (window.history.length === 0 // first history entry
 | 
					
						
							| 
									
										
										
										
											2021-05-22 12:26:45 +02:00
										 |  |  |             || (activeNoteContext && activeNoteContext.notePath !== treeService.getHashValueFromAddress()[0])) { | 
					
						
							| 
									
										
										
										
											2022-12-21 15:19:05 +01:00
										 |  |  |             const url = `#${activeNoteContext.notePath || ""}-${activeNoteContext.ntxId}`; | 
					
						
							| 
									
										
										
										
											2020-02-09 21:13:05 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             // using pushState instead of directly modifying document.location because it does not trigger hashchange
 | 
					
						
							|  |  |  |             window.history.pushState(null, "", url); | 
					
						
							| 
									
										
										
										
											2020-10-26 20:11:43 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-02-09 21:13:05 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-03 19:52:24 +01:00
										 |  |  |         this.updateDocumentTitle(activeNoteContext); | 
					
						
							| 
									
										
										
										
											2020-03-08 17:17:18 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         this.triggerEvent('activeNoteChanged'); // trigger this even in on popstate event
 | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-24 14:53:45 +02:00
										 |  |  |     /** @returns {NoteContext[]} */ | 
					
						
							| 
									
										
										
										
											2021-05-22 12:26:45 +02:00
										 |  |  |     getNoteContexts() { | 
					
						
							|  |  |  |         return this.noteContexts; | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-29 22:38:35 +02:00
										 |  |  |     /** @returns {NoteContext[]} */ | 
					
						
							|  |  |  |     getMainNoteContexts() { | 
					
						
							|  |  |  |         return this.noteContexts.filter(nc => nc.isMainContext()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-22 12:26:45 +02:00
										 |  |  |     /** @returns {NoteContext} */ | 
					
						
							|  |  |  |     getNoteContextById(ntxId) { | 
					
						
							|  |  |  |         const noteContext = this.noteContexts.find(nc => nc.ntxId === ntxId); | 
					
						
							| 
									
										
										
										
											2021-05-20 23:13:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-22 12:26:45 +02:00
										 |  |  |         if (!noteContext) { | 
					
						
							|  |  |  |             throw new Error(`Cannot find noteContext id='${ntxId}'`); | 
					
						
							| 
									
										
										
										
											2021-05-20 23:13:34 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-22 12:26:45 +02:00
										 |  |  |         return noteContext; | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-22 12:26:45 +02:00
										 |  |  |     /** @returns {NoteContext} */ | 
					
						
							| 
									
										
										
										
											2021-05-22 12:35:41 +02:00
										 |  |  |     getActiveContext() { | 
					
						
							| 
									
										
										
										
											2021-05-22 13:04:08 +02:00
										 |  |  |         return this.activeNtxId | 
					
						
							|  |  |  |             ? this.getNoteContextById(this.activeNtxId) | 
					
						
							|  |  |  |             : null; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** @returns {NoteContext} */ | 
					
						
							|  |  |  |     getActiveMainContext() { | 
					
						
							|  |  |  |         return this.activeNtxId | 
					
						
							|  |  |  |             ? this.getNoteContextById(this.activeNtxId).getMainContext() | 
					
						
							| 
									
										
										
										
											2021-05-20 23:13:34 +02:00
										 |  |  |             : null; | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** @returns {string|null} */ | 
					
						
							| 
									
										
										
										
											2021-05-22 12:35:41 +02:00
										 |  |  |     getActiveContextNotePath() { | 
					
						
							|  |  |  |         const activeContext = this.getActiveContext(); | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |         return activeContext ? activeContext.notePath : null; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-03 13:35:10 +01:00
										 |  |  |     /** @returns {FNote} */ | 
					
						
							| 
									
										
										
										
											2021-05-22 12:35:41 +02:00
										 |  |  |     getActiveContextNote() { | 
					
						
							|  |  |  |         const activeContext = this.getActiveContext(); | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |         return activeContext ? activeContext.note : null; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-24 14:53:45 +02:00
										 |  |  |     /** @returns {string|null} */ | 
					
						
							| 
									
										
										
										
											2021-05-22 12:35:41 +02:00
										 |  |  |     getActiveContextNoteId() { | 
					
						
							|  |  |  |         const activeNote = this.getActiveContextNote(); | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return activeNote ? activeNote.noteId : null; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-24 14:53:45 +02:00
										 |  |  |     /** @returns {string|null} */ | 
					
						
							| 
									
										
										
										
											2021-05-22 12:35:41 +02:00
										 |  |  |     getActiveContextNoteType() { | 
					
						
							|  |  |  |         const activeNote = this.getActiveContextNote(); | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return activeNote ? activeNote.type : null; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-21 21:41:51 -04:00
										 |  |  |     /** @returns {string|null} */ | 
					
						
							|  |  |  |     getActiveContextNoteMime() { | 
					
						
							|  |  |  |         const activeNote = this.getActiveContextNote(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return activeNote ? activeNote.mime : null; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-22 12:35:41 +02:00
										 |  |  |     async switchToNoteContext(ntxId, notePath) { | 
					
						
							| 
									
										
										
										
											2021-05-22 12:26:45 +02:00
										 |  |  |         const noteContext = this.noteContexts.find(nc => nc.ntxId === ntxId) | 
					
						
							| 
									
										
										
										
											2020-02-29 16:26:46 +01:00
										 |  |  |             || await this.openEmptyTab(); | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-13 16:57:46 +01:00
										 |  |  |         await this.activateNoteContext(noteContext.ntxId); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (notePath) { | 
					
						
							|  |  |  |             await noteContext.setNote(notePath); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async openAndActivateEmptyTab() { | 
					
						
							| 
									
										
										
										
											2021-05-22 12:26:45 +02:00
										 |  |  |         const noteContext = await this.openEmptyTab(); | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-22 12:35:41 +02:00
										 |  |  |         await this.activateNoteContext(noteContext.ntxId); | 
					
						
							| 
									
										
										
										
											2020-02-28 11:46:35 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-22 12:26:45 +02:00
										 |  |  |         await noteContext.setEmpty(); | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-10 20:44:59 +01:00
										 |  |  |     async openEmptyTab(ntxId = null, hoistedNoteId = 'root', mainNtxId = null) { | 
					
						
							| 
									
										
										
										
											2021-05-22 12:26:45 +02:00
										 |  |  |         const noteContext = new NoteContext(ntxId, hoistedNoteId, mainNtxId); | 
					
						
							| 
									
										
										
										
											2021-05-21 22:34:40 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-18 22:05:06 +01:00
										 |  |  |         let existingNoteContext; | 
					
						
							| 
									
										
										
										
											2022-12-13 21:45:57 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (utils.isMobile()) { | 
					
						
							|  |  |  |             // kind of hacky way to enforce a single tab on mobile interface - all requests to create a new one
 | 
					
						
							|  |  |  |             // are forced to reuse the existing ab instead
 | 
					
						
							|  |  |  |             existingNoteContext = this.getActiveContext(); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             existingNoteContext = this.children.find(nc => nc.ntxId === noteContext.ntxId); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-05-21 22:34:40 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-22 12:26:45 +02:00
										 |  |  |         if (existingNoteContext) { | 
					
						
							| 
									
										
										
										
											2022-12-13 21:45:57 +01:00
										 |  |  |             await existingNoteContext.setHoistedNoteId(hoistedNoteId); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-22 12:26:45 +02:00
										 |  |  |             return existingNoteContext; | 
					
						
							| 
									
										
										
										
											2021-05-21 22:34:40 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-22 12:26:45 +02:00
										 |  |  |         this.child(noteContext); | 
					
						
							| 
									
										
										
										
											2020-02-27 10:03:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-22 12:35:41 +02:00
										 |  |  |         await this.triggerEvent('newNoteContextCreated', {noteContext}); | 
					
						
							| 
									
										
										
										
											2020-02-27 10:03:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-22 12:26:45 +02:00
										 |  |  |         return noteContext; | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-19 23:19:47 +01:00
										 |  |  |     async openInNewTab(targetNoteId, hoistedNoteId = null) { | 
					
						
							|  |  |  |         const noteContext = await this.openEmptyTab(null, hoistedNoteId || this.getActiveContext().hoistedNoteId); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await noteContext.setNote(targetNoteId); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async openInSameTab(targetNoteId, hoistedNoteId = null) { | 
					
						
							|  |  |  |         const activeContext = this.getActiveContext(); | 
					
						
							|  |  |  |         await activeContext.setHoistedNoteId(hoistedNoteId || activeContext.hoistedNoteId); | 
					
						
							|  |  |  |         await activeContext.setNote(targetNoteId); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-24 23:24:05 +01:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * If the requested notePath is within current note hoisting scope then keep the note hoisting also for the new tab. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2023-04-03 23:47:24 +02:00
										 |  |  |     async openTabWithNoteWithHoisting(notePath, opts = {}) { | 
					
						
							| 
									
										
										
										
											2021-05-22 12:35:41 +02:00
										 |  |  |         const noteContext = this.getActiveContext(); | 
					
						
							| 
									
										
										
										
											2020-11-24 23:24:05 +01:00
										 |  |  |         let hoistedNoteId = 'root'; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-22 12:26:45 +02:00
										 |  |  |         if (noteContext) { | 
					
						
							|  |  |  |             const resolvedNotePath = await treeService.resolveNotePath(notePath, noteContext.hoistedNoteId); | 
					
						
							| 
									
										
										
										
											2020-11-24 23:24:05 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-21 16:11:00 +01:00
										 |  |  |             if (resolvedNotePath.includes(noteContext.hoistedNoteId) || resolvedNotePath.includes('_hidden')) { | 
					
						
							| 
									
										
										
										
											2021-05-22 12:26:45 +02:00
										 |  |  |                 hoistedNoteId = noteContext.hoistedNoteId; | 
					
						
							| 
									
										
										
										
											2020-11-24 23:24:05 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-04-03 23:47:24 +02:00
										 |  |  |         opts.hoistedNoteId = hoistedNoteId; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return this.openContextWithNote(notePath, opts); | 
					
						
							| 
									
										
										
										
											2020-11-24 23:24:05 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-14 16:06:49 +01:00
										 |  |  |     async openContextWithNote(notePath, opts = {}) { | 
					
						
							|  |  |  |         const activate = !!opts.activate; | 
					
						
							|  |  |  |         const ntxId = opts.ntxId || null; | 
					
						
							|  |  |  |         const mainNtxId = opts.mainNtxId || null; | 
					
						
							|  |  |  |         const hoistedNoteId = opts.hoistedNoteId || 'root'; | 
					
						
							| 
									
										
										
										
											2023-04-03 23:47:24 +02:00
										 |  |  |         const viewScope = opts.viewScope || { viewMode: "default" }; | 
					
						
							| 
									
										
										
										
											2023-02-14 16:06:49 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-22 12:26:45 +02:00
										 |  |  |         const noteContext = await this.openEmptyTab(ntxId, hoistedNoteId, mainNtxId); | 
					
						
							| 
									
										
										
										
											2020-02-27 12:26:42 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-05-05 19:30:03 +02:00
										 |  |  |         if (notePath) { | 
					
						
							| 
									
										
										
										
											2023-02-14 16:06:49 +01:00
										 |  |  |             await noteContext.setNote(notePath, { | 
					
						
							|  |  |  |                 // if activate is false then send normal noteSwitched event
 | 
					
						
							|  |  |  |                 triggerSwitchEvent: !activate, | 
					
						
							| 
									
										
										
										
											2023-04-03 23:47:24 +02:00
										 |  |  |                 viewScope: viewScope | 
					
						
							| 
									
										
										
										
											2023-02-14 16:06:49 +01:00
										 |  |  |             }); | 
					
						
							| 
									
										
										
										
											2020-05-05 19:30:03 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-02-27 12:26:42 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (activate) { | 
					
						
							| 
									
										
										
										
											2021-05-22 12:35:41 +02:00
										 |  |  |             this.activateNoteContext(noteContext.ntxId, false); | 
					
						
							| 
									
										
										
										
											2020-02-27 12:26:42 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-22 12:35:41 +02:00
										 |  |  |             await this.triggerEvent('noteSwitchedAndActivated', { | 
					
						
							| 
									
										
										
										
											2021-05-22 12:26:45 +02:00
										 |  |  |                 noteContext, | 
					
						
							|  |  |  |                 notePath: noteContext.notePath // resolved note path
 | 
					
						
							| 
									
										
										
										
											2020-02-28 00:31:12 +01:00
										 |  |  |             }); | 
					
						
							| 
									
										
										
										
											2020-02-27 12:26:42 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-05-08 23:39:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-22 12:26:45 +02:00
										 |  |  |         return noteContext; | 
					
						
							| 
									
										
										
										
											2020-02-27 12:26:42 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |     async activateOrOpenNote(noteId) { | 
					
						
							| 
									
										
										
										
											2021-05-22 12:26:45 +02:00
										 |  |  |         for (const noteContext of this.getNoteContexts()) { | 
					
						
							|  |  |  |             if (noteContext.note && noteContext.note.noteId === noteId) { | 
					
						
							| 
									
										
										
										
											2021-05-22 12:35:41 +02:00
										 |  |  |                 this.activateNoteContext(noteContext.ntxId); | 
					
						
							| 
									
										
										
										
											2020-04-05 15:35:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // if no tab with this note has been found we'll create new tab
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-02-14 16:06:49 +01:00
										 |  |  |         await this.openContextWithNote(noteId, { activate: true }); | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-24 22:29:49 +02:00
										 |  |  |     async activateNoteContext(ntxId, triggerEvent = true) { | 
					
						
							| 
									
										
										
										
											2021-05-22 13:04:08 +02:00
										 |  |  |         if (ntxId === this.activeNtxId) { | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-22 13:04:08 +02:00
										 |  |  |         this.activeNtxId = ntxId; | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-27 12:26:42 +01:00
										 |  |  |         if (triggerEvent) { | 
					
						
							| 
									
										
										
										
											2021-05-24 22:29:49 +02:00
										 |  |  |             await this.triggerEvent('activeContextChanged', { | 
					
						
							| 
									
										
										
										
											2021-05-22 12:26:45 +02:00
										 |  |  |                 noteContext: this.getNoteContextById(ntxId) | 
					
						
							| 
									
										
										
										
											2020-03-07 13:40:46 +01:00
										 |  |  |             }); | 
					
						
							| 
									
										
										
										
											2020-02-27 12:26:42 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-02-08 21:23:42 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         this.tabsUpdate.scheduleUpdate(); | 
					
						
							| 
									
										
										
										
											2020-05-22 19:30:21 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-08 21:23:42 +01:00
										 |  |  |         this.setCurrentNotePathToHash(); | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-29 22:38:35 +02:00
										 |  |  |     /** | 
					
						
							|  |  |  |      * @param ntxId | 
					
						
							|  |  |  |      * @returns {Promise<boolean>} true if note context has been removed, false otherwise | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-05-22 12:35:41 +02:00
										 |  |  |     async removeNoteContext(ntxId) { | 
					
						
							| 
									
										
										
										
											2022-02-09 21:21:17 +01:00
										 |  |  |         // removing note context is async process which can take some time, if users presses CTRL-W quickly, two
 | 
					
						
							|  |  |  |         // close events could interleave which would then lead to attempting to activate already removed context.
 | 
					
						
							| 
									
										
										
										
											2022-06-29 22:38:35 +02:00
										 |  |  |         return await this.mutex.runExclusively(async () => { | 
					
						
							|  |  |  |             let noteContextToRemove; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             try { | 
					
						
							|  |  |  |                 noteContextToRemove = this.getNoteContextById(ntxId); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             catch { | 
					
						
							|  |  |  |                 // note context not found
 | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-02-09 21:21:17 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if (noteContextToRemove.isMainContext()) { | 
					
						
							|  |  |  |                 const mainNoteContexts = this.getNoteContexts().filter(nc => nc.isMainContext()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (mainNoteContexts.length === 1) { | 
					
						
							| 
									
										
										
										
											2022-12-10 14:35:58 +01:00
										 |  |  |                     if (noteContextToRemove.isEmpty()) { | 
					
						
							|  |  |  |                         // this is already the empty note context, no point in closing it and replacing with another
 | 
					
						
							|  |  |  |                         // empty tab
 | 
					
						
							|  |  |  |                         return false; | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2022-06-02 22:28:25 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-10 14:35:58 +01:00
										 |  |  |                     await this.openEmptyTab(); | 
					
						
							| 
									
										
										
										
											2022-02-09 21:21:17 +01:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2021-10-28 22:27:21 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-05-22 19:30:21 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-09 21:21:17 +01:00
										 |  |  |             // close dangling autocompletes after closing the tab
 | 
					
						
							|  |  |  |             $(".aa-input").autocomplete("close"); | 
					
						
							| 
									
										
										
										
											2021-05-20 23:13:34 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-09 21:21:17 +01:00
										 |  |  |             const noteContextsToRemove = noteContextToRemove.getSubContexts(); | 
					
						
							|  |  |  |             const ntxIdsToRemove = noteContextsToRemove.map(nc => nc.ntxId); | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-02 22:28:25 +02:00
										 |  |  |             await this.triggerEvent('beforeNoteContextRemove', { ntxIds: ntxIdsToRemove }); | 
					
						
							| 
									
										
										
										
											2020-03-07 13:57:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-02-09 21:21:17 +01:00
										 |  |  |             if (!noteContextToRemove.isMainContext()) { | 
					
						
							|  |  |  |                 await this.activateNoteContext(noteContextToRemove.getMainContext().ntxId); | 
					
						
							| 
									
										
										
										
											2020-03-07 13:57:31 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-02-09 21:21:17 +01:00
										 |  |  |             else if (this.mainNoteContexts.length <= 1) { | 
					
						
							|  |  |  |                 await this.openAndActivateEmptyTab(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             else if (ntxIdsToRemove.includes(this.activeNtxId)) { | 
					
						
							|  |  |  |                 const idx = this.mainNoteContexts.findIndex(nc => nc.ntxId === noteContextToRemove.ntxId); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (idx === this.mainNoteContexts.length - 1) { | 
					
						
							|  |  |  |                     await this.activatePreviousTabCommand(); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 else { | 
					
						
							|  |  |  |                     await this.activateNextTabCommand(); | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2020-03-07 13:57:31 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-02 22:28:25 +02:00
										 |  |  |             this.removeNoteContexts(noteContextsToRemove); | 
					
						
							| 
									
										
										
										
											2022-06-29 22:38:35 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             return true; | 
					
						
							| 
									
										
										
										
											2022-06-02 22:28:25 +02:00
										 |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-02 22:28:25 +02:00
										 |  |  |     removeNoteContexts(noteContextsToRemove) { | 
					
						
							|  |  |  |         const ntxIdsToRemove = noteContextsToRemove.map(nc => nc.ntxId); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.children = this.children.filter(nc => !ntxIdsToRemove.includes(nc.ntxId)); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-10 14:35:58 +01:00
										 |  |  |         this.addToRecentlyClosedTabs(noteContextsToRemove); | 
					
						
							| 
									
										
										
										
											2022-06-02 22:28:25 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         this.triggerEvent('noteContextRemoved', {ntxIds: ntxIdsToRemove}); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.tabsUpdate.scheduleUpdate(); | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-10 14:35:58 +01:00
										 |  |  |     addToRecentlyClosedTabs(noteContexts) { | 
					
						
							|  |  |  |         if (noteContexts.length === 1 && noteContexts[0].isEmpty()) { | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-24 13:15:19 +01:00
										 |  |  |         this.recentlyClosedTabs.push(noteContexts); | 
					
						
							| 
									
										
										
										
											2022-12-10 14:35:58 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-22 12:26:45 +02:00
										 |  |  |     tabReorderEvent({ntxIdsInOrder}) { | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |         const order = {}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-24 21:05:44 +02:00
										 |  |  |         let i = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-24 21:43:24 +02:00
										 |  |  |         for (const ntxId of ntxIdsInOrder) { | 
					
						
							|  |  |  |             for (const noteContext of this.getNoteContextById(ntxId).getSubContexts()) { | 
					
						
							| 
									
										
										
										
											2021-05-24 21:05:44 +02:00
										 |  |  |                 order[noteContext.ntxId] = i++; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.children.sort((a, b) => order[a.ntxId] < order[b.ntxId] ? -1 : 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.tabsUpdate.scheduleUpdate(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     noteContextReorderEvent({ntxIdsInOrder}) { | 
					
						
							|  |  |  |         const order = {}; | 
					
						
							|  |  |  |         let i = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-27 21:32:03 +02:00
										 |  |  |         for (const ntxId of ntxIdsInOrder) { | 
					
						
							| 
									
										
										
										
											2021-05-24 21:05:44 +02:00
										 |  |  |             order[ntxId] = i++; | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-22 12:26:45 +02:00
										 |  |  |         this.children.sort((a, b) => order[a.ntxId] < order[b.ntxId] ? -1 : 1); | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-08 21:23:42 +01:00
										 |  |  |         this.tabsUpdate.scheduleUpdate(); | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-05 15:50:21 +02:00
										 |  |  |     async activateNextTabCommand() { | 
					
						
							| 
									
										
										
										
											2021-07-24 22:51:12 +02:00
										 |  |  |         const activeMainNtxId = this.getActiveMainContext().ntxId; | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-24 22:51:12 +02:00
										 |  |  |         const oldIdx = this.mainNoteContexts.findIndex(nc => nc.ntxId === activeMainNtxId); | 
					
						
							|  |  |  |         const newActiveNtxId = this.mainNoteContexts[oldIdx === this.mainNoteContexts.length - 1 ? 0 : oldIdx + 1].ntxId; | 
					
						
							| 
									
										
										
										
											2021-07-20 13:29:11 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         await this.activateNoteContext(newActiveNtxId); | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-05 15:50:21 +02:00
										 |  |  |     async activatePreviousTabCommand() { | 
					
						
							| 
									
										
										
										
											2021-07-24 22:51:12 +02:00
										 |  |  |         const activeMainNtxId = this.getActiveMainContext().ntxId; | 
					
						
							| 
									
										
										
										
											2021-07-20 13:29:11 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-24 22:51:12 +02:00
										 |  |  |         const oldIdx = this.mainNoteContexts.findIndex(nc => nc.ntxId === activeMainNtxId); | 
					
						
							|  |  |  |         const newActiveNtxId = this.mainNoteContexts[oldIdx === 0 ? this.mainNoteContexts.length - 1 : oldIdx - 1].ntxId; | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-20 13:29:11 +02:00
										 |  |  |         await this.activateNoteContext(newActiveNtxId); | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-05 15:50:21 +02:00
										 |  |  |     async closeActiveTabCommand() { | 
					
						
							|  |  |  |         await this.removeNoteContext(this.activeNtxId); | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-16 19:23:49 +01:00
										 |  |  |     beforeUnloadEvent() { | 
					
						
							| 
									
										
										
										
											2020-02-08 20:53:07 +01:00
										 |  |  |         this.tabsUpdate.updateNowIfNecessary(); | 
					
						
							| 
									
										
										
										
											2021-02-27 23:39:02 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return true; // don't block closing the tab, this metadata is not that important
 | 
					
						
							| 
									
										
										
										
											2020-02-08 20:53:07 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-16 19:54:11 +01:00
										 |  |  |     openNewTabCommand() { | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |         this.openAndActivateEmptyTab(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 13:58:51 +01:00
										 |  |  |     async closeAllTabsCommand() { | 
					
						
							| 
									
										
										
										
											2021-10-03 23:01:22 +02:00
										 |  |  |         for (const ntxIdToRemove of this.mainNoteContexts.map(nc => nc.ntxId)) { | 
					
						
							| 
									
										
										
										
											2021-05-22 12:35:41 +02:00
										 |  |  |             await this.removeNoteContext(ntxIdToRemove); | 
					
						
							| 
									
										
										
										
											2020-02-09 21:13:05 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-02-07 21:08:55 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 13:58:51 +01:00
										 |  |  |     async closeOtherTabsCommand({ntxId}) { | 
					
						
							| 
									
										
										
										
											2021-10-03 23:01:22 +02:00
										 |  |  |         for (const ntxIdToRemove of this.mainNoteContexts.map(nc => nc.ntxId)) { | 
					
						
							| 
									
										
										
										
											2021-05-22 12:26:45 +02:00
										 |  |  |             if (ntxIdToRemove !== ntxId) { | 
					
						
							| 
									
										
										
										
											2021-05-22 12:35:41 +02:00
										 |  |  |                 await this.removeNoteContext(ntxIdToRemove); | 
					
						
							| 
									
										
										
										
											2020-02-09 21:13:05 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-01-08 13:58:51 +01:00
										 |  |  |     async closeTabCommand({ntxId}) { | 
					
						
							|  |  |  |         await this.removeNoteContext(ntxId); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-29 22:38:35 +02:00
										 |  |  |     async moveTabToNewWindowCommand({ntxId}) { | 
					
						
							| 
									
										
										
										
											2021-05-22 12:26:45 +02:00
										 |  |  |         const {notePath, hoistedNoteId} = this.getNoteContextById(ntxId); | 
					
						
							| 
									
										
										
										
											2020-04-26 23:11:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-29 22:38:35 +02:00
										 |  |  |         const removed = await this.removeNoteContext(ntxId); | 
					
						
							| 
									
										
										
										
											2020-04-26 23:11:52 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-29 22:38:35 +02:00
										 |  |  |         if (removed) { | 
					
						
							|  |  |  |             this.triggerCommand('openInWindow', {notePath, hoistedNoteId}); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2020-04-26 23:11:52 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-11-24 22:32:22 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-09 21:20:12 +02:00
										 |  |  |     async reopenLastTabCommand() { | 
					
						
							| 
									
										
										
										
											2022-12-10 14:35:58 +01:00
										 |  |  |         let closeLastEmptyTab = null; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         await this.mutex.runExclusively(async () => { | 
					
						
							|  |  |  |             if (this.recentlyClosedTabs.length === 0) { | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (this.noteContexts.length === 1 && this.noteContexts[0].isEmpty()) { | 
					
						
							|  |  |  |                 // new empty tab is created after closing the last tab, this reverses the empty tab creation
 | 
					
						
							|  |  |  |                 closeLastEmptyTab = this.noteContexts[0]; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-09 22:03:24 +02:00
										 |  |  |             const noteContexts = this.recentlyClosedTabs.pop(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             for (const noteContext of noteContexts) { | 
					
						
							|  |  |  |                 this.child(noteContext); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 await this.triggerEvent('newNoteContextCreated', {noteContext}); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             const noteContextToActivate = noteContexts.length === 1 | 
					
						
							|  |  |  |                 ? noteContexts[0] | 
					
						
							|  |  |  |                 : noteContexts.find(nc => nc.isMainContext()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-10 14:35:58 +01:00
										 |  |  |             await this.activateNoteContext(noteContextToActivate.ntxId); | 
					
						
							| 
									
										
										
										
											2021-10-09 21:20:12 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             await this.triggerEvent('noteSwitched', { | 
					
						
							| 
									
										
										
										
											2021-10-09 22:03:24 +02:00
										 |  |  |                 noteContext: noteContextToActivate, | 
					
						
							|  |  |  |                 notePath: noteContextToActivate.notePath | 
					
						
							| 
									
										
										
										
											2021-10-09 21:20:12 +02:00
										 |  |  |             }); | 
					
						
							| 
									
										
										
										
											2022-12-10 14:35:58 +01:00
										 |  |  |         }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (closeLastEmptyTab) { | 
					
						
							|  |  |  |             await this.removeNoteContext(closeLastEmptyTab.ntxId); | 
					
						
							| 
									
										
										
										
											2021-10-09 21:20:12 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-24 22:32:22 +01:00
										 |  |  |     hoistedNoteChangedEvent() { | 
					
						
							|  |  |  |         this.tabsUpdate.scheduleUpdate(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-01-03 19:52:24 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     updateDocumentTitle(activeNoteContext) { | 
					
						
							|  |  |  |         const titleFragments = [ | 
					
						
							| 
									
										
										
										
											2022-07-05 22:40:41 +02:00
										 |  |  |             // it helps to navigate in history if note title is included in the title
 | 
					
						
							| 
									
										
										
										
											2022-01-03 19:52:24 +01:00
										 |  |  |             activeNoteContext.note?.title, | 
					
						
							|  |  |  |             "Trilium Notes" | 
					
						
							|  |  |  |         ].filter(Boolean); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         document.title = titleFragments.join(" - "); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     entitiesReloadedEvent({loadResults}) { | 
					
						
							|  |  |  |         const activeContext = this.getActiveContext(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (activeContext && loadResults.isNoteReloaded(activeContext.noteId)) { | 
					
						
							|  |  |  |             this.updateDocumentTitle(activeContext); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-05-22 19:30:21 +02:00
										 |  |  | } |