Forráskód Böngészése

:art: Automatic refresh of document tree information https://github.com/siyuan-note/siyuan/issues/11043

Daniel 9 hónapja
szülő
commit
d35386d79d

+ 5 - 3
kernel/filesys/tree.go

@@ -103,7 +103,7 @@ func LoadTreeByData(data []byte, boxID, p string, luteEngine *lute.Lute) (ret *p
 			if os.IsNotExist(readErr) {
 				// 子文档缺失父文档时自动补全 https://github.com/siyuan-note/siyuan/issues/7376
 				parentTree := treenode.NewTree(boxID, parentPath, hPathBuilder.String()+"Untitled", "Untitled")
-				if writeErr := WriteTree(parentTree); nil != writeErr {
+				if _, writeErr := WriteTree(parentTree); nil != writeErr {
 					logging.LogErrorf("rebuild parent tree [%s] failed: %s", parentAbsPath, writeErr)
 				} else {
 					logging.LogInfof("rebuilt parent tree [%s]", parentAbsPath)
@@ -133,16 +133,18 @@ func LoadTreeByData(data []byte, boxID, p string, luteEngine *lute.Lute) (ret *p
 	return
 }
 
-func WriteTree(tree *parse.Tree) (err error) {
+func WriteTree(tree *parse.Tree) (size uint64, err error) {
 	data, filePath, err := prepareWriteTree(tree)
 	if err != nil {
 		return
 	}
 
+	size = uint64(len(data))
 	if err = filelock.WriteFile(filePath, data); err != nil {
 		msg := fmt.Sprintf("write data [%s] failed: %s", filePath, err)
 		logging.LogErrorf(msg)
-		return errors.New(msg)
+		err = errors.New(msg)
+		return
 	}
 
 	afterWriteTree(tree)

+ 9 - 3
kernel/model/file.go

@@ -1075,18 +1075,22 @@ func loadNodesByMode(node *ast.Node, inputIndex, mode, size int, isDoc, isHeadin
 }
 
 func writeTreeUpsertQueue(tree *parse.Tree) (err error) {
-	if err = filesys.WriteTree(tree); err != nil {
+	size, err := filesys.WriteTree(tree)
+	if err != nil {
 		return
 	}
 	sql.UpsertTreeQueue(tree)
+	refreshDocInfo(tree, size)
 	return
 }
 
 func writeTreeIndexQueue(tree *parse.Tree) (err error) {
-	if err = filesys.WriteTree(tree); err != nil {
+	size, err := filesys.WriteTree(tree)
+	if err != nil {
 		return
 	}
 	sql.IndexTreeQueue(tree)
+	refreshDocInfo(tree, size)
 	return
 }
 
@@ -1101,11 +1105,13 @@ func indexWriteTreeUpsertQueue(tree *parse.Tree) (err error) {
 }
 
 func renameWriteJSONQueue(tree *parse.Tree) (err error) {
-	if err = filesys.WriteTree(tree); err != nil {
+	size, err := filesys.WriteTree(tree)
+	if err != nil {
 		return
 	}
 	sql.RenameTreeQueue(tree)
 	treenode.UpsertBlockTree(tree)
+	refreshDocInfo(tree, size)
 	return
 }
 

+ 1 - 1
kernel/model/index.go

@@ -179,7 +179,7 @@ func index(boxID string) {
 			updated := util.TimeFromID(tree.Root.ID)
 			tree.Root.SetIALAttr("updated", updated)
 			docIAL["updated"] = updated
-			if writeErr := filesys.WriteTree(tree); nil != writeErr {
+			if _, writeErr := filesys.WriteTree(tree); nil != writeErr {
 				logging.LogErrorf("write tree [%s] failed: %s", tree.Path, writeErr)
 			}
 		}

+ 2 - 2
kernel/model/index_fix.go

@@ -239,7 +239,7 @@ func resetDuplicateBlocksOnFileSys() {
 
 			if needOverwrite {
 				logging.LogWarnf("exist more than one node with the same id in tree [%s], reset it", box.ID+p)
-				if writeErr := filesys.WriteTree(tree); nil != writeErr {
+				if _, writeErr := filesys.WriteTree(tree); nil != writeErr {
 					logging.LogErrorf("write tree [%s] failed: %s", p, writeErr)
 				}
 			}
@@ -266,7 +266,7 @@ func recreateTree(tree *parse.Tree, absPath string) {
 	treenode.RemoveBlockTreesByRootID(tree.ID)
 
 	resetTree(tree, "", true)
-	if err := filesys.WriteTree(tree); err != nil {
+	if _, err := filesys.WriteTree(tree); err != nil {
 		logging.LogWarnf("write tree [%s] failed: %s", tree.Path, err)
 		return
 	}

+ 42 - 0
kernel/model/push_reload.go

@@ -17,6 +17,9 @@
 package model
 
 import (
+	"github.com/88250/go-humanize"
+	"os"
+	"path/filepath"
 	"strings"
 	"time"
 
@@ -31,6 +34,45 @@ import (
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 
+func refreshDocInfo(tree *parse.Tree, size uint64) {
+	cTime, _ := time.ParseInLocation("20060102150405", tree.ID[:14], time.Local)
+	mTime := cTime
+	if updated := tree.Root.IALAttr("updated"); "" != updated {
+		if updatedTime, err := time.ParseInLocation("20060102150405", updated, time.Local); err == nil {
+			mTime = updatedTime
+		}
+	}
+
+	subFileCount := 0
+	subFiles, err := os.ReadDir(filepath.Join(util.DataDir, tree.Box, strings.TrimSuffix(tree.Path, ".sy")))
+	if err == nil {
+		for _, subFile := range subFiles {
+			if "true" == tree.Root.IALAttr("custom-hidden") {
+				continue
+			}
+
+			if strings.HasSuffix(subFile.Name(), ".sy") {
+				subFileCount++
+			}
+		}
+	}
+
+	docInfo := map[string]interface{}{
+		"rootID":       tree.ID,
+		"size":         size,
+		"hSize":        humanize.BytesCustomCeil(size, 2),
+		"mtime":        mTime.Unix(),
+		"ctime":        cTime.Unix(),
+		"hmtime":       cTime.Format("2006-01-02 15:04:05") + ", " + util.HumanizeTime(mTime, Conf.Lang),
+		"hctime":       mTime.Format("2006-01-02 15:04:05") + ", " + util.HumanizeTime(cTime, Conf.Lang),
+		"subFileCount": subFileCount,
+	}
+
+	task.AppendAsyncTaskWithDelay(task.ReloadProtyle, 500*time.Millisecond, util.PushReloadDocInfo, docInfo)
+
+	// TODO 子文档修改后也需要递归刷新父文档
+}
+
 func refreshProtyle(rootID string) {
 	// 刷新关联的引用
 	defTree, _ := LoadTreeByBlockID(rootID)

+ 4 - 0
kernel/util/websocket.go

@@ -254,6 +254,10 @@ func PushSaveDoc(rootID, typ string, sources interface{}) {
 	PushEvent(evt)
 }
 
+func PushReloadDocInfo(docInfo map[string]any) {
+	BroadcastByType("main", "reloadDocInfo", 0, "", docInfo)
+}
+
 func PushReloadProtyle(rootID string) {
 	BroadcastByType("protyle", "reload", 0, "", rootID)
 }