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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

## v2.x 近期变化

- **v2.1.2**:通知行改用分裂式“推迟 1 小时”按钮,主区域一键推迟,箭头保留其他时长选项。
- **v2.1.2**:通知行改用分裂式“推迟1h”按钮,主区域一键推迟,箭头保留其他时长选项。
- **v2.1.1**:拆分用户可见名称与稳定的 `QSettings` 命名空间,界面不再显示过期的 v1 标识,已有窗口几何和状态继续兼容。
- **v2.1.0**:到期通知收敛为逐项“完成”“推迟”“忽略”,明确忽略任务的时间约束语义。
- **v2.0.0**:将任务卡片和详情浮层的关键布局规则收敛为可独立测试的纯函数模型,保持既有界面行为。
Expand Down
4 changes: 2 additions & 2 deletions anchor.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
- 相邻任务卡片的可见外边界固定保留 8px 透明列表间距,item 高度必须与当前卡片动态高度一致且不得小于卡片最小高度;卡片、边框、计时文字和优先级标识按主题形成轻量层次,操作浮层使用不透明主题背景遮住底层计时,编辑/删除按钮默认保持中性,仅在 hover、focus 或 pressed 时分别强化主题强调与危险语义。
- 列表纵向滚动条固定为 8px 紧凑宽度,轨道透明、滑块跟随主题配色;窗口左侧外边距等于“滚动条宽度 + 滚动条右侧外边距”,当前参数为 `15px = 8px + 7px`。滚动条隐藏时,列表 viewport 在同一边界保留 8px gutter;滚动条出现时释放 gutter 给真实滚动条,使可见卡片左右外边界到主内容边界的留白始终对称,取整误差不超过 1px。仅列表向右延伸,顶部筛选和标题行仍保持 15px 右外边距;状态切换不得残留旧几何、触发横向滚动条或造成卡片裁切。
- 已完成任务只通过勾选状态、线框及配色区分,编辑按钮始终可用,由主窗口逻辑负责根据任务 ID 处理编辑请求。
- 提醒流程:`master_timer` 每秒触发 `tick_update` 扫描完整 `self.todos`,提醒不受当前列表筛选影响,可见卡片循环只刷新倒计时;一轮请求先写入提醒去重字段,再汇总到任意时刻唯一的非模态软件内 `NotificationDialog`,同一任务按 ID 去重且“已到期”覆盖“提前提醒”。同批任务只播放一次 `play_sound_effect` 软件提醒音,窗口打开期间的新批次追加到原窗口,不创建 Windows 系统任务通知、Toast 或任务到期托盘气泡。提醒唤醒时优先调用原生接口恢复并前置主窗口,若平台不支持则临时添加 `WindowStaysOnTopHint` 保障可见,之后自动回退。通知窗口不提供复选框或底部批量操作;每条任务只通过自己的行内“完成”“推迟 1 小时”“忽略”处置,推迟按钮主区域一键推迟 1 小时,只有箭头区域展开 15 分钟、1 小时、晚上 8 点和次日上午 9 点选项,“忽略”清除时间约束。每次处置由主窗口统一持久化并刷新列表;主窗口隐藏到托盘时同步隐藏提醒窗口但保留批次,恢复主窗口时重新显示同一批次,任务全部处理、用户主动关闭提醒窗口或真正退出后释放 Qt 对象与主题信号连接。
- 提醒流程:`master_timer` 每秒触发 `tick_update` 扫描完整 `self.todos`,提醒不受当前列表筛选影响,可见卡片循环只刷新倒计时;一轮请求先写入提醒去重字段,再汇总到任意时刻唯一的非模态软件内 `NotificationDialog`,同一任务按 ID 去重且“已到期”覆盖“提前提醒”。同批任务只播放一次 `play_sound_effect` 软件提醒音,窗口打开期间的新批次追加到原窗口,不创建 Windows 系统任务通知、Toast 或任务到期托盘气泡。提醒唤醒时优先调用原生接口恢复并前置主窗口,若平台不支持则临时添加 `WindowStaysOnTopHint` 保障可见,之后自动回退。通知窗口不提供复选框或底部批量操作;每条任务只通过自己的行内“完成”“推迟1h”“忽略”处置,推迟按钮主区域一键推迟 1 小时,只有箭头区域展开 15 分钟、1 小时、晚上 8 点和次日上午 9 点选项,“忽略”清除时间约束。每次处置由主窗口统一持久化并刷新列表;主窗口隐藏到托盘时同步隐藏提醒窗口但保留批次,恢复主窗口时重新显示同一批次,任务全部处理、用户主动关闭提醒窗口或真正退出后释放 Qt 对象与主题信号连接。
- 推迟流程:推迟会同步更新 `snoozeUntil` 与可编辑的 `dueDate`;若原截止时间已早于推迟目标,默认截止时间自动推进到推迟目标。编辑保存按同一时刻而非 ISO 字符串判断截止时间是否变化,普通内容与优先级修改保留延后的新时间及提醒状态,只有实际修改时间或提醒偏移时才清理旧调度状态。
- 忽略语义:通知中的“忽略”表示保留任务但清除其时间约束;主窗口将 `dueDate` 与 `snoozeUntil` 置为 `None`,将 `notifiedForReminder` 与 `notifiedForDue` 重置为 `False`,保留 `reminderOffset`、`completed` 与 `lastNotifiedAt`。无截止时间时任务不显示超时且不会触发提醒;以后重新设置截止时间时继续使用原提醒偏好。本语义不提供撤销或历史恢复。
- 截止时间编辑:新增任务的默认截止时间沿绝对时间线取本地当前时间一小时后,日期与时间来自同一目标时刻并按可见分钟保存;未改默认日期与分钟时保留该目标的 UTC 实例,避免夏令时重复小时丢失 offset。时间使用支持滚轮和上下键微调的 `QTimeEdit`,日期使用低频内联 `QDateEdit` 日历下拉。选择日期直接应用,不再创建独立日期确认窗口。编辑已有任务时,未改日期与分钟则保留原截止时间的完整精度,实际调整后秒与毫秒归零。
Expand All @@ -80,7 +80,7 @@
- 若确认无变更,提交说明需写明“锚点已复盘,无需更新”。

## 最近约定变更
- 2026-08-12:bugfix,通知行改用分裂式“推迟 1 小时”按钮,主区域一键执行默认时长,箭头保留其他推迟选项,版本更新至 `v2.1.2`。
- 2026-08-12:bugfix,通知行改用分裂式“推迟1h”按钮,主区域一键执行默认时长,箭头保留其他推迟选项,版本更新至 `v2.1.2`。
- 2026-08-11:bugfix,拆分用户可见应用名与稳定的 `QSettings` 命名空间,移除窗口和托盘中过期的 v1 标识并无损保留已有窗口状态,版本更新至 `v2.1.1`。
- 2026-08-07:feature,到期通知只保留行内逐项“完成”“推迟”“忽略”,移除复选框与底部批量操作;“忽略”保留任务与提醒偏好但清除时间约束,版本更新至 `v2.1.0`。
- 2026-07-31:refactor,将任务卡片宽高、区域挤压优先级与详情浮层尺寸/位置收敛为不依赖 Qt 事件循环的纯函数布局模型,用户可见行为与像素结果不变;按 refactor 版本规则更新至 `v2.0.0`。
Expand Down
4 changes: 2 additions & 2 deletions tests/test_notifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ def test_inline_actions_target_only_their_own_task(self) -> None:
self.assertIsNotNone(complete_first)
self.assertIsNotNone(snooze_second)
self.assertIsNotNone(ignore_first)
self.assertEqual(snooze_second.text(), "推迟 1 小时")
self.assertEqual(snooze_second.text(), "推迟1h")
self.assertEqual(
snooze_second.toolButtonStyle(),
Qt.ToolButtonStyle.ToolButtonTextOnly,
Expand All @@ -115,7 +115,7 @@ def test_inline_actions_target_only_their_own_task(self) -> None:
style_option.toolButtonStyle,
Qt.ToolButtonStyle.ToolButtonTextOnly,
)
self.assertEqual(style_option.text, "推迟 1 小时")
self.assertEqual(style_option.text, "推迟1h")
self.assertEqual(
snooze_second.popupMode(),
QToolButton.ToolButtonPopupMode.MenuButtonPopup,
Expand Down
2 changes: 1 addition & 1 deletion todo_app/dialogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ def add_or_update_tasks(self, requests: list[tuple[dict, bool]]) -> None:
)

snooze_action = QToolButton()
snooze_action.setText("推迟 1 小时")
snooze_action.setText("推迟1h")
snooze_action.setToolButtonStyle(
Qt.ToolButtonStyle.ToolButtonTextOnly
)
Expand Down
Loading