feat: show incomplete Magic Notes todo counts
Magic Notes can now show a default-on incomplete todo badge in the primary navigation. The badge hides at zero, caps its visual label at 99+ while retaining the exact accessible count, and refreshes after user or Agent/MCP note changes. Platform Features > Magic Notes includes a persistent switch that hides only the count without changing notes or the Magic Notes entry. Existing settings migrate with the count enabled. Release note: 左侧“魔法笔记”入口现在可显示未完成待办数量;可在“平台功能 → 魔法笔记”中关闭,超过 99 项显示“99+”。
This commit is contained in:
@@ -24,10 +24,17 @@ afterEach(async () => {
|
||||
)
|
||||
})
|
||||
|
||||
async function createDatabase(): Promise<AssistantDatabase> {
|
||||
async function createDatabase(
|
||||
options: {
|
||||
onMagicTodosChanged?: () => void
|
||||
} = {}
|
||||
): Promise<AssistantDatabase> {
|
||||
const directory = await mkdtemp(join(tmpdir(), 'goodbuddy-assistant-'))
|
||||
temporaryDirectories.push(directory)
|
||||
const database = new AssistantDatabase(join(directory, 'assistant.sqlite'))
|
||||
const database = new AssistantDatabase(
|
||||
join(directory, 'assistant.sqlite'),
|
||||
options
|
||||
)
|
||||
database.initialize('C:\\Workspace')
|
||||
return database
|
||||
}
|
||||
@@ -4064,6 +4071,60 @@ describe('AssistantDatabase', () => {
|
||||
database.close()
|
||||
})
|
||||
|
||||
it('counts incomplete todos and publishes todo-changing writes', async () => {
|
||||
const onMagicTodosChanged = vi.fn()
|
||||
const database = await createDatabase({ onMagicTodosChanged })
|
||||
const note = database.createMagicNote({ title: '发布笔记' })
|
||||
|
||||
expect(database.getMagicTodoStatus()).toEqual({
|
||||
incompleteCount: 0
|
||||
})
|
||||
expect(onMagicTodosChanged).not.toHaveBeenCalled()
|
||||
|
||||
database.createMagicNoteEntry({
|
||||
noteId: note.id,
|
||||
content: {
|
||||
version: 1,
|
||||
ops: [
|
||||
{ insert: '核对发布材料' },
|
||||
{ insert: '\n', attributes: { list: 'unchecked' } },
|
||||
{ insert: '上传构建产物' },
|
||||
{ insert: '\n', attributes: { list: 'unchecked' } },
|
||||
{ insert: '通知负责人' },
|
||||
{ insert: '\n', attributes: { list: 'checked' } }
|
||||
]
|
||||
},
|
||||
plainText: '核对发布材料\n上传构建产物\n通知负责人'
|
||||
})
|
||||
|
||||
expect(database.getMagicTodoStatus()).toEqual({
|
||||
incompleteCount: 2
|
||||
})
|
||||
expect(onMagicTodosChanged).toHaveBeenCalledTimes(1)
|
||||
|
||||
const todo = database
|
||||
.listMagicTodos()
|
||||
.find((candidate) => !candidate.completed)!
|
||||
database.updateMagicTodo({
|
||||
todoId: todo.id,
|
||||
completed: true,
|
||||
expectedRevision: todo.revision
|
||||
})
|
||||
|
||||
expect(database.getMagicTodoStatus()).toEqual({
|
||||
incompleteCount: 1
|
||||
})
|
||||
expect(onMagicTodosChanged).toHaveBeenCalledTimes(2)
|
||||
|
||||
database.deleteMagicNote(note.id)
|
||||
expect(database.getMagicTodoStatus()).toEqual({
|
||||
incompleteCount: 0
|
||||
})
|
||||
expect(onMagicTodosChanged).toHaveBeenCalledTimes(3)
|
||||
|
||||
database.close()
|
||||
})
|
||||
|
||||
it('protects magic note records from stale revisions', async () => {
|
||||
const database = await createDatabase()
|
||||
const note = database.createMagicNote({ title: '并发笔记' })
|
||||
|
||||
Reference in New Issue
Block a user