fix: recover chat replies and organize setup navigation [skip ci]

Targeted source-only patch from reviewed local e370485. Adds bounded realtime/catch-up recovery and moves the setup wizard under System. Static checks only; regression tests, full build and runtime verification have not been run. No deployment. Separate hardening-review branch is not merged. Expected tree: 6235478b9a.
This commit is contained in:
2026-10-16 13:43:41 +00:00
parent e57610a27c
commit 299ea50fb5
8 changed files with 843 additions and 72 deletions

View File

@@ -1,3 +1,4 @@
// Modified for targeted chat realtime recovery; see docs/fixes/chat-realtime-recovery.md.
"use client"
import {
@@ -139,6 +140,7 @@ function SupportChatPanelContent() {
sendAttachment,
retry,
disconnectSocket,
recoverConnection,
markConversationRead,
closeConversation,
setConversationSatisfaction,
@@ -164,6 +166,7 @@ function SupportChatPanelContent() {
sendAttachment: state.sendAttachment,
retry: state.retry,
disconnectSocket: state.disconnectSocket,
recoverConnection: state.recoverConnection,
markConversationRead: state.markConversationRead,
closeConversation: state.closeConversation,
setConversationSatisfaction: state.setConversationSatisfaction,
@@ -206,13 +209,9 @@ function SupportChatPanelContent() {
useEffect(() => {
bootstrap()
}, [isOpen, bootstrap])
return () => {
if (!isOpen) {
disconnectSocket()
}
}
}, [isOpen, bootstrap, disconnectSocket])
useEffect(() => () => disconnectSocket(), [disconnectSocket])
useEffect(() => {
maybeMarkConversationRead()
@@ -220,21 +219,25 @@ function SupportChatPanelContent() {
useEffect(() => {
const handleVisibilityChange = () => {
recoverConnection()
if (document.visibilityState === "visible") {
maybeMarkConversationRead()
}
}
const handleFocus = () => {
recoverConnection()
maybeMarkConversationRead()
}
document.addEventListener("visibilitychange", handleVisibilityChange)
window.addEventListener("focus", handleFocus)
window.addEventListener("online", recoverConnection)
return () => {
document.removeEventListener("visibilitychange", handleVisibilityChange)
window.removeEventListener("focus", handleFocus)
window.removeEventListener("online", recoverConnection)
}
}, [maybeMarkConversationRead])
}, [maybeMarkConversationRead, recoverConnection])
async function handleSend(content: string) {
await handleSendMessage(content)