mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-10-31 13:01:31 +08:00 
			
		
		
		
	change the heuristics to choose the best note path when ambiguous/incomplete/just noteId is provided, #1711
This commit is contained in:
		
							parent
							
								
									060d4fc27b
								
							
						
					
					
						commit
						9f002fa802
					
				| @ -253,6 +253,32 @@ class NoteShort { | |||||||
|         return noteAttributeCache.attributes[this.noteId]; |         return noteAttributeCache.attributes[this.noteId]; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     getAllNotePaths() { | ||||||
|  |         if (this.noteId === 'root') { | ||||||
|  |             return [['root']]; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         const parentNotes = this.getParentNotes(); | ||||||
|  |         let paths; | ||||||
|  | 
 | ||||||
|  |         if (parentNotes.length === 1) { // optimization for the most common case
 | ||||||
|  |             paths = parentNotes[0].getAllNotePaths(); | ||||||
|  |         } | ||||||
|  |         else { | ||||||
|  |             paths = []; | ||||||
|  | 
 | ||||||
|  |             for (const parentNote of parentNotes) { | ||||||
|  |                 paths.push(...parentNote.getAllNotePaths()); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         for (const path of paths) { | ||||||
|  |             path.push(this.noteId); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return paths; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     __filterAttrs(attributes, type, name) { |     __filterAttrs(attributes, type, name) { | ||||||
|         if (!type && !name) { |         if (!type && !name) { | ||||||
|             return attributes; |             return attributes; | ||||||
|  | |||||||
| @ -125,7 +125,7 @@ async function deleteNotes(branchIdsToDelete) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| async function moveNodeUpInHierarchy(node) { | async function moveNodeUpInHierarchy(node) { | ||||||
|     if (hoistedNoteService.isRootNode(node) |     if (hoistedNoteService.isHoistedNode(node) | ||||||
|         || hoistedNoteService.isTopLevelNode(node) |         || hoistedNoteService.isTopLevelNode(node) | ||||||
|         || node.getParent().data.noteType === 'search') { |         || node.getParent().data.noteType === 'search') { | ||||||
|         return; |         return; | ||||||
|  | |||||||
| @ -16,10 +16,10 @@ async function unhoist() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function isTopLevelNode(node) { | function isTopLevelNode(node) { | ||||||
|     return isRootNode(node.getParent()); |     return isHoistedNode(node.getParent()); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function isRootNode(node) { | function isHoistedNode(node) { | ||||||
|     // even though check for 'root' should not be necessary, we keep it just in case
 |     // even though check for 'root' should not be necessary, we keep it just in case
 | ||||||
|     return node.data.noteId === "root" |     return node.data.noteId === "root" | ||||||
|         || node.data.noteId === getHoistedNoteId(); |         || node.data.noteId === getHoistedNoteId(); | ||||||
| @ -55,6 +55,6 @@ export default { | |||||||
|     getHoistedNoteId, |     getHoistedNoteId, | ||||||
|     unhoist, |     unhoist, | ||||||
|     isTopLevelNode, |     isTopLevelNode, | ||||||
|     isRootNode, |     isHoistedNode, | ||||||
|     checkNoteAccess |     checkNoteAccess | ||||||
| } | } | ||||||
|  | |||||||
| @ -75,14 +75,10 @@ async function resolveNotePathToSegments(notePath, hoistedNoteId = 'root', logEr | |||||||
|                     console.log(utils.now(), `Did not find parent ${parentNoteId} (${parent ? parent.title : 'n/a'}) for child ${childNoteId} (${child.title}), available parents: ${parents.map(p => `${p.noteId} (${p.title})`)}`); |                     console.log(utils.now(), `Did not find parent ${parentNoteId} (${parent ? parent.title : 'n/a'}) for child ${childNoteId} (${child.title}), available parents: ${parents.map(p => `${p.noteId} (${p.title})`)}`); | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 const hoistedNote = await treeCache.getNote(hoistedNoteId); |                 const someNotePath = getSomeNotePath(child, hoistedNoteId); | ||||||
| 
 |  | ||||||
|                 const chosenParent = parents.find(parent => parent.hasAncestor(hoistedNote)) |  | ||||||
|                     || parents[0]; // if no parent is in hoisted subtree then it just doesn't matter and pick any
 |  | ||||||
|                 const someNotePath = getSomeNotePath(chosenParent); |  | ||||||
| 
 | 
 | ||||||
|                 if (someNotePath) { // in case it's root the path may be empty
 |                 if (someNotePath) { // in case it's root the path may be empty
 | ||||||
|                     const pathToRoot = someNotePath.split("/").reverse(); |                     const pathToRoot = someNotePath.split("/").reverse().slice(1); | ||||||
| 
 | 
 | ||||||
|                     for (const noteId of pathToRoot) { |                     for (const noteId of pathToRoot) { | ||||||
|                         effectivePath.push(noteId); |                         effectivePath.push(noteId); | ||||||
| @ -100,29 +96,35 @@ async function resolveNotePathToSegments(notePath, hoistedNoteId = 'root', logEr | |||||||
|     return effectivePath.reverse(); |     return effectivePath.reverse(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function getSomeNotePath(note) { | function getSomeNotePathSegments(note, hoistedNotePath = 'root') { | ||||||
|     utils.assertArguments(note); |     utils.assertArguments(note); | ||||||
| 
 | 
 | ||||||
|     const path = []; |     const notePaths = note.getAllNotePaths().map(path => ({ | ||||||
|  |         notePath: path, | ||||||
|  |         isInHoistedSubTree: path.includes(hoistedNotePath), | ||||||
|  |         isArchived: path.find(noteId => treeCache.notes[noteId].hasLabel('archived')), | ||||||
|  |         isSearch: path.find(noteId => treeCache.notes[noteId].type === 'search') | ||||||
|  |     })); | ||||||
| 
 | 
 | ||||||
|     let cur = note; |     notePaths.sort((a, b) => { | ||||||
|  |         if (a.isInHoistedSubTree !== b.isInHoistedSubTree) { | ||||||
|  |             return a.isInHoistedSubTree ? -1 : 1; | ||||||
|  |         } else if (a.isSearch !== b.isSearch) { | ||||||
|  |             return a.isSearch ? 1 : -1; | ||||||
|  |         } else if (a.isArchived !== b.isArchived) { | ||||||
|  |             return a.isArchived ? 1 : -1; | ||||||
|  |         } else { | ||||||
|  |             return a.notePath.length - b.notePath.length; | ||||||
|  |         } | ||||||
|  |     }); | ||||||
| 
 | 
 | ||||||
|     while (cur.noteId !== 'root') { |     return notePaths[0].notePath; | ||||||
|         path.push(cur.noteId); |  | ||||||
| 
 |  | ||||||
|         const parents = cur.getParentNotes().filter(note => note.type !== 'search'); |  | ||||||
| 
 |  | ||||||
|         if (!parents.length) { |  | ||||||
|             logError(`Can't find parents for note ${cur.noteId}`); |  | ||||||
|             return; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|         cur = parents[0]; | function getSomeNotePath(note, hoistedNotePath = 'root') { | ||||||
|     } |     const notePath = getSomeNotePathSegments(note, hoistedNotePath); | ||||||
| 
 | 
 | ||||||
|     path.push('root'); |     return notePath.join('/'); | ||||||
| 
 |  | ||||||
|     return path.reverse().join('/'); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| async function sortAlphabetically(noteId) { | async function sortAlphabetically(noteId) { | ||||||
| @ -142,7 +144,7 @@ ws.subscribeToMessages(message => { | |||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| function getParentProtectedStatus(node) { | function getParentProtectedStatus(node) { | ||||||
|     return hoistedNoteService.isRootNode(node) ? 0 : node.getParent().data.isProtected; |     return hoistedNoteService.isHoistedNode(node) ? 0 : node.getParent().data.isProtected; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function getNoteIdFromNotePath(notePath) { | function getNoteIdFromNotePath(notePath) { | ||||||
| @ -202,7 +204,7 @@ function getNotePath(node) { | |||||||
| 
 | 
 | ||||||
|     const path = []; |     const path = []; | ||||||
| 
 | 
 | ||||||
|     while (node && !hoistedNoteService.isRootNode(node)) { |     while (node) { | ||||||
|         if (node.data.noteId) { |         if (node.data.noteId) { | ||||||
|             path.push(node.data.noteId); |             path.push(node.data.noteId); | ||||||
|         } |         } | ||||||
| @ -210,10 +212,6 @@ function getNotePath(node) { | |||||||
|         node = node.getParent(); |         node = node.getParent(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     if (node) { // null node can happen directly after unhoisting when tree is still hoisted but option has been changed already
 |  | ||||||
|         path.push(node.data.noteId); // root or hoisted noteId
 |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return path.reverse().join("/"); |     return path.reverse().join("/"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -317,6 +315,7 @@ export default { | |||||||
|     resolveNotePath, |     resolveNotePath, | ||||||
|     resolveNotePathToSegments, |     resolveNotePathToSegments, | ||||||
|     getSomeNotePath, |     getSomeNotePath, | ||||||
|  |     getSomeNotePathSegments, | ||||||
|     getParentProtectedStatus, |     getParentProtectedStatus, | ||||||
|     getNotePath, |     getNotePath, | ||||||
|     getNoteIdFromNotePath, |     getNoteIdFromNotePath, | ||||||
|  | |||||||
| @ -1210,18 +1210,10 @@ export default class NoteTreeWidget extends TabAwareWidget { | |||||||
|                 this.tree.clearFilter(); |                 this.tree.clearFilter(); | ||||||
|             } |             } | ||||||
|             else { |             else { | ||||||
|                 let found = false;console.log(this.tabContext.notePath, this.tabContext.hoistedNoteId, "ZZZ"); |  | ||||||
| 
 |  | ||||||
|                 // hack when hoisted note is cloned then it could be filtered multiple times while we want only 1
 |                 // hack when hoisted note is cloned then it could be filtered multiple times while we want only 1
 | ||||||
|                 this.tree.filterBranches(node => { |                 this.tree.filterBranches(node => | ||||||
|                     if (found) { |                     node.data.noteId === this.tabContext.hoistedNoteId // optimization to not having always resolve the node path
 | ||||||
|                         return false; |                     && treeService.getNotePath(node) === hoistedNotePath); | ||||||
|                     } |  | ||||||
| 
 |  | ||||||
|                     found = node.data.noteId === this.tabContext.hoistedNoteId; |  | ||||||
| 
 |  | ||||||
|                     return found; |  | ||||||
|                 }); |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 zadam
						zadam