From f063d86d6278903d49f96738fcfc0aa9efe23d76 Mon Sep 17 00:00:00 2001 From: Zsolt Viczian Date: Mon, 8 Aug 2022 22:35:18 +0200 Subject: [PATCH] 0.1.5 --- manifest.json | 2 +- package-lock.json | 127 ++++++++++++++---------------- package.json | 2 +- src/Scene.ts | 175 +++++++++++++++++++++++++----------------- src/Settings.ts | 39 ++++++++++ src/graph/Layout.ts | 4 +- src/graph/Page.ts | 1 + src/graph/Pages.ts | 18 ++++- src/lang/locale/en.ts | 9 ++- src/main.ts | 4 +- 10 files changed, 232 insertions(+), 149 deletions(-) diff --git a/manifest.json b/manifest.json index b44da70..f017dae 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "excalibrain", "name": "ExcaliBrain", - "version": "0.1.4", + "version": "0.1.5", "minAppVersion": "0.15.5", "description": "A clean, intuitive and editable graph view for Obsidian", "author": "Zsolt Viczian", diff --git a/package-lock.json b/package-lock.json index 2786b4b..e82591e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,7 @@ "license": "MIT", "dependencies": { "@popperjs/core": "^2.11.2", - "obsidian-dataview": "^0.5.31" + "obsidian-dataview": "^0.5.38" }, "devDependencies": { "@babel/core": "^7.16.12", @@ -28,7 +28,7 @@ "eslint-config-prettier": "8.3.0", "eslint-plugin-prettier": "^4.0.0", "obsidian": "^0.15.3", - "obsidian-excalidraw-plugin": "1.6.33", + "obsidian-excalidraw-plugin": "1.7.11", "prettier": "^2.5.1", "rollup": "^2.70.1", "rollup-plugin-terser": "^7.0.2", @@ -4295,16 +4295,13 @@ "dev": true }, "node_modules/@zsviczian/excalidraw": { - "version": "0.11.0-obsidian-20", - "resolved": "https://registry.npmjs.org/@zsviczian/excalidraw/-/excalidraw-0.11.0-obsidian-20.tgz", - "integrity": "sha512-9r/F1q1K/uUFrDeJ81MrzD85deB77HioNkdVRU05IeAUSk7cSImvbKrtrCYefdx2jyICb5j/dY9/PKH8G/hbrA==", + "version": "0.12.0-obsidian-4", + "resolved": "https://registry.npmjs.org/@zsviczian/excalidraw/-/excalidraw-0.12.0-obsidian-4.tgz", + "integrity": "sha512-x16SkkNewR+Mbfn0mULjLDMfvxJ4iXBtwO2T1PWajNcn2QwHnByn4KTFUsuTD0PfQ/ZTgTLeLUztpAZ8cted1w==", "dev": true, - "dependencies": { - "dotenv": "10.0.0" - }, "peerDependencies": { - "react": "^17.0.2", - "react-dom": "^17.0.2" + "react": "^17.0.2 || ^18.2.0", + "react-dom": "^17.0.2 || ^18.2.0" } }, "node_modules/abab": { @@ -12580,9 +12577,9 @@ "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" }, "node_modules/obsidian-dataview": { - "version": "0.5.31", - "resolved": "https://registry.npmjs.org/obsidian-dataview/-/obsidian-dataview-0.5.31.tgz", - "integrity": "sha512-InvUz5uONd4Jm2ZlG+AInz3WWRX+TNDtN3aejH3yGeghbWcOTrYCvf3uxGem03TSEgQUyxyJFPJQzY0RDiu4Kg==", + "version": "0.5.41", + "resolved": "https://registry.npmjs.org/obsidian-dataview/-/obsidian-dataview-0.5.41.tgz", + "integrity": "sha512-3qPIMi10sdWm7YG4SHB6BZtzBPRMs1Mpx9ffNQ1rY4+E3M4NlGivim/S5jgkuV/IDetJXpt1f1lc6IzNflabvw==", "dependencies": { "emoji-regex": "^10.0.0", "localforage": "^1.10.0", @@ -12599,19 +12596,19 @@ "integrity": "sha512-xAEnNCT3w2Tg6MA7ly6QqYJvEoY1tm9iIjJ3yMKK9JPlWuRHAMoe5iETwQnx3M9TVbFMfsrBgWKR+IsmswwNjg==" }, "node_modules/obsidian-excalidraw-plugin": { - "version": "1.6.33", - "resolved": "https://registry.npmjs.org/obsidian-excalidraw-plugin/-/obsidian-excalidraw-plugin-1.6.33.tgz", - "integrity": "sha512-SBTpXcDyfkDa1F91l3TKPcVVbxU6MlQ2kNSUW3cT0kv4q8kh6yFcBynJ0ZGL0F31tRGz042rlkFaY80/0GdDEw==", + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/obsidian-excalidraw-plugin/-/obsidian-excalidraw-plugin-1.7.11.tgz", + "integrity": "sha512-hh8381ZlePZBRhXc3R2N1ei4aQYyLhpQ0v00OHo2jCfnNTAuVWfp87Y6NpXV9USDkX0oWLJPJHW/7g8Pr3nGSw==", "dev": true, "dependencies": { "@types/lz-string": "^1.3.34", - "@zsviczian/excalidraw": "0.11.0-obsidian-20", - "clsx": "1.1.1", + "@zsviczian/excalidraw": "0.12.0-obsidian-4", + "clsx": "^1.1.1", "lz-string": "^1.4.4", "monkey-around": "^2.3.0", - "react": "^17.0.2", - "react-dom": "^17.0.2", - "react-scripts": "^5.0.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-scripts": "^5.0.1", "roughjs": "^4.5.2" } }, @@ -14554,13 +14551,12 @@ } }, "node_modules/react": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", - "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", "dev": true, "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" + "loose-envify": "^1.1.0" }, "engines": { "node": ">=0.10.0" @@ -14710,17 +14706,16 @@ } }, "node_modules/react-dom": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", - "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", "dev": true, "dependencies": { "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "scheduler": "^0.20.2" + "scheduler": "^0.23.0" }, "peerDependencies": { - "react": "17.0.2" + "react": "^18.2.0" } }, "node_modules/react-error-overlay": { @@ -15359,13 +15354,12 @@ } }, "node_modules/scheduler": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", - "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", "dev": true, "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" + "loose-envify": "^1.1.0" } }, "node_modules/schema-utils": { @@ -20892,13 +20886,11 @@ "dev": true }, "@zsviczian/excalidraw": { - "version": "0.11.0-obsidian-20", - "resolved": "https://registry.npmjs.org/@zsviczian/excalidraw/-/excalidraw-0.11.0-obsidian-20.tgz", - "integrity": "sha512-9r/F1q1K/uUFrDeJ81MrzD85deB77HioNkdVRU05IeAUSk7cSImvbKrtrCYefdx2jyICb5j/dY9/PKH8G/hbrA==", + "version": "0.12.0-obsidian-4", + "resolved": "https://registry.npmjs.org/@zsviczian/excalidraw/-/excalidraw-0.12.0-obsidian-4.tgz", + "integrity": "sha512-x16SkkNewR+Mbfn0mULjLDMfvxJ4iXBtwO2T1PWajNcn2QwHnByn4KTFUsuTD0PfQ/ZTgTLeLUztpAZ8cted1w==", "dev": true, - "requires": { - "dotenv": "10.0.0" - } + "requires": {} }, "abab": { "version": "2.0.6", @@ -27084,9 +27076,9 @@ } }, "obsidian-dataview": { - "version": "0.5.31", - "resolved": "https://registry.npmjs.org/obsidian-dataview/-/obsidian-dataview-0.5.31.tgz", - "integrity": "sha512-InvUz5uONd4Jm2ZlG+AInz3WWRX+TNDtN3aejH3yGeghbWcOTrYCvf3uxGem03TSEgQUyxyJFPJQzY0RDiu4Kg==", + "version": "0.5.41", + "resolved": "https://registry.npmjs.org/obsidian-dataview/-/obsidian-dataview-0.5.41.tgz", + "integrity": "sha512-3qPIMi10sdWm7YG4SHB6BZtzBPRMs1Mpx9ffNQ1rY4+E3M4NlGivim/S5jgkuV/IDetJXpt1f1lc6IzNflabvw==", "requires": { "emoji-regex": "^10.0.0", "localforage": "^1.10.0", @@ -27105,19 +27097,19 @@ } }, "obsidian-excalidraw-plugin": { - "version": "1.6.33", - "resolved": "https://registry.npmjs.org/obsidian-excalidraw-plugin/-/obsidian-excalidraw-plugin-1.6.33.tgz", - "integrity": "sha512-SBTpXcDyfkDa1F91l3TKPcVVbxU6MlQ2kNSUW3cT0kv4q8kh6yFcBynJ0ZGL0F31tRGz042rlkFaY80/0GdDEw==", + "version": "1.7.11", + "resolved": "https://registry.npmjs.org/obsidian-excalidraw-plugin/-/obsidian-excalidraw-plugin-1.7.11.tgz", + "integrity": "sha512-hh8381ZlePZBRhXc3R2N1ei4aQYyLhpQ0v00OHo2jCfnNTAuVWfp87Y6NpXV9USDkX0oWLJPJHW/7g8Pr3nGSw==", "dev": true, "requires": { "@types/lz-string": "^1.3.34", - "@zsviczian/excalidraw": "0.11.0-obsidian-20", - "clsx": "1.1.1", + "@zsviczian/excalidraw": "0.12.0-obsidian-4", + "clsx": "^1.1.1", "lz-string": "^1.4.4", "monkey-around": "^2.3.0", - "react": "^17.0.2", - "react-dom": "^17.0.2", - "react-scripts": "^5.0.0", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "react-scripts": "^5.0.1", "roughjs": "^4.5.2" } }, @@ -28418,13 +28410,12 @@ } }, "react": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", - "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", "dev": true, "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" + "loose-envify": "^1.1.0" } }, "react-app-polyfill": { @@ -28537,14 +28528,13 @@ } }, "react-dom": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", - "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", "dev": true, "requires": { "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "scheduler": "^0.20.2" + "scheduler": "^0.23.0" } }, "react-error-overlay": { @@ -29002,13 +28992,12 @@ } }, "scheduler": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", - "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", "dev": true, "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" + "loose-envify": "^1.1.0" } }, "schema-utils": { diff --git a/package.json b/package.json index 4f68f2d..c3b0501 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "@popperjs/core": "^2.11.2" }, "devDependencies": { - "obsidian-excalidraw-plugin": "1.6.33", + "obsidian-excalidraw-plugin": "1.7.11", "@babel/core": "^7.16.12", "@babel/preset-env": "^7.16.11", "@babel/preset-react": "^7.16.7", diff --git a/src/Scene.ts b/src/Scene.ts index 0e7fbc5..ac684cd 100644 --- a/src/Scene.ts +++ b/src/Scene.ts @@ -53,8 +53,7 @@ export class Scene { this.focusSearchAfterInitiation = focusSearchAfterInitiation; await this.plugin.loadSettings(); this.toolsPanel = new ToolsPanel((this.leaf.view as TextFileView).contentEl,this.plugin); - await this.initializeScene(); - this.historyPanel = new HistoryPanel((this.leaf.view as TextFileView).contentEl,this.plugin); + this.initializeScene(); } /** @@ -78,10 +77,11 @@ export class Scene { return; } if(updateIndex) { + this.vaultFileChanged = false; await this.plugin.createIndex(); //temporary } await this.render(); - this.toolsPanel.rerender(); + //this.toolsPanel.rerender(); //this is also there at the end of render. Seems duplicate. } /** @@ -216,10 +216,9 @@ export class Scene { const ea = this.ea; const style = this.plugin.settings.baseNodeStyle; let counter = 0; - ea.clear(); - + ea.clear(); ea.setView(this.leaf.view as any) - counter = 0; + while(!ea.targetView.excalidrawAPI && counter++<10) { await sleep(50); } @@ -227,42 +226,58 @@ export class Scene { new Notice(`Error initializing Excalidraw view`); return; } + + const api = ea.getExcalidrawAPI(); this.ea.registerThisAsViewEA(); this.ea.targetView.semaphores.saving = true; //disable saving by setting this Excalidraw flag (not published API) - this.ea.targetView.excalidrawAPI.setMobileModeAllowed(false); //disable mobile view https://github.com/zsviczian/excalibrain/issues/9 + api.setMobileModeAllowed(false); //disable mobile view https://github.com/zsviczian/excalibrain/issues/9 ea.style.fontFamily = style.fontFamily; ea.style.fontSize = style.fontSize; this.textSize = ea.measureText("m".repeat(style.maxLabelLength+3)); this.nodeWidth = this.textSize.width + 3 * style.padding; this.nodeHeight = 2 * (this.textSize.height + 2 * style.padding); - - ea.getExcalidrawAPI().updateScene({ - appState: { - viewModeEnabled:true, - activeTool: { - lastActiveToolBeforeEraser: null, - locked: false, - type: "selection" + + const frame1 = () => { + api.updateScene({ + appState: { + viewModeEnabled:true, + activeTool: { + lastActiveToolBeforeEraser: null, + locked: false, + type: "selection" + }, + theme: "light", + viewBackgroundColor: this.plugin.settings.backgroundColor }, - theme: "light", - viewBackgroundColor: this.plugin.settings.backgroundColor - }, - elements:[] + elements: [] + }); + } + const frame2 = () => { + ea.style.strokeColor = style.textColor; + ea.addText(0,0,"🚀 To get started\nselect a document using the search in the top left or\n" + + "open a document in another pane.\n\n" + + "✨ For the best experience enable 'Open in adjacent pane'\nin Excalidraw settings " + + "under 'Links and Transclusion'.\n\n⚠ ExcaliBrain may need to wait for " + + "DataView to initialize its index.\nThis can take up to a few minutes after starting Obsidian.", {textAlign:"center"}); + ea.addElementsToView(); + } + const frame3 = () => { + api.zoomToFit(null, 5, 0.15); + ea.targetView.linksAlwaysOpenInANewPane = true; + this.addEventHandler(); + this.historyPanel = new HistoryPanel((this.leaf.view as TextFileView).contentEl,this.plugin); + new Notice("ExcaliBrain On"); + } + + ea.targetView.ownerWindow.requestAnimationFrame(()=>{ + frame1(); + ea.targetView.ownerWindow.requestAnimationFrame(()=>{ + frame2(); + ea.targetView.ownerWindow.requestAnimationFrame(()=>{ + frame3(); + }); + }); }); - - ea.style.strokeColor = style.textColor; - ea.addText(0,0,"🚀 To get started\nselect a document using the search in the top left or\n" + - "open a document in another pane.\n\n" + - "✨ For the best experience enable 'Open in adjacent pane'\nin Excalidraw settings " + - "under 'Links and Transclusion'.\n\n⚠ ExcaliBrain may need to wait for " + - "DataView to initialize its index.\nThis can take up to a few minutes after starting Obsidian.", {textAlign:"center"}); - await ea.addElementsToView(); - ea.getExcalidrawAPI().zoomToFit(null, 5, 0.15); - - ea.targetView.linksAlwaysOpenInANewPane = true; - - this.addEventHandler(); - new Notice("ExcaliBrain On"); } addNodes(x:{ @@ -302,9 +317,11 @@ export class Scene { if(!centralPage) return; } - this.ea.clear(); - this.ea.getExcalidrawAPI().updateScene({elements:[]}); - this.ea.style.verticalAlign = "middle"; + const ea = this.ea; + + ea.clear(); + ea.getExcalidrawAPI().updateScene({elements:[]}); + ea.style.verticalAlign = "middle"; //List nodes for the graph const parents = centralPage.getParents() @@ -408,9 +425,9 @@ export class Scene { const siblingsStyle = this.plugin.settings.siblingNodeStyle; const siblingsPadding = siblingsStyle.padding??baseStyle.padding; const siblingsLabelLength = siblingsStyle.maxLabelLength??baseStyle.maxLabelLength; - this.ea.style.fontFamily = siblingsStyle.fontFamily; - this.ea.style.fontSize = siblingsStyle.fontSize; - const siblingsTextSize = this.ea.measureText("m".repeat(siblingsLabelLength+3)); + ea.style.fontFamily = siblingsStyle.fontFamily; + ea.style.fontSize = siblingsStyle.fontSize; + const siblingsTextSize = ea.measureText("m".repeat(siblingsLabelLength+3)); const siblingsNodeWidth = siblingsTextSize.width + 3 * siblingsPadding; const siblingsNodeHeight = 2 * (siblingsTextSize.height + 2 * siblingsPadding); @@ -426,7 +443,7 @@ export class Scene { this.layouts.push(lSiblings); const rootNode = new Node({ - ea: this.ea, + ea, page: centralPage, isInferred: false, isCentral: true, @@ -486,7 +503,7 @@ export class Scene { neighbour.relationType, neighbour.typeDefinition, neighbour.linkDirection, - this.ea, + ea, this.plugin.settings ) }) @@ -500,18 +517,24 @@ export class Scene { //------------------------------------------------------- // Render - this.ea.style.opacity = 100; + ea.style.opacity = 100; this.layouts.forEach(layout => layout.render()); - const nodeElements = this.ea.getElements(); + const nodeElements = ea.getElements(); this.links.render(Array.from(this.toolsPanel.linkTagFilter.selectedLinks)); - const linkElements = this.ea.getElements().filter(el=>!nodeElements.includes(el)); + const linkElements = ea.getElements().filter(el=>!nodeElements.includes(el)); - this.ea.getExcalidrawAPI().updateScene({ + ea.getExcalidrawAPI().updateScene({ elements: linkElements.concat(nodeElements) //send link elements behind node elements }) - this.ea.getExcalidrawAPI().zoomToFit(null,5,0.15); + ea.targetView.ownerWindow.requestAnimationFrame(()=>{ + ea.getExcalidrawAPI().updateScene({appState: {viewBackgroundColor: this.plugin.settings.backgroundColor}}); + ea.targetView.ownerWindow.requestAnimationFrame(()=>{ + ea.getExcalidrawAPI().zoomToFit(null,5,0.15); + }); + }); + this.toolsPanel.rerender(); if(this.focusSearchAfterInitiation) { this.toolsPanel.searchElement.focus(); @@ -535,7 +558,8 @@ export class Scene { } self.blockUpdateTimer = true; //await self.plugin.createIndex(); - await new Promise((resolve) => setTimeout(resolve, 100)); + await sleep(100); + //------------------------------------------------------- //terminate event handler if view no longer exists or file has changed @@ -559,6 +583,9 @@ export class Scene { const rootFile = leaf.view.file; if (rootFile.path === self.ea.targetView.file.path) { //brainview drawing is the active leaf + if(this.vaultFileChanged) { + await this.reRender(true); + } self.blockUpdateTimer = false; return; } @@ -584,34 +611,13 @@ export class Scene { self.render(); } - const updateTimer = async () => { - if(this.blockUpdateTimer) { - return; - } - if(this.vaultFileChanged) { - this.vaultFileChanged = false; - await this.plugin.createIndex(); - if(this.centralPagePath) { - if(!this.plugin.pages.get(this.centralPagePath)) { - //@ts-ignore - if(this.centralLeaf && this.centralLeaf.view && this.centralLeaf.view.file) { - //@ts-ignore - this.centralPagePath = this.centralLeaf.view.file.path; - } - } - } - this.render(); - } - } - const fileChangeHandler = () => { this.vaultFileChanged = true; } app.workspace.on("active-leaf-change", brainEventHandler); this.removeEH = () => app.workspace.off("active-leaf-change",brainEventHandler); - const timer = setInterval(updateTimer,5000); - this.removeTimer = () => clearInterval(timer); + this.setTimer(); app.vault.on("rename",fileChangeHandler); this.removeOnRename = () => app.vault.off("rename",fileChangeHandler) app.vault.on("modify",fileChangeHandler); @@ -635,6 +641,37 @@ export class Scene { } } + setTimer() { + const updateTimer = async () => { + if(this.blockUpdateTimer) { + return; + } + if(this.vaultFileChanged) { + this.vaultFileChanged = false; + await this.plugin.createIndex(); + if(this.centralPagePath) { + if(!this.plugin.pages.get(this.centralPagePath)) { + //@ts-ignore + if(this.centralLeaf && this.centralLeaf.view && this.centralLeaf.view.file) { + //@ts-ignore + this.centralPagePath = this.centralLeaf.view.file.path; + } + } + } + this.render(); + } + } + + if(this.removeTimer) { + this.removeTimer(); + this.removeTimer = undefined; + } + + const timer = setInterval(updateTimer,this.plugin.settings.indexUpdateInterval); + this.removeTimer = () => clearInterval(timer); + } + + public unloadScene() { if(this.removeEH) { this.removeEH(); diff --git a/src/Settings.ts b/src/Settings.ts index aedb756..1fe8f49 100644 --- a/src/Settings.ts +++ b/src/Settings.ts @@ -23,8 +23,10 @@ import { DEFAULT_LINK_STYLE, DEFAULT_NODE_STYLE, PREDEFINED_LINK_STYLES } from " export interface ExcaliBrainSettings { excalibrainFilepath: string; + indexUpdateInterval: number; hierarchy: Hierarchy; inferAllLinksAsFriends: boolean; + inverseInfer: boolean; renderAlias: boolean; nodeTitleScript: string; backgroundColor: string; @@ -66,6 +68,7 @@ export interface ExcaliBrainSettings { export const DEFAULT_SETTINGS: ExcaliBrainSettings = { excalibrainFilepath: "excalibrain.md", + indexUpdateInterval: 5000, hierarchy: { exclusions: ["excalidraw-font","excalidraw-font-color","excalidraw-css","excalidraw-plugin", "excalidraw-link-brackets","excalidraw-link-prefix","excalidraw-border-color","excalidraw-default-mode", @@ -76,6 +79,7 @@ export const DEFAULT_SETTINGS: ExcaliBrainSettings = { friends: ["Friends", "Friend", "Jump", "Jumps", "j"] }, inferAllLinksAsFriends: false, + inverseInfer: false, renderAlias: true, nodeTitleScript: "", backgroundColor: "#0c3e6aff", @@ -180,6 +184,7 @@ export class ExcaliBrainSettingTab extends PluginSettingTab { private demoLinkImg: HTMLImageElement; private demoLinkStyle: LinkStyleData; private demoNodeStyle: NodeStyleData; + private updateTimer: boolean = false; constructor(app: App, plugin: ExcaliBrain) { super(app, plugin); @@ -328,6 +333,10 @@ export class ExcaliBrainSettingTab extends PluginSettingTab { this.plugin.settings.tagStyleList = Object.keys(this.plugin.settings.tagNodeStyles); this.plugin.loadCustomNodeLabelFunction(); this.plugin.saveSettings(); + if(this.updateTimer && this.plugin.scene && !this.plugin.scene.terminated) { + this.plugin.scene.setTimer(); + } + this.plugin.scene?.reRender(); } @@ -403,6 +412,7 @@ export class ExcaliBrainSettingTab extends PluginSettingTab { el.value = getHex(getValue()??defaultValue); el.onchange = () => { setValue(el.value+ getAlphaHex(sliderComponent.getValue())); + this.dirty = true; } }); setting.controlEl.appendChild(picker); @@ -422,6 +432,7 @@ export class ExcaliBrainSettingTab extends PluginSettingTab { setValue(picker.value + getAlphaHex(value)); displayText.innerText = ` ${value.toString()}`; picker.style.opacity = value.toString(); + this.dirty = true; }) }) @@ -1299,6 +1310,21 @@ export class ExcaliBrainSettingTab extends PluginSettingTab { }) .inputEl.onblur = () => {text.setValue(this.plugin.settings.excalibrainFilepath)} ) + + this.numberslider( + containerEl, + t("INDEX_REFRESH_FREQ_NAME"), + t("INDEX_REFRESH_FREQ_DESC"), + {min:5,max:120, step:5}, + ()=>this.plugin.settings.indexUpdateInterval/1000, + (val)=>{ + this.plugin.settings.indexUpdateInterval = val*1000; + this.updateTimer = true; + }, + ()=>{}, + false, + 5000 + ) this.containerEl.createEl("h1", { cls: "excalibrain-settings-h1", @@ -1422,6 +1448,19 @@ export class ExcaliBrainSettingTab extends PluginSettingTab { }) ) + new Setting(containerEl) + .setName(t("REVERSE_NAME")) + .setDesc(fragWithHTML(t("REVERSE_DESC"))) + .addToggle(toggle => + toggle + .setValue(this.plugin.settings.inverseInfer) + .onChange(value => { + this.plugin.settings.inverseInfer = value; + this.dirty = true; + }) + ) + + let pSetting:Setting, cSetting:Setting, fSetting:Setting, gSetting: Setting, mSetting: Setting, bSetting: Setting; new Setting(containerEl) diff --git a/src/graph/Layout.ts b/src/graph/Layout.ts index c6cff8f..d44639d 100644 --- a/src/graph/Layout.ts +++ b/src/graph/Layout.ts @@ -25,8 +25,8 @@ export class Layout { } const getRowLayout = (items: number) => items%2 - ? generateLayoutVector([(columns-items)/2,items,(columns-items)/2]) - : generateLayoutVector([(columns-items)/2,items/2,1,items/2,(columns-items)/2]); + ? generateLayoutVector([(columns-items)/2,items,(columns-items)/2]) //odd + : generateLayoutVector([(columns-items)/2,items/2,1,items/2,(columns-items)/2]); //even const sortedNodes = this.nodes.sort((a,b) => a.title.toLowerCase() < b.title.toLowerCase() ? -1 : 1) const itemCount = sortedNodes.length; diff --git a/src/graph/Page.ts b/src/graph/Page.ts index d4cb164..afbd412 100644 --- a/src/graph/Page.ts +++ b/src/graph/Page.ts @@ -90,6 +90,7 @@ export class Page { if(!child) { return; } + if(this.neighbours.has(path)) return; //https://github.com/zsviczian/excalibrain/issues/74 child.addParent(this,RelationType.DEFINED,LinkDirection.FROM,"tag-tree"); this.addChild(child,RelationType.DEFINED,LinkDirection.TO,"tag-tree"); }); diff --git a/src/graph/Pages.ts b/src/graph/Pages.ts index 5b4f9f6..5af5ea8 100644 --- a/src/graph/Pages.ts +++ b/src/graph/Pages.ts @@ -66,8 +66,13 @@ export class Pages { child.addFriend(parent,RelationType.INFERRED, LinkDirection.FROM); parent.addFriend(child,RelationType.INFERRED, LinkDirection.TO); } else { - child.addParent(parent,RelationType.INFERRED, LinkDirection.FROM); - parent.addChild(child,RelationType.INFERRED, LinkDirection.TO); + if(this.plugin.settings.inverseInfer) { //https://github.com/zsviczian/excalibrain/issues/78 + child.addChild(parent,RelationType.INFERRED, LinkDirection.FROM); + parent.addParent(child,RelationType.INFERRED, LinkDirection.TO); + } else { + child.addParent(parent,RelationType.INFERRED, LinkDirection.FROM); + parent.addChild(child,RelationType.INFERRED, LinkDirection.TO); + } } }) }); @@ -101,8 +106,13 @@ export class Pages { newPage.addFriend(parent,RelationType.INFERRED, LinkDirection.FROM); parent.addFriend(newPage,RelationType.INFERRED, LinkDirection.TO); } else { - newPage.addParent(parent,RelationType.INFERRED, LinkDirection.FROM); - parent.addChild(newPage,RelationType.INFERRED, LinkDirection.TO); + if(this.plugin.settings.inverseInfer) { //https://github.com/zsviczian/excalibrain/issues/78 + newPage.addChild(parent,RelationType.INFERRED, LinkDirection.FROM); + parent.addParent(newPage,RelationType.INFERRED, LinkDirection.TO); + } else { + newPage.addParent(parent,RelationType.INFERRED, LinkDirection.FROM); + parent.addChild(newPage,RelationType.INFERRED, LinkDirection.TO); + } } this.add(childPath,newPage); }) diff --git a/src/lang/locale/en.ts b/src/lang/locale/en.ts index a53c167..594a8e2 100644 --- a/src/lang/locale/en.ts +++ b/src/lang/locale/en.ts @@ -10,6 +10,11 @@ export default { EXCALIBRAIN_FILE_DESC: "⚠ This file will be overwritten by the plugin. If you stop the script and make changes to the graph, you " + "should rename the file so your edits are preserved, because the next time you initiate ExcaliBrain your edits will be overwritten by " + "the automatically generated ExcaliBrain graph.", + INDEX_REFRESH_FREQ_NAME: "Index refresh frequency", + INDEX_REFRESH_FREQ_DESC: "ExcaliBrain will update its index whenever you switch work panes, in case a file has changed in your Vault since the last index update.
" + + "This setting is thus only relevant when you are typing in a markdown editor (not switching files or panes) and you still want ExcaliBrain to update it's graph as you type. " + + "Becuase frequent background index updates can be resource intensive you have an option to increase the time interval for the index-updates which in turn will reduce the " + + "overhead on your system.", HIERARCHY_HEAD: "Ontology", HIERARCHY_DESC: "Enter the Dataview field names separated by comma (,) that you will use to define link directions in your graph.
" + "You can also add fields to the ontology on the fly from the markdown editor by typing the new field at the beginning of a paragraph (e.g.: 'Consits of::') " + @@ -21,6 +26,8 @@ export default { "
  • A forward link is inferred as a CHILD
  • " + "
  • A backlink is inferred as a PARENT
  • " + "
  • If files mutually link to each other, they are FRIENDS
  • ", + REVERSE_NAME: "Reverse infer logic", + REVERSE_DESC: "Toggle ON: Treat backlinks as children and forward links as parents.
    Toggle OFF: Treat backlinks as parents and forward links as children", PARENTS_NAME: "Parents", CHILDREN_NAME: "Children", FRIENDS_NAME: "Friends", @@ -94,7 +101,7 @@ export default { NODESTYLE_PREFIX_NAME: "Prefix", NODESTYLE_PREFIX_DESC: "Prefix character or emoji to display in front of the node's label", NODESTYLE_BGCOLOR: "Background color", - NODESTYLE_BG_FILLSTYLE: "Bacground fill-style", + NODESTYLE_BG_FILLSTYLE: "Background fill-style", NODESTYLE_TEXTCOLOR: "Text color", NODESTYLE_BORDERCOLOR: "Border color", NODESTYLE_FONTSIZE: "Font size", diff --git a/src/main.ts b/src/main.ts index 6a0377e..8d3b854 100644 --- a/src/main.ts +++ b/src/main.ts @@ -357,9 +357,9 @@ export default class ExcaliBrain extends Plugin { name: t("COMMAND_START_POPOUT"), checkCallback: (checking:boolean) => { if(checking) { - return this.excalidrawAvailable(); + return !app.isMobile && this.excalidrawAvailable(); } - if(!this.excalidrawAvailable()) return; //still need this in case user sets a hotkey + if(!this.excalidrawAvailable() || app.isMobile) return; //still need this in case user sets a hotkey if(this.scene && !this.scene.terminated) { this.revealBrainLeaf();