feat: add desktop notification toggle to general settings

Add a default-on persisted desktop notification switch that takes effect immediately for background task results while leaving in-app notifications unchanged. Group General settings into shortcut, conversation and notification, and workspace and download cards.

Validation: 756 related tests passed, 1 skipped; typecheck and lint passed. Full suite timed out with three supervision preview failures; native OS notification delivery was not manually verified.

Release note: 通用设置新增默认开启的桌面通知开关,可随时关闭系统任务提醒并保留应用内提示;设置项按用途分组,方便查找。
This commit is contained in:
mesalogo
2026-09-28 01:43:21 +08:00
parent 8e607366ca
commit f35198df01
14 changed files with 411 additions and 121 deletions
@@ -44,6 +44,34 @@ afterEach(async () => {
})
describe('ApplicationSettingsStore', () => {
it.each([11, 12])('defaults missing desktop notifications to on in version %s', async (version) => {
const { filePath, store } = await createStore()
const legacy: Record<string, unknown> = { ...defaultApplicationSettings, version, lastSeenReleaseNotesVersion: null, checkUpdatesOnStartup: false }
delete legacy.desktopNotificationsEnabled
await writeFile(filePath, JSON.stringify(legacy))
expect(await store.get()).toEqual({ ...defaultApplicationSettings, checkUpdatesOnStartup: false })
expect(applicationSettingsSchema.parse({ ...defaultApplicationSettings, desktopNotificationsEnabled: undefined }).desktopNotificationsEnabled).toBe(true)
})
it('persists and publishes desktop notification choices without resetting them on unrelated updates', async () => {
const { filePath, store } = await createStore()
expect((await store.get()).desktopNotificationsEnabled).toBe(true)
const changed = vi.fn()
store.onChanged(changed)
for (const desktopNotificationsEnabled of [false, true]) {
const saved = await store.update({ desktopNotificationsEnabled })
expect(saved.desktopNotificationsEnabled).toBe(desktopNotificationsEnabled)
expect(changed).toHaveBeenLastCalledWith(saved)
await store.update({ checkUpdatesOnStartup: false })
expect((await createApplicationSettingsStore(filePath).get()).desktopNotificationsEnabled).toBe(desktopNotificationsEnabled)
expect(JSON.parse(await readFile(filePath, 'utf8')).desktopNotificationsEnabled).toBe(desktopNotificationsEnabled)
}
expect(applicationSettingsUpdateSchema.parse({ checkUpdatesOnStartup: false })).toEqual({ checkUpdatesOnStartup: false })
for (const desktopNotificationsEnabled of ['false', 0, null]) {
await expect(store.update({ desktopNotificationsEnabled })).rejects.toThrow()
}
})
it('persists review pagination and batch controls without enabling supervision', async () => {
const { filePath, store } = await createStore()
const supervisionReview = { pageSize: 1, batchCharacters: 16000, batchMessages: 50, executionSeconds: 3600 }