Repository navigation
Releases: NihilDigit/tokmato
Release list
v5.0
主要变化
-
Kanban 的多端同步从“只合并看得见的卡片”补上了删除记录。以前一台设备删掉任务后,另一台离线或慢同步的设备还握着旧副本,下一次合并会把它带回来;现在删除本身也成为同步事实,旧副本会被压下去。这个版本把“删掉就是删掉”作为 Kanban 的基本规则,而不是把每台设备的旧列表简单相加。
-
PWA 打开路径加了本地应用壳缓存。tokmato 的真实数据仍然来自本机状态和登录后的云端同步,但页面壳、静态脚本、图标和常用路由不再每次都从冷网络开始。这样做的边界是:先让 app 立即可见,再让后台刷新跟上;不缓存登录、同步、推送等会影响真实状态的请求。
-
Kanban 拖拽减少了高频渲染。拖动任务卡时,指针移动会按浏览器帧率合并处理,而不是每个移动事件都让整页重算。结果应该是拖拽更稳,尤其是在任务较多或设备性能一般时。
修复
-
修复一端删除 Kanban 卡片后,另一端旧本地副本在同步时把卡片复活的问题。
-
修复同一张 Kanban 卡片在多端移动后,可能同时出现在两个列里的合并风险。
-
修复 Kanban 卡片只编辑文字、不改变数量时,自动同步可能漏掉这次修改的问题。
工程
-
补充 Kanban 删除、移动合并和旧快照兼容的回归测试。
-
为 service worker 增加保守缓存策略,并保持同步与 API 请求不进缓存。
v4.4
主要变化
- 番茄串改成连续滚动:25 分钟一格,自动续约,不再插一段 60 秒的
缓冲期。设计回到番茄时间盒最初的样子——节奏稳,不被一段半空的
暂停打断。从前那段缓冲在体验上既挡视线又难手动结束(实际跑下
来还会偶尔卡死),加进来时是想给一个"喘口气"的窗口,结果变成
专注节奏的杂质,删掉是干净选择。 - 提前结束分两档。当前番茄不到 13 分钟,长按结束直接销毁,符合
从前的算法(已完成的算,进行中的丢)。超过 13 分钟,给两条路:
一是销毁,二是填一句"这段时间做了什么",按完整番茄计入。13
分钟的门槛是给真做了事但凑不到 25 的人一条体面路径,避免"做
了 24 分钟还要被算成零"产生的放弃情绪。代价是必须写一句话——
既是对 token 经济学的诚实,也强制做一次最小反思。 - Journey 的"最近 20 串"列表点开可以改 tag、改描述,也可以整条
删除。删除会把这条番茄当时拿到的 F 和 bonus 从余额里反扣,今
天的话连日计数一起回退。从前打错 tag 或写错任务名只能死着,
现在补救路径打开了;删除之所以连账本也一起冲销,是为了让账本
始终跟历史对得上,避免出现"番茄串里没有但 F 多了几个"的悬空
记录。 - 番茄和娱乐计时不再绑定 Kanban 卡片。开番茄、玩娱乐时不需要再
选 Kanban 卡,结束时也没有"完成此卡片"的勾选。绑定的本意是省
一次手动同步两个状态机,但实际跑下来更像摩擦——每开一个番茄要
先扫一眼 Kanban,每次结束又要决定 Kanban 那边的状态。Kanban
和番茄分开节奏看反而清爽。
修复
- 缓冲期偶尔跨不过去导致计时卡在第二个番茄之间的那种状态,长按
结束也只能扣到中间相位、跨设备同步还会显示成"另一端缓冲中"
下不去——整段相关代码随缓冲期一起退场,这条路彻底没了。
工程
- persist 版本升 9,迁移把进行中且处于旧缓冲态的会话平滑过渡到
新的下一个番茄,不会因为升级丢节奏。云快照里的旧字段保留兼容
位,新版本读取时忽略,老设备写出来仍能正常解析。 - 推送链单相位化:服务端每 25 分钟一跳,不再交替 running/buffer
两条 QStash 链。跨设备只读镜像跟着简化为单一节拍。 - 单元测试覆盖三个新口径:自动续约的多边界跨越、历史编辑的账本
联动、删除的余额反冲与今日计数回退。
v4.3
主要变化
- v4.0 上来时为了稳,把上一版的 RN 客户端目录留在树里。relay 真机
端到端跑通后(配对码 → FCM token 绑定 → priority:high 推送 → 通知
点击 deep-link 拉起 PWA),把整套 mobile/ 删掉,连同它专用的那批
REST 路由。仓库现在只剩两个独立工件:Next.js web 应用,和 native
Android 推送增强器。 - 服务端的 /api/rpc 表面相应收窄。原来给 cookie-less RN 客户端镜像
web server actions 的十几条路由删掉,只留配对绑定用的两条。auth
的 Bearer JWT 通道随之退场。
工程
- README 与 CLAUDE.md 都按现状重写一遍,顺手过一道文风:去掉装饰
em-dash、去聊天式叙事、去营销腔。架构图、技术栈、Android 章节
都对到 relay 现状。 - lib/rpc-auth.ts 简化为 auth() 的薄壳。它过去同时处理 cookie 与
Bearer,现在只剩 cookie。
v4.2
主要变化
- Android 推送增强器入口的引导文案换了一遍。原来三句里 "13 MB
薄壳 APK / 只接 FCM 高优先级 / 输入下方 4 位码" 都是工程视角的
实现细节,对实际用户是噪音;其中"下方"在还没生成码时还是个
指向不存在元素的死引用。改成两句:先说 Web Push 在锁屏后会被
节流的现实问题,再说装 APK 接管。 - 配对成功后的页面去掉了 FCM token 前 24 字符那一行。最初是
bring-up 期方便自查的 debug 视图,对完成绑定的用户没意义,
反倒看上去像后台诊断界面。「用户」一行已经能确认绑定到了哪个
账号。
工程
- 配对码倒计时(4 Hz setState)从 Settings 页面级 state 抽到
独立 PairCodeCard。原来每 250 ms 都会重跑页面的 useShallow
9-selector 比较,纯属浪费。 - 屏幕阅读器可达性:配对码区改用
<output>+ 完整 aria-label
含逐位读出 + 剩余秒数;状态消息加role="status" aria-live;
Compose BindScreen 的隐藏 BasicTextField 给了合并语义,4 个
视觉 CodeBox 的 semantics 清掉,TalkBack 听到的是单一带标签的
输入框而不是四个无标签格子。 - Compose 端 BindScreen / BoundScreen 标题字号从 displayMedium
(44sp) 降到 headlineLarge (32sp)。绑定是一次性仪式,不算情感
峰值,大字号留给 settle / journey 这种真有重量的瞬间。 - 配对码生成加了每用户 5/min 的 mint 速率限制,避免单账号长期
squat 4 位码空间;客户端把 401 / 429 映射成可执行的中文文案。 - FCM 推送改成 data-only payload,让 relay APK 自己渲染通知 +
自挂 ACTION_VIEW PendingIntent,点击如期跳浏览器到 /home。
通知 id 改用 tag.hashCode(),相同 tag 的新推送替换而不是堆叠。
v4.0.1
修复
- v4.0 的 FCM 推送同时包含 notification 块和 data 块,Firebase 在
APK 不在前台时自动渲染通知并把点击 action 默认到 launcher
Activity,relay 的 deep-link PendingIntent 因此从未生效,结果点
通知只会拉起 relay 自身。改成 data-only payload,APK 一侧的
onMessageReceived 自己渲染通知 + 自己挂 ACTION_VIEW PendingIntent,
点击如期跳浏览器到 /home。Doze 在 high priority + data-only 下仍
被绕过。
v4.0
主要变化
- 之前 RN 客户端的全部存在理由是 FCM priority:high 通道
(Web Push 没这个旋钮,Android Doze 会节流通知)。把整套 UI
用 RN 重写一份只为换推送通道,工程量太重。这版回到职责拆分:
原生只负责推送,UI 全走 PWA。 - 新增 tokmato-relay:约 13 MB 的原生 Android 应用,Jetpack
Compose + Material 3。只有两屏(输配对码、显示绑定状态),
没有 webview、没有数据镜像、没有 auth 栈。点击通知 deep-link
拉起 PWA。 - 配对绑定不走 OAuth:网页端 Settings 生成 4 位码(60 秒有效,
单次消费),APK 输码 + 上报 FCM token 完成绑定。单用户场景下
码空间足够,避开了在原生端再写一遍 OAuth 来回的代价。 - 顺带通了 iOS:Safari 16.4+ 在 PWA 安装到主屏后已支持 Web Push,
本版不需要为 iOS 再发客户端。
工程
- 移动端 CI 从 EAS local build 换回 Gradle 标准链路,工具链不再
依赖第三方配额;keystore / Firebase 配置 secrets 复用。 - 上一版的 RN 客户端目录暂留,待真机端到端验证后下版删除。
- 项目落入 AGPL-3.0;网络服务对外提供时需履行源码义务。
v3.2
主要变化
Android 端从 Capacitor WebView 套壳切到 Expo / RN 真原生。原因不只是工程收敛——看板的长按径向移动手势此前在 React 树里 setState,中端 Android 卡顿肉眼可见,搬到 react-native-gesture-handler + reanimated 跑在 UI 线程之后体感是另一档。番茄启动 / 笔记 / 缓冲跳过等操作现在用 @gorhom/bottom-sheet 的物理曲线,不再是 Radix Sheet 的 CSS transition。
注意:装着旧 Capacitor APK 的设备不会自动收到本次更新,需要从 GitHub Release 重新下载 sideload。Web / PWA 用户无影响。
移动端补齐 12/13 web sheet(Play 启动娱乐 timer + 全屏 overlay 长按结束按比例退还时间池、Settle 单页结算、AddWish / Food / KanbanCard / EditTag / EditBonus 等),Settings 加上 Tags / Bonuses / 食物常用项的 CRUD 入口,Journey 按 dayKey 分组只显示近 30 天。延后两个:LedgerSheet(Journey 已经覆盖账本视图)、WelcomeGuideSheet(mobile 用户基本走 web 端引导)。
APK 从 86 MB 压到 32 MB(单 ABI 只打 arm64-v8a,覆盖 2017 年后所有 Android 设备)。
工程
CI release-apk.yml 改为 EAS local build(在 GH runner 上跑,不消耗 Expo 云端构建额度),release-mobile.yml 合并进来。Firebase google-services.json 入库(设计就是公开嵌入 APK 的客户端配置)。lib/push-client.ts 摘掉 window.Capacitor 分支,纯 web 通道。push-client + active-session + sync 的 RPC 镜像保持双端共用。
v3.1.2
修复
娱乐计时绑定 Kanban 时改为单行任务选择,不再把启动弹窗挤高变形。启动娱乐时间的主流程保持紧凑,任务绑定只是可选关联。
v3.1.1
修复
Journey 的余额折线图去掉兑换金额线,只保留 FToken 与 HToken 的余额变化。这样图表不再混合不同量纲,读图重点回到代币余额本身。
v3.1
主要变化
- 计时器现在更像一套统一的任务流程,而不是番茄和娱乐各走各的路:开始时可以关联 Kanban 任务,结束时能把实际结果记下来。
- 番茄开始时可以用 Kanban 卡片填入预期任务;结束时记录结果。如果这次确实把绑定任务做完了,可以直接标记完成,让它从待办板上退场。
- 娱乐计时改成不阻塞全局操作的浮动计时条。只有绑定了 Kanban 任务的娱乐计时才要求结束反馈,普通娱乐到点仍然轻量结束。
- Journey 的走势图改为画余额,而不是每日收入;F、H 和可兑换金额一起显示,所以充值、消费和兑换都会反映在曲线上。
- 另一台设备启动番茄后,本机不再只能等待;如果对端断电或失联,可以从远端镜像里结束服务器端番茄,解除锁定和后续提醒。
修复
- 修复 Kanban 径向移动菜单长按后闪现即消失的问题。
- 修复番茄结束时灵感内容重复进入 Kanban 的问题。
- 修复娱乐结束通知经常收不到的问题;自然到点不再被前端提前取消。
- 修复 Journey 分布图在单一分类占满时看起来为空的问题。
工程
- 抽出通用计时 tick 和长按确认机制。
- 拆分番茄与娱乐的后台提醒生命周期。
- 扩展持久化数据以保存计时绑定和结束结果。