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:
@@ -58,13 +58,15 @@ describe('ApplicationSettingsStore', () => {
|
||||
await expect(
|
||||
store.update({
|
||||
checkUpdatesOnStartup: false,
|
||||
magicNotesEnabled: false
|
||||
magicNotesEnabled: false,
|
||||
magicNotesShowIncompleteTodoCount: false
|
||||
})
|
||||
).resolves.toEqual({
|
||||
checkUpdatesOnStartup: false,
|
||||
updateSource: 'github',
|
||||
modelDownloadSource: 'modelscope',
|
||||
magicNotesEnabled: false,
|
||||
magicNotesShowIncompleteTodoCount: false,
|
||||
magicNoteCommentMode: 'immediate',
|
||||
magicNoteCommentFormat: 'combined'
|
||||
})
|
||||
@@ -73,15 +75,17 @@ describe('ApplicationSettingsStore', () => {
|
||||
updateSource: 'github',
|
||||
modelDownloadSource: 'modelscope',
|
||||
magicNotesEnabled: false,
|
||||
magicNotesShowIncompleteTodoCount: false,
|
||||
magicNoteCommentMode: 'immediate',
|
||||
magicNoteCommentFormat: 'combined'
|
||||
})
|
||||
expect(JSON.parse(await readFile(filePath, 'utf8'))).toEqual({
|
||||
version: 7,
|
||||
version: 8,
|
||||
checkUpdatesOnStartup: false,
|
||||
updateSource: 'github',
|
||||
modelDownloadSource: 'modelscope',
|
||||
magicNotesEnabled: false,
|
||||
magicNotesShowIncompleteTodoCount: false,
|
||||
magicNoteCommentMode: 'immediate',
|
||||
magicNoteCommentFormat: 'combined',
|
||||
lastSeenReleaseNotesVersion: null
|
||||
@@ -107,6 +111,7 @@ describe('ApplicationSettingsStore', () => {
|
||||
updateSource: 'github',
|
||||
modelDownloadSource: 'modelscope',
|
||||
magicNotesEnabled: false,
|
||||
magicNotesShowIncompleteTodoCount: true,
|
||||
magicNoteCommentMode: 'immediate',
|
||||
magicNoteCommentFormat: 'combined'
|
||||
})
|
||||
@@ -130,6 +135,7 @@ describe('ApplicationSettingsStore', () => {
|
||||
updateSource: 'github',
|
||||
modelDownloadSource: 'modelscope',
|
||||
magicNotesEnabled: false,
|
||||
magicNotesShowIncompleteTodoCount: true,
|
||||
magicNoteCommentMode: 'immediate',
|
||||
magicNoteCommentFormat: 'combined'
|
||||
})
|
||||
@@ -153,6 +159,7 @@ describe('ApplicationSettingsStore', () => {
|
||||
updateSource: 'github',
|
||||
modelDownloadSource: 'modelscope',
|
||||
magicNotesEnabled: true,
|
||||
magicNotesShowIncompleteTodoCount: true,
|
||||
magicNoteCommentMode: 'immediate',
|
||||
magicNoteCommentFormat: 'combined'
|
||||
})
|
||||
@@ -176,6 +183,7 @@ describe('ApplicationSettingsStore', () => {
|
||||
updateSource: 'github',
|
||||
modelDownloadSource: 'modelscope',
|
||||
magicNotesEnabled: true,
|
||||
magicNotesShowIncompleteTodoCount: true,
|
||||
magicNoteCommentMode: 'after-save-manual',
|
||||
magicNoteCommentFormat: 'combined'
|
||||
})
|
||||
@@ -201,11 +209,12 @@ describe('ApplicationSettingsStore', () => {
|
||||
new ApplicationSettingsStore(filePath).getLastSeenReleaseNotesVersion()
|
||||
).resolves.toBe('0.8.18')
|
||||
expect(JSON.parse(await readFile(filePath, 'utf8'))).toEqual({
|
||||
version: 7,
|
||||
version: 8,
|
||||
checkUpdatesOnStartup: false,
|
||||
updateSource: 'github',
|
||||
modelDownloadSource: 'modelscope',
|
||||
magicNotesEnabled: true,
|
||||
magicNotesShowIncompleteTodoCount: true,
|
||||
magicNoteCommentMode: 'after-save-manual',
|
||||
magicNoteCommentFormat: 'narrative',
|
||||
lastSeenReleaseNotesVersion: '0.8.18'
|
||||
@@ -232,6 +241,7 @@ describe('ApplicationSettingsStore', () => {
|
||||
updateSource: 'github',
|
||||
modelDownloadSource: 'modelscope',
|
||||
magicNotesEnabled: true,
|
||||
magicNotesShowIncompleteTodoCount: true,
|
||||
magicNoteCommentMode: 'after-save-auto',
|
||||
magicNoteCommentFormat: 'structured'
|
||||
})
|
||||
@@ -258,6 +268,7 @@ describe('ApplicationSettingsStore', () => {
|
||||
updateSource: 'mirror',
|
||||
modelDownloadSource: 'modelscope',
|
||||
magicNotesEnabled: true,
|
||||
magicNotesShowIncompleteTodoCount: true,
|
||||
magicNoteCommentMode: 'after-save-auto',
|
||||
magicNoteCommentFormat: 'structured'
|
||||
})
|
||||
@@ -268,11 +279,40 @@ describe('ApplicationSettingsStore', () => {
|
||||
await store.update({ modelDownloadSource: 'hugging-face' })
|
||||
expect(JSON.parse(await readFile(filePath, 'utf8'))).toEqual({
|
||||
...versionSix,
|
||||
version: 7,
|
||||
modelDownloadSource: 'hugging-face'
|
||||
version: 8,
|
||||
modelDownloadSource: 'hugging-face',
|
||||
magicNotesShowIncompleteTodoCount: true
|
||||
})
|
||||
})
|
||||
|
||||
it('migrates version 7 to show incomplete todo counts', async () => {
|
||||
const { filePath, store } = await createStore()
|
||||
const versionSeven = {
|
||||
version: 7,
|
||||
checkUpdatesOnStartup: false,
|
||||
updateSource: 'github',
|
||||
modelDownloadSource: 'modelscope',
|
||||
magicNotesEnabled: true,
|
||||
magicNoteCommentMode: 'immediate',
|
||||
magicNoteCommentFormat: 'combined',
|
||||
lastSeenReleaseNotesVersion: null
|
||||
}
|
||||
await writeFile(filePath, JSON.stringify(versionSeven), 'utf8')
|
||||
|
||||
await expect(store.get()).resolves.toEqual({
|
||||
checkUpdatesOnStartup: false,
|
||||
updateSource: 'github',
|
||||
modelDownloadSource: 'modelscope',
|
||||
magicNotesEnabled: true,
|
||||
magicNotesShowIncompleteTodoCount: true,
|
||||
magicNoteCommentMode: 'immediate',
|
||||
magicNoteCommentFormat: 'combined'
|
||||
})
|
||||
expect(JSON.parse(await readFile(filePath, 'utf8'))).toEqual(
|
||||
versionSeven
|
||||
)
|
||||
})
|
||||
|
||||
it('strictly rejects incomplete full settings', () => {
|
||||
for (const input of [
|
||||
{},
|
||||
@@ -319,6 +359,7 @@ describe('ApplicationSettingsStore', () => {
|
||||
updateSource: 'github',
|
||||
modelDownloadSource: 'modelscope',
|
||||
magicNotesEnabled: true,
|
||||
magicNotesShowIncompleteTodoCount: true,
|
||||
magicNoteCommentMode: 'immediate',
|
||||
magicNoteCommentFormat: 'combined'
|
||||
})
|
||||
@@ -433,15 +474,17 @@ describe('ApplicationSettingsStore', () => {
|
||||
updateSource: 'github',
|
||||
modelDownloadSource: 'modelscope',
|
||||
magicNotesEnabled: false,
|
||||
magicNotesShowIncompleteTodoCount: true,
|
||||
magicNoteCommentMode: 'immediate',
|
||||
magicNoteCommentFormat: 'combined'
|
||||
})
|
||||
expect(JSON.parse(await readFile(filePath, 'utf8'))).toEqual({
|
||||
version: 7,
|
||||
version: 8,
|
||||
checkUpdatesOnStartup: false,
|
||||
updateSource: 'github',
|
||||
modelDownloadSource: 'modelscope',
|
||||
magicNotesEnabled: false,
|
||||
magicNotesShowIncompleteTodoCount: true,
|
||||
magicNoteCommentMode: 'immediate',
|
||||
magicNoteCommentFormat: 'combined',
|
||||
lastSeenReleaseNotesVersion: null
|
||||
@@ -467,6 +510,7 @@ describe('ApplicationSettingsStore', () => {
|
||||
updateSource: 'github',
|
||||
modelDownloadSource: 'modelscope',
|
||||
magicNotesEnabled: true,
|
||||
magicNotesShowIncompleteTodoCount: true,
|
||||
magicNoteCommentMode: 'immediate',
|
||||
magicNoteCommentFormat: 'combined'
|
||||
})
|
||||
|
||||
@@ -20,7 +20,7 @@ export {
|
||||
} from '../shared/application-settings-contracts'
|
||||
export type { ApplicationSettings } from '../shared/application-settings-contracts'
|
||||
|
||||
const CURRENT_SETTINGS_VERSION = 7
|
||||
const CURRENT_SETTINGS_VERSION = 8
|
||||
|
||||
const legacyStoredApplicationSettingsSchema = z
|
||||
.object({
|
||||
@@ -47,14 +47,22 @@ const versionThreeStoredApplicationSettingsSchema = z
|
||||
.strict()
|
||||
|
||||
const versionFourStoredApplicationSettingsSchema = applicationSettingsSchema
|
||||
.omit({ updateSource: true, modelDownloadSource: true })
|
||||
.omit({
|
||||
updateSource: true,
|
||||
modelDownloadSource: true,
|
||||
magicNotesShowIncompleteTodoCount: true
|
||||
})
|
||||
.extend({
|
||||
version: z.literal(4)
|
||||
})
|
||||
.strict()
|
||||
|
||||
const versionFiveStoredApplicationSettingsSchema = applicationSettingsSchema
|
||||
.omit({ updateSource: true, modelDownloadSource: true })
|
||||
.omit({
|
||||
updateSource: true,
|
||||
modelDownloadSource: true,
|
||||
magicNotesShowIncompleteTodoCount: true
|
||||
})
|
||||
.extend({
|
||||
version: z.literal(5),
|
||||
lastSeenReleaseNotesVersion: releaseVersionSchema.nullable()
|
||||
@@ -62,13 +70,25 @@ const versionFiveStoredApplicationSettingsSchema = applicationSettingsSchema
|
||||
.strict()
|
||||
|
||||
const versionSixStoredApplicationSettingsSchema = applicationSettingsSchema
|
||||
.omit({ modelDownloadSource: true })
|
||||
.omit({
|
||||
modelDownloadSource: true,
|
||||
magicNotesShowIncompleteTodoCount: true
|
||||
})
|
||||
.extend({
|
||||
version: z.literal(6),
|
||||
lastSeenReleaseNotesVersion: releaseVersionSchema.nullable()
|
||||
})
|
||||
.strict()
|
||||
|
||||
const versionSevenStoredApplicationSettingsSchema =
|
||||
applicationSettingsSchema
|
||||
.omit({ magicNotesShowIncompleteTodoCount: true })
|
||||
.extend({
|
||||
version: z.literal(7),
|
||||
lastSeenReleaseNotesVersion: releaseVersionSchema.nullable()
|
||||
})
|
||||
.strict()
|
||||
|
||||
const storedApplicationSettingsSchema = applicationSettingsSchema
|
||||
.extend({
|
||||
version: z.literal(CURRENT_SETTINGS_VERSION),
|
||||
@@ -85,6 +105,7 @@ export const defaultApplicationSettings: ApplicationSettings = {
|
||||
updateSource: 'github',
|
||||
modelDownloadSource: 'modelscope',
|
||||
magicNotesEnabled: false,
|
||||
magicNotesShowIncompleteTodoCount: true,
|
||||
magicNoteCommentMode: 'immediate',
|
||||
magicNoteCommentFormat: 'combined'
|
||||
}
|
||||
@@ -140,13 +161,24 @@ export class ApplicationSettingsStore {
|
||||
)
|
||||
const result = storedApplicationSettingsSchema.safeParse(parsed)
|
||||
if (!result.success) {
|
||||
const versionSevenResult =
|
||||
versionSevenStoredApplicationSettingsSchema.safeParse(parsed)
|
||||
if (versionSevenResult.success) {
|
||||
this.settings = {
|
||||
...versionSevenResult.data,
|
||||
version: CURRENT_SETTINGS_VERSION,
|
||||
magicNotesShowIncompleteTodoCount: true
|
||||
}
|
||||
return this.settings
|
||||
}
|
||||
const versionSixResult =
|
||||
versionSixStoredApplicationSettingsSchema.safeParse(parsed)
|
||||
if (versionSixResult.success) {
|
||||
this.settings = {
|
||||
...versionSixResult.data,
|
||||
version: CURRENT_SETTINGS_VERSION,
|
||||
modelDownloadSource: 'modelscope'
|
||||
modelDownloadSource: 'modelscope',
|
||||
magicNotesShowIncompleteTodoCount: true
|
||||
}
|
||||
return this.settings
|
||||
}
|
||||
@@ -157,7 +189,8 @@ export class ApplicationSettingsStore {
|
||||
...versionFiveResult.data,
|
||||
version: CURRENT_SETTINGS_VERSION,
|
||||
updateSource: 'github',
|
||||
modelDownloadSource: 'modelscope'
|
||||
modelDownloadSource: 'modelscope',
|
||||
magicNotesShowIncompleteTodoCount: true
|
||||
}
|
||||
return this.settings
|
||||
}
|
||||
@@ -169,6 +202,7 @@ export class ApplicationSettingsStore {
|
||||
version: CURRENT_SETTINGS_VERSION,
|
||||
updateSource: 'github',
|
||||
modelDownloadSource: 'modelscope',
|
||||
magicNotesShowIncompleteTodoCount: true,
|
||||
lastSeenReleaseNotesVersion: null
|
||||
}
|
||||
return this.settings
|
||||
@@ -181,6 +215,7 @@ export class ApplicationSettingsStore {
|
||||
version: CURRENT_SETTINGS_VERSION,
|
||||
updateSource: 'github',
|
||||
modelDownloadSource: 'modelscope',
|
||||
magicNotesShowIncompleteTodoCount: true,
|
||||
magicNoteCommentFormat: 'combined',
|
||||
lastSeenReleaseNotesVersion: null
|
||||
}
|
||||
@@ -194,6 +229,7 @@ export class ApplicationSettingsStore {
|
||||
version: CURRENT_SETTINGS_VERSION,
|
||||
updateSource: 'github',
|
||||
modelDownloadSource: 'modelscope',
|
||||
magicNotesShowIncompleteTodoCount: true,
|
||||
magicNoteCommentMode: 'immediate',
|
||||
magicNoteCommentFormat: 'combined',
|
||||
lastSeenReleaseNotesVersion: null
|
||||
@@ -210,6 +246,7 @@ export class ApplicationSettingsStore {
|
||||
updateSource: 'github',
|
||||
modelDownloadSource: 'modelscope',
|
||||
magicNotesEnabled: false,
|
||||
magicNotesShowIncompleteTodoCount: true,
|
||||
magicNoteCommentMode: 'immediate',
|
||||
magicNoteCommentFormat: 'combined',
|
||||
lastSeenReleaseNotesVersion: null
|
||||
@@ -251,6 +288,8 @@ export class ApplicationSettingsStore {
|
||||
updateSource: stored.updateSource,
|
||||
modelDownloadSource: stored.modelDownloadSource,
|
||||
magicNotesEnabled: stored.magicNotesEnabled,
|
||||
magicNotesShowIncompleteTodoCount:
|
||||
stored.magicNotesShowIncompleteTodoCount,
|
||||
magicNoteCommentMode: stored.magicNoteCommentMode,
|
||||
magicNoteCommentFormat: stored.magicNoteCommentFormat,
|
||||
...(this.warnings.length > 0
|
||||
@@ -284,6 +323,8 @@ export class ApplicationSettingsStore {
|
||||
updateSource: next.updateSource,
|
||||
modelDownloadSource: next.modelDownloadSource,
|
||||
magicNotesEnabled: next.magicNotesEnabled,
|
||||
magicNotesShowIncompleteTodoCount:
|
||||
next.magicNotesShowIncompleteTodoCount,
|
||||
magicNoteCommentMode: next.magicNoteCommentMode,
|
||||
magicNoteCommentFormat: next.magicNoteCommentFormat
|
||||
}
|
||||
|
||||
@@ -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: '并发笔记' })
|
||||
|
||||
@@ -63,6 +63,7 @@ import {
|
||||
type MagicNoteSearchResult,
|
||||
type MagicNoteSummary,
|
||||
type MagicTodoItem,
|
||||
type MagicTodoStatus,
|
||||
type MagicTodoUpdateInput
|
||||
} from '../../shared/magic-notes-contracts'
|
||||
import type { ComputerControlAuditEvent } from '../computer-control/audit'
|
||||
@@ -967,7 +968,16 @@ export class AssistantDatabase {
|
||||
private channelEventWrites = 0
|
||||
private channelOutboxWrites = 0
|
||||
|
||||
constructor(private readonly databasePath: string) {}
|
||||
constructor(
|
||||
private readonly databasePath: string,
|
||||
private readonly options: {
|
||||
onMagicTodosChanged?: () => void
|
||||
} = {}
|
||||
) {}
|
||||
|
||||
private notifyMagicTodosChanged(): void {
|
||||
this.options.onMagicTodosChanged?.()
|
||||
}
|
||||
|
||||
initialize(defaultRootPath: string): void {
|
||||
if (this.database) {
|
||||
@@ -2605,7 +2615,11 @@ export class AssistantDatabase {
|
||||
database.exec('ROLLBACK')
|
||||
throw error
|
||||
}
|
||||
return this.getMagicNote(id)
|
||||
const detail = this.getMagicNote(id)
|
||||
if (input.content) {
|
||||
this.notifyMagicTodosChanged()
|
||||
}
|
||||
return detail
|
||||
}
|
||||
|
||||
updateMagicNote(input: {
|
||||
@@ -2644,6 +2658,7 @@ export class AssistantDatabase {
|
||||
if (result.changes !== 1) {
|
||||
throw new Error('笔记不存在')
|
||||
}
|
||||
this.notifyMagicTodosChanged()
|
||||
}
|
||||
|
||||
createMagicNoteEntry(input: {
|
||||
@@ -2696,7 +2711,9 @@ export class AssistantDatabase {
|
||||
database.exec('ROLLBACK')
|
||||
throw error
|
||||
}
|
||||
return this.getMagicNote(input.noteId)
|
||||
const detail = this.getMagicNote(input.noteId)
|
||||
this.notifyMagicTodosChanged()
|
||||
return detail
|
||||
}
|
||||
|
||||
updateMagicNoteEntry(input: {
|
||||
@@ -2758,7 +2775,9 @@ export class AssistantDatabase {
|
||||
database.exec('ROLLBACK')
|
||||
throw error
|
||||
}
|
||||
return this.getMagicNote(existing.note_id)
|
||||
const detail = this.getMagicNote(existing.note_id)
|
||||
this.notifyMagicTodosChanged()
|
||||
return detail
|
||||
}
|
||||
|
||||
deleteMagicNoteEntry(entryId: string): MagicNoteDetail {
|
||||
@@ -2787,7 +2806,9 @@ export class AssistantDatabase {
|
||||
database.exec('ROLLBACK')
|
||||
throw error
|
||||
}
|
||||
return this.getMagicNote(existing.note_id)
|
||||
const detail = this.getMagicNote(existing.note_id)
|
||||
this.notifyMagicTodosChanged()
|
||||
return detail
|
||||
}
|
||||
|
||||
getMagicNoteEntry(entryId: string): MagicNoteEntry {
|
||||
@@ -2861,6 +2882,17 @@ export class AssistantDatabase {
|
||||
).map(toMagicTodo)
|
||||
}
|
||||
|
||||
getMagicTodoStatus(): MagicTodoStatus {
|
||||
const row = this.requireDatabase()
|
||||
.prepare(
|
||||
`SELECT COUNT(*) AS incomplete_count
|
||||
FROM magic_todos
|
||||
WHERE source = 'note' AND completed = 0`
|
||||
)
|
||||
.get() as { incomplete_count: number }
|
||||
return { incompleteCount: row.incomplete_count }
|
||||
}
|
||||
|
||||
searchMagicNotes(query: string, limit: number): MagicNoteSearchResult[] {
|
||||
const pattern = `%${query.replace(/[\\%_]/gu, '\\$&')}%`
|
||||
return (
|
||||
@@ -2985,7 +3017,9 @@ export class AssistantDatabase {
|
||||
database.exec('ROLLBACK')
|
||||
throw error
|
||||
}
|
||||
return this.getMagicTodo(input.todoId)
|
||||
const todo = this.getMagicTodo(input.todoId)
|
||||
this.notifyMagicTodosChanged()
|
||||
return todo
|
||||
}
|
||||
|
||||
saveMagicTodoAnalysis(input: {
|
||||
|
||||
+16
-1
@@ -511,7 +511,22 @@ if (hasSingleInstanceLock) {
|
||||
| ReturnType<typeof createRerankProvider>
|
||||
| undefined
|
||||
const startupAssistantDatabase = new AssistantDatabase(
|
||||
join(app.getPath('userData'), 'assistant.sqlite')
|
||||
join(app.getPath('userData'), 'assistant.sqlite'),
|
||||
{
|
||||
onMagicTodosChanged: () => {
|
||||
queueMicrotask(() => {
|
||||
if (
|
||||
mainWindow &&
|
||||
!mainWindow.isDestroyed() &&
|
||||
!mainWindow.webContents.isDestroyed()
|
||||
) {
|
||||
mainWindow.webContents.send(
|
||||
ipcChannels.magicTodosStatusChanged
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
)
|
||||
assistantDatabase = startupAssistantDatabase
|
||||
const goodbuddyConfigService = new GoodBuddyConfigService(
|
||||
|
||||
@@ -5682,6 +5682,14 @@ export function registerIpcHandlers(
|
||||
}
|
||||
)
|
||||
|
||||
registerHandler(
|
||||
ipcChannels.magicTodosStatus,
|
||||
(event) => {
|
||||
assertTrustedSender(event, window)
|
||||
return assistantDatabase.getMagicTodoStatus()
|
||||
}
|
||||
)
|
||||
|
||||
registerHandler(
|
||||
ipcChannels.magicTodosUpdate,
|
||||
(event, input: unknown) => {
|
||||
|
||||
Reference in New Issue
Block a user