AskaEth
28c314262e
feat(chat): 接上 A5 正向增量 after,并用 404 session_not_found 把「会话已删」如实说出来
改了什么:
- SessionsApi.listMessages 加可选 after(契约 §1 行 6)。before / q / after 三者互斥是服务端的
硬约束,本端三个调用点各只给一个;after 为 null 时 Retrofit 整个省掉这个参数 ⇒ 既有三条路径
的线上请求逐字节不变。
- MessageRepository 加 loadAfter:同一个端点,服务端按【升序】返回(与 before 的倒序相反),
仍统一转成升序的 PagedMessages。顺手去掉 toPagedMessages 参数名里那个已经不对的 newestFirst。
- ChatViewModel:
· 新增 newestKnownAt(从状态现算的 after 游标)与 absorb(只并消息与乐观气泡,不碰
loading / loadingOlder / hasMore / error —— 一次静默补拉不该把上拉位置和错误横幅掀掉)。
· 掉线那一刻记下游标、重新连上时用它做一次正向增量。记录时机必须在「掉线」而不是「重连后」:
重连的 history 帧会把最近 50 条灌进来、游标随即被推到「现在」,那时再取就取不到那个洞了。
「再拉一页最新」永远补不回中间断掉的那一段,这正是 after 存在的理由(02/A5 的欠账)。
· ensureMessageKnown 先用增量(只要新来的那几条),还认不出来才退回整页重拉。
· 循环推进抽成纯函数 loadForwardPages:游标必须严格前进(同毫秒并列且超过一页时推不动,
契约 §A5 明写的已知边界)+ 轮数上限 20,两道防死循环的闸都由单测钉住。
- 404 session_not_found(契约 v0.63):首屏 / 上拉 / 增量三条读路径都判,非主会话就置
ChatUiState.sessionGone;ChatScreen 据此显示一句实话并回调 ChatHomeScreen 重拉会话列表
(refresh 内部会把「指向已删会话」的 activeSessionId 收敛回主会话)。
主会话不置位:那说明部署本身出了问题,该显示的是普通错误横幅,而不是一句假的「已切回主会话」。
为什么:
主人那次「图片凭空消失、别的端也看不到」的真相,就是会话在别处被删掉之后,客户端把它渲染成了
一条空会话 —— 让用户对着空白猜。现在有了机器可读的 404,就能如实说一句并把人带回主会话。
另一半是重连补洞:一直是「再拉一页最新」在顶着,断线期间超过 50 条必丢中间那一段。
验证:assembleDebug + testDebugUnitTest 全绿,846 测试 / 0 失败 / 0 错误。
较基线 831 新增 15 条(MessageAfterRepositoryTest 5 条走真 OkHttp 断言线上 URI;
ChatRecoveryTest 10 条钉住 404 判据与增量循环的两道闸)。
设备侧验证(点开看到那句实话、断线补洞)另行做,不在本次提交的断言范围内。
2026-10-04 22:00:55 +08:00
..
2026-10-04 22:00:55 +08:00
2026-09-08 21:48:40 +08:00
2026-09-08 20:40:58 +08:00