mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 10:26:08 +01:00 
			
		
		
		
	wip attachment support
This commit is contained in:
		| @@ -7,8 +7,9 @@ CREATE TABLE IF NOT EXISTS "attachments" | |||||||
|     title         TEXT not null, |     title         TEXT not null, | ||||||
|     isProtected    INT  not null DEFAULT 0, |     isProtected    INT  not null DEFAULT 0, | ||||||
|     blobId    TEXT DEFAULT null, |     blobId    TEXT DEFAULT null, | ||||||
|     utcDateScheduledForDeletionSince TEXT DEFAULT NULL, |     dateModified TEXT NOT NULL, | ||||||
|     utcDateModified TEXT not null, |     utcDateModified TEXT not null, | ||||||
|  |     utcDateScheduledForDeletionSince TEXT DEFAULT NULL, | ||||||
|     isDeleted    INT  not null, |     isDeleted    INT  not null, | ||||||
|     deleteId    TEXT DEFAULT NULL); |     deleteId    TEXT DEFAULT NULL); | ||||||
|  |  | ||||||
|   | |||||||
| @@ -118,8 +118,9 @@ CREATE TABLE IF NOT EXISTS "attachments" | |||||||
|     title         TEXT not null, |     title         TEXT not null, | ||||||
|     isProtected    INT  not null DEFAULT 0, |     isProtected    INT  not null DEFAULT 0, | ||||||
|     blobId    TEXT DEFAULT null, |     blobId    TEXT DEFAULT null, | ||||||
|     utcDateScheduledForDeletionSince TEXT DEFAULT NULL, |     dateModified TEXT NOT NULL, | ||||||
|     utcDateModified TEXT not null, |     utcDateModified TEXT not null, | ||||||
|  |     utcDateScheduledForDeletionSince TEXT DEFAULT NULL, | ||||||
|     isDeleted    INT  not null, |     isDeleted    INT  not null, | ||||||
|     deleteId    TEXT DEFAULT NULL); |     deleteId    TEXT DEFAULT NULL); | ||||||
| CREATE INDEX IDX_attachments_parentId_role | CREATE INDEX IDX_attachments_parentId_role | ||||||
|   | |||||||
| @@ -6,6 +6,8 @@ const becca = require('../becca'); | |||||||
| const AbstractBeccaEntity = require("./abstract_becca_entity"); | const AbstractBeccaEntity = require("./abstract_becca_entity"); | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  |  * FIXME: how to order attachments? | ||||||
|  |  * | ||||||
|  * Attachment represent data related/attached to the note. Conceptually similar to attributes, but intended for |  * Attachment represent data related/attached to the note. Conceptually similar to attributes, but intended for | ||||||
|  * larger amounts of data and generally not accessible to the user. |  * larger amounts of data and generally not accessible to the user. | ||||||
|  * |  * | ||||||
| @@ -45,9 +47,11 @@ class BAttachment extends AbstractBeccaEntity { | |||||||
|         /** @type {boolean} */ |         /** @type {boolean} */ | ||||||
|         this.isProtected = !!row.isProtected; |         this.isProtected = !!row.isProtected; | ||||||
|         /** @type {string} */ |         /** @type {string} */ | ||||||
|         this.utcDateScheduledForDeletionSince = row.utcDateScheduledForDeletionSince; |         this.dateModified = row.dateModified; | ||||||
|         /** @type {string} */ |         /** @type {string} */ | ||||||
|         this.utcDateModified = row.utcDateModified; |         this.utcDateModified = row.utcDateModified; | ||||||
|  |         /** @type {string} */ | ||||||
|  |         this.utcDateScheduledForDeletionSince = row.utcDateScheduledForDeletionSince; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     getNote() { |     getNote() { | ||||||
| @@ -76,6 +80,7 @@ class BAttachment extends AbstractBeccaEntity { | |||||||
|     beforeSaving() { |     beforeSaving() { | ||||||
|         super.beforeSaving(); |         super.beforeSaving(); | ||||||
|  |  | ||||||
|  |         this.dateModified = dateUtils.localNowDateTime(); | ||||||
|         this.utcDateModified = dateUtils.utcNowDateTime(); |         this.utcDateModified = dateUtils.utcNowDateTime(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -89,8 +94,9 @@ class BAttachment extends AbstractBeccaEntity { | |||||||
|             blobId: this.blobId, |             blobId: this.blobId, | ||||||
|             isProtected: !!this.isProtected, |             isProtected: !!this.isProtected, | ||||||
|             isDeleted: false, |             isDeleted: false, | ||||||
|             utcDateScheduledForDeletionSince: this.utcDateScheduledForDeletionSince, |             dateModified: this.dateModified, | ||||||
|             utcDateModified: this.utcDateModified |             utcDateModified: this.utcDateModified, | ||||||
|  |             utcDateScheduledForDeletionSince: this.utcDateScheduledForDeletionSince | ||||||
|         }; |         }; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -38,7 +38,7 @@ export default class Entrypoints extends Component { | |||||||
|  |  | ||||||
|         await ws.waitForMaxKnownEntityChangeId(); |         await ws.waitForMaxKnownEntityChangeId(); | ||||||
|  |  | ||||||
|         await appContext.tabManager.openTabWithNoteWithHoisting(note.noteId, true); |         await appContext.tabManager.openTabWithNoteWithHoisting(note.noteId, {activate: true}); | ||||||
|  |  | ||||||
|         appContext.triggerEvent('focusAndSelectTitle', {isNewNote: true}); |         appContext.triggerEvent('focusAndSelectTitle', {isNewNote: true}); | ||||||
|     } |     } | ||||||
| @@ -135,7 +135,7 @@ export default class Entrypoints extends Component { | |||||||
|         utils.reloadFrontendApp("Switching to mobile version"); |         utils.reloadFrontendApp("Switching to mobile version"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async openInWindowCommand({notePath, hoistedNoteId}) { |     async openInWindowCommand({notePath, hoistedNoteId, viewScope}) { | ||||||
|         if (!hoistedNoteId) { |         if (!hoistedNoteId) { | ||||||
|             hoistedNoteId = 'root'; |             hoistedNoteId = 'root'; | ||||||
|         } |         } | ||||||
| @@ -143,10 +143,10 @@ export default class Entrypoints extends Component { | |||||||
|         if (utils.isElectron()) { |         if (utils.isElectron()) { | ||||||
|             const {ipcRenderer} = utils.dynamicRequire('electron'); |             const {ipcRenderer} = utils.dynamicRequire('electron'); | ||||||
|  |  | ||||||
|             ipcRenderer.send('create-extra-window', {notePath, hoistedNoteId}); |             ipcRenderer.send('create-extra-window', {notePath, hoistedNoteId, viewScope}); | ||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
|             const url = `${window.location.protocol}//${window.location.host}${window.location.pathname}?extra=1#${notePath}`; |             const url = `${window.location.protocol}//${window.location.host}${window.location.pathname}?extraWindow=1&extraHoistedNoteId=${hoistedNoteId}&extraViewScope=${JSON.stringify(viewScope)}#${notePath}`; | ||||||
|  |  | ||||||
|             window.open(url, '', 'width=1000,height=800'); |             window.open(url, '', 'width=1000,height=800'); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -53,8 +53,8 @@ class NoteContext extends Component { | |||||||
|         this.notePath = resolvedNotePath; |         this.notePath = resolvedNotePath; | ||||||
|         ({noteId: this.noteId, parentNoteId: this.parentNoteId} = treeService.getNoteIdAndParentIdFromNotePath(resolvedNotePath)); |         ({noteId: this.noteId, parentNoteId: this.parentNoteId} = treeService.getNoteIdAndParentIdFromNotePath(resolvedNotePath)); | ||||||
|  |  | ||||||
|         this.resetViewScope(); |         this.viewScope = opts.viewScope || {}; | ||||||
|         this.viewScope.viewMode = opts.viewMode || "default"; |         this.viewScope.viewMode = this.viewScope.viewMode || "default"; | ||||||
|  |  | ||||||
|         this.saveToRecentNotes(resolvedNotePath); |         this.saveToRecentNotes(resolvedNotePath); | ||||||
|  |  | ||||||
| @@ -187,7 +187,7 @@ class NoteContext extends Component { | |||||||
|             notePath: this.notePath, |             notePath: this.notePath, | ||||||
|             hoistedNoteId: this.hoistedNoteId, |             hoistedNoteId: this.hoistedNoteId, | ||||||
|             active: this.isActive(), |             active: this.isActive(), | ||||||
|             viewMode: this.viewScope.viewMode |             viewScope: this.viewScope | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -117,7 +117,12 @@ export default class RootCommandExecutor extends Component { | |||||||
|         const notePath = appContext.tabManager.getActiveContextNotePath(); |         const notePath = appContext.tabManager.getActiveContextNotePath(); | ||||||
|  |  | ||||||
|         if (notePath) { |         if (notePath) { | ||||||
|             await appContext.tabManager.openContextWithNote(notePath, { activate: true, viewMode: 'source' }); |             await appContext.tabManager.openContextWithNote(notePath, { | ||||||
|  |                 activate: true, | ||||||
|  |                 viewScope: { | ||||||
|  |                     viewMode: 'source' | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -125,7 +130,25 @@ export default class RootCommandExecutor extends Component { | |||||||
|         const notePath = appContext.tabManager.getActiveContextNotePath(); |         const notePath = appContext.tabManager.getActiveContextNotePath(); | ||||||
|  |  | ||||||
|         if (notePath) { |         if (notePath) { | ||||||
|             await appContext.tabManager.openContextWithNote(notePath, { activate: true, viewMode: 'attachments' }); |             await appContext.tabManager.openContextWithNote(notePath, { | ||||||
|  |                 activate: true, | ||||||
|  |                 viewScope: { | ||||||
|  |                     viewMode: 'attachments' | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     async showAttachmentDetailCommand() { | ||||||
|  |         const notePath = appContext.tabManager.getActiveContextNotePath(); | ||||||
|  |  | ||||||
|  |         if (notePath) { | ||||||
|  |             await appContext.tabManager.openContextWithNote(notePath, { | ||||||
|  |                 activate: true, | ||||||
|  |                 viewScope: { | ||||||
|  |                     viewMode: 'attachments' | ||||||
|  |                 } | ||||||
|  |             }); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -86,7 +86,8 @@ export default class TabManager extends Component { | |||||||
|                 filteredTabs.push({ |                 filteredTabs.push({ | ||||||
|                     notePath: notePathInUrl || 'root', |                     notePath: notePathInUrl || 'root', | ||||||
|                     active: true, |                     active: true, | ||||||
|                     hoistedNoteId: glob.extraHoistedNoteId || 'root' |                     hoistedNoteId: glob.extraHoistedNoteId || 'root', | ||||||
|  |                     viewScope: glob.extraViewScope || {} | ||||||
|                 }); |                 }); | ||||||
|             } |             } | ||||||
|  |  | ||||||
| @@ -101,7 +102,7 @@ export default class TabManager extends Component { | |||||||
|                         ntxId: tab.ntxId, |                         ntxId: tab.ntxId, | ||||||
|                         mainNtxId: tab.mainNtxId, |                         mainNtxId: tab.mainNtxId, | ||||||
|                         hoistedNoteId: tab.hoistedNoteId, |                         hoistedNoteId: tab.hoistedNoteId, | ||||||
|                         viewMode: tab.viewMode |                         viewScope: tab.viewScope | ||||||
|                     }); |                     }); | ||||||
|                 } |                 } | ||||||
|             }); |             }); | ||||||
| @@ -271,7 +272,7 @@ export default class TabManager extends Component { | |||||||
|     /** |     /** | ||||||
|      * If the requested notePath is within current note hoisting scope then keep the note hoisting also for the new tab. |      * If the requested notePath is within current note hoisting scope then keep the note hoisting also for the new tab. | ||||||
|      */ |      */ | ||||||
|     async openTabWithNoteWithHoisting(notePath, activate = false) { |     async openTabWithNoteWithHoisting(notePath, opts = {}) { | ||||||
|         const noteContext = this.getActiveContext(); |         const noteContext = this.getActiveContext(); | ||||||
|         let hoistedNoteId = 'root'; |         let hoistedNoteId = 'root'; | ||||||
|  |  | ||||||
| @@ -283,7 +284,9 @@ export default class TabManager extends Component { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         return this.openContextWithNote(notePath, { activate, hoistedNoteId }); |         opts.hoistedNoteId = hoistedNoteId; | ||||||
|  |  | ||||||
|  |         return this.openContextWithNote(notePath, opts); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async openContextWithNote(notePath, opts = {}) { |     async openContextWithNote(notePath, opts = {}) { | ||||||
| @@ -291,7 +294,7 @@ export default class TabManager extends Component { | |||||||
|         const ntxId = opts.ntxId || null; |         const ntxId = opts.ntxId || null; | ||||||
|         const mainNtxId = opts.mainNtxId || null; |         const mainNtxId = opts.mainNtxId || null; | ||||||
|         const hoistedNoteId = opts.hoistedNoteId || 'root'; |         const hoistedNoteId = opts.hoistedNoteId || 'root'; | ||||||
|         const viewMode = opts.viewMode || "default"; |         const viewScope = opts.viewScope || { viewMode: "default" }; | ||||||
|  |  | ||||||
|         const noteContext = await this.openEmptyTab(ntxId, hoistedNoteId, mainNtxId); |         const noteContext = await this.openEmptyTab(ntxId, hoistedNoteId, mainNtxId); | ||||||
|  |  | ||||||
| @@ -299,7 +302,7 @@ export default class TabManager extends Component { | |||||||
|             await noteContext.setNote(notePath, { |             await noteContext.setNote(notePath, { | ||||||
|                 // if activate is false then send normal noteSwitched event |                 // if activate is false then send normal noteSwitched event | ||||||
|                 triggerSwitchEvent: !activate, |                 triggerSwitchEvent: !activate, | ||||||
|                 viewMode: viewMode |                 viewScope: viewScope | ||||||
|             }); |             }); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										33
									
								
								src/public/app/entities/fattachment.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/public/app/entities/fattachment.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | |||||||
|  | class FAttachment { | ||||||
|  |     constructor(froca, row) { | ||||||
|  |         this.froca = froca; | ||||||
|  |  | ||||||
|  |         this.update(row); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     update(row) { | ||||||
|  |         /** @type {string} */ | ||||||
|  |         this.attachmentId = row.attachmentId; | ||||||
|  |         /** @type {string} */ | ||||||
|  |         this.parentId = row.parentId; | ||||||
|  |         /** @type {string} */ | ||||||
|  |         this.role = row.role; | ||||||
|  |         /** @type {string} */ | ||||||
|  |         this.mime = row.mime; | ||||||
|  |         /** @type {string} */ | ||||||
|  |         this.title = row.title; | ||||||
|  |         /** @type {string} */ | ||||||
|  |         this.dateModified = row.dateModified; | ||||||
|  |         /** @type {string} */ | ||||||
|  |         this.utcDateModified = row.utcDateModified; | ||||||
|  |         /** @type {string} */ | ||||||
|  |         this.utcDateScheduledForDeletionSince = row.utcDateScheduledForDeletionSince; | ||||||
|  |  | ||||||
|  |         this.froca.attachments[this.attachmentId] = this; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** @returns {FNote} */ | ||||||
|  |     getNote() { | ||||||
|  |         return this.froca.notes[this.parentId]; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -51,6 +51,9 @@ class FNote { | |||||||
|         /** @type {Object.<string, string>} */ |         /** @type {Object.<string, string>} */ | ||||||
|         this.childToBranch = {}; |         this.childToBranch = {}; | ||||||
|  |  | ||||||
|  |         /** @type {FAttachment[]|null} */ | ||||||
|  |         this.attachments = null; // lazy loaded | ||||||
|  |  | ||||||
|         this.update(row); |         this.update(row); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -225,6 +228,23 @@ class FNote { | |||||||
|         return await this.froca.getNotes(this.children); |         return await this.froca.getNotes(this.children); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /** @returns {Promise<FAttachment[]>} */ | ||||||
|  |     async getAttachments() { | ||||||
|  |         if (!this.attachments) { | ||||||
|  |             this.attachments = (await server.get(`notes/${this.noteId}/attachments`)) | ||||||
|  |                 .map(row => new FAttachment(froca, row)); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return this.attachments; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** @returns {Promise<FAttachment>} */ | ||||||
|  |     async getAttachmentById(attachmentId) { | ||||||
|  |         const attachments = await this.getAttachments(); | ||||||
|  |  | ||||||
|  |         return attachments.find(att => att.attachmentId === attachmentId); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|      * @param {string} [type] - (optional) attribute type to filter |      * @param {string} [type] - (optional) attribute type to filter | ||||||
|      * @param {string} [name] - (optional) attribute name to filter |      * @param {string} [name] - (optional) attribute name to filter | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| /** | /** | ||||||
|  |  * FIXME: probably make it a FBlob | ||||||
|  * Complements the FNote with the main note content and other extra attributes |  * Complements the FNote with the main note content and other extra attributes | ||||||
|  */ |  */ | ||||||
| class FNoteComplement { | class FNoteComplement { | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| import contextMenu from "./context_menu.js"; | import contextMenu from "./context_menu.js"; | ||||||
| import appContext from "../components/app_context.js"; | import appContext from "../components/app_context.js"; | ||||||
|  |  | ||||||
| function openContextMenu(notePath, hoistedNoteId, e) { | function openContextMenu(notePath, e, viewScope = {}, hoistedNoteId = null) { | ||||||
|     contextMenu.show({ |     contextMenu.show({ | ||||||
|         x: e.pageX, |         x: e.pageX, | ||||||
|         y: e.pageY, |         y: e.pageY, | ||||||
| @@ -16,16 +16,16 @@ function openContextMenu(notePath, hoistedNoteId, e) { | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             if (command === 'openNoteInNewTab') { |             if (command === 'openNoteInNewTab') { | ||||||
|                 appContext.tabManager.openContextWithNote(notePath, { hoistedNoteId }); |                 appContext.tabManager.openContextWithNote(notePath, { hoistedNoteId, viewScope }); | ||||||
|             } |             } | ||||||
|             else if (command === 'openNoteInNewSplit') { |             else if (command === 'openNoteInNewSplit') { | ||||||
|                 const subContexts = appContext.tabManager.getActiveContext().getSubContexts(); |                 const subContexts = appContext.tabManager.getActiveContext().getSubContexts(); | ||||||
|                 const {ntxId} = subContexts[subContexts.length - 1]; |                 const {ntxId} = subContexts[subContexts.length - 1]; | ||||||
|  |  | ||||||
|                 appContext.triggerCommand("openNewNoteSplit", {ntxId, notePath, hoistedNoteId}); |                 appContext.triggerCommand("openNewNoteSplit", {ntxId, notePath, hoistedNoteId, viewScope}); | ||||||
|             } |             } | ||||||
|             else if (command === 'openNoteInNewWindow') { |             else if (command === 'openNoteInNewWindow') { | ||||||
|                 appContext.triggerCommand('openInWindow', {notePath, hoistedNoteId}); |                 appContext.triggerCommand('openInWindow', {notePath, hoistedNoteId, viewScope}); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     }); |     }); | ||||||
|   | |||||||
| @@ -34,6 +34,10 @@ class Froca { | |||||||
|         /** @type {Object.<string, FAttribute>} */ |         /** @type {Object.<string, FAttribute>} */ | ||||||
|         this.attributes = {}; |         this.attributes = {}; | ||||||
|  |  | ||||||
|  |         /** @type {Object.<string, FAttachment>} */ | ||||||
|  |         this.attachments = {}; | ||||||
|  |  | ||||||
|  |         // FIXME | ||||||
|         /** @type {Object.<string, Promise<FNoteComplement>>} */ |         /** @type {Object.<string, Promise<FNoteComplement>>} */ | ||||||
|         this.blobPromises = {}; |         this.blobPromises = {}; | ||||||
|  |  | ||||||
| @@ -311,6 +315,7 @@ class Froca { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
|  |      * // FIXME | ||||||
|      * @returns {Promise<FNoteComplement>} |      * @returns {Promise<FNoteComplement>} | ||||||
|      */ |      */ | ||||||
|     async getNoteComplement(noteId) { |     async getNoteComplement(noteId) { | ||||||
|   | |||||||
| @@ -34,7 +34,7 @@ async function processEntityChanges(entityChanges) { | |||||||
|  |  | ||||||
|                 loadResults.addOption(ec.entity.name); |                 loadResults.addOption(ec.entity.name); | ||||||
|             } else if (ec.entityName === 'attachments') { |             } else if (ec.entityName === 'attachments') { | ||||||
|                 loadResults.addAttachment(ec.entity); |                 processAttachment(loadResults, ec); | ||||||
|             } else if (ec.entityName === 'etapi_tokens') { |             } else if (ec.entityName === 'etapi_tokens') { | ||||||
|                 // NOOP |                 // NOOP | ||||||
|             } |             } | ||||||
| @@ -231,6 +231,43 @@ function processAttributeChange(loadResults, ec) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | function processAttachment(loadResults, ec) { | ||||||
|  |     if (ec.isErased && ec.entityId in froca.attachments) { | ||||||
|  |         utils.reloadFrontendApp(`${ec.entityName} ${ec.entityId} is erased, need to do complete reload.`); | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     const attachment = froca.attachments[ec.entityId]; | ||||||
|  |  | ||||||
|  |     if (ec.isErased || ec.entity?.isDeleted) { | ||||||
|  |         if (attachment) { | ||||||
|  |             const note = attachment.getNote(); | ||||||
|  |  | ||||||
|  |             if (note && note.attachments) { | ||||||
|  |                 note.attachments = note.attachments.filter(att => att.attachmentId !== attachment.attachmentId); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             loadResults.addAttachment(ec.entity); | ||||||
|  |  | ||||||
|  |             delete froca.attachments[ec.entityId]; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         return; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (attachment) { | ||||||
|  |         attachment.update(ec.entity); | ||||||
|  |     } else { | ||||||
|  |         const note = froca.notes[ec.entity.parentId]; | ||||||
|  |  | ||||||
|  |         if (note && note.attachments) { | ||||||
|  |             note.attachments.push(new FAttachment(froca, ec.entity)); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     loadResults.addAttachment(ec.entity); | ||||||
|  | } | ||||||
|  |  | ||||||
| export default { | export default { | ||||||
|     processEntityChanges |     processEntityChanges | ||||||
| } | } | ||||||
|   | |||||||
| @@ -87,7 +87,16 @@ function getNotePathFromLink($link) { | |||||||
|  |  | ||||||
|     const url = $link.attr('href'); |     const url = $link.attr('href'); | ||||||
|  |  | ||||||
|     return url ? getNotePathFromUrl(url) : null; |     const notePath = url ? getNotePathFromUrl(url) : null; | ||||||
|  |     const viewScope = { | ||||||
|  |         viewMode: $link.attr('data-view-mode'), | ||||||
|  |         attachmentId: $link.attr('data-attachment-id'), | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     return { | ||||||
|  |         notePath, | ||||||
|  |         viewScope | ||||||
|  |     }; | ||||||
| } | } | ||||||
|  |  | ||||||
| function goToLink(evt) { | function goToLink(evt) { | ||||||
| @@ -101,22 +110,25 @@ function goToLink(evt) { | |||||||
|     evt.preventDefault(); |     evt.preventDefault(); | ||||||
|     evt.stopPropagation(); |     evt.stopPropagation(); | ||||||
|  |  | ||||||
|     const notePath = getNotePathFromLink($link); |     const {notePath, viewScope} = getNotePathFromLink($link); | ||||||
|  |  | ||||||
|     const ctrlKey = utils.isCtrlKey(evt); |     const ctrlKey = utils.isCtrlKey(evt); | ||||||
|  |     const isLeftClick = evt.which === 1; | ||||||
|  |     const isMiddleClick = evt.which === 2; | ||||||
|  |     const openInNewTab = (isLeftClick && ctrlKey) || isMiddleClick; | ||||||
|  |  | ||||||
|     if (notePath) { |     if (notePath) { | ||||||
|         if ((evt.which === 1 && ctrlKey) || evt.which === 2) { |         if (openInNewTab) { | ||||||
|             appContext.tabManager.openTabWithNoteWithHoisting(notePath); |             appContext.tabManager.openTabWithNoteWithHoisting(notePath, { viewScope }); | ||||||
|         } |         } | ||||||
|         else if (evt.which === 1) { |         else if (isLeftClick) { | ||||||
|             const ntxId = $(evt.target).closest("[data-ntx-id]").attr("data-ntx-id"); |             const ntxId = $(evt.target).closest("[data-ntx-id]").attr("data-ntx-id"); | ||||||
|  |  | ||||||
|             const noteContext = ntxId |             const noteContext = ntxId | ||||||
|                 ? appContext.tabManager.getNoteContextById(ntxId) |                 ? appContext.tabManager.getNoteContextById(ntxId) | ||||||
|                 : appContext.tabManager.getActiveContext(); |                 : appContext.tabManager.getActiveContext(); | ||||||
|  |  | ||||||
|             noteContext.setNote(notePath).then(() => { |             noteContext.setNote(notePath, { viewScope }).then(() => { | ||||||
|                 if (noteContext !== appContext.tabManager.getActiveContext()) { |                 if (noteContext !== appContext.tabManager.getActiveContext()) { | ||||||
|                     appContext.tabManager.activateNoteContext(noteContext.ntxId); |                     appContext.tabManager.activateNoteContext(noteContext.ntxId); | ||||||
|                 } |                 } | ||||||
| @@ -124,7 +136,7 @@ function goToLink(evt) { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
|         if ((evt.which === 1 && ctrlKey) || evt.which === 2 |         if (openInNewTab | ||||||
|             || $link.hasClass("ck-link-actions__preview") // within edit link dialog single click suffices |             || $link.hasClass("ck-link-actions__preview") // within edit link dialog single click suffices | ||||||
|             || $link.closest("[contenteditable]").length === 0 // outside of CKEditor single click suffices |             || $link.closest("[contenteditable]").length === 0 // outside of CKEditor single click suffices | ||||||
|         ) { |         ) { | ||||||
| @@ -147,7 +159,7 @@ function goToLink(evt) { | |||||||
| function linkContextMenu(e) { | function linkContextMenu(e) { | ||||||
|     const $link = $(e.target).closest("a"); |     const $link = $(e.target).closest("a"); | ||||||
|  |  | ||||||
|     const notePath = getNotePathFromLink($link); |     const {notePath, viewScope} = getNotePathFromLink($link); | ||||||
|  |  | ||||||
|     if (!notePath) { |     if (!notePath) { | ||||||
|         return; |         return; | ||||||
| @@ -155,7 +167,7 @@ function linkContextMenu(e) { | |||||||
|  |  | ||||||
|     e.preventDefault(); |     e.preventDefault(); | ||||||
|  |  | ||||||
|     linkContextMenuService.openContextMenu(notePath, null, e); |     linkContextMenuService.openContextMenu(notePath, e, viewScope, null); | ||||||
| } | } | ||||||
|  |  | ||||||
| async function loadReferenceLinkTitle(noteId, $el) { | async function loadReferenceLinkTitle(noteId, $el) { | ||||||
|   | |||||||
| @@ -37,7 +37,7 @@ const TPL = ` | |||||||
|  |  | ||||||
|     <div class="attachment-detail-wrapper"> |     <div class="attachment-detail-wrapper"> | ||||||
|         <div class="attachment-title-line"> |         <div class="attachment-title-line"> | ||||||
|             <h4 class="attachment-title"></h4>                 |             <h4 class="attachment-title"><a href="javascript:" data-trigger-command="openAttachmentDetail"></a></h4>                 | ||||||
|             <div class="attachment-details"></div> |             <div class="attachment-details"></div> | ||||||
|             <div style="flex: 1 1;"></div> |             <div style="flex: 1 1;"></div> | ||||||
|             <div class="attachment-actions-container"></div> |             <div class="attachment-actions-container"></div> | ||||||
| @@ -73,7 +73,7 @@ export default class AttachmentDetailWidget extends BasicWidget { | |||||||
|                     .html() |                     .html() | ||||||
|             ); |             ); | ||||||
|         this.$wrapper = this.$widget.find('.attachment-detail-wrapper'); |         this.$wrapper = this.$widget.find('.attachment-detail-wrapper'); | ||||||
|         this.$wrapper.find('.attachment-title').text(this.attachment.title); |         this.$wrapper.find('.attachment-title a').text(this.attachment.title); | ||||||
|         this.$wrapper.find('.attachment-details') |         this.$wrapper.find('.attachment-details') | ||||||
|             .text(`Role: ${this.attachment.role}, Size: ${utils.formatSize(this.attachment.contentLength)}`); |             .text(`Role: ${this.attachment.role}, Size: ${utils.formatSize(this.attachment.contentLength)}`); | ||||||
|         this.$wrapper.find('.attachment-actions-container').append(this.attachmentActionsWidget.render()); |         this.$wrapper.find('.attachment-actions-container').append(this.attachmentActionsWidget.render()); | ||||||
| @@ -90,9 +90,11 @@ export default class AttachmentDetailWidget extends BasicWidget { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async entitiesReloadedEvent({loadResults}) { |     openAttachmentDetailCommand() { | ||||||
|         console.log("AttachmentDetailWidget: entitiesReloadedEvent"); |  | ||||||
|  |  | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     async entitiesReloadedEvent({loadResults}) { | ||||||
|         const attachmentChange = loadResults.getAttachments().find(att => att.attachmentId === this.attachment.attachmentId); |         const attachmentChange = loadResults.getAttachments().find(att => att.attachmentId === this.attachment.attachmentId); | ||||||
|  |  | ||||||
|         if (attachmentChange) { |         if (attachmentChange) { | ||||||
|   | |||||||
| @@ -27,7 +27,7 @@ export default class NoteLauncher extends AbstractLauncher { | |||||||
|  |  | ||||||
|                 const hoistedNoteId = this.getHoistedNoteId(); |                 const hoistedNoteId = this.getHoistedNoteId(); | ||||||
|  |  | ||||||
|                 linkContextMenuService.openContextMenu(targetNoteId, hoistedNoteId, evt); |                 linkContextMenuService.openContextMenu(targetNoteId, evt, {}, hoistedNoteId); | ||||||
|             }); |             }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ export default class OpenNoteButtonWidget extends OnClickButtonWidget { | |||||||
|             .icon(() => this.noteToOpen.getIcon()) |             .icon(() => this.noteToOpen.getIcon()) | ||||||
|             .onClick((widget, evt) => this.launch(evt)) |             .onClick((widget, evt) => this.launch(evt)) | ||||||
|             .onAuxClick((widget, evt) => this.launch(evt)) |             .onAuxClick((widget, evt) => this.launch(evt)) | ||||||
|             .onContextMenu(evt => linkContextMenuService.openContextMenu(this.noteToOpen.noteId, null, evt)); |             .onContextMenu(evt => linkContextMenuService.openContextMenu(this.noteToOpen.noteId, evt)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async launch(evt) { |     async launch(evt) { | ||||||
|   | |||||||
| @@ -34,7 +34,7 @@ export default class SplitNoteContainer extends FlexContainer { | |||||||
|         this.child(widget); |         this.child(widget); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     async openNewNoteSplitEvent({ntxId, notePath, hoistedNoteId}) { |     async openNewNoteSplitEvent({ntxId, notePath, hoistedNoteId, viewScope}) { | ||||||
|         const mainNtxId = appContext.tabManager.getActiveMainContext().ntxId; |         const mainNtxId = appContext.tabManager.getActiveMainContext().ntxId; | ||||||
|  |  | ||||||
|         if (!ntxId) { |         if (!ntxId) { | ||||||
| @@ -63,7 +63,7 @@ export default class SplitNoteContainer extends FlexContainer { | |||||||
|         await appContext.tabManager.activateNoteContext(noteContext.ntxId); |         await appContext.tabManager.activateNoteContext(noteContext.ntxId); | ||||||
|  |  | ||||||
|         if (notePath) { |         if (notePath) { | ||||||
|             await noteContext.setNote(notePath); |             await noteContext.setNote(notePath, viewScope); | ||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
|             await noteContext.setEmpty(); |             await noteContext.setEmpty(); | ||||||
|   | |||||||
| @@ -61,6 +61,10 @@ export default class NoteContextAwareWidget extends BasicWidget { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * @param {FNote} note | ||||||
|  |      * @returns {Promise<void>} | ||||||
|  |      */ | ||||||
|     async refreshWithNote(note) {} |     async refreshWithNote(note) {} | ||||||
|  |  | ||||||
|     async noteSwitchedEvent({noteContext, notePath}) { |     async noteSwitchedEvent({noteContext, notePath}) { | ||||||
|   | |||||||
| @@ -27,7 +27,8 @@ import NoteMapTypeWidget from "./type_widgets/note_map.js"; | |||||||
| import WebViewTypeWidget from "./type_widgets/web_view.js"; | import WebViewTypeWidget from "./type_widgets/web_view.js"; | ||||||
| import DocTypeWidget from "./type_widgets/doc.js"; | import DocTypeWidget from "./type_widgets/doc.js"; | ||||||
| import ContentWidgetTypeWidget from "./type_widgets/content_widget.js"; | import ContentWidgetTypeWidget from "./type_widgets/content_widget.js"; | ||||||
| import AttachmentsTypeWidget from "./type_widgets/attachments.js"; | import AttachmentListTypeWidget from "./type_widgets/attachment_list.js"; | ||||||
|  | import AttachmentDetailTypeWidget from "./type_widgets/attachment_detail.js"; | ||||||
|  |  | ||||||
| const TPL = ` | const TPL = ` | ||||||
| <div class="note-detail"> | <div class="note-detail"> | ||||||
| @@ -63,7 +64,8 @@ const typeWidgetClasses = { | |||||||
|     'webView': WebViewTypeWidget, |     'webView': WebViewTypeWidget, | ||||||
|     'doc': DocTypeWidget, |     'doc': DocTypeWidget, | ||||||
|     'contentWidget': ContentWidgetTypeWidget, |     'contentWidget': ContentWidgetTypeWidget, | ||||||
|     'attachments': AttachmentsTypeWidget |     'attachmentDetail': AttachmentDetailTypeWidget, | ||||||
|  |     'attachmentList': AttachmentListTypeWidget | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export default class NoteDetailWidget extends NoteContextAwareWidget { | export default class NoteDetailWidget extends NoteContextAwareWidget { | ||||||
| @@ -188,11 +190,12 @@ export default class NoteDetailWidget extends NoteContextAwareWidget { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         let type = note.type; |         let type = note.type; | ||||||
|  |         const viewScope = this.noteContext.viewScope; | ||||||
|  |  | ||||||
|         if (type === 'text' && this.noteContext.viewScope.viewMode === 'source') { |         if (type === 'text' && viewScope.viewMode === 'source') { | ||||||
|             type = 'readOnlyCode'; |             type = 'readOnlyCode'; | ||||||
|         } else if (this.noteContext.viewScope.viewMode === 'attachments') { |         } else if (viewScope.viewMode === 'attachments') { | ||||||
|             type = 'attachments'; |             type = viewScope.attachmentId ? 'attachmentDetail' : 'attachmentList'; | ||||||
|         } else if (type === 'text' && await this.noteContext.isReadOnly()) { |         } else if (type === 'text' && await this.noteContext.isReadOnly()) { | ||||||
|             type = 'readOnlyText'; |             type = 'readOnlyText'; | ||||||
|         } else if ((type === 'code' || type === 'mermaid') && await this.noteContext.isReadOnly()) { |         } else if ((type === 'code' || type === 'mermaid') && await this.noteContext.isReadOnly()) { | ||||||
|   | |||||||
| @@ -113,7 +113,7 @@ export default class NoteMapWidget extends NoteContextAwareWidget { | |||||||
|             .linkWidth(1) |             .linkWidth(1) | ||||||
|             .linkColor(() => this.css.mutedTextColor) |             .linkColor(() => this.css.mutedTextColor) | ||||||
|             .onNodeClick(node => appContext.tabManager.getActiveContext().setNote(node.id)) |             .onNodeClick(node => appContext.tabManager.getActiveContext().setNote(node.id)) | ||||||
|             .onNodeRightClick((node, e) => linkContextMenuService.openContextMenu(node.id, null, e)); |             .onNodeRightClick((node, e) => linkContextMenuService.openContextMenu(node.id, e)); | ||||||
|  |  | ||||||
|         if (this.mapType === 'link') { |         if (this.mapType === 'link') { | ||||||
|             this.graph |             this.graph | ||||||
|   | |||||||
| @@ -70,20 +70,38 @@ export default class NoteTitleWidget extends NoteContextAwareWidget { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     async refreshWithNote(note) { |     async refreshWithNote(note) { | ||||||
|         const viewMode = this.noteContext.viewScope.viewMode; |         this.$noteTitle.val(await this.getTitleText(note)); | ||||||
|         this.$noteTitle.val(viewMode === 'default' |  | ||||||
|             ? note.title |  | ||||||
|             : `${viewMode}: ${note.title}`); |  | ||||||
|  |  | ||||||
|         this.$noteTitle.prop("readonly", |         this.$noteTitle.prop("readonly", | ||||||
|             (note.isProtected && !protectedSessionHolder.isProtectedSessionAvailable()) |             (note.isProtected && !protectedSessionHolder.isProtectedSessionAvailable()) | ||||||
|             || ['_lbRoot', '_lbAvailableLaunchers', '_lbVisibleLaunchers'].includes(note.noteId) |             || ['_lbRoot', '_lbAvailableLaunchers', '_lbVisibleLaunchers'].includes(note.noteId) | ||||||
|             || viewMode !== 'default' |             || this.noteContext.viewScope.viewMode !== 'default' | ||||||
|         ); |         ); | ||||||
|  |  | ||||||
|         this.setProtectedStatus(note); |         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) { |     setProtectedStatus(note) { | ||||||
|         this.$noteTitle.toggleClass("protected", !!note.isProtected); |         this.$noteTitle.toggleClass("protected", !!note.isProtected); | ||||||
|     } |     } | ||||||
|   | |||||||
							
								
								
									
										54
									
								
								src/public/app/widgets/type_widgets/attachment_detail.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/public/app/widgets/type_widgets/attachment_detail.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | |||||||
|  | import TypeWidget from "./type_widget.js"; | ||||||
|  | import server from "../../services/server.js"; | ||||||
|  | import AttachmentDetailWidget from "../attachment_detail.js"; | ||||||
|  |  | ||||||
|  | const TPL = ` | ||||||
|  | <div class="attachment-detail note-detail-printable"> | ||||||
|  |     <style> | ||||||
|  |         .attachment-detail { | ||||||
|  |             padding: 15px; | ||||||
|  |         } | ||||||
|  |     </style> | ||||||
|  |  | ||||||
|  |     <div class="attachment-wrapper"></div> | ||||||
|  | </div>`; | ||||||
|  |  | ||||||
|  | export default class AttachmentDetailTypeWidget extends TypeWidget { | ||||||
|  |     static getType() { | ||||||
|  |         return "attachmentDetail"; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     doRender() { | ||||||
|  |         this.$widget = $(TPL); | ||||||
|  |         this.$wrapper = this.$widget.find('.attachment-wrapper'); | ||||||
|  |  | ||||||
|  |         super.doRender(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     async doRefresh(note) { | ||||||
|  |         this.$wrapper.empty(); | ||||||
|  |         this.children = []; | ||||||
|  |         this.renderedAttachmentIds = new Set(); | ||||||
|  |  | ||||||
|  |         const attachment = await server.get(`notes/${this.noteId}/attachments/${this.noteContext.viewScope.attachment.attachmentId}/?includeContent=true`); | ||||||
|  |  | ||||||
|  |         if (!attachment) { | ||||||
|  |             this.$list.html("<strong>This attachment has been deleted.</strong>"); | ||||||
|  |  | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         const attachmentDetailWidget = new AttachmentDetailWidget(attachment); | ||||||
|  |         this.child(attachmentDetailWidget); | ||||||
|  |  | ||||||
|  |         this.$list.append(attachmentDetailWidget.render()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     async entitiesReloadedEvent({loadResults}) { | ||||||
|  |         const attachmentChange = loadResults.getAttachments().find(att => att.attachmentId === this.attachment.attachmentId); | ||||||
|  |  | ||||||
|  |         if (attachmentChange.isDeleted) { | ||||||
|  |             this.refresh(); // all other updates are handled within AttachmentDetailWidget | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -3,24 +3,24 @@ import server from "../../services/server.js"; | |||||||
| import AttachmentDetailWidget from "../attachment_detail.js"; | import AttachmentDetailWidget from "../attachment_detail.js"; | ||||||
| 
 | 
 | ||||||
| const TPL = ` | const TPL = ` | ||||||
| <div class="attachments note-detail-printable"> | <div class="attachment-list note-detail-printable"> | ||||||
|     <style> |     <style> | ||||||
|         .attachments { |         .attachment-list { | ||||||
|             padding: 15px; |             padding: 15px; | ||||||
|         } |         } | ||||||
|     </style> |     </style> | ||||||
| 
 | 
 | ||||||
|     <div class="attachment-list"></div> |     <div class="attachment-list-wrapper"></div> | ||||||
| </div>`; | </div>`; | ||||||
| 
 | 
 | ||||||
| export default class AttachmentsTypeWidget extends TypeWidget { | export default class AttachmentListTypeWidget extends TypeWidget { | ||||||
|     static getType() { |     static getType() { | ||||||
|         return "attachments"; |         return "attachmentList"; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     doRender() { |     doRender() { | ||||||
|         this.$widget = $(TPL); |         this.$widget = $(TPL); | ||||||
|         this.$list = this.$widget.find('.attachment-list'); |         this.$list = this.$widget.find('.attachment-list-wrapper'); | ||||||
| 
 | 
 | ||||||
|         super.doRender(); |         super.doRender(); | ||||||
|     } |     } | ||||||
| @@ -34,8 +34,10 @@ function index(req, res) { | |||||||
|         instanceName: config.General ? config.General.instanceName : null, |         instanceName: config.General ? config.General.instanceName : null, | ||||||
|         appCssNoteIds: getAppCssNoteIds(), |         appCssNoteIds: getAppCssNoteIds(), | ||||||
|         isDev: env.isDev(), |         isDev: env.isDev(), | ||||||
|         isMainWindow: !req.query.extra, |         isMainWindow: !req.query.extraWindow, | ||||||
|         extraHoistedNoteId: req.query.extraHoistedNoteId, |         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(), |         isProtectedSessionAvailable: protectedSessionService.isProtectedSessionAvailable(), | ||||||
|         maxContentWidth: parseInt(options.maxContentWidth), |         maxContentWidth: parseInt(options.maxContentWidth), | ||||||
|         triliumVersion: packageJson.version, |         triliumVersion: packageJson.version, | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ let mainWindow; | |||||||
| /** @type {Electron.BrowserWindow} */ | /** @type {Electron.BrowserWindow} */ | ||||||
| let setupWindow; | let setupWindow; | ||||||
|  |  | ||||||
| async function createExtraWindow(notePath, hoistedNoteId = 'root') { | async function createExtraWindow(notePath, hoistedNoteId = 'root', viewScope = {}) { | ||||||
|     const spellcheckEnabled = optionService.getOptionBool('spellCheckEnabled'); |     const spellcheckEnabled = optionService.getOptionBool('spellCheckEnabled'); | ||||||
|  |  | ||||||
|     const {BrowserWindow} = require('electron'); |     const {BrowserWindow} = require('electron'); | ||||||
| @@ -35,13 +35,13 @@ async function createExtraWindow(notePath, hoistedNoteId = 'root') { | |||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     win.setMenuBarVisibility(false); |     win.setMenuBarVisibility(false); | ||||||
|     win.loadURL(`http://127.0.0.1:${port}/?extra=1&extraHoistedNoteId=${hoistedNoteId}#${notePath}`); |     win.loadURL(`http://127.0.0.1:${port}/?extraWindow=1&extraHoistedNoteId=${hoistedNoteId}&extraViewScope=${JSON.stringify(viewScope)}#${notePath}`); | ||||||
|  |  | ||||||
|     configureWebContents(win.webContents, spellcheckEnabled); |     configureWebContents(win.webContents, spellcheckEnabled); | ||||||
| } | } | ||||||
|  |  | ||||||
| ipcMain.on('create-extra-window', (event, arg) => { | ipcMain.on('create-extra-window', (event, arg) => { | ||||||
|     createExtraWindow(arg.notePath, arg.hoistedNoteId); |     createExtraWindow(arg.notePath, arg.hoistedNoteId, arg.viewScope); | ||||||
| }); | }); | ||||||
|  |  | ||||||
| async function createMainWindow(app) { | async function createMainWindow(app) { | ||||||
|   | |||||||
| @@ -33,6 +33,7 @@ | |||||||
|         appCssNoteIds: <%- JSON.stringify(appCssNoteIds) %>, |         appCssNoteIds: <%- JSON.stringify(appCssNoteIds) %>, | ||||||
|         isMainWindow: <%= isMainWindow %>, |         isMainWindow: <%= isMainWindow %>, | ||||||
|         extraHoistedNoteId: '<%= extraHoistedNoteId %>', |         extraHoistedNoteId: '<%= extraHoistedNoteId %>', | ||||||
|  |         extraViewScope: <%- extraViewScope %>, | ||||||
|         isProtectedSessionAvailable: <%= isProtectedSessionAvailable %>, |         isProtectedSessionAvailable: <%= isProtectedSessionAvailable %>, | ||||||
|         triliumVersion: "<%= triliumVersion %>", |         triliumVersion: "<%= triliumVersion %>", | ||||||
|         assetPath: "<%= assetPath %>", |         assetPath: "<%= assetPath %>", | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user