mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 10:26:08 +01:00 
			
		
		
		
	navigation state is more nicely and completely serialized into URL
This commit is contained in:
		| @@ -155,14 +155,14 @@ $(window).on('beforeunload', () => { | ||||
|  | ||||
| $(window).on('hashchange', function() { | ||||
|     if (treeService.isNotePathInAddress()) { | ||||
|         const [notePath, ntxId] = treeService.getHashValueFromAddress(); | ||||
|         const {notePath, ntxId, viewScope} = treeService.parseNavigationStateFromAddress(); | ||||
|  | ||||
|         if (!notePath && !ntxId) { | ||||
|             console.log(`Invalid hash value "${document.location.hash}", ignoring.`); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         appContext.tabManager.switchToNoteContext(ntxId, notePath); | ||||
|         appContext.tabManager.switchToNoteContext(ntxId, notePath, viewScope); | ||||
|     } | ||||
| }); | ||||
|  | ||||
|   | ||||
| @@ -8,6 +8,7 @@ import toastService from "../services/toast.js"; | ||||
| import ws from "../services/ws.js"; | ||||
| import bundleService from "../services/bundle.js"; | ||||
| import froca from "../services/froca.js"; | ||||
| import linkService from "../services/link.js"; | ||||
|  | ||||
| export default class Entrypoints extends Component { | ||||
|     constructor() { | ||||
| @@ -136,17 +137,15 @@ export default class Entrypoints extends Component { | ||||
|     } | ||||
|  | ||||
|     async openInWindowCommand({notePath, hoistedNoteId, viewScope}) { | ||||
|         if (!hoistedNoteId) { | ||||
|             hoistedNoteId = 'root'; | ||||
|         } | ||||
|         const extraWindowHash = linkService.calculateHash({notePath, hoistedNoteId, viewScope}); | ||||
|  | ||||
|         if (utils.isElectron()) { | ||||
|             const {ipcRenderer} = utils.dynamicRequire('electron'); | ||||
|  | ||||
|             ipcRenderer.send('create-extra-window', {notePath, hoistedNoteId, viewScope}); | ||||
|             ipcRenderer.send('create-extra-window', { extraWindowHash }); | ||||
|         } | ||||
|         else { | ||||
|             const url = `${window.location.protocol}//${window.location.host}${window.location.pathname}?extraWindow=1&extraHoistedNoteId=${hoistedNoteId}&extraViewScope=${JSON.stringify(viewScope)}#${notePath}`; | ||||
|             const url = `${window.location.protocol}//${window.location.host}${window.location.pathname}?extraWindow=1${extraWindowHash}`; | ||||
|  | ||||
|             window.open(url, '', 'width=1000,height=800'); | ||||
|         } | ||||
|   | ||||
| @@ -12,13 +12,17 @@ class NoteContext extends Component { | ||||
|     constructor(ntxId = null, hoistedNoteId = 'root', mainNtxId = null) { | ||||
|         super(); | ||||
|  | ||||
|         this.ntxId = ntxId || utils.randomString(4); | ||||
|         this.ntxId = ntxId || this.constructor.generateNtxId(); | ||||
|         this.hoistedNoteId = hoistedNoteId; | ||||
|         this.mainNtxId = mainNtxId; | ||||
|  | ||||
|         this.resetViewScope(); | ||||
|     } | ||||
|  | ||||
|     static generateNtxId() { | ||||
|         return utils.randomString(6); | ||||
|     } | ||||
|  | ||||
|     setEmpty() { | ||||
|         this.notePath = null; | ||||
|         this.noteId = null; | ||||
| @@ -57,9 +61,8 @@ class NoteContext extends Component { | ||||
|         utils.closeActiveDialog(); | ||||
|  | ||||
|         this.notePath = resolvedNotePath; | ||||
|         ({noteId: this.noteId, parentNoteId: this.parentNoteId} = treeService.getNoteIdAndParentIdFromNotePath(resolvedNotePath)); | ||||
|  | ||||
|         this.viewScope = opts.viewScope; | ||||
|         ({noteId: this.noteId, parentNoteId: this.parentNoteId} = treeService.getNoteIdAndParentIdFromNotePath(resolvedNotePath)); | ||||
|  | ||||
|         this.saveToRecentNotes(resolvedNotePath); | ||||
|  | ||||
| @@ -298,6 +301,29 @@ class NoteContext extends Component { | ||||
|         // this is reset after navigating to a different note | ||||
|         this.viewScope = {}; | ||||
|     } | ||||
|  | ||||
|     async getNavigationTitle() { | ||||
|         if (!this.note) { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         const { note, viewScope } = this; | ||||
|  | ||||
|         let title = viewScope.viewMode === 'default' | ||||
|             ? note.title | ||||
|             : `${note.title}: ${viewScope.viewMode}`; | ||||
|  | ||||
|         if (viewScope.attachmentId) { | ||||
|             // assuming the attachment has been already loaded | ||||
|             const attachment = await note.getAttachmentById(viewScope.attachmentId); | ||||
|  | ||||
|             if (attachment) { | ||||
|                 title += `: ${attachment.title}`; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return title; | ||||
|     } | ||||
| } | ||||
|  | ||||
| export default NoteContext; | ||||
|   | ||||
| @@ -8,6 +8,7 @@ import utils from "../services/utils.js"; | ||||
| import NoteContext from "./note_context.js"; | ||||
| import appContext from "./app_context.js"; | ||||
| import Mutex from "../utils/mutex.js"; | ||||
| import linkService from "../services/link.js"; | ||||
|  | ||||
| export default class TabManager extends Component { | ||||
|     constructor() { | ||||
| @@ -53,45 +54,44 @@ export default class TabManager extends Component { | ||||
|                 ? (options.getJson('openTabs') || []) | ||||
|                 : []; | ||||
|  | ||||
|             let filteredTabs = []; | ||||
|  | ||||
|             // preload all notes at once | ||||
|             await froca.getNotes([ | ||||
|                     ...tabsToOpen.map(tab => treeService.getNoteIdFromNotePath(tab.notePath)), | ||||
|                     ...tabsToOpen.map(tab => tab.hoistedNoteId), | ||||
|             ], true); | ||||
|  | ||||
|             for (const openTab of tabsToOpen) { | ||||
|                 if (openTab.notePath && !(treeService.getNoteIdFromNotePath(openTab.notePath) in froca.notes)) { | ||||
|             const filteredTabs = tabsToOpen.filter(openTab => { | ||||
|                 if (utils.isMobile()) { // mobile frontend doesn't have tabs so show only the active tab | ||||
|                     return !!openTab.active; | ||||
|                 } | ||||
|  | ||||
|                 const noteId = treeService.getNoteIdFromNotePath(openTab.notePath); | ||||
|                 if (!(noteId in froca.notes)) { | ||||
|                     // note doesn't exist so don't try to open tab for it | ||||
|                     continue; | ||||
|                     return false; | ||||
|                 } | ||||
|  | ||||
|                 if (!(openTab.hoistedNoteId in froca.notes)) { | ||||
|                     openTab.hoistedNoteId = 'root'; | ||||
|                 } | ||||
|  | ||||
|                 filteredTabs.push(openTab); | ||||
|             } | ||||
|  | ||||
|             if (utils.isMobile()) { | ||||
|                 // mobile frontend doesn't have tabs so show only the active tab | ||||
|                 filteredTabs = filteredTabs.filter(tab => tab.active); | ||||
|             } | ||||
|                 return true; | ||||
|             }); | ||||
|  | ||||
|             // resolve before opened tabs can change this | ||||
|             const [notePathInUrl, ntxIdInUrl] = treeService.getHashValueFromAddress(); | ||||
|             const parsedFromUrl = treeService.parseNavigationStateFromAddress(); | ||||
|  | ||||
|             if (filteredTabs.length === 0) { | ||||
|                 filteredTabs.push({ | ||||
|                     notePath: notePathInUrl || 'root', | ||||
|                     active: true, | ||||
|                     hoistedNoteId: glob.extraHoistedNoteId || 'root', | ||||
|                     viewScope: glob.extraViewScope || {} | ||||
|                 }); | ||||
|             } | ||||
|                 parsedFromUrl.ntxId = parsedFromUrl.ntxId || NoteContext.generateNtxId(); // generate already here, so that we later know which one to activate | ||||
|  | ||||
|             if (!filteredTabs.find(tab => tab.active)) { | ||||
|                 filteredTabs.push({ | ||||
|                     notePath: parsedFromUrl.notePath || 'root', | ||||
|                     ntxId: parsedFromUrl.ntxId, | ||||
|                     active: true, | ||||
|                     hoistedNoteId: parsedFromUrl.hoistedNoteId || 'root', | ||||
|                     viewScope: parsedFromUrl.viewScope || {} | ||||
|                 }); | ||||
|             } else if (!filteredTabs.find(tab => tab.active)) { | ||||
|                 filteredTabs[0].active = true; | ||||
|             } | ||||
|  | ||||
| @@ -109,8 +109,13 @@ export default class TabManager extends Component { | ||||
|  | ||||
|             // if there's notePath in the URL, make sure it's open and active | ||||
|             // (useful, for e.g. opening clipped notes from clipper or opening link in an extra window) | ||||
|             if (notePathInUrl) { | ||||
|                 await appContext.tabManager.switchToNoteContext(ntxIdInUrl, notePathInUrl); | ||||
|             if (parsedFromUrl.notePath) { | ||||
|                 await appContext.tabManager.switchToNoteContext( | ||||
|                     parsedFromUrl.ntxId, | ||||
|                     parsedFromUrl.notePath, | ||||
|                     parsedFromUrl.viewScope, | ||||
|                     parsedFromUrl.hoistedNoteId | ||||
|                 ); | ||||
|             } | ||||
|         } | ||||
|         catch (e) { | ||||
| @@ -123,28 +128,41 @@ export default class TabManager extends Component { | ||||
|  | ||||
|     noteSwitchedEvent({noteContext}) { | ||||
|         if (noteContext.isActive()) { | ||||
|             this.setCurrentNotePathToHash(); | ||||
|             this.setCurrentNavigationStateToHash(); | ||||
|         } | ||||
|  | ||||
|         this.tabsUpdate.scheduleUpdate(); | ||||
|     } | ||||
|  | ||||
|     setCurrentNotePathToHash() { | ||||
|         const activeNoteContext = this.getActiveContext(); | ||||
|  | ||||
|         if (window.history.length === 0 // first history entry | ||||
|             || (activeNoteContext && activeNoteContext.notePath !== treeService.getHashValueFromAddress()[0])) { | ||||
|             const url = `#${activeNoteContext.notePath || ""}-${activeNoteContext.ntxId}`; | ||||
|     setCurrentNavigationStateToHash() { | ||||
|         const calculatedHash = this.calculateHash(); | ||||
|  | ||||
|         // update if it's the first history entry or there has been a change | ||||
|         if (window.history.length === 0 || calculatedHash !== window.location?.hash) { | ||||
|             // using pushState instead of directly modifying document.location because it does not trigger hashchange | ||||
|             window.history.pushState(null, "", url); | ||||
|             window.history.pushState(null, "", calculatedHash); | ||||
|         } | ||||
|  | ||||
|         const activeNoteContext = this.getActiveContext(); | ||||
|         this.updateDocumentTitle(activeNoteContext); | ||||
|  | ||||
|         this.triggerEvent('activeNoteChanged'); // trigger this even in on popstate event | ||||
|     } | ||||
|  | ||||
|     calculateHash() { | ||||
|         const activeNoteContext = this.getActiveContext(); | ||||
|         if (!activeNoteContext) { | ||||
|             return ""; | ||||
|         } | ||||
|  | ||||
|         return linkService.calculateHash({ | ||||
|             notePath: activeNoteContext.notePath, | ||||
|             ntxId: activeNoteContext.ntxId, | ||||
|             hoistedNoteId: activeNoteContext.hoistedNoteId, | ||||
|             viewScope: activeNoteContext.viewScope | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     /** @returns {NoteContext[]} */ | ||||
|     getNoteContexts() { | ||||
|         return this.noteContexts; | ||||
| @@ -212,14 +230,18 @@ export default class TabManager extends Component { | ||||
|         return activeNote ? activeNote.mime : null; | ||||
|     } | ||||
|  | ||||
|     async switchToNoteContext(ntxId, notePath) { | ||||
|     async switchToNoteContext(ntxId, notePath, viewScope = {}, hoistedNoteId = null) { | ||||
|         const noteContext = this.noteContexts.find(nc => nc.ntxId === ntxId) | ||||
|             || await this.openEmptyTab(); | ||||
|  | ||||
|         await this.activateNoteContext(noteContext.ntxId); | ||||
|  | ||||
|         if (hoistedNoteId) { | ||||
|             await noteContext.setHoistedNoteId(hoistedNoteId); | ||||
|         } | ||||
|  | ||||
|         if (notePath) { | ||||
|             await noteContext.setNote(notePath); | ||||
|             await noteContext.setNote(notePath, { viewScope }); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -347,7 +369,7 @@ export default class TabManager extends Component { | ||||
|  | ||||
|         this.tabsUpdate.scheduleUpdate(); | ||||
|  | ||||
|         this.setCurrentNotePathToHash(); | ||||
|         this.setCurrentNavigationStateToHash(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -564,21 +586,21 @@ export default class TabManager extends Component { | ||||
|         this.tabsUpdate.scheduleUpdate(); | ||||
|     } | ||||
|  | ||||
|     updateDocumentTitle(activeNoteContext) { | ||||
|     async updateDocumentTitle(activeNoteContext) { | ||||
|         const titleFragments = [ | ||||
|             // it helps to navigate in history if note title is included in the title | ||||
|             activeNoteContext.note?.title, | ||||
|             await activeNoteContext.getNavigationTitle(), | ||||
|             "Trilium Notes" | ||||
|         ].filter(Boolean); | ||||
|  | ||||
|         document.title = titleFragments.join(" - "); | ||||
|     } | ||||
|  | ||||
|     entitiesReloadedEvent({loadResults}) { | ||||
|     async entitiesReloadedEvent({loadResults}) { | ||||
|         const activeContext = this.getActiveContext(); | ||||
|  | ||||
|         if (activeContext && loadResults.isNoteReloaded(activeContext.noteId)) { | ||||
|             this.updateDocumentTitle(activeContext); | ||||
|             await this.updateDocumentTitle(activeContext); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -99,6 +99,37 @@ function parseNotePathAndScope($link) { | ||||
|     }; | ||||
| } | ||||
|  | ||||
| function calculateHash({notePath, ntxId, hoistedNoteId, viewScope = {}}) { | ||||
|     notePath = notePath || ""; | ||||
|     const params = [ | ||||
|         ntxId ? { ntxId: ntxId } : null, | ||||
|         (hoistedNoteId && hoistedNoteId !== 'root') ? { hoistedNoteId: hoistedNoteId } : null, | ||||
|         viewScope.viewMode !== 'default' ? { viewMode: viewScope.viewMode } : null, | ||||
|         viewScope.attachmentId ? { attachmentId: viewScope.attachmentId } : null | ||||
|     ].filter(p => !!p); | ||||
|  | ||||
|     const paramStr = params.map(pair => { | ||||
|         const name = Object.keys(pair)[0]; | ||||
|         const value = pair[name]; | ||||
|  | ||||
|         return `${encodeURIComponent(name)}=${encodeURIComponent(value)}`; | ||||
|     }).join("&"); | ||||
|  | ||||
|     if (!notePath && !paramStr) { | ||||
|         return ""; | ||||
|     } | ||||
|  | ||||
|     let hash = `#${notePath}`; | ||||
|  | ||||
|     if (paramStr) { | ||||
|         hash += `?${paramStr}`; | ||||
|     } | ||||
|  | ||||
|     console.log(hash); | ||||
|  | ||||
|     return hash; | ||||
| } | ||||
|  | ||||
| function goToLink(evt) { | ||||
|     const $link = $(evt.target).closest("a,.block-link"); | ||||
|     const hrefLink = $link.attr('href'); | ||||
| @@ -223,5 +254,6 @@ export default { | ||||
|     createNoteLink, | ||||
|     goToLink, | ||||
|     loadReferenceLinkTitle, | ||||
|     parseNotePathAndScope | ||||
|     parseNotePathAndScope, | ||||
|     calculateHash | ||||
| }; | ||||
|   | ||||
| @@ -23,8 +23,8 @@ async function resolveNotePath(notePath, hoistedNoteId = 'root') { | ||||
| async function resolveNotePathToSegments(notePath, hoistedNoteId = 'root', logErrors = true) { | ||||
|     utils.assertArguments(notePath); | ||||
|  | ||||
|     // we might get notePath with the ntxId suffix, remove it if present | ||||
|     notePath = notePath.split("-")[0].trim(); | ||||
|     // we might get notePath with the params suffix, remove it if present | ||||
|     notePath = notePath.split("?")[0].trim(); | ||||
|  | ||||
|     if (notePath.length === 0) { | ||||
|         return; | ||||
| @@ -159,8 +159,8 @@ function getNoteIdFromNotePath(notePath) { | ||||
|  | ||||
|     const lastSegment = path[path.length - 1]; | ||||
|  | ||||
|     // path could have also ntxId suffix | ||||
|     return lastSegment.split("-")[0]; | ||||
|     // path could have also params suffix | ||||
|     return lastSegment.split("?")[0]; | ||||
| } | ||||
|  | ||||
| async function getBranchIdFromNotePath(notePath) { | ||||
| @@ -185,8 +185,8 @@ function getNoteIdAndParentIdFromNotePath(notePath) { | ||||
|  | ||||
|         const lastSegment = path[path.length - 1]; | ||||
|  | ||||
|         // path could have also ntxId suffix | ||||
|         noteId = lastSegment.split("-")[0]; | ||||
|         // path could have also params suffix | ||||
|         noteId = lastSegment.split("?")[0]; | ||||
|  | ||||
|         if (path.length > 1) { | ||||
|             parentNoteId = path[path.length - 2]; | ||||
| @@ -297,14 +297,44 @@ async function getNoteTitleWithPathAsSuffix(notePath) { | ||||
|     return $titleWithPath; | ||||
| } | ||||
|  | ||||
| function getHashValueFromAddress() { | ||||
|     const str = document.location.hash ? document.location.hash.substr(1) : ""; // strip initial # | ||||
| function parseNavigationStateFromAddress() { | ||||
|     const str = document.location.hash?.substr(1) || ""; // strip initial # | ||||
|  | ||||
|     return str.split("-"); | ||||
|     const [notePath, paramString] = str.split("?"); | ||||
|     const viewScope = { | ||||
|         viewMode: 'default' | ||||
|     }; | ||||
|     let ntxId = null; | ||||
|     let hoistedNoteId = null; | ||||
|  | ||||
|     if (paramString) { | ||||
|         for (const pair of paramString.split("&")) { | ||||
|             let [name, value] = pair.split("="); | ||||
|             name = decodeURIComponent(name); | ||||
|             value = decodeURIComponent(value); | ||||
|  | ||||
|             if (name === 'ntxId') { | ||||
|                 ntxId = value; | ||||
|             } else if (name === 'hoistedNoteId') { | ||||
|                 hoistedNoteId = value; | ||||
|             } else if (['viewMode', 'attachmentId'].includes(name)) { | ||||
|                 viewScope[name] = value; | ||||
|             } else { | ||||
|                 console.warn(`Unrecognized hash parameter '${name}'.`); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return { | ||||
|         notePath, | ||||
|         ntxId, | ||||
|         hoistedNoteId, | ||||
|         viewScope | ||||
|     }; | ||||
| } | ||||
|  | ||||
| function isNotePathInAddress() { | ||||
|     const [notePath, ntxId] = getHashValueFromAddress(); | ||||
|     const {notePath, ntxId} = parseNavigationStateFromAddress(); | ||||
|  | ||||
|     return notePath.startsWith("root") | ||||
|         // empty string is for empty/uninitialized tab | ||||
| @@ -338,7 +368,7 @@ export default { | ||||
|     getNoteTitle, | ||||
|     getNotePathTitle, | ||||
|     getNoteTitleWithPathAsSuffix, | ||||
|     getHashValueFromAddress, | ||||
|     parseNavigationStateFromAddress, | ||||
|     isNotePathInAddress, | ||||
|     parseNotePath, | ||||
|     isNotePathInHiddenSubtree | ||||
|   | ||||
| @@ -55,6 +55,7 @@ export default class HistoryNavigationButton extends ButtonFromNoteWidget { | ||||
|         for (const idx in this.webContents.history) { | ||||
|             const url = this.webContents.history[idx]; | ||||
|             const [_, notePathWithTab] = url.split('#'); | ||||
|             // broken: use treeService.parseNavigationStateFromAddress(); | ||||
|             const [notePath, ntxId] = notePathWithTab.split('-'); | ||||
|  | ||||
|             const title = await treeService.getNotePathTitle(notePath); | ||||
|   | ||||
| @@ -70,37 +70,20 @@ export default class NoteTitleWidget extends NoteContextAwareWidget { | ||||
|     } | ||||
|  | ||||
|     async refreshWithNote(note) { | ||||
|         this.$noteTitle.val(await this.getTitleText(note)); | ||||
|  | ||||
|         this.$noteTitle.prop("readonly", | ||||
|             (note.isProtected && !protectedSessionHolder.isProtectedSessionAvailable()) | ||||
|         const isReadOnly = (note.isProtected && !protectedSessionHolder.isProtectedSessionAvailable()) | ||||
|             || ['_lbRoot', '_lbAvailableLaunchers', '_lbVisibleLaunchers'].includes(note.noteId) | ||||
|             || this.noteContext.viewScope.viewMode !== 'default' | ||||
|             || this.noteContext.viewScope.viewMode !== 'default'; | ||||
|  | ||||
|         this.$noteTitle.val( | ||||
|             isReadOnly | ||||
|                 ? await this.noteContext.getNavigationTitle() | ||||
|                 : note.title | ||||
|         ); | ||||
|         this.$noteTitle.prop("readonly", isReadOnly); | ||||
|  | ||||
|         this.setProtectedStatus(note); | ||||
|     } | ||||
|  | ||||
|     /** @param {FNote} note */ | ||||
|     async getTitleText(note) { | ||||
|         const viewScope = this.noteContext.viewScope; | ||||
|  | ||||
|         let title = viewScope.viewMode === 'default' | ||||
|             ? note.title | ||||
|             : `${note.title}: ${viewScope.viewMode}`; | ||||
|  | ||||
|         if (viewScope.attachmentId) { | ||||
|             // assuming the attachment has been already loaded | ||||
|             const attachment = await note.getAttachmentById(viewScope.attachmentId); | ||||
|  | ||||
|             if (attachment) { | ||||
|                 title += `: ${attachment.title}`; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return title; | ||||
|     } | ||||
|  | ||||
|     /** @param {FNote} note */ | ||||
|     setProtectedStatus(note) { | ||||
|         this.$noteTitle.toggleClass("protected", !!note.isProtected); | ||||
|   | ||||
| @@ -618,7 +618,7 @@ export default class TabRowWidget extends BasicWidget { | ||||
|     } | ||||
|  | ||||
|     /** @param {NoteContext} noteContext */ | ||||
|     updateTab($tab, noteContext) { | ||||
|     async updateTab($tab, noteContext) { | ||||
|         if (!$tab.length) { | ||||
|             return; | ||||
|         } | ||||
| @@ -652,11 +652,7 @@ export default class TabRowWidget extends BasicWidget { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         const viewMode = noteContext.viewScope?.viewMode; | ||||
|         const title = (viewMode && viewMode !== 'default') | ||||
|             ? `${viewMode}: ${note.title}` | ||||
|             : note.title; | ||||
|  | ||||
|         const title = await noteContext.getNavigationTitle(); | ||||
|         this.updateTitle($tab, title); | ||||
|  | ||||
|         $tab.addClass(note.getCssClass()); | ||||
|   | ||||
| @@ -35,9 +35,6 @@ function index(req, res) { | ||||
|         appCssNoteIds: getAppCssNoteIds(), | ||||
|         isDev: env.isDev(), | ||||
|         isMainWindow: !req.query.extraWindow, | ||||
|         extraHoistedNoteId: req.query.extraHoistedNoteId, | ||||
|         // make sure only valid JSON gets rendered | ||||
|         extraViewScope: JSON.stringify(req.query.extraViewScope ? JSON.parse(req.query.extraViewScope) : {}), | ||||
|         isProtectedSessionAvailable: protectedSessionService.isProtectedSessionAvailable(), | ||||
|         maxContentWidth: parseInt(options.maxContentWidth), | ||||
|         triliumVersion: packageJson.version, | ||||
|   | ||||
| @@ -15,7 +15,7 @@ let mainWindow; | ||||
| /** @type {Electron.BrowserWindow} */ | ||||
| let setupWindow; | ||||
|  | ||||
| async function createExtraWindow(notePath, hoistedNoteId = 'root', viewScope = {}) { | ||||
| async function createExtraWindow(extraWindowHash) { | ||||
|     const spellcheckEnabled = optionService.getOptionBool('spellCheckEnabled'); | ||||
|  | ||||
|     const {BrowserWindow} = require('electron'); | ||||
| @@ -35,13 +35,13 @@ async function createExtraWindow(notePath, hoistedNoteId = 'root', viewScope = { | ||||
|     }); | ||||
|  | ||||
|     win.setMenuBarVisibility(false); | ||||
|     win.loadURL(`http://127.0.0.1:${port}/?extraWindow=1&extraHoistedNoteId=${hoistedNoteId}&extraViewScope=${JSON.stringify(viewScope)}#${notePath}`); | ||||
|     win.loadURL(`http://127.0.0.1:${port}/?extraWindow=1${extraWindowHash}`); | ||||
|  | ||||
|     configureWebContents(win.webContents, spellcheckEnabled); | ||||
| } | ||||
|  | ||||
| ipcMain.on('create-extra-window', (event, arg) => { | ||||
|     createExtraWindow(arg.notePath, arg.hoistedNoteId, arg.viewScope); | ||||
|     createExtraWindow(arg.extraWindowHash); | ||||
| }); | ||||
|  | ||||
| async function createMainWindow(app) { | ||||
|   | ||||
| @@ -32,8 +32,6 @@ | ||||
|         isDev: <%= isDev %>, | ||||
|         appCssNoteIds: <%- JSON.stringify(appCssNoteIds) %>, | ||||
|         isMainWindow: <%= isMainWindow %>, | ||||
|         extraHoistedNoteId: '<%= extraHoistedNoteId %>', | ||||
|         extraViewScope: <%- extraViewScope %>, | ||||
|         isProtectedSessionAvailable: <%= isProtectedSessionAvailable %>, | ||||
|         triliumVersion: "<%= triliumVersion %>", | ||||
|         assetPath: "<%= assetPath %>", | ||||
|   | ||||
		Reference in New Issue
	
	Block a user