mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-10-31 04:51:31 +08:00 
			
		
		
		
	improvements in frontend sync (WIP)
This commit is contained in:
		
							parent
							
								
									66374bf95f
								
							
						
					
					
						commit
						d0747b125c
					
				| @ -41,44 +41,6 @@ class Attribute { | ||||
|         return `Attribute(attributeId=${this.attributeId}, type=${this.type}, name=${this.name}, value=${this.value})`; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * @return {boolean} - returns true if this attribute has the potential to influence the note in the argument. | ||||
|      *         That can happen in multiple ways: | ||||
|      *         1. attribute is owned by the note | ||||
|      *         2. attribute is owned by the template of the note | ||||
|      *         3. attribute is owned by some note's ancestor and is inheritable | ||||
|      */ | ||||
|     isAffecting(affectedNote) { | ||||
|         if (!affectedNote) { | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         const attrNote = this.getNote(); | ||||
| 
 | ||||
|         if (!attrNote) { | ||||
|             // the note (owner of the attribute) is not even loaded into the cache so it should not affect anything else
 | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         const owningNotes = [affectedNote, ...affectedNote.getTemplateNotes()]; | ||||
| 
 | ||||
|         for (const owningNote of owningNotes) { | ||||
|             if (owningNote.noteId === attrNote.noteId) { | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if (this.isInheritable) { | ||||
|             for (const owningNote of owningNotes) { | ||||
|                 if (owningNote.hasAncestor(attrNote)) { | ||||
|                     return true; | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     isDefinition() { | ||||
|         return this.type === 'label' && (this.name.startsWith('label:') || this.name.startsWith('relation:')); | ||||
|     } | ||||
|  | ||||
| @ -1,4 +1,5 @@ | ||||
| import server from './server.js'; | ||||
| import froca from './froca.js'; | ||||
| 
 | ||||
| async function addLabel(noteId, name, value = "") { | ||||
|     await server.put(`notes/${noteId}/attribute`, { | ||||
| @ -20,8 +21,47 @@ async function removeAttributeById(noteId, attributeId) { | ||||
|     await server.remove(`notes/${noteId}/attributes/${attributeId}`); | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * @return {boolean} - returns true if this attribute has the potential to influence the note in the argument. | ||||
|  *         That can happen in multiple ways: | ||||
|  *         1. attribute is owned by the note | ||||
|  *         2. attribute is owned by the template of the note | ||||
|  *         3. attribute is owned by some note's ancestor and is inheritable | ||||
|  */ | ||||
| function isAffecting(attrRow, affectedNote) { | ||||
|     if (!affectedNote || !attrRow) { | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     const attrNote = froca.notes[attrRow.noteId]; | ||||
| 
 | ||||
|     if (!attrNote) { | ||||
|         // the note (owner of the attribute) is not even loaded into the cache so it should not affect anything else
 | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     const owningNotes = [affectedNote, ...affectedNote.getTemplateNotes()]; | ||||
| 
 | ||||
|     for (const owningNote of owningNotes) { | ||||
|         if (owningNote.noteId === attrNote.noteId) { | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if (this.isInheritable) { | ||||
|         for (const owningNote of owningNotes) { | ||||
|             if (owningNote.hasAncestor(attrNote)) { | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return false; | ||||
| } | ||||
| 
 | ||||
| export default { | ||||
|     addLabel, | ||||
|     setLabel, | ||||
|     removeAttributeById | ||||
|     removeAttributeById, | ||||
|     isAffecting | ||||
| } | ||||
|  | ||||
| @ -8,6 +8,7 @@ import froca from "../../services/froca.js"; | ||||
| import attributeRenderer from "../../services/attribute_renderer.js"; | ||||
| import noteCreateService from "../../services/note_create.js"; | ||||
| import treeService from "../../services/tree.js"; | ||||
| import attributeService from "../../services/attributes.js"; | ||||
| 
 | ||||
| const HELP_TEXT = ` | ||||
| <p>To add label, just type e.g. <code>#rock</code> or if you want to add also value then e.g. <code>#year = 2020</code></p>  | ||||
| @ -511,7 +512,7 @@ export default class AttributeEditorWidget extends NoteContextAwareWidget { | ||||
|     } | ||||
| 
 | ||||
|     entitiesReloadedEvent({loadResults}) { | ||||
|         if (loadResults.getAttributes(this.componentId).find(attr => attr.isAffecting(this.note))) { | ||||
|         if (loadResults.getAttributes(this.componentId).find(attr => attributeService.isAffecting(attr, this.note))) { | ||||
|             this.refresh(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -1,5 +1,4 @@ | ||||
| import NoteContextAwareWidget from "./note_context_aware_widget.js"; | ||||
| import utils from "../services/utils.js"; | ||||
| import protectedSessionHolder from "../services/protected_session_holder.js"; | ||||
| import SpacedUpdate from "../services/spaced_update.js"; | ||||
| import server from "../services/server.js"; | ||||
| @ -20,6 +19,7 @@ import DeletedTypeWidget from "./type_widgets/deleted.js"; | ||||
| import ReadOnlyTextTypeWidget from "./type_widgets/read_only_text.js"; | ||||
| import ReadOnlyCodeTypeWidget from "./type_widgets/read_only_code.js"; | ||||
| import NoneTypeWidget from "./type_widgets/none.js"; | ||||
| import attributeService from "../services/attributes.js"; | ||||
| 
 | ||||
| const TPL = ` | ||||
| <div class="note-detail"> | ||||
| @ -246,12 +246,12 @@ export default class NoteDetailWidget extends NoteContextAwareWidget { | ||||
|             const label = attrs.find(attr => | ||||
|                 attr.type === 'label' | ||||
|                 && ['readOnly', 'autoReadOnlyDisabled', 'cssClass', 'displayRelations'].includes(attr.name) | ||||
|                 && attr.isAffecting(this.note)); | ||||
|                 && attributeService.isAffecting(attr, this.note)); | ||||
| 
 | ||||
|             const relation = attrs.find(attr => | ||||
|                 attr.type === 'relation' | ||||
|                 && ['template', 'renderNote'].includes(attr.name) | ||||
|                 && attr.isAffecting(this.note)); | ||||
|                 && attributeService.isAffecting(attr, this.note)); | ||||
| 
 | ||||
|             if (label || relation) { | ||||
|                 // probably incorrect event
 | ||||
|  | ||||
| @ -126,7 +126,7 @@ export default class NoteIconWidget extends NoteContextAwareWidget { | ||||
|         for (const attr of loadResults.getAttributes()) { | ||||
|             if (attr.type === 'label' | ||||
|                 && ['iconClass', 'workspaceIconClass'].includes(attr.name) | ||||
|                 && attr.isAffecting(this.note)) { | ||||
|                 && attributeService.isAffecting(attr, this.note)) { | ||||
| 
 | ||||
|                 this.refresh(); | ||||
|                 break; | ||||
|  | ||||
| @ -972,36 +972,36 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { | ||||
|         const noteIdsToUpdate = new Set(); | ||||
|         const noteIdsToReload = new Set(); | ||||
| 
 | ||||
|         for (const attr of loadResults.getAttributes()) { | ||||
|             if (attr.type === 'label' && ['iconClass', 'cssClass', 'workspace', 'workspaceIconClass', 'archived'].includes(attr.name)) { | ||||
|                 if (attr.isInheritable) { | ||||
|                     noteIdsToReload.add(attr.noteId); | ||||
|         for (const ecAttr of loadResults.getAttributes()) { | ||||
|             if (ecAttr.type === 'label' && ['iconClass', 'cssClass', 'workspace', 'workspaceIconClass', 'archived'].includes(ecAttr.name)) { | ||||
|                 if (ecAttr.isInheritable) { | ||||
|                     noteIdsToReload.add(ecAttr.noteId); | ||||
|                 } | ||||
|                 else { | ||||
|                     noteIdsToUpdate.add(attr.noteId); | ||||
|                     noteIdsToUpdate.add(ecAttr.noteId); | ||||
|                 } | ||||
|             } | ||||
|             else if (attr.type === 'relation' && attr.name === 'template') { | ||||
|             else if (ecAttr.type === 'relation' && ecAttr.name === 'template') { | ||||
|                 // missing handling of things inherited from template
 | ||||
|                 noteIdsToReload.add(attr.noteId); | ||||
|                 noteIdsToReload.add(ecAttr.noteId); | ||||
|             } | ||||
|             else if (attr.type === 'relation' && attr.name === 'imageLink') { | ||||
|                 const note = froca.getNoteFromCache(attr.noteId); | ||||
|             else if (ecAttr.type === 'relation' && ecAttr.name === 'imageLink') { | ||||
|                 const note = froca.getNoteFromCache(ecAttr.noteId); | ||||
| 
 | ||||
|                 if (note && note.getChildNoteIds().includes(attr.value)) { | ||||
|                 if (note && note.getChildNoteIds().includes(ecAttr.value)) { | ||||
|                     // there's new/deleted imageLink betwen note and its image child - which can show/hide
 | ||||
|                     // the image (if there is a imageLink relation between parent and child then it is assumed to be "contained" in the note and thus does not have to be displayed in the tree)
 | ||||
|                     noteIdsToReload.add(attr.noteId); | ||||
|                     noteIdsToReload.add(ecAttr.noteId); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         for (const branch of loadResults.getBranches()) { | ||||
|         for (const ecBranch of loadResults.getBranches()) { | ||||
|             // adding noteId itself to update all potential clones
 | ||||
|             noteIdsToUpdate.add(branch.noteId); | ||||
|             noteIdsToUpdate.add(ecBranch.noteId); | ||||
| 
 | ||||
|             for (const node of this.getNodesByBranch(branch)) { | ||||
|                 if (branch.isDeleted) { | ||||
|             for (const node of this.getNodesByBranch(ecBranch)) { | ||||
|                 if (ecBranch.isDeleted) { | ||||
|                     if (node.isActive()) { | ||||
|                         const newActiveNode = node.getNextSibling() | ||||
|                             || node.getPrevSibling() | ||||
| @ -1016,22 +1016,22 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { | ||||
|                         node.remove(); | ||||
|                     } | ||||
| 
 | ||||
|                     noteIdsToUpdate.add(branch.parentNoteId); | ||||
|                     noteIdsToUpdate.add(ecBranch.parentNoteId); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             if (!branch.isDeleted) { | ||||
|                 for (const parentNode of this.getNodesByNoteId(branch.parentNoteId)) { | ||||
|             if (!ecBranch.isDeleted) { | ||||
|                 for (const parentNode of this.getNodesByNoteId(ecBranch.parentNoteId)) { | ||||
|                     if (parentNode.isFolder() && !parentNode.isLoaded()) { | ||||
|                         continue; | ||||
|                     } | ||||
| 
 | ||||
|                     const found = (parentNode.getChildren() || []).find(child => child.data.noteId === branch.noteId); | ||||
|                     const found = (parentNode.getChildren() || []).find(child => child.data.noteId === ecBranch.noteId); | ||||
| 
 | ||||
|                     if (!found) { | ||||
|                         // make sure it's loaded
 | ||||
|                         await froca.getNote(branch.noteId); | ||||
|                         const frocaBranch = froca.getBranch(branch.branchId); | ||||
|                         await froca.getNote(ecBranch.noteId); | ||||
|                         const frocaBranch = froca.getBranch(ecBranch.branchId); | ||||
| 
 | ||||
|                             // we're forcing lazy since it's not clear if the whole required subtree is in froca
 | ||||
|                         parentNode.addChildren([this.prepareNode(frocaBranch, true)]); | ||||
| @ -1039,7 +1039,7 @@ export default class NoteTreeWidget extends NoteContextAwareWidget { | ||||
|                         this.sortChildren(parentNode); | ||||
| 
 | ||||
|                         // this might be a first child which would force an icon change
 | ||||
|                         noteIdsToUpdate.add(branch.parentNoteId); | ||||
|                         noteIdsToUpdate.add(ecBranch.parentNoteId); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| import NoteContextAwareWidget from "../note_context_aware_widget.js"; | ||||
| import AttributeDetailWidget from "../attribute_widgets/attribute_detail.js"; | ||||
| import attributeRenderer from "../../services/attribute_renderer.js"; | ||||
| import attributeService from "../../services/attributes.js"; | ||||
| 
 | ||||
| const TPL = ` | ||||
| <div class="inherited-attributes-widget"> | ||||
| @ -88,7 +89,7 @@ export default class InheritedAttributesWidget extends NoteContextAwareWidget { | ||||
|     } | ||||
| 
 | ||||
|     entitiesReloadedEvent({loadResults}) { | ||||
|         if (loadResults.getAttributes(this.componentId).find(attr => attr.isAffecting(this.note))) { | ||||
|         if (loadResults.getAttributes(this.componentId).find(attr => attributeService.isAffecting(attr, this.note))) { | ||||
|             this.refresh(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @ -1,6 +1,7 @@ | ||||
| import NoteContextAwareWidget from "../note_context_aware_widget.js"; | ||||
| import AttributeDetailWidget from "../attribute_widgets/attribute_detail.js"; | ||||
| import AttributeEditorWidget from "../attribute_widgets/attribute_editor.js"; | ||||
| import attributeService from "../../services/attributes.js"; | ||||
| 
 | ||||
| const TPL = ` | ||||
| <div class="attribute-list"> | ||||
| @ -75,7 +76,7 @@ export default class OwnedAttributeListWidget extends NoteContextAwareWidget { | ||||
|     } | ||||
| 
 | ||||
|     entitiesReloadedEvent({loadResults}) { | ||||
|         if (loadResults.getAttributes(this.componentId).find(attr => attr.isAffecting(this.note))) { | ||||
|         if (loadResults.getAttributes(this.componentId).find(attr => attributeService.isAffecting(attr, this.note))) { | ||||
|             this.refreshWithNote(this.note, true); | ||||
| 
 | ||||
|             this.getTitle(this.note); | ||||
|  | ||||
| @ -3,6 +3,7 @@ import ws from "../../services/ws.js"; | ||||
| import treeService from "../../services/tree.js"; | ||||
| import noteAutocompleteService from "../../services/note_autocomplete.js"; | ||||
| import NoteContextAwareWidget from "../note_context_aware_widget.js"; | ||||
| import attributeService from "../../services/attributes.js"; | ||||
| 
 | ||||
| const TPL = ` | ||||
| <div> | ||||
| @ -294,7 +295,7 @@ export default class PromotedAttributesWidget extends NoteContextAwareWidget { | ||||
|     } | ||||
| 
 | ||||
|     entitiesReloadedEvent({loadResults}) { | ||||
|         if (loadResults.getAttributes(this.componentId).find(attr => attr.isAffecting(this.note))) { | ||||
|         if (loadResults.getAttributes(this.componentId).find(attr => attributeService.isAffecting(attr, this.note))) { | ||||
|             this.refresh(); | ||||
| 
 | ||||
|             this.getTitle(this.note); | ||||
|  | ||||
| @ -4,6 +4,7 @@ import utils from "../services/utils.js"; | ||||
| import keyboardActionService from "../services/keyboard_actions.js"; | ||||
| import appContext from "../services/app_context.js"; | ||||
| import froca from "../services/froca.js"; | ||||
| import attributeService from "../services/attributes.js"; | ||||
| 
 | ||||
| /*! | ||||
|  * Draggabilly v2.3.0 | ||||
| @ -668,7 +669,7 @@ export default class TabRowWidget extends BasicWidget { | ||||
|             if (loadResults.isNoteReloaded(noteContext.noteId) || | ||||
|                 loadResults.getAttributes().find(attr => | ||||
|                     ['workspace', 'workspaceIconClass', 'workspaceTabBackgroundColor'].includes(attr.name) | ||||
|                     && attr.isAffecting(noteContext.note)) | ||||
|                     && attributeService.isAffecting(attr, noteContext.note)) | ||||
|             ) { | ||||
|                 const $tab = this.getTabById(noteContext.ntxId); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 zadam
						zadam