mirror of
https://github.com/taskgenius/taskgenius-plugin.git
synced 2026-07-22 06:40:25 +00:00
chore: clean up documentation and refine onboarding UI
- Remove 25 outdated documentation files from completed refactoring efforts - Reorder placement options to prioritize inline mode in onboarding - Fix task item CSS class naming for consistency - Remove unused content area showcase from fluent components - Correct sideleaves configuration logic in placement step - Update onboarding component styles for better visual hierarchy These changes streamline the codebase by removing completed migration documentation and improve the onboarding experience with better defaults and cleaner UI presentation.
This commit is contained in:
parent
055ba03772
commit
962623b3e8
31 changed files with 37 additions and 6257 deletions
|
|
@ -1,172 +0,0 @@
|
|||
## 目标
|
||||
|
||||
- 在 Task 视图(src/pages/TaskView.ts)中,为每个任务的右键菜单新增“删除任务”按钮。
|
||||
- 当目标任务存在子任务时,弹出二次确认,允许选择“仅删除该任务”或“删除该任务及所有子任务”。
|
||||
- 完成后,数据流(Dataflow)中缓存/索引即时更新;WriteAPI 支持级联删除并发出明确的事件,Canvas 任务同样支持。
|
||||
|
||||
## 涉及范围
|
||||
|
||||
- UI:TaskView 右键菜单、用户确认弹窗
|
||||
- 应用层:调用 WriteAPI 的删除接口(新增 deleteChildren 支持)
|
||||
- Dataflow/事件:明确发出 TASK_DELETED(含批量删除信息),监听方执行增量删除更新
|
||||
- Markdown/Canvas 文件写入:单行删除与“子树”删除;Canvas 文本节点的删除逻辑
|
||||
- i18n:新增菜单与确认文案
|
||||
|
||||
## 交互与用户体验
|
||||
|
||||
- 右键菜单新增“删除任务”项:
|
||||
- 无子任务:点击后直接删除,删除成功后在 UI 中移除,toast/notice 简短提示
|
||||
- 有子任务:点击后弹确认对话框,内容包含:
|
||||
- 选项 A:仅删除该任务(保留子任务,子任务提升为同级或根据设计保留缩进,见“边界与策略”)
|
||||
- 选项 B:删除该任务及其所有子任务
|
||||
- 删除完成后,列表立即更新,无需刷新;如失败显示错误提示
|
||||
|
||||
建议文案(以 t(key) 引用):
|
||||
- t("Delete Task"),t("Delete"),t("Delete task only"),t("Delete task and all subtasks"),t("This task has N subtasks. How would you like to proceed?")
|
||||
|
||||
## 数据流与事件
|
||||
|
||||
- WriteAPI 删除成功后显式发出:
|
||||
- Events.TASK_DELETED,payload 建议:
|
||||
- taskId: string
|
||||
- filePath: string
|
||||
- deletedTaskIds: string[](若级联删除,包含所有被删节点;仅删除自己则数组长度为 1)
|
||||
- mode: "single" | "subtree"
|
||||
- 继续保留现有 WRITE_OPERATION_START/COMPLETE 事件(兼容已有 Orchestrator)
|
||||
- Dataflow 监听 TASK_DELETED,做增量更新:
|
||||
- 从任务缓存/索引移除对应 taskId 与其 descendants
|
||||
- 调整同文件中被删行下方任务的行号(如你的索引维护行号)
|
||||
- 发出 TASK_CACHE_UPDATED 或对应局部更新事件(当前架构已有 TASK_CACHE_UPDATED)
|
||||
|
||||
说明:现有 Events.ts 已定义 TASK_DELETED 常量,但 WriteAPI.deleteTask 尚未发出;此次补齐并优先级采用 TASK_DELETED 进行 UI 直达更新,减少“全量重扫”开销。
|
||||
|
||||
## WriteAPI 方案(Markdown + Canvas)
|
||||
|
||||
在 src/dataflow/api/WriteAPI.ts:
|
||||
|
||||
1) DeleteTaskArgs 增加 deleteChildren?: boolean
|
||||
- interface DeleteTaskArgs { taskId: string; deleteChildren?: boolean }
|
||||
|
||||
2) deleteTask(args) 行为扩展
|
||||
- 读取目标任务(getTaskById)
|
||||
- 分支:
|
||||
- Canvas 任务:调用 deleteCanvasTask,并新增支持级联删除的实现(见下)
|
||||
- Markdown 任务:
|
||||
- 无级联(默认):按现有逻辑,删除该行
|
||||
- 级联(deleteChildren=true):
|
||||
- 方式 A(优先):依赖任务索引拿到 descendants 列表,按行号聚合并自底向上批量删除
|
||||
- 方式 B(回退):基于 Markdown 缩进扫描“子树”范围(见算法)
|
||||
- 发出 WRITE_OPERATION_START → vault.modify → WRITE_OPERATION_COMPLETE
|
||||
- 新增:emit(Events.TASK_DELETED, { taskId, filePath, deletedTaskIds, mode })
|
||||
|
||||
3) CanvasTaskUpdater(src/parsers/canvas-task-updater.ts)
|
||||
- 现有 deleteCanvasTask 仅删除单条。扩展:
|
||||
- 解析文本节点后,按“子树”算法在纯文本中删除对应行和被嵌套的子任务行
|
||||
- 返回 updatedContent
|
||||
- WriteAPI.deleteTask 在 Canvas 分支拿到 descendants 时同样构造 deletedTaskIds 并 emit TASK_DELETED
|
||||
|
||||
### Markdown “子树”删除算法(回退策略)
|
||||
|
||||
- 读取文件并 split 为行数组
|
||||
- 定位父任务行 parentLine 与其前导空白长度 parentIndent(空格数/制表符长度)
|
||||
- 从 parentLine + 1 开始向下扫描,直到:
|
||||
- 遇到同级或上级的任务项(识别条件:以空白+[-*+] [ ] 或 [x] 开头,且当前行的前导空白长度 <= parentIndent),停止
|
||||
- 中间所有“子任务行”记录进删除列表(建议仅删除带复选框的“任务行”,不删除纯文本说明行,以避免误删注释;如需同时删除说明行,需与产品确认)
|
||||
- 删除集合 = {parentLine} ∪ {子任务行集合}
|
||||
- 自底向上 splice 删除,防止行号位移
|
||||
|
||||
注意:你们当前已有 insertSubtask 等方法,说明对缩进/父子关系已有约定,上述算法应与解析器保持一致。首选用索引的 descendants 做删除集合,回退才用缩进扫描。
|
||||
|
||||
## Task 索引/缓存配合
|
||||
|
||||
- 如果当前索引已维护 parent/children 关系,建议新增一个工具:
|
||||
- getDescendants(taskId): string[],返回所有后代 ID(含子、孙…)
|
||||
- Dataflow 监听 TASK_DELETED 后:
|
||||
- 从 Map/Index 移除 taskId 与这些 descendants
|
||||
- 如果仅删除父节点且保留子节点,需决定“提升子节点为同级”还是“保留缩进但无父”(推荐与产品/设计确定,见“边界与策略”)
|
||||
- 对于同文件更靠下的任务,若你们缓存了 line,执行行号偏移修正(根据删除的行数)
|
||||
|
||||
## UI 改动(src/pages/TaskView.ts)
|
||||
|
||||
在 handleTaskContextMenu 内新增一项:
|
||||
- “删除任务”菜单项
|
||||
- onClick:
|
||||
- 查索引判断是否存在子任务(优先索引;没有则可只弹一次确认“是否删除”,简单版)
|
||||
- 无子任务:直接调用 this.plugin.writeApi.deleteTask({ taskId: task.id })
|
||||
- 有子任务:弹窗:
|
||||
- 仅删除该任务:deleteChildren=false
|
||||
- 删除任务及所有子任务:deleteChildren=true
|
||||
- 删除成功后:可显式从本地列表移除项(或依赖 TASK_DELETED 事件驱动刷新)
|
||||
- 失败:显示 Notice 提示
|
||||
|
||||
确认弹窗可以使用 ConfirmModal.ts
|
||||
|
||||
## Canvas 支持
|
||||
|
||||
- CanvasTaskUpdater.deleteTaskFromTextNode 目前只处理单行任务删除,需扩展为支持“子树”:
|
||||
- 与 Markdown 回退算法类似,在 Canvas 文本节点的 Markdown 中计算子树范围
|
||||
- 修改 Canvas JSON 后写回
|
||||
- WriteAPI.deleteTask 对 Canvas 分支传递 deleteChildren 参数,并组装 deletedTaskIds(索引可提供 descendants;若无,则按文本子树扫描推导)
|
||||
|
||||
## i18n
|
||||
|
||||
新增 keys(示例):
|
||||
- "Delete Task", "Delete", "Delete task only", "Delete task and all subtasks", "This task has {n} subtasks. How would you like to proceed?", "Deleted", "Failed to delete task"
|
||||
|
||||
## 边界与策略待确认
|
||||
|
||||
- 仅删除父节点时子节点的处理策略:
|
||||
- 选项 1:子任务整体提升为父节点的同级(需要在 WriteAPI 中调整这些行的缩进,较复杂)
|
||||
- 选项 2:保留原缩进但无父(可能导致“悬空子任务”)
|
||||
- 选项 3:UI 层不提供“仅删除父节点”,统一为“删除父及所有子节点”以避免歧义(最简单)
|
||||
- 是否删除带说明的非任务行(不带复选框的列表项/文本):
|
||||
- 默认只删除“任务行”(有复选框)
|
||||
- 若确需一并删除说明行,需明确说明行的识别规则(例如直到下一个同级任务或空行)
|
||||
- FileSource 任务(metadata.source === "file-source")的删除语义:
|
||||
- 若支持删除,是否需要发出 FILE_TASK_REMOVED 之类事件(项目中已有 FILE_TASK_REMOVED 常量)
|
||||
- 撤销/回滚:依赖 Obsidian 本身文件级撤销还是需要插件内提供 Undo?(建议先依赖 Obsidian)
|
||||
|
||||
## 验收标准
|
||||
|
||||
- 右键菜单出现“删除任务”,符合 i18n
|
||||
- 无子任务:点击后文件内容更新、缓存更新、UI 移除该任务
|
||||
- 有子任务:
|
||||
- 仅删除父:父行被删、子任务处理符合策略(见上)
|
||||
- 删除父及所有子:对应行全部删除,deletedTaskIds 包含所有被删任务
|
||||
- Markdown/Canvas 两种来源都支持
|
||||
- 事件序列正确:
|
||||
- WRITE_OPERATION_START → 文件修改 → WRITE_OPERATION_COMPLETE
|
||||
- 以及 TASK_DELETED(包含 deletedTaskIds)
|
||||
- 删除后不出现“幽灵任务”(索引和 UI 无残留)
|
||||
- 无控制台报错,异常可见错误提示
|
||||
|
||||
## 分工与实施清单(按文件)
|
||||
|
||||
1) src/pages/TaskView.ts
|
||||
- 在 handleTaskContextMenu 添加“删除任务”菜单项
|
||||
- 新增 confirmAndDeleteTask(task):
|
||||
- 读取 descendants 数(索引或简单判断)
|
||||
- 显示确认对话框(存在子任务时)
|
||||
- 调用 this.plugin.writeApi.deleteTask({ taskId: task.id, deleteChildren })
|
||||
- 成功后依赖 TASK_DELETED 刷新或局部移除
|
||||
|
||||
2) src/dataflow/api/WriteAPI.ts
|
||||
- 扩展 DeleteTaskArgs:deleteChildren?: boolean
|
||||
- deleteTask:
|
||||
- 读取任务,分 Canvas/Markdown
|
||||
- Markdown:
|
||||
- deleteChildren=true 时按索引 descendants 或缩进扫描删除集合;自底向上删除
|
||||
- Canvas:调用扩展后的 deleteCanvasTask,支持子树
|
||||
- 发出 WRITE_OPERATION_START/COMPLETE 和 TASK_DELETED(带 deletedTaskIds)
|
||||
- 如需,针对 file-source 任务发 FILE_TASK_REMOVED
|
||||
|
||||
3) src/parsers/canvas-task-updater.ts
|
||||
- 扩展 deleteCanvasTask 支持 deleteChildren 或新增 deleteCanvasTaskSubtree
|
||||
- 在文本节点里按缩进/层级识别子树并删除
|
||||
|
||||
4) Dataflow 监听与缓存
|
||||
- 监听 TASK_DELETED,移除缓存中任务及 descendants,修正行号偏移,最后 emit TASK_CACHE_UPDATED
|
||||
- 若当前已有 Orchestrator 依赖 WRITE_OPERATION_COMPLETE 触发全量更新,可在过渡期两者都保留
|
||||
|
||||
5) i18n
|
||||
- 增加相关键(中英)
|
||||
|
|
@ -1,220 +0,0 @@
|
|||
# Canvas Task API Guide
|
||||
|
||||
## Overview
|
||||
|
||||
The WriteAPI now provides comprehensive support for Canvas tasks, allowing you to create, update, delete, and manipulate tasks within Obsidian Canvas files (.canvas).
|
||||
|
||||
## Architecture
|
||||
|
||||
Canvas task support is implemented through:
|
||||
- **CanvasTaskUpdater**: Core utility class handling Canvas-specific operations
|
||||
- **WriteAPI Integration**: Automatic detection and routing of Canvas tasks
|
||||
- **Event System**: Proper event emission for dataflow updates
|
||||
|
||||
## API Methods
|
||||
|
||||
### Automatic Detection
|
||||
|
||||
The following methods automatically detect Canvas tasks and route them appropriately:
|
||||
|
||||
```typescript
|
||||
// These methods work for both regular and Canvas tasks
|
||||
writeAPI.updateTask(args)
|
||||
writeAPI.deleteTask(args)
|
||||
writeAPI.updateTaskStatus(args)
|
||||
```
|
||||
|
||||
### Canvas-Specific Methods
|
||||
|
||||
#### Update Canvas Task
|
||||
```typescript
|
||||
await writeAPI.updateCanvasTask({
|
||||
taskId: "task-123",
|
||||
updates: {
|
||||
content: "Updated task content",
|
||||
completed: true,
|
||||
metadata: {
|
||||
priority: 3,
|
||||
dueDate: new Date().getTime()
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
#### Delete Canvas Task
|
||||
```typescript
|
||||
await writeAPI.deleteCanvasTask({
|
||||
taskId: "task-123"
|
||||
})
|
||||
```
|
||||
|
||||
#### Move Canvas Task
|
||||
```typescript
|
||||
await writeAPI.moveCanvasTask({
|
||||
taskId: "task-123",
|
||||
targetFilePath: "another-canvas.canvas",
|
||||
targetNodeId: "node-456", // Optional: specific node
|
||||
targetSection: "## Tasks" // Optional: section within node
|
||||
})
|
||||
```
|
||||
|
||||
#### Duplicate Canvas Task
|
||||
```typescript
|
||||
await writeAPI.duplicateCanvasTask({
|
||||
taskId: "task-123",
|
||||
targetFilePath: "target.canvas", // Optional: defaults to same file
|
||||
targetNodeId: "node-789", // Optional: specific node
|
||||
targetSection: "## Duplicates", // Optional: section within node
|
||||
preserveMetadata: false // Optional: whether to keep completion data
|
||||
})
|
||||
```
|
||||
|
||||
#### Add Task to Canvas Node
|
||||
```typescript
|
||||
await writeAPI.addTaskToCanvasNode({
|
||||
filePath: "my-canvas.canvas",
|
||||
content: "New task content",
|
||||
targetNodeId: "node-123", // Optional: creates new node if not specified
|
||||
targetSection: "## New Tasks", // Optional: section within node
|
||||
completed: false,
|
||||
metadata: {
|
||||
project: "MyProject",
|
||||
priority: 2,
|
||||
tags: ["important", "review"]
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### Utility Methods
|
||||
|
||||
#### Check if Task is Canvas Task
|
||||
```typescript
|
||||
const isCanvas = writeAPI.isCanvasTask(task);
|
||||
```
|
||||
|
||||
#### Get Canvas Task Updater Instance
|
||||
```typescript
|
||||
const canvasUpdater = writeAPI.getCanvasTaskUpdater();
|
||||
// Use for advanced Canvas operations
|
||||
```
|
||||
|
||||
## Task Detection
|
||||
|
||||
Canvas tasks are identified by:
|
||||
- File extension: `.canvas`
|
||||
- Metadata property: `sourceType === "canvas"`
|
||||
- Canvas node ID: `metadata.canvasNodeId`
|
||||
|
||||
## Event Flow
|
||||
|
||||
When Canvas tasks are updated:
|
||||
1. WriteAPI detects Canvas task type
|
||||
2. Routes to CanvasTaskUpdater
|
||||
3. Updates Canvas JSON structure
|
||||
4. Emits `WRITE_OPERATION_START` event
|
||||
5. Writes to vault
|
||||
6. Emits `TASK_UPDATED` event for dataflow
|
||||
7. Emits `WRITE_OPERATION_COMPLETE` event
|
||||
|
||||
## Error Handling
|
||||
|
||||
All Canvas operations return a result object:
|
||||
|
||||
```typescript
|
||||
interface Result {
|
||||
success: boolean;
|
||||
error?: string;
|
||||
task?: Task; // For update operations
|
||||
updatedContent?: string; // For debugging
|
||||
}
|
||||
```
|
||||
|
||||
Example error handling:
|
||||
```typescript
|
||||
const result = await writeAPI.updateCanvasTask({
|
||||
taskId: "task-123",
|
||||
updates: { completed: true }
|
||||
});
|
||||
|
||||
if (!result.success) {
|
||||
console.error("Failed to update Canvas task:", result.error);
|
||||
// Handle error appropriately
|
||||
}
|
||||
```
|
||||
|
||||
## Canvas Task Metadata
|
||||
|
||||
Canvas tasks include special metadata:
|
||||
|
||||
```typescript
|
||||
interface CanvasTaskMetadata extends StandardTaskMetadata {
|
||||
sourceType: "canvas";
|
||||
canvasNodeId: string; // ID of the Canvas text node
|
||||
canvasNodeX?: number; // Node position
|
||||
canvasNodeY?: number;
|
||||
canvasNodeWidth?: number; // Node dimensions
|
||||
canvasNodeHeight?: number;
|
||||
}
|
||||
```
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### Task Matching
|
||||
Canvas tasks are matched within nodes using:
|
||||
1. Original markdown content
|
||||
2. Core content extraction (removing metadata)
|
||||
3. Line-by-line comparison
|
||||
|
||||
### Metadata Preservation
|
||||
When updating Canvas tasks, the system:
|
||||
- Preserves task indentation
|
||||
- Maintains metadata format preferences (emoji vs dataview)
|
||||
- Handles project/context tags correctly
|
||||
- Updates completion dates automatically
|
||||
|
||||
### Node Management
|
||||
- New nodes are automatically positioned to avoid overlaps
|
||||
- Empty nodes are handled gracefully
|
||||
- Multi-task nodes are supported
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Always check task type** before performing Canvas-specific operations
|
||||
2. **Use automatic detection** when possible (updateTask, deleteTask, updateTaskStatus)
|
||||
3. **Handle errors gracefully** - Canvas operations can fail due to JSON parsing or node issues
|
||||
4. **Emit proper events** to ensure dataflow stays synchronized
|
||||
5. **Preserve metadata format** according to user preferences
|
||||
|
||||
## Migration from TaskManager
|
||||
|
||||
If migrating from the old TaskManager system:
|
||||
|
||||
| TaskManager Method | WriteAPI Equivalent |
|
||||
|-------------------|-------------------|
|
||||
| `canvasTaskUpdater.updateCanvasTask()` | `writeAPI.updateCanvasTask()` |
|
||||
| `canvasTaskUpdater.deleteCanvasTask()` | `writeAPI.deleteCanvasTask()` |
|
||||
| `canvasTaskUpdater.moveCanvasTask()` | `writeAPI.moveCanvasTask()` |
|
||||
| `canvasTaskUpdater.duplicateCanvasTask()` | `writeAPI.duplicateCanvasTask()` |
|
||||
| Direct CanvasTaskUpdater usage | `writeAPI.getCanvasTaskUpdater()` |
|
||||
|
||||
## Testing
|
||||
|
||||
Canvas task operations are tested in:
|
||||
- `/src/__tests__/CanvasTaskUpdater.test.ts`
|
||||
- `/src/__tests__/CanvasIntegration.test.ts`
|
||||
- `/src/__tests__/CanvasTaskMatching.integration.test.ts`
|
||||
|
||||
## Limitations
|
||||
|
||||
- Canvas files must be valid JSON
|
||||
- Node IDs must be unique within a Canvas
|
||||
- Task line matching may fail if content is heavily modified outside the system
|
||||
- Bulk operations on Canvas tasks may be slower than regular tasks due to JSON parsing
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
Potential improvements:
|
||||
- Batch Canvas operations for better performance
|
||||
- Canvas-specific query methods in QueryAPI
|
||||
- Visual task positioning helpers
|
||||
- Canvas template support
|
||||
|
|
@ -1,568 +0,0 @@
|
|||
# src/components 目录重构与迁移方案(最终执行版)
|
||||
|
||||
本方案用于将当前过于分散且命名不一致的前端 UI 组件进行系统性重构,目标是:
|
||||
- 建立“共享 UI 库(ui/)+ 业务功能模块(features/)”的稳定结构
|
||||
- 统一命名规则,便于检索、复用与增量演进
|
||||
- 分阶段稳妥迁移,保证任意阶段都可编译运行
|
||||
|
||||
不在本次范围:API/数据流重构、视觉设计改造、依赖升级。
|
||||
|
||||
---
|
||||
|
||||
## 1. 目标目录结构(提案)
|
||||
|
||||
- src/components/
|
||||
- ui/(共享可复用的通用组件与行为)
|
||||
- modals/
|
||||
- popovers/
|
||||
- menus/
|
||||
- inputs/
|
||||
- date-picker/
|
||||
- renderers/
|
||||
- feedback/
|
||||
- behavior/
|
||||
- widgets/
|
||||
- suggest/
|
||||
- tree/
|
||||
- features/(按业务域分组)
|
||||
- calendar/(algorithm、rendering、views)
|
||||
- gantt/
|
||||
- kanban/
|
||||
- quadrant/
|
||||
- habit/
|
||||
- onboarding/
|
||||
- quick-capture/
|
||||
- workflow/
|
||||
- settings/
|
||||
- tabs/
|
||||
- components/
|
||||
- core/
|
||||
- task/
|
||||
- edit/
|
||||
- view/
|
||||
- filter/
|
||||
- timeline-sidebar/
|
||||
- read-mode/
|
||||
- table/
|
||||
- on-completion/
|
||||
|
||||
说明:每个二级/三级目录都添加 index.ts 作为 barrel 出口(统一导出)。
|
||||
|
||||
---
|
||||
|
||||
## 2. 命名规则
|
||||
|
||||
- 目录:kebab-case(如 on-completion、habit-card)
|
||||
- 文件:导出“类/组件”的文件使用 PascalCase(ConfirmModal.ts、TaskList.ts)
|
||||
- 后缀统一:Modal/Popover/Dialog/View/Component/Renderer/Manager/Service/Widget/Suggest/Tab
|
||||
- 设置页签统一为 XxxxSettingsTab.ts(注意复数 Settings)
|
||||
- 文件名与主要导出保持一致
|
||||
|
||||
---
|
||||
|
||||
## 3. 分阶段迁移计划
|
||||
|
||||
建议每阶段单独提交一次,采用 git mv 保留历史;阶段结束进行编译与关键 UI 冒烟检查。
|
||||
|
||||
### Phase 0:准备
|
||||
- 决定目录命名统一为 kebab-case
|
||||
- (可选)是否引入路径别名,如:
|
||||
- @ui/* -> src/components/ui/*
|
||||
- @features/* -> src/components/features/*
|
||||
|
||||
### Phase 1:抽取共享 UI(ui/)
|
||||
- 新建:src/components/ui/{modals,popovers,menus,inputs,date-picker,renderers,feedback,behavior,widgets,suggest,tree}
|
||||
- 移动与重命名(示例):
|
||||
- AutoComplete.ts → ui/inputs/AutoComplete.ts
|
||||
- ConfirmModal.ts → ui/modals/ConfirmModal.ts
|
||||
- IframeModal.ts → ui/modals/IframeModal.ts
|
||||
- IconMenu.ts → ui/menus/IconMenu.ts
|
||||
- MarkdownRenderer.ts → ui/renderers/MarkdownRenderer.ts
|
||||
- StatusComponent.ts → ui/feedback/StatusIndicator.ts(建议改名更贴近语义)
|
||||
- DragManager.ts → ui/behavior/DragManager.ts
|
||||
- ViewComponentManager.ts → ui/behavior/ViewComponentManager.ts
|
||||
- date-picker/ → ui/date-picker/
|
||||
- common/TreeComponent.ts → ui/tree/TreeComponent.ts
|
||||
- common/TreeItemRenderer.ts → ui/tree/TreeItemRenderer.ts
|
||||
- suggest/ → ui/suggest/
|
||||
- 为 ui/ 及其子目录添加 index.ts 出口
|
||||
- 过渡策略:
|
||||
- 方案 A:一次性修正所有 import 到新路径
|
||||
- 方案 B:原位置保留同名文件,仅 re-export 新路径(逐步替换后再删除)
|
||||
|
||||
### Phase 2:合并业务功能模块(features/)
|
||||
- 新建:src/components/features/
|
||||
- 迁移(示例):
|
||||
- calendar/ → features/calendar/(algorithm.ts、rendering/、views/ 原样保留)
|
||||
- gantt/ → features/gantt/
|
||||
- kanban/ → features/kanban/
|
||||
- quadrant/ → features/quadrant/
|
||||
- onboarding/ → features/onboarding/
|
||||
- timeline-sidebar/ → features/timeline-sidebar/
|
||||
- readModeProgressbarWidget.ts → features/read-mode/ReadModeProgressBarWidget.ts(规范大小写与单词分割)
|
||||
- readModeTextMark.ts → features/read-mode/ReadModeTextMark.ts
|
||||
- habit/ → features/habit/
|
||||
- habit/habitcard/ → features/habit/components/habit-card/
|
||||
- HabitEditDialog.ts → features/habit/components/HabitEditDialog.ts
|
||||
- RewardModal.ts → (二选一)
|
||||
- A. features/habit/modals/RewardModal.ts
|
||||
- B. features/reward/modals/RewardModal.ts(与 RewardSettingsTab 形成一组)
|
||||
- quick-capture/
|
||||
- MinimalQuickCaptureModal.ts → features/quick-capture/modals/MinimalQuickCaptureModal.ts
|
||||
- QuickCaptureModal.ts → features/quick-capture/modals/QuickCaptureModal.ts
|
||||
- MinimalQuickCaptureSuggest.ts → features/quick-capture/suggest/MinimalQuickCaptureSuggest.ts(或 MinimalQuickCaptureSuggester.ts)
|
||||
- workflow/
|
||||
- QuickWorkflowModal.ts → features/workflow/modals/QuickWorkflowModal.ts
|
||||
- StageEditModal.ts → features/workflow/modals/StageEditModal.ts
|
||||
- WorkflowDefinitionModal.ts → features/workflow/modals/WorkflowDefinitionModal.ts
|
||||
- WorkflowProgressIndicator.ts → (二选一)
|
||||
- A. features/workflow/widgets/WorkflowProgressIndicator.ts
|
||||
- B. ui/widgets/WorkflowProgressIndicator.ts(视作通用)
|
||||
- task/
|
||||
- task-edit/ → features/task/edit/
|
||||
- task-view/ → features/task/view/
|
||||
- task-filter/ → features/task/filter/
|
||||
- inview-filter/ → features/task/filter/in-view/(或保留为 features/in-view-filter/)
|
||||
- table/ → features/table/
|
||||
- onCompletion/ → features/on-completion/
|
||||
- 为 features/* 添加 index.ts 出口
|
||||
|
||||
### Phase 3:标准化设置(settings/)
|
||||
- settings/ → features/settings/
|
||||
- tabs/:将所有 *SettingsTab.ts 移至此处并统一命名(保持 *SettingsTab)
|
||||
- TaskTimerSettingTab.ts → TaskTimerSettingsTab.ts(修正为复数 Settings)
|
||||
- components/:
|
||||
- FileSourceSettings.ts → components/FileSourceSettingsSection.ts(增加 Section 后缀更贴合)
|
||||
- SettingsSearchComponent.ts → components/SettingsSearchComponent.ts
|
||||
- core/:
|
||||
- SettingsIndexer.ts → core/SettingsIndexer.ts
|
||||
- 更新 features/settings/index.ts,统一导出 tabs/components/core
|
||||
|
||||
### Phase 4:统一导入与过渡清理
|
||||
- 在 ui/ 与各 features/* 目录添加 index.ts(barrel 模式)
|
||||
- 采用路径别名或相对路径统一 import:
|
||||
- import { ConfirmModal } from '@ui/modals'
|
||||
- import { TaskList } from '@features/task/view'
|
||||
- 若采用过渡 re-export:
|
||||
- 原路径文件仅保留:export * from '新路径'
|
||||
- 扫描替换存量 import 后,最终删除过渡文件
|
||||
|
||||
### Phase 5:收尾
|
||||
- 删除所有过渡 re-export 文件
|
||||
- 搜索并清理旧路径残留引用
|
||||
- 全量构建 + 核心 UI 冒烟
|
||||
|
||||
---
|
||||
|
||||
## 4. 详细映射清单(代表性)
|
||||
|
||||
- 顶层散落组件 → ui/ 或特性模块
|
||||
- AutoComplete.ts → ui/inputs/AutoComplete.ts
|
||||
- ConfirmModal.ts → ui/modals/ConfirmModal.ts
|
||||
- IframeModal.ts → ui/modals/IframeModal.ts
|
||||
- IconMenu.ts → ui/menus/IconMenu.ts
|
||||
- MarkdownRenderer.ts → ui/renderers/MarkdownRenderer.ts
|
||||
- StatusComponent.ts → ui/feedback/StatusIndicator.ts
|
||||
- DragManager.ts → ui/behavior/DragManager.ts
|
||||
- ViewComponentManager.ts → ui/behavior/ViewComponentManager.ts
|
||||
- ViewConfigModal.ts → features/task/view/modals/ViewConfigModal.ts
|
||||
- QuickWorkflowModal.ts → features/workflow/modals/QuickWorkflowModal.ts
|
||||
- WorkflowProgressIndicator.ts → features/workflow/widgets/WorkflowProgressIndicator.ts(或 ui/widgets/…)
|
||||
- readModeProgressbarWidget.ts → features/read-mode/ReadModeProgressBarWidget.ts
|
||||
- readModeTextMark.ts → features/read-mode/ReadModeTextMark.ts
|
||||
|
||||
- 目录整体迁移
|
||||
- calendar → features/calendar(algorithm.ts、rendering/、views/)
|
||||
- date-picker → ui/date-picker
|
||||
- suggest → ui/suggest
|
||||
- common/Tree* → ui/tree
|
||||
- gantt/、kanban/、quadrant/、onboarding/ → 对应 features/*
|
||||
- task-edit/、task-filter/、task-view/ → features/task 下分 edit/filter/view
|
||||
- inview-filter/ → features/task/filter/in-view(或 features/in-view-filter)
|
||||
- onboarding/、timeline-sidebar/、table/、onCompletion/ → 对应 features/*
|
||||
- habit/ + habitcard/ + HabitEditDialog.ts + RewardModal.ts → 归入 features/habit(或 RewardModal 放 features/reward)
|
||||
|
||||
- settings 专项
|
||||
- 全部 *SettingsTab.ts → features/settings/tabs/
|
||||
- FileSourceSettings.ts → features/settings/components/FileSourceSettingsSection.ts
|
||||
- SettingsIndexer.ts → features/settings/core/SettingsIndexer.ts
|
||||
- SettingsSearchComponent.ts → features/settings/components/SettingsSearchComponent.ts
|
||||
|
||||
---
|
||||
|
||||
## 5. 过渡 re-export 示例(可选策略 B)
|
||||
|
||||
- 原文件 src/components/ConfirmModal.ts(仅保留):
|
||||
|
||||
```ts
|
||||
export * from './ui/modals/ConfirmModal'
|
||||
```
|
||||
|
||||
- 原目录 src/components/suggest/index.ts(仅保留):
|
||||
|
||||
```ts
|
||||
export * from '../ui/suggest'
|
||||
```
|
||||
|
||||
后续逐步把业务代码的 import 改为新路径,再删除这些过渡文件。
|
||||
|
||||
---
|
||||
|
||||
## 6. (可选)路径别名建议
|
||||
|
||||
- 若采用 tsconfig 路径:
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@ui/*": ["src/components/ui/*"],
|
||||
"@features/*": ["src/components/features/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- import 示例:
|
||||
|
||||
```ts
|
||||
import { ConfirmModal } from '@ui/modals'
|
||||
import { TaskList } from '@features/task/view'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 验证清单
|
||||
|
||||
- 每阶段完成后:
|
||||
- 构建通过,无 TS 路径错误
|
||||
- 搜索旧路径是否仍有引用
|
||||
- 核心 UI(如任务视图、设置页、日历)打开不报错
|
||||
- 最终阶段:清除过渡 re-export,所有 import 指向新结构
|
||||
|
||||
---
|
||||
|
||||
## 8. 未决项(待确认)
|
||||
|
||||
- inview-filter:
|
||||
- A. 收敛到 features/task/filter/in-view/
|
||||
- B. 独立 features/in-view-filter/
|
||||
- RewardModal:
|
||||
- A. 放 features/habit/
|
||||
- B. 放 features/reward/(与 RewardSettingsTab 配对)
|
||||
- WorkflowProgressIndicator:
|
||||
- A. 放 features/workflow/widgets/
|
||||
- B. 放 ui/widgets/(若确认为通用)
|
||||
- 是否启用 @ui / @features 路径别名
|
||||
|
||||
---
|
||||
|
||||
## 9. 执行建议
|
||||
|
||||
- 使用 git mv,按阶段提交,commit message 清晰指明范围
|
||||
- 优先迁移“共享 UI”,减少后续重复
|
||||
- 大范围修改 import 前,优先采用过渡 re-export,降低一次性影响
|
||||
- 阶段结束进行构建与冒烟,确保安全可回滚
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 10. 详细执行步骤(可直接复制运行)
|
||||
|
||||
以下步骤假设你在仓库根目录执行,使用 git mv 确保历史保留。若路径别名未启用,请保持相对路径;若启用,请在 Phase 4 统一替换 import。
|
||||
|
||||
### Phase 1:抽取共享 UI(ui/)
|
||||
|
||||
1) 创建目录
|
||||
|
||||
```bash
|
||||
mkdir -p src/components/ui/{modals,popovers,menus,inputs,date-picker,renderers,feedback,behavior,widgets,suggest,tree}
|
||||
```
|
||||
|
||||
2) 移动文件(命令清单)
|
||||
|
||||
```bash
|
||||
# 顶层散落文件 → ui
|
||||
|
||||
git mv src/components/AutoComplete.ts src/components/ui/inputs/AutoComplete.ts
|
||||
|
||||
git mv src/components/ConfirmModal.ts src/components/ui/modals/ConfirmModal.ts
|
||||
|
||||
git mv src/components/IframeModal.ts src/components/ui/modals/IframeModal.ts
|
||||
|
||||
git mv src/components/IconMenu.ts src/components/ui/menus/IconMenu.ts
|
||||
|
||||
git mv src/components/MarkdownRenderer.ts src/components/ui/renderers/MarkdownRenderer.ts
|
||||
|
||||
git mv src/components/DragManager.ts src/components/ui/behavior/DragManager.ts
|
||||
|
||||
git mv src/components/ViewComponentManager.ts src/components/ui/behavior/ViewComponentManager.ts
|
||||
|
||||
# 状态指示重命名(建议)
|
||||
# 如需保留原名,可跳过,后续统一改名
|
||||
# 方案 A:直接重命名
|
||||
|
||||
git mv src/components/StatusComponent.ts src/components/ui/feedback/StatusIndicator.ts
|
||||
|
||||
# Date Picker 整体
|
||||
|
||||
git mv src/components/date-picker src/components/ui/date-picker
|
||||
|
||||
# Tree 相关
|
||||
mkdir -p src/components/ui/tree
|
||||
|
||||
git mv src/components/common/TreeComponent.ts src/components/ui/tree/TreeComponent.ts
|
||||
|
||||
git mv src/components/common/TreeItemRenderer.ts src/components/ui/tree/TreeItemRenderer.ts
|
||||
|
||||
# Suggest 整体
|
||||
|
||||
git mv src/components/suggest src/components/ui/suggest
|
||||
```
|
||||
|
||||
3) (可选)在旧位置添加过渡 re-export(若暂不批量改 import)
|
||||
|
||||
```bash
|
||||
# 示例:创建 src/components/ConfirmModal.ts 并仅导出新路径(如果前一步已移动,可新建同名文件)
|
||||
# echo "export * from './ui/modals/ConfirmModal'" > src/components/ConfirmModal.ts
|
||||
# 其他类似文件按需添加
|
||||
```
|
||||
|
||||
4) 添加 barrel 出口(index.ts)
|
||||
|
||||
```bash
|
||||
# 示例:为 ui/ 及子目录创建 index.ts(根据实际导出补充)
|
||||
# echo "export * from './modals'" > src/components/ui/index.ts
|
||||
# echo "export * from './ConfirmModal'" > src/components/ui/modals/index.ts
|
||||
```
|
||||
|
||||
提交:
|
||||
|
||||
```bash
|
||||
git add -A
|
||||
git commit -m "refactor(components): extract shared UI into src/components/ui/* (phase 1)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Phase 2:合并业务功能模块(features/)
|
||||
|
||||
1) 创建目录
|
||||
|
||||
```bash
|
||||
mkdir -p src/components/features/{calendar,gantt,kanban,quadrant,habit,onboarding,quick-capture,workflow,settings,task/{edit,view,filter},timeline-sidebar,read-mode,table,on-completion}
|
||||
```
|
||||
|
||||
2) 迁移与重命名(命令清单)
|
||||
|
||||
```bash
|
||||
# Calendar
|
||||
|
||||
git mv src/components/calendar src/components/features/calendar
|
||||
|
||||
# Gantt / Kanban / Quadrant / Onboarding
|
||||
|
||||
git mv src/components/gantt src/components/features/gantt
|
||||
|
||||
git mv src/components/kanban src/components/features/kanban
|
||||
|
||||
git mv src/components/quadrant src/components/features/quadrant
|
||||
|
||||
git mv src/components/onboarding src/components/features/onboarding
|
||||
|
||||
# Timeline Sidebar
|
||||
|
||||
git mv src/components/timeline-sidebar src/components/features/timeline-sidebar
|
||||
|
||||
# Read Mode(并统一大小写)
|
||||
mkdir -p src/components/features/read-mode
|
||||
|
||||
git mv src/components/readModeProgressbarWidget.ts src/components/features/read-mode/ReadModeProgressBarWidget.ts
|
||||
|
||||
git mv src/components/readModeTextMark.ts src/components/features/read-mode/ReadModeTextMark.ts
|
||||
|
||||
# Habit
|
||||
|
||||
git mv src/components/habit src/components/features/habit
|
||||
mkdir -p src/components/features/habit/components/habit-card
|
||||
|
||||
git mv src/components/habit/habitcard src/components/features/habit/components/habit-card
|
||||
|
||||
git mv src/components/HabitEditDialog.ts src/components/features/habit/components/HabitEditDialog.ts
|
||||
|
||||
# Reward(依你选择,若归入 habit 则移动到 habit 下)
|
||||
# git mv src/components/RewardModal.ts src/components/features/habit/modals/RewardModal.ts
|
||||
# 或:
|
||||
# mkdir -p src/components/features/reward/modals
|
||||
# git mv src/components/RewardModal.ts src/components/features/reward/modals/RewardModal.ts
|
||||
|
||||
# Quick Capture
|
||||
mkdir -p src/components/features/quick-capture/{modals,suggest}
|
||||
|
||||
git mv src/components/MinimalQuickCaptureModal.ts src/components/features/quick-capture/modals/MinimalQuickCaptureModal.ts
|
||||
|
||||
git mv src/components/QuickCaptureModal.ts src/components/features/quick-capture/modals/QuickCaptureModal.ts
|
||||
|
||||
git mv src/components/MinimalQuickCaptureSuggest.ts src/components/features/quick-capture/suggest/MinimalQuickCaptureSuggest.ts
|
||||
|
||||
# Workflow
|
||||
mkdir -p src/components/features/workflow/{modals,widgets}
|
||||
|
||||
git mv src/components/QuickWorkflowModal.ts src/components/features/workflow/modals/QuickWorkflowModal.ts
|
||||
|
||||
git mv src/components/StageEditModal.ts src/components/features/workflow/modals/StageEditModal.ts
|
||||
|
||||
git mv src/components/WorkflowDefinitionModal.ts src/components/features/workflow/modals/WorkflowDefinitionModal.ts
|
||||
|
||||
git mv src/components/WorkflowProgressIndicator.ts src/components/features/workflow/widgets/WorkflowProgressIndicator.ts
|
||||
|
||||
# Task(edit/view/filter)
|
||||
mkdir -p src/components/features/task/{edit,view,filter}
|
||||
|
||||
git mv src/components/task-edit src/components/features/task/edit
|
||||
|
||||
git mv src/components/task-view src/components/features/task/view
|
||||
|
||||
git mv src/components/task-filter src/components/features/task/filter
|
||||
|
||||
# In-view Filter(两种放置方式其一)
|
||||
# 方案 A:
|
||||
mkdir -p src/components/features/task/filter/in-view
|
||||
|
||||
git mv src/components/inview-filter src/components/features/task/filter/in-view
|
||||
# 方案 B:
|
||||
# mkdir -p src/components/features/in-view-filter
|
||||
# git mv src/components/inview-filter src/components/features/in-view-filter
|
||||
|
||||
# Table
|
||||
|
||||
git mv src/components/table src/components/features/table
|
||||
|
||||
# On Completion(目录名统一为 kebab-case)
|
||||
|
||||
git mv src/components/onCompletion src/components/features/on-completion
|
||||
```
|
||||
|
||||
3) 为各 features/* 添加 index.ts(按需)并提交:
|
||||
|
||||
```bash
|
||||
git add -A
|
||||
git commit -m "refactor(components): consolidate feature modules under src/components/features/* (phase 2)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Phase 3:标准化设置(settings/)
|
||||
|
||||
```bash
|
||||
# 将 settings 迁移到 features/settings
|
||||
mkdir -p src/components/features/settings/{tabs,components,core}
|
||||
|
||||
git mv src/components/settings/AboutSettingsTab.ts src/components/features/settings/tabs/AboutSettingsTab.ts
|
||||
|
||||
git mv src/components/settings/BasesSettingsTab.ts src/components/features/settings/tabs/BasesSettingsTab.ts
|
||||
|
||||
git mv src/components/settings/BetaTestSettingsTab.ts src/components/features/settings/tabs/BetaTestSettingsTab.ts
|
||||
|
||||
git mv src/components/settings/DatePrioritySettingsTab.ts src/components/features/settings/tabs/DatePrioritySettingsTab.ts
|
||||
|
||||
git mv src/components/settings/FileFilterSettingsTab.ts src/components/features/settings/tabs/FileFilterSettingsTab.ts
|
||||
|
||||
git mv src/components/settings/HabitSettingsTab.ts src/components/features/settings/tabs/HabitSettingsTab.ts
|
||||
|
||||
git mv src/components/settings/IcsSettingsTab.ts src/components/features/settings/tabs/IcsSettingsTab.ts
|
||||
|
||||
git mv src/components/settings/IndexSettingsTab.ts src/components/features/settings/tabs/IndexSettingsTab.ts
|
||||
|
||||
git mv src/components/settings/McpIntegrationSettingsTab.ts src/components/features/settings/tabs/McpIntegrationSettingsTab.ts
|
||||
|
||||
git mv src/components/settings/ProgressSettingsTab.ts src/components/features/settings/tabs/ProgressSettingsTab.ts
|
||||
|
||||
git mv src/components/settings/ProjectSettingsTab.ts src/components/features/settings/tabs/ProjectSettingsTab.ts
|
||||
|
||||
git mv src/components/settings/QuickCaptureSettingsTab.ts src/components/features/settings/tabs/QuickCaptureSettingsTab.ts
|
||||
|
||||
git mv src/components/settings/RewardSettingsTab.ts src/components/features/settings/tabs/RewardSettingsTab.ts
|
||||
|
||||
git mv src/components/settings/TaskFilterSettingsTab.ts src/components/features/settings/tabs/TaskFilterSettingsTab.ts
|
||||
|
||||
git mv src/components/settings/TaskHandlerSettingsTab.ts src/components/features/settings/tabs/TaskHandlerSettingsTab.ts
|
||||
|
||||
git mv src/components/settings/TaskStatusSettingsTab.ts src/components/features/settings/tabs/TaskStatusSettingsTab.ts
|
||||
|
||||
git mv src/components/settings/TimeParsingSettingsTab.ts src/components/features/settings/tabs/TimeParsingSettingsTab.ts
|
||||
|
||||
git mv src/components/settings/TimelineSidebarSettingsTab.ts src/components/features/settings/tabs/TimelineSidebarSettingsTab.ts
|
||||
|
||||
git mv src/components/settings/ViewSettingsTab.ts src/components/features/settings/tabs/ViewSettingsTab.ts
|
||||
|
||||
git mv src/components/settings/WorkflowSettingsTab.ts src/components/features/settings/tabs/WorkflowSettingsTab.ts
|
||||
|
||||
# 修正单复数:TaskTimerSettingTab.ts -> TaskTimerSettingsTab.ts
|
||||
|
||||
git mv src/components/settings/TaskTimerSettingTab.ts src/components/features/settings/tabs/TaskTimerSettingsTab.ts
|
||||
|
||||
# 其他设置相关组件
|
||||
|
||||
git mv src/components/settings/FileSourceSettings.ts src/components/features/settings/components/FileSourceSettingsSection.ts
|
||||
|
||||
git mv src/components/settings/SettingsIndexer.ts src/components/features/settings/core/SettingsIndexer.ts
|
||||
|
||||
git mv src/components/settings/SettingsSearchComponent.ts src/components/features/settings/components/SettingsSearchComponent.ts
|
||||
|
||||
# index.ts 移至新位置(如需要保留,可改为 re-export)
|
||||
# git mv src/components/settings/index.ts src/components/features/settings/index.ts
|
||||
```
|
||||
|
||||
提交:
|
||||
|
||||
```bash
|
||||
git add -A
|
||||
git commit -m "refactor(settings): standardize settings under features/settings with tabs/components/core (phase 3)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Phase 4:barrels、import 与过渡清理
|
||||
|
||||
1) 添加/完善 index.ts(示例)
|
||||
|
||||
```bash
|
||||
# ui/index.ts → 按子目录导出
|
||||
# features/*/index.ts → 导出每个模块公共 API
|
||||
```
|
||||
|
||||
2) (可选)启用路径别名并批量替换 import(示例)
|
||||
|
||||
```bash
|
||||
# tsconfig.json 中添加 paths(见上文第 6 节)
|
||||
# 然后批量替换 import:
|
||||
# from 'src/components/ui/...' → from '@ui/...'
|
||||
# from 'src/components/features/...' → from '@features/...'
|
||||
```
|
||||
|
||||
3) 若采用过渡 re-export,逐步替换后删除旧文件
|
||||
|
||||
提交:
|
||||
|
||||
```bash
|
||||
git add -A
|
||||
git commit -m "refactor(components): add barrels and update imports; remove transitional re-exports (phase 4)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Phase 5:收尾
|
||||
|
||||
```bash
|
||||
# 搜索旧路径残留
|
||||
rg -n "src/components/(?!ui|features)/" src | cat
|
||||
|
||||
# 最终清理与提交
|
||||
git add -A
|
||||
git commit -m "refactor(components): finalize directory migration and clean up (phase 5)"
|
||||
```
|
||||
|
||||
> 注:若未安装 ripgrep(rg),可使用 grep -R -n 进行搜索。
|
||||
|
|
@ -1,380 +0,0 @@
|
|||
# Dataflow Architecture Documentation
|
||||
|
||||
## Overview
|
||||
|
||||
The Dataflow architecture is a modern, modular task management system that replaces the legacy TaskManager-based approach. It provides better separation of concerns, improved performance, and a more maintainable codebase. The architecture now supports both file-based tasks and external data sources (like ICS calendar events) through a unified event-driven pipeline.
|
||||
|
||||
## Architecture Components
|
||||
|
||||
### Core Directory Structure
|
||||
|
||||
```
|
||||
src/dataflow/
|
||||
├── api/ # Public API interfaces
|
||||
│ └── QueryAPI.ts # Unified query interface for all views
|
||||
├── augment/ # Task enhancement logic
|
||||
│ └── Augmentor.ts # Centralized task augmentation
|
||||
├── core/ # Core parsing logic
|
||||
│ ├── CanvasParser.ts
|
||||
│ ├── ConfigurableTaskParser.ts
|
||||
│ └── CoreTaskParser.ts
|
||||
├── events/ # Event system
|
||||
│ └── Events.ts # Centralized event management
|
||||
├── indexer/ # Task indexing
|
||||
│ └── Repository.ts # Task repository with indexing & ICS integration
|
||||
├── parsers/ # High-level parsing entries
|
||||
│ ├── CanvasEntry.ts
|
||||
│ ├── FileMetaEntry.ts
|
||||
│ └── MarkdownEntry.ts
|
||||
├── persistence/ # Data persistence
|
||||
│ └── Storage.ts # Unified storage layer (tasks + ICS events)
|
||||
├── project/ # Project management
|
||||
│ └── Resolver.ts # Project resolution logic
|
||||
├── sources/ # Data sources
|
||||
│ ├── ObsidianSource.ts # File system monitoring
|
||||
│ ├── IcsSource.ts # ICS calendar events source
|
||||
│ ├── FileSource.ts # File-based task recognition system
|
||||
│ └── FileSourceConfig.ts # FileSource configuration management
|
||||
├── workers/ # Background processing
|
||||
│ ├── ProjectData.worker.ts
|
||||
│ ├── ProjectDataWorkerManager.ts
|
||||
│ ├── TaskIndex.worker.ts
|
||||
│ ├── TaskWorkerManager.ts
|
||||
│ └── WorkerOrchestrator.ts
|
||||
├── Orchestrator.ts # Main coordination component
|
||||
├── createDataflow.ts # Factory function
|
||||
└── index.ts # Module exports
|
||||
```
|
||||
|
||||
## Key Principles
|
||||
|
||||
### 1. Separation of Concerns
|
||||
- **Parsers**: Only extract raw task data, no enhancement
|
||||
- **Augmentor**: All task enhancement logic in one place
|
||||
- **Repository**: Centralized indexing, querying, and data merging
|
||||
- **Storage**: Unified persistence layer for all data types
|
||||
- **Sources**: Independent data providers (files, ICS, etc.)
|
||||
|
||||
### 2. Event-Driven Architecture
|
||||
- Centralized event system through `Events.ts`
|
||||
- Consistent event naming and payload structure
|
||||
- Decoupled components communicate via events
|
||||
- Event sequence tracking prevents circular updates
|
||||
|
||||
### 3. Production Ready
|
||||
- Core setting (`dataflowEnabled`) enabled by default
|
||||
- Full backward compatibility maintained
|
||||
- Complete feature parity achieved
|
||||
|
||||
### 4. Unified Data Pipeline
|
||||
- All data sources flow through the same architecture
|
||||
- File-based tasks and external events (ICS) are merged seamlessly
|
||||
- Consistent querying interface regardless of data source
|
||||
|
||||
## Component Responsibilities
|
||||
|
||||
### Orchestrator
|
||||
- Coordinates all dataflow components
|
||||
- Manages initialization and lifecycle
|
||||
- Routes events between components
|
||||
- Handles multiple data sources (ObsidianSource, IcsSource)
|
||||
- Implements sequence-based loop prevention
|
||||
|
||||
### Data Sources
|
||||
|
||||
#### ObsidianSource
|
||||
- Monitors file system changes
|
||||
- Emits FILE_UPDATED events
|
||||
- Handles Markdown and Canvas files
|
||||
- Tracks file modifications, creations, deletions
|
||||
|
||||
#### IcsSource (New)
|
||||
- Integrates external calendar events
|
||||
- Emits ICS_EVENTS_UPDATED events
|
||||
- Syncs with IcsManager
|
||||
- Converts calendar events to task format
|
||||
|
||||
#### FileSource (Integrated - Bug Fixed)
|
||||
- Recognizes files as tasks based on configurable strategies
|
||||
- Supports metadata, tag, template, and path-based recognition
|
||||
- Emits file-task-updated events for file-level tasks
|
||||
- Manages file task caching and deduplication
|
||||
- Integrates with status mapping for flexible task states
|
||||
- **Status**: Fully integrated with configuration path fix applied
|
||||
|
||||
### QueryAPI
|
||||
- Public interface for all data queries
|
||||
- Abstracts internal repository complexity
|
||||
- Provides consistent API for views
|
||||
- Returns merged data from all sources
|
||||
|
||||
### Repository
|
||||
- Maintains task index for file-based tasks
|
||||
- Stores ICS events separately
|
||||
- Merges data from multiple sources in queries
|
||||
- Handles snapshot persistence
|
||||
- Emits update events with source tracking
|
||||
|
||||
### Augmentor
|
||||
- Applies task enhancement strategies
|
||||
- Handles inheritance and deduplication
|
||||
- Manages project references
|
||||
|
||||
### Storage
|
||||
- Wraps LocalStorageCache
|
||||
- Manages versioning and invalidation
|
||||
- Provides namespace isolation
|
||||
- Persists:
|
||||
- Raw tasks (file-based)
|
||||
- Augmented tasks
|
||||
- Project data
|
||||
- ICS events
|
||||
- Consolidated index
|
||||
|
||||
## Event Flow & Loop Prevention
|
||||
|
||||
### Event Types
|
||||
```typescript
|
||||
Events = {
|
||||
CACHE_READY: "task-genius:cache-ready",
|
||||
TASK_CACHE_UPDATED: "task-genius:task-cache-updated",
|
||||
FILE_UPDATED: "task-genius:file-updated",
|
||||
ICS_EVENTS_UPDATED: "task-genius:ics-events-updated",
|
||||
FILE_TASK_UPDATED: "task-genius:file-task-updated", // FileSource events
|
||||
FILE_TASK_REMOVED: "task-genius:file-task-removed", // FileSource removal
|
||||
// ... other events
|
||||
}
|
||||
```
|
||||
|
||||
### Loop Prevention Mechanism
|
||||
1. **Source Sequence Tracking**: Each operation generates a unique sequence number
|
||||
2. **Event Tagging**: Events include `sourceSeq` to identify their origin
|
||||
3. **Filtering**: Components ignore events they originated
|
||||
4. **Clean Event Flow**: Prevents infinite update loops
|
||||
|
||||
### Typical Event Flow
|
||||
```
|
||||
1. File Change → ObsidianSource → FILE_UPDATED event
|
||||
2. Orchestrator processes → Repository.updateFile()
|
||||
3. Repository → TASK_CACHE_UPDATED event (with sourceSeq)
|
||||
4. Views update → UI refreshes
|
||||
|
||||
OR
|
||||
|
||||
1. Calendar Sync → IcsSource → ICS_EVENTS_UPDATED event
|
||||
2. Orchestrator processes → Repository.updateIcsEvents()
|
||||
3. Repository → TASK_CACHE_UPDATED event (with sourceSeq)
|
||||
4. Views update → UI refreshes
|
||||
|
||||
OR (pending integration)
|
||||
|
||||
1. File Recognition → FileSource → FILE_TASK_UPDATED event
|
||||
2. Orchestrator processes → Repository.updateFileTasks()
|
||||
3. Repository → TASK_CACHE_UPDATED event (with sourceSeq)
|
||||
4. Views update → UI refreshes
|
||||
```
|
||||
|
||||
## Data Flow
|
||||
|
||||
### Initialization
|
||||
1. **Repository.initialize()**: Load consolidated index and ICS events
|
||||
2. **ObsidianSource.initialize()**: Start file monitoring
|
||||
3. **IcsSource.initialize()**: Start calendar sync
|
||||
4. **FileSource.initialize()** (pending): Start file recognition
|
||||
5. **Initial Scan**: Process all files if no cache exists
|
||||
|
||||
### Runtime Updates
|
||||
1. **File Changes**: ObsidianSource → Orchestrator → Repository → Views
|
||||
2. **ICS Updates**: IcsSource → Orchestrator → Repository → Views
|
||||
3. **File Task Updates** (pending): FileSource → Orchestrator → Repository → Views
|
||||
4. **Manual Refresh**: Views → QueryAPI → Repository (cached data)
|
||||
|
||||
### Data Persistence
|
||||
- **Continuous**: Augmented tasks stored on each update
|
||||
- **ICS Events**: Persisted separately for fast recovery
|
||||
- **File Tasks** (pending): Cached with recognition metadata
|
||||
- **Consolidated Index**: Saved periodically and on shutdown
|
||||
- **Version Control**: Schema versioning for migration support
|
||||
|
||||
## Migration Status
|
||||
|
||||
### Completed Phases
|
||||
- ✅ Phase A: Parallel initialization with feature flag
|
||||
- ✅ Phase B: View migration to QueryAPI
|
||||
- ✅ Phase C: Parser and enhancement separation
|
||||
- ✅ Phase D: Unified persistence layer
|
||||
- ✅ Phase E: Default enablement and cleanup
|
||||
- ✅ Phase F: ICS integration through dataflow
|
||||
|
||||
### Current Architecture State
|
||||
- **Default Mode**: Dataflow is now the default (enabled by default)
|
||||
- **Legacy Support**: TaskManager fully replaced by Dataflow
|
||||
- **External Data**: ICS events integrated seamlessly
|
||||
- **File Recognition**: FileSource fully integrated and operational
|
||||
- **Performance**: Optimized with caching and workers
|
||||
- **Stability**: Loop prevention and error handling
|
||||
|
||||
## Usage
|
||||
|
||||
### Enabling Dataflow
|
||||
```typescript
|
||||
// In settings (now default)
|
||||
dataflowEnabled: true
|
||||
```
|
||||
|
||||
### Querying Tasks
|
||||
```typescript
|
||||
// Using QueryAPI - returns both file tasks and ICS events
|
||||
const allTasks = await queryAPI.getAllTasks();
|
||||
const projectTasks = await queryAPI.getTasksByProject("MyProject");
|
||||
const taggedTasks = await queryAPI.getTasksByTags(["important"]);
|
||||
```
|
||||
|
||||
### Event Subscription
|
||||
```typescript
|
||||
// Subscribe to all task updates (files + ICS)
|
||||
Events.on(Events.TASK_CACHE_UPDATED, (payload) => {
|
||||
const { changedFiles, stats } = payload;
|
||||
// Handle updated tasks
|
||||
});
|
||||
|
||||
// Subscribe to ICS-specific updates
|
||||
Events.on(Events.ICS_EVENTS_UPDATED, (payload) => {
|
||||
const { events } = payload;
|
||||
// Handle ICS events
|
||||
});
|
||||
```
|
||||
|
||||
## Performance Characteristics
|
||||
|
||||
### Optimizations
|
||||
1. **Snapshot Loading**: Fast startup from persisted state (~100ms for 1000 tasks)
|
||||
2. **Worker Orchestration**: Parallel processing for large vaults
|
||||
3. **Batch Operations**: Reduced I/O overhead
|
||||
4. **Event Deduplication**: Sequence-based loop prevention
|
||||
5. **Incremental Updates**: Only changed files processed
|
||||
6. **Separate ICS Storage**: Calendar events don't impact file indexing
|
||||
|
||||
### Cache Strategy
|
||||
- **Multi-tier**: Raw → Augmented → Consolidated
|
||||
- **Content Hashing**: Detect actual changes
|
||||
- **Modification Time**: Quick staleness check
|
||||
- **Lazy Loading**: Load data only when needed
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
#### Infinite Loop Detection
|
||||
- **Symptom**: Repeated "Batch update" logs
|
||||
- **Cause**: Missing sourceSeq in events
|
||||
- **Solution**: Ensure all TASK_CACHE_UPDATED events include sourceSeq
|
||||
|
||||
#### Missing ICS Events
|
||||
- **Symptom**: Calendar events not showing in views
|
||||
- **Cause**: IcsSource not initialized or IcsManager unavailable
|
||||
- **Solution**: Check IcsManager configuration and initialization
|
||||
|
||||
#### Stale Data
|
||||
- **Symptom**: Changes not reflected in views
|
||||
- **Cause**: Cache not invalidated properly
|
||||
- **Solution**: Clear cache or trigger manual rebuild
|
||||
|
||||
### Debug Commands
|
||||
```javascript
|
||||
// In console
|
||||
app.plugins.plugins['task-genius'].dataflowOrchestrator.getStats()
|
||||
app.plugins.plugins['task-genius'].dataflowOrchestrator.rebuild()
|
||||
```
|
||||
|
||||
## Development Guidelines
|
||||
|
||||
### Adding New Data Sources
|
||||
1. Create source in `src/dataflow/sources/`
|
||||
2. Implement event emission pattern
|
||||
3. Add event type to `Events.ts`
|
||||
4. Update Orchestrator to subscribe
|
||||
5. Extend Repository if needed
|
||||
6. Update Storage for persistence
|
||||
|
||||
### FileSource Integration (Completed)
|
||||
The FileSource component has been fully integrated into the Orchestrator:
|
||||
1. ✅ Initialize FileSource in Orchestrator constructor
|
||||
2. ✅ Subscribe to FILE_TASK_UPDATED and FILE_TASK_REMOVED events
|
||||
3. ✅ Extend Repository to handle file tasks separately from regular tasks
|
||||
4. ✅ Update QueryAPI to merge file tasks in query results
|
||||
5. ✅ Implement caching strategy to avoid redundant project resolution
|
||||
6. ✅ Complete template and path recognition strategies
|
||||
7. ✅ Add removeFileTask method to Repository
|
||||
|
||||
**Bug Fixes Applied**:
|
||||
- Fixed configuration path mismatch where Orchestrator was checking `fileSourceConfig` instead of `fileSource` in settings
|
||||
- Added missing removeFileTask method to Repository for proper file task cleanup
|
||||
- Completed template recognition strategy implementation
|
||||
|
||||
### Adding New Features
|
||||
1. Implement in dataflow architecture first
|
||||
2. Add conditional logic for backward compatibility
|
||||
3. Include sourceSeq in any TASK_CACHE_UPDATED events
|
||||
4. Test both dataflow and legacy modes
|
||||
5. Update this documentation
|
||||
|
||||
### Best Practices
|
||||
- Always use QueryAPI for data access
|
||||
- Never bypass Repository for updates
|
||||
- Include proper event metadata
|
||||
- Handle errors gracefully
|
||||
- Log with component prefix: `[ComponentName]`
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
### Planned
|
||||
1. **Write Operations**: Extend dataflow for task creation/updates
|
||||
2. **Advanced Querying**: GraphQL-like query capabilities
|
||||
3. **Real-time Sync**: Multi-device synchronization
|
||||
4. **Plugin API**: External plugin support
|
||||
|
||||
### Under Consideration
|
||||
- WebSocket support for real-time collaboration
|
||||
- Database backend option for large vaults
|
||||
- Incremental parsing for huge files
|
||||
- Custom data source plugins
|
||||
|
||||
## Architecture Decisions
|
||||
|
||||
### Why Separate ICS Storage?
|
||||
- **Independence**: ICS events have different lifecycle than file tasks
|
||||
- **Performance**: Avoid re-parsing files when only calendar changes
|
||||
- **Flexibility**: Easy to add/remove external sources
|
||||
- **Clarity**: Clear separation of concerns
|
||||
|
||||
### Why Source Sequences?
|
||||
- **Simplicity**: Single number comparison prevents loops
|
||||
- **Performance**: Minimal overhead
|
||||
- **Debugging**: Easy to trace event origins
|
||||
- **Compatibility**: Works with existing event system
|
||||
|
||||
### Why Keep Legacy Support?
|
||||
- **Safety**: Fallback for critical issues
|
||||
- **Migration**: Gradual transition for large vaults
|
||||
- **Testing**: A/B comparison capability
|
||||
- **Confidence**: Users can always revert
|
||||
|
||||
## Bug Fixes and Updates
|
||||
|
||||
### FileSource Configuration Path Fix (2025-08-22)
|
||||
**Problem**: FileSource was not initializing despite being enabled in settings.
|
||||
- **Root Cause**: Configuration path mismatch between settings structure (`fileSource`) and Orchestrator code (`fileSourceConfig`)
|
||||
- **Files Modified**: `src/dataflow/Orchestrator.ts` (lines 88-91)
|
||||
- **Resolution**: Updated Orchestrator to use correct settings path `plugin.settings.fileSource`
|
||||
- **Impact**: FileSource now properly initializes when enabled and can recognize files as tasks
|
||||
|
||||
## Conclusion
|
||||
|
||||
The Dataflow architecture has evolved from a file-centric system to a unified data pipeline supporting multiple sources. Its event-driven, modular design enables:
|
||||
- Clean integration of new data sources
|
||||
- Robust loop prevention
|
||||
- Excellent performance characteristics
|
||||
- Maintainable and testable codebase
|
||||
|
||||
The architecture is production-ready and serves as the foundation for future task management enhancements.
|
||||
|
|
@ -1,208 +0,0 @@
|
|||
# Dataflow 事件系统架构
|
||||
|
||||
## 概述
|
||||
|
||||
Dataflow 架构通过事件驱动的方式处理任务的增删改查操作,确保 UI 和数据层的同步更新。
|
||||
|
||||
## 核心组件
|
||||
|
||||
### 1. ObsidianSource
|
||||
- **作用**: 监听 Obsidian 文件系统事件
|
||||
- **事件**:
|
||||
- 文件创建/修改/删除/重命名
|
||||
- 元数据变更
|
||||
- **特性**:
|
||||
- 自动去抖动(300ms)
|
||||
- 批量处理
|
||||
- 跳过 WriteAPI 触发的修改
|
||||
|
||||
### 2. DataflowOrchestrator
|
||||
- **作用**: 协调所有数据流组件
|
||||
- **监听事件**:
|
||||
- `FILE_UPDATED`: 处理文件变更
|
||||
- `TASK_CACHE_UPDATED`: 处理批量更新
|
||||
- `WRITE_OPERATION_COMPLETE`: 处理 WriteAPI 完成的操作
|
||||
- **处理流程**:
|
||||
1. 接收事件
|
||||
2. 解析文件内容
|
||||
3. 增强任务数据
|
||||
4. 更新 Repository
|
||||
5. 触发 UI 更新
|
||||
|
||||
### 3. Repository
|
||||
- **作用**: 中央数据仓库
|
||||
- **功能**:
|
||||
- 维护任务索引
|
||||
- 持久化存储
|
||||
- 触发 `TASK_CACHE_UPDATED` 事件通知 UI
|
||||
|
||||
### 4. WriteAPI
|
||||
- **作用**: 处理所有写操作
|
||||
- **事件流程**:
|
||||
1. 发送 `WRITE_OPERATION_START` 事件
|
||||
2. 修改文件
|
||||
3. 发送 `WRITE_OPERATION_COMPLETE` 事件
|
||||
4. Orchestrator 接收事件并重新处理文件
|
||||
|
||||
## 数据流路径
|
||||
|
||||
### 场景 1: UI 更新任务
|
||||
```
|
||||
UI操作 → WriteAPI → 发送 WRITE_OPERATION_START
|
||||
→ 修改文件
|
||||
→ 发送 WRITE_OPERATION_COMPLETE
|
||||
→ Orchestrator 处理文件
|
||||
→ Repository 更新
|
||||
→ 发送 TASK_CACHE_UPDATED
|
||||
→ UI 更新
|
||||
```
|
||||
|
||||
### 场景 2: 直接编辑文件
|
||||
```
|
||||
文件编辑 → ObsidianSource 检测变化
|
||||
→ 发送 FILE_UPDATED 事件
|
||||
→ Orchestrator 处理文件
|
||||
→ Repository 更新
|
||||
→ 发送 TASK_CACHE_UPDATED
|
||||
→ UI 更新
|
||||
```
|
||||
|
||||
### 场景 3: Canvas 任务更新
|
||||
```
|
||||
Canvas 任务编辑 → CanvasTaskUpdater
|
||||
→ 发送 WRITE_OPERATION_START
|
||||
→ 修改 Canvas JSON
|
||||
→ 发送 WRITE_OPERATION_COMPLETE
|
||||
→ Orchestrator 处理
|
||||
→ UI 更新
|
||||
```
|
||||
|
||||
## 关键事件
|
||||
|
||||
### Events 定义
|
||||
```typescript
|
||||
export const Events = {
|
||||
CACHE_READY: "task-genius:cache-ready",
|
||||
TASK_CACHE_UPDATED: "task-genius:task-cache-updated",
|
||||
FILE_UPDATED: "task-genius:file-updated",
|
||||
WRITE_OPERATION_START: "task-genius:write-operation-start",
|
||||
WRITE_OPERATION_COMPLETE: "task-genius:write-operation-complete",
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### 事件协作
|
||||
|
||||
1. **ObsidianSource 与 WriteAPI 协作**:
|
||||
- WriteAPI 发送 `WRITE_OPERATION_START` 时,ObsidianSource 标记该文件
|
||||
- ObsidianSource 跳过被标记文件的 modify 事件
|
||||
- 避免重复处理
|
||||
|
||||
2. **Orchestrator 事件处理**:
|
||||
- 监听多个事件源
|
||||
- 对 WriteAPI 操作立即处理(无去抖)
|
||||
- 对文件系统事件进行去抖处理
|
||||
|
||||
3. **Repository 事件发送**:
|
||||
- 每次更新后发送 `TASK_CACHE_UPDATED`
|
||||
- 包含变更文件列表和统计信息
|
||||
- UI 组件监听此事件进行更新
|
||||
|
||||
## 实现细节
|
||||
|
||||
### 去抖动机制
|
||||
- ObsidianSource: 300ms 去抖
|
||||
- Orchestrator: 300ms 去抖(除 WriteAPI 操作外)
|
||||
- 批量操作: 150ms 批处理延迟
|
||||
|
||||
### 事件跳过机制
|
||||
```typescript
|
||||
// ObsidianSource
|
||||
if (this.skipNextModify.has(file.path)) {
|
||||
this.skipNextModify.delete(file.path);
|
||||
console.log(`Skipping modify event (handled by WriteAPI)`);
|
||||
return;
|
||||
}
|
||||
```
|
||||
|
||||
### 立即处理机制
|
||||
```typescript
|
||||
// Orchestrator - WriteAPI 操作立即处理
|
||||
on(Events.WRITE_OPERATION_COMPLETE, async (payload) => {
|
||||
const file = this.vault.getAbstractFileByPath(payload.path);
|
||||
if (file) {
|
||||
await this.processFileImmediate(file); // 无去抖
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## 测试要点
|
||||
|
||||
1. **UI 更新测试**:
|
||||
- 通过 UI 修改任务状态
|
||||
- 验证文件被更新
|
||||
- 验证 UI 自动刷新
|
||||
|
||||
2. **文件编辑测试**:
|
||||
- 直接在 Obsidian 中编辑任务
|
||||
- 验证 UI 在 300ms 后更新
|
||||
|
||||
3. **Canvas 任务测试**:
|
||||
- 在 Canvas 中修改任务
|
||||
- 验证 Canvas 文件更新
|
||||
- 验证任务列表刷新
|
||||
|
||||
4. **批量操作测试**:
|
||||
- 同时修改多个文件
|
||||
- 验证批处理机制工作
|
||||
- 验证性能优化效果
|
||||
|
||||
## 调试技巧
|
||||
|
||||
### 启用日志
|
||||
```typescript
|
||||
// 在 Orchestrator 中
|
||||
console.log(`[DataflowOrchestrator] FILE_UPDATED: ${path}`);
|
||||
console.log(`[DataflowOrchestrator] WRITE_OPERATION_COMPLETE: ${path}`);
|
||||
|
||||
// 在 ObsidianSource 中
|
||||
console.log(`ObsidianSource: File modified - ${file.path}`);
|
||||
console.log(`ObsidianSource: Skipping modify event (handled by WriteAPI)`);
|
||||
```
|
||||
|
||||
### 事件流追踪
|
||||
1. 打开控制台
|
||||
2. 执行操作
|
||||
3. 观察事件序列:
|
||||
- WRITE_OPERATION_START
|
||||
- File modification (可能被跳过)
|
||||
- WRITE_OPERATION_COMPLETE
|
||||
- TASK_CACHE_UPDATED
|
||||
|
||||
### 常见问题
|
||||
|
||||
1. **UI 不更新**:
|
||||
- 检查 TASK_CACHE_UPDATED 事件是否触发
|
||||
- 验证 UI 组件是否正确监听事件
|
||||
|
||||
2. **重复处理**:
|
||||
- 检查 skipNextModify 机制
|
||||
- 验证去抖动时间设置
|
||||
|
||||
3. **Canvas 更新失败**:
|
||||
- 检查 CanvasTaskUpdater 事件发送
|
||||
- 验证 Canvas JSON 格式正确
|
||||
|
||||
## 未来改进
|
||||
|
||||
1. **性能优化**:
|
||||
- 实现更智能的增量更新
|
||||
- 优化大文件处理
|
||||
|
||||
2. **错误处理**:
|
||||
- 添加重试机制
|
||||
- 改进错误报告
|
||||
|
||||
3. **监控**:
|
||||
- 添加性能指标
|
||||
- 实现事件追踪系统
|
||||
|
|
@ -1,99 +0,0 @@
|
|||
# Dataflow Migration - Phase A Complete
|
||||
|
||||
## Summary
|
||||
Phase A of the dataflow migration has been successfully implemented. This phase enables parallel initialization of both the traditional TaskManager and the new dataflow architecture, with experimental user control.
|
||||
|
||||
## Completed Tasks
|
||||
|
||||
### A1: Experimental Settings Switch ✅
|
||||
- **Location**: `src/common/setting-definition.ts`, `src/setting.ts`
|
||||
- **Changes**:
|
||||
- Added `experimental.dataflowEnabled` setting with default `false`
|
||||
- Created new "Experimental" tab in settings UI
|
||||
- Added warning messages and user-friendly descriptions
|
||||
- Added CSS styles for experimental settings
|
||||
|
||||
### A2: Parallel Initialization ✅
|
||||
- **Location**: `src/index.ts`, `src/dataflow/createDataflow.ts`
|
||||
- **Changes**:
|
||||
- Created `createDataflow()` factory function
|
||||
- Added `isDataflowEnabled()` utility function
|
||||
- Modified plugin `onload()` to conditionally initialize dataflow
|
||||
- Added proper cleanup in `onunload()`
|
||||
- Both systems run in parallel when dataflow is enabled
|
||||
|
||||
### A3: TaskView Data Source Selection ✅
|
||||
- **Location**: `src/pages/TaskView.ts`
|
||||
- **Changes**:
|
||||
- Modified `loadTasks()` method to check dataflow availability
|
||||
- Modified `loadTasksFast()` method with same logic
|
||||
- Added fallback mechanism to TaskManager if dataflow fails
|
||||
- Maintained backward compatibility
|
||||
|
||||
## Key Features
|
||||
|
||||
### Safe Experimentation
|
||||
- Users can enable/disable dataflow through settings
|
||||
- Automatic fallback to TaskManager on any dataflow errors
|
||||
- Both systems can run simultaneously for comparison
|
||||
|
||||
### Non-Breaking Changes
|
||||
- All existing functionality preserved
|
||||
- No changes to default behavior (dataflow disabled by default)
|
||||
- Graceful error handling
|
||||
|
||||
### Ready for Testing
|
||||
- TaskView now conditionally uses QueryAPI when dataflow is enabled
|
||||
- Console logging for debugging and verification
|
||||
- Clean separation between old and new systems
|
||||
|
||||
## Testing Instructions
|
||||
|
||||
1. **Enable Dataflow**:
|
||||
- Go to Settings → Advanced → Experimental
|
||||
- Toggle "Enable Dataflow Architecture"
|
||||
- Restart plugin (recommended)
|
||||
|
||||
2. **Verify Operation**:
|
||||
- Open Task Genius view
|
||||
- Check console for messages:
|
||||
- "Loading tasks from dataflow orchestrator..." (dataflow enabled)
|
||||
- "TaskView loaded X tasks from dataflow" (success)
|
||||
- "Loading tasks from TaskManager" (fallback/disabled)
|
||||
|
||||
3. **Test Fallback**:
|
||||
- If dataflow fails, should automatically fall back to TaskManager
|
||||
- No user-visible errors should occur
|
||||
|
||||
## Next Phase Recommendations
|
||||
|
||||
**Phase B: View Migration**
|
||||
- Migrate remaining views (Projects, Tags, Forecast)
|
||||
- Add more sophisticated error handling
|
||||
- Implement data consistency checks
|
||||
|
||||
**Phase C: Feature Parity**
|
||||
- Ensure all TaskManager features work with dataflow
|
||||
- Performance comparison and optimization
|
||||
- User feedback collection
|
||||
|
||||
## Code Locations
|
||||
|
||||
```
|
||||
src/common/setting-definition.ts # Settings definition
|
||||
src/setting.ts # Settings UI
|
||||
src/styles/setting.css # Experimental settings styles
|
||||
src/index.ts # Plugin initialization
|
||||
src/dataflow/createDataflow.ts # Dataflow factory
|
||||
src/pages/TaskView.ts # Main view with conditional data source
|
||||
```
|
||||
|
||||
## Architecture Notes
|
||||
|
||||
The implementation maintains clean separation:
|
||||
- **Settings Layer**: Controls experimental features
|
||||
- **Initialization Layer**: Manages parallel system startup
|
||||
- **Data Layer**: Provides conditional data source selection
|
||||
- **UI Layer**: Unchanged, works with both systems
|
||||
|
||||
This approach allows for gradual migration with minimal risk and easy rollback capabilities.
|
||||
|
|
@ -1,136 +0,0 @@
|
|||
# Dataflow Architecture - Production Ready
|
||||
|
||||
## Overview
|
||||
|
||||
The Dataflow architecture has been promoted from experimental status to production ready. This document outlines the changes made to reflect this milestone.
|
||||
|
||||
## Changes Made
|
||||
|
||||
### 1. Settings Structure Update
|
||||
|
||||
**Before (Experimental)**:
|
||||
```typescript
|
||||
interface TaskProgressBarSettings {
|
||||
experimental?: {
|
||||
dataflowEnabled: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
// Default
|
||||
experimental: {
|
||||
dataflowEnabled: true
|
||||
}
|
||||
```
|
||||
|
||||
**After (Production)**:
|
||||
```typescript
|
||||
interface TaskProgressBarSettings {
|
||||
// Core Architecture Settings
|
||||
dataflowEnabled: boolean;
|
||||
}
|
||||
|
||||
// Default
|
||||
dataflowEnabled: true
|
||||
```
|
||||
|
||||
### 2. Settings UI Migration
|
||||
|
||||
- **Moved from**: Experimental tab → Index & Sources tab
|
||||
- **New location**: Core Architecture section in Index & Sources
|
||||
- **Updated description**: Removed experimental warnings, emphasized as recommended setting
|
||||
|
||||
### 3. Code References Updated
|
||||
|
||||
All references to `settings.experimental.dataflowEnabled` have been updated to `settings.dataflowEnabled`:
|
||||
|
||||
- `src/dataflow/createDataflow.ts` - `isDataflowEnabled()` function
|
||||
- `src/index.ts` - Command handlers
|
||||
- `src/mcp/McpServer.ts` - MCP integration
|
||||
- `src/components/settings/IndexSettingsTab.ts` - Settings UI
|
||||
|
||||
### 4. Default Behavior
|
||||
|
||||
- **Default value**: `true` (Dataflow enabled by default)
|
||||
- **Fallback behavior**: If setting is undefined, defaults to `true`
|
||||
- **Migration**: Existing users with `experimental.dataflowEnabled: false` will need to manually update
|
||||
|
||||
## Migration Guide
|
||||
|
||||
### For Plugin Users
|
||||
|
||||
1. **Automatic Migration**: New installations will use Dataflow by default
|
||||
2. **Existing Users**:
|
||||
- If you had Dataflow enabled: No action needed
|
||||
- If you had Dataflow disabled: Check "Index & Sources" → "Enable Dataflow Architecture"
|
||||
3. **Settings Location**: Find Dataflow settings in "Index & Sources" tab instead of "Experimental"
|
||||
|
||||
### For Developers
|
||||
|
||||
1. **API Changes**: Use `plugin.settings.dataflowEnabled` instead of `plugin.settings.experimental?.dataflowEnabled`
|
||||
2. **Default Assumption**: Code should assume Dataflow is enabled unless explicitly disabled
|
||||
3. **Backward Compatibility**: Old experimental setting is ignored
|
||||
|
||||
## Benefits of Production Status
|
||||
|
||||
### 1. User Confidence
|
||||
- No longer marked as experimental
|
||||
- Clear indication that the feature is stable and recommended
|
||||
- Reduced barrier to adoption
|
||||
|
||||
### 2. Simplified Settings
|
||||
- Cleaner settings structure
|
||||
- More logical organization (Core Architecture vs Experimental)
|
||||
- Better user experience
|
||||
|
||||
### 3. Development Focus
|
||||
- Experimental tab reserved for truly experimental features
|
||||
- Core architecture decisions are clearly separated
|
||||
- Easier maintenance and documentation
|
||||
|
||||
## Architecture Maturity Indicators
|
||||
|
||||
### ✅ Completed Milestones
|
||||
|
||||
1. **Feature Parity**: All TaskManager functionality replicated
|
||||
2. **Performance**: Optimized with caching and workers
|
||||
3. **Stability**: Comprehensive error handling and recovery
|
||||
4. **Testing**: Extensive test coverage
|
||||
5. **Documentation**: Complete architecture documentation
|
||||
6. **User Feedback**: Positive feedback from beta users
|
||||
|
||||
### ✅ Production Readiness Criteria
|
||||
|
||||
1. **Zero Data Loss**: Safe migration from legacy system
|
||||
2. **Performance**: Equal or better performance than legacy
|
||||
3. **Reliability**: Stable operation under various conditions
|
||||
4. **Maintainability**: Clean, well-documented codebase
|
||||
5. **Extensibility**: Easy to add new features
|
||||
|
||||
## Future Roadmap
|
||||
|
||||
### Short Term
|
||||
- Monitor user adoption and feedback
|
||||
- Performance optimizations based on real usage
|
||||
- Bug fixes and stability improvements
|
||||
|
||||
### Medium Term
|
||||
- Advanced query capabilities
|
||||
- Additional data source integrations
|
||||
- Enhanced caching strategies
|
||||
|
||||
### Long Term
|
||||
- Plugin ecosystem support
|
||||
- Advanced analytics and insights
|
||||
- Multi-vault synchronization
|
||||
|
||||
## Conclusion
|
||||
|
||||
The promotion of Dataflow architecture to production status represents a significant milestone in the Task Genius plugin's evolution. The architecture has proven itself through extensive testing and real-world usage, providing a solid foundation for future enhancements.
|
||||
|
||||
Users can now confidently use the Dataflow architecture as the primary task processing system, enjoying improved performance, reliability, and feature richness compared to the legacy TaskManager system.
|
||||
|
||||
---
|
||||
|
||||
**Document Version**: 1.0
|
||||
**Last Updated**: 2025-01-23
|
||||
**Status**: Production Ready ✅
|
||||
|
|
@ -1,351 +0,0 @@
|
|||
# Directory Structure Refactoring Plan
|
||||
|
||||
## Overview
|
||||
This document outlines the comprehensive refactoring plan for reorganizing the `src/utils` directory and establishing a clearer, more maintainable directory structure for the Task Genius plugin.
|
||||
|
||||
## Current Issues
|
||||
|
||||
### Problem Analysis
|
||||
1. **Mixed Responsibilities**: The `src/utils/` directory contains managers, services, parsers, utilities, and executors all mixed together
|
||||
2. **Inconsistent Naming**: Files have inconsistent naming conventions (e.g., `TaskManager.ts` vs `taskUtil.ts`)
|
||||
3. **Poor Organization**: Related functionality is scattered across different locations
|
||||
4. **Overly Large Files**: `TaskManager.ts` is over 27,000 tokens and should be split
|
||||
5. **Unclear Dependencies**: Hard to understand relationships between components
|
||||
|
||||
## Existing Structures to Preserve
|
||||
|
||||
### Keep As-Is
|
||||
- **`src/dataflow/`** - Already well-organized with:
|
||||
- `api/` - QueryAPI, WriteAPI for dataflow operations
|
||||
- `parsers/` - Dataflow-specific parsers (MarkdownEntry, FileMetaEntry, CanvasEntry)
|
||||
- `workers/` - Dataflow-specific workers
|
||||
- `core/`, `events/`, `sources/`, etc.
|
||||
|
||||
- **`src/mcp/`** - MCP server implementation with:
|
||||
- `auth/` - Authentication middleware
|
||||
- `bridge/` - Bridge implementations (DataflowBridge, TaskManagerBridge)
|
||||
- `types/` - Type definitions
|
||||
|
||||
## New Directory Structure
|
||||
|
||||
```
|
||||
src/
|
||||
├── cache/ # Caching and storage utilities
|
||||
│ ├── local-storage-cache.ts (from utils/persister.ts)
|
||||
│ └── project-data-cache.ts (from utils/ProjectDataCache.ts)
|
||||
│
|
||||
├── core/ # Core business logic
|
||||
│ ├── goal/ # Goal-related functionality (moved from utils/goal/)
|
||||
│ │ ├── edit-mode.ts
|
||||
│ │ ├── read-mode.ts
|
||||
│ │ └── regex-goal.ts
|
||||
│ ├── project-filter.ts (from utils/projectFilter.ts)
|
||||
│ ├── project-tree-builder.ts (from utils/projectTreeBuilder.ts)
|
||||
│ ├── task-indexer.ts (from utils/import/TaskIndexer.ts)
|
||||
│ └── workflow-converter.ts (from utils/workflowConversion.ts)
|
||||
│
|
||||
├── dataflow/ # [EXISTING - NO CHANGES]
|
||||
│ └── workers/ # Add worker-related utilities here
|
||||
│ ├── [existing files]
|
||||
│ ├── task-index-message.ts (from utils/workers/TaskIndexWorkerMessage.ts)
|
||||
│ └── deferred-promise.ts (from utils/workers/deferred.ts)
|
||||
│
|
||||
├── executors/ # Action executors
|
||||
│ └── completion/ # Task completion actions
|
||||
│ ├── base-executor.ts (from utils/onCompletion/BaseActionExecutor.ts)
|
||||
│ ├── archive-executor.ts (from utils/onCompletion/ArchiveActionExecutor.ts)
|
||||
│ ├── complete-executor.ts (from utils/onCompletion/CompleteActionExecutor.ts)
|
||||
│ ├── delete-executor.ts (from utils/onCompletion/DeleteActionExecutor.ts)
|
||||
│ ├── duplicate-executor.ts (from utils/onCompletion/DuplicateActionExecutor.ts)
|
||||
│ ├── keep-executor.ts (from utils/onCompletion/KeepActionExecutor.ts)
|
||||
│ ├── move-executor.ts (from utils/onCompletion/MoveActionExecutor.ts)
|
||||
│ └── canvas-operation-utils.ts (from utils/onCompletion/CanvasTaskOperationUtils.ts)
|
||||
│
|
||||
├── managers/ # Feature-specific managers
|
||||
│ ├── completion-manager.ts (from utils/OnCompletionManager.ts)
|
||||
│ ├── file-filter-manager.ts (from utils/FileFilterManager.ts)
|
||||
│ ├── file-task-manager.ts (from utils/FileTaskManager.ts)
|
||||
│ ├── habit-manager.ts (from utils/HabitManager.ts)
|
||||
│ ├── icon-manager.ts (from utils/TaskGeniusIconManager.ts)
|
||||
│ ├── ics-manager.ts (from utils/ics/IcsManager.ts)
|
||||
│ ├── onboarding-manager.ts (from utils/OnboardingConfigManager.ts)
|
||||
│ ├── project-config-manager.ts (from utils/ProjectConfigManager.ts)
|
||||
│ ├── rebuild-progress-manager.ts (from utils/RebuildProgressManager.ts)
|
||||
│ ├── reward-manager.ts (from utils/RewardManager.ts)
|
||||
│ ├── task-manager.ts (from utils/TaskManager.ts)
|
||||
│ ├── timer-manager.ts (from utils/TaskTimerManager.ts)
|
||||
│ └── version-manager.ts (from utils/VersionManager.ts)
|
||||
│
|
||||
├── mcp/ # [EXISTING - NO CHANGES]
|
||||
│
|
||||
├── parsers/ # General-purpose parsers (non-dataflow)
|
||||
│ ├── canvas-parser.ts (from utils/parsing/CanvasParser.ts)
|
||||
│ ├── canvas-task-updater.ts (from utils/parsing/CanvasTaskUpdater.ts)
|
||||
│ ├── configurable-task-parser.ts (from utils/workers/ConfigurableTaskParser.ts)
|
||||
│ ├── context-detector.ts (from utils/workers/ContextDetector.ts)
|
||||
│ ├── file-metadata-parser.ts (from utils/workers/FileMetadataTaskParser.ts)
|
||||
│ ├── file-metadata-updater.ts (from utils/workers/FileMetadataTaskUpdater.ts)
|
||||
│ ├── holiday-detector.ts (from utils/ics/HolidayDetector.ts)
|
||||
│ ├── ics-parser.ts (from utils/ics/IcsParser.ts)
|
||||
│ ├── ics-status-mapper.ts (from utils/ics/StatusMapper.ts)
|
||||
│ └── webcal-converter.ts (from utils/ics/WebcalUrlConverter.ts)
|
||||
│
|
||||
├── services/ # Service classes
|
||||
│ ├── settings-change-detector.ts (from utils/SettingsChangeDetector.ts)
|
||||
│ ├── task-parsing-service.ts (from utils/TaskParsingService.ts)
|
||||
│ ├── time-parsing-service.ts (from utils/TimeParsingService.ts)
|
||||
│ ├── timer-export-service.ts (from utils/TaskTimerExporter.ts)
|
||||
│ ├── timer-format-service.ts (from utils/TaskTimerFormatter.ts)
|
||||
│ └── timer-metadata-service.ts (from utils/TaskTimerMetadataDetector.ts)
|
||||
│
|
||||
└── utils/ # Pure utility functions only
|
||||
├── date/ # Date utilities
|
||||
│ ├── date-formatter.ts (from utils/dateUtil.ts)
|
||||
│ └── date-helper.ts (from utils/DateHelper.ts)
|
||||
├── file/ # File utilities
|
||||
│ ├── file-operations.ts (from utils/fileUtils.ts)
|
||||
│ └── file-type-detector.ts (from utils/fileTypeUtils.ts)
|
||||
├── task/ # Task utilities
|
||||
│ ├── filter-compatibility.ts (from utils/filterUtils.ts)
|
||||
│ ├── priority-utils.ts (from utils/priorityUtils.ts)
|
||||
│ ├── task-filter-utils.ts (from utils/TaskFilterUtils.ts)
|
||||
│ ├── task-migration.ts (from utils/taskMigrationUtils.ts)
|
||||
│ └── task-operations.ts (from utils/taskUtil.ts - if not deprecated)
|
||||
├── ui/ # UI utilities
|
||||
│ ├── tree-view-utils.ts (from utils/treeViewUtil.ts)
|
||||
│ └── view-mode-utils.ts (from utils/viewModeUtils.ts)
|
||||
└── id-generator.ts (from utils/common.ts)
|
||||
```
|
||||
|
||||
## Implementation Phases
|
||||
|
||||
### Phase 1: Directory Creation
|
||||
Create all new directories before moving any files:
|
||||
- `src/managers/`
|
||||
- `src/services/`
|
||||
- `src/executors/completion/`
|
||||
- `src/parsers/`
|
||||
- `src/cache/`
|
||||
- `src/core/goal/`
|
||||
- `src/utils/date/`
|
||||
- `src/utils/file/`
|
||||
- `src/utils/task/`
|
||||
- `src/utils/ui/`
|
||||
|
||||
### Phase 2: Manager Migration
|
||||
Move all manager classes from `src/utils/` to `src/managers/`:
|
||||
|
||||
| Original File | New Location | Rename Reason |
|
||||
|--------------|--------------|---------------|
|
||||
| `FileTaskManager.ts` | `managers/file-task-manager.ts` | Kebab-case consistency |
|
||||
| `HabitManager.ts` | `managers/habit-manager.ts` | Kebab-case consistency |
|
||||
| `TaskManager.ts` | `managers/task-manager.ts` | Kebab-case consistency |
|
||||
| `OnCompletionManager.ts` | `managers/completion-manager.ts` | Clearer naming + kebab-case |
|
||||
| `OnboardingConfigManager.ts` | `managers/onboarding-manager.ts` | Simpler name + kebab-case |
|
||||
| `ProjectConfigManager.ts` | `managers/project-config-manager.ts` | Kebab-case consistency |
|
||||
| `RebuildProgressManager.ts` | `managers/rebuild-progress-manager.ts` | Kebab-case consistency |
|
||||
| `RewardManager.ts` | `managers/reward-manager.ts` | Kebab-case consistency |
|
||||
| `TaskGeniusIconManager.ts` | `managers/icon-manager.ts` | Simpler name + kebab-case |
|
||||
| `TaskTimerManager.ts` | `managers/timer-manager.ts` | Simpler name + kebab-case |
|
||||
| `VersionManager.ts` | `managers/version-manager.ts` | Kebab-case consistency |
|
||||
| `FileFilterManager.ts` | `managers/file-filter-manager.ts` | Kebab-case consistency |
|
||||
| `ics/IcsManager.ts` | `managers/ics-manager.ts` | Flatten structure + kebab-case |
|
||||
|
||||
### Phase 3: Service Migration
|
||||
Move service classes from `src/utils/` to `src/services/`:
|
||||
|
||||
| Original File | New Location | Rename Reason |
|
||||
|--------------|--------------|---------------|
|
||||
| `TaskParsingService.ts` | `services/task-parsing-service.ts` | Kebab-case consistency |
|
||||
| `TimeParsingService.ts` | `services/time-parsing-service.ts` | Kebab-case consistency |
|
||||
| `SettingsChangeDetector.ts` | `services/settings-change-detector.ts` | Kebab-case consistency |
|
||||
| `TaskTimerExporter.ts` | `services/timer-export-service.ts` | Clearer naming + kebab-case |
|
||||
| `TaskTimerFormatter.ts` | `services/timer-format-service.ts` | Clearer naming + kebab-case |
|
||||
| `TaskTimerMetadataDetector.ts` | `services/timer-metadata-service.ts` | Clearer naming + kebab-case |
|
||||
|
||||
### Phase 4: Executor Migration
|
||||
Move executors from `src/utils/onCompletion/` to `src/executors/completion/`:
|
||||
|
||||
| Original File | New Location | Rename Reason |
|
||||
|--------------|--------------|---------------|
|
||||
| `onCompletion/BaseActionExecutor.ts` | `executors/completion/base-executor.ts` | Simpler name + kebab-case |
|
||||
| `onCompletion/ArchiveActionExecutor.ts` | `executors/completion/archive-executor.ts` | Simpler name + kebab-case |
|
||||
| `onCompletion/CompleteActionExecutor.ts` | `executors/completion/complete-executor.ts` | Simpler name + kebab-case |
|
||||
| `onCompletion/DeleteActionExecutor.ts` | `executors/completion/delete-executor.ts` | Simpler name + kebab-case |
|
||||
| `onCompletion/DuplicateActionExecutor.ts` | `executors/completion/duplicate-executor.ts` | Simpler name + kebab-case |
|
||||
| `onCompletion/KeepActionExecutor.ts` | `executors/completion/keep-executor.ts` | Simpler name + kebab-case |
|
||||
| `onCompletion/MoveActionExecutor.ts` | `executors/completion/move-executor.ts` | Simpler name + kebab-case |
|
||||
| `onCompletion/CanvasTaskOperationUtils.ts` | `executors/completion/canvas-operation-utils.ts` | Clearer naming + kebab-case |
|
||||
|
||||
### Phase 5: Parser Migration
|
||||
Move parsers from various locations to appropriate directories:
|
||||
|
||||
| Original File | New Location | Rename Reason |
|
||||
|--------------|--------------|---------------|
|
||||
| `parsing/CanvasParser.ts` | `parsers/canvas-parser.ts` | Kebab-case consistency |
|
||||
| `parsing/CanvasTaskUpdater.ts` | `parsers/canvas-task-updater.ts` | Kebab-case consistency |
|
||||
| `ics/IcsParser.ts` | `parsers/ics-parser.ts` | Flatten structure + kebab-case |
|
||||
| `ics/HolidayDetector.ts` | `parsers/holiday-detector.ts` | Flatten structure + kebab-case |
|
||||
| `ics/StatusMapper.ts` | `parsers/ics-status-mapper.ts` | Clearer naming + kebab-case |
|
||||
| `ics/WebcalUrlConverter.ts` | `parsers/webcal-converter.ts` | Simpler name + kebab-case |
|
||||
| `workers/ConfigurableTaskParser.ts` | `parsers/configurable-task-parser.ts` | Kebab-case consistency |
|
||||
| `workers/ContextDetector.ts` | `parsers/context-detector.ts` | Kebab-case consistency |
|
||||
| `workers/FileMetadataTaskParser.ts` | `parsers/file-metadata-parser.ts` | Simpler name + kebab-case |
|
||||
| `workers/FileMetadataTaskUpdater.ts` | `parsers/file-metadata-updater.ts` | Simpler name + kebab-case |
|
||||
|
||||
### Phase 6: Cache Migration
|
||||
Move caching utilities to `src/cache/`:
|
||||
|
||||
| Original File | New Location | Rename Reason |
|
||||
|--------------|--------------|---------------|
|
||||
| `persister.ts` | `cache/local-storage-cache.ts` | Descriptive name + kebab-case |
|
||||
| `ProjectDataCache.ts` | `cache/project-data-cache.ts` | Kebab-case consistency |
|
||||
|
||||
### Phase 7: Core Business Logic Migration
|
||||
Move core business logic to `src/core/`:
|
||||
|
||||
| Original File | New Location | Rename Reason |
|
||||
|--------------|--------------|---------------|
|
||||
| `projectFilter.ts` | `core/project-filter.ts` | Kebab-case consistency |
|
||||
| `projectTreeBuilder.ts` | `core/project-tree-builder.ts` | Kebab-case consistency |
|
||||
| `workflowConversion.ts` | `core/workflow-converter.ts` | Clearer naming + kebab-case |
|
||||
| `goal/` (entire directory) | `core/goal/` | Preserve structure |
|
||||
| `import/TaskIndexer.ts` | `core/task-indexer.ts` | Flatten structure + kebab-case |
|
||||
|
||||
### Phase 8: Worker Migration to Dataflow
|
||||
Move worker utilities to existing `src/dataflow/workers/`:
|
||||
|
||||
| Original File | New Location | Rename Reason |
|
||||
|--------------|--------------|---------------|
|
||||
| `workers/TaskIndexWorkerMessage.ts` | `dataflow/workers/task-index-message.ts` | Simpler name + kebab-case |
|
||||
| `workers/deferred.ts` | `dataflow/workers/deferred-promise.ts` | Descriptive name + kebab-case |
|
||||
|
||||
### Phase 9: Utility Reorganization
|
||||
Reorganize remaining utilities into categorized subdirectories:
|
||||
|
||||
| Original File | New Location | Rename Reason |
|
||||
|--------------|--------------|---------------|
|
||||
| `DateHelper.ts` | `utils/date/date-helper.ts` | Kebab-case consistency |
|
||||
| `dateUtil.ts` | `utils/date/date-formatter.ts` | Descriptive name + kebab-case |
|
||||
| `fileTypeUtils.ts` | `utils/file/file-type-detector.ts` | Descriptive name + kebab-case |
|
||||
| `fileUtils.ts` | `utils/file/file-operations.ts` | Descriptive name + kebab-case |
|
||||
| `priorityUtils.ts` | `utils/task/priority-utils.ts` | Kebab-case consistency |
|
||||
| `taskUtil.ts` | `utils/task/task-operations.ts` | Descriptive name + kebab-case |
|
||||
| `TaskFilterUtils.ts` | `utils/task/task-filter-utils.ts` | Kebab-case consistency |
|
||||
| `filterUtils.ts` | `utils/task/filter-compatibility.ts` | Descriptive name + kebab-case |
|
||||
| `taskMigrationUtils.ts` | `utils/task/task-migration.ts` | Simpler name + kebab-case |
|
||||
| `treeViewUtil.ts` | `utils/ui/tree-view-utils.ts` | Kebab-case consistency |
|
||||
| `viewModeUtils.ts` | `utils/ui/view-mode-utils.ts` | Kebab-case consistency |
|
||||
| `common.ts` | `utils/id-generator.ts` | Descriptive name + kebab-case |
|
||||
|
||||
### Phase 10: Import Path Updates
|
||||
After all files are moved, update all import statements throughout the codebase:
|
||||
|
||||
1. Use automated refactoring tools where possible
|
||||
2. Run TypeScript compiler to identify broken imports
|
||||
3. Update test file imports
|
||||
4. Update barrel exports (index.ts files)
|
||||
5. Verify no circular dependencies were introduced
|
||||
|
||||
### Phase 11: Cleanup
|
||||
1. Remove empty directories
|
||||
2. Delete or update `src/utils/README.md`
|
||||
3. Update any documentation that references old file paths
|
||||
4. Run full test suite to ensure nothing broke
|
||||
|
||||
## Validation Checklist
|
||||
|
||||
- [ ] All directories created successfully
|
||||
- [ ] All files moved to new locations
|
||||
- [ ] All files renamed to kebab-case
|
||||
- [ ] All import paths updated
|
||||
- [ ] TypeScript compilation succeeds
|
||||
- [ ] All tests pass
|
||||
- [ ] No circular dependencies introduced
|
||||
- [ ] Documentation updated
|
||||
- [ ] Commit with detailed message explaining the refactoring
|
||||
|
||||
## Commit Message Template
|
||||
|
||||
```
|
||||
refactor: reorganize directory structure for better maintainability
|
||||
|
||||
BREAKING CHANGE: Major directory restructuring - all import paths updated
|
||||
|
||||
Motivation:
|
||||
- Mixed responsibilities in utils/ directory causing confusion
|
||||
- Inconsistent naming conventions across files
|
||||
- Poor organization making code discovery difficult
|
||||
- Need for clearer separation of concerns
|
||||
|
||||
Changes by category:
|
||||
|
||||
Managers (utils/ → managers/):
|
||||
- Renamed to kebab-case for consistency
|
||||
- FileTaskManager → file-task-manager
|
||||
- TaskGeniusIconManager → icon-manager (simplified)
|
||||
- OnCompletionManager → completion-manager (clarified)
|
||||
|
||||
Services (utils/ → services/):
|
||||
- Separated service classes from utilities
|
||||
- TaskTimerExporter → timer-export-service (clarified purpose)
|
||||
- TaskTimerFormatter → timer-format-service (clarified purpose)
|
||||
|
||||
Executors (utils/onCompletion/ → executors/completion/):
|
||||
- Grouped action executors together
|
||||
- Simplified names (e.g., BaseActionExecutor → base-executor)
|
||||
|
||||
Parsers (various → parsers/):
|
||||
- Consolidated general-purpose parsers
|
||||
- Kept dataflow-specific parsers in dataflow/parsers/
|
||||
|
||||
Core Logic (utils/ → core/):
|
||||
- Moved business logic out of utils
|
||||
- Created goal/ subdirectory for goal-related features
|
||||
|
||||
Cache (utils/ → cache/):
|
||||
- Separated caching utilities
|
||||
- persister → local-storage-cache (descriptive rename)
|
||||
|
||||
Pure Utilities (reorganized in utils/):
|
||||
- Created subdirectories: date/, file/, task/, ui/
|
||||
- Renamed for clarity and consistency
|
||||
- common.ts → id-generator.ts (specific purpose)
|
||||
|
||||
Worker Integration:
|
||||
- Moved worker utilities to dataflow/workers/
|
||||
- Maintains consistency with dataflow architecture
|
||||
|
||||
Benefits:
|
||||
- Clear separation of concerns
|
||||
- Easier code discovery
|
||||
- Consistent naming conventions
|
||||
- Better maintainability
|
||||
- Reduced cognitive load for developers
|
||||
```
|
||||
|
||||
## Notes
|
||||
|
||||
1. **Naming Convention**: All files use kebab-case for consistency
|
||||
2. **Dataflow Preservation**: The existing dataflow architecture is preserved
|
||||
3. **MCP Preservation**: The MCP server structure remains unchanged
|
||||
4. **Gradual Migration**: Can be implemented in phases to minimize disruption
|
||||
5. **Future Consideration**: TaskManager.ts should be split into smaller, focused modules
|
||||
|
||||
## Risk Mitigation
|
||||
|
||||
1. **Create a branch**: `refactor/directory-structure`
|
||||
2. **Implement in small commits**: One phase per commit for easy rollback
|
||||
3. **Run tests after each phase**: Ensure nothing breaks
|
||||
4. **Use automated tools**: VSCode's "Move file" and "Rename Symbol" features
|
||||
5. **Review imports carefully**: Some imports might need manual adjustment
|
||||
6. **Document changes**: Update README and other docs as needed
|
||||
|
||||
## Future Improvements
|
||||
|
||||
After this refactoring:
|
||||
1. Consider splitting `TaskManager.ts` into smaller modules
|
||||
2. Create barrel exports (index.ts) for each major directory
|
||||
3. Add JSDoc comments to clarify module purposes
|
||||
4. Consider dependency injection for better testability
|
||||
5. Evaluate if any managers should become services or vice versa
|
||||
|
|
@ -1,118 +0,0 @@
|
|||
# Editor Extensions Refactoring Plan
|
||||
|
||||
## Overview
|
||||
This document outlines the refactoring of the `editor-ext` directory to improve organization, consistency, and maintainability of editor extension code.
|
||||
|
||||
## Completed on: 2025-01-19
|
||||
|
||||
## Changes Implemented
|
||||
|
||||
### Directory Renaming
|
||||
- **Old**: `src/editor-ext/`
|
||||
- **New**: `src/editor-extensions/`
|
||||
- **Reason**: More complete and professional naming
|
||||
|
||||
### New Directory Structure
|
||||
|
||||
```
|
||||
src/editor-extensions/
|
||||
├── autocomplete/ # Auto-completion and suggestion features
|
||||
│ ├── task-metadata-suggest.ts
|
||||
│ └── parent-task-updater.ts
|
||||
│
|
||||
├── task-operations/ # Task operations (status, cleanup, monitoring)
|
||||
│ ├── status-cycler.ts
|
||||
│ ├── status-switcher.ts
|
||||
│ ├── completion-monitor.ts
|
||||
│ ├── mark-cleanup.ts
|
||||
│ └── gutter-marker.ts
|
||||
│
|
||||
├── date-time/ # Date and time features
|
||||
│ ├── date-picker.ts
|
||||
│ ├── date-manager.ts
|
||||
│ └── task-timer.ts
|
||||
│
|
||||
├── ui-widgets/ # UI decorations and widgets
|
||||
│ ├── progress-bar-widget.ts
|
||||
│ ├── priority-picker.ts
|
||||
│ └── workflow-decorator.ts
|
||||
│
|
||||
├── workflow/ # Workflow features
|
||||
│ ├── workflow-handler.ts
|
||||
│ └── workflow-enter-handler.ts
|
||||
│
|
||||
└── core/ # Core editor functionality
|
||||
├── markdown-editor.ts
|
||||
├── extended-gutter.ts
|
||||
├── regex-cursor.ts
|
||||
├── task-filter-panel.ts
|
||||
└── quick-capture-panel.ts
|
||||
```
|
||||
|
||||
## File Renaming Details
|
||||
|
||||
### Autocomplete
|
||||
| Original | New | Reason |
|
||||
|----------|-----|--------|
|
||||
| QuickCaptureSuggest.ts | task-metadata-suggest.ts | More accurate description of task metadata suggestions |
|
||||
| autoCompleteParent.ts | parent-task-updater.ts | Clearly indicates parent task update functionality |
|
||||
|
||||
### Task Operations
|
||||
| Original | New | Reason |
|
||||
|----------|-----|--------|
|
||||
| cycleCompleteStatus.ts | status-cycler.ts | Simplified name, kebab-case |
|
||||
| taskStatusSwitcher.ts | status-switcher.ts | Kebab-case consistency |
|
||||
| monitorTaskCompleted.ts | completion-monitor.ts | Simplified and clearer |
|
||||
| taskMarkCleanup.ts | mark-cleanup.ts | Simplified name |
|
||||
| TaskGutterHandler.ts | gutter-marker.ts | More accurate description |
|
||||
|
||||
### Date-Time
|
||||
| Original | New | Reason |
|
||||
|----------|-----|--------|
|
||||
| datePicker.ts | date-picker.ts | Kebab-case consistency |
|
||||
| autoDateManager.ts | date-manager.ts | Simplified name |
|
||||
| taskTimer.ts | task-timer.ts | Kebab-case consistency |
|
||||
|
||||
### UI Widgets
|
||||
| Original | New | Reason |
|
||||
|----------|-----|--------|
|
||||
| progressBarWidget.ts | progress-bar-widget.ts | Kebab-case consistency |
|
||||
| priorityPicker.ts | priority-picker.ts | Kebab-case consistency |
|
||||
| workflowDecorator.ts | workflow-decorator.ts | Kebab-case consistency |
|
||||
|
||||
### Workflow
|
||||
| Original | New | Reason |
|
||||
|----------|-----|--------|
|
||||
| workflow.ts | workflow-handler.ts | More explicit name |
|
||||
| workflowRootEnterHandler.ts | workflow-enter-handler.ts | Simplified name |
|
||||
|
||||
### Core
|
||||
| Original | New | Reason |
|
||||
|----------|-----|--------|
|
||||
| markdownEditor.ts | markdown-editor.ts | Kebab-case consistency |
|
||||
| patchedGutter.ts | extended-gutter.ts | More professional name |
|
||||
| regexp-cursor.ts | regex-cursor.ts | Common abbreviation |
|
||||
| filterTasks.ts | task-filter-panel.ts | More explicit name |
|
||||
| quickCapture.ts | quick-capture-panel.ts | More explicit name |
|
||||
|
||||
## Benefits Achieved
|
||||
|
||||
1. **Clear Separation of Concerns**: Each subdirectory now has a specific, well-defined purpose
|
||||
2. **Consistent Naming**: All files use kebab-case naming convention
|
||||
3. **Improved Discoverability**: Developers can easily find functionality based on category
|
||||
4. **Better Maintainability**: Related code is grouped together
|
||||
5. **Professional Structure**: The naming and organization follows modern best practices
|
||||
|
||||
## Migration Impact
|
||||
|
||||
- All import paths have been updated throughout the codebase
|
||||
- No functionality changes, only organizational improvements
|
||||
- Build succeeds with no errors
|
||||
- All tests continue to pass
|
||||
|
||||
## Future Considerations
|
||||
|
||||
1. Consider creating barrel exports (index.ts) for each subdirectory
|
||||
2. Add README files in each subdirectory explaining the purpose and contents
|
||||
3. Consider further splitting large files if they contain multiple responsibilities
|
||||
4. Add JSDoc comments to exported functions for better documentation
|
||||
|
|
@ -1,734 +0,0 @@
|
|||
# Enhanced Time Parsing API Documentation
|
||||
|
||||
## Overview
|
||||
|
||||
The Enhanced Time Parsing API extends Task Genius's existing time parsing capabilities to support granular time recognition including single times, time ranges, and intelligent date inheritance. This document provides comprehensive developer guidance for working with the enhanced time parsing system.
|
||||
|
||||
## Core Interfaces
|
||||
|
||||
### TimeComponent
|
||||
|
||||
The `TimeComponent` interface represents a parsed time value with validation and range support.
|
||||
|
||||
```typescript
|
||||
interface TimeComponent {
|
||||
/** Hour (0-23) */
|
||||
hour: number;
|
||||
/** Minute (0-59) */
|
||||
minute: number;
|
||||
/** Second (0-59, optional) */
|
||||
second?: number;
|
||||
/** Original text that was parsed */
|
||||
originalText: string;
|
||||
/** Whether this is part of a time range */
|
||||
isRange: boolean;
|
||||
/** Range partner (for start/end time pairs) */
|
||||
rangePartner?: TimeComponent;
|
||||
}
|
||||
```
|
||||
|
||||
#### Usage Example
|
||||
|
||||
```typescript
|
||||
// Creating a TimeComponent for 2:30 PM
|
||||
const timeComponent: TimeComponent = {
|
||||
hour: 14,
|
||||
minute: 30,
|
||||
originalText: "2:30 PM",
|
||||
isRange: false
|
||||
};
|
||||
|
||||
// Creating a time range (9:00-17:00)
|
||||
const startTime: TimeComponent = {
|
||||
hour: 9,
|
||||
minute: 0,
|
||||
originalText: "9:00-17:00",
|
||||
isRange: true,
|
||||
rangePartner: endTime
|
||||
};
|
||||
|
||||
const endTime: TimeComponent = {
|
||||
hour: 17,
|
||||
minute: 0,
|
||||
originalText: "9:00-17:00",
|
||||
isRange: true,
|
||||
rangePartner: startTime
|
||||
};
|
||||
```
|
||||
|
||||
### EnhancedParsedTimeResult
|
||||
|
||||
Extends the existing `ParsedTimeResult` to include time component information.
|
||||
|
||||
```typescript
|
||||
interface EnhancedParsedTimeResult extends ParsedTimeResult {
|
||||
// Time-specific components
|
||||
timeComponents: {
|
||||
startTime?: TimeComponent;
|
||||
endTime?: TimeComponent;
|
||||
dueTime?: TimeComponent;
|
||||
scheduledTime?: TimeComponent;
|
||||
};
|
||||
// Enhanced expressions with time information
|
||||
parsedExpressions: Array<EnhancedTimeExpression>;
|
||||
}
|
||||
```
|
||||
|
||||
#### Usage Example
|
||||
|
||||
```typescript
|
||||
import { TimeParsingService } from '../services/time-parsing-service';
|
||||
|
||||
const timeParser = new TimeParsingService();
|
||||
const result: EnhancedParsedTimeResult = await timeParser.parseTimeExpressions(
|
||||
"Meeting tomorrow 2:30 PM - 4:00 PM"
|
||||
);
|
||||
|
||||
// Access parsed time components
|
||||
if (result.timeComponents.startTime) {
|
||||
console.log(`Start: ${result.timeComponents.startTime.hour}:${result.timeComponents.startTime.minute}`);
|
||||
}
|
||||
|
||||
if (result.timeComponents.endTime) {
|
||||
console.log(`End: ${result.timeComponents.endTime.hour}:${result.timeComponents.endTime.minute}`);
|
||||
}
|
||||
```
|
||||
|
||||
### EnhancedTimeExpression
|
||||
|
||||
Represents a parsed time expression with enhanced metadata.
|
||||
|
||||
```typescript
|
||||
interface EnhancedTimeExpression {
|
||||
text: string;
|
||||
date: Date;
|
||||
type: "start" | "due" | "scheduled";
|
||||
index: number;
|
||||
length: number;
|
||||
// New time-specific fields
|
||||
timeComponent?: TimeComponent;
|
||||
isTimeRange: boolean;
|
||||
rangeStart?: TimeComponent;
|
||||
rangeEnd?: TimeComponent;
|
||||
}
|
||||
```
|
||||
|
||||
### EnhancedStandardTaskMetadata
|
||||
|
||||
Extends task metadata to include time components alongside existing timestamp fields.
|
||||
|
||||
```typescript
|
||||
interface EnhancedStandardTaskMetadata extends StandardTaskMetadata {
|
||||
// Time-specific metadata (separate from date timestamps)
|
||||
timeComponents?: {
|
||||
/** Start time component */
|
||||
startTime?: TimeComponent;
|
||||
/** End time component (for time ranges) */
|
||||
endTime?: TimeComponent;
|
||||
/** Due time component */
|
||||
dueTime?: TimeComponent;
|
||||
/** Scheduled time component */
|
||||
scheduledTime?: TimeComponent;
|
||||
};
|
||||
|
||||
// Enhanced date fields that combine date + time
|
||||
enhancedDates?: {
|
||||
/** Full datetime for start (combines startDate + startTime) */
|
||||
startDateTime?: Date;
|
||||
/** Full datetime for end (combines date + endTime) */
|
||||
endDateTime?: Date;
|
||||
/** Full datetime for due (combines dueDate + dueTime) */
|
||||
dueDateTime?: Date;
|
||||
/** Full datetime for scheduled (combines scheduledDate + scheduledTime) */
|
||||
scheduledDateTime?: Date;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## TimeParsingService API
|
||||
|
||||
### Core Methods
|
||||
|
||||
#### parseTimeComponents(text: string): Promise<TimeComponent[]>
|
||||
|
||||
Extracts time components from text without processing dates.
|
||||
|
||||
```typescript
|
||||
const timeParser = new TimeParsingService();
|
||||
|
||||
// Parse single time
|
||||
const singleTime = await timeParser.parseTimeComponents("Meeting at 2:30 PM");
|
||||
// Returns: [{ hour: 14, minute: 30, originalText: "2:30 PM", isRange: false }]
|
||||
|
||||
// Parse time range
|
||||
const timeRange = await timeParser.parseTimeComponents("Workshop 9:00-17:00");
|
||||
// Returns: [
|
||||
// { hour: 9, minute: 0, originalText: "9:00-17:00", isRange: true, rangePartner: endTime },
|
||||
// { hour: 17, minute: 0, originalText: "9:00-17:00", isRange: true, rangePartner: startTime }
|
||||
// ]
|
||||
```
|
||||
|
||||
#### parseTimeExpressions(text: string): Promise<EnhancedParsedTimeResult>
|
||||
|
||||
Enhanced version of the existing method that includes time component parsing.
|
||||
|
||||
```typescript
|
||||
const result = await timeParser.parseTimeExpressions("Project due tomorrow 5:00 PM");
|
||||
|
||||
// Access both date and time information
|
||||
console.log(result.parsedExpressions[0].date); // Date object for tomorrow
|
||||
console.log(result.timeComponents.dueTime?.hour); // 17
|
||||
console.log(result.timeComponents.dueTime?.minute); // 0
|
||||
```
|
||||
|
||||
#### combineDateTime(date: Date, timeComponent: TimeComponent): Date
|
||||
|
||||
Utility method to combine date and time components into a full datetime object.
|
||||
|
||||
```typescript
|
||||
const date = new Date('2024-12-25');
|
||||
const timeComponent: TimeComponent = { hour: 14, minute: 30, originalText: "2:30 PM", isRange: false };
|
||||
|
||||
const combinedDateTime = timeParser.combineDateTime(date, timeComponent);
|
||||
// Returns: Date object for 2024-12-25 14:30:00
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
#### EnhancedTimeParsingConfig
|
||||
|
||||
Configure time parsing behavior through the enhanced configuration interface.
|
||||
|
||||
```typescript
|
||||
interface EnhancedTimeParsingConfig extends TimeParsingConfig {
|
||||
timePatterns: {
|
||||
/** Single time patterns (12:00, 12:00:00, 1:30 PM) */
|
||||
singleTime: RegExp[];
|
||||
/** Time range patterns (12:00-13:00, 12:00 - 13:00, 12:00~13:00) */
|
||||
timeRange: RegExp[];
|
||||
/** Time separators for ranges */
|
||||
rangeSeparators: string[];
|
||||
};
|
||||
timeDefaults: {
|
||||
/** Default format preference (12-hour vs 24-hour) */
|
||||
preferredFormat: "12h" | "24h";
|
||||
/** Default AM/PM when ambiguous */
|
||||
defaultPeriod: "AM" | "PM";
|
||||
/** How to handle midnight crossing ranges */
|
||||
midnightCrossing: "next-day" | "same-day" | "error";
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
#### Usage Example
|
||||
|
||||
```typescript
|
||||
const config: EnhancedTimeParsingConfig = {
|
||||
// ... existing config
|
||||
timeDefaults: {
|
||||
preferredFormat: "24h",
|
||||
defaultPeriod: "AM",
|
||||
midnightCrossing: "next-day"
|
||||
}
|
||||
};
|
||||
|
||||
const timeParser = new TimeParsingService(config);
|
||||
```
|
||||
|
||||
## Date Inheritance API
|
||||
|
||||
### DateInheritanceService
|
||||
|
||||
Handles intelligent date resolution for time-only expressions.
|
||||
|
||||
```typescript
|
||||
interface DateInheritanceService {
|
||||
/** Resolve date for time-only expressions using priority logic */
|
||||
resolveDateForTimeOnly(
|
||||
task: Task,
|
||||
timeComponent: TimeComponent,
|
||||
context: DateResolutionContext
|
||||
): Promise<DateResolutionResult>;
|
||||
|
||||
/** Get file-based date information with caching */
|
||||
getFileDateInfo(filePath: string): Promise<FileDateInfo>;
|
||||
|
||||
/** Extract daily note date from file path/title */
|
||||
extractDailyNoteDate(filePath: string): Date | null;
|
||||
}
|
||||
```
|
||||
|
||||
#### Usage Example
|
||||
|
||||
```typescript
|
||||
import { DateInheritanceService } from '../services/date-inheritance-service';
|
||||
|
||||
const dateService = new DateInheritanceService();
|
||||
|
||||
const context: DateResolutionContext = {
|
||||
currentLine: "- [ ] Meeting 📅 14:30",
|
||||
filePath: "Daily Notes/2024-12-25.md",
|
||||
parentTask: undefined,
|
||||
fileMetadataCache: new Map()
|
||||
};
|
||||
|
||||
const timeComponent: TimeComponent = {
|
||||
hour: 14,
|
||||
minute: 30,
|
||||
originalText: "14:30",
|
||||
isRange: false
|
||||
};
|
||||
|
||||
const result = await dateService.resolveDateForTimeOnly(task, timeComponent, context);
|
||||
console.log(result.resolvedDate); // Date for 2024-12-25 14:30
|
||||
console.log(result.source); // "daily-note-date"
|
||||
console.log(result.confidence); // "high"
|
||||
```
|
||||
|
||||
### DateResolutionContext
|
||||
|
||||
Provides context information for date resolution.
|
||||
|
||||
```typescript
|
||||
interface DateResolutionContext {
|
||||
/** Current line being parsed */
|
||||
currentLine: string;
|
||||
/** File path of the task */
|
||||
filePath: string;
|
||||
/** Parent task information for inheritance */
|
||||
parentTask?: Task;
|
||||
/** File metadata cache */
|
||||
fileMetadataCache?: Map<string, FileDateInfo>;
|
||||
}
|
||||
```
|
||||
|
||||
### DateResolutionResult
|
||||
|
||||
Result of date resolution with metadata about the source and confidence.
|
||||
|
||||
```typescript
|
||||
interface DateResolutionResult {
|
||||
/** Resolved date */
|
||||
resolvedDate: Date;
|
||||
/** Source of the date */
|
||||
source: "line-date" | "metadata-date" | "daily-note-date" | "file-ctime" | "parent-task";
|
||||
/** Confidence level of the resolution */
|
||||
confidence: "high" | "medium" | "low";
|
||||
/** Whether fallback was used */
|
||||
usedFallback: boolean;
|
||||
}
|
||||
```
|
||||
|
||||
## Timeline Integration
|
||||
|
||||
### EnhancedTimelineEvent
|
||||
|
||||
Extended timeline event interface with time information.
|
||||
|
||||
```typescript
|
||||
interface EnhancedTimelineEvent extends TimelineEvent {
|
||||
// Enhanced time information
|
||||
timeInfo?: {
|
||||
/** Primary time for display and sorting */
|
||||
primaryTime: Date;
|
||||
/** End time for ranges */
|
||||
endTime?: Date;
|
||||
/** Whether this is a time range */
|
||||
isRange: boolean;
|
||||
/** Original time component from parsing */
|
||||
timeComponent?: TimeComponent;
|
||||
/** Display format preference */
|
||||
displayFormat: "time-only" | "date-time" | "range";
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
#### Usage Example
|
||||
|
||||
```typescript
|
||||
// Creating an enhanced timeline event
|
||||
const timelineEvent: EnhancedTimelineEvent = {
|
||||
// ... existing TimelineEvent properties
|
||||
timeInfo: {
|
||||
primaryTime: new Date('2024-12-25T14:30:00'),
|
||||
endTime: new Date('2024-12-25T16:00:00'),
|
||||
isRange: true,
|
||||
timeComponent: startTimeComponent,
|
||||
displayFormat: "range"
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
### TimeParsingError
|
||||
|
||||
Structured error information for time parsing failures.
|
||||
|
||||
```typescript
|
||||
interface TimeParsingError {
|
||||
type: "invalid-format" | "midnight-crossing" | "ambiguous-time" | "range-error";
|
||||
originalText: string;
|
||||
position: number;
|
||||
message: string;
|
||||
fallbackUsed: boolean;
|
||||
fallbackValue?: TimeComponent;
|
||||
}
|
||||
```
|
||||
|
||||
### EnhancedParseResult
|
||||
|
||||
Comprehensive result structure with error handling.
|
||||
|
||||
```typescript
|
||||
interface EnhancedParseResult {
|
||||
success: boolean;
|
||||
result?: EnhancedParsedTimeResult;
|
||||
errors: TimeParsingError[];
|
||||
warnings: string[];
|
||||
}
|
||||
```
|
||||
|
||||
#### Usage Example
|
||||
|
||||
```typescript
|
||||
const parseResult: EnhancedParseResult = await timeParser.parseWithErrorHandling(
|
||||
"Invalid time format 25:70"
|
||||
);
|
||||
|
||||
if (!parseResult.success) {
|
||||
parseResult.errors.forEach(error => {
|
||||
console.error(`Time parsing error: ${error.message}`);
|
||||
if (error.fallbackUsed && error.fallbackValue) {
|
||||
console.log(`Using fallback: ${error.fallbackValue.hour}:${error.fallbackValue.minute}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## Migration Strategies
|
||||
|
||||
### Automatic Task Enhancement
|
||||
|
||||
Existing tasks are automatically enhanced when accessed through the new API:
|
||||
|
||||
```typescript
|
||||
import { TaskMigrationService } from '../services/task-migration-service';
|
||||
|
||||
const migrationService = new TaskMigrationService();
|
||||
|
||||
// Migrate existing task to enhanced format
|
||||
const enhancedTask = migrationService.migrateTaskToEnhanced(existingTask);
|
||||
|
||||
// Check if task has enhanced metadata
|
||||
if (enhancedTask.metadata.timeComponents) {
|
||||
console.log("Task has enhanced time information");
|
||||
}
|
||||
```
|
||||
|
||||
### Backward Compatibility
|
||||
|
||||
The enhanced API maintains full backward compatibility:
|
||||
|
||||
```typescript
|
||||
// Existing code continues to work
|
||||
const oldResult = await timeParser.parseTimeExpressions("tomorrow 5pm");
|
||||
console.log(oldResult.parsedExpressions[0].date); // Still works
|
||||
|
||||
// New features are additive
|
||||
if (oldResult.timeComponents?.dueTime) {
|
||||
console.log("Enhanced time info available");
|
||||
}
|
||||
```
|
||||
|
||||
### Gradual Migration
|
||||
|
||||
For large codebases, migrate incrementally:
|
||||
|
||||
```typescript
|
||||
// 1. Update type annotations to enhanced interfaces
|
||||
function processTask(task: Task<EnhancedStandardTaskMetadata>) {
|
||||
// Enhanced functionality available
|
||||
if (task.metadata.timeComponents?.startTime) {
|
||||
// Use enhanced time information
|
||||
} else {
|
||||
// Fall back to existing timestamp-based logic
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Update parsing calls to use enhanced methods
|
||||
const result = await timeParser.parseTimeExpressions(text);
|
||||
// Enhanced result includes both old and new fields
|
||||
|
||||
// 3. Update UI components to display enhanced information
|
||||
if (result.timeComponents?.startTime) {
|
||||
displayEnhancedTime(result.timeComponents.startTime);
|
||||
} else {
|
||||
displayBasicTime(result.parsedExpressions[0].date);
|
||||
}
|
||||
```
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
### Caching Strategies
|
||||
|
||||
The enhanced time parsing system includes several performance optimizations:
|
||||
|
||||
```typescript
|
||||
// File metadata caching
|
||||
const fileCache = new Map<string, FileDateInfo>();
|
||||
const context: DateResolutionContext = {
|
||||
// ... other properties
|
||||
fileMetadataCache: fileCache
|
||||
};
|
||||
|
||||
// Reuse cache across multiple parsing operations
|
||||
const result1 = await dateService.resolveDateForTimeOnly(task1, time1, context);
|
||||
const result2 = await dateService.resolveDateForTimeOnly(task2, time2, context);
|
||||
```
|
||||
|
||||
### Batch Processing
|
||||
|
||||
For processing multiple tasks efficiently:
|
||||
|
||||
```typescript
|
||||
// Batch process tasks with shared context
|
||||
const tasks = await getAllTasks();
|
||||
const batchContext = await createBatchContext(tasks);
|
||||
|
||||
const enhancedTasks = await Promise.all(
|
||||
tasks.map(task => enhanceTaskWithTimeInfo(task, batchContext))
|
||||
);
|
||||
```
|
||||
|
||||
### Memory Management
|
||||
|
||||
Time components are lightweight objects, but for large datasets:
|
||||
|
||||
```typescript
|
||||
// Use weak references for temporary time components
|
||||
const timeComponentCache = new WeakMap<Task, TimeComponent[]>();
|
||||
|
||||
// Clean up enhanced metadata when not needed
|
||||
function cleanupEnhancedMetadata(task: Task) {
|
||||
if (task.metadata.enhancedDates) {
|
||||
delete task.metadata.enhancedDates;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Testing Utilities
|
||||
|
||||
### Mock Time Components
|
||||
|
||||
```typescript
|
||||
// Test utilities for creating mock time components
|
||||
export function createMockTimeComponent(
|
||||
hour: number,
|
||||
minute: number,
|
||||
options: Partial<TimeComponent> = {}
|
||||
): TimeComponent {
|
||||
return {
|
||||
hour,
|
||||
minute,
|
||||
originalText: `${hour}:${minute.toString().padStart(2, '0')}`,
|
||||
isRange: false,
|
||||
...options
|
||||
};
|
||||
}
|
||||
|
||||
// Create mock time ranges
|
||||
export function createMockTimeRange(
|
||||
startHour: number,
|
||||
startMinute: number,
|
||||
endHour: number,
|
||||
endMinute: number
|
||||
): [TimeComponent, TimeComponent] {
|
||||
const originalText = `${startHour}:${startMinute}-${endHour}:${endMinute}`;
|
||||
|
||||
const startTime: TimeComponent = {
|
||||
hour: startHour,
|
||||
minute: startMinute,
|
||||
originalText,
|
||||
isRange: true,
|
||||
rangePartner: undefined // Will be set below
|
||||
};
|
||||
|
||||
const endTime: TimeComponent = {
|
||||
hour: endHour,
|
||||
minute: endMinute,
|
||||
originalText,
|
||||
isRange: true,
|
||||
rangePartner: startTime
|
||||
};
|
||||
|
||||
startTime.rangePartner = endTime;
|
||||
|
||||
return [startTime, endTime];
|
||||
}
|
||||
```
|
||||
|
||||
### Test Examples
|
||||
|
||||
```typescript
|
||||
describe('Enhanced Time Parsing', () => {
|
||||
let timeParser: TimeParsingService;
|
||||
|
||||
beforeEach(() => {
|
||||
timeParser = new TimeParsingService();
|
||||
});
|
||||
|
||||
test('should parse single time correctly', async () => {
|
||||
const result = await timeParser.parseTimeComponents("Meeting at 2:30 PM");
|
||||
|
||||
expect(result).toHaveLength(1);
|
||||
expect(result[0].hour).toBe(14);
|
||||
expect(result[0].minute).toBe(30);
|
||||
expect(result[0].isRange).toBe(false);
|
||||
});
|
||||
|
||||
test('should parse time range correctly', async () => {
|
||||
const result = await timeParser.parseTimeComponents("Workshop 9:00-17:00");
|
||||
|
||||
expect(result).toHaveLength(2);
|
||||
expect(result[0].hour).toBe(9);
|
||||
expect(result[1].hour).toBe(17);
|
||||
expect(result[0].isRange).toBe(true);
|
||||
expect(result[1].isRange).toBe(true);
|
||||
expect(result[0].rangePartner).toBe(result[1]);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### API Usage
|
||||
|
||||
1. **Always check for enhanced metadata availability**:
|
||||
```typescript
|
||||
if (task.metadata.timeComponents?.startTime) {
|
||||
// Use enhanced time information
|
||||
} else {
|
||||
// Fall back to timestamp-based logic
|
||||
}
|
||||
```
|
||||
|
||||
2. **Use type guards for enhanced interfaces**:
|
||||
```typescript
|
||||
function isEnhancedTask(task: Task): task is Task<EnhancedStandardTaskMetadata> {
|
||||
return 'timeComponents' in task.metadata;
|
||||
}
|
||||
```
|
||||
|
||||
3. **Handle errors gracefully**:
|
||||
```typescript
|
||||
try {
|
||||
const result = await timeParser.parseTimeExpressions(text);
|
||||
// Process result
|
||||
} catch (error) {
|
||||
// Fall back to basic date parsing
|
||||
const basicResult = await timeParser.parseBasicDates(text);
|
||||
}
|
||||
```
|
||||
|
||||
### Performance Optimization
|
||||
|
||||
1. **Cache file metadata for batch operations**
|
||||
2. **Use lazy loading for enhanced metadata**
|
||||
3. **Implement proper cleanup for temporary objects**
|
||||
4. **Consider memory usage in large datasets**
|
||||
|
||||
### Integration Guidelines
|
||||
|
||||
1. **Maintain backward compatibility in all public APIs**
|
||||
2. **Provide migration utilities for existing integrations**
|
||||
3. **Document breaking changes clearly**
|
||||
4. **Use feature flags for gradual rollout**
|
||||
|
||||
## Examples and Recipes
|
||||
|
||||
### Common Integration Patterns
|
||||
|
||||
#### Task Creation with Enhanced Time Parsing
|
||||
|
||||
```typescript
|
||||
async function createTaskWithTime(text: string, filePath: string): Promise<Task> {
|
||||
const timeParser = new TimeParsingService();
|
||||
const dateService = new DateInheritanceService();
|
||||
|
||||
// Parse time expressions
|
||||
const parseResult = await timeParser.parseTimeExpressions(text);
|
||||
|
||||
// Create base task
|
||||
const task: Task = {
|
||||
// ... basic task properties
|
||||
metadata: {
|
||||
// ... basic metadata
|
||||
}
|
||||
};
|
||||
|
||||
// Add enhanced time information if available
|
||||
if (parseResult.timeComponents) {
|
||||
const enhancedMetadata: EnhancedStandardTaskMetadata = {
|
||||
...task.metadata,
|
||||
timeComponents: parseResult.timeComponents
|
||||
};
|
||||
|
||||
// Resolve dates for time-only expressions
|
||||
if (parseResult.timeComponents.startTime && !parseResult.parsedExpressions[0]?.date) {
|
||||
const context: DateResolutionContext = {
|
||||
currentLine: text,
|
||||
filePath,
|
||||
parentTask: undefined
|
||||
};
|
||||
|
||||
const dateResult = await dateService.resolveDateForTimeOnly(
|
||||
task,
|
||||
parseResult.timeComponents.startTime,
|
||||
context
|
||||
);
|
||||
|
||||
enhancedMetadata.enhancedDates = {
|
||||
startDateTime: timeParser.combineDateTime(
|
||||
dateResult.resolvedDate,
|
||||
parseResult.timeComponents.startTime
|
||||
)
|
||||
};
|
||||
}
|
||||
|
||||
task.metadata = enhancedMetadata;
|
||||
}
|
||||
|
||||
return task;
|
||||
}
|
||||
```
|
||||
|
||||
#### Timeline Event Enhancement
|
||||
|
||||
```typescript
|
||||
function createEnhancedTimelineEvent(task: Task): EnhancedTimelineEvent {
|
||||
const baseEvent: TimelineEvent = {
|
||||
// ... create base timeline event
|
||||
};
|
||||
|
||||
if (isEnhancedTask(task) && task.metadata.timeComponents?.startTime) {
|
||||
const timeComponent = task.metadata.timeComponents.startTime;
|
||||
const enhancedEvent: EnhancedTimelineEvent = {
|
||||
...baseEvent,
|
||||
timeInfo: {
|
||||
primaryTime: task.metadata.enhancedDates?.startDateTime || baseEvent.date,
|
||||
endTime: task.metadata.enhancedDates?.endDateTime,
|
||||
isRange: timeComponent.isRange,
|
||||
timeComponent,
|
||||
displayFormat: timeComponent.isRange ? "range" : "time-only"
|
||||
}
|
||||
};
|
||||
|
||||
return enhancedEvent;
|
||||
}
|
||||
|
||||
return baseEvent;
|
||||
}
|
||||
```
|
||||
|
||||
This comprehensive API documentation provides developers with all the necessary information to integrate with and extend the enhanced time parsing system while maintaining backward compatibility and following best practices.
|
||||
|
|
@ -1,487 +0,0 @@
|
|||
# FileSource Implementation Tracking
|
||||
|
||||
## Overview
|
||||
|
||||
This document tracks the implementation progress of the FileSource feature, which enables files to be recognized as tasks based on their metadata properties. The implementation follows the dataflow architecture patterns and integrates seamlessly with existing functionality.
|
||||
|
||||
## Task Breakdown
|
||||
|
||||
### Phase 1: Core Infrastructure (Week 1-2)
|
||||
|
||||
#### TypeScript Definitions
|
||||
- [x] Create `src/types/file-source.d.ts`
|
||||
- [x] `FileSourceTaskMetadata` interface
|
||||
- [x] `FileSourceConfiguration` interface
|
||||
- [x] `RecognitionStrategy` interface
|
||||
- [x] `FileSourceStats` interface
|
||||
- [x] Recognition strategy type definitions
|
||||
|
||||
#### Configuration Management
|
||||
- [x] Create `src/dataflow/sources/FileSourceConfig.ts`
|
||||
- [x] Configuration validation logic
|
||||
- [x] Default configuration constants
|
||||
- [x] Configuration update handlers
|
||||
- [x] Strategy-specific configuration management
|
||||
|
||||
#### Basic FileSource Implementation
|
||||
- [x] Create `src/dataflow/sources/FileSource.ts`
|
||||
- [x] Basic source initialization
|
||||
- [x] Event subscription to FILE_UPDATED
|
||||
- [ ] Granular event subscriptions (FILE_METADATA_CHANGED, FILE_CONTENT_CHANGED)
|
||||
- [x] Basic file task detection
|
||||
- [x] Smart update detection integration (basic implementation)
|
||||
- [x] Selective property updates (updateFileTaskProperties)
|
||||
- [x] Selective children updates (updateFileTaskChildren)
|
||||
- [x] Event emission for file task updates
|
||||
- [x] Basic cleanup and destroy methods
|
||||
|
||||
#### Settings Integration
|
||||
- [x] Update `src/common/setting-definition.ts`
|
||||
- [x] Add FileSourceConfiguration to TaskProgressBarSettings
|
||||
- [x] Update DEFAULT_SETTINGS with FileSource defaults
|
||||
- [x] Add validation for FileSource settings
|
||||
|
||||
- [x] Create settings UI components
|
||||
- [x] `src/components/settings/FileSourceSettings.ts`
|
||||
- [x] Recognition strategy configuration panels
|
||||
- [x] File task properties configuration
|
||||
- [x] Performance settings interface
|
||||
|
||||
#### Unit Tests
|
||||
- [x] Create `src/__tests__/file-source/`
|
||||
- [x] `FileSourceConfig.test.ts` - Configuration validation tests
|
||||
- [x] `FileSource.basic.test.ts` - Basic functionality tests
|
||||
- [ ] `FileSourceUpdateDetector.test.ts` - Update detection logic tests (Phase 2)
|
||||
- [ ] Test metadata change detection
|
||||
- [ ] Test content change detection
|
||||
- [ ] Test children structure detection
|
||||
- [ ] Test hash comparison logic
|
||||
- [ ] `RecognitionStrategies.test.ts` - Strategy testing framework (Phase 2)
|
||||
|
||||
### Phase 2: Recognition Strategies (Week 3-4)
|
||||
|
||||
#### Update Detection System
|
||||
- [ ] Create `src/dataflow/sources/FileSourceUpdateDetector.ts`
|
||||
- [ ] Update decision logic implementation
|
||||
- [ ] Change type analysis (metadata vs content)
|
||||
- [ ] Children structure change detection
|
||||
- [ ] Previous state caching mechanism
|
||||
- [ ] Hash-based property comparison
|
||||
- [ ] Performance metrics collection
|
||||
|
||||
#### Core Parser Implementation
|
||||
- [ ] Create `src/dataflow/parsers/FileSourceParser.ts`
|
||||
- [ ] Base recognition strategy framework
|
||||
- [ ] Metadata extraction utilities
|
||||
- [ ] File content analysis helpers
|
||||
- [ ] Strategy result aggregation
|
||||
- [ ] Selective parsing for updates
|
||||
|
||||
#### Metadata-Based Recognition
|
||||
- [ ] Implement metadata recognition strategy
|
||||
- [ ] Frontmatter field checking
|
||||
- [ ] Required vs optional field logic
|
||||
- [ ] Metadata validation and parsing
|
||||
- [ ] Default value assignment
|
||||
|
||||
#### Tag-Based Recognition
|
||||
- [ ] Implement tag recognition strategy
|
||||
- [ ] Tag pattern matching (exact, prefix, contains)
|
||||
- [ ] Tag extraction from file cache
|
||||
- [ ] Multiple tag requirement logic
|
||||
- [ ] Tag-based metadata extraction
|
||||
|
||||
#### Template-Based Recognition
|
||||
- [ ] Implement template recognition strategy
|
||||
- [ ] Template path matching
|
||||
- [ ] Template metadata inheritance
|
||||
- [ ] Template instance detection
|
||||
- [ ] Template-specific configuration
|
||||
|
||||
#### Path-Based Recognition
|
||||
- [ ] Implement path recognition strategy
|
||||
- [ ] Path pattern matching (prefix, regex, glob)
|
||||
- [ ] Path-based metadata assignment
|
||||
- [ ] Exclude pattern handling
|
||||
- [ ] Path hierarchy analysis
|
||||
|
||||
#### Parser Entry Point
|
||||
- [ ] Create `src/dataflow/parsers/FileSourceEntry.ts`
|
||||
- [ ] Integration with existing parser architecture
|
||||
- [ ] Strategy orchestration
|
||||
- [ ] Result merging and conflict resolution
|
||||
- [ ] Performance optimization
|
||||
|
||||
#### Strategy Testing
|
||||
- [ ] Comprehensive strategy tests
|
||||
- [ ] `MetadataStrategy.test.ts`
|
||||
- [ ] `TagStrategy.test.ts`
|
||||
- [ ] `TemplateStrategy.test.ts`
|
||||
- [ ] `PathStrategy.test.ts`
|
||||
- [ ] Strategy integration tests
|
||||
|
||||
### Phase 3: Integration & Augmentation (Week 5-6)
|
||||
|
||||
#### File Task Augmentation
|
||||
- [ ] Create `src/dataflow/augment/FileSourceAugmentor.ts`
|
||||
- [ ] File task metadata enhancement
|
||||
- [ ] Child task relationship building
|
||||
- [ ] Metadata inheritance implementation
|
||||
- [ ] Project data integration
|
||||
|
||||
#### Repository Integration
|
||||
- [ ] Update `src/dataflow/indexer/Repository.ts`
|
||||
- [ ] File task storage and indexing
|
||||
- [ ] File task query methods
|
||||
- [ ] Integration with existing task cache
|
||||
- [ ] Event handling for file task updates
|
||||
|
||||
#### Event System Integration
|
||||
- [ ] Update `src/dataflow/events/Events.ts`
|
||||
- [ ] Add FileSource event types
|
||||
- [ ] Add granular update events (FILE_METADATA_CHANGED, FILE_CONTENT_CHANGED)
|
||||
- [ ] Add specific file task events (FILE_TASK_PROPERTY_CHANGED, FILE_TASK_CHILDREN_CHANGED)
|
||||
- [ ] Add INLINE_TASK_CONTENT_CHANGED event
|
||||
- [ ] Event payload definitions
|
||||
- [ ] Sequence tracking for file tasks
|
||||
|
||||
- [ ] Update `src/dataflow/Orchestrator.ts`
|
||||
- [ ] FileSource initialization
|
||||
- [ ] Event routing for file tasks
|
||||
- [ ] Integration with existing sources
|
||||
- [ ] Granular event handling logic
|
||||
|
||||
#### Child Task Relationships
|
||||
- [ ] Implement child task management
|
||||
- [ ] Parent-child relationship tracking
|
||||
- [ ] Child task discovery within files
|
||||
- [ ] Relationship updates on file changes
|
||||
- [ ] Orphaned task cleanup
|
||||
|
||||
#### Metadata Inheritance System
|
||||
- [ ] Implement inheritance logic
|
||||
- [ ] Configurable inheritance fields
|
||||
- [ ] Inheritance priority resolution
|
||||
- [ ] Update propagation to child tasks
|
||||
- [ ] Inheritance conflict resolution
|
||||
|
||||
#### Integration Tests
|
||||
- [ ] End-to-end integration testing
|
||||
- [ ] `FileSourceDataflow.test.ts`
|
||||
- [ ] `FileTaskRelationships.test.ts`
|
||||
- [ ] `MetadataInheritance.test.ts`
|
||||
- [ ] `EventFlow.test.ts`
|
||||
|
||||
### Phase 4: Performance & Polish (Week 7-8)
|
||||
|
||||
#### Specialized Indexing
|
||||
- [ ] Create `src/dataflow/indexer/FileSourceIndex.ts`
|
||||
- [ ] Optimized file task indexing
|
||||
- [ ] Fast lookup structures
|
||||
- [ ] Batch update operations
|
||||
- [ ] Memory-efficient storage
|
||||
|
||||
#### Worker Integration
|
||||
- [ ] Update worker system for file tasks
|
||||
- [ ] `src/dataflow/workers/FileSourceWorker.ts`
|
||||
- [ ] Background file task processing
|
||||
- [ ] Worker message protocol
|
||||
- [ ] Performance monitoring
|
||||
|
||||
#### Caching Implementation
|
||||
- [ ] Create `src/dataflow/indexer/FileTaskCache.ts`
|
||||
- [ ] File task state caching structure
|
||||
- [ ] Frontmatter hash implementation
|
||||
- [ ] Children ID set management
|
||||
- [ ] Recognition result caching
|
||||
- [ ] TTL-based cache invalidation
|
||||
- [ ] Memory usage optimization
|
||||
- [ ] Cache performance metrics
|
||||
- [ ] State comparison utilities
|
||||
|
||||
#### Settings UI Enhancement
|
||||
- [ ] Advanced settings components
|
||||
- [ ] Strategy priority configuration
|
||||
- [ ] Custom recognition function editor
|
||||
- [ ] Performance tuning interface
|
||||
- [ ] Diagnostic tools
|
||||
|
||||
#### Performance Testing
|
||||
- [ ] Performance benchmark suite
|
||||
- [ ] Large vault testing (1000+ files)
|
||||
- [ ] Recognition performance metrics
|
||||
- [ ] Memory usage profiling
|
||||
- [ ] Worker performance validation
|
||||
- [ ] Update detection performance tests
|
||||
- [ ] Rapid file changes scenario
|
||||
- [ ] Large file with many tasks
|
||||
- [ ] Metadata-only updates
|
||||
- [ ] Content-only updates
|
||||
- [ ] Mixed update patterns
|
||||
- [ ] `PerformanceOptimization.test.ts`
|
||||
- [ ] Test early exit patterns
|
||||
- [ ] Test selective processing
|
||||
- [ ] Test cache hit rates
|
||||
- [ ] Test event deduplication
|
||||
|
||||
#### Documentation
|
||||
- [ ] User documentation
|
||||
- [ ] Feature overview guide
|
||||
- [ ] Configuration examples
|
||||
- [ ] Troubleshooting guide
|
||||
- [ ] Best practices document
|
||||
|
||||
### Phase 5: Advanced Features (Week 9-10)
|
||||
|
||||
#### Custom Recognition Functions
|
||||
- [ ] Implement custom function support
|
||||
- [ ] JavaScript function parsing
|
||||
- [ ] Sandboxed execution environment
|
||||
- [ ] Function validation and testing
|
||||
- [ ] Error handling and logging
|
||||
|
||||
#### Advanced Conflict Resolution
|
||||
- [ ] Sophisticated conflict handling
|
||||
- [ ] Dual role (project/task) management
|
||||
- [ ] Metadata priority rules
|
||||
- [ ] User-defined resolution strategies
|
||||
- [ ] Conflict notification system
|
||||
|
||||
#### Bulk Operations
|
||||
- [ ] Bulk file task operations
|
||||
- [ ] Batch file task creation
|
||||
- [ ] Bulk metadata updates
|
||||
- [ ] Batch recognition re-evaluation
|
||||
- [ ] Progress reporting for bulk ops
|
||||
|
||||
#### Export/Import Functionality
|
||||
- [ ] File task data portability
|
||||
- [ ] Export file task configurations
|
||||
- [ ] Import recognition strategies
|
||||
- [ ] Backup and restore functionality
|
||||
- [ ] Migration tools
|
||||
|
||||
#### Advanced Filtering
|
||||
- [ ] Enhanced query capabilities
|
||||
- [ ] File task specific filters
|
||||
- [ ] Recognition strategy filtering
|
||||
- [ ] Child task aggregation filters
|
||||
- [ ] Custom filter expressions
|
||||
|
||||
## File Structure and Components
|
||||
|
||||
### New Files to Create
|
||||
|
||||
```
|
||||
src/
|
||||
├── types/
|
||||
│ └── file-source.d.ts # Core type definitions
|
||||
├── dataflow/
|
||||
│ ├── sources/
|
||||
│ │ ├── FileSource.ts # Main FileSource implementation
|
||||
│ │ ├── FileSourceConfig.ts # Configuration management
|
||||
│ │ └── FileSourceUpdateDetector.ts # Update detection logic
|
||||
│ ├── parsers/
|
||||
│ │ ├── FileSourceEntry.ts # Parser entry point
|
||||
│ │ └── FileSourceParser.ts # Recognition strategies
|
||||
│ ├── augment/
|
||||
│ │ └── FileSourceAugmentor.ts # File task augmentation
|
||||
│ ├── indexer/
|
||||
│ │ ├── FileSourceIndex.ts # Specialized indexing
|
||||
│ │ └── FileTaskCache.ts # File task state caching
|
||||
│ └── workers/
|
||||
│ └── FileSourceWorker.ts # Background processing
|
||||
├── components/
|
||||
│ └── settings/
|
||||
│ └── FileSourceSettings.ts # Settings UI
|
||||
└── __tests__/
|
||||
└── file-source/
|
||||
├── FileSourceConfig.test.ts
|
||||
├── FileSource.basic.test.ts
|
||||
├── FileSourceUpdateDetector.test.ts
|
||||
├── RecognitionStrategies.test.ts
|
||||
├── MetadataStrategy.test.ts
|
||||
├── TagStrategy.test.ts
|
||||
├── TemplateStrategy.test.ts
|
||||
├── PathStrategy.test.ts
|
||||
├── FileSourceDataflow.test.ts
|
||||
├── FileTaskRelationships.test.ts
|
||||
├── MetadataInheritance.test.ts
|
||||
├── EventFlow.test.ts
|
||||
└── PerformanceOptimization.test.ts
|
||||
```
|
||||
|
||||
### Files to Modify
|
||||
|
||||
```
|
||||
src/
|
||||
├── common/
|
||||
│ └── setting-definition.ts # Add FileSource configuration
|
||||
├── dataflow/
|
||||
│ ├── events/
|
||||
│ │ └── Events.ts # Add FileSource events and granular update events
|
||||
│ ├── sources/
|
||||
│ │ └── ObsidianSource.ts # Emit granular events (FILE_METADATA_CHANGED, FILE_CONTENT_CHANGED)
|
||||
│ ├── indexer/
|
||||
│ │ └── Repository.ts # File task integration
|
||||
│ ├── Orchestrator.ts # FileSource initialization
|
||||
│ └── createDataflow.ts # Factory updates
|
||||
├── components/
|
||||
│ └── settings/
|
||||
│ └── TaskProgressBarSettingTab.ts # Settings integration
|
||||
└── index.ts # Plugin initialization
|
||||
```
|
||||
|
||||
## Dependencies and Integration Points
|
||||
|
||||
### Internal Dependencies
|
||||
|
||||
- **Dataflow Architecture**: Core event system, repository, orchestrator
|
||||
- **Project System**: Resolver, ProjectConfigManager, ProjectDataCache
|
||||
- **Task System**: Task types, metadata, parsing infrastructure
|
||||
- **Settings System**: Setting definitions, UI components, validation
|
||||
- **Worker System**: TaskWorkerManager, worker orchestration
|
||||
|
||||
### External Dependencies
|
||||
|
||||
- **Obsidian API**: Vault, MetadataCache, TFile, FileSystemAdapter
|
||||
- **File System**: Path manipulation, file watching, metadata extraction
|
||||
- **Performance**: Worker threads, caching, batch processing
|
||||
|
||||
### Integration Points
|
||||
|
||||
1. **Event System**: FILE_UPDATED → FileSource → FILE_TASK_UPDATED
|
||||
2. **Repository**: File task storage alongside regular tasks
|
||||
3. **QueryAPI**: Extended queries for file tasks
|
||||
4. **Views**: File tasks displayed in all task views
|
||||
5. **Project System**: Dual role management and conflict resolution
|
||||
|
||||
## Progress Tracking Sections
|
||||
|
||||
### Week 1-2: Core Infrastructure
|
||||
**Status**: ✅ Completed
|
||||
**Target Completion**: 2025-08-20
|
||||
**Completion**: 20/25 tasks (80% - Core functionality complete)
|
||||
|
||||
**Priority Tasks**:
|
||||
- [x] Core type definitions
|
||||
- [x] Basic FileSource implementation
|
||||
- [x] Settings integration
|
||||
- [x] Initial unit tests
|
||||
|
||||
**Implementation Notes**:
|
||||
- Core FileSource infrastructure is fully functional
|
||||
- Metadata and tag-based recognition strategies implemented
|
||||
- Comprehensive configuration system with validation
|
||||
- Full test coverage for core components
|
||||
- TypeScript compilation passing without errors
|
||||
- Ready for Phase 2 implementation
|
||||
|
||||
### Week 3-4: Recognition Strategies
|
||||
**Status**: ⏳ Not Started
|
||||
**Target Completion**: [Date]
|
||||
**Completion**: 0/18 tasks
|
||||
|
||||
**Priority Tasks**:
|
||||
- [ ] Metadata-based recognition
|
||||
- [ ] Tag-based recognition
|
||||
- [ ] Strategy testing framework
|
||||
- [ ] Parser entry point
|
||||
|
||||
### Week 5-6: Integration & Augmentation
|
||||
**Status**: ⏳ Not Started
|
||||
**Target Completion**: [Date]
|
||||
**Completion**: 0/22 tasks
|
||||
|
||||
**Priority Tasks**:
|
||||
- [ ] Repository integration
|
||||
- [ ] Event system integration
|
||||
- [ ] Child task relationships
|
||||
- [ ] Metadata inheritance
|
||||
|
||||
### Week 7-8: Performance & Polish
|
||||
**Status**: ⏳ Not Started
|
||||
**Target Completion**: [Date]
|
||||
**Completion**: 0/18 tasks
|
||||
|
||||
**Priority Tasks**:
|
||||
- [ ] Worker integration
|
||||
- [ ] Caching implementation
|
||||
- [ ] Performance testing
|
||||
- [ ] User documentation
|
||||
|
||||
### Week 9-10: Advanced Features
|
||||
**Status**: ⏳ Not Started
|
||||
**Target Completion**: [Date]
|
||||
**Completion**: 0/15 tasks
|
||||
|
||||
**Priority Tasks**:
|
||||
- [ ] Custom recognition functions
|
||||
- [ ] Bulk operations
|
||||
- [ ] Advanced filtering
|
||||
- [ ] Export/import functionality
|
||||
|
||||
## Risk Assessment
|
||||
|
||||
### High Risk Items
|
||||
- **Performance Impact**: Large vaults with many files could impact startup time
|
||||
- *Mitigation*: Worker-based processing, selective file scanning, caching
|
||||
- **Memory Usage**: File tasks add to memory footprint
|
||||
- *Mitigation*: Efficient indexing, lazy loading, configurable limits
|
||||
- **Conflict Resolution**: Dual role files may create complex scenarios
|
||||
- *Mitigation*: Clear precedence rules, user configuration options
|
||||
|
||||
### Medium Risk Items
|
||||
- **Configuration Complexity**: Many options may overwhelm users
|
||||
- *Mitigation*: Sensible defaults, configuration wizard, presets
|
||||
- **Event Loop Performance**: Additional event processing overhead
|
||||
- *Mitigation*: Debounced events, batch processing, sequence optimization
|
||||
|
||||
### Low Risk Items
|
||||
- **Backward Compatibility**: New feature shouldn't break existing functionality
|
||||
- *Mitigation*: Feature flag, disabled by default, comprehensive testing
|
||||
|
||||
## Success Metrics
|
||||
|
||||
### Functional Metrics
|
||||
- [ ] All recognition strategies working correctly
|
||||
- [ ] File tasks appear in all relevant views
|
||||
- [ ] Child task relationships functioning
|
||||
- [ ] Metadata inheritance working
|
||||
- [ ] Settings interface complete and intuitive
|
||||
|
||||
### Performance Metrics
|
||||
- [ ] File task detection under 100ms for typical files
|
||||
- [ ] Memory usage increase under 10% for equivalent functionality
|
||||
- [ ] No noticeable impact on plugin startup time
|
||||
- [ ] Worker processing provides measurable performance benefits
|
||||
|
||||
### Quality Metrics
|
||||
- [ ] 90%+ test coverage for FileSource components
|
||||
- [ ] Zero regression in existing functionality
|
||||
- [ ] User documentation complete and clear
|
||||
- [ ] Configuration examples working as documented
|
||||
|
||||
## Notes and Decisions
|
||||
|
||||
### Architecture Decisions
|
||||
- **FileSource as separate source**: Maintains clean separation from ObsidianSource
|
||||
- **Event-driven integration**: Leverages existing event system for consistency
|
||||
- **Strategy pattern**: Allows flexible recognition approaches
|
||||
- **Metadata extension**: Extends existing task metadata rather than creating new types
|
||||
|
||||
### Configuration Decisions
|
||||
- **Disabled by default**: Conservative rollout approach
|
||||
- **Multiple strategies**: Accommodates different user workflows
|
||||
- **Extensive configuration**: Provides flexibility while maintaining usability
|
||||
|
||||
### Performance Decisions
|
||||
- **Worker integration**: Maintains UI responsiveness
|
||||
- **Caching strategy**: Balances memory usage with performance
|
||||
- **Selective processing**: Avoid processing irrelevant files
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: [Current Date]
|
||||
**Document Version**: 1.0
|
||||
**Next Review**: [Date]
|
||||
|
|
@ -1,613 +0,0 @@
|
|||
# FileSource Feature Specification
|
||||
|
||||
## Overview
|
||||
|
||||
The FileSource feature extends the dataflow architecture to recognize files themselves as tasks based on their metadata properties. This enables a dual-role model where a file can simultaneously serve as both a Project (container for tasks) and a FileSource Task (a task with its own properties like due dates, status, etc.).
|
||||
|
||||
## Architecture Alignment
|
||||
|
||||
### Dataflow Integration
|
||||
|
||||
FileSource integrates seamlessly into the existing dataflow architecture following established patterns:
|
||||
|
||||
- **Source Pattern**: Follows the same pattern as `ObsidianSource` and `IcsSource`
|
||||
- **Event-Driven**: Uses the centralized event system with proper sequence tracking
|
||||
- **Separation of Concerns**: Maintains clear boundaries between parsing, augmentation, repository, and storage
|
||||
- **Performance**: Leverages existing worker orchestration and caching mechanisms
|
||||
|
||||
### Key Design Principles
|
||||
|
||||
1. **Non-Intrusive**: Builds on existing file metadata parsing without breaking current functionality
|
||||
2. **Dual Role Support**: A file can be both a Project and a Task without conflicts
|
||||
3. **Flexible Recognition**: Multiple strategies for identifying files as tasks
|
||||
4. **Configuration-Driven**: Extensive configuration options for different use cases
|
||||
|
||||
## Core Concepts
|
||||
|
||||
### File as Task
|
||||
|
||||
A file becomes a FileSource Task when it meets configured recognition criteria:
|
||||
|
||||
- **Metadata-Based**: File has specific frontmatter properties (e.g., `dueDate`, `status`, `priority`)
|
||||
- **Tag-Based**: File contains specific tags (e.g., `#task`, `#project-task`, `#actionable`)
|
||||
- **Template-Based**: File is created from or matches specific templates
|
||||
- **Path-Based**: File location matches configured patterns
|
||||
|
||||
### Dual Role Model
|
||||
|
||||
Files can simultaneously serve as:
|
||||
|
||||
1. **Project**: Container for child tasks within the file
|
||||
2. **FileSource Task**: A task entity with its own metadata and lifecycle
|
||||
|
||||
This dual role is managed through:
|
||||
- **Namespace Separation**: Project data vs. task data are kept distinct
|
||||
- **Hierarchical Relationships**: File-tasks can contain child tasks from within the file
|
||||
- **Status Independence**: File status is separate from contained task statuses
|
||||
|
||||
### Relationship with Projects
|
||||
|
||||
FileSource integrates with the existing Project system:
|
||||
|
||||
- **Project Enhancement**: Files that are Projects can also be tasks
|
||||
- **Hierarchy Preservation**: Existing project hierarchies remain intact
|
||||
- **Metadata Inheritance**: Child tasks can inherit metadata from file-tasks
|
||||
- **Conflict Resolution**: Clear rules for handling conflicts between project and task metadata
|
||||
|
||||
## Technical Design
|
||||
|
||||
### Architecture Components
|
||||
|
||||
```
|
||||
src/dataflow/sources/
|
||||
├── FileSource.ts # Main FileSource implementation
|
||||
└── FileSourceConfig.ts # Configuration management
|
||||
|
||||
src/dataflow/parsers/
|
||||
├── FileSourceEntry.ts # File-to-task parsing entry point
|
||||
└── FileSourceParser.ts # Core file metadata → task conversion
|
||||
|
||||
src/dataflow/augment/
|
||||
└── FileSourceAugmentor.ts # File task augmentation logic
|
||||
|
||||
src/dataflow/indexer/
|
||||
└── FileSourceIndex.ts # Specialized indexing for file tasks
|
||||
|
||||
src/types/
|
||||
└── file-source.d.ts # TypeScript definitions
|
||||
```
|
||||
|
||||
### Data Flow
|
||||
|
||||
```
|
||||
1. File Change → ObsidianSource → FILE_UPDATED event
|
||||
2. FileSource subscribes to FILE_UPDATED events
|
||||
3. FileSource evaluates recognition criteria
|
||||
4. If match: FileSource → FILE_TASK_UPDATED event
|
||||
5. Orchestrator → Repository.updateFileTasks()
|
||||
6. Repository → TASK_CACHE_UPDATED event (with sourceSeq)
|
||||
7. Views update with merged file tasks + regular tasks
|
||||
```
|
||||
|
||||
### Event System
|
||||
|
||||
New events added to the centralized event system:
|
||||
|
||||
```typescript
|
||||
Events = {
|
||||
// ... existing events
|
||||
FILE_TASK_DETECTED: "task-genius:file-task-detected",
|
||||
FILE_TASK_UPDATED: "task-genius:file-task-updated",
|
||||
FILE_TASK_REMOVED: "task-genius:file-task-removed",
|
||||
}
|
||||
```
|
||||
|
||||
### Task Metadata Extension
|
||||
|
||||
File tasks use extended metadata:
|
||||
|
||||
```typescript
|
||||
interface FileSourceTaskMetadata extends StandardTaskMetadata {
|
||||
/** Task source */
|
||||
source: "file-source";
|
||||
|
||||
/** Recognition strategy that identified this file as a task */
|
||||
recognitionStrategy: "metadata" | "tag" | "template" | "path";
|
||||
|
||||
/** Recognition criteria that matched */
|
||||
recognitionCriteria: string;
|
||||
|
||||
/** File creation/modification timestamps */
|
||||
fileTimestamps: {
|
||||
created: number;
|
||||
modified: number;
|
||||
};
|
||||
|
||||
/** Child task relationships */
|
||||
childTasks: string[]; // IDs of tasks within this file
|
||||
|
||||
/** Project relationship (if file is also a project) */
|
||||
projectData?: {
|
||||
isProject: boolean;
|
||||
projectName?: string;
|
||||
projectType?: string;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
## Configuration Schema
|
||||
|
||||
### FileSource Configuration
|
||||
|
||||
```typescript
|
||||
interface FileSourceConfiguration {
|
||||
/** Enable FileSource feature */
|
||||
enabled: boolean;
|
||||
|
||||
/** Recognition strategies */
|
||||
recognitionStrategies: {
|
||||
/** Metadata-based recognition */
|
||||
metadata: {
|
||||
enabled: boolean;
|
||||
/** Metadata fields that make a file a task */
|
||||
taskFields: string[]; // Default: ["dueDate", "status", "priority", "assigned"]
|
||||
/** Require all fields or any field */
|
||||
requireAllFields: boolean; // Default: false
|
||||
};
|
||||
|
||||
/** Tag-based recognition */
|
||||
tags: {
|
||||
enabled: boolean;
|
||||
/** Tags that make a file a task */
|
||||
taskTags: string[]; // Default: ["#task", "#actionable", "#todo"]
|
||||
/** Tag matching mode */
|
||||
matchMode: "exact" | "prefix" | "contains"; // Default: "exact"
|
||||
};
|
||||
|
||||
/** Template-based recognition */
|
||||
templates: {
|
||||
enabled: boolean;
|
||||
/** Template files or patterns */
|
||||
templatePaths: string[]; // Default: ["Templates/Task Template.md"]
|
||||
/** Check template metadata */
|
||||
checkTemplateMetadata: boolean; // Default: true
|
||||
};
|
||||
|
||||
/** Path-based recognition */
|
||||
paths: {
|
||||
enabled: boolean;
|
||||
/** Path patterns that contain file tasks */
|
||||
taskPaths: string[]; // Default: ["Projects/", "Tasks/"]
|
||||
/** Pattern matching mode */
|
||||
matchMode: "prefix" | "regex" | "glob"; // Default: "prefix"
|
||||
};
|
||||
};
|
||||
|
||||
/** File task properties */
|
||||
fileTaskProperties: {
|
||||
/** Default task content source */
|
||||
contentSource: "filename" | "title" | "h1" | "custom"; // Default: "filename"
|
||||
/** Custom content field (if contentSource is "custom") */
|
||||
customContentField?: string;
|
||||
/** Strip file extension from content */
|
||||
stripExtension: boolean; // Default: true
|
||||
/** Default status for new file tasks */
|
||||
defaultStatus: string; // Default: " "
|
||||
/** Default priority for new file tasks */
|
||||
defaultPriority?: number;
|
||||
};
|
||||
|
||||
/** Relationship configuration */
|
||||
relationships: {
|
||||
/** Enable file-task to child-task relationships */
|
||||
enableChildRelationships: boolean; // Default: true
|
||||
/** Inherit metadata from file to child tasks */
|
||||
enableMetadataInheritance: boolean; // Default: true
|
||||
/** Metadata fields to inherit */
|
||||
inheritanceFields: string[]; // Default: ["project", "priority", "context"]
|
||||
};
|
||||
|
||||
/** Performance configuration */
|
||||
performance: {
|
||||
/** Enable worker processing for file tasks */
|
||||
enableWorkerProcessing: boolean; // Default: true
|
||||
/** Cache file task results */
|
||||
enableCaching: boolean; // Default: true
|
||||
/** Cache TTL in milliseconds */
|
||||
cacheTTL: number; // Default: 300000 (5 minutes)
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Default Configuration
|
||||
|
||||
```typescript
|
||||
const DEFAULT_FILE_SOURCE_CONFIG: FileSourceConfiguration = {
|
||||
enabled: false,
|
||||
recognitionStrategies: {
|
||||
metadata: {
|
||||
enabled: true,
|
||||
taskFields: ["dueDate", "status", "priority", "assigned"],
|
||||
requireAllFields: false
|
||||
},
|
||||
tags: {
|
||||
enabled: true,
|
||||
taskTags: ["#task", "#actionable", "#todo"],
|
||||
matchMode: "exact"
|
||||
},
|
||||
templates: {
|
||||
enabled: false,
|
||||
templatePaths: ["Templates/Task Template.md"],
|
||||
checkTemplateMetadata: true
|
||||
},
|
||||
paths: {
|
||||
enabled: false,
|
||||
taskPaths: ["Projects/", "Tasks/"],
|
||||
matchMode: "prefix"
|
||||
}
|
||||
},
|
||||
fileTaskProperties: {
|
||||
contentSource: "filename",
|
||||
stripExtension: true,
|
||||
defaultStatus: " ",
|
||||
defaultPriority: undefined
|
||||
},
|
||||
relationships: {
|
||||
enableChildRelationships: true,
|
||||
enableMetadataInheritance: true,
|
||||
inheritanceFields: ["project", "priority", "context"]
|
||||
},
|
||||
performance: {
|
||||
enableWorkerProcessing: true,
|
||||
enableCaching: true,
|
||||
cacheTTL: 300000
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
## Implementation Roadmap
|
||||
|
||||
### Phase 1: Core Infrastructure (Week 1-2)
|
||||
|
||||
**Components to Implement:**
|
||||
- [ ] `src/types/file-source.d.ts` - Core type definitions
|
||||
- [ ] `src/dataflow/sources/FileSourceConfig.ts` - Configuration management
|
||||
- [ ] `src/dataflow/sources/FileSource.ts` - Basic source implementation
|
||||
- [ ] Settings integration for FileSource configuration
|
||||
- [ ] Unit tests for core components
|
||||
|
||||
**Deliverables:**
|
||||
- Basic FileSource that can detect metadata-based file tasks
|
||||
- Configuration system fully integrated
|
||||
- Test coverage for core functionality
|
||||
|
||||
### Phase 2: Recognition Strategies (Week 3-4)
|
||||
|
||||
**Components to Implement:**
|
||||
- [ ] `src/dataflow/parsers/FileSourceParser.ts` - Recognition strategy implementations
|
||||
- [ ] `src/dataflow/parsers/FileSourceEntry.ts` - Parser entry point
|
||||
- [ ] Tag-based recognition
|
||||
- [ ] Template-based recognition
|
||||
- [ ] Path-based recognition
|
||||
- [ ] Integration tests for all strategies
|
||||
|
||||
**Deliverables:**
|
||||
- All recognition strategies functional
|
||||
- Comprehensive strategy testing
|
||||
- Performance benchmarks
|
||||
|
||||
### Phase 3: Integration & Augmentation (Week 5-6)
|
||||
|
||||
**Components to Implement:**
|
||||
- [ ] `src/dataflow/augment/FileSourceAugmentor.ts` - File task augmentation
|
||||
- [ ] Repository integration for file tasks
|
||||
- [ ] Event system integration
|
||||
- [ ] Child task relationship management
|
||||
- [ ] Metadata inheritance system
|
||||
|
||||
**Deliverables:**
|
||||
- Full dataflow integration
|
||||
- File-task to child-task relationships
|
||||
- Metadata inheritance working
|
||||
|
||||
### Phase 4: Performance & Polish (Week 7-8)
|
||||
|
||||
**Components to Implement:**
|
||||
- [ ] `src/dataflow/indexer/FileSourceIndex.ts` - Specialized indexing
|
||||
- [ ] Worker integration for performance
|
||||
- [ ] Caching implementation
|
||||
- [ ] Settings UI components
|
||||
- [ ] Documentation and examples
|
||||
|
||||
**Deliverables:**
|
||||
- Optimized performance for large vaults
|
||||
- Complete settings interface
|
||||
- User documentation
|
||||
- Migration guide
|
||||
|
||||
### Phase 5: Advanced Features (Week 9-10)
|
||||
|
||||
**Components to Implement:**
|
||||
- [ ] Custom recognition function support
|
||||
- [ ] Advanced conflict resolution
|
||||
- [ ] Bulk operations for file tasks
|
||||
- [ ] Export/import functionality
|
||||
- [ ] Advanced filtering for file tasks
|
||||
|
||||
**Deliverables:**
|
||||
- Advanced user customization options
|
||||
- Bulk management capabilities
|
||||
- Integration with existing tools
|
||||
|
||||
## API Specifications
|
||||
|
||||
### FileSource Class
|
||||
|
||||
```typescript
|
||||
export class FileSource {
|
||||
constructor(
|
||||
private app: App,
|
||||
private config: FileSourceConfiguration
|
||||
);
|
||||
|
||||
/** Initialize the FileSource */
|
||||
initialize(): void;
|
||||
|
||||
/** Check if a file should be treated as a task */
|
||||
shouldCreateFileTask(filePath: string): Promise<boolean>;
|
||||
|
||||
/** Convert a file to a FileSource task */
|
||||
createFileTask(filePath: string): Promise<Task<FileSourceTaskMetadata> | null>;
|
||||
|
||||
/** Update an existing file task */
|
||||
updateFileTask(filePath: string): Promise<Task<FileSourceTaskMetadata> | null>;
|
||||
|
||||
/** Remove a file task */
|
||||
removeFileTask(filePath: string): Promise<void>;
|
||||
|
||||
/** Get all file tasks */
|
||||
getAllFileTasks(): Promise<Task<FileSourceTaskMetadata>[]>;
|
||||
|
||||
/** Update configuration */
|
||||
updateConfiguration(config: Partial<FileSourceConfiguration>): void;
|
||||
|
||||
/** Get statistics */
|
||||
getStats(): FileSourceStats;
|
||||
|
||||
/** Cleanup and destroy */
|
||||
destroy(): void;
|
||||
}
|
||||
```
|
||||
|
||||
### Recognition Strategy Interface
|
||||
|
||||
```typescript
|
||||
interface RecognitionStrategy {
|
||||
/** Strategy name */
|
||||
name: string;
|
||||
|
||||
/** Check if file matches this strategy */
|
||||
matches(filePath: string, fileContent: string, fileCache: CachedMetadata): boolean;
|
||||
|
||||
/** Extract task metadata from file */
|
||||
extractMetadata(filePath: string, fileContent: string, fileCache: CachedMetadata): Partial<FileSourceTaskMetadata>;
|
||||
|
||||
/** Get strategy configuration */
|
||||
getConfig(): any;
|
||||
|
||||
/** Update strategy configuration */
|
||||
updateConfig(config: any): void;
|
||||
}
|
||||
```
|
||||
|
||||
### Query API Extensions
|
||||
|
||||
```typescript
|
||||
// Extensions to existing QueryAPI
|
||||
interface QueryAPI {
|
||||
/** Get all file tasks */
|
||||
getFileTasks(): Promise<Task<FileSourceTaskMetadata>[]>;
|
||||
|
||||
/** Get file tasks by criteria */
|
||||
getFileTasksByStrategy(strategy: string): Promise<Task<FileSourceTaskMetadata>[]>;
|
||||
|
||||
/** Get child tasks for a file task */
|
||||
getChildTasks(fileTaskId: string): Promise<Task[]>;
|
||||
|
||||
/** Get file task for a specific file */
|
||||
getFileTaskByPath(filePath: string): Promise<Task<FileSourceTaskMetadata> | null>;
|
||||
}
|
||||
```
|
||||
|
||||
## Testing Strategy
|
||||
|
||||
### Unit Tests
|
||||
|
||||
- **Recognition Strategy Tests**: Each strategy with various file configurations
|
||||
- **FileSource Core Tests**: Basic functionality, event handling, configuration
|
||||
- **Metadata Extraction Tests**: Parsing different file types and frontmatter formats
|
||||
- **Configuration Validation Tests**: Ensure configuration changes are properly handled
|
||||
|
||||
### Integration Tests
|
||||
|
||||
- **Dataflow Integration**: End-to-end file task creation and updates
|
||||
- **Event Flow Tests**: Verify proper event emission and handling
|
||||
- **Repository Integration**: File task storage and retrieval
|
||||
- **View Integration**: File tasks appearing in various views
|
||||
|
||||
### Performance Tests
|
||||
|
||||
- **Large Vault Tests**: 1000+ files with mixed file tasks
|
||||
- **Recognition Performance**: Speed of strategy evaluation
|
||||
- **Memory Usage**: Memory consumption with large numbers of file tasks
|
||||
- **Worker Performance**: Performance gains from worker processing
|
||||
|
||||
### Edge Case Tests
|
||||
|
||||
- **Dual Role Conflicts**: Files that are both projects and tasks
|
||||
- **Circular Dependencies**: File tasks with circular child relationships
|
||||
- **Invalid Configurations**: Handling of malformed recognition criteria
|
||||
- **File System Events**: Rapid file changes, renames, deletions
|
||||
|
||||
## Migration Considerations
|
||||
|
||||
### Backward Compatibility
|
||||
|
||||
- **Existing Functionality**: All current features remain unchanged
|
||||
- **Configuration**: FileSource disabled by default
|
||||
- **Data Integrity**: No changes to existing task data
|
||||
- **Performance**: No impact when FileSource is disabled
|
||||
|
||||
### Migration Path
|
||||
|
||||
1. **Incremental Rollout**: Feature flag for gradual enablement
|
||||
2. **Configuration Wizard**: Guided setup for common use cases
|
||||
3. **Data Migration**: Tools to convert existing project files to file tasks
|
||||
4. **Documentation**: Clear migration guides and examples
|
||||
|
||||
### Rollback Strategy
|
||||
|
||||
- **Clean Disable**: FileSource can be completely disabled without data loss
|
||||
- **Data Preservation**: File task data stored separately, can be ignored
|
||||
- **Event Cleanup**: Clean removal of FileSource events and handlers
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### Update Detection Strategy
|
||||
|
||||
FileSource implements intelligent update detection to minimize unnecessary processing:
|
||||
|
||||
#### Metadata Changes
|
||||
- **Detection**: Uses Obsidian's MetadataCache for efficient frontmatter monitoring
|
||||
- **Processing**: Only updates file task properties, not entire file
|
||||
- **Events**: FILE_METADATA_CHANGED → FILE_TASK_PROPERTY_CHANGED
|
||||
- **Optimization**: Diff-based property updates avoid full re-parsing
|
||||
|
||||
#### Content Changes
|
||||
- **Detection**: Analyzes change type to determine impact
|
||||
- **Processing**:
|
||||
- File not a task: Skip FileSource update entirely
|
||||
- File is a task: Check if children structure changed
|
||||
- Only task content: Trigger INLINE_TASK_CONTENT_CHANGED
|
||||
- **Events**: FILE_CONTENT_CHANGED → conditional processing
|
||||
|
||||
#### Children Structure Detection
|
||||
- **Optimization**: Only checks task IDs, not content
|
||||
- **Caching**: Maintains previous state for comparison
|
||||
- **Threshold**: Only updates on add/remove, not content changes
|
||||
- **Performance**: O(n) comparison using Set operations
|
||||
|
||||
### Event Granularity
|
||||
|
||||
Fine-grained events prevent cascading updates:
|
||||
|
||||
```typescript
|
||||
Events = {
|
||||
// Granular file events
|
||||
FILE_METADATA_CHANGED: "task-genius:file-metadata-changed",
|
||||
FILE_CONTENT_CHANGED: "task-genius:file-content-changed",
|
||||
|
||||
// Specific file task events
|
||||
FILE_TASK_PROPERTY_CHANGED: "task-genius:file-task-property-changed",
|
||||
FILE_TASK_CHILDREN_CHANGED: "task-genius:file-task-children-changed",
|
||||
|
||||
// Inline task events
|
||||
INLINE_TASK_CONTENT_CHANGED: "task-genius:inline-task-content-changed"
|
||||
}
|
||||
```
|
||||
|
||||
### Update Decision Logic
|
||||
|
||||
```typescript
|
||||
interface UpdateDecision {
|
||||
update: boolean;
|
||||
reason: 'not-a-file-task' | 'task-status-changed' |
|
||||
'task-properties-changed' | 'children-structure-changed' |
|
||||
'no-relevant-changes';
|
||||
details?: any;
|
||||
}
|
||||
|
||||
class FileSourceUpdateDetector {
|
||||
async shouldUpdateFileTask(
|
||||
filePath: string,
|
||||
changeReason: 'metadata' | 'content' | 'create' | 'delete'
|
||||
): Promise<UpdateDecision> {
|
||||
// Smart detection logic based on change type
|
||||
// Minimizes false positives and unnecessary updates
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Performance Characteristics
|
||||
|
||||
#### Typical Operations
|
||||
- **Metadata update**: < 10ms (property extraction only)
|
||||
- **Children structure check**: < 20ms (ID comparison only)
|
||||
- **Full file task update**: < 50ms (includes augmentation)
|
||||
- **Inline task update (no file task)**: 0ms FileSource overhead
|
||||
|
||||
#### Memory Optimization
|
||||
- **State caching**: ~100 bytes per file task
|
||||
- **Children ID cache**: ~20 bytes per child task
|
||||
- **Total overhead**: < 1MB for 1000 file tasks
|
||||
|
||||
#### Batch Processing
|
||||
- **Debounced updates**: 300ms delay for rapid changes
|
||||
- **Batch merging**: Multiple file updates processed together
|
||||
- **Worker offloading**: Heavy processing in background threads
|
||||
|
||||
### Cache Strategy
|
||||
|
||||
```typescript
|
||||
interface FileTaskCache {
|
||||
// Minimal cache for change detection
|
||||
fileTaskExists: boolean;
|
||||
frontmatterHash: string; // Quick property change detection
|
||||
childTaskIds: Set<string>; // Structure tracking only
|
||||
lastUpdated: number;
|
||||
}
|
||||
```
|
||||
|
||||
### Optimization Techniques
|
||||
|
||||
1. **Early Exit Patterns**
|
||||
- Non-task files skip processing immediately
|
||||
- Known unchanged files use cached results
|
||||
- Quick hash comparisons before deep analysis
|
||||
|
||||
2. **Selective Processing**
|
||||
- Only parse changed sections
|
||||
- Reuse unchanged metadata
|
||||
- Incremental children updates
|
||||
|
||||
3. **Smart Caching**
|
||||
- TTL-based cache invalidation
|
||||
- Content hash validation
|
||||
- Memory-bounded cache size
|
||||
|
||||
4. **Event Deduplication**
|
||||
- Sequence-based duplicate detection
|
||||
- Merge rapid sequential updates
|
||||
- Coalesce related events
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### File Access
|
||||
|
||||
- **Read-Only Operations**: FileSource only reads file metadata
|
||||
- **Path Validation**: All file paths validated and sanitized
|
||||
- **Permission Checks**: Respect Obsidian's file access permissions
|
||||
|
||||
### Configuration Security
|
||||
|
||||
- **Input Validation**: All configuration inputs validated
|
||||
- **Custom Functions**: Custom recognition functions sandboxed
|
||||
- **Path Traversal**: Protection against path traversal attacks
|
||||
|
||||
## Conclusion
|
||||
|
||||
The FileSource feature represents a natural evolution of the Task Genius plugin, extending the powerful dataflow architecture to support files as first-class task entities. The design maintains backward compatibility while providing flexible, performant, and user-friendly file task management.
|
||||
|
||||
The dual-role model allows users to organize their work hierarchically (files as projects containing tasks) while also treating files themselves as actionable items with due dates, priorities, and status tracking. This bridges the gap between project management and task management within Obsidian.
|
||||
|
||||
The implementation follows established architectural patterns, ensuring maintainability and consistency with the existing codebase. The extensive configuration options provide flexibility for various user workflows while maintaining simplicity for basic use cases.
|
||||
|
|
@ -1,144 +0,0 @@
|
|||
# FileSource 架构审查报告
|
||||
|
||||
## 概述
|
||||
FileSource 是一个新实现的数据源组件,用于将文件识别为任务并集成到 dataflow 架构中。本报告审查了 FileSource 的设计实现,并评估了其与现有 dataflow 架构的集成情况。
|
||||
|
||||
## 当前状态
|
||||
|
||||
### 已实现功能
|
||||
1. **文件识别策略**
|
||||
- 基于元数据(frontmatter)的识别
|
||||
- 基于标签的识别
|
||||
- 模板和路径策略(预留接口)
|
||||
- 灵活的状态映射系统
|
||||
|
||||
2. **事件处理**
|
||||
- 订阅 FILE_UPDATED 事件
|
||||
- 发射 file-task-updated 和 file-task-removed 事件
|
||||
- 防抖机制(300ms)避免频繁更新
|
||||
|
||||
3. **缓存管理**
|
||||
- FileTaskCache 跟踪文件任务状态
|
||||
- FrontmatterHash 用于变更检测
|
||||
- 统计信息跟踪
|
||||
|
||||
### 待集成部分
|
||||
FileSource 已完全实现但尚未集成到 DataflowOrchestrator 中。需要的集成步骤包括:
|
||||
1. 在 Orchestrator 构造函数中初始化 FileSource
|
||||
2. 订阅 FILE_TASK_UPDATED 和 FILE_TASK_REMOVED 事件
|
||||
3. 扩展 Repository 以处理文件任务
|
||||
4. 更新 QueryAPI 以合并文件任务到查询结果
|
||||
|
||||
## 架构设计评估
|
||||
|
||||
### 优点
|
||||
1. **模块化设计**:FileSource 完全独立,遵循 dataflow 的数据源模式
|
||||
2. **配置灵活性**:通过 FileSourceConfig 提供丰富的配置选项
|
||||
3. **性能优化**:实现了防抖、缓存和增量更新机制
|
||||
4. **事件驱动**:与现有事件系统良好集成
|
||||
|
||||
### 潜在问题与建议
|
||||
|
||||
#### 1. 重复计算问题
|
||||
**问题**:FileSource 在处理文件时需要获取项目数据,这可能与 Orchestrator 的处理产生重复。
|
||||
|
||||
**分析**:
|
||||
- FileSource 独立获取项目数据(通过 project/Resolver)
|
||||
- Orchestrator 也会为同一文件获取项目数据
|
||||
- 但由于 ProjectDataCache 的存在,实际不会产生重复计算
|
||||
|
||||
**建议**:
|
||||
- 当前设计可接受,缓存机制有效避免了重复计算
|
||||
- 未来可考虑通过事件传递项目数据,进一步优化
|
||||
|
||||
#### 2. 事件循环风险
|
||||
**问题**:FileSource 订阅 FILE_UPDATED 事件,可能与 ObsidianSource 产生冲突。
|
||||
|
||||
**分析**:
|
||||
- FileSource 监听 FILE_UPDATED 来识别文件任务
|
||||
- ObsidianSource 发射 FILE_UPDATED 事件
|
||||
- 存在潜在的事件循环风险
|
||||
|
||||
**建议**:
|
||||
- 使用序列号(Seq)机制防止循环
|
||||
- FileSource 应忽略自己触发的更新
|
||||
- 考虑使用不同的事件通道避免冲突
|
||||
|
||||
#### 3. 数据合并策略
|
||||
**问题**:文件任务与普通任务如何在 Repository 中合并?
|
||||
|
||||
**当前设计缺陷**:
|
||||
- Repository 当前只处理文件内的任务和 ICS 事件
|
||||
- 没有专门处理文件级任务的机制
|
||||
- QueryAPI 需要扩展以合并三种数据源
|
||||
|
||||
**建议**:
|
||||
```typescript
|
||||
// Repository 扩展建议
|
||||
class Repository {
|
||||
private fileTasks: Map<string, Task> = new Map(); // 新增:文件任务存储
|
||||
|
||||
async updateFileTask(filePath: string, task: Task): Promise<void> {
|
||||
this.fileTasks.set(filePath, task);
|
||||
// 发射更新事件
|
||||
}
|
||||
|
||||
async all(): Promise<Task[]> {
|
||||
const regularTasks = await this.indexer.getAllTasks();
|
||||
const fileTaskArray = Array.from(this.fileTasks.values());
|
||||
return [...regularTasks, ...this.icsEvents, ...fileTaskArray];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 4. 性能考虑
|
||||
**问题**:初始扫描可能处理大量文件。
|
||||
|
||||
**当前实现**:
|
||||
- 同步处理所有文件
|
||||
- 没有批处理或并行处理
|
||||
|
||||
**建议**:
|
||||
- 实现批处理机制
|
||||
- 考虑使用 Worker 进行并行处理
|
||||
- 添加进度报告机制
|
||||
|
||||
## 集成路线图
|
||||
|
||||
### 第一阶段:基础集成
|
||||
1. 在 Orchestrator 中初始化 FileSource
|
||||
2. 添加事件监听器
|
||||
3. 扩展 Repository 支持文件任务
|
||||
4. 更新 QueryAPI 合并逻辑
|
||||
|
||||
### 第二阶段:优化
|
||||
1. 实现批处理和并行扫描
|
||||
2. 优化项目数据传递
|
||||
3. 添加更多识别策略(模板、路径)
|
||||
4. 实现智能更新检测
|
||||
|
||||
### 第三阶段:高级功能
|
||||
1. 支持文件任务的子任务
|
||||
2. 实现文件任务的双向同步
|
||||
3. 添加文件任务的特殊视图
|
||||
4. 支持文件任务的批量操作
|
||||
|
||||
## 结论
|
||||
|
||||
FileSource 的实现质量良好,遵循了 dataflow 架构的设计原则。主要需要关注的是:
|
||||
|
||||
1. **集成工作**:需要将 FileSource 正式集成到 Orchestrator 中
|
||||
2. **数据合并**:Repository 需要扩展以正确处理三种数据源
|
||||
3. **性能优化**:大规模文件扫描需要优化
|
||||
4. **避免冲突**:确保与现有系统的事件处理不产生冲突
|
||||
|
||||
通过 ProjectDataCache 的缓存机制,重复计算的担忧已得到有效解决。FileSource 的设计是合理的,只需完成集成工作即可投入使用。
|
||||
|
||||
## 建议的下一步行动
|
||||
|
||||
1. 完成 FileSource 与 Orchestrator 的集成
|
||||
2. 扩展 Repository 以支持文件任务存储
|
||||
3. 更新 QueryAPI 的查询逻辑
|
||||
4. 添加集成测试确保三种数据源正确合并
|
||||
5. 优化初始扫描性能
|
||||
6. 更新用户文档说明新功能
|
||||
|
|
@ -1,276 +0,0 @@
|
|||
# Onboarding Intro Step 修复文档
|
||||
|
||||
## 问题描述
|
||||
|
||||
在引导流程(Onboarding)的 Intro 步骤中,第四条消息(intro-line-4)在显示后立即被清除,用户无法阅读完整内容。
|
||||
|
||||
**问题消息内容:**
|
||||
> "In the current version, Task Genius provides a brand new visual and interactive experience: Fluent; while also providing the option to return to the previous interface. Which one do you prefer?"
|
||||
|
||||
## 根本原因
|
||||
|
||||
### 错误的实现逻辑
|
||||
|
||||
在重构后的代码中(commit 8f5daebd),`IntroStep.ts` 的实现逻辑是:
|
||||
|
||||
```typescript
|
||||
// 错误的实现
|
||||
new TypingAnimation(typingContainer, messages, () => {
|
||||
// 打字完成后立即切换步骤
|
||||
footerEl.style.display = "";
|
||||
controller.setStep(OnboardingStep.MODE_SELECT); // ❌ 这里切换步骤
|
||||
});
|
||||
```
|
||||
|
||||
当 `controller.setStep(OnboardingStep.MODE_SELECT)` 被调用时:
|
||||
1. `ModeSelectionStep.render()` 被触发
|
||||
2. 该方法首先调用 `contentEl.empty()` 清空内容
|
||||
3. `intro-line-4` 消息被立即清除
|
||||
4. 用户几乎看不到消息内容
|
||||
|
||||
### 原始的正确逻辑
|
||||
|
||||
在旧版本中(commit 491e2a6),`IntroTyping` 组件的实现是:
|
||||
|
||||
```typescript
|
||||
// 正确的实现
|
||||
this.introTyping.render(this.onboardingContentEl, () => {
|
||||
// 打字完成后,在同一容器中添加模式选择
|
||||
const modeContainer = this.onboardingContentEl.createDiv({
|
||||
cls: "intro-mode-selection-container"
|
||||
});
|
||||
|
||||
this.modeSelection.render(modeContainer, this.state.uiMode, (mode) => {
|
||||
this.state.uiMode = mode;
|
||||
// 用户选择后才显示 footer
|
||||
this.footerEl.style.display = '';
|
||||
this.updateButtonStates();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
**关键区别:**
|
||||
- ✅ 不切换步骤,保持在 INTRO 步骤
|
||||
- ✅ 在同一个 `contentEl` 中追加模式选择 UI
|
||||
- ✅ `intro-line-4` 消息保留在页面上
|
||||
- ✅ 用户可以完整阅读消息后再选择模式
|
||||
|
||||
## 解决方案
|
||||
|
||||
### 修改的文件
|
||||
|
||||
1. **`src/components/features/onboarding/steps/IntroStep.ts`**
|
||||
- 修改 `TypingAnimation` 的 `onComplete` 回调
|
||||
- 不再切换到 MODE_SELECT 步骤
|
||||
- 而是在同一容器中渲染模式选择 UI
|
||||
|
||||
2. **`src/components/features/onboarding/steps/ModeSelectionStep.ts`**
|
||||
- 添加新方法 `renderInline()`
|
||||
- 该方法不清空容器,直接在给定容器中渲染
|
||||
- 接受自定义的 `onSelect` 回调
|
||||
|
||||
### 具体实现
|
||||
|
||||
#### IntroStep.ts 修改
|
||||
|
||||
```typescript
|
||||
// Start typing animation
|
||||
new TypingAnimation(typingContainer, messages, () => {
|
||||
// After typing completes, show mode selection in same container
|
||||
const modeContainer = introWrapper.createDiv({
|
||||
cls: "intro-mode-selection-container"
|
||||
});
|
||||
|
||||
// Render mode selection inline (without clearing intro-line-4)
|
||||
ModeSelectionStep.renderInline(
|
||||
modeContainer,
|
||||
controller,
|
||||
(mode: UIMode) => {
|
||||
// User selected a mode, show footer with Next button
|
||||
controller.setUIMode(mode);
|
||||
footerEl.style.display = "";
|
||||
}
|
||||
);
|
||||
});
|
||||
```
|
||||
|
||||
#### ModeSelectionStep.ts 新增方法
|
||||
|
||||
```typescript
|
||||
/**
|
||||
* Render mode selection inline (for intro step)
|
||||
* This version doesn't clear the container and calls a custom callback
|
||||
*/
|
||||
static renderInline(
|
||||
containerEl: HTMLElement,
|
||||
controller: OnboardingController,
|
||||
onSelect: (mode: UIMode) => void
|
||||
) {
|
||||
// Get current state
|
||||
const currentMode = controller.getState().uiMode;
|
||||
|
||||
// Create cards configuration
|
||||
const cardConfigs: SelectableCardConfig<UIMode>[] = [
|
||||
// ... 卡片配置
|
||||
];
|
||||
|
||||
// Render selectable cards
|
||||
const card = new SelectableCard<UIMode>(
|
||||
containerEl,
|
||||
cardConfigs,
|
||||
{
|
||||
containerClass: "selectable-cards-container",
|
||||
cardClass: "selectable-card",
|
||||
showPreview: true,
|
||||
},
|
||||
(mode) => {
|
||||
onSelect(mode); // 调用自定义回调
|
||||
}
|
||||
);
|
||||
|
||||
// Set initial selection
|
||||
if (currentMode) {
|
||||
card.setSelected(currentMode);
|
||||
}
|
||||
|
||||
// Add info alert
|
||||
Alert.create(
|
||||
containerEl,
|
||||
t("You can change this option later in settings"),
|
||||
{
|
||||
variant: "info",
|
||||
className: "mode-selection-tip",
|
||||
}
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
## 用户体验流程
|
||||
|
||||
修复后的用户体验流程:
|
||||
|
||||
1. **打字动画阶段**
|
||||
- 显示 "Hi,"
|
||||
- 显示 "Thank you for using Task Genius"
|
||||
- 显示长文本,然后淡出前三条消息
|
||||
- 显示 `intro-line-4` 消息(关键消息)
|
||||
|
||||
2. **模式选择阶段**
|
||||
- `intro-line-4` 消息**保留在页面上**
|
||||
- 在消息下方显示模式选择卡片(Fluent vs Legacy)
|
||||
- 用户可以完整阅读消息内容
|
||||
- 用户选择模式后,显示 Next 按钮
|
||||
|
||||
3. **下一步**
|
||||
- 用户点击 Next 按钮
|
||||
- 才清除内容并进入下一个步骤
|
||||
|
||||
## CSS 样式支持
|
||||
|
||||
相关的 CSS 样式已经存在于 `src/styles/onboarding.css`:
|
||||
|
||||
```css
|
||||
/* Mode selection container that appears after intro typing */
|
||||
.intro-mode-selection-container {
|
||||
animation: fadeInFromBottom 0.6s ease-out;
|
||||
animation-fill-mode: both;
|
||||
width: 100%;
|
||||
margin-top: var(--size-4-10);
|
||||
}
|
||||
|
||||
.intro-line-4 {
|
||||
font-size: clamp(1rem, 2vw, 1.4rem);
|
||||
color: var(--text-muted);
|
||||
line-height: 1.8;
|
||||
margin-bottom: var(--size-4-5);
|
||||
}
|
||||
```
|
||||
|
||||
## 测试验证
|
||||
|
||||
构建成功,无错误:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
# ✅ Build successful
|
||||
# dist\main.js 3.7mb
|
||||
# dist\main.css 345.1kb
|
||||
```
|
||||
|
||||
## 导航逻辑修复
|
||||
|
||||
### 问题
|
||||
|
||||
修复 intro 消息显示后,发现了新的导航问题:
|
||||
|
||||
当用户在 INTRO 步骤中选择模式后点击 Next,会经过以下流程:
|
||||
1. INTRO → MODE_SELECT(因为 handleNext 中 INTRO 的下一步是 MODE_SELECT)
|
||||
2. MODE_SELECT 被渲染(但用户已经选择过了)
|
||||
3. 用户再次点击 Next
|
||||
4. MODE_SELECT → FLUENT_COMPONENTS(**跳过了 FLUENT_PLACEMENT**)
|
||||
|
||||
### 解决方案
|
||||
|
||||
修改 `OnboardingController.ts` 中的 `handleNext()` 逻辑:
|
||||
|
||||
```typescript
|
||||
case OnboardingStep.INTRO:
|
||||
// Mode selection is now inline in INTRO step
|
||||
// So we skip MODE_SELECT and go directly based on selected mode
|
||||
if (this.state.uiMode === 'fluent') {
|
||||
nextStep = OnboardingStep.FLUENT_PLACEMENT; // ✅ 正确跳转
|
||||
} else {
|
||||
// Legacy mode: check for existing changes
|
||||
if (this.state.userHasChanges) {
|
||||
nextStep = OnboardingStep.SETTINGS_CHECK;
|
||||
} else {
|
||||
nextStep = OnboardingStep.USER_LEVEL_SELECT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case OnboardingStep.MODE_SELECT:
|
||||
// This step is now integrated into INTRO, but keep for backward compatibility
|
||||
if (this.state.uiMode === 'fluent') {
|
||||
nextStep = OnboardingStep.FLUENT_PLACEMENT; // ✅ 修复:不再跳过
|
||||
} else {
|
||||
// Legacy mode: check for existing changes
|
||||
if (this.state.userHasChanges) {
|
||||
nextStep = OnboardingStep.SETTINGS_CHECK;
|
||||
} else {
|
||||
nextStep = OnboardingStep.USER_LEVEL_SELECT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
```
|
||||
|
||||
### 修复后的流程
|
||||
|
||||
**Fluent 模式:**
|
||||
1. INTRO(包含模式选择)
|
||||
2. FLUENT_PLACEMENT(选择 Sideleaves 或 Inline)
|
||||
3. FLUENT_COMPONENTS(组件预览)
|
||||
4. SETTINGS_CHECK 或 USER_LEVEL_SELECT(根据是否有更改)
|
||||
|
||||
**Legacy 模式:**
|
||||
1. INTRO(包含模式选择)
|
||||
2. SETTINGS_CHECK(如果有更改)或 USER_LEVEL_SELECT(如果没有更改)
|
||||
|
||||
## 总结
|
||||
|
||||
通过恢复原始的实现逻辑并修复导航逻辑,现在:
|
||||
|
||||
**消息显示:**
|
||||
- ✅ `intro-line-4` 消息完整显示在页面上
|
||||
- ✅ 在模式选择卡片上方保留
|
||||
- ✅ 用户有充足时间阅读
|
||||
- ✅ 只有在点击 Next 后才被清除
|
||||
|
||||
**导航流程:**
|
||||
- ✅ INTRO 步骤包含模式选择(内联)
|
||||
- ✅ 选择 Fluent 后正确进入 FLUENT_PLACEMENT
|
||||
- ✅ 选择 Legacy 后根据配置进入相应步骤
|
||||
- ✅ 不会跳过任何必要的步骤
|
||||
|
||||
这符合原始设计意图,提供了更好的用户体验。
|
||||
|
||||
|
|
@ -1,237 +0,0 @@
|
|||
# OnCompletion Feature Guide
|
||||
|
||||
## Overview
|
||||
|
||||
The OnCompletion feature allows you to define automatic actions that occur when a task is marked as completed. This is useful for workflows like archiving completed tasks, triggering dependent tasks, or moving tasks to different locations.
|
||||
|
||||
## Architecture
|
||||
|
||||
The OnCompletion system consists of:
|
||||
- **OnCompletionManager**: Core manager that listens for task completion events
|
||||
- **Action Executors**: Individual executors for each action type (delete, move, archive, etc.)
|
||||
- **Event System**: Integration with `task-genius:task-completed` event
|
||||
- **WriteAPI Integration**: Automatic triggering when tasks are completed via API
|
||||
|
||||
## Setup
|
||||
|
||||
The OnCompletion feature is automatically initialized when the plugin loads with indexer enabled. No additional configuration is required.
|
||||
|
||||
## Usage
|
||||
|
||||
### Task Metadata Format
|
||||
|
||||
Add an `onCompletion` property to your task metadata:
|
||||
|
||||
#### Simple Format (Emoji)
|
||||
```markdown
|
||||
- [ ] Task content 🏁 delete
|
||||
- [ ] Task content 🏁 keep
|
||||
- [ ] Task content 🏁 archive
|
||||
- [ ] Task content 🏁 move:Projects/Archive.md
|
||||
- [ ] Task content 🏁 complete:task-id-1,task-id-2
|
||||
- [ ] Task content 🏁 duplicate:Projects/Templates.md
|
||||
```
|
||||
|
||||
#### Dataview Format
|
||||
```markdown
|
||||
- [ ] Task content [onCompletion:: delete]
|
||||
- [ ] Task content [onCompletion:: keep]
|
||||
- [ ] Task content [onCompletion:: archive]
|
||||
- [ ] Task content [onCompletion:: move:Projects/Archive.md]
|
||||
- [ ] Task content [onCompletion:: complete:task-id-1,task-id-2]
|
||||
- [ ] Task content [onCompletion:: duplicate:Projects/Templates.md]
|
||||
```
|
||||
|
||||
#### JSON Format (Advanced)
|
||||
```markdown
|
||||
- [ ] Task content 🏁 {"type":"move","targetFile":"Archive.md","section":"## Completed"}
|
||||
- [ ] Task content 🏁 {"type":"complete","taskIds":["id1","id2"],"cascade":true}
|
||||
- [ ] Task content 🏁 {"type":"archive","archiveFile":"2024-Archive.md","preserveMetadata":true}
|
||||
```
|
||||
|
||||
## Action Types
|
||||
|
||||
### DELETE
|
||||
Removes the task from the file when completed.
|
||||
```markdown
|
||||
- [ ] Temporary task 🏁 delete
|
||||
```
|
||||
|
||||
### KEEP
|
||||
Keeps the task as completed (default behavior, useful for overriding).
|
||||
```markdown
|
||||
- [ ] Important task 🏁 keep
|
||||
```
|
||||
|
||||
### ARCHIVE
|
||||
Moves the task to an archive file (default: "Archive.md" in same folder).
|
||||
```markdown
|
||||
- [ ] Task to archive 🏁 archive
|
||||
- [ ] Custom archive 🏁 archive:Completed/2024.md
|
||||
```
|
||||
|
||||
### MOVE
|
||||
Moves the task to a different file or section.
|
||||
```markdown
|
||||
- [ ] Task to move 🏁 move:Another File.md
|
||||
- [ ] Move to section 🏁 {"type":"move","targetFile":"File.md","section":"## Done"}
|
||||
```
|
||||
|
||||
### COMPLETE
|
||||
Automatically completes other tasks when this task is completed.
|
||||
```markdown
|
||||
- [ ] Parent task 🏁 complete:child-task-id-1,child-task-id-2
|
||||
- [ ] Cascade completion 🏁 {"type":"complete","taskIds":["id1"],"cascade":true}
|
||||
```
|
||||
|
||||
### DUPLICATE
|
||||
Creates a copy of the task in another location when completed.
|
||||
```markdown
|
||||
- [ ] Template task 🏁 duplicate:Templates/Recurring.md
|
||||
- [ ] Duplicate and reset 🏁 {"type":"duplicate","targetFile":"Tomorrow.md","resetStatus":true}
|
||||
```
|
||||
|
||||
## Event Flow
|
||||
|
||||
1. User marks task as completed (via UI, command, or API)
|
||||
2. WriteAPI detects completion and triggers `task-genius:task-completed` event
|
||||
3. OnCompletionManager receives the event
|
||||
4. Manager parses the `onCompletion` metadata
|
||||
5. Appropriate executor is invoked
|
||||
6. Action is performed (delete, move, archive, etc.)
|
||||
7. Result is logged
|
||||
|
||||
## Integration Points
|
||||
|
||||
### WriteAPI
|
||||
The WriteAPI automatically triggers the completion event:
|
||||
- `updateTask()` - When `completed: true` is set
|
||||
- `updateTaskStatus()` - When task is marked complete
|
||||
- `updateCanvasTask()` - Canvas tasks also trigger events
|
||||
|
||||
### Editor Extensions
|
||||
- `monitorTaskCompletedExtension` - Monitors inline completions
|
||||
- `status-switcher` - Triggers on status changes
|
||||
- `status-cycler` - Triggers on cycle operations
|
||||
|
||||
### Canvas Support
|
||||
Canvas tasks fully support OnCompletion:
|
||||
```javascript
|
||||
// Canvas task with onCompletion
|
||||
{
|
||||
"type": "text",
|
||||
"text": "- [ ] Canvas task 🏁 delete",
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
If an OnCompletion action fails:
|
||||
1. Error is logged to console
|
||||
2. Task remains completed
|
||||
3. No rollback occurs
|
||||
4. User is not notified (silent failure)
|
||||
|
||||
To debug issues:
|
||||
1. Open Developer Console (Ctrl+Shift+I)
|
||||
2. Look for "OnCompletionManager" logs
|
||||
3. Check for parsing or execution errors
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Use simple format** for basic actions (delete, keep, archive)
|
||||
2. **Use JSON format** for complex configurations
|
||||
3. **Test actions** on non-critical tasks first
|
||||
4. **Validate file paths** exist before using move/archive
|
||||
5. **Use task IDs** carefully with complete action
|
||||
|
||||
## Examples
|
||||
|
||||
### Daily Task Cleanup
|
||||
```markdown
|
||||
## Daily Tasks
|
||||
- [ ] Review emails 🏁 delete
|
||||
- [ ] Update status report 🏁 move:Completed/2024-08.md
|
||||
- [ ] Team standup 🏁 delete
|
||||
```
|
||||
|
||||
### Project Dependencies
|
||||
```markdown
|
||||
## Project Steps
|
||||
- [ ] Design mockups 🆔 design-001
|
||||
- [ ] Implement frontend 🆔 frontend-001 🏁 complete:testing-001
|
||||
- [ ] Write tests 🆔 testing-001 🏁 complete:deploy-001
|
||||
- [ ] Deploy to production 🆔 deploy-001
|
||||
```
|
||||
|
||||
### Recurring Task Template
|
||||
```markdown
|
||||
## Templates
|
||||
- [ ] Weekly review 🏁 duplicate:Next Week.md
|
||||
- [ ] Monthly report 🏁 {"type":"duplicate","targetFile":"Next Month.md","resetStatus":true}
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
Currently, OnCompletion actions are defined per-task via metadata. Global configuration options may be added in future versions.
|
||||
|
||||
## Limitations
|
||||
|
||||
- Actions are not undoable
|
||||
- Circular dependencies in `complete` action may cause issues
|
||||
- File operations may fail if target doesn't exist
|
||||
- No UI for configuring actions (metadata only)
|
||||
|
||||
## Migration from TaskManager
|
||||
|
||||
The OnCompletion feature is fully compatible with the new Dataflow architecture:
|
||||
|
||||
| Component | Old (TaskManager) | New (Dataflow) |
|
||||
|-----------|------------------|----------------|
|
||||
| Manager | Part of TaskManager | Standalone OnCompletionManager |
|
||||
| Events | Manual triggering | Automatic via WriteAPI |
|
||||
| Canvas | Limited support | Full support |
|
||||
| Performance | Synchronous | Asynchronous |
|
||||
|
||||
## Testing OnCompletion
|
||||
|
||||
To test if OnCompletion is working:
|
||||
|
||||
1. Create a test task:
|
||||
```markdown
|
||||
- [ ] Test task 🏁 delete
|
||||
```
|
||||
|
||||
2. Mark it complete using:
|
||||
- Click the checkbox
|
||||
- Use keyboard shortcut
|
||||
- Use WriteAPI
|
||||
|
||||
3. Check that the task is deleted
|
||||
|
||||
4. Check console for logs:
|
||||
```
|
||||
[Plugin] OnCompletionManager initialized
|
||||
handleTaskCompleted {task object}
|
||||
parseResult {config object}
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### OnCompletion not triggering
|
||||
- Ensure indexer is enabled in settings
|
||||
- Check that task has valid onCompletion metadata
|
||||
- Verify task-completed event is firing (check console)
|
||||
- Ensure OnCompletionManager is loaded
|
||||
|
||||
### Action failing
|
||||
- Check file paths are correct
|
||||
- Ensure target files exist for move/archive
|
||||
- Verify task IDs exist for complete action
|
||||
- Check console for specific error messages
|
||||
|
||||
### Performance issues
|
||||
- Large batch operations may be slow
|
||||
- Consider using delete instead of archive for many tasks
|
||||
- Avoid deep cascade chains in complete action
|
||||
|
|
@ -1,262 +0,0 @@
|
|||
# Parser Refactoring Plan
|
||||
|
||||
## Current State Analysis
|
||||
|
||||
### 1. Parser Duplication Issues
|
||||
|
||||
#### Canvas Parser Chain (3 layers)
|
||||
```
|
||||
src/parsers/canvas-parser.ts (redirect)
|
||||
→ src/dataflow/core/CanvasParser.ts (implementation)
|
||||
→ src/dataflow/parsers/CanvasEntry.ts (entry point)
|
||||
```
|
||||
|
||||
**Current Usage:**
|
||||
- Tests import from `src/parsers/canvas-parser.ts` (2 test files)
|
||||
- Worker imports directly from `src/dataflow/core/CanvasParser.ts`
|
||||
- Orchestrator uses `parseCanvas()` from `CanvasEntry.ts`
|
||||
|
||||
#### TaskParserConfig Duplication
|
||||
- **Old**: `src/types/task.d.ts:267` - Simple interface with regex patterns
|
||||
- **New**: `src/types/TaskParserConfig.ts:12` - Comprehensive with 60+ fields
|
||||
- **Active Usage**: All 13 imports use the new TaskParserConfig.ts
|
||||
|
||||
#### Parser Implementation Overlap
|
||||
- **MarkdownTaskParser**: Core implementation (1700+ lines)
|
||||
- **ConfigurableTaskParser**: Extends MarkdownTaskParser with time parsing
|
||||
- **FileMetadataTaskParser**: Separate implementation for metadata
|
||||
- **TaskParsingService**: High-level orchestrator
|
||||
|
||||
### 2. Dependency Analysis
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Orchestrator] --> B[CanvasEntry::parseCanvas]
|
||||
B --> C[CanvasParser::parseCanvasFile]
|
||||
C --> D[ConfigurableTaskParser]
|
||||
|
||||
E[Tests] --> F[canvas-parser.ts redirect]
|
||||
F --> C
|
||||
|
||||
G[Worker] --> C
|
||||
|
||||
H[TaskParsingService] --> D
|
||||
H --> I[FileMetadataTaskParser]
|
||||
```
|
||||
|
||||
## Refactoring Steps
|
||||
|
||||
### Phase 1: Immediate Cleanup (Low Risk)
|
||||
|
||||
#### 1.1 Remove Canvas Parser Redirect
|
||||
**Files to modify:**
|
||||
- Delete: `src/parsers/canvas-parser.ts`
|
||||
- Update imports in:
|
||||
- `src/__tests__/CanvasParser.test.ts`
|
||||
- `src/__tests__/CanvasIntegration.test.ts`
|
||||
|
||||
**Change:**
|
||||
```typescript
|
||||
// Before
|
||||
import { CanvasParser } from '../parsers/canvas-parser';
|
||||
|
||||
// After
|
||||
import { CanvasParser } from '../dataflow/core/CanvasParser';
|
||||
```
|
||||
|
||||
#### 1.2 Remove Old TaskParserConfig
|
||||
**Files to modify:**
|
||||
- Remove interface from `src/types/task.d.ts:267-284`
|
||||
- No import changes needed (all use the new one)
|
||||
|
||||
### Phase 2: Consolidate Canvas Parsing (Medium Risk)
|
||||
|
||||
#### 2.1 Merge CanvasEntry into CanvasParser
|
||||
**Goal:** Single entry point for Canvas parsing
|
||||
|
||||
**New structure:**
|
||||
```typescript
|
||||
// src/dataflow/core/CanvasParser.ts
|
||||
export class CanvasParser {
|
||||
// Existing implementation
|
||||
|
||||
// Add entry function from CanvasEntry
|
||||
static async parseCanvas(
|
||||
filePath: string,
|
||||
fileContent: string,
|
||||
plugin: TaskProgressBarPlugin
|
||||
): Promise<TaskResult> {
|
||||
// Merge logic from CanvasEntry
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 2.2 Update Canvas Updater
|
||||
**Goal:** Share parsing logic with CanvasParser
|
||||
|
||||
**Files to modify:**
|
||||
- `src/parsers/canvas-task-updater.ts`
|
||||
- Import Canvas types from CanvasParser
|
||||
- Reuse node parsing logic
|
||||
|
||||
### Phase 3: Unified Parser Architecture (High Impact)
|
||||
|
||||
#### 3.1 Create Unified Parser Registry
|
||||
```typescript
|
||||
// src/parsing/ParserRegistry.ts
|
||||
export class ParserRegistry {
|
||||
private parsers: Map<string, BaseParser>;
|
||||
|
||||
register(extension: string, parser: BaseParser) { }
|
||||
parse(file: TFile, config: TaskParserConfig): Promise<TaskResult> { }
|
||||
}
|
||||
```
|
||||
|
||||
#### 3.2 Standardize Parser Interface
|
||||
```typescript
|
||||
// src/parsing/BaseParser.ts
|
||||
export interface BaseParser {
|
||||
parse(content: string, config: TaskParserConfig): Promise<ParseResult>;
|
||||
update(content: string, updates: TaskUpdate[]): Promise<string>;
|
||||
supports(file: TFile): boolean;
|
||||
}
|
||||
```
|
||||
|
||||
#### 3.3 Implement Specific Parsers
|
||||
```
|
||||
src/parsing/
|
||||
├── BaseParser.ts
|
||||
├── ParserRegistry.ts
|
||||
├── parsers/
|
||||
│ ├── MarkdownParser.ts
|
||||
│ ├── CanvasParser.ts
|
||||
│ └── ICSParser.ts
|
||||
└── updaters/
|
||||
├── MarkdownUpdater.ts
|
||||
└── CanvasUpdater.ts
|
||||
```
|
||||
|
||||
## Migration Strategy
|
||||
|
||||
### Step-by-Step Execution
|
||||
|
||||
1. **Week 1**: Phase 1 - Immediate Cleanup
|
||||
- Remove redirects and duplicates
|
||||
- Run full test suite
|
||||
- Monitor for issues
|
||||
|
||||
2. **Week 2**: Phase 2.1 - Canvas Consolidation
|
||||
- Merge CanvasEntry into CanvasParser
|
||||
- Update Orchestrator imports
|
||||
- Test Canvas functionality
|
||||
|
||||
3. **Week 3**: Phase 2.2 - Updater Integration
|
||||
- Refactor Canvas updater
|
||||
- Share parsing logic
|
||||
- Test update operations
|
||||
|
||||
4. **Week 4+**: Phase 3 - Architecture (Optional)
|
||||
- Implement if needed for new features
|
||||
- Gradual migration
|
||||
- Maintain backward compatibility
|
||||
|
||||
## Testing Requirements
|
||||
|
||||
### Unit Tests
|
||||
- [ ] Canvas parsing tests pass
|
||||
- [ ] Markdown parsing tests pass
|
||||
- [ ] Task parsing service tests pass
|
||||
- [ ] Worker tests pass
|
||||
|
||||
### Integration Tests
|
||||
- [ ] Canvas file operations
|
||||
- [ ] Task updates in Canvas
|
||||
- [ ] Cross-file task references
|
||||
- [ ] Performance benchmarks
|
||||
|
||||
### Manual Testing
|
||||
- [ ] Create tasks in Canvas
|
||||
- [ ] Update task status in Canvas
|
||||
- [ ] Parse complex Canvas files
|
||||
- [ ] Verify no UI regressions
|
||||
|
||||
## Risk Assessment
|
||||
|
||||
### Low Risk Changes
|
||||
- Removing redirect files
|
||||
- Removing unused interfaces
|
||||
- Import path updates
|
||||
|
||||
### Medium Risk Changes
|
||||
- Merging CanvasEntry logic
|
||||
- Sharing parsing code between parser/updater
|
||||
|
||||
### High Risk Changes
|
||||
- Full architecture refactor
|
||||
- Parser registry implementation
|
||||
- Breaking API changes
|
||||
|
||||
## Success Metrics
|
||||
|
||||
1. **Code Reduction**: ~200 lines removed from duplicates
|
||||
2. **Performance**: No regression in parsing speed
|
||||
3. **Maintainability**: Single source of truth for each parser
|
||||
4. **Test Coverage**: All tests passing
|
||||
5. **Bug Count**: No new parsing issues reported
|
||||
|
||||
## Rollback Plan
|
||||
|
||||
If issues arise:
|
||||
1. Revert commits in reverse order
|
||||
2. Restore redirect files temporarily
|
||||
3. Document specific failure points
|
||||
4. Create targeted fixes
|
||||
|
||||
## Implementation Status
|
||||
|
||||
### Phase 1: Immediate Cleanup ✅ COMPLETED
|
||||
- ✅ Removed canvas-parser.ts redirect file
|
||||
- ✅ Updated test imports to use dataflow/core/CanvasParser
|
||||
- ✅ Removed old TaskParserConfig from task.d.ts
|
||||
- ✅ All tests passing
|
||||
- ✅ TypeScript compilation clean
|
||||
- ✅ Build successful
|
||||
|
||||
### Phase 2.1: Canvas Consolidation ✅ COMPLETED
|
||||
- ✅ Added static parseCanvas method to CanvasParser
|
||||
- ✅ Removed CanvasEntry.ts file
|
||||
- ✅ Updated Orchestrator to use CanvasParser.parseCanvas()
|
||||
- ✅ Updated WorkerOrchestrator dynamic imports
|
||||
- ✅ Reduced Canvas parsing layers from 3 to 2
|
||||
|
||||
### Phase 2.2: Canvas Updater Integration ✅ COMPLETED
|
||||
- ✅ Added utility methods to CanvasParser:
|
||||
- parseCanvasJSON() - Safe JSON parsing
|
||||
- findTextNode() - Find node by ID
|
||||
- getTextNodes() - Get all text nodes
|
||||
- ✅ Refactored canvas-task-updater to use shared utilities
|
||||
- ✅ Eliminated duplicate Canvas JSON parsing logic
|
||||
- ✅ All Canvas functionality tested and working
|
||||
|
||||
## Results Summary
|
||||
|
||||
### Code Improvements
|
||||
- **Lines Removed**: ~60 lines (redundant code)
|
||||
- **Files Deleted**: 2 (canvas-parser.ts, CanvasEntry.ts)
|
||||
- **Architecture**: Simplified from 3-layer to 2-layer Canvas parsing
|
||||
- **Code Reuse**: Shared utilities between parser and updater
|
||||
|
||||
### Quality Metrics
|
||||
- ✅ **TypeScript**: No compilation errors
|
||||
- ✅ **Build**: Successful (3.3MB bundle)
|
||||
- ✅ **Tests**: Canvas-specific tests passing
|
||||
- ✅ **Backward Compatibility**: Maintained through static methods
|
||||
|
||||
## Next Actions
|
||||
|
||||
1. ✅ Document current state
|
||||
2. ✅ Remove canvas-parser.ts redirect
|
||||
3. ✅ Remove old TaskParserConfig interface
|
||||
4. ✅ Test changes
|
||||
5. ✅ Proceed with Phase 2
|
||||
6. ⬜ Consider Phase 3 (Unified Parser Architecture) for future major refactor
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
# Review: 待修复 Bugs 列表(2025-09-04)
|
||||
|
||||
说明:以下清单基于当前代码与已知反馈整理。已确认不纳入本次修复范围的项:
|
||||
- [已修复] 任务在 Task View 中编辑后不更新(原问题 #2)
|
||||
- [暂不考虑] List View 渲染卡顿(原问题 #4)
|
||||
- [已在新架构修复] 启动时任务重建漏项(原问题 #7)
|
||||
|
||||
以下为仍需修复的问题与建议方案:
|
||||
|
||||
## 1) 过滤器输入导致实时加载,Task View 打开时性能大幅下降(原问题 #1)
|
||||
- 现象:在“视图过滤器”输入每个字符时就触发刷新,造成频繁过滤与重渲染。
|
||||
- 涉及模块:
|
||||
- 过滤器组件事件广播:`src/components/features/task/filter/ViewTaskFilter.ts`(saveStateToLocalStorage → 触发 `task-genius:filter-changed`)
|
||||
- TaskView 处理防抖:`src/pages/TaskView.ts`(`debouncedApplyFilter` 当前延时较短)
|
||||
- 文本搜索即时刷新:`src/components/features/task/view/content.ts`(`filterTasks`)
|
||||
- 修复建议:
|
||||
- 提高 TaskView 内 `debouncedApplyFilter` 延迟(建议 300–500ms)。
|
||||
- 在 ViewTaskFilter 中对输入框 `input` 事件增加本地防抖;或编辑时 `saveStateToLocalStorage(triggerRealtimeUpdate=false)`,提交/失焦时再广播。
|
||||
- ContentComponent 的文本搜索同样使用防抖(约 300ms)。
|
||||
- 验收:连续输入时渲染频率显著下降;大型数据集输入体验流畅,无明显掉帧。
|
||||
|
||||
## 2) 视图顺序在设置中调整后,Task View 侧边栏未按顺序展示(原问题 #3)
|
||||
- 现象:Views & Index 页中上下移动视图后,侧边栏排序不一致。
|
||||
- 涉及模块:
|
||||
- 设置页顺序变更:`src/components/features/settings/tabs/ViewSettingsTab.ts`
|
||||
- 侧边栏渲染:`src/components/features/task/view/sidebar.ts`(当前将视图分为默认/自定义/底部组,改变了原始顺序)
|
||||
- 修复建议:
|
||||
- 侧边栏按 `settings.viewConfiguration` 原始顺序渲染(仅过滤 `visible`),不要再额外分组打乱顺序。
|
||||
- 若需“底部固定组”(habit/calendar/gantt/kanban),可在设置层面赋予“区域”属性,或在数据层维护顺序一致性。
|
||||
- 验收:在设置中调整顺序后,侧边栏显示顺序与设置数组一致。
|
||||
|
||||
## 3) 编辑包含任务的文件时,Task View 展示的文本出现偏差,需关闭重开才正确(原问题 #5)
|
||||
- 现象:外部编辑器或 Obsidian 编辑某文件中的任务时,Task View 中对应条目短时间显示不一致内容。
|
||||
- 涉及模块:
|
||||
- 任务缓存更新与视图刷新:`src/pages/TaskView.ts`(监听 `TASK_CACHE_UPDATED`,`debouncedViewUpdate` 刷新)
|
||||
- 列表项 Markdown 渲染:`src/components/features/task/view/listItem.ts`(`renderMarkdown` 使用 `task.originalMarkdown`)
|
||||
- 修复建议:
|
||||
- 稳定事件节奏:适度加大 `debouncedViewUpdate` 延迟或合并短时间内的多次更新,避免“半成品”快照进入 UI。
|
||||
- 确保外部写入后再触发一次最终刷新(Orchestrator rebuild/快照完成时统一触发视图更新)。
|
||||
- 列表项渲染前确保完全清理旧内容(已 empty)并使用最新 `originalMarkdown` 渲染。
|
||||
- 验收:编辑文件后,无需关闭重开,Task View 即可稳定显示最终内容,无中间错乱。
|
||||
|
||||
## 4) 自定义任务视图从分栏(split)模式无法切回单列模式(原问题 #6)
|
||||
- 现象:编辑自定义视图时,无法从“两列视图”回到“单列视图”。
|
||||
- 涉及模块:
|
||||
- 两列视图基类与切换:`src/components/features/task/view/TwoColumnViewBase.ts`
|
||||
- 视图创建/切换:`src/pages/TaskView.ts`(根据 `viewConfig.specificConfig.viewType === "twocolumn"` 决定)
|
||||
- 视图配置弹窗:`src/components/features/task/view/modals/ViewConfigModal.ts`
|
||||
- 修复建议:
|
||||
- 在 ViewConfigModal 中暴露“视图布局类型”(single/twocolumn)切换;保存后更新 `viewConfiguration`。
|
||||
- TaskView 在 `onSettingsUpdate` 时销毁/隐藏旧的 TwoColumn 组件,恢复常规 ContentComponent,并刷新当前视图。
|
||||
- 验收:用户可在配置中自由切换布局,保存后侧边栏对应视图正确切换模式。
|
||||
|
||||
## 5) 勾选一个习惯时,偶发地所有习惯都被勾选(原问题 #8)
|
||||
- 现象:点击单个 Habit 打勾,偶发地其它 Habit 也被更新。
|
||||
- 涉及模块:
|
||||
- Habit 勾选入口:`src/components/features/habit/habitcard/habitcard.ts`(`toggleHabitCompletion`)
|
||||
- 写回与索引:`src/managers/habit-manager.ts`(`updateHabitInObsidian` 与后续 habit 索引更新)
|
||||
- 修复建议:
|
||||
- 校验 Habit `id` 的唯一性与全链路使用一致;仅更新目标 habit 的 `completions[today]`。
|
||||
- 写回模板/标记仅定位目标 habit 片段,避免通配批量替换。
|
||||
- 索引更新(map 遍历)中保持纯函数式修改,仅对目标 habit 变动,防止共享引用导致联动。
|
||||
- 验收:反复勾选单一 Habit,不会影响其它 Habit 的状态。
|
||||
|
||||
## 6) Ctrl+K 未能聚焦设置菜单的搜索框(原问题 #9)
|
||||
- 现象:提示文案包含 “(Ctrl+K)”,但快捷键无法聚焦搜索输入。
|
||||
- 涉及模块:
|
||||
- 设置搜索组件:`src/components/features/settings/components/SettingsSearchComponent.ts`
|
||||
- 设置页入口:`src/setting.ts`(创建搜索组件)
|
||||
- 修复建议:
|
||||
- 在 SettingsSearchComponent 内注册全局键盘监听:在 macOS 使用 `metaKey + K`,Windows/Linux 使用 `ctrlKey + K`,触发 `searchInputEl.focus()` 与结果弹出。
|
||||
- 或通过 SettingTab 的 Scope 定义快捷键绑定到聚焦行为。
|
||||
- 验收:在设置页按下 Ctrl/Cmd+K,输入框获得焦点并可立即搜索。
|
||||
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
# Storage API 修复记录
|
||||
|
||||
## 完成的修复
|
||||
|
||||
### 1. API 不匹配问题
|
||||
- **问题**: Storage.ts 使用了 LocalStorageCache 不存在的方法 `clearFile()` 和 `getKeys()`
|
||||
- **修复**:
|
||||
- 将所有 `clearFile()` 调用替换为 `removeFile()`
|
||||
- 将所有 `getKeys()` 调用替换为 `allFiles()` 或 `allKeys()`
|
||||
|
||||
### 2. 哈希校验逻辑不一致
|
||||
- **问题**:
|
||||
- `storeRaw()` 使用任务数组计算哈希
|
||||
- `isRawValid()` 使用文件内容计算哈希
|
||||
- 导致校验失真
|
||||
- **修复**:
|
||||
- 修改 `storeRaw()` 签名,增加可选的 `fileContent` 参数
|
||||
- 使用文件内容(如果提供)计算哈希,保持语义一致
|
||||
- 更新 Orchestrator.processFileImmediate() 调用,传入 fileContent
|
||||
|
||||
### 3. clearNamespace 实现修正
|
||||
- **问题**: 原实现使用底层的完整键,而非路径化键
|
||||
- **修复**:
|
||||
- 改为使用 `allFiles()` 获取路径化键
|
||||
- 按正确的前缀模式匹配和删除
|
||||
- 为每个命名空间定义明确的前缀映射
|
||||
|
||||
### 4. consolidated 快照 API 统一
|
||||
- **问题**: 混用了 `loadFile()` 和专用的 consolidated API
|
||||
- **修复**:
|
||||
- `loadConsolidated()` 改用 `loadConsolidatedCache()`
|
||||
- `storeConsolidated()` 改用 `storeConsolidatedCache()`
|
||||
- 保持与 LocalStorageCache 的设计一致
|
||||
|
||||
### 5. getStats() 统计方法修正
|
||||
- **问题**: 使用底层键统计,计数不准确
|
||||
- **修复**:
|
||||
- 改用 `allFiles()` 获取路径化键
|
||||
- 按正确的前缀模式统计各命名空间的文件数
|
||||
|
||||
## 影响范围
|
||||
|
||||
### 修改的文件
|
||||
1. `/src/dataflow/persistence/Storage.ts` - 主要修复
|
||||
2. `/src/dataflow/Orchestrator.ts` - 更新 storeRaw() 调用参数
|
||||
|
||||
### 行为改进
|
||||
- ✅ 冷启动优先从快照加载,无需等待索引
|
||||
- ✅ 单文件内容校验准确可靠
|
||||
- ✅ 命名空间清理功能正常工作
|
||||
- ✅ 统计数据准确反映实际存储状态
|
||||
- ✅ 版本不兼容时正确清理过期缓存
|
||||
|
||||
## 后续建议
|
||||
|
||||
### 短期优化
|
||||
1. 考虑将 Keys 命名空间管理抽象为独立的 helper 类
|
||||
2. 添加单元测试覆盖所有存储操作
|
||||
3. 增加缓存命中率的监控指标
|
||||
|
||||
### 长期改进
|
||||
1. 实现渐进式 schema 迁移器,而非简单的版本检查删除
|
||||
2. 考虑添加缓存压缩机制以减少存储空间占用
|
||||
3. 实现更智能的缓存淘汰策略(LRU/LFU)
|
||||
|
||||
## 验证清单
|
||||
|
||||
- [x] removeFile() 方法调用正常
|
||||
- [x] allFiles() 返回正确的路径化键
|
||||
- [x] clearNamespace 按前缀正确删除
|
||||
- [x] consolidated API 使用统一
|
||||
- [x] 哈希校验逻辑一致
|
||||
- [x] getStats() 统计准确
|
||||
- [x] Orchestrator 传参更新
|
||||
|
||||
## 相关文档
|
||||
- [TaskIndexer 迁移计划](./taskindexer-migration-plan.md)
|
||||
- [Dataflow 架构文档](./dataflow-architecture.md)
|
||||
|
|
@ -1,232 +0,0 @@
|
|||
## Task Genius 数据流全面重构计划(Refactor Plan)
|
||||
|
||||
### 目的(Goals)
|
||||
- 去重与统一:消除项目识别、文件级元数据解析、任务解析、增强/继承、索引、缓存、持久化、事件传递在多处重复实现与分散入口的问题。
|
||||
- 稳定与持久:建立单一数据源与可验证的数据流,降低未来演进/扩展成本。
|
||||
- 一致与同步:保证视图数据与底层缓存/索引严格一致,避免“视图数据不同步”。
|
||||
- 快速冷启动:最大程度复用持久化数据,避免用户反复 reindex。
|
||||
- 事件驱动:所有上行/下行数据变更通过 Obsidian 事件系统传播,而不是上级组件直接 setTasks。
|
||||
- 增量更新:跟随 Obsidian 的 vault/metadataCache/设置事件做最小代价的增量更新。
|
||||
|
||||
### 非目标(Non-goals)
|
||||
- 不改变用户可见的功能语义与现有配置的含义(除非标注为改进项)。
|
||||
- 不一次性大爆炸替换;采用阶段性迁移确保回退路径。
|
||||
|
||||
---
|
||||
|
||||
## 设计原则
|
||||
- 单一职责与单一真相源(Single Source of Truth):
|
||||
- 项目识别只在 ProjectResolver(统一接口)进行;解析器与增强器不再分散探测。
|
||||
- 继承/增强只在 TaskAugmentor 进行;解析器仅负责“从文本抽取”。
|
||||
- 事件优于回调:统一使用 Obsidian workspace 事件分发数据变更,视图通过事件 + 查询 API 获取数据。
|
||||
- 可重放、可回退:Worker 与主线程遵循相同协议;主线程兜底。
|
||||
- 可持久与可验证:内容哈希 + 版本/架构版本管理;命名空间化缓存;精细化失效与一致性校验。
|
||||
- 增量优先:文件内容变动仅重解析该文件;项目配置变动仅重跑增强;设置变动按 scope 精准失效。
|
||||
- 向后兼容:提供 Adapter 兼容旧 setTasks 调用路径,逐步下线。
|
||||
|
||||
---
|
||||
|
||||
## 数据拥有权与边界(Ownership)
|
||||
- 源事件(File events):ObsidianSource 拥有,统一发出内部文件事件。
|
||||
- 项目识别(Project):ProjectResolver 拥有,对外只暴露“文件 → {tgProject, enhancedMetadata}”。
|
||||
- 解析器(Parsers):Markdown/Canvas/FileLevel 仅负责“抽取任务/文件级任务”,不写入项目或其他增强信息。
|
||||
- 增强/继承(Augment):TaskAugmentor 拥有“task > file > project”的可配置优先级合并。
|
||||
- 索引(Indexing):TaskIndexer 拥有内存索引与查询,不做解析与增强。
|
||||
- 持久化(Persistence):StorageAdapter(基于 LocalStorageCache)拥有命名空间与 hash/版本校验。
|
||||
- 事件与查询(Events & Query):Events 模块拥有事件契约;QueryAPI 对外只读查询。
|
||||
|
||||
---
|
||||
|
||||
## 目标数据流(高层)
|
||||
1) Obsidian 事件 → Sources 标准化为 FileChanged/FileDeleted/Renamed 等内部事件。
|
||||
2) ParsersEntry(根据文件类型)抽取:
|
||||
- FileLevelTaskParser:从 frontmatter/tags 形成“文件级任务”。
|
||||
- MarkdownTaskParserEntry / CanvasTaskParserEntry:从正文生成“基础任务”。
|
||||
3) ProjectResolver 计算项目 + 项目增强元数据(可并行)。
|
||||
4) TaskAugmentor:将“文件级 + 正文任务”与“文件元数据 + 项目增强元数据”按策略合并到任务对象。
|
||||
5) TaskIndexer.updateIndexWithTasks(filePath, tasksEnhanced)。
|
||||
6) Persistence:写入命名空间缓存(见下);必要时更新 consolidated 索引快照。
|
||||
7) 事件广播 task-genius:task-cache-updated { changedFiles }。
|
||||
8) 视图订阅事件 → QueryAPI 拉取 → 渲染。
|
||||
|
||||
---
|
||||
|
||||
## 组件与目录结构(建议新增 src/dataflow/*)
|
||||
- sources/ObsidianSource.ts
|
||||
- 订阅 vault/metadataCache/设置事件;统一去抖与批量合并;发出内部文件事件。
|
||||
- project/ProjectResolver.ts
|
||||
- 合并现有 ProjectConfigManager + ProjectDataCache/Worker 的“对外接口”。
|
||||
- 输入:filePath;输出:{ tgProject?, enhancedMetadata, timestamp }。
|
||||
- 统一“frontmatter 指定项目、目录 config、tag/link 提示”的优先级;可配置。
|
||||
- parsers/
|
||||
- MarkdownTaskParserEntry.ts(包装 ConfigurableTaskParser.parseLegacy)
|
||||
- CanvasTaskParserEntry.ts(包装 CanvasParser)
|
||||
- FileLevelTaskParser.ts(包装 FileMetadataTaskParser,禁用内部项目探测)
|
||||
- augment/TaskAugmentor.ts
|
||||
- 单一继承/增强实现:
|
||||
- 标量:task 显式 > file > project > 默认
|
||||
- 数组:合并去重(保持稳定次序)
|
||||
- 状态/完成:只取 task 行级
|
||||
- 复发:task 显式优先
|
||||
- 子任务继承:按 FileMetadataInheritance/设置 per-key 控制
|
||||
- workers/WorkerOrchestrator.ts
|
||||
- 统一任务/项目命令:parseFileTasks、batchParse、computeProjectData、batchCompute
|
||||
- 并发控制、重试、回退、指标
|
||||
- indexer/TaskRepository.ts
|
||||
- 组合 TaskIndexer + Persistence;提供查询 API 的后端依赖
|
||||
- persistence/StorageAdapter.ts
|
||||
- 命名空间 + hash(内容)+ 版本/架构版本 + 粒度化失效
|
||||
- Keyspace:
|
||||
- tasks.raw:<filePath>
|
||||
- project.data:<filePath>
|
||||
- tasks.augmented:<filePath>
|
||||
- consolidated:taskIndex
|
||||
- meta:version / meta:schemaVersion
|
||||
- events/Events.ts
|
||||
- 事件常量/载荷类型/帮助方法(emit/subscribe)。与 obsidian-ex.d.ts 契约一致。
|
||||
- api/QueryAPI.ts
|
||||
- 为视图提供只读查询(按项目/标签/状态/时间窗口等),屏蔽内部实现细节。
|
||||
|
||||
---
|
||||
|
||||
## 最大化避免与现有功能重复的策略
|
||||
1) 单一入口与关停重复:
|
||||
- FileMetadataTaskParser:关闭其内部项目探测,统一由 ProjectResolver 提供 project 值后在 Augmentor 注入。
|
||||
- ConfigurableTaskParser/CanvasParser:不处理项目/继承,仅返回“基础任务”。
|
||||
- TaskManager 内的解析/增强/持久化逻辑收敛到新模块,TaskManager 变为编排薄层。
|
||||
2) 功能所有权迁移表(旧 → 新):
|
||||
- 项目识别:FileMetadataTaskParser.detectProjectFromFile / ProjectData* → ProjectResolver
|
||||
- 继承/增强:ConfigurableTaskParser 内部继承 / FileMetadataInheritance 分散 → TaskAugmentor
|
||||
- 数据广播:上层 setTasks → Events + QueryAPI
|
||||
- Worker 管理:TaskWorkerManager/ProjectDataWorkerManager → WorkerOrchestrator(内部保留原 Worker)
|
||||
- 持久化:LocalStorageCache 直接使用 → StorageAdapter 管理命名空间/版本/hash
|
||||
3) Adapter 与 Deprecation:
|
||||
- ViewComponentManager.setTasks 标记 deprecated;提供兼容 Adapter:setTasks 内部转为发事件 + 触发查询,避免一次性改动所有视图。
|
||||
- FileMetadataTaskParser 暴露“允许/禁止项目探测”开关;重构期禁用。
|
||||
|
||||
---
|
||||
|
||||
## 视图同步与一致性保证
|
||||
- 事件驱动 + 拉取查询:视图统一订阅 task-genius:task-cache-updated / filter-changed,随后调用 QueryAPI 拉取。彻底替代上级 setTasks 链接。
|
||||
- 原子性:单文件变更导出单批次“增强后任务”提交到 Indexer,再触发事件,视图永远看到同一版本。
|
||||
- 序号/时间戳:在广播载荷中携带 sequence/timestamp,视图可丢弃过期更新。
|
||||
- 去抖/批量:Sources 对频繁变动进行批处理,减少 UI 抖动。
|
||||
- 兼容策略:在迁移期间,旧视图通过 Adapter 仍可工作。
|
||||
|
||||
---
|
||||
|
||||
## 持久化与缓存策略
|
||||
- 命名空间:
|
||||
- tasks.raw:<filePath> → 基础解析结果
|
||||
- project.data:<filePath> → {tgProject, enhancedMetadata}
|
||||
- tasks.augmented:<filePath> → Augmentor 合成产物(可选,提升冷启动)
|
||||
- consolidated:taskIndex → 全量索引快照(可选)
|
||||
- 版本与架构版本:
|
||||
- meta:version(插件版本) + meta:schemaVersion(缓存结构版本);不兼容时精准清理对应命名空间。
|
||||
- 内容哈希:
|
||||
- tasks.raw 基于文件内容 hash;project.data 基于“有效配置 + frontmatter + tags/links”等来源 hash。
|
||||
- 仅当 hash 改变时重算;mtime 仅用于快速预判。
|
||||
- 失效矩阵:
|
||||
- 文件正文变动:重算 tasks.raw → augment → 更新 index → 事件。
|
||||
- 文件 frontmatter/tags 变动:重做 file→task 继承与 augment(若正文未变,可跳过正文解析)。
|
||||
- 项目配置变动:仅失效 project.data 与 tasks.augmented,重做 augment;跳过正文解析。
|
||||
- 设置变动:按 scope(解析/增强/索引)精准失效。
|
||||
|
||||
---
|
||||
|
||||
## 失败与回退
|
||||
- Worker 异常:自动回退主线程解析;熔断/退避重试;错误事件与日志。
|
||||
- 缓存损坏:校验失败则清理对应命名空间并重建;保留其余命名空间。
|
||||
- 事件风暴:限流与批处理;视图侧忽略过期序号。
|
||||
|
||||
---
|
||||
|
||||
## 性能与 SLO
|
||||
- 冷启动:优先使用 consolidated:taskIndex 或 tasks.augmented,目标 P50 < 300ms(视库大小微调)。
|
||||
- 增量更新:单文件保存到视图更新 P95 < 150ms(含解析 + augment + index + 事件)。
|
||||
- 内存:索引结构保持与现有相当;新增缓存命名空间带来可控增量。
|
||||
|
||||
---
|
||||
|
||||
## 向后兼容与迁移
|
||||
- Adapter:
|
||||
- 视图 setTasks 调用 → 转为发事件并触发 QueryAPI,从而兼容旧代码;逐视图切换到纯事件。
|
||||
- 逐步替换:
|
||||
- ProjectResolver 接管后,禁用 FileMetadataTaskParser 的项目探测。
|
||||
- Augmentor 接管继承后,解析器不再做继承。
|
||||
- 配置兼容:沿用原设置字段并提供合理默认;新增 per-key 策略作为高级选项。
|
||||
|
||||
---
|
||||
|
||||
## 阶段性实施与检查清单
|
||||
Phase A:事件封装 + 查询 API(2 天)
|
||||
- [ ] 新增 events/Events.ts,封装现有触发点(保持事件名兼容)。
|
||||
- [ ] 新增 api/QueryAPI.ts,提供最小查询(全部任务/按项目/按标签)。
|
||||
- [ ] TaskManager 触发统一走 Events.ts。
|
||||
|
||||
Phase B:解析入口收敛 + Augmentor(3 天)
|
||||
- [ ] 新建 parsers/*Entry.ts;主线程路径先打通。
|
||||
- [ ] 新建 augment/TaskAugmentor.ts,落地继承策略(task>file>project)。
|
||||
- [ ] 修改 FileMetadataTaskParser:允许禁用项目探测(默认禁用)。
|
||||
|
||||
Phase C:持久化命名空间 + hash(2 天)
|
||||
- [ ] StorageAdapter.ts:命名空间 + 版本/架构版本 + hash。
|
||||
- [ ] 冷启动优先加载 consolidated 或 tasks.augmented;兼容旧数据。
|
||||
|
||||
Phase D:WorkerOrchestrator(3 天)
|
||||
- [ ] 合并任务/项目 worker 调度;统一命令协议与回退策略。
|
||||
- [ ] 指标与日志:成功率、延迟、退避情况。
|
||||
|
||||
Phase E:视图去 setTasks(试点 2 个视图)(3 天)
|
||||
- [ ] 视图订阅事件 + QueryAPI 拉取;移除直接 setTasks。
|
||||
- [ ] 保留 Adapter 以兼容未迁移视图。
|
||||
|
||||
Phase F:项目配置变更仅增强重算(2 天)
|
||||
- [ ] 变更监听 → 失效 project.data 与 tasks.augmented → augment → 事件。
|
||||
|
||||
Phase G:全面测试与性能调优(2 天)
|
||||
- [ ] 单测/集成测补齐;SLO 校验;回归修复。
|
||||
|
||||
---
|
||||
|
||||
## 测试计划(重点)
|
||||
- 冷启动:无修改 → 不 reindex;版本兼容 → 直接用。
|
||||
- 文件增量:正文变更、frontmatter/tags 变更、重命名/删除;仅影响对应文件。
|
||||
- 项目配置变更:仅增强重算;正文不解析。
|
||||
- 设置变更:按 scope 精准失效。
|
||||
- 事件一致性:视图通过事件 + 查询看到一致数据;序号去重验证。
|
||||
- 兼容回归:
|
||||
- 空/Null 排序规则:空值永远排在非空之后(双向排序)。
|
||||
- 中文标签重复历史问题:复发任务创建链路校验不重复,解析层不二次注入。
|
||||
- 性能:P50/P95 指标达标;压力下稳定。
|
||||
|
||||
---
|
||||
|
||||
## 回退计划
|
||||
- 任意阶段可切回旧路径:
|
||||
- 解析:保留旧 TaskWorkerManager/TaskManager 主路径开关。
|
||||
- 事件:保留 setTasks Adapter。
|
||||
- 缓存:清空新命名空间后回退旧 consolidated 流程。
|
||||
|
||||
---
|
||||
|
||||
## 开放问题(需确认)
|
||||
- 事件载荷是否需要强制携带 diff(新增/删除/修改的 taskIds)以优化大视图刷新?
|
||||
- 默认继承策略中是否存在“项目优先于文件”的字段(例如 SLA 类字段)?
|
||||
- consolidated:taskIndex 是否纳入默认启用,还是作为可选以节省空间?
|
||||
|
||||
---
|
||||
|
||||
## 附:事件契约(建议)
|
||||
- task-genius:cache-ready { initial: boolean, timestamp, seq }
|
||||
- task-genius:task-cache-updated { changedFiles?: string[], stats?, timestamp, seq }
|
||||
- task-genius:file-updated { path, reason, timestamp }
|
||||
- task-genius:project-data-updated { affectedFiles: string[], timestamp }
|
||||
- task-genius:settings-changed { scopes: string[], timestamp }
|
||||
|
||||
说明:保持与现有 obsidian-ex.d.ts 的兼容命名(如 task-cache-updated)。
|
||||
|
||||
---
|
||||
|
||||
## 结束语
|
||||
本方案以“单一真相源 + 事件驱动 + 命名空间缓存 + 可回退”为核心,最大化复用现有解析/索引能力,在不破坏现有功能的前提下,消除重复与耦合点,确保视图数据与缓存/索引一致。分阶段推进、可测可回退,可支撑后续长期演进。
|
||||
|
|
@ -1,164 +0,0 @@
|
|||
## Task Genius 数据流重构实施规范(Implementation Spec)
|
||||
|
||||
本规范补充《task-genius-refactor-plan.md》,面向执行同学,提供可直接落地的事件载荷类型、QueryAPI 函数签名、StorageAdapter 的 Key 规则,以及示例代码与任务清单。
|
||||
|
||||
---
|
||||
|
||||
### 1. 事件载荷类型(建议)
|
||||
|
||||
事件名称与 obsidian-ex.d.ts 兼容,并统一通过 Events.ts 导出常量与帮助方法。
|
||||
|
||||
- task-genius:cache-ready
|
||||
- payload: { initial: boolean; timestamp: number; seq: number }
|
||||
- task-genius:task-cache-updated
|
||||
- payload: { changedFiles?: string[]; stats?: { total: number; changed: number }; timestamp: number; seq: number }
|
||||
- task-genius:file-updated
|
||||
- payload: { path: string; reason: "modify" | "frontmatter" | "rename" | "delete"; timestamp: number }
|
||||
- task-genius:project-data-updated
|
||||
- payload: { affectedFiles: string[]; reason?: string; timestamp: number }
|
||||
- task-genius:settings-changed
|
||||
- payload: { scopes: ("parser" | "augment" | "index" | "view")[]; timestamp: number }
|
||||
- 保留:task-genius:task-completed/task-added/task-updated/task-deleted(按现有类型)
|
||||
|
||||
辅助:
|
||||
- seq 为单调递增序号(TaskRepository 维护)
|
||||
- timestamp 为事件生成时间
|
||||
|
||||
---
|
||||
|
||||
### 2. QueryAPI 函数签名(草案)
|
||||
|
||||
文件:src/dataflow/api/QueryAPI.ts
|
||||
|
||||
- getAllTasks(): Promise<Task[]>
|
||||
- getTasksByProject(projectName: string): Promise<Task[]>
|
||||
- getTasksByTags(tags: string[]): Promise<Task[]>
|
||||
- getTasksByStatus(completed: boolean): Promise<Task[]>
|
||||
- getTasksByDateRange(opts: { from?: number; to?: number; field?: "due" | "start" | "scheduled" }): Promise<Task[]>
|
||||
- getTaskById(id: string): Promise<Task | null>
|
||||
- getIndexSummary(): Promise<{ total: number; byProject: Record<string, number>; byTag: Record<string, number> }>
|
||||
|
||||
实现要点:
|
||||
- 背后依赖 TaskRepository(组合 TaskIndexer + Persistence),严禁直接访问内部索引结构于视图层。
|
||||
- 函数返回的 Task 均为“增强后任务”。
|
||||
|
||||
---
|
||||
|
||||
### 3. StorageAdapter Key 规则与版本
|
||||
|
||||
文件:src/dataflow/persistence/StorageAdapter.ts
|
||||
|
||||
- 命名空间规范(namespace:key)
|
||||
- tasks.raw:<filePath>
|
||||
- project.data:<filePath>
|
||||
- tasks.augmented:<filePath>
|
||||
- consolidated:taskIndex
|
||||
- meta:version(插件版本)
|
||||
- meta:schemaVersion(缓存架构版本)
|
||||
|
||||
- 哈希与版本
|
||||
- tasks.raw 记录:{ hash: string; time: number; version: string; schema: number; data: Task[] }
|
||||
- project.data 记录:{ hash: string; time: number; version: string; schema: number; data: { tgProject?: TgProject; enhancedMetadata: Record<string, any> } }
|
||||
- tasks.augmented 记录:{ hash: string; time: number; version: string; schema: number; data: Task[] }
|
||||
- consolidated:taskIndex 记录:{ time: number; version: string; schema: number; data: TaskCacheSnapshot }
|
||||
|
||||
- 兼容策略
|
||||
- 版本或 schema 不兼容时仅清理受影响命名空间。
|
||||
- hash 优先判定是否需要重算;mtime 仅作为辅助。
|
||||
|
||||
---
|
||||
|
||||
### 4. 代码示例(2 段)
|
||||
|
||||
示例 A:视图订阅事件 + QueryAPI 拉取(替代 setTasks)
|
||||
|
||||
```ts
|
||||
// 在某视图 onOpen 内
|
||||
import { subscribeTaskCacheUpdated } from "src/dataflow/events/Events";
|
||||
import { QueryAPI } from "src/dataflow/api/QueryAPI";
|
||||
|
||||
let unsub: () => void;
|
||||
this.registerEvent(
|
||||
(unsub = subscribeTaskCacheUpdated(async (payload) => {
|
||||
const tasks = await QueryAPI.getTasksByProject(this.currentProject ?? "");
|
||||
this.renderer.render(tasks); // 视图自身的渲染方法
|
||||
}))
|
||||
);
|
||||
|
||||
// onClose 时
|
||||
if (unsub) unsub();
|
||||
```
|
||||
|
||||
示例 B:单文件变更 → 解析 + 增强 + 索引 + 事件
|
||||
|
||||
```ts
|
||||
import { ParsersEntry } from "src/dataflow/parsers";
|
||||
import { ProjectResolver } from "src/dataflow/project/ProjectResolver";
|
||||
import { TaskAugmentor } from "src/dataflow/augment/TaskAugmentor";
|
||||
import { TaskRepository } from "src/dataflow/indexer/TaskRepository";
|
||||
import { emitTaskCacheUpdated } from "src/dataflow/events/Events";
|
||||
import { StorageAdapter } from "src/dataflow/persistence/StorageAdapter";
|
||||
|
||||
async function handleFileChanged(filePath: string) {
|
||||
// 1. 尝试读取 tasks.raw(hash 命中则跳过正文解析)
|
||||
const raw = await StorageAdapter.loadRaw(filePath);
|
||||
const needsParse = !(raw && StorageAdapter.isRawValid(filePath, raw));
|
||||
const rawTasks = needsParse
|
||||
? await ParsersEntry.parseFile(filePath) // Markdown/Canvas/FileLevel 分流
|
||||
: raw.data;
|
||||
|
||||
if (needsParse) await StorageAdapter.storeRaw(filePath, rawTasks);
|
||||
|
||||
// 2. 读取/计算项目数据(可并行)
|
||||
const proj = await ProjectResolver.getProjectData(filePath);
|
||||
await StorageAdapter.storeProjectData(filePath, proj);
|
||||
|
||||
// 3. 增强合并
|
||||
const augmented = await TaskAugmentor.merge({ filePath, rawTasks, project: proj });
|
||||
await StorageAdapter.storeAugmented(filePath, augmented);
|
||||
|
||||
// 4. 更新索引
|
||||
await TaskRepository.updateFile(filePath, augmented);
|
||||
|
||||
// 5. 广播事件
|
||||
emitTaskCacheUpdated({ changedFiles: [filePath], timestamp: Date.now() });
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5. 执行清单(给贡献者)
|
||||
|
||||
1) 新增骨架文件
|
||||
- src/dataflow/events/Events.ts:事件常量与 emit/subscribe;内部维护 seq。
|
||||
- src/dataflow/api/QueryAPI.ts:空壳方法先返回现有 TaskManager 数据(过渡)。
|
||||
- src/dataflow/parsers/MarkdownTaskParserEntry.ts:包装现有 ConfigurableTaskParser.parseLegacy。
|
||||
- src/dataflow/parsers/CanvasTaskParserEntry.ts:包装现有 CanvasParser。
|
||||
- src/dataflow/parsers/FileLevelTaskParser.ts:包装现有 FileMetadataTaskParser,并添加“禁用项目探测”配置(默认禁用)。
|
||||
- src/dataflow/augment/TaskAugmentor.ts:实现继承策略(task>file>project);支持子任务控制。
|
||||
- src/dataflow/project/ProjectResolver.ts:统一项目识别接口;内部复用 ProjectConfigManager/ProjectDataCache。
|
||||
- src/dataflow/persistence/StorageAdapter.ts:命名空间 + 版本/schema + hash 校验;读写 helpers。
|
||||
- src/dataflow/indexer/TaskRepository.ts:组合 TaskIndexer 与 StorageAdapter;对外提供查询。
|
||||
|
||||
2) TaskManager 接入
|
||||
- 触发事件统一改为 Events.ts 的封装。
|
||||
- 冷启动改为优先读取 consolidated 或 tasks.augmented,失败再回落旧流程。
|
||||
- 单文件变更路径替换为“解析入口 + Augmentor + Repository”的新流水线(逐步灰度)。
|
||||
|
||||
3) 视图迁移(首批 1-2 个)
|
||||
- 去除直接 setTasks 调用,改成订阅 task-cache-updated + QueryAPI 拉取。
|
||||
- 保留 Adapter 以兼容未迁移视图。
|
||||
|
||||
4) 持久化与失效策略
|
||||
- 引入命名空间 key 规则与 hash 计算;对项目配置变更只失效 project.data 与 tasks.augmented。
|
||||
|
||||
5) 测试
|
||||
- 单测:ParsersEntry、TaskAugmentor(继承策略)、StorageAdapter(hash/版本/失效)、ProjectResolver(优先级)。
|
||||
- 集成:单文件改动/重命名/删除、项目配置变更、冷启动、事件序号。
|
||||
|
||||
6) 文档
|
||||
- 在 README 或开发文档中标注 setTasks 已废弃(迁移至事件 + QueryAPI)。
|
||||
|
||||
---
|
||||
|
||||
如需我补充具体类型定义(TypeScript 接口)或更详细的函数注释,请告知要优先完善的模块。
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
# TaskIndexer 迁移动计划
|
||||
|
||||
## 1. 目标
|
||||
- 将 TaskIndexer 从 `src/utils/import/TaskIndexer.ts` 迁移至 `src/dataflow/indexer/TaskIndexer.ts`。
|
||||
- 统一“索引层”的所有权到 dataflow 命名空间,减少新旧架构交叉依赖。
|
||||
- 保持功能零回归、提供兼容过渡(re-export),并具备可快速回滚能力。
|
||||
|
||||
## 2. 现状与依赖
|
||||
- 现有引用(至少):
|
||||
- dataflow: `src/dataflow/indexer/Repository.ts` → `../../utils/import/TaskIndexer`
|
||||
- legacy: `src/utils/TaskManager.ts` → `./import/TaskIndexer`
|
||||
- 说明:Repository 属于 dataflow,却反向引用 utils 的 TaskIndexer;迁移后应改为本地引用 `./TaskIndexer`。
|
||||
|
||||
## 3. 分阶段迁移步骤
|
||||
|
||||
### 阶段 A:平滑迁移与适配(兼容期)
|
||||
1) 移动实现
|
||||
- 将 `src/utils/import/TaskIndexer.ts` 的实现移动到 `src/dataflow/indexer/TaskIndexer.ts`。
|
||||
- 修正文件内部的相对导入路径(若有)。
|
||||
|
||||
2) 更新 dataflow 内部引用
|
||||
- 修改 `src/dataflow/indexer/Repository.ts` 导入:
|
||||
- `import { TaskIndexer } from "./TaskIndexer";`
|
||||
|
||||
3) 旧路径提供 re-export(保持旧架构可用)
|
||||
- 将 `src/utils/import/TaskIndexer.ts` 改为仅转发:
|
||||
```ts
|
||||
export { TaskIndexer } from "../../dataflow/indexer/TaskIndexer";
|
||||
```
|
||||
|
||||
4) (可选)在 `src/dataflow/index.ts` 导出 TaskIndexer(仅当需要对外暴露)
|
||||
|
||||
### 阶段 B:去耦旧架构依赖
|
||||
5) 旧 TaskManager 改用新路径
|
||||
- 在 `src/utils/TaskManager.ts` 将导入改为:
|
||||
- `import { TaskIndexer } from "../dataflow/indexer/TaskIndexer";`(或继续依赖上一步 re-export,推荐直接走 dataflow)
|
||||
|
||||
6) 全仓替换引用
|
||||
- 搜索引用旧路径的地方(包含相对路径与别名路径),替换为 dataflow 新路径或保留通过 re-export 过渡。
|
||||
|
||||
7) 校验环依赖
|
||||
- 确认 utils → dataflow 的依赖不会引入 dataflow ↔ utils 的循环(若存在,则保持 TaskManager 通过 re-export 访问)。
|
||||
|
||||
### 阶段 C:收尾与清理
|
||||
8) 文档更新
|
||||
- 更新架构文档中 TaskIndexer 所有权,归属 `src/dataflow/indexer`。
|
||||
|
||||
9) 清理 re-export(下个版本周期)
|
||||
- 保留 `src/utils/import/TaskIndexer.ts` re-export 一个版本周期后,删除该文件。
|
||||
|
||||
10) 守护措施(可选)
|
||||
- 在 `src/utils/import/` 目录添加 README 或 lint 规则,禁止新增 dataflow 相关实现,仅允许过渡性 re-export。
|
||||
|
||||
## 4. 任务清单(派工用)
|
||||
- A1 移动实现并修正内部导入
|
||||
- A2 更新 Repository 导入路径
|
||||
- A3 添加 re-export 兼容层
|
||||
- B1 更新 TaskManager 导入为 dataflow 新路径
|
||||
- B2 全仓替换其他引用(如有)
|
||||
- B3 编译/类型检查 + 本地运行验证
|
||||
- C1 更新 docs(dataflow-architecture 等)
|
||||
- C2 移除 re-export(一个版本周期后)
|
||||
|
||||
## 5. 验收标准(DoD)
|
||||
- 构建与类型检查通过,无循环依赖警告
|
||||
- dataflow 默认路径正常:
|
||||
- 冷启动从 Storage 快照恢复成功(Repository.initialize)
|
||||
- 事件广播与视图刷新正常(CACHE_READY/TASK_CACHE_UPDATED)
|
||||
- 旧 TaskManager 路径仍可回退使用(过渡期)
|
||||
- 全仓再无对 `utils/import/TaskIndexer` 的直接实现引用(仅允许 re-export 在过渡期存在)
|
||||
|
||||
## 6. 风险与回滚
|
||||
- 风险:隐性引用遗漏
|
||||
- 缓解:grep 全仓 `from "./import/TaskIndexer"` 与 `from "../../utils/import/TaskIndexer"`。
|
||||
- 风险:环依赖
|
||||
- 缓解:TaskManager 如引入环,则继续通过 re-export 访问;确认后再做进一步解耦。
|
||||
- 回滚:保留 re-export 不删即可回滚(Repository 可临时指回旧路径)。
|
||||
|
||||
## 7. 预估工作量
|
||||
- A–B:0.5–1 天(含全仓引用更新与验证)
|
||||
- C:合并后 1 个版本周期内清理(0.5 天)
|
||||
|
||||
|
|
@ -1,169 +0,0 @@
|
|||
# TaskManager → Dataflow 架构迁移计划
|
||||
|
||||
本计划用于逐步替换仓库内对 TaskManager 的依赖,全面切换到 Dataflow 架构(QueryAPI + Repository + Events + WorkerOrchestrator + WriteAPI)。
|
||||
|
||||
---
|
||||
|
||||
## 1. 现存 TaskManager 依赖清单(待迁移点)
|
||||
|
||||
以下为当前明确依赖 TaskManager 的文件与使用方式(以本仓库为范围):
|
||||
|
||||
- src/index.ts
|
||||
- 持有实例:`taskManager: TaskManager`
|
||||
- 初始化:在 onload 时 `new TaskManager(...)` 并 `this.addChild(this.taskManager)`
|
||||
- 与版本管理耦合:VersionManager 检测版本变化后调用 `taskManager.initialize()` 触发重建
|
||||
- 数据查询/回退:WriteAPI 的 `getTaskById` 优先 dataflow,失败则回退 `this.taskManager.getTaskById`
|
||||
- 其它:`setProgressManager()`、`initialize()`、`getAllTasks()` 等调用路径
|
||||
|
||||
- src/pages/TaskView.ts
|
||||
- 读取:`this.plugin.taskManager.getAllTasksWithSync()` / `this.plugin.taskManager.getAllTasks()`
|
||||
- 用于初始化与后续刷新
|
||||
|
||||
- src/mcp/McpServer.ts
|
||||
- 判断/桥接:在 dataflow 未启用时检查 `this.plugin.taskManager` 存在性
|
||||
- 绑定桥:`this.taskBridge = new TaskManagerBridge(this.plugin, this.plugin.taskManager)`
|
||||
|
||||
- src/mcp/bridge/TaskManagerBridge.ts
|
||||
- 广泛使用 TaskManager:查询/索引/更新/获取文件任务等(`getAllTasks`、`indexFile`、`getTasksForFile`、`updateTask` 等)
|
||||
|
||||
- 文档说明(需更新):
|
||||
- src/utils/README.md 描述了 TaskManager 是“Primary orchestrator”;迁移后将以 Dataflow 架构为主
|
||||
|
||||
> 备注:可能仍有零散依赖 `this.taskManager` 的地方,迁移期需通过全仓检索“`taskManager`”“`TaskManager`”逐步清理。
|
||||
|
||||
---
|
||||
|
||||
## 2. 迁移目标与原则
|
||||
|
||||
- 目标:所有读取、写入、索引、事件广播、缓存持久化均通过 Dataflow。
|
||||
- 原则:
|
||||
- 渐进式切换:在开关/灰度下替换调用者,优先完成“读取路径”迁移,随后完成“写入路径”与“初始化/重建路径”迁移。
|
||||
- 兼容性:在切换窗口期保留 TaskManager 适配器与回退路径,直到完成验证。
|
||||
- 稳定性优先:每一阶段完成后提供可回退的 feature flag。
|
||||
|
||||
---
|
||||
|
||||
## 3. 分阶段实施计划(建议顺序)
|
||||
|
||||
### Phase 0:开关与基础
|
||||
- 确认并使用既有 `settings.experimental.dataflowEnabled` 开关门控。
|
||||
- 在该开关打开时:严禁新的调用者再接入 TaskManager;新功能只接入 Dataflow。
|
||||
|
||||
### Phase 1:读取路径迁移(Views/MCP 查询)
|
||||
- 目标:所有“读”都从 Dataflow 的 QueryAPI/Repository 取数,而非 TaskManager。
|
||||
- 任务:
|
||||
1. 视图层(以 TaskView 为起点)
|
||||
- 改造 `TaskView`:
|
||||
- 将 `loadTasksFromTaskManager()` 替换为基于 Dataflow 的查询:
|
||||
- 订阅 Dataflow 事件 `CACHE_READY`(initial/非 initial)与 `TASK_CACHE_UPDATED`
|
||||
- 初次加载:`dataflowOrchestrator.queryAPI.getAllTasks()` 或基于筛选的查询
|
||||
- 去除对 `this.plugin.taskManager` 的直接读取
|
||||
2. MCP 查询层
|
||||
- 用 `DataflowBridge` 取代 `TaskManagerBridge`:
|
||||
- 若缺功能(如按条件查询/搜索/按日期范围等),扩展 `DataflowBridge`,通过 `QueryAPI`/`Repository` 实现
|
||||
- 在 `McpServer` 中:当 dataflowEnabled 时,优先创建并使用 `DataflowBridge`,不再依赖 `TaskManagerBridge`
|
||||
|
||||
- 验收:关闭 TaskManager 后,视图和 MCP 查询仍能完整工作(仅依赖 Dataflow)。
|
||||
|
||||
### Phase 2:写入路径统一(创建/更新/删除)
|
||||
- 目标:所有写操作通过 Dataflow 的 WriteAPI + 事件回流(而非 TaskManager 的更新方法)。
|
||||
- 任务:
|
||||
- 统一写入口:确保 UI/MCP 写操作均使用 `WriteAPI`(已存在)
|
||||
- 监听 `WRITE_OPERATION_*` 与 `FILE_UPDATED`,由 Orchestrator 触发增量解析与索引
|
||||
- 从 `TaskManagerBridge` 中迁移写逻辑至 `DataflowBridge`(或直接调用 `WriteAPI`)
|
||||
|
||||
- 验收:关闭 TaskManager 后,写入与后续实时更新(事件/视图刷新)正常。
|
||||
|
||||
### Phase 3:初始化/重建路径迁移
|
||||
- 目标:去除对 TaskManager 初始化与 VersionManager-重建的耦合,改由 Dataflow 主导冷启动与重建。
|
||||
- 任务:
|
||||
- 在 `src/index.ts`:
|
||||
- 若 dataflowEnabled:跳过 `new TaskManager(...)` 与其 `initialize()`、`setProgressManager()`、版本重建流程;以 Dataflow 的 `Repository.initialize()` + `Orchestrator.initialize()` 为唯一路径
|
||||
- 若需要版本驱动重建(兼容策略),在 Dataflow 中实现对应的重建触发(调用 `DataflowOrchestrator.rebuild()`)
|
||||
|
||||
- 验收:dataflowEnabled 下,重启不再触发 TaskManager 重建路径;缓存与增量解析由 Dataflow 自洽。
|
||||
|
||||
### Phase 4:适配器/回退清理
|
||||
- 目标:在默认启用 Dataflow 后,移除大部分 TaskManager 依赖,保留最小回退。
|
||||
- 任务:
|
||||
- 在配置中隐藏或标注 TaskManager 已废弃
|
||||
- 将 `TaskManagerBridge` 标记 deprecated,并在代码注释中引导迁移到 `DataflowBridge`
|
||||
- 清理 src/utils/README.md 等文档中对 TaskManager 的“Primary orchestrator”描述,改为 Dataflow
|
||||
|
||||
### Phase 5:彻底移除 TaskManager(最终)
|
||||
- 前置条件:稳定运行一段时间(至少 1-2 个版本周期),无回退需求
|
||||
- 任务:移除 `src/managers/task-manager.ts` 与相关桥接/引用、设置项
|
||||
|
||||
---
|
||||
|
||||
## 4. 详细改动清单(按文件)
|
||||
|
||||
- src/index.ts
|
||||
- [Phase 3] dataflowEnabled 时:不实例化 TaskManager,不进入 VersionManager→TaskManager 的重建流程
|
||||
- [Phase 1/2] WriteAPI 只走 Dataflow,`getTaskById` 的 fallback 去除(或仅在禁用 dataflow 时保留)
|
||||
|
||||
- src/pages/TaskView.ts
|
||||
- [Phase 1] 替换为订阅 Dataflow 事件 + `QueryAPI` 拉取
|
||||
- 移除 `loadTasksFromTaskManager` / `this.plugin.taskManager` 依赖
|
||||
|
||||
- src/mcp/McpServer.ts
|
||||
- [Phase 1] dataflowEnabled 时绑定 `DataflowBridge`(扩展其查询接口)
|
||||
- 移除/降级 `TaskManagerBridge` 使用
|
||||
|
||||
- src/mcp/bridge/TaskManagerBridge.ts
|
||||
- [Phase 2/4] 将功能迁移至 `DataflowBridge`,并标记 deprecated;最终删除
|
||||
|
||||
- 文档
|
||||
- src/utils/README.md:更新“核心架构图/职责”,以 Dataflow 为准
|
||||
|
||||
- (全仓)
|
||||
- 检索与替换:`this.taskManager` / `TaskManager` 的 import/方法调用
|
||||
|
||||
---
|
||||
|
||||
## 5. 事件/查询对齐(供视图迁移参照)
|
||||
|
||||
- 事件:
|
||||
- 使用 Dataflow 事件中心(src/dataflow/events/Events.ts):
|
||||
- `CACHE_READY`(initial 与非 initial)
|
||||
- `TASK_CACHE_UPDATED`(批量或单文件更新)
|
||||
- 查询:
|
||||
- 使用 Dataflow `QueryAPI`:
|
||||
- `getAllTasks()`、`getTasksByProject(project)`、`getTasksByTags(tags)`、`byDateRange({from,to,field})` 等(可按需扩展)
|
||||
|
||||
---
|
||||
|
||||
## 6. 风险与回滚
|
||||
|
||||
- 风险:
|
||||
- 视图或 MCP 仍有隐藏依赖 `TaskManager`
|
||||
- 写入后事件链路与增量索引在部分场景不同步
|
||||
- 缓解:
|
||||
- 阶段性灰度与双写/双读对比(仅限调试)
|
||||
- 增强日志与 metrics(WorkerOrchestrator.metrics、Repository.persist 频率等)
|
||||
- 回滚策略:
|
||||
- 保留设置开关:关闭 dataflow 时恢复 TaskManager 初始化/路径
|
||||
|
||||
---
|
||||
|
||||
## 7. 建议的实施顺序与 PR 拆分
|
||||
|
||||
1) PR#1:视图读取改造(TaskView → Dataflow),不改写入与初始化
|
||||
2) PR#2:MCP 查询改造(TaskManagerBridge → DataflowBridge 扩展)
|
||||
3) PR#3:写入统一(全面使用 WriteAPI + Dataflow 事件)
|
||||
4) PR#4:启动/重建路径切换(dataflowEnabled 时禁用 TaskManager 初始化及其重建)
|
||||
5) PR#5:清理与文档(deprecated 标记、README 更新)
|
||||
6) PR#6:移除 TaskManager(最终)
|
||||
|
||||
---
|
||||
|
||||
## 8. 待办检查清单(简版)
|
||||
|
||||
- [ ] 全仓检索并列出所有 `taskManager`/`TaskManager` 引用
|
||||
- [ ] TaskView 读取改为 Dataflow + 事件订阅
|
||||
- [ ] MCP 查询改为 DataflowBridge + QueryAPI
|
||||
- [ ] 写入统一走 WriteAPI(Dataflow),确认事件与索引链路
|
||||
- [ ] dataflowEnabled 下禁用 TaskManager 初始化与重建
|
||||
- [ ] 文档更新与 deprecated 标记
|
||||
- [ ] 最终删除 TaskManager 代码
|
||||
|
||||
|
|
@ -1,229 +0,0 @@
|
|||
# TaskManager 与 WriteAPI/QueryAPI 功能差异分析报告
|
||||
|
||||
## 功能覆盖状态总览
|
||||
|
||||
### ✅ 已完全覆盖的功能
|
||||
|
||||
#### 写入操作 (WriteAPI 已实现)
|
||||
- `updateTask` - 更新任务属性
|
||||
- `createTask` - 创建新任务
|
||||
- `deleteTask` - 删除任务
|
||||
- `updateTaskStatus` - 更新任务状态/完成标记
|
||||
- `batchUpdateTaskStatus` - 批量更新任务状态
|
||||
- `postponeTasks` - 推迟任务到新日期
|
||||
- `batchUpdateText` - 批量文本查找替换
|
||||
- `batchCreateSubtasks` - 批量创建子任务
|
||||
- `createTaskInDailyNote` - 在日记中创建任务
|
||||
- `addProjectTaskToQuickCapture` - 添加项目任务到快速捕获
|
||||
|
||||
#### 查询操作 (QueryAPI 已实现)
|
||||
- `getAllTasks` / `getAllTasksSync` - 获取所有任务
|
||||
- `getTaskById` / `getTaskByIdSync` - 按ID获取任务
|
||||
- `getTasksByProject` - 按项目筛选任务
|
||||
- `getTasksByTags` - 按标签筛选任务
|
||||
- `getTasksByStatus` - 按完成状态筛选任务
|
||||
- `getTasksByDateRange` - 按日期范围筛选任务
|
||||
- `query` - 通用查询接口 (支持 TaskFilter 和 SortingCriteria)
|
||||
|
||||
### ⚠️ 需要补充的功能
|
||||
|
||||
#### 1. 便捷查询方法 (需要在 QueryAPI 中添加)
|
||||
|
||||
```typescript
|
||||
// 需要添加到 QueryAPI 的方法:
|
||||
|
||||
// 获取特定文件的任务
|
||||
async getTasksForFile(filePath: string): Promise<Task[]> {
|
||||
const allTasks = await this.getAllTasks();
|
||||
return allTasks.filter(task => task.filePath === filePath);
|
||||
}
|
||||
|
||||
// 获取今天到期的任务
|
||||
async getTasksDueToday(): Promise<Task[]> {
|
||||
const today = new Date();
|
||||
today.setHours(0, 0, 0, 0);
|
||||
const tomorrow = new Date(today);
|
||||
tomorrow.setDate(tomorrow.getDate() + 1);
|
||||
|
||||
return this.getTasksByDateRange({
|
||||
from: today,
|
||||
to: tomorrow,
|
||||
field: 'due'
|
||||
});
|
||||
}
|
||||
|
||||
// 获取过期任务
|
||||
async getOverdueTasks(): Promise<Task[]> {
|
||||
const now = new Date();
|
||||
const allTasks = await this.getAllTasks();
|
||||
return allTasks.filter(task =>
|
||||
!task.completed &&
|
||||
task.metadata?.dueDate &&
|
||||
task.metadata.dueDate < now.getTime()
|
||||
);
|
||||
}
|
||||
|
||||
// 获取所有可用的上下文和项目
|
||||
async getAvailableContextsAndProjects(): Promise<{
|
||||
contexts: string[];
|
||||
projects: string[];
|
||||
}> {
|
||||
const allTasks = await this.getAllTasks();
|
||||
const contexts = new Set<string>();
|
||||
const projects = new Set<string>();
|
||||
|
||||
allTasks.forEach(task => {
|
||||
if (task.metadata?.context) contexts.add(task.metadata.context);
|
||||
if (task.metadata?.project) projects.add(task.metadata.project);
|
||||
// 兼容旧格式
|
||||
const tgProject = (task.metadata as any)?.tgProject;
|
||||
if (tgProject?.name) projects.add(tgProject.name);
|
||||
});
|
||||
|
||||
return {
|
||||
contexts: Array.from(contexts).sort(),
|
||||
projects: Array.from(projects).sort()
|
||||
};
|
||||
}
|
||||
|
||||
// 获取未完成任务 (便捷方法)
|
||||
async getIncompleteTasks(): Promise<Task[]> {
|
||||
return this.getTasksByStatus(false);
|
||||
}
|
||||
|
||||
// 获取已完成任务 (便捷方法)
|
||||
async getCompletedTasks(): Promise<Task[]> {
|
||||
return this.getTasksByStatus(true);
|
||||
}
|
||||
```
|
||||
|
||||
#### 2. 同步查询方法 (需要添加到 QueryAPI)
|
||||
|
||||
```typescript
|
||||
// 基于缓存的同步方法:
|
||||
|
||||
getTasksForFileSync(filePath: string): Task[] {
|
||||
const allTasks = this.getAllTasksSync();
|
||||
return allTasks.filter(task => task.filePath === filePath);
|
||||
}
|
||||
|
||||
getIncompleteTasksSync(): Task[] {
|
||||
const allTasks = this.getAllTasksSync();
|
||||
return allTasks.filter(task => !task.completed);
|
||||
}
|
||||
|
||||
getCompletedTasksSync(): Task[] {
|
||||
const allTasks = this.getAllTasksSync();
|
||||
return allTasks.filter(task => task.completed);
|
||||
}
|
||||
```
|
||||
|
||||
### 🏗️ 架构差异说明
|
||||
|
||||
#### 管理器功能迁移
|
||||
原 TaskManager 中的管理器功能在 Dataflow 架构中有不同的实现位置:
|
||||
|
||||
| TaskManager 功能 | Dataflow 架构对应 |
|
||||
|-----------------|------------------|
|
||||
| `FileFilterManager` | 集成在 `ObsidianSource` 和 `ConfigurableTaskParser` |
|
||||
| `OnCompletionManager` | 需要在 `WriteAPI` 或独立模块中实现 |
|
||||
| `RebuildProgressManager` | 集成在 `Orchestrator` 的 `rebuild()` 方法 |
|
||||
| `forceReindex()` | `DataflowOrchestrator.rebuild()` |
|
||||
| `updateParsingConfiguration()` | 配置直接更新,Orchestrator 监听配置变化 |
|
||||
| `updateFileFilterConfiguration()` | 配置直接更新,ObsidianSource 响应变化 |
|
||||
|
||||
#### Canvas 和元数据支持
|
||||
- `CanvasTaskUpdater` - 应该作为 WriteAPI 的扩展方法
|
||||
- `FileMetadataTaskUpdater` - 已集成在 `ConfigurableTaskParser`
|
||||
|
||||
### 📋 实施建议
|
||||
|
||||
#### 优先级 1:补充常用查询方法 ✅ 已完成
|
||||
在 `src/dataflow/api/QueryAPI.ts` 中添加:
|
||||
- [x] `getTasksForFile()` - ✅ 已实现
|
||||
- [x] `getTasksDueToday()` - ✅ 已实现
|
||||
- [x] `getOverdueTasks()` - ✅ 已实现
|
||||
- [x] `getAvailableContextsAndProjects()` - ✅ 已实现
|
||||
- [x] 对应的同步版本 (基于缓存) - ✅ 已实现
|
||||
- [x] `getIncompleteTasks()` / `getCompletedTasks()` - ✅ 已实现
|
||||
|
||||
#### 优先级 2:OnCompletion 支持
|
||||
- [ ] 创建 `src/dataflow/managers/OnCompletionManager.ts`
|
||||
- [ ] 在 WriteAPI 中集成 OnCompletion 触发逻辑
|
||||
- [ ] 支持任务完成后的自动操作
|
||||
|
||||
#### 优先级 3:Canvas 支持增强
|
||||
- [ ] 在 WriteAPI 中添加 `updateCanvasTask()` 方法
|
||||
- [ ] 确保 Canvas 文件的任务更新正确触发事件
|
||||
|
||||
#### 优先级 4:清理和文档
|
||||
- [ ] 更新 API 文档说明新增方法
|
||||
- [ ] 在迁移指南中标注功能对应关系
|
||||
- [ ] 清理遗留的 TaskManager 引用
|
||||
|
||||
### 📊 影响评估
|
||||
|
||||
#### 低风险补充
|
||||
- 查询便捷方法 - 仅是现有功能的封装
|
||||
- 同步查询方法 - 基于已有缓存机制
|
||||
|
||||
#### 中等风险功能
|
||||
- OnCompletionManager - 需要与事件系统深度集成
|
||||
- Canvas 任务更新 - 需要处理特殊文件格式
|
||||
|
||||
#### 已解决的风险
|
||||
- 批量操作 - WriteAPI 已完整实现
|
||||
- 日记集成 - createTaskInDailyNote 已实现
|
||||
- 快速捕获 - addProjectTaskToQuickCapture 已实现
|
||||
|
||||
## 结论
|
||||
|
||||
WriteAPI 和 QueryAPI 已经覆盖了 TaskManager 的核心功能(约 **98%**)。
|
||||
|
||||
### 已完成的补充功能(2025-08-22)
|
||||
|
||||
✅ **QueryAPI 便捷查询方法** - 全部实现:
|
||||
- `getTasksForFile()` / `getTasksForFileSync()` - 获取文件任务
|
||||
- `getTasksDueToday()` / `getTasksDueTodaySync()` - 今日到期任务
|
||||
- `getOverdueTasks()` / `getOverdueTasksSync()` - 过期任务
|
||||
- `getIncompleteTasks()` / `getIncompleteTasksSync()` - 未完成任务
|
||||
- `getCompletedTasks()` / `getCompletedTasksSync()` - 已完成任务
|
||||
- `getAvailableContextsAndProjects()` / `getAvailableContextsAndProjectsSync()` - 可用项目/上下文
|
||||
|
||||
✅ **WriteAPI Canvas 支持** - 全部实现:
|
||||
- `updateCanvasTask()` - 更新 Canvas 任务
|
||||
- `deleteCanvasTask()` - 删除 Canvas 任务
|
||||
- `moveCanvasTask()` - 移动 Canvas 任务
|
||||
- `duplicateCanvasTask()` - 复制 Canvas 任务
|
||||
- `addTaskToCanvasNode()` - 添加任务到 Canvas 节点
|
||||
- `isCanvasTask()` - 检查是否为 Canvas 任务
|
||||
- `getCanvasTaskUpdater()` - 获取 CanvasTaskUpdater 实例
|
||||
- **自动检测**:`updateTask()`, `deleteTask()`, `updateTaskStatus()` 会自动检测并处理 Canvas 任务
|
||||
|
||||
✅ **OnCompletion 管理器** - 全部实现:
|
||||
- OnCompletionManager 已集成到主插件
|
||||
- WriteAPI 自动触发 task-completed 事件
|
||||
- 支持所有 OnCompletion 操作(delete, keep, archive, move, complete, duplicate)
|
||||
- Canvas 任务也完全支持 OnCompletion
|
||||
- 完整的错误处理和日志记录
|
||||
|
||||
## 最终成果
|
||||
|
||||
### 功能覆盖率
|
||||
WriteAPI 和 QueryAPI 现已覆盖 TaskManager **100%** 的功能!
|
||||
|
||||
### 已完成的所有工作
|
||||
1. ✅ 所有 QueryAPI 便捷查询方法
|
||||
2. ✅ 完整的 Canvas 任务支持
|
||||
3. ✅ OnCompletion 管理器集成
|
||||
4. ✅ 事件系统完整集成
|
||||
5. ✅ 同步和异步方法支持
|
||||
|
||||
### 架构优势
|
||||
- **模块化设计**:各组件职责清晰
|
||||
- **事件驱动**:松耦合的组件通信
|
||||
- **性能优化**:缓存机制和请求去重
|
||||
- **向后兼容**:自动检测任务类型
|
||||
- **可扩展性**:易于添加新功能
|
||||
|
||||
迁移已完全完成,系统现已成功切换到 Dataflow 架构!
|
||||
|
|
@ -1,126 +0,0 @@
|
|||
# obsidian:// deep link rollout plan for Task Genius settings
|
||||
|
||||
This plan documents the exact deep-link formats supported by the plugin and where to add "Open Settings" buttons across the docs-site so users can jump directly to the right configuration screens in Obsidian.
|
||||
|
||||
## Supported URI formats
|
||||
|
||||
Primary scheme (recommended):
|
||||
- Open plugin settings root
|
||||
- obsidian://task-genius/settings
|
||||
- Open a specific tab
|
||||
- obsidian://task-genius/settings?tab=<tabId>
|
||||
- Open tab and scroll to a section (where supported)
|
||||
- obsidian://task-genius/settings?tab=<tabId>§ion=<sectionId>
|
||||
- Open tab and focus the search box with a query
|
||||
- obsidian://task-genius/settings?tab=<tabId>&search=<text>
|
||||
- Trigger tab-specific actions (currently on MCP tab):
|
||||
- Enable MCP server: obsidian://task-genius/settings?tab=mcp-integration&action=enable
|
||||
- Test MCP connection: obsidian://task-genius/settings?tab=mcp-integration&action=test
|
||||
- Regenerate auth token: obsidian://task-genius/settings?tab=mcp-integration&action=regenerate-token
|
||||
|
||||
Alternative legacy form (also supported):
|
||||
- obsidian://task-genius?action=settings (less explicit; prefer the path-based form above)
|
||||
|
||||
Notes
|
||||
- Use ASCII punctuation exactly as shown: obsidian:// (not full‑width colon).
|
||||
- MCP Integration tab exists on desktop only; on mobile, deep links will land on the General tab.
|
||||
|
||||
## Tab IDs you can link to
|
||||
|
||||
- general
|
||||
- index
|
||||
- view-settings
|
||||
- file-filter
|
||||
- progress-bar
|
||||
- task-status
|
||||
- task-handler
|
||||
- task-filter
|
||||
- project
|
||||
- workflow
|
||||
- date-priority
|
||||
- quick-capture
|
||||
- task-timer
|
||||
- time-parsing
|
||||
- timeline-sidebar
|
||||
- reward
|
||||
- habit
|
||||
- ics-integration
|
||||
- mcp-integration (desktop only)
|
||||
- beta-test
|
||||
- experimental
|
||||
- about
|
||||
|
||||
Special sections
|
||||
- On the MCP Integration tab, section=cursor expands and scrolls to the Cursor client configuration section when present:
|
||||
- obsidian://task-genius/settings?tab=mcp-integration§ion=cursor
|
||||
|
||||
## Placement plan in docs-site
|
||||
|
||||
Add a small call-to-action button near the top of each page’s Configuration or Getting Started section. Use consistent labels and the recommended links below.
|
||||
|
||||
Already good
|
||||
- MCP Integration index: Includes Enable/Test deep links. Keep as is.
|
||||
- MCP Clients (Cursor, Claude Desktop, Claude Code): Include “Open MCP Settings” deep links. Keep/expand with regenerate-token link in troubleshooting where helpful.
|
||||
|
||||
Add/update these pages
|
||||
- /docs/getting-started
|
||||
- Add an “Open Task Genius Settings” button: obsidian://task-genius/settings
|
||||
- /docs/installation/index, /docs/installation/community, /docs/installation/manual
|
||||
- After “Enable the plugin”, add: “Open Task Genius Settings”: obsidian://task-genius/settings
|
||||
- /docs/quick-capture
|
||||
- Add: “Open Quick Capture Settings”: obsidian://task-genius/settings?tab=quick-capture
|
||||
- /docs/habit
|
||||
- Add: “Open Habit Settings”: obsidian://task-genius/settings?tab=habit
|
||||
- /docs/task-view/habit-view
|
||||
- Add: “Open Habit Settings”: obsidian://task-genius/settings?tab=habit
|
||||
- /docs/ics-support
|
||||
- Add: “Open ICS Integration Settings”: obsidian://task-genius/settings?tab=ics-integration
|
||||
- /docs/progress-bars
|
||||
- Add: “Open Progress Display Settings”: obsidian://task-genius/settings?tab=progress-bar
|
||||
- /docs/task-status
|
||||
- Add: “Open Checkbox Status Settings”: obsidian://task-genius/settings?tab=task-status
|
||||
- /docs/filtering
|
||||
- Add: “Open Task Filter Settings”: obsidian://task-genius/settings?tab=task-filter
|
||||
- /docs/date-priority
|
||||
- Add: “Open Dates & Priority Settings”: obsidian://task-genius/settings?tab=date-priority
|
||||
- /docs/task-view/timeline-sidebar-view
|
||||
- Add: “Open Timeline Sidebar Settings”: obsidian://task-genius/settings?tab=timeline-sidebar
|
||||
- /docs/workflows
|
||||
- Add: “Open Workflows Settings”: obsidian://task-genius/settings?tab=workflow
|
||||
- /docs/reward
|
||||
- Add: “Open Rewards Settings”: obsidian://task-genius/settings?tab=reward
|
||||
|
||||
Optional advanced links
|
||||
- MCP quick actions (place in troubleshooting sections):
|
||||
- Enable server: obsidian://task-genius/settings?tab=mcp-integration&action=enable
|
||||
- Test connection: obsidian://task-genius/settings?tab=mcp-integration&action=test
|
||||
- Regenerate token: obsidian://task-genius/settings?tab=mcp-integration&action=regenerate-token
|
||||
- Jump straight to Cursor section (MCP Integration):
|
||||
- obsidian://task-genius/settings?tab=mcp-integration§ion=cursor
|
||||
|
||||
## Copy and style guidelines
|
||||
|
||||
- Button label conventions
|
||||
- Primary: “Open … Settings” (e.g., “Open MCP Settings”).
|
||||
- Keep labels short; avoid sentence case after the first word.
|
||||
- Use a styled anchor tag in MDX pages for visual prominence, e.g.:
|
||||
- <a href="obsidian://task-genius/settings?tab=habit" className="btn btn-primary">Open Habit Settings</a>
|
||||
- Place the button right after the first paragraph of the Configuration section, or at the end of the Installation steps.
|
||||
- Include a one-line fallback for users whose environment blocks deeplinks: “If the button doesn’t work, open Obsidian → Settings → Community Plugins → Task Genius → [Tab Name].”
|
||||
|
||||
## Consistency notes for client docs
|
||||
|
||||
- Server name in examples
|
||||
- Our server name auto-derives from the vault (e.g., my-vault-tasks) with a fallback obsidian-tasks. For simplicity, standardize docs examples to obsidian-tasks unless showing multi-vault setups.
|
||||
- Auth header format
|
||||
- Always show: Authorization: Bearer TOKEN+APP_ID
|
||||
- Ports
|
||||
- Default port 7777. Use 7778, 7779 in multi-vault examples.
|
||||
|
||||
## Validation checklist
|
||||
|
||||
- All new links use ASCII obsidian:// and correct tab IDs.
|
||||
- MCP action links validated on desktop (enable, test, regenerate-token).
|
||||
- Mobile gracefully shows General tab when MCP tab not available.
|
||||
- Pages render with a single primary button per configuration area to reduce clutter.
|
||||
|
||||
|
|
@ -1,61 +0,0 @@
|
|||
# Worker Processing Control Implementation
|
||||
|
||||
## Overview
|
||||
Implemented complete control for background worker processing in Task Genius plugin, allowing users to enable/disable worker threads for file parsing performance optimization.
|
||||
|
||||
## Changes Made
|
||||
|
||||
### 1. Settings UI Integration (`IndexSettingsTab.ts`)
|
||||
- Updated the "Enable worker processing" toggle to use the new `fileSource.performance.enableWorkerProcessing` setting path
|
||||
- Added backward compatibility with legacy `fileParsingConfig.enableWorkerProcessing` setting
|
||||
- Ensures proper initialization of setting structure when needed
|
||||
|
||||
### 2. WorkerOrchestrator Enhancement (`WorkerOrchestrator.ts`)
|
||||
- Added `enableWorkerProcessing` configuration option to constructor
|
||||
- Implemented `setWorkerProcessingEnabled()` method for dynamic control
|
||||
- Added `isWorkerProcessingEnabled()` status check method
|
||||
- Enhanced `getMetrics()` to provide comprehensive performance statistics
|
||||
- Circuit breaker automatically resets when re-enabling workers
|
||||
|
||||
### 3. DataflowOrchestrator Integration (`Orchestrator.ts`)
|
||||
- Reads worker processing setting from both new and legacy paths
|
||||
- Passes configuration to WorkerOrchestrator during initialization
|
||||
- Added `updateSettings()` method to propagate setting changes
|
||||
- Added `getWorkerStatus()` for monitoring worker state and metrics
|
||||
|
||||
### 4. Settings Update Flow (`setting.ts`)
|
||||
- Modified `applySettingsUpdate()` to call `dataflowOrchestrator.updateSettings()`
|
||||
- Ensures worker processing changes take effect immediately without restart
|
||||
|
||||
### 5. FileSource Management (`FileSource.ts`)
|
||||
- Added `cleanup()` method for proper resource cleanup
|
||||
- Added `updateConfig()` alias for configuration updates
|
||||
- Properly handles initialization and cleanup based on settings
|
||||
|
||||
## How It Works
|
||||
|
||||
1. **User toggles setting**: User changes "Enable worker processing" in Index Settings
|
||||
2. **Setting saved**: New value stored in `fileSource.performance.enableWorkerProcessing`
|
||||
3. **Update propagated**: `applySettingsUpdate()` calls `dataflowOrchestrator.updateSettings()`
|
||||
4. **Worker control**: `WorkerOrchestrator.setWorkerProcessingEnabled()` updates worker state
|
||||
5. **Processing mode**: Tasks are processed either by workers or main thread based on setting
|
||||
|
||||
## Benefits
|
||||
|
||||
- **Performance Control**: Users can disable workers if experiencing issues
|
||||
- **Dynamic Updates**: Changes take effect immediately without plugin restart
|
||||
- **Backward Compatibility**: Works with both old and new setting paths
|
||||
- **Circuit Breaker**: Automatic recovery when re-enabling workers
|
||||
- **Monitoring**: Comprehensive metrics for debugging and optimization
|
||||
|
||||
## Testing
|
||||
|
||||
Created comprehensive test suite (`worker-processing-control.test.ts`) that verifies:
|
||||
- Default enabled state
|
||||
- Configuration respect on initialization
|
||||
- Dynamic enabling/disabling
|
||||
- Circuit breaker reset behavior
|
||||
- Metrics availability
|
||||
- Settings path fallback logic
|
||||
|
||||
All tests pass successfully, confirming proper implementation.
|
||||
|
|
@ -52,17 +52,19 @@ export class FluentPlacement {
|
|||
el.addClass("clickable-icon");
|
||||
};
|
||||
|
||||
|
||||
makeCard(
|
||||
"inline",
|
||||
t("Inline (Single-Page Immersion)"),
|
||||
t("All content in one page, focusing on the main view and reducing interface distractions.")
|
||||
);
|
||||
|
||||
makeCard(
|
||||
"sideleaves",
|
||||
t("Sideleaves (Multi-Column Collaboration)"),
|
||||
t("Left navigation and right details as separate workspace sidebars, ideal for simultaneous browsing and editing.")
|
||||
);
|
||||
|
||||
makeCard(
|
||||
"inline",
|
||||
t("Inline (Single-Page Immersion)"),
|
||||
t("All content in one page, focusing on the main view and reducing interface distractions.")
|
||||
);
|
||||
|
||||
const tips = section.createDiv({ cls: "placement-tips" });
|
||||
tips.createEl("p", {
|
||||
|
|
|
|||
|
|
@ -229,7 +229,7 @@ export class ComponentPreviewFactory {
|
|||
];
|
||||
|
||||
mockTasks.forEach(task => {
|
||||
const taskItem = taskList.createDiv({ cls: "task-list-item" });
|
||||
const taskItem = taskList.createDiv({ cls: "task-item" });
|
||||
|
||||
const checkbox = taskItem.createDiv({ cls: "task-checkbox" });
|
||||
setIcon(checkbox, "circle");
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ export class FluentComponentsStep {
|
|||
}> = [
|
||||
{ id: "sidebar", label: t("Sidebar") },
|
||||
{ id: "topnav", label: t("Top Navigation") },
|
||||
{ id: "content", label: t("Content Area") },
|
||||
// { id: "content", label: t("Content Area") },
|
||||
{ id: "project", label: t("Project Management") },
|
||||
];
|
||||
|
||||
|
|
@ -92,9 +92,9 @@ export class FluentComponentsStep {
|
|||
case "topnav":
|
||||
this.renderTopNavShowcase(previewSection, descSection);
|
||||
break;
|
||||
case "content":
|
||||
this.renderContentShowcase(previewSection, descSection);
|
||||
break;
|
||||
// case "content":
|
||||
// this.renderContentShowcase(previewSection, descSection);
|
||||
// break;
|
||||
case "project":
|
||||
this.renderProjectShowcase(previewSection, descSection);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ export class PlacementStep {
|
|||
showPreview: true,
|
||||
},
|
||||
(placement) => {
|
||||
controller.setUseSideLeaves(placement === "sideleaves");
|
||||
controller.setUseSideLeaves(placement === "inline");
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,19 @@
|
|||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.component-preview .v2-nav-left {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.onboarding-view:has(.component-showcase) .onboarding-header {
|
||||
padding: calc(var(--onboarding-spacing) * 2) var(--onboarding-spacing) var(--size-4-2) var(--onboarding-spacing);
|
||||
}
|
||||
|
||||
.v2-top-navigation.component-preview {
|
||||
overflow-x: auto;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
/* Component showcase container */
|
||||
.component-showcase {
|
||||
display: flex;
|
||||
|
|
@ -68,7 +81,6 @@
|
|||
.component-preview {
|
||||
pointer-events: none;
|
||||
user-select: none;
|
||||
transform-origin: top left;
|
||||
}
|
||||
|
||||
/* Scale down previews to fit */
|
||||
|
|
@ -76,17 +88,8 @@
|
|||
max-width: 300px;
|
||||
}
|
||||
|
||||
.component-preview-topnav {
|
||||
transform: scale(0.9);
|
||||
}
|
||||
|
||||
.component-preview-content {
|
||||
transform: scale(0.9);
|
||||
}
|
||||
|
||||
.component-preview-popover {
|
||||
max-width: 350px;
|
||||
transform: scale(0.9);
|
||||
}
|
||||
|
||||
/* Disable interactions in previews */
|
||||
|
|
@ -141,10 +144,6 @@
|
|||
.component-showcase-preview {
|
||||
min-height: 300px;
|
||||
}
|
||||
|
||||
.component-preview {
|
||||
transform: scale(0.75);
|
||||
}
|
||||
}
|
||||
|
||||
/* File filter preview styles */
|
||||
|
|
|
|||
23
styles.css
23
styles.css
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue