Browse Source

:art: Improve dynamic anchor text auto-refresh stability https://github.com/siyuan-note/siyuan/issues/8234

Daniel 10 months ago
parent
commit
e5df997e19
2 changed files with 25 additions and 7 deletions
  1. 23 5
      kernel/model/transaction.go
  2. 2 2
      kernel/util/websocket.go

+ 23 - 5
kernel/model/transaction.go

@@ -1439,8 +1439,9 @@ func refreshDynamicRefText(updatedDefNode *ast.Node, updatedTree *parse.Tree) {
 func refreshDynamicRefTexts(updatedDefNodes map[string]*ast.Node, updatedTrees map[string]*parse.Tree) {
 	// 1. 更新引用的动态锚文本
 	treeRefNodeIDs := map[string]*hashset.Set{}
+	var changedParentNodes []*ast.Node
 	for _, updateNode := range updatedDefNodes {
-		refs := getRefsCacheByDefNode(updateNode)
+		refs, parentNodes := getRefsCacheByDefNode(updateNode)
 		for _, ref := range refs {
 			if refIDs, ok := treeRefNodeIDs[ref.RootID]; !ok {
 				refIDs = hashset.New()
@@ -1450,6 +1451,14 @@ func refreshDynamicRefTexts(updatedDefNodes map[string]*ast.Node, updatedTrees m
 				refIDs.Add(ref.BlockID)
 			}
 		}
+		if 0 < len(parentNodes) {
+			changedParentNodes = append(changedParentNodes, parentNodes...)
+		}
+	}
+	if 0 < len(changedParentNodes) {
+		for _, parent := range changedParentNodes {
+			updatedDefNodes[parent.ID] = parent
+		}
 	}
 
 	changedRefTree := map[string]*parse.Tree{}
@@ -1471,13 +1480,15 @@ func refreshDynamicRefTexts(updatedDefNodes map[string]*ast.Node, updatedTrees m
 			}
 
 			if n.IsBlock() && refNodeIDs.Contains(n.ID) {
-				changed := updateRefText(n, updatedDefNodes)
+				changed, changedDefNodes := updateRefText(n, updatedDefNodes)
 				if !refTreeChanged && changed {
 					refTreeChanged = true
 				}
 
 				// 推送动态锚文本节点刷新
-				task.AppendAsyncTaskWithDelay(task.ReloadProtyleBlock, 200*time.Millisecond, util.PushReloadBlock, refTreeID, n.ID)
+				for _, defNode := range changedDefNodes {
+					task.AppendAsyncTaskWithDelay(task.ReloadProtyleBlock, 200*time.Millisecond, util.PushReloadBlock, refTreeID, n.ID, defNode.id, defNode.refText)
+				}
 				return ast.WalkContinue
 			}
 			return ast.WalkContinue
@@ -1532,7 +1543,7 @@ func refreshDynamicRefTexts(updatedDefNodes map[string]*ast.Node, updatedTrees m
 	}
 }
 
-func getRefsCacheByDefNode(updateNode *ast.Node) (ret []*sql.Ref) {
+func getRefsCacheByDefNode(updateNode *ast.Node) (ret []*sql.Ref, changedParentNodes []*ast.Node) {
 	ret = sql.GetRefsCacheByDefID(updateNode.ID)
 	if nil != updateNode.Parent && ast.NodeDocument != updateNode.Parent.Type &&
 		updateNode.Parent.IsContainerBlock() && updateNode == treenode.FirstLeafBlock(updateNode.Parent) { // 容器块下第一个叶子块
@@ -1545,6 +1556,7 @@ func getRefsCacheByDefNode(updateNode *ast.Node) (ret []*sql.Ref) {
 			parentRefs := sql.GetRefsCacheByDefID(parent.ID)
 			if 0 < len(parentRefs) {
 				ret = append(ret, parentRefs...)
+				changedParentNodes = append(changedParentNodes, parent)
 			}
 		}
 	}
@@ -1575,7 +1587,12 @@ func flushUpdateRefTextRenameDoc() {
 	updateRefTextRenameDocs = map[string]*parse.Tree{}
 }
 
-func updateRefText(refNode *ast.Node, changedDefNodes map[string]*ast.Node) (changed bool) {
+type changedDefNode struct {
+	id      string
+	refText string
+}
+
+func updateRefText(refNode *ast.Node, changedDefNodes map[string]*ast.Node) (changed bool, defNodes []*changedDefNode) {
 	ast.Walk(refNode, func(n *ast.Node, entering bool) ast.WalkStatus {
 		if !entering {
 			return ast.WalkContinue
@@ -1597,6 +1614,7 @@ func updateRefText(refNode *ast.Node, changedDefNodes map[string]*ast.Node) (cha
 		refText := getNodeRefText(defNode)
 		treenode.SetDynamicBlockRefText(n, refText)
 		changed = true
+		defNodes = append(defNodes, &changedDefNode{id: defID, refText: refText})
 		return ast.WalkContinue
 	})
 	return

+ 2 - 2
kernel/util/websocket.go

@@ -258,8 +258,8 @@ func PushProtyleReload(rootID string) {
 	BroadcastByType("protyle", "reload", 0, "", rootID)
 }
 
-func PushReloadBlock(rootID, blockID string) {
-	BroadcastByType("main", "reloadBlock", 0, "", map[string]interface{}{"rootID": rootID, "blockID": blockID})
+func PushReloadBlock(rootID, blockID, defBlockID, refText string) {
+	BroadcastByType("protyle", "reloadBlock", 0, "", map[string]interface{}{"rootID": rootID, "blockID": blockID, "defBlockID": defBlockID, "refText": refText})
 }
 
 func PushProtyleLoading(rootID, msg string) {