mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-10-31 13:01:31 +08:00 
			
		
		
		
	link map lazy loading
This commit is contained in:
		
							parent
							
								
									e48bbe5b19
								
							
						
					
					
						commit
						9a147365f5
					
				| @ -56,7 +56,7 @@ | |||||||
|     "jimp": "0.16.1", |     "jimp": "0.16.1", | ||||||
|     "joplin-turndown-plugin-gfm": "1.0.12", |     "joplin-turndown-plugin-gfm": "1.0.12", | ||||||
|     "jsdom": "16.6.0", |     "jsdom": "16.6.0", | ||||||
|     "mime-types": "2.1.30", |     "mime-types": "2.1.31", | ||||||
|     "multer": "1.4.2", |     "multer": "1.4.2", | ||||||
|     "node-abi": "2.30.0", |     "node-abi": "2.30.0", | ||||||
|     "open": "8.2.0", |     "open": "8.2.0", | ||||||
| @ -89,7 +89,7 @@ | |||||||
|     "jsdoc": "3.6.7", |     "jsdoc": "3.6.7", | ||||||
|     "lorem-ipsum": "2.0.3", |     "lorem-ipsum": "2.0.3", | ||||||
|     "rcedit": "3.0.0", |     "rcedit": "3.0.0", | ||||||
|     "webpack": "5.37.1", |     "webpack": "5.38.1", | ||||||
|     "webpack-cli": "4.7.0" |     "webpack-cli": "4.7.0" | ||||||
|   }, |   }, | ||||||
|   "optionalDependencies": { |   "optionalDependencies": { | ||||||
|  | |||||||
| @ -175,6 +175,8 @@ export default class CollapsibleSectionContainer extends NoteContextAwareWidget | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     async refreshWithNote(note, noExplicitActivation = false) { |     async refreshWithNote(note, noExplicitActivation = false) { | ||||||
|  |         this.lastNoteType = note.type; | ||||||
|  | 
 | ||||||
|         let $sectionToActivate, $lastActiveSection; |         let $sectionToActivate, $lastActiveSection; | ||||||
| 
 | 
 | ||||||
|         this.$titleContainer.empty(); |         this.$titleContainer.empty(); | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ import NoteContextAwareWidget from "../note_context_aware_widget.js"; | |||||||
| import froca from "../../services/froca.js"; | import froca from "../../services/froca.js"; | ||||||
| import libraryLoader from "../../services/library_loader.js"; | import libraryLoader from "../../services/library_loader.js"; | ||||||
| import server from "../../services/server.js"; | import server from "../../services/server.js"; | ||||||
|  | import appContext from "../../services/app_context.js"; | ||||||
| 
 | 
 | ||||||
| const TPL = ` | const TPL = ` | ||||||
| <div class="link-map-widget"> | <div class="link-map-widget"> | ||||||
| @ -117,6 +118,9 @@ export default class LinkMapWidget extends NoteContextAwareWidget { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     async refreshWithNote(note) { |     async refreshWithNote(note) { | ||||||
|  |         this.linkIdToLinkMap = {}; | ||||||
|  |         this.noteIdToLinkCountMap = {}; | ||||||
|  | 
 | ||||||
|         this.$container.empty(); |         this.$container.empty(); | ||||||
| 
 | 
 | ||||||
|         await libraryLoader.requireLibrary(libraryLoader.FORCE_GRAPH); |         await libraryLoader.requireLibrary(libraryLoader.FORCE_GRAPH); | ||||||
| @ -153,7 +157,7 @@ export default class LinkMapWidget extends NoteContextAwareWidget { | |||||||
|         this.graph.d3Force('charge').strength(-30); |         this.graph.d3Force('charge').strength(-30); | ||||||
|         this.graph.d3Force('charge').distanceMax(400); |         this.graph.d3Force('charge').distanceMax(400); | ||||||
| 
 | 
 | ||||||
|         this.renderData(await this.loadNotesAndRelations()); |         this.renderData(await this.loadNotesAndRelations(this.noteId,1)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     renderData(data, zoomToFit = true, zoomPadding = 10) { |     renderData(data, zoomToFit = true, zoomPadding = 10) { | ||||||
| @ -164,61 +168,72 @@ export default class LinkMapWidget extends NoteContextAwareWidget { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     centerOnNode(node) { |  | ||||||
|         this.nodeClicked(node); |  | ||||||
| 
 |  | ||||||
|         this.graph.centerAt(node.x, node.y, 1000); |  | ||||||
|         this.graph.zoom(6, 2000); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     async nodeClicked(node) { |     async nodeClicked(node) { | ||||||
|         if (!node.expanded) { |         if (!node.expanded) { | ||||||
|             const neighborGraph = await fetchNeighborGraph(node.id); |             this.renderData( | ||||||
| 
 |                 await this.loadNotesAndRelations(node.id,1), | ||||||
|             addToTasGraph(neighborGraph); |                 false | ||||||
| 
 |             ); | ||||||
|             renderData(getTasGraph(), false); |         } | ||||||
|  |         else { | ||||||
|  |             await appContext.tabManager.getActiveContext().setNote(node.id); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     async loadNotesAndRelations(options = {}) { |     async loadNotesAndRelations(noteId, maxDepth) { | ||||||
|         const {noteIdToLinkCountMap, links} = await server.post(`notes/${this.note.noteId}/link-map`, { |         const resp = await server.post(`notes/${noteId}/link-map`, { | ||||||
|             maxNotes: 30, |             maxNotes: 1000, | ||||||
|             maxDepth: 1 |             maxDepth | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         // preload all notes
 |         this.noteIdToLinkCountMap = {...this.noteIdToLinkCountMap, ...resp.noteIdToLinkCountMap}; | ||||||
|         const notes = await froca.getNotes(Object.keys(noteIdToLinkCountMap), true); |  | ||||||
| 
 | 
 | ||||||
|         const noteIdToLinkMap = {}; |         for (const link of resp.links) { | ||||||
| 
 |             this.linkIdToLinkMap[link.id] = link; | ||||||
|         for (const link of links) { |  | ||||||
|             noteIdToLinkMap[link.sourceNoteId] = noteIdToLinkMap[link.sourceNoteId] || []; |  | ||||||
|             noteIdToLinkMap[link.sourceNoteId].push(link); |  | ||||||
| 
 |  | ||||||
|             noteIdToLinkMap[link.targetNoteId] = noteIdToLinkMap[link.targetNoteId] || []; |  | ||||||
|             noteIdToLinkMap[link.targetNoteId].push(link); |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         console.log(notes.map(note => ({ |         // preload all notes
 | ||||||
|             id: note.noteId, |         const notes = await froca.getNotes(Object.keys(this.noteIdToLinkCountMap), true); | ||||||
|             name: note.title, | 
 | ||||||
|             type: note.type, |         const noteIdToLinkIdMap = {}; | ||||||
|             expanded: noteIdToLinkCountMap[note.noteId] === noteIdToLinkMap[note.noteId].length |         const linksGroupedBySourceTarget = {}; | ||||||
|         }))) | 
 | ||||||
|  |         for (const link of Object.values(this.linkIdToLinkMap)) { | ||||||
|  |             noteIdToLinkIdMap[link.sourceNoteId] = noteIdToLinkIdMap[link.sourceNoteId] || new Set(); | ||||||
|  |             noteIdToLinkIdMap[link.sourceNoteId].add(link.id); | ||||||
|  | 
 | ||||||
|  |             noteIdToLinkIdMap[link.targetNoteId] = noteIdToLinkIdMap[link.targetNoteId] || new Set(); | ||||||
|  |             noteIdToLinkIdMap[link.targetNoteId].add(link.id); | ||||||
|  | 
 | ||||||
|  |             const key = `${link.sourceNoteId}-${link.targetNoteId}`; | ||||||
|  | 
 | ||||||
|  |             if (key in linksGroupedBySourceTarget) { | ||||||
|  |                 if (!linksGroupedBySourceTarget[key].names.includes(link.name)) { | ||||||
|  |                     linksGroupedBySourceTarget[key].names.push(link.name); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             else { | ||||||
|  |                 linksGroupedBySourceTarget[key] = { | ||||||
|  |                     id: key, | ||||||
|  |                     sourceNoteId: link.sourceNoteId, | ||||||
|  |                     targetNoteId: link.targetNoteId, | ||||||
|  |                     names: [link.name] | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|         return { |         return { | ||||||
|             nodes: notes.map(note => ({ |             nodes: notes.map(note => ({ | ||||||
|                 id: note.noteId, |                 id: note.noteId, | ||||||
|                 name: note.title, |                 name: note.title, | ||||||
|                 type: note.type, |                 type: note.type, | ||||||
|                 expanded: noteIdToLinkCountMap[note.noteId] === noteIdToLinkMap[note.noteId].length |                 expanded: this.noteIdToLinkCountMap[note.noteId] === noteIdToLinkIdMap[note.noteId].size | ||||||
|             })), |             })), | ||||||
|             links: links.map(link => ({ |             links: Object.values(linksGroupedBySourceTarget).map(link => ({ | ||||||
|                 id: link.sourceNoteId + "-" + link.name + "-" + link.targetNoteId, |                 id: link.id, | ||||||
|                 source: link.sourceNoteId, |                 source: link.sourceNoteId, | ||||||
|                 target: link.targetNoteId, |                 target: link.targetNoteId, | ||||||
|                 name: link.name |                 name: link.names.join(", ") | ||||||
|             })) |             })) | ||||||
|         }; |         }; | ||||||
|     } |     } | ||||||
| @ -260,9 +275,9 @@ export default class LinkMapWidget extends NoteContextAwareWidget { | |||||||
|     paintNode(node, color, ctx) { |     paintNode(node, color, ctx) { | ||||||
|         const {x, y} = node; |         const {x, y} = node; | ||||||
| 
 | 
 | ||||||
|         ctx.fillStyle = color; |         ctx.fillStyle = node.id === this.noteId ? 'red' : color; | ||||||
|         ctx.beginPath(); |         ctx.beginPath(); | ||||||
|         ctx.arc(x, y, 4, 0, 2 * Math.PI, false); |         ctx.arc(x, y, node.id === this.noteId ? 8 : 4, 0, 2 * Math.PI, false); | ||||||
|         ctx.fill(); |         ctx.fill(); | ||||||
| 
 | 
 | ||||||
|         if (this.zoomLevel < 2) { |         if (this.zoomLevel < 2) { | ||||||
| @ -288,7 +303,7 @@ export default class LinkMapWidget extends NoteContextAwareWidget { | |||||||
|             title = title.substr(0, 15) + "..."; |             title = title.substr(0, 15) + "..."; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         ctx.fillText(title, x, y + 7); |         ctx.fillText(title, x, y + (node.id === this.noteId ? 11 : 7)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     stringToColor(str) { |     stringToColor(str) { | ||||||
| @ -306,21 +321,7 @@ export default class LinkMapWidget extends NoteContextAwareWidget { | |||||||
| 
 | 
 | ||||||
|     entitiesReloadedEvent({loadResults}) { |     entitiesReloadedEvent({loadResults}) { | ||||||
|         if (loadResults.getAttributes().find(attr => attr.type === 'relation' && (attr.noteId === this.noteId || attr.value === this.noteId))) { |         if (loadResults.getAttributes().find(attr => attr.type === 'relation' && (attr.noteId === this.noteId || attr.value === this.noteId))) { | ||||||
|             this.noteSwitched(); |             this.refresh(); | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         const changedNoteIds = loadResults.getNoteIds(); |  | ||||||
| 
 |  | ||||||
|         if (changedNoteIds.length > 0) { |  | ||||||
|             const $linkMapContainer = this.$widget.find('.link-map-container'); |  | ||||||
| 
 |  | ||||||
|             for (const noteId of changedNoteIds) { |  | ||||||
|                 const note = froca.notes[noteId]; |  | ||||||
| 
 |  | ||||||
|                 if (note) { |  | ||||||
|                     $linkMapContainer.find(`a[data-note-path="${noteId}"]`).text(note.title); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
| @ -40,9 +40,9 @@ function collectRelations(noteId, relations, depth) { | |||||||
|             relations.add(relation); |             relations.add(relation); | ||||||
| 
 | 
 | ||||||
|             if (relation.noteId !== noteId) { |             if (relation.noteId !== noteId) { | ||||||
|                 collectRelations(relation.noteId, relations, depth--); |                 collectRelations(relation.noteId, relations, depth - 1); | ||||||
|             } else if (relation.value !== noteId) { |             } else if (relation.value !== noteId) { | ||||||
|                 collectRelations(relation.value, relations, depth--); |                 collectRelations(relation.value, relations, depth - 1); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -71,6 +71,7 @@ function getLinkMap(req) { | |||||||
|     return { |     return { | ||||||
|         noteIdToLinkCountMap, |         noteIdToLinkCountMap, | ||||||
|         links: Array.from(relations).map(rel => ({ |         links: Array.from(relations).map(rel => ({ | ||||||
|  |             id: rel.noteId + "-" + rel.name + "-" + rel.value, | ||||||
|             sourceNoteId: rel.noteId, |             sourceNoteId: rel.noteId, | ||||||
|             targetNoteId: rel.value, |             targetNoteId: rel.value, | ||||||
|             name: rel.name |             name: rel.name | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 zadam
						zadam