New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor flashcard low-level implementation structure #10471
Comments
双手支持,并且希望插件能提供闪卡复习界面的一些事件,来开发出更高级的功能。 基于以上,可以实现例如闪卡自动发音(可能会有什么安全限制?这个待验证),闪卡支持正面手动输入答案,背面自动评分,自动推迟昨日到期闪卡等等高级功能。 以上的部分功能虽然可以通过前端的MutationObserver实现,但是需要考虑的东西太多,远不如官方提供准确的事件来的方便。 |
@HowcanoeWang 一张闪卡只能对应一个块,否则编辑器会有问题,所以添加闪卡的时候也是一张闪卡对应一个块的;关于双向制卡和模板制卡我估计基于现有结构很难实现了…… |
@88250 闪卡和单块绑定感觉限制太大了(比如你说的,编辑器会出问题) 有没有可能把闪卡在数据库中独立出来一个数据结构+编辑UI? 从数据库来说,每张闪卡有一个独立的ID,然后记录正面卡面包含的所有块ID,和反面卡片包含的块ID。 @zxhd863943427 闪卡独立ID后,还能增加你上面提到的不同闪卡类型,然后思源闪卡UI就能根据类型来进行不同的UI渲染 一切的基础都是要把闪卡从单个块绑定剥离 |
@88250 @zxhd863943427 @luo-chuan 比如在数据库中,闪卡独立出来,拥有如下的数据结构:
这种数据结构,无缝兼容目前思源笔记所使用的闪卡和单个块绑定(把frontIDs改成绑定的单个块列表即可) |
能详细说一下为什么一张闪卡只能对应一个块,否则编辑器会有问题? 我自己在捣鼓实现的时候,拿废弃的卡包当成分类依据,也实现了一块多卡的demo。 |
目前闪卡的具体结构不是这个样子的,参见这个:https://pkg.go.dev/github.com/open-spaced-repetition/go-fsrs#Card 我把它复制过来在下面方便看:
思源目前的实现差不多就是在这个包的基础上浅浅地套了一层皮,改成你这个数据结构其实改动并不小。 |
期待大佬们讨论出完美方案,我先围观。 |
@zxhd863943427 直接把哪些属性添加到上面数据结构表格的列就无缝对接了,但代码层面确实要改动不少。不过个人感觉赶紧把底层重新设计一下对拓展性来说更重要一点 |
类似的,可以参考Anki的数据结构:
|
双向制卡的应用场景主要是背单词是吧,包括闪卡语音功能也是,我尚未想到其他应用场景。其实我觉得背单词这种需求为啥不用专门的背单词软件,欧路词典、墨墨背单词、百词斩一大堆功能丰富的。用anki记单词,自己复制释义、例句吗? 如果是英语翻译、改错、完形填空这种学习,也用不到双向吧 |
话说其他笔记软件如logseq,obsidian插件怎么实现双向闪卡的呢?可以研究下吧 |
你是说独立出一个类似anki的制卡和复习页面吗?其实思源的优势就是在做笔记、复习笔记的过程中非常方便地将重要内容制作闪卡,在复习闪卡时非常方便地修改闪卡以及查看闪卡上下文(退出聚焦),笔记为主、闪卡为辅。 思源闪卡其实没有正面、反面的概念,只有问题、答案的概念,一张闪卡绑定一个问题块,前端根据问题块类型(列表块、超级块、标题块…)的不同,以不同的展示方式展示答案。这个anki的逻辑有很大差别。 在制卡方面,思源可以参照下其他笔记软件,毕竟anki不是笔记软件 |
这两的闪卡功能不值一提。参考remnote才有意义。 |
双向卡很多学科都需要,举个例子。 |
后端改动主要是 Riff card 基类,将 BID 改成 frontIDs 和 backIDs,考虑到需要向前兼容,所以估计得保留 BID,新增 frontIDs 和 backIDs,使用过程中自动将 BID 迁移到 frontIDs 中,以及已有容器块子块迁移到 backIDs 中。 前端改动主要是闪卡管理界面,右侧需要类似嵌入块分栏多个块 @Vanessa219 这个 Issue 有点大,我估计得拆分一下(先占位,等考虑好后创建 issue 关联):
#10471 (comment) 这里提到的结构,挖空 字段估计不适合,因为思源挖空是个开关,用户随时可以打开或者关闭,不是在卡片上记录挖空状态的。 |
建议挖空变成工具栏feature也行呢,和标记区分开。 |
对。既然要重构,那就重新考虑一下这个。 |
关联block的部分与卡片最好分开来,如果重构的话还是考虑参考anki的设计,从note的field字段中生成卡片。 总之这个不急着开工,先确定一个足够拓展性的结构再说。 |
嗯,不急着开工的,这个改动有点大,我们先完成闪卡其他能够改进的点,这个需要再考虑一段时间,估计今年内都不一定能改到这里。 |
感觉这方面可能需要适当提高速度了,不然依赖于当前结构的接口太多了到时候就不好改了。 |
不是嵌入块,官方的复习界面应该直接使用插件生成的dom |
要实现高级制卡,恐怕插件还要实现一个类似anki一样的制卡界面,通过拖动,将问题块、答案块分别拖动到问题栏,答案栏。 在复习界面还要有个修改按钮,能唤醒该制卡界面。 |
哦哦,这样吗,我看到D大上面写了嵌入块三个字,以为要改成这样 |
嗯,主要就是复习界面的交互方式,我个人感觉应该不存在太大的问题,估计需要 @Vanessa219 一起讨论看看。 |
我仔细想了想,cardsource我之后还是想办法pr给内核吧,不然没办法实现统一的note管理,各个插件自己管理自己那一部分闪卡有点不对劲 |
插件实现 CardSource 的话是存在这种情况,内核实现的话我们得再考虑一下,先不急着开工。 |
歪个楼 如果闪卡能用dom实现直接编辑的话,那其实嵌入块应该也能实现直接编辑?目前嵌入块弹出新窗口再编辑,感觉有点太跳脱了 |
插件实现的高级闪卡该怎么编辑还在考虑呢,总之不大可能直接在闪卡复习界面就能编辑,大概会像anki一样,有啥更好的想法吗? |
闪卡复习界面不能编辑的话,那拿闪卡来实现渐进阅读/写作的怎么办 |
只是说比较难像全部像现在这样直接写,可能需要搞一个弹窗出来,一些本身就用块实现的依然可以编辑,总之这个依赖于实现。 比如说,要是实现了一个database闪卡,那它肯定不能像块一样编辑的。 |
我觉得闪卡编辑要不学obsedian,提供一个预览和编辑切换按钮。 如果遇到了和块嵌入一样的dom问题不能直接编辑,或许可以切换之后类似那个思源vscode插件界面,提供kmarkdown进行编辑? |
这个想法好 |
已知的块类型(包括现在的标记制卡、列表制卡和标题制卡等)可以和现在一样,都是编辑器里加载。高级闪卡需要哪些反面的支持能否举个例子? |
基本思路就是还是要跳转回相应块来编辑。至于跳转回哪个块,可以留个接口,由插件决定。 |
可以直接跳转到块的例子:
let cardSource = {
noteID:'20230121',
cardType:"hollow",
data:'20240319164146-3zncux0'
}
let card1 = {
noteID:"20230121",
cardID:"20240323sdfasf",
分组标记:"1"
}
let card2 = {
noteID:"20230121",
cardID:"2024032341341fd",
分组标记:"2"
} 内容: 正面: 反面: 编辑界面:
let cardSource = {
noteID:'202302131',
cardType:"word card",
data:'[\'20240319173630-5ko8z08\',\'20240319173645-khw0yh8\',\'20240319173713-hs9qgdm\']'
}
let card1 = {
noteID:"202302131",
cardID:"20240323sdfasf",
分组标记:"只显示单词"
}
let card2 = {
noteID:"202302131",
cardID:"2024032341341fd",
分组标记:"只显示含义"
}
let card2 = {
noteID:"202302131",
cardID:"2024032341341fd",
分组标记:"只播放音频"
} 这个每个闪卡应该显示什么应该很明显了,所有就不截图演示了。 编辑界面: 无法直接跳转到块编辑的例子:
let cardSource = {
noteID:'20230dasfs',
cardType:"database card",
data:`
{
database_id:'20231226123452-7j7qvvm',
问题列id:"20231205125404-4ycg770", //database中问题所在列ID
答案列id:"20231205125412-4g1by0h" //database中答案所在列ID
}
`
}
let card1 = {
noteID:"202302131",
cardID:"20240323sdfasf",
分组标记:"20231205125406-gimld0c" //第一行的ID
}
let card2 = {
noteID:"202302131",
cardID:"2024032341341fd",
分组标记:"20231205125408-mzm2878" //第二行的ID
}
let cardSource = {
noteID:'asadada',
cardType:"hollow",
data:`
{
img:"assets/00203-20231117222620-1fbxbl6.jpeg",
hollow:[{"left":313.532506203474,"top":147.8433862433862,"width":72.89131513647638,"height":103.88994708994707,"angle":0,"cId":1}]
}
`
}
let card1 = {
noteID:"asadada",
cardID:"20240323sdfasf",
分组标记:"1"
} 编辑界面: |
因此,对于之后插件实现的不同闪卡类型,其实不太可能使用统一的方案进行编辑,而只能由闪卡的实现者来设置编辑界面。 |
@zxhd863943427 感谢示意,我明白了。 现在整个方案应该是清晰了,稍后我整理一下方案大家再评估讨论看看。 时间上争取在下个月能开工。 |
D大,方案还没整理好吗 |
还没开始……这两天事情太多了,我尽量抓紧。 |
路过,顶顶 |
1 similar comment
路过,顶顶 |
顶顶,月末了!!心痒难赖 |
大致整理了下方案: 原则现有的 快速制卡 保持不变,提供 高级制卡。 数据结构修改 Card,增加字段:
新增 CardSource:
前端TODO 版本计划
|
这个方案感觉没有太大问题。 |
前端没有时间,后面考虑吧。 |
返回的数据只是额外增加字段即可,前端不需要这么快变动。 |
提供闪卡交互API
In what scenarios do you need this feature?
目前的闪卡只提供了 正面-反面 制卡,对于大部分问答式场景来说足够使用,但有时候也有翻转的需求(一个内容提供 正-反,反-正两张卡片)。
更进一步来说,对于部分学习的场景下,可能有更复杂的模板制卡的需求(Anki的)。如英语单词,最基本的需要准备 英语、中文、发音 三块内容,对应的需要制成 英-中(知道意思),中-英(中文意思到英语单词),音-中(听力卡片) 三张卡片才能比较好的掌握该单词。
虽然Anki可以很方便的实现上述功能,但Anki的卡组没有笔记的逻辑性,在数据超过上千的时候,即使使用标签也非常混乱,不利于知识库的维护。
因此想增强一下思源的闪卡功能,目前本人愿意开发模板制卡的插件,希望能提供或更新一下闪卡的API,目前想出来的插件可能需要有如下的API:
从指定的块ID中创建卡片,不确定这个是不是已经有实现了?
siyuan/kernel/api/router.go
Line 316 in bdacf39
API/flashcard/addFlashcard
编辑闪卡对应的正面内容和反面内容
API/flashcard/setFlashcard
输入一个块ID,打上制卡的颜色提示(可选项,或后续再讨论)
上述API修改,将闪卡制卡不仅限于父子块,允许完全独立的块生成闪卡(方便闪卡模板插件生成对应的markdown模板进行管理)
使用示例(插件调用API实现,不需要官方下场,仅用来说明应用场景)
调用插件,制卡,会在文档中插入一个如下的 无序列表块 来提供闪卡模板 (仅作示例,用户可以在插件中自定义来生成更复杂的
模板):
对于整体的无序列表块,自定义如下属性:
来追踪和管理,这个生成了哪些闪卡。
对于上面的每一个字段列表项 (如
* 字段1 (field-1)
),有如下自定义属性:用来引导下面的所有子块作为模板填充选项。
根据用户的闪卡生成设置(如这个例子,生成3张单词表闪卡):
正面是字段1 (field-1) 下面的所有子块,反面是 field-2 和field-3的所有子块 (用户可自定义)
正面是 field-2 下面的所有子块,反面是 field-1 和field-3的所有子块 (用户可自定义)
正面是 field-3 下面的所有子块,反面是 field-1 和field-2的所有子块 (用户可自定义)
Describe the optimal solution
官方实现翻转闪卡和用户自定义模板?感觉官方应该没有精力来搞
Describe the candidate solution
No response
Other information
No response
The text was updated successfully, but these errors were encountered: