🎨 Spaced repetition interface supports review by document selection https://github.com/siyuan-note/siyuan/issues/7954

This commit is contained in:
Liang Ding 2023-04-13 19:07:09 +08:00
parent 0ebdd49f8a
commit 66bd5e91a5
No known key found for this signature in database
GPG key ID: 136F30F901A2231D
7 changed files with 112 additions and 38 deletions

View file

@ -95,7 +95,7 @@ func heading2Doc(c *gin.Context) {
name := path.Base(targetPath)
box := model.Conf.Box(targetNotebook)
files, _, _ := model.ListDocTree(targetNotebook, path.Dir(targetPath), model.Conf.FileTree.Sort)
files, _, _ := model.ListDocTree(targetNotebook, path.Dir(targetPath), model.Conf.FileTree.Sort, false)
evt := util.NewCmdResult("heading2doc", 0, util.PushModeBroadcast)
evt.Data = map[string]interface{}{
"box": box,
@ -140,7 +140,7 @@ func li2Doc(c *gin.Context) {
name := path.Base(targetPath)
box := model.Conf.Box(targetNotebook)
files, _, _ := model.ListDocTree(targetNotebook, path.Dir(targetPath), model.Conf.FileTree.Sort)
files, _, _ := model.ListDocTree(targetNotebook, path.Dir(targetPath), model.Conf.FileTree.Sort, false)
evt := util.NewCmdResult("li2doc", 0, util.PushModeBroadcast)
evt.Data = map[string]interface{}{
"box": box,
@ -448,7 +448,7 @@ func createDailyNote(c *gin.Context) {
evt.AppId = app
name := path.Base(p)
files, _, _ := model.ListDocTree(box.ID, path.Dir(p), model.Conf.FileTree.Sort)
files, _, _ := model.ListDocTree(box.ID, path.Dir(p), model.Conf.FileTree.Sort, false)
evt.Data = map[string]interface{}{
"box": box,
"path": p,
@ -590,8 +590,13 @@ func searchDocs(c *gin.Context) {
return
}
flashcard := false
if arg["flashcard"] != nil {
flashcard = arg["flashcard"].(bool)
}
k := arg["k"].(string)
ret.Data = model.SearchDocsByKeyword(k)
ret.Data = model.SearchDocsByKeyword(k, flashcard)
}
func listDocsByPath(c *gin.Context) {
@ -610,7 +615,12 @@ func listDocsByPath(c *gin.Context) {
if nil != sortParam {
sortMode = int(sortParam.(float64))
}
files, totals, err := model.ListDocTree(notebook, p, sortMode)
flashcard := false
if arg["flashcard"] != nil {
flashcard = arg["flashcard"].(bool)
}
files, totals, err := model.ListDocTree(notebook, p, sortMode, flashcard)
if nil != err {
ret.Code = -1
ret.Msg = err.Error()
@ -708,7 +718,7 @@ func getDoc(c *gin.Context) {
func pushCreate(box *model.Box, p, treeID string, arg map[string]interface{}) {
evt := util.NewCmdResult("create", 0, util.PushModeBroadcast)
name := path.Base(p)
files, _, _ := model.ListDocTree(box.ID, path.Dir(p), model.Conf.FileTree.Sort)
files, _, _ := model.ListDocTree(box.ID, path.Dir(p), model.Conf.FileTree.Sort, false)
evt.Data = map[string]interface{}{
"box": box,
"path": p,

View file

@ -308,11 +308,27 @@ func lsNotebooks(c *gin.Context) {
ret := gulu.Ret.NewResult()
defer c.JSON(http.StatusOK, ret)
notebooks, err := model.ListNotebooks()
if nil != err {
arg, ok := util.JsonArg(c, ret)
if !ok {
return
}
flashcard := false
if arg["flashcard"] != nil {
flashcard = arg["flashcard"].(bool)
}
var notebooks []*model.Box
if flashcard {
notebooks = model.GetFlashcardNotebooks()
} else {
var err error
notebooks, err = model.ListNotebooks()
if nil != err {
return
}
}
ret.Data = map[string]interface{}{
"notebooks": notebooks,
}

View file

@ -27,16 +27,6 @@ import (
"github.com/siyuan-note/siyuan/kernel/util"
)
func getRiffCardNotebooks(c *gin.Context) {
ret := gulu.Ret.NewResult()
defer c.JSON(http.StatusOK, ret)
notebooks := model.GetFlashcardNotebooks()
ret.Data = map[string]interface{}{
"notebooks": notebooks,
}
}
func getNotebookRiffCards(c *gin.Context) {
ret := gulu.Ret.NewResult()
defer c.JSON(http.StatusOK, ret)

View file

@ -110,7 +110,7 @@ func loadTreeNodes(box string, p string, level int) (ret []*ast.Node, err error)
}
func buildBlockChildren(block *Block) (err error) {
files, _, err := ListDocTree(block.Box, block.Path, Conf.FileTree.Sort)
files, _, err := ListDocTree(block.Box, block.Path, Conf.FileTree.Sort, false)
if nil != err {
return
}

View file

@ -141,9 +141,18 @@ func (box *Box) moveCorruptedData(filePath string) {
logging.LogWarnf("moved corrupted data file [%s] to [%s]", filePath, to)
}
func SearchDocsByKeyword(keyword string) (ret []map[string]string) {
func SearchDocsByKeyword(keyword string, flashcard bool) (ret []map[string]string) {
ret = []map[string]string{}
var deckBlockIDs []string
if flashcard {
deck := Decks[builtinDeckID]
if nil != deck {
return
}
deckBlockIDs = deck.GetBlockIDs()
}
openedBoxes := Conf.GetOpenedBoxes()
boxes := map[string]*Box{}
for _, box := range openedBoxes {
@ -154,7 +163,13 @@ func SearchDocsByKeyword(keyword string) (ret []map[string]string) {
if "" != keyword {
for _, box := range boxes {
if strings.Contains(box.Name, keyword) {
ret = append(ret, map[string]string{"path": "/", "hPath": box.Name + "/", "box": box.ID, "boxIcon": box.Icon})
if flashcard {
if isBoxContainFlashcard(box.ID, deckBlockIDs) {
ret = append(ret, map[string]string{"path": "/", "hPath": box.Name + "/", "box": box.ID, "boxIcon": box.Icon})
}
} else {
ret = append(ret, map[string]string{"path": "/", "hPath": box.Name + "/", "box": box.ID, "boxIcon": box.Icon})
}
}
}
@ -168,17 +183,29 @@ func SearchDocsByKeyword(keyword string) (ret []map[string]string) {
rootBlocks = sql.QueryRootBlockByCondition(condition)
} else {
for _, box := range boxes {
ret = append(ret, map[string]string{"path": "/", "hPath": box.Name + "/", "box": box.ID, "boxIcon": box.Icon})
if flashcard {
if isBoxContainFlashcard(box.ID, deckBlockIDs) {
ret = append(ret, map[string]string{"path": "/", "hPath": box.Name + "/", "box": box.ID, "boxIcon": box.Icon})
}
} else {
ret = append(ret, map[string]string{"path": "/", "hPath": box.Name + "/", "box": box.ID, "boxIcon": box.Icon})
}
}
}
for _, block := range rootBlocks {
b := boxes[block.Box]
for _, rootBlock := range rootBlocks {
b := boxes[rootBlock.Box]
if nil == b {
continue
}
hPath := b.Name + block.HPath
ret = append(ret, map[string]string{"path": block.Path, "hPath": hPath, "box": block.Box, "boxIcon": b.Icon})
hPath := b.Name + rootBlock.HPath
if flashcard {
if isTreeContainFlashcard(rootBlock.ID, deckBlockIDs) {
ret = append(ret, map[string]string{"path": rootBlock.Path, "hPath": hPath, "box": rootBlock.Box, "boxIcon": b.Icon})
}
} else {
ret = append(ret, map[string]string{"path": rootBlock.Path, "hPath": hPath, "box": rootBlock.Box, "boxIcon": b.Icon})
}
}
sort.Slice(ret, func(i, j int) bool {
@ -194,7 +221,7 @@ type FileInfo struct {
isdir bool
}
func ListDocTree(boxID, path string, sortMode int) (ret []*File, totals int, err error) {
func ListDocTree(boxID, path string, sortMode int, flashcard bool) (ret []*File, totals int, err error) {
//os.MkdirAll("pprof", 0755)
//cpuProfile, _ := os.Create("pprof/cpu_profile_list_doc_tree")
//pprof.StartCPUProfile(cpuProfile)
@ -202,6 +229,15 @@ func ListDocTree(boxID, path string, sortMode int) (ret []*File, totals int, err
ret = []*File{}
var deckBlockIDs []string
if flashcard {
deck := Decks[builtinDeckID]
if nil != deck {
return
}
deckBlockIDs = deck.GetBlockIDs()
}
box := Conf.Box(boxID)
if nil == box {
return nil, 0, errors.New(Conf.Language(0))
@ -247,7 +283,15 @@ func ListDocTree(boxID, path string, sortMode int) (ret []*File, totals int, err
}
}
}
docs = append(docs, doc)
if flashcard {
rootID := strings.TrimSuffix(filepath.Base(parentDocPath), ".sy")
if isTreeContainFlashcard(rootID, deckBlockIDs) {
docs = append(docs, doc)
}
} else {
docs = append(docs, doc)
}
}
continue
}
@ -259,8 +303,15 @@ func ListDocTree(boxID, path string, sortMode int) (ret []*File, totals int, err
if ial := box.docIAL(file.path); nil != ial {
doc := box.docFromFileInfo(file, ial)
docs = append(docs, doc)
continue
if flashcard {
rootID := strings.TrimSuffix(filepath.Base(file.path), ".sy")
if isTreeContainFlashcard(rootID, deckBlockIDs) {
docs = append(docs, doc)
}
} else {
docs = append(docs, doc)
}
}
}
elapsed = time.Now().Sub(start).Milliseconds()

View file

@ -47,14 +47,24 @@ func GetFlashcardNotebooks() (ret []*Box) {
boxes := Conf.GetOpenedBoxes()
for _, box := range boxes {
if isNotebookContainFlashcard(box.ID, deckBlockIDs) {
if isBoxContainFlashcard(box.ID, deckBlockIDs) {
ret = append(ret, box)
}
}
return
}
func isNotebookContainFlashcard(boxID string, deckBlockIDs []string) (ret bool) {
func isTreeContainFlashcard(rootID string, deckBlockIDs []string) (ret bool) {
blockIDs := getTreeSubTreeChildBlocks(rootID)
for _, blockID := range deckBlockIDs {
if gulu.Str.Contains(blockID, blockIDs) {
return true
}
}
return
}
func isBoxContainFlashcard(boxID string, deckBlockIDs []string) (ret bool) {
entries, err := os.ReadDir(filepath.Join(util.DataDir, boxID))
if nil != err {
logging.LogErrorf("read dir failed: %s", err)
@ -71,11 +81,8 @@ func isNotebookContainFlashcard(boxID string, deckBlockIDs []string) (ret bool)
}
rootID := strings.TrimSuffix(entry.Name(), ".sy")
blockIDs := getTreeSubTreeChildBlocks(rootID)
for _, blockID := range deckBlockIDs {
if gulu.Str.Contains(blockID, blockIDs) {
return true
}
if isTreeContainFlashcard(rootID, deckBlockIDs) {
return true
}
}
return

View file

@ -194,7 +194,7 @@ func Mount(boxID string) (alreadyMount bool, err error) {
box.Index()
// 缓存根一级的文档树展开
ListDocTree(box.ID, "/", Conf.FileTree.Sort)
ListDocTree(box.ID, "/", Conf.FileTree.Sort, false)
treenode.SaveBlockTree(false)
util.ClearPushProgress(100)