Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ target_link_libraries(nextnotes-storage PUBLIC Qt6::Core SQLite::SQLite3)
qt_add_executable(nextnotes src/main.cpp src/EditorSession.cpp src/EditorSessionWeb.cpp src/EditorSession.h src/NotesController.cpp src/NotesLibrary.cpp src/EditorExport.cpp src/PdfExport.cpp src/NotesOrganizer.cpp src/NotesKnowledge.cpp src/NotesController.h)
target_sources(nextnotes PRIVATE src/EditorRenderLifecycle.cpp src/EditorRenderLifecycle.h)
qt_add_qml_module(nextnotes URI NextNotes VERSION 1.0 RESOURCE_PREFIX /qt/qml
QML_FILES qml/NotesSelectionBox.qml qml/FolderIcons.js qml/PopupPlacement.js qml/NotesPopover.qml qml/NotesContentPopover.qml qml/NotesSettings.qml qml/LibraryActions.qml qml/NotesWindowControls.qml qml/KnowledgePanel.qml qml/RecycleBin.qml qml/Main.qml qml/NotesOrganizer.qml qml/SourceEditor.qml qml/EditorTools.qml qml/CommandRegistry.qml qml/NotesTokens.qml qml/NoteReadingView.qml)
QML_FILES qml/NotesSelectionBox.qml qml/FolderIcons.js qml/PopupPlacement.js qml/NotesPopover.qml qml/NotesContentPopover.qml qml/NotesSettings.qml qml/LibraryActions.qml qml/NotesWindowControls.qml qml/KnowledgePanel.qml qml/RecycleBin.qml qml/Main.qml qml/NoteNameEditor.qml qml/NotesOrganizer.qml qml/SourceEditor.qml qml/EditorTools.qml qml/CommandRegistry.qml qml/NotesTokens.qml qml/NoteReadingView.qml)
qt_add_resources(nextnotes window-controls PREFIX /nextnotes/platform BASE qml FILES qml/NativeWindowControls.qml)
qt_add_resources(nextnotes app-icon PREFIX /nextnotes/icons BASE packaging FILES packaging/org.nextks.notes.svg)
file(GLOB_RECURSE EDITOR_ASSETS CONFIGURE_DEPENDS web/editor/dist/* web/editor/vendor/*)
qt_add_resources(nextnotes editor-assets PREFIX /editor BASE web/editor FILES web/editor/index.html web/editor/editor.css ${EDITOR_ASSETS})
target_link_libraries(nextnotes PRIVATE nextnotes-storage Kos::Ui Kos::UiPlugin Qt6::Core Qt6::Gui Qt6::Qml Qt6::Quick Qt6::QuickControls2 Qt6::QuickDialogs2 Qt6::Svg Qt6::WebEngineCore Qt6::WebEngineQuick Qt6::WebChannel)
Expand Down
6 changes: 4 additions & 2 deletions docs/notes-interaction-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@

## 日常界面

- 顶部保留新建、撤销/重做、当前笔记操作、搜索和设置。
- 顶部左侧放新建和当前笔记操作,中间用一个公共按钮组统一承载撤销/重做、段落样式、粗体/斜体/删除线、插入、表格和更多编辑工具,右侧放搜索和设置;正文不再单独占用一行格式工具栏。编辑按钮组优先居中,空间不足时避开左右操作并支持横向滚动,键盘聚焦时跟随显示;格式状态并入底部状态栏。
- 侧栏分为“视图”和“文件夹”:视图包含全部笔记、收藏、最近删除及已保存的搜索筛选;文件夹包含“随手记”、初始化时添加的“默认文件夹”和用户创建的顶层文件夹;子文件夹放在对应笔记列表上方,通过返回上一级逐层导航。侧栏底部不显示新建文件夹,暂不增加“新建视图”入口;保存搜索仍从设置进入。
- “随手记”和“默认文件夹”都是仅初始化一次的普通文件夹,支持重命名、移动、删除和恢复,之后不自动补回。升级时将原收件箱的正常笔记一次性归入“随手记”,保留笔记 ID 并调整路径链接;有待恢复草稿或无法调整的链接时,整批保留原位并提示。在具体文件夹中新建归入当前文件夹;新建或导入未指定文件夹时显示为“未分类”,可在“全部笔记”中找到,不会隐式重建“随手记”。
- 笔记菜单包含置顶、收藏、移动、修改标题、笔记信息、分享与导出、创建副本和最近删除。分享与导出以二级菜单提供当前笔记的 PDF、Markdown、HTML 和打印。自动保存不再占用普通笔记菜单的首位。
- 正文左右各保留 48px 留白,笔记名称与正文左对齐;块操作按钮放在左侧留白内,与正文相隔 8px,并至少离开编辑区边界 12px。
- 正文上方提供独立的“笔记名称”输入框,按 Enter 或“保存名称”提交;新建笔记的名称默认为“未命名笔记”,正文为空。名称保存在 Markdown 元数据的 `title` 字段中,修改名称不改写正文标题,也不将名称列入正文大纲。正文标题仍通过格式工具或 Markdown 设置。
- 笔记菜单包含置顶、收藏、移动、修改笔记名称、笔记信息、分享与导出、创建副本和最近删除。分享与导出以二级菜单提供当前笔记的 PDF、Markdown、HTML 和打印。自动保存不再占用普通笔记菜单的首位。
- 列表右键菜单沿用邮件列表的定位:在鼠标点击位置弹出无箭头 LiquidPopover,只在接近窗口边缘时收进可见区域。笔记、子文件夹及最近删除列表使用同一规则;键盘打开笔记行菜单时以当前行中点作为位置,工具栏按钮仍就近弹出。
- 全部菜单与浮动表单采用统一触发规则:右键无箭头,按钮下方居中并指向按钮,后续菜单继承最初入口;空间不足时向上调整。完整范围和检查边界见 [菜单与浮动表单](popover-interactions.md)。
- 标签、关联和历史是当前笔记的信息,保留在“笔记信息”;模板管理从这套标签页中移出。
Expand Down
2 changes: 2 additions & 0 deletions docs/product-interaction-review.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# 笔记产品视角复查

2026-11-10 更新:笔记名称现使用正文上方的独立输入框,按 Enter 或“保存名称”提交;不再同步改写正文开头的一级标题。新建笔记使用 `title` 元数据和空正文。下文关于名称与一级标题同步的记录属于旧版行为。

2026-11-06。目标是让日常操作围绕记录、查找、归类、回看和输出内容;设置管理全局偏好与整个笔记空间。文件、原始路径和格式只在明确导入、导出、临时编辑外部文件时出现。

## 本轮发现与调整
Expand Down
4 changes: 2 additions & 2 deletions qml/EditorTools.qml
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ Item {
LiquidActionButton {
id: handle
visible: !!root.state.block && root.state.block.y >= 0 && root.state.block.y < root.height && root.editable
x: Math.max(0, root.state.block ? root.state.block.x - 28 : 0); y: Math.max(0, root.state.block ? root.state.block.y : 0)
x: Math.max(12, root.state.block ? root.state.block.x - width - 8 : 12); y: Math.max(0, root.state.block ? root.state.block.y : 0)
implicitWidth: 26; implicitHeight: 26; iconOnly: true; iconName: "more"; iconSize: 16
materialForm: true
Accessible.name: "块操作,可拖动块,或使用 Alt+Shift+方向键移动"
Expand Down Expand Up @@ -96,7 +96,7 @@ Item {
}
KosToolTip { target: handle; text: "拖动移动块,点击打开块操作" }
}
Rectangle { visible: root.dragging; x: 28; y: root.dragY; width: Math.max(0, root.width - root.outlineWidth - 52); height: 2; color: AppTheme.border }
Rectangle { visible: root.dragging; x: root.source.inset; y: root.dragY; width: Math.max(0, root.width - root.outlineWidth - root.source.inset * 2); height: 2; color: AppTheme.border }
Component {
id: outlineView
ColumnLayout {
Expand Down
38 changes: 1 addition & 37 deletions qml/FolderIcons.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,6 @@
.pragma library

// App-specific subjects extend the shared 24px outline icon vocabulary.
var paths = {
work: "M8 7V5a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2 M5 7h14a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2 M3 12a20 20 0 0 0 18 0 M12 11v4",
study: "M12 5v16 M12 5C9 3 5 3 2 4v15c4-1 7-1 10 2 3-3 6-3 10-2V4c-3-1-7-1-10 1",
sport: "M15 2a2 2 0 1 0 0 4 2 2 0 1 0 0-4 M5 10l4-3 4 2 3 4h4 M13 9l-3 5 4 3v5 M10 14l-3 5H3",
running: "M3 6h5l2 6 4 2 5 1a3 3 0 0 1 2 3v2H3z M3 17h18 M10 12l-2 2 M13 14l-2 2",
cycling: "M6 13a4 4 0 1 0 0 8 4 4 0 1 0 0-8 M18 13a4 4 0 1 0 0 8 4 4 0 1 0 0-8 M6 17l4-8 4 8H6 M10 9h7 M15 5h3l-1 4 1 8 M8 6h4",
swimming: "M18 7a2 2 0 1 0 0 4 2 2 0 1 0 0-4 M3 12l6-6 5 3-4 5 M3 16q2-2 4 0t4 0 4 0 4 0 M3 21q2-2 4 0t4 0 4 0 4 0",
fitness: "M5 6h3v12H5z M16 6h3v12h-3z M8 12h8 M2 9v6 M22 9v6 M2 12h3 M19 12h3",
basketball: "M12 3a9 9 0 1 0 0 18 9 9 0 1 0 0-18 M3 12h18 M12 3v18 M6 5c7 4 7 10 0 14 M18 5c-7 4-7 10 0 14",
football: "M12 3a9 9 0 1 0 0 18 9 9 0 1 0 0-18 M12 8l5 3-2 5H9l-2-5z M12 3v5 M17 11l4-2 M15 16l3 3 M9 16l-3 3 M7 11 3 9",
badminton: "M4 4l6 14 4-1L21 4z M9 4l3 13 M15 4l-2 13 M7 11h10 M10 18l1 3h3l1-4",
tennis: "M14 3c-4 0-7 3-7 7s2 6 5 6 7-4 7-8-2-5-5-5z M9 15l-6 6 M10 5l6 8 M7 9l6 7 M9 12l8-7",
shopping: "M5 7h14l2 14H3z M8 8V6a4 4 0 0 1 8 0v2",
travel: "M22 2 9 15 M22 2l-5 20-5-10L2 7z",
food: "M4 3v6a3 3 0 0 0 6 0V3 M7 3v18 M20 3c-4 3-5 7-5 10h5 M20 3v18",
coffee: "M3 8h14v8a4 4 0 0 1-4 4H7a4 4 0 0 1-4-4z M17 9h2a3 3 0 0 1 0 6h-2 M6 3v2 M10 2v3 M14 3v2",
health: "M9 3h6v6h6v6h-6v6H9v-6H3V9h6z",
finance: "M20 8V5H5a3 3 0 0 0 0 6h16v10H5a3 3 0 0 1-3-3V8 M21 13h-5v5h5 M17 15.5h.01",
gift: "M3 8h18v5H3z M5 13v8h14v-8 M12 8v13 M12 8H7a3 3 0 1 1 3-3z M12 8h5a3 3 0 1 0-3-3z",
pets: "M8 14c2-4 6-4 8 0l3 4c2 4-3 5-7 3-4 2-9 1-7-3z M7 5a2 3 0 1 0 4 0 2 3 0 1 0-4 0 M14 5a2 3 0 1 0 4 0 2 3 0 1 0-4 0 M2 10a2 2 0 1 0 4 0 2 2 0 1 0-4 0 M19 10a2 2 0 1 0 4 0 2 2 0 1 0-4 0",
garden: "M20 3C6 1 1 8 6 16c8 5 15 0 14-13 M3 21 15 9",
car: "M4 11l2-6h12l2 6 M3 11h18v8H3z M5 19v2 M19 19v2 M7 15h.01 M17 15h.01",
code: "M8 6 2 12l6 6 M16 6l6 6-6 6 M14 3l-4 18",
camera: "M8 6l2-3h4l2 3h4a2 2 0 0 1 2 2v11H2V8a2 2 0 0 1 2-2z M8 12a4 4 0 1 0 8 0 4 4 0 1 0-8 0",
ideas: "M8 16c0-3-3-4-3-8a7 7 0 0 1 14 0c0 4-3 5-3 8z M8 19h8 M10 22h4"
}

// Persisted category identifiers. Rendering and aliases belong to Kos.Icons.
var choices = [
{ name: "folder", label: "文件夹" }, { name: "home", label: "家庭" },
{ name: "work", label: "工作" }, { name: "study", label: "学习" },
Expand Down Expand Up @@ -55,12 +28,3 @@ var choices = [
{ name: "sliders", label: "调节" }, { name: "circle", label: "圆环" },
{ name: "waves", label: "波浪" }, { name: "info", label: "资料" }
]

function source(name, color) {
if (!paths[name]) return ""
var ink = "rgb(" + Math.round(color.r * 255) + "," + Math.round(color.g * 255) + "," + Math.round(color.b * 255) + ")"
return "data:image/svg+xml;utf8," + encodeURIComponent(
'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" stroke="'
+ ink + '" stroke-opacity="' + color.a + '" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" d="'
+ paths[name] + '"/></svg>')
}
Loading
Loading