mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-12-17 15:10:12 +01:00
♻️ Adjust addRiffCards/removeRiffCards implementation to be asynchronous transaction https://github.com/siyuan-note/siyuan/issues/7936
This commit is contained in:
parent
e5143a8474
commit
3e14b4f29c
3 changed files with 58 additions and 104 deletions
|
|
@ -216,13 +216,22 @@ func removeRiffCards(c *gin.Context) {
|
||||||
for _, blockID := range blockIDsArg {
|
for _, blockID := range blockIDsArg {
|
||||||
blockIDs = append(blockIDs, blockID.(string))
|
blockIDs = append(blockIDs, blockID.(string))
|
||||||
}
|
}
|
||||||
err := model.RemoveFlashcardsByBlockIDs(deckID, blockIDs)
|
|
||||||
if nil != err {
|
transactions := []*model.Transaction{
|
||||||
ret.Code = -1
|
{
|
||||||
ret.Msg = err.Error()
|
DoOperations: []*model.Operation{
|
||||||
return
|
{
|
||||||
|
Action: "removeFlashcards",
|
||||||
|
DeckID: deckID,
|
||||||
|
BlockIDs: blockIDs,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model.PerformTransactions(&transactions)
|
||||||
|
model.WaitForWritingFiles()
|
||||||
|
|
||||||
if "" != deckID {
|
if "" != deckID {
|
||||||
deck := model.Decks[deckID]
|
deck := model.Decks[deckID]
|
||||||
ret.Data = deckData(deck)
|
ret.Data = deckData(deck)
|
||||||
|
|
@ -245,13 +254,22 @@ func addRiffCards(c *gin.Context) {
|
||||||
for _, blockID := range blockIDsArg {
|
for _, blockID := range blockIDsArg {
|
||||||
blockIDs = append(blockIDs, blockID.(string))
|
blockIDs = append(blockIDs, blockID.(string))
|
||||||
}
|
}
|
||||||
err := model.AddFlashcards(deckID, blockIDs)
|
|
||||||
if nil != err {
|
transactions := []*model.Transaction{
|
||||||
ret.Code = -1
|
{
|
||||||
ret.Msg = err.Error()
|
DoOperations: []*model.Operation{
|
||||||
return
|
{
|
||||||
|
Action: "addFlashcards",
|
||||||
|
DeckID: deckID,
|
||||||
|
BlockIDs: blockIDs,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
model.PerformTransactions(&transactions)
|
||||||
|
model.WaitForWritingFiles()
|
||||||
|
|
||||||
deck := model.Decks[deckID]
|
deck := model.Decks[deckID]
|
||||||
ret.Data = deckData(deck)
|
ret.Data = deckData(deck)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -456,95 +456,20 @@ func getAllDueFlashcards(reviewedCardIDs []string) (ret []*Flashcard) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func RemoveFlashcardsByCardIDs(deckID string, cardIDs []string) (err error) {
|
func (tx *Transaction) doRemoveFlashcards(operation *Operation) (ret *TxErr) {
|
||||||
deckLock.Lock()
|
deckLock.Lock()
|
||||||
defer deckLock.Unlock()
|
defer deckLock.Unlock()
|
||||||
|
|
||||||
if syncingStorages {
|
if syncingStorages {
|
||||||
err = errors.New(Conf.Language(81))
|
ret = &TxErr{code: TxErrCodeDataIsSyncing}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var needRemoveDeckAttrBlockIDs []string
|
deckID := operation.DeckID
|
||||||
if "" == deckID {
|
blockIDs := operation.BlockIDs
|
||||||
// 在 All 卡包中移除
|
|
||||||
var affectedBlockIDs []string
|
|
||||||
for _, deck := range Decks {
|
|
||||||
changed := false
|
|
||||||
for _, cardID := range cardIDs {
|
|
||||||
card := deck.GetCard(cardID)
|
|
||||||
if nil == card {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
affectedBlockIDs = append(affectedBlockIDs, card.BlockID())
|
if err := tx.removeBlocksDeckAttr(blockIDs, deckID); nil != err {
|
||||||
deck.RemoveCard(cardID)
|
return &TxErr{code: TxErrCodeWriteTree, msg: err.Error(), id: deckID}
|
||||||
changed = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if changed {
|
|
||||||
if err = deck.Save(); nil != err {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查刚刚移除的卡片关联的块是否还存在更多关联的卡片
|
|
||||||
affectedBlockIDs = gulu.Str.RemoveDuplicatedElem(affectedBlockIDs)
|
|
||||||
for _, blockID := range affectedBlockIDs {
|
|
||||||
moreRelatedCards := deck.GetCardsByBlockID(blockID)
|
|
||||||
if 1 > len(moreRelatedCards) {
|
|
||||||
needRemoveDeckAttrBlockIDs = append(needRemoveDeckAttrBlockIDs, blockID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 在指定卡包中移除
|
|
||||||
deck := Decks[deckID]
|
|
||||||
if nil == deck {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var affectedBlockIDs []string
|
|
||||||
for _, cardID := range cardIDs {
|
|
||||||
card := deck.GetCard(cardID)
|
|
||||||
if nil == card {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
affectedBlockIDs = append(affectedBlockIDs, card.BlockID())
|
|
||||||
deck.RemoveCard(cardID)
|
|
||||||
if err = deck.Save(); nil != err {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查刚刚移除的卡片关联的块是否还存在更多关联的卡片
|
|
||||||
affectedBlockIDs = gulu.Str.RemoveDuplicatedElem(affectedBlockIDs)
|
|
||||||
for _, blockID := range affectedBlockIDs {
|
|
||||||
moreRelatedCards := deck.GetCardsByBlockID(blockID)
|
|
||||||
if 1 > len(moreRelatedCards) {
|
|
||||||
needRemoveDeckAttrBlockIDs = append(needRemoveDeckAttrBlockIDs, blockID)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = removeBlocksDeckAttr(needRemoveDeckAttrBlockIDs, deckID); nil != err {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func RemoveFlashcardsByBlockIDs(deckID string, blockIDs []string) (err error) {
|
|
||||||
deckLock.Lock()
|
|
||||||
defer deckLock.Unlock()
|
|
||||||
|
|
||||||
if syncingStorages {
|
|
||||||
err = errors.New(Conf.Language(81))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = removeBlocksDeckAttr(blockIDs, deckID); nil != err {
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if "" == deckID { // 支持在 All 卡包中移除闪卡 https://github.com/siyuan-note/siyuan/issues/7425
|
if "" == deckID { // 支持在 All 卡包中移除闪卡 https://github.com/siyuan-note/siyuan/issues/7425
|
||||||
|
|
@ -557,7 +482,7 @@ func RemoveFlashcardsByBlockIDs(deckID string, blockIDs []string) (err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func removeBlocksDeckAttr(blockIDs []string, deckID string) (err error) {
|
func (tx *Transaction) removeBlocksDeckAttr(blockIDs []string, deckID string) (err error) {
|
||||||
var rootIDs []string
|
var rootIDs []string
|
||||||
blockRoots := map[string]string{}
|
blockRoots := map[string]string{}
|
||||||
for _, blockID := range blockIDs {
|
for _, blockID := range blockIDs {
|
||||||
|
|
@ -577,7 +502,7 @@ func removeBlocksDeckAttr(blockIDs []string, deckID string) (err error) {
|
||||||
|
|
||||||
tree := trees[rootID]
|
tree := trees[rootID]
|
||||||
if nil == tree {
|
if nil == tree {
|
||||||
tree, _ = loadTreeByBlockID(blockID)
|
tree, _ = tx.loadTree(blockID)
|
||||||
}
|
}
|
||||||
if nil == tree {
|
if nil == tree {
|
||||||
continue
|
continue
|
||||||
|
|
@ -612,7 +537,7 @@ func removeBlocksDeckAttr(blockIDs []string, deckID string) (err error) {
|
||||||
node.SetIALAttr("custom-riff-decks", val)
|
node.SetIALAttr("custom-riff-decks", val)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = indexWriteJSONQueue(tree); nil != err {
|
if err = tx.writeTree(tree); nil != err {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -643,15 +568,18 @@ func removeFlashcardsByBlockIDs(blockIDs []string, deck *riff.Deck) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func AddFlashcards(deckID string, blockIDs []string) (err error) {
|
func (tx *Transaction) doAddFlashcards(operation *Operation) (ret *TxErr) {
|
||||||
deckLock.Lock()
|
deckLock.Lock()
|
||||||
defer deckLock.Unlock()
|
defer deckLock.Unlock()
|
||||||
|
|
||||||
if syncingStorages {
|
if syncingStorages {
|
||||||
err = errors.New(Conf.Language(81))
|
ret = &TxErr{code: TxErrCodeDataIsSyncing}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deckID := operation.DeckID
|
||||||
|
blockIDs := operation.BlockIDs
|
||||||
|
|
||||||
blockRoots := map[string]string{}
|
blockRoots := map[string]string{}
|
||||||
for _, blockID := range blockIDs {
|
for _, blockID := range blockIDs {
|
||||||
bt := treenode.GetBlockTree(blockID)
|
bt := treenode.GetBlockTree(blockID)
|
||||||
|
|
@ -668,7 +596,7 @@ func AddFlashcards(deckID string, blockIDs []string) (err error) {
|
||||||
|
|
||||||
tree := trees[rootID]
|
tree := trees[rootID]
|
||||||
if nil == tree {
|
if nil == tree {
|
||||||
tree, _ = loadTreeByBlockID(blockID)
|
tree, _ = tx.loadTree(blockID)
|
||||||
}
|
}
|
||||||
if nil == tree {
|
if nil == tree {
|
||||||
continue
|
continue
|
||||||
|
|
@ -691,8 +619,8 @@ func AddFlashcards(deckID string, blockIDs []string) (err error) {
|
||||||
val = strings.TrimSuffix(val, ",")
|
val = strings.TrimSuffix(val, ",")
|
||||||
node.SetIALAttr("custom-riff-decks", val)
|
node.SetIALAttr("custom-riff-decks", val)
|
||||||
|
|
||||||
if err = indexWriteJSONQueue(tree); nil != err {
|
if err := tx.writeTree(tree); nil != err {
|
||||||
return
|
return &TxErr{code: TxErrCodeWriteTree, msg: err.Error(), id: deckID}
|
||||||
}
|
}
|
||||||
|
|
||||||
cache.PutBlockIAL(blockID, parse.IAL2Map(node.KramdownIAL))
|
cache.PutBlockIAL(blockID, parse.IAL2Map(node.KramdownIAL))
|
||||||
|
|
@ -715,8 +643,8 @@ func AddFlashcards(deckID string, blockIDs []string) (err error) {
|
||||||
cardID := ast.NewNodeID()
|
cardID := ast.NewNodeID()
|
||||||
deck.AddCard(cardID, blockID)
|
deck.AddCard(cardID, blockID)
|
||||||
}
|
}
|
||||||
err = deck.Save()
|
|
||||||
if nil != err {
|
if err := deck.Save(); nil != err {
|
||||||
logging.LogErrorf("save deck [%s] failed: %s", deckID, err)
|
logging.LogErrorf("save deck [%s] failed: %s", deckID, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -155,6 +155,7 @@ func PerformTransactions(transactions *[]*Transaction) {
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TxErrCodeBlockNotFound = 0
|
TxErrCodeBlockNotFound = 0
|
||||||
|
TxErrCodeDataIsSyncing = 1
|
||||||
TxErrCodeWriteTree = 2
|
TxErrCodeWriteTree = 2
|
||||||
TxErrWriteAttributeView = 3
|
TxErrWriteAttributeView = 3
|
||||||
)
|
)
|
||||||
|
|
@ -208,7 +209,11 @@ func performTx(tx *Transaction) (ret *TxErr) {
|
||||||
case "unfoldHeading":
|
case "unfoldHeading":
|
||||||
ret = tx.doUnfoldHeading(op)
|
ret = tx.doUnfoldHeading(op)
|
||||||
case "setAttrs":
|
case "setAttrs":
|
||||||
ret = tx.setAttrs(op)
|
ret = tx.doSetAttrs(op)
|
||||||
|
case "addFlashcards":
|
||||||
|
ret = tx.doAddFlashcards(op)
|
||||||
|
case "removeFlashcards":
|
||||||
|
ret = tx.doRemoveFlashcards(op)
|
||||||
case "insertAttrViewBlock":
|
case "insertAttrViewBlock":
|
||||||
ret = tx.doInsertAttrViewBlock(op)
|
ret = tx.doInsertAttrViewBlock(op)
|
||||||
case "removeAttrViewBlock":
|
case "removeAttrViewBlock":
|
||||||
|
|
@ -927,7 +932,7 @@ func (tx *Transaction) doCreate(operation *Operation) (ret *TxErr) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *Transaction) setAttrs(operation *Operation) (ret *TxErr) {
|
func (tx *Transaction) doSetAttrs(operation *Operation) (ret *TxErr) {
|
||||||
id := operation.ID
|
id := operation.ID
|
||||||
tree, err := tx.loadTree(id)
|
tree, err := tx.loadTree(id)
|
||||||
if nil != err {
|
if nil != err {
|
||||||
|
|
@ -968,7 +973,7 @@ func (tx *Transaction) setAttrs(operation *Operation) (ret *TxErr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = indexWriteJSONQueue(tree); nil != err {
|
if err = tx.writeTree(tree); nil != err {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cache.PutBlockIAL(id, parse.IAL2Map(node.KramdownIAL))
|
cache.PutBlockIAL(id, parse.IAL2Map(node.KramdownIAL))
|
||||||
|
|
@ -1007,6 +1012,9 @@ type Operation struct {
|
||||||
PreviousID string `json:"previousID"`
|
PreviousID string `json:"previousID"`
|
||||||
NextID string `json:"nextID"`
|
NextID string `json:"nextID"`
|
||||||
RetData interface{} `json:"retData"`
|
RetData interface{} `json:"retData"`
|
||||||
|
BlockIDs []string `json:"blockIDs"`
|
||||||
|
|
||||||
|
DeckID string `json:"deckID"` // 用于添加/删除闪卡
|
||||||
|
|
||||||
SrcIDs []string `json:"srcIDs"` // 用于将块拖拽到属性视图中
|
SrcIDs []string `json:"srcIDs"` // 用于将块拖拽到属性视图中
|
||||||
Name string `json:"name"` // 用于属性视图列名
|
Name string `json:"name"` // 用于属性视图列名
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue