diff --git a/UI-DESIGN.md b/UI-DESIGN.md index c84b588b..996b18e7 100644 --- a/UI-DESIGN.md +++ b/UI-DESIGN.md @@ -625,6 +625,7 @@ GoodBuddy 是可调整窗口大小的桌面应用。响应式设计优先保证 - “笔记 / 待办”属于同一工作台内的同级内容面板,使用 `PageTabs` 的 `segmented` 视觉变体,与模型设置的分段控件保持同一外观。 - 页签切换保留 `tablist`、`tab` 和 `tabpanel` 语义;待办状态仍使用独立的 `SegmentedControl`,不得与内容页签合并。 +- 笔记编辑器保留 Quill 原生列表快捷输入:输入 `-`、`*`、`1.`、`[ ]` 或 `[x]` 后按空格,分别转换为项目符号、编号或待办清单。快捷输入只生成现有 Delta 富文本,不引入 Markdown 源码模式、第二套持久化格式或第三方 Markdown 插件;编辑区附近持续提供简短提示。 - 左侧“魔法笔记”入口可显示未完成待办数量。数量为 0 时隐藏徽标,超过 99 时显示 `99+`,可访问名称仍说明精确数量;勾选、取消勾选以及 Agent / MCP 对笔记清单的写入都必须刷新数量。 - 未完成待办徽标的高度不得超过主导航图标;数量从 0 变为可见或再次隐藏时,主导航项行高和相邻菜单位置必须保持不变。 - 在待办面板勾选或取消勾选后,当前缓存中的源笔记正文必须立即同步对应清单状态,不得依赖离开工作区后重新加载。 diff --git a/src/renderer/src/MagicNoteEditor.test.tsx b/src/renderer/src/MagicNoteEditor.test.tsx index 42bd8928..a7a54758 100644 --- a/src/renderer/src/MagicNoteEditor.test.tsx +++ b/src/renderer/src/MagicNoteEditor.test.tsx @@ -3,6 +3,7 @@ import { fireEvent, render, screen, waitFor } from '@testing-library/react' import { readFileSync } from 'node:fs' import { join } from 'node:path' +import Quill from 'quill' import { describe, expect, it, vi } from 'vitest' import type { MagicNoteRichContent } from '../../shared/magic-notes-contracts' import { MagicNoteEditor } from './MagicNoteEditor' @@ -45,6 +46,46 @@ describe('MagicNoteEditor', () => { ).toBeInTheDocument() }) + it.each([ + ['-', 'bullet'], + ['*', 'bullet'], + ['1.', 'ordered'], + ['[ ]', 'unchecked'], + ['[x]', 'checked'] + ])( + 'keeps the native Quill %s list shortcut enabled', + async (marker, expectedList) => { + const onChange = vi.fn<(content: MagicNoteRichContent) => void>() + const { container } = render( + + ) + const editor = container.querySelector('.ql-editor') + const quillContainer = container.querySelector( + '.magic-note-editor__content' + ) + expect(editor).not.toBeNull() + expect(quillContainer).not.toBeNull() + + const quill = Quill.find(quillContainer!) as Quill + quill.setText(marker, 'user') + quill.setSelection(marker.length, 0, 'silent') + fireEvent.keyDown(editor!, { key: ' ' }) + + await waitFor(() => { + const content = onChange.mock.calls.at(-1)?.[0] + expect( + content?.ops.some( + (operation) => operation.attributes?.list === expectedList + ) + ).toBe(true) + }) + } + ) + it('intercepts a pasted image before Quill and inserts it once', async () => { const onChange = vi.fn<(content: MagicNoteRichContent) => void>() const { container } = render( diff --git a/src/renderer/src/i18n/locales/en-US/magicNotes.ts b/src/renderer/src/i18n/locales/en-US/magicNotes.ts index 25053f21..ac3b6b97 100644 --- a/src/renderer/src/i18n/locales/en-US/magicNotes.ts +++ b/src/renderer/src/i18n/locales/en-US/magicNotes.ts @@ -86,9 +86,10 @@ export const magicNotes = { emptySelectionDescription: 'Select a note on the left, or create a note to start writing.', newEntryLabel: 'New entry content', - composerImmediateHint: 'AI comments after you stop typing for 5 seconds', + composerImmediateHint: + 'Type -, 1., [ ], or [x] then Space to start a list; AI comments after 5 seconds of inactivity', composerRichTextHint: - 'Supports rich text and pasting or dropping local images, videos, and attachments', + 'Type -, 1., [ ], or [x] then Space to start a list; you can also paste or drop local files', emptyEntries: 'No entries yet. Write the first entry above.', editEntryLabel: 'Edit entry content', entryAt: '{{date}} entry' diff --git a/src/renderer/src/i18n/locales/zh-CN/magicNotes.ts b/src/renderer/src/i18n/locales/zh-CN/magicNotes.ts index 0a12dd20..76a836c3 100644 --- a/src/renderer/src/i18n/locales/zh-CN/magicNotes.ts +++ b/src/renderer/src/i18n/locales/zh-CN/magicNotes.ts @@ -80,8 +80,10 @@ export const magicNotes = { emptySelectionTitle: '还没有选择笔记', emptySelectionDescription: '从左侧选择笔记,或新建一篇笔记开始记录。', newEntryLabel: '新记录内容', - composerImmediateHint: '停止输入 5 秒后自动评论', - composerRichTextHint: '支持富文本,可粘贴或拖入本地图片、视频和附件', + composerImmediateHint: + '输入 -、1.、[ ] 或 [x] 后按空格可创建列表;停止输入 5 秒后自动评论', + composerRichTextHint: + '输入 -、1.、[ ] 或 [x] 后按空格可创建列表;也可粘贴或拖入本地文件', emptyEntries: '还没有记录,在上方写下第一条内容。', editEntryLabel: '编辑记录内容', entryAt: '{{date}} 的记录'