From 0054a3a97a21fde445dd075df9fa7b14540756c8 Mon Sep 17 00:00:00 2001 From: AskaEth Date: Tue, 6 Oct 2026 16:14:27 +0800 Subject: [PATCH] =?UTF-8?q?fix(chat):=20=E9=A6=96=E5=B1=8F=E5=A4=B1?= =?UTF-8?q?=E8=B4=A5=E7=9A=84=E3=80=8C=E9=87=8D=E8=AF=95=E3=80=8D=E6=8C=89?= =?UTF-8?q?=E9=92=AE=E6=B0=B8=E8=BF=9C=E4=B8=8D=E5=87=BA=E7=8E=B0=20?= =?UTF-8?q?=E2=80=94=E2=80=94=20=E5=88=A4=E6=8D=AE=E6=9E=81=E6=80=A7?= =?UTF-8?q?=E6=8E=A5=E5=8F=8D=EF=BC=88W52/E=20=E7=9C=9F=E6=9C=BA=E9=AA=8C?= =?UTF-8?q?=E6=94=B6=E6=9A=B4=E9=9C=B2=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 改了什么: - ChatScreen 里 shouldOfferRetryOnEmpty 的第三个实参从 `state.items.isEmpty()` 改成 `state.items.isNotEmpty()`。 为什么:判据是 `!loading && hasError && !hasItems`,参数语义是「列表里**有没有**东西」;调用点传的是 `isEmpty()`(极性相反),于是「列表为空」这个**唯一会求值**的场景里结论永远是 false ⇒ 按钮永远不出现。 判据单测用的是正确语义(不含调用点),所以全绿——这条只有真机才会露出来。 怎么定位的:先加一条一次性诊断日志把 UI 实际看到的三个输入打出来(`loading=false hasError=true items=0 retry=false` —— 三个输入全真而结论为假 ⇒ 只可能是极性),核对判据本体后确认;定位完日志已删。 真机复验:断网冷启动 ⇒ 「消息没能加载出来」+「重试」;恢复网络后点它 ⇒ 发出 `GET /api/v1/sessions/web/messages` 且离线期间落库的那条出现在屏幕上;按钮随列表非空消失。 --- app/src/main/kotlin/top/yeij/cyrene/ui/chat/ChatScreen.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/src/main/kotlin/top/yeij/cyrene/ui/chat/ChatScreen.kt b/app/src/main/kotlin/top/yeij/cyrene/ui/chat/ChatScreen.kt index d370043..012259d 100644 --- a/app/src/main/kotlin/top/yeij/cyrene/ui/chat/ChatScreen.kt +++ b/app/src/main/kotlin/top/yeij/cyrene/ui/chat/ChatScreen.kt @@ -550,7 +550,10 @@ fun ChatScreen( val retry = shouldOfferRetryOnEmpty( loading = state.loading, hasError = state.error != null, - hasItems = state.items.isEmpty(), + // ⚠️ 语义是「**有没有**东西」而不是「是不是空」——W52/E 第一版这里传了 + // `isEmpty()`,极性反了,于是「列表为空」这个唯一会求值的场景里结论**永远为假**、 + // 按钮永远不出现(判据单测用的是正确语义,所以全绿;只有真机才露出来)。 + hasItems = state.items.isNotEmpty(), ) CenterHint( text = if (retry) FIRST_PAGE_FAILED_HINT else EMPTY_CONVERSATION_HINT,