From a8806968d051e6144e6ebb4e4c5d29c39744d9a6 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Sun, 8 Oct 2023 16:35:06 +0800 Subject: [PATCH 1/2] :art: Export related flashcard data when exporting .sy.zip https://github.com/siyuan-note/siyuan/issues/9372 --- kernel/model/export.go | 22 +++++++++++++++++++++ kernel/model/flashcard.go | 37 ++++++++++++++++++++++++++++++++++-- kernel/treenode/blocktree.go | 15 +++++++++++++++ 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/kernel/model/export.go b/kernel/model/export.go index 212e62261..08c70152f 100644 --- a/kernel/model/export.go +++ b/kernel/model/export.go @@ -46,6 +46,7 @@ import ( "github.com/siyuan-note/filelock" "github.com/siyuan-note/httpclient" "github.com/siyuan-note/logging" + "github.com/siyuan-note/riff" "github.com/siyuan-note/siyuan/kernel/av" "github.com/siyuan-note/siyuan/kernel/filesys" "github.com/siyuan-note/siyuan/kernel/sql" @@ -1382,6 +1383,27 @@ func exportSYZip(boxID, rootDirPath, baseFolderName string, docPaths []string) ( }) } + // 导出闪卡 Export related flashcard data when exporting .sy.zip https://github.com/siyuan-note/siyuan/issues/9372 + exportStorageRiffDir := filepath.Join(exportFolder, "storage", "riff") + deckID := ast.NewNodeID() + deck, loadErr := riff.LoadDeck(exportStorageRiffDir, deckID, Conf.Flashcard.RequestRetention, Conf.Flashcard.MaximumInterval, Conf.Flashcard.Weights) + for _, tree := range trees { + cards := getTreeFlashcards(tree.ID) + if nil != loadErr { + logging.LogErrorf("load deck [%s] failed: %s", name, loadErr) + continue + } + + for _, card := range cards { + deck.AddCard(card.ID(), card.BlockID()) + } + } + if 0 < deck.CountCards() { + if saveErr := deck.Save(); nil != saveErr { + logging.LogErrorf("save deck [%s] failed: %s", name, saveErr) + } + } + // 导出自定义排序 sortPath := filepath.Join(util.DataDir, box.ID, ".siyuan", "sort.json") fullSortIDs := map[string]int{} diff --git a/kernel/model/flashcard.go b/kernel/model/flashcard.go index 600b11d77..8717d6cd8 100644 --- a/kernel/model/flashcard.go +++ b/kernel/model/flashcard.go @@ -148,6 +148,12 @@ func GetNotebookFlashcards(boxID string, page int) (blocks []*Block, total, page func GetTreeFlashcards(rootID string, page int) (blocks []*Block, total, pageCount int) { blocks = []*Block{} + cards := getTreeSubTreeFlashcards(rootID) + blocks, total, pageCount = getCardsBlocks(cards, page) + return +} + +func getTreeSubTreeFlashcards(rootID string) (ret []riff.Card) { deck := Decks[builtinDeckID] if nil == deck { return @@ -162,9 +168,26 @@ func GetTreeFlashcards(rootID string, page int) (blocks []*Block, total, pageCou } } allBlockIDs = gulu.Str.RemoveDuplicatedElem(allBlockIDs) - cards := deck.GetCardsByBlockIDs(allBlockIDs) + ret = deck.GetCardsByBlockIDs(allBlockIDs) + return +} - blocks, total, pageCount = getCardsBlocks(cards, page) +func getTreeFlashcards(rootID string) (ret []riff.Card) { + deck := Decks[builtinDeckID] + if nil == deck { + return + } + + var allBlockIDs []string + deckBlockIDs := deck.GetBlockIDs() + treeBlockIDsMap, _ := getTreeBlocks(rootID) + for _, blockID := range deckBlockIDs { + if treeBlockIDsMap[blockID] { + allBlockIDs = append(allBlockIDs, blockID) + } + } + allBlockIDs = gulu.Str.RemoveDuplicatedElem(allBlockIDs) + ret = deck.GetCardsByBlockIDs(allBlockIDs) return } @@ -420,6 +443,16 @@ func getTreeSubTreeChildBlocks(rootID string) (treeBlockIDsMap map[string]bool, return } +func getTreeBlocks(rootID string) (treeBlockIDsMap map[string]bool, treeBlockIDs []string) { + treeBlockIDsMap = map[string]bool{} + bts := treenode.GetBlockTreesByRootID(rootID) + for _, bt := range bts { + treeBlockIDsMap[bt.ID] = true + treeBlockIDs = append(treeBlockIDs, bt.ID) + } + return +} + func getBoxBlocks(boxID string) (blockIDsMap map[string]bool, blockIDs []string) { blockIDsMap = map[string]bool{} bts := treenode.GetBlockTreesByBoxID(boxID) diff --git a/kernel/treenode/blocktree.go b/kernel/treenode/blocktree.go index 609483ee6..12787a581 100644 --- a/kernel/treenode/blocktree.go +++ b/kernel/treenode/blocktree.go @@ -226,6 +226,21 @@ func GetBlockTreesByPathPrefix(pathPrefix string) (ret []*BlockTree) { return } +func GetBlockTreesByRootID(rootID string) (ret []*BlockTree) { + blockTrees.Range(func(key, value interface{}) bool { + slice := value.(*btSlice) + slice.m.Lock() + for _, b := range slice.data { + if b.RootID == rootID { + ret = append(ret, b) + } + } + slice.m.Unlock() + return true + }) + return +} + func RemoveBlockTreesByPathPrefix(pathPrefix string) { var ids []string blockTrees.Range(func(key, value interface{}) bool { From 8733433eb1adf9438d5c94158c9b2bef9b0a53c9 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Sun, 8 Oct 2023 19:17:54 +0800 Subject: [PATCH 2/2] :art: Export related flashcard data when exporting .sy.zip https://github.com/siyuan-note/siyuan/issues/9372 --- kernel/model/export.go | 27 +++++++++++++-------------- kernel/model/import.go | 31 +++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 14 deletions(-) diff --git a/kernel/model/export.go b/kernel/model/export.go index 08c70152f..55160ed91 100644 --- a/kernel/model/export.go +++ b/kernel/model/export.go @@ -1385,22 +1385,21 @@ func exportSYZip(boxID, rootDirPath, baseFolderName string, docPaths []string) ( // 导出闪卡 Export related flashcard data when exporting .sy.zip https://github.com/siyuan-note/siyuan/issues/9372 exportStorageRiffDir := filepath.Join(exportFolder, "storage", "riff") - deckID := ast.NewNodeID() - deck, loadErr := riff.LoadDeck(exportStorageRiffDir, deckID, Conf.Flashcard.RequestRetention, Conf.Flashcard.MaximumInterval, Conf.Flashcard.Weights) - for _, tree := range trees { - cards := getTreeFlashcards(tree.ID) - if nil != loadErr { - logging.LogErrorf("load deck [%s] failed: %s", name, loadErr) - continue - } + deck, loadErr := riff.LoadDeck(exportStorageRiffDir, builtinDeckID, Conf.Flashcard.RequestRetention, Conf.Flashcard.MaximumInterval, Conf.Flashcard.Weights) + if nil != loadErr { + logging.LogErrorf("load deck [%s] failed: %s", name, loadErr) + } else { + for _, tree := range trees { + cards := getTreeFlashcards(tree.ID) - for _, card := range cards { - deck.AddCard(card.ID(), card.BlockID()) + for _, card := range cards { + deck.AddCard(card.ID(), card.BlockID()) + } } - } - if 0 < deck.CountCards() { - if saveErr := deck.Save(); nil != saveErr { - logging.LogErrorf("save deck [%s] failed: %s", name, saveErr) + if 0 < deck.CountCards() { + if saveErr := deck.Save(); nil != saveErr { + logging.LogErrorf("save deck [%s] failed: %s", name, saveErr) + } } } diff --git a/kernel/model/import.go b/kernel/model/import.go index 8fe66f800..ec6f9c198 100644 --- a/kernel/model/import.go +++ b/kernel/model/import.go @@ -22,6 +22,7 @@ import ( "encoding/json" "errors" "fmt" + "github.com/siyuan-note/riff" "github.com/siyuan-note/siyuan/kernel/av" "image" "image/jpeg" @@ -277,6 +278,36 @@ func ImportSY(zipPath, boxID, toPath string) (err error) { } } + // 将关联的闪卡数据合并到默认卡包 data/storage/riff/20230218211946-2kw8jgx 中 + storageRiffDir := filepath.Join(storage, "riff") + if gulu.File.IsExist(storageRiffDir) { + deckToImport, loadErr := riff.LoadDeck(storageRiffDir, builtinDeckID, Conf.Flashcard.RequestRetention, Conf.Flashcard.MaximumInterval, Conf.Flashcard.Weights) + if nil != loadErr { + logging.LogErrorf("load deck [%s] failed: %s", name, loadErr) + } else { + deck := Decks[builtinDeckID] + if nil == deck { + var createErr error + deck, createErr = createDeck0("Built-in Deck", builtinDeckID) + if nil == createErr { + Decks[deck.ID] = deck + } + } + + bIDs := deckToImport.GetBlockIDs() + cards := deckToImport.GetCardsByBlockIDs(bIDs) + for _, card := range cards { + deck.AddCard(card.ID(), blockIDs[card.BlockID()]) + } + + if 0 < len(cards) { + if saveErr := deck.Save(); nil != saveErr { + logging.LogErrorf("save deck [%s] failed: %s", name, saveErr) + } + } + } + } + // storage 文件夹已在上方处理,所以这里删除源 storage 文件夹,避免后面被拷贝到导入目录下 targetDir if removeErr := os.RemoveAll(storage); nil != removeErr { logging.LogErrorf("remove temp storage av dir failed: %s", removeErr)