Selaa lähdekoodia

Merge remote-tracking branch 'origin/dev' into dev

Vanessa 1 vuosi sitten
vanhempi
commit
b86ed5b356

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 0 - 0
app/stage/protyle/js/lute/lute.min.js


+ 44 - 2
kernel/api/av.go

@@ -135,7 +135,49 @@ func getAttributeViewPrimaryKeyValues(c *gin.Context) {
 	}
 	}
 }
 }
 
 
-func addAttributeViewValues(c *gin.Context) {
+func appendAttributeViewDetachedBlocksWithValues(c *gin.Context) {
+	// Add an internal kernel API `/api/av/appendAttributeViewDetachedBlocksWithValues` https://github.com/siyuan-note/siyuan/issues/11608
+
+	ret := gulu.Ret.NewResult()
+	defer c.JSON(http.StatusOK, ret)
+
+	arg, _ := util.JsonArg(c, ret)
+	if nil == arg {
+		return
+	}
+
+	avID := arg["avID"].(string)
+	var values [][]*av.Value
+	for _, blocksVals := range arg["blocksValues"].([]interface{}) {
+		vals := blocksVals.([]interface{})
+		var rowValues []*av.Value
+		for _, val := range vals {
+			data, marshalErr := gulu.JSON.MarshalJSON(val)
+			if nil != marshalErr {
+				ret.Code = -1
+				ret.Msg = marshalErr.Error()
+				return
+			}
+			value := av.Value{}
+			if unmarshalErr := gulu.JSON.UnmarshalJSON(data, &value); nil != unmarshalErr {
+				ret.Code = -1
+				ret.Msg = unmarshalErr.Error()
+				return
+			}
+			rowValues = append(rowValues, &value)
+		}
+		values = append(values, rowValues)
+	}
+
+	err := model.AppendAttributeViewDetachedBlocksWithValues(avID, values)
+	if nil != err {
+		ret.Code = -1
+		ret.Msg = err.Error()
+		return
+	}
+}
+
+func addAttributeViewBlocks(c *gin.Context) {
 	ret := gulu.Ret.NewResult()
 	ret := gulu.Ret.NewResult()
 	defer c.JSON(http.StatusOK, ret)
 	defer c.JSON(http.StatusOK, ret)
 
 
@@ -173,7 +215,7 @@ func addAttributeViewValues(c *gin.Context) {
 	util.PushReloadAttrView(avID)
 	util.PushReloadAttrView(avID)
 }
 }
 
 
-func removeAttributeViewValues(c *gin.Context) {
+func removeAttributeViewBlocks(c *gin.Context) {
 	ret := gulu.Ret.NewResult()
 	ret := gulu.Ret.NewResult()
 	defer c.JSON(http.StatusOK, ret)
 	defer c.JSON(http.StatusOK, ret)
 
 

+ 31 - 0
kernel/api/notebook.go

@@ -19,10 +19,12 @@ package api
 import (
 import (
 	"net/http"
 	"net/http"
 	"strings"
 	"strings"
+	"time"
 
 
 	"github.com/88250/gulu"
 	"github.com/88250/gulu"
 	"github.com/gin-gonic/gin"
 	"github.com/gin-gonic/gin"
 	"github.com/siyuan-note/siyuan/kernel/model"
 	"github.com/siyuan-note/siyuan/kernel/model"
+	"github.com/siyuan-note/siyuan/kernel/treenode"
 	"github.com/siyuan-note/siyuan/kernel/util"
 	"github.com/siyuan-note/siyuan/kernel/util"
 )
 )
 
 
@@ -222,6 +224,35 @@ func openNotebook(c *gin.Context) {
 	}
 	}
 	evt.Callback = arg["callback"]
 	evt.Callback = arg["callback"]
 	util.PushEvent(evt)
 	util.PushEvent(evt)
+
+	if isUserGuide {
+		appArg := arg["app"]
+		app := ""
+		if nil != appArg {
+			app = appArg.(string)
+		}
+
+		go func() {
+			var startID string
+			i := 0
+			for ; i < 70; i++ {
+				time.Sleep(100 * time.Millisecond)
+				guideStartID := map[string]string{
+					"20210808180117-czj9bvb": "20200812220555-lj3enxa",
+					"20211226090932-5lcq56f": "20211226115423-d5z1joq",
+					"20210808180117-6v0mkxr": "20200923234011-ieuun1p",
+					"20240530133126-axarxgx": "20240530101000-4qitucx",
+				}
+				startID = guideStartID[notebook]
+				if nil != treenode.GetBlockTree(startID) {
+					util.BroadcastByTypeAndApp("main", app, "openFileById", 0, "", map[string]interface{}{
+						"id": startID,
+					})
+					break
+				}
+			}
+		}()
+	}
 }
 }
 
 
 func closeNotebook(c *gin.Context) {
 func closeNotebook(c *gin.Context) {

+ 3 - 2
kernel/api/router.go

@@ -419,13 +419,14 @@ func ServeAPI(ginServer *gin.Engine) {
 	ginServer.Handle("POST", "/api/av/removeAttributeViewKey", model.CheckAuth, model.CheckReadonly, removeAttributeViewKey)
 	ginServer.Handle("POST", "/api/av/removeAttributeViewKey", model.CheckAuth, model.CheckReadonly, removeAttributeViewKey)
 	ginServer.Handle("POST", "/api/av/sortAttributeViewViewKey", model.CheckAuth, model.CheckReadonly, sortAttributeViewViewKey)
 	ginServer.Handle("POST", "/api/av/sortAttributeViewViewKey", model.CheckAuth, model.CheckReadonly, sortAttributeViewViewKey)
 	ginServer.Handle("POST", "/api/av/sortAttributeViewKey", model.CheckAuth, model.CheckReadonly, sortAttributeViewKey)
 	ginServer.Handle("POST", "/api/av/sortAttributeViewKey", model.CheckAuth, model.CheckReadonly, sortAttributeViewKey)
-	ginServer.Handle("POST", "/api/av/addAttributeViewValues", model.CheckAuth, model.CheckReadonly, addAttributeViewValues)
-	ginServer.Handle("POST", "/api/av/removeAttributeViewValues", model.CheckAuth, model.CheckReadonly, removeAttributeViewValues)
+	ginServer.Handle("POST", "/api/av/addAttributeViewBlocks", model.CheckAuth, model.CheckReadonly, addAttributeViewBlocks)
+	ginServer.Handle("POST", "/api/av/removeAttributeViewBlocks", model.CheckAuth, model.CheckReadonly, removeAttributeViewBlocks)
 	ginServer.Handle("POST", "/api/av/getAttributeViewPrimaryKeyValues", model.CheckAuth, model.CheckReadonly, getAttributeViewPrimaryKeyValues)
 	ginServer.Handle("POST", "/api/av/getAttributeViewPrimaryKeyValues", model.CheckAuth, model.CheckReadonly, getAttributeViewPrimaryKeyValues)
 	ginServer.Handle("POST", "/api/av/setDatabaseBlockView", model.CheckAuth, model.CheckReadonly, setDatabaseBlockView)
 	ginServer.Handle("POST", "/api/av/setDatabaseBlockView", model.CheckAuth, model.CheckReadonly, setDatabaseBlockView)
 	ginServer.Handle("POST", "/api/av/getMirrorDatabaseBlocks", model.CheckAuth, model.CheckReadonly, getMirrorDatabaseBlocks)
 	ginServer.Handle("POST", "/api/av/getMirrorDatabaseBlocks", model.CheckAuth, model.CheckReadonly, getMirrorDatabaseBlocks)
 	ginServer.Handle("POST", "/api/av/getAttributeViewKeysByAvID", model.CheckAuth, model.CheckReadonly, getAttributeViewKeysByAvID)
 	ginServer.Handle("POST", "/api/av/getAttributeViewKeysByAvID", model.CheckAuth, model.CheckReadonly, getAttributeViewKeysByAvID)
 	ginServer.Handle("POST", "/api/av/duplicateAttributeViewBlock", model.CheckAuth, model.CheckReadonly, duplicateAttributeViewBlock)
 	ginServer.Handle("POST", "/api/av/duplicateAttributeViewBlock", model.CheckAuth, model.CheckReadonly, duplicateAttributeViewBlock)
+	ginServer.Handle("POST", "/api/av/appendAttributeViewDetachedBlocksWithValues", model.CheckAuth, model.CheckReadonly, appendAttributeViewDetachedBlocksWithValues)
 
 
 	ginServer.Handle("POST", "/api/ai/chatGPT", model.CheckAuth, chatGPT)
 	ginServer.Handle("POST", "/api/ai/chatGPT", model.CheckAuth, chatGPT)
 	ginServer.Handle("POST", "/api/ai/chatGPTWithAction", model.CheckAuth, chatGPTWithAction)
 	ginServer.Handle("POST", "/api/ai/chatGPTWithAction", model.CheckAuth, chatGPTWithAction)

+ 20 - 0
kernel/av/av.go

@@ -62,6 +62,26 @@ func (kValues *KeyValues) GetValue(blockID string) (ret *Value) {
 	return
 	return
 }
 }
 
 
+func (kValues *KeyValues) GetBlockValue() (ret *Value) {
+	for _, v := range kValues.Values {
+		if KeyTypeBlock != v.Type {
+			ret = v
+			return
+		}
+	}
+	return
+}
+
+func GetKeyBlockValue(blockKeyValues []*KeyValues) (ret *Value) {
+	for _, kv := range blockKeyValues {
+		if KeyTypeBlock == kv.Key.Type && 0 < len(kv.Values) {
+			ret = kv.Values[0]
+			break
+		}
+	}
+	return
+}
+
 type KeyType string
 type KeyType string
 
 
 const (
 const (

+ 1 - 1
kernel/go.mod

@@ -8,7 +8,7 @@ require (
 	github.com/88250/epub v0.0.0-20230830085737-c19055cd1f48
 	github.com/88250/epub v0.0.0-20230830085737-c19055cd1f48
 	github.com/88250/go-humanize v0.0.0-20240424102817-4f78fac47ea7
 	github.com/88250/go-humanize v0.0.0-20240424102817-4f78fac47ea7
 	github.com/88250/gulu v1.2.3-0.20240505150113-bc43bd50f866
 	github.com/88250/gulu v1.2.3-0.20240505150113-bc43bd50f866
-	github.com/88250/lute v1.7.7-0.20240529025122-c2b54f422dc4
+	github.com/88250/lute v1.7.7-0.20240531135614-85cb33ff053b
 	github.com/88250/pdfcpu v0.3.14-0.20230401044135-c7369a99720c
 	github.com/88250/pdfcpu v0.3.14-0.20230401044135-c7369a99720c
 	github.com/88250/vitess-sqlparser v0.0.0-20210205111146-56a2ded2aba1
 	github.com/88250/vitess-sqlparser v0.0.0-20210205111146-56a2ded2aba1
 	github.com/ClarkThan/ahocorasick v0.0.0-20231011042242-30d1ef1347f4
 	github.com/ClarkThan/ahocorasick v0.0.0-20231011042242-30d1ef1347f4

+ 2 - 2
kernel/go.sum

@@ -12,8 +12,8 @@ github.com/88250/go-sqlite3 v1.14.13-0.20231214121541-e7f54c482950 h1:Pa5hMiBceT
 github.com/88250/go-sqlite3 v1.14.13-0.20231214121541-e7f54c482950/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
 github.com/88250/go-sqlite3 v1.14.13-0.20231214121541-e7f54c482950/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
 github.com/88250/gulu v1.2.3-0.20240505150113-bc43bd50f866 h1:RFfNFS0hv6TbOuwET6xZAfGlV4hNlXiWTnfbLN1eF6k=
 github.com/88250/gulu v1.2.3-0.20240505150113-bc43bd50f866 h1:RFfNFS0hv6TbOuwET6xZAfGlV4hNlXiWTnfbLN1eF6k=
 github.com/88250/gulu v1.2.3-0.20240505150113-bc43bd50f866/go.mod h1:MUfzyfmbPrRDZLqxc7aPrVYveatTHRfoUa5TynPS0i8=
 github.com/88250/gulu v1.2.3-0.20240505150113-bc43bd50f866/go.mod h1:MUfzyfmbPrRDZLqxc7aPrVYveatTHRfoUa5TynPS0i8=
-github.com/88250/lute v1.7.7-0.20240529025122-c2b54f422dc4 h1:5/vRlAP/3C7YG7KMd35OlHIgNwMx3s6QLBwcjx8YABw=
-github.com/88250/lute v1.7.7-0.20240529025122-c2b54f422dc4/go.mod h1:VDAzL8b+oCh+e3NAlmwwLzC53ten0rZlS8NboB7ljtk=
+github.com/88250/lute v1.7.7-0.20240531135614-85cb33ff053b h1:zOpPknjyTDYchi+kQtWJoGfqE3kfKfZbij+cYNdjta0=
+github.com/88250/lute v1.7.7-0.20240531135614-85cb33ff053b/go.mod h1:VDAzL8b+oCh+e3NAlmwwLzC53ten0rZlS8NboB7ljtk=
 github.com/88250/pdfcpu v0.3.14-0.20230401044135-c7369a99720c h1:Dl/8S9iLyPMTElnWIBxmjaLiWrkI5P4a21ivwAn5pU0=
 github.com/88250/pdfcpu v0.3.14-0.20230401044135-c7369a99720c h1:Dl/8S9iLyPMTElnWIBxmjaLiWrkI5P4a21ivwAn5pU0=
 github.com/88250/pdfcpu v0.3.14-0.20230401044135-c7369a99720c/go.mod h1:S5YT38L/GCjVjmB4PB84PymA1qfopjEhfhTNQilLpv4=
 github.com/88250/pdfcpu v0.3.14-0.20230401044135-c7369a99720c/go.mod h1:S5YT38L/GCjVjmB4PB84PymA1qfopjEhfhTNQilLpv4=
 github.com/88250/vitess-sqlparser v0.0.0-20210205111146-56a2ded2aba1 h1:48T899JQDwyyRu9yXHePYlPdHtpJfrJEUGBMH3SMBWY=
 github.com/88250/vitess-sqlparser v0.0.0-20210205111146-56a2ded2aba1 h1:48T899JQDwyyRu9yXHePYlPdHtpJfrJEUGBMH3SMBWY=

+ 54 - 11
kernel/model/attribute_view.go

@@ -42,6 +42,59 @@ import (
 	"github.com/xrash/smetrics"
 	"github.com/xrash/smetrics"
 )
 )
 
 
+func AppendAttributeViewDetachedBlocksWithValues(avID string, blocksValues [][]*av.Value) (err error) {
+	attrView, err := av.ParseAttributeView(avID)
+	if nil != err {
+		logging.LogErrorf("parse attribute view [%s] failed: %s", avID, err)
+		return
+	}
+
+	now := util.CurrentTimeMillis()
+	var blockIDs []string
+	for _, blockValues := range blocksValues {
+		blockID := ast.NewNodeID()
+		blockIDs = append(blockIDs, blockID)
+		for _, v := range blockValues {
+			keyValues, _ := attrView.GetKeyValues(v.KeyID)
+			if nil == keyValues {
+				err = fmt.Errorf("key [%s] not found", v.KeyID)
+				return
+			}
+
+			v.ID = ast.NewNodeID()
+			v.BlockID = blockID
+			v.Type = keyValues.Key.Type
+			if av.KeyTypeBlock == v.Type {
+				v.Block.ID = blockID
+				v.Block.Created = now
+				v.Block.Updated = now
+			}
+			v.IsDetached = true
+			v.CreatedAt = now
+			v.UpdatedAt = now
+
+			keyValues.Values = append(keyValues.Values, v)
+		}
+	}
+
+	for _, v := range attrView.Views {
+		switch v.LayoutType {
+		case av.LayoutTypeTable:
+			for _, addingBlockID := range blockIDs {
+				v.Table.RowIDs = append(v.Table.RowIDs, addingBlockID)
+			}
+		}
+	}
+
+	if err = av.SaveAttributeView(attrView); nil != err {
+		logging.LogErrorf("save attribute view [%s] failed: %s", avID, err)
+		return
+	}
+
+	util.PushReloadAttrView(avID)
+	return
+}
+
 func DuplicateDatabaseBlock(avID string) (newAvID, newBlockID string, err error) {
 func DuplicateDatabaseBlock(avID string) (newAvID, newBlockID string, err error) {
 	storageAvDir := filepath.Join(util.DataDir, "storage", "av")
 	storageAvDir := filepath.Join(util.DataDir, "storage", "av")
 	oldAvPath := filepath.Join(storageAvDir, avID+".json")
 	oldAvPath := filepath.Join(storageAvDir, avID+".json")
@@ -574,7 +627,7 @@ func GetBlockAttributeViewKeys(blockID string) (ret []*BlockAttributeViewKeys) {
 			case av.KeyTypeTemplate:
 			case av.KeyTypeTemplate:
 				if 0 < len(kv.Values) {
 				if 0 < len(kv.Values) {
 					ial := map[string]string{}
 					ial := map[string]string{}
-					block := getRowBlockValue(keyValues)
+					block := av.GetKeyBlockValue(keyValues)
 					if nil != block && !block.IsDetached {
 					if nil != block && !block.IsDetached {
 						ial = GetBlockAttrsWithoutWaitWriting(block.BlockID)
 						ial = GetBlockAttrsWithoutWaitWriting(block.BlockID)
 					}
 					}
@@ -915,16 +968,6 @@ func renderAttributeView(attrView *av.AttributeView, viewID, query string, page,
 	return
 	return
 }
 }
 
 
-func getRowBlockValue(keyValues []*av.KeyValues) (ret *av.Value) {
-	for _, kv := range keyValues {
-		if av.KeyTypeBlock == kv.Key.Type && 0 < len(kv.Values) {
-			ret = kv.Values[0]
-			break
-		}
-	}
-	return
-}
-
 func (tx *Transaction) doUnbindAttrViewBlock(operation *Operation) (ret *TxErr) {
 func (tx *Transaction) doUnbindAttrViewBlock(operation *Operation) (ret *TxErr) {
 	err := unbindAttributeViewBlock(operation, tx)
 	err := unbindAttributeViewBlock(operation, tx)
 	if nil != err {
 	if nil != err {

+ 5 - 0
kernel/model/history.go

@@ -271,6 +271,11 @@ func RollbackDocHistory(boxID, historyPath string) (err error) {
 
 
 	FullReindex()
 	FullReindex()
 	IncSync()
 	IncSync()
+	go func() {
+		sql.WaitForWritingDatabase()
+		// 刷新关联的动态锚文本 https://github.com/siyuan-note/siyuan/issues/11575
+		refreshDynamicRefText(tree.Root, tree)
+	}()
 	return nil
 	return nil
 }
 }
 
 

+ 0 - 23
kernel/model/mount.go

@@ -250,29 +250,6 @@ func Mount(boxID string) (alreadyMount bool, err error) {
 	treenode.SaveBlockTree(false)
 	treenode.SaveBlockTree(false)
 	util.ClearPushProgress(100)
 	util.ClearPushProgress(100)
 
 
-	if isUserGuide {
-		go func() {
-			var startID string
-			i := 0
-			for ; i < 70; i++ {
-				time.Sleep(100 * time.Millisecond)
-				guideStartID := map[string]string{
-					"20210808180117-czj9bvb": "20200812220555-lj3enxa",
-					"20211226090932-5lcq56f": "20211226115423-d5z1joq",
-					"20210808180117-6v0mkxr": "20200923234011-ieuun1p",
-					"20240530133126-axarxgx": "20240530101000-4qitucx",
-				}
-				startID = guideStartID[boxID]
-				if nil != treenode.GetBlockTree(startID) {
-					util.BroadcastByType("main", "openFileById", 0, "", map[string]interface{}{
-						"id": startID,
-					})
-					break
-				}
-			}
-		}()
-	}
-
 	if reMountGuide {
 	if reMountGuide {
 		return true, nil
 		return true, nil
 	}
 	}

+ 7 - 2
kernel/sql/queue.go

@@ -36,6 +36,7 @@ var (
 	operationQueue []*dbQueueOperation
 	operationQueue []*dbQueueOperation
 	dbQueueLock    = sync.Mutex{}
 	dbQueueLock    = sync.Mutex{}
 	txLock         = sync.Mutex{}
 	txLock         = sync.Mutex{}
+	isWriting      = false
 )
 )
 
 
 type dbQueueOperation struct {
 type dbQueueOperation struct {
@@ -77,7 +78,7 @@ func isWritingDatabase() bool {
 	time.Sleep(util.SQLFlushInterval + 50*time.Millisecond)
 	time.Sleep(util.SQLFlushInterval + 50*time.Millisecond)
 	dbQueueLock.Lock()
 	dbQueueLock.Lock()
 	defer dbQueueLock.Unlock()
 	defer dbQueueLock.Unlock()
-	if 0 < len(operationQueue) {
+	if 0 < len(operationQueue) || isWriting {
 		return true
 		return true
 	}
 	}
 	return false
 	return false
@@ -103,7 +104,11 @@ func FlushQueue() {
 	}
 	}
 
 
 	txLock.Lock()
 	txLock.Lock()
-	defer txLock.Unlock()
+	isWriting = true
+	defer func() {
+		isWriting = false
+		txLock.Unlock()
+	}()
 
 
 	start := time.Now()
 	start := time.Now()
 
 

+ 20 - 0
kernel/util/websocket.go

@@ -32,6 +32,26 @@ var (
 	sessions = sync.Map{} // {appId, {sessionId, session}}
 	sessions = sync.Map{} // {appId, {sessionId, session}}
 )
 )
 
 
+func BroadcastByTypeAndApp(typ, app, cmd string, code int, msg string, data interface{}) {
+	appSessions, ok := sessions.Load(app)
+	if !ok {
+		return
+	}
+
+	appSessions.(*sync.Map).Range(func(key, value interface{}) bool {
+		session := value.(*melody.Session)
+		if t, ok := session.Get("type"); ok && typ == t {
+			event := NewResult()
+			event.Cmd = cmd
+			event.Code = code
+			event.Msg = msg
+			event.Data = data
+			session.Write(event.Bytes())
+		}
+		return true
+	})
+}
+
 // BroadcastByType 广播所有实例上 typ 类型的会话。
 // BroadcastByType 广播所有实例上 typ 类型的会话。
 func BroadcastByType(typ, cmd string, code int, msg string, data interface{}) {
 func BroadcastByType(typ, cmd string, code int, msg string, data interface{}) {
 	typeSessions := SessionsByType(typ)
 	typeSessions := SessionsByType(typ)

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä