mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-27 12:56:01 -06:00
fix(ui): unread badge latches un-clearable when the read patch is never sent (#123252)
sessions.patch resolves null without sending a request when the connection scope cannot be captured, but the read-marker guard only unlatched on promise rejection — so the once-per-episode latch stayed set with no request in flight, and the unread badge stayed lit on the open session until navigating away and back. Treat a null resolution like a failure.
This commit is contained in:
committed by
GitHub
parent
dc61fe5abe
commit
63bc139872
@@ -189,11 +189,20 @@ export abstract class ChatPaneSession extends ChatPaneTaskSuggestions {
|
||||
return;
|
||||
}
|
||||
const guardKey = state.sessionKey;
|
||||
void this.context.sessions.patch(row.key, { unread: false }, { agentId }).catch(() => {
|
||||
// Unlatch so later unread snapshots retry; the session capability
|
||||
// publishes the actionable error for the owning page.
|
||||
this.unreadPatchGuard.patchFailed(guardKey);
|
||||
});
|
||||
void this.context.sessions.patch(row.key, { unread: false }, { agentId }).then(
|
||||
(result) => {
|
||||
// A null result means no request was sent (connection scope lost);
|
||||
// unlatch like a failure or the badge stays lit until navigation.
|
||||
if (result === null) {
|
||||
this.unreadPatchGuard.patchFailed(guardKey);
|
||||
}
|
||||
},
|
||||
() => {
|
||||
// Unlatch so later unread snapshots retry; the session capability
|
||||
// publishes the actionable error for the owning page.
|
||||
this.unreadPatchGuard.patchFailed(guardKey);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
protected async restoreArchivedSession(sessionKey: string, expectedSessionId: string) {
|
||||
|
||||
@@ -90,6 +90,30 @@ describe("chat pane read markers", () => {
|
||||
expect(state.lastError).toBeNull();
|
||||
});
|
||||
|
||||
it("retries the read patch after a null (unsent) resolution", async () => {
|
||||
// sessions.patch resolves null without a request when the connection
|
||||
// scope is lost; the guard must unlatch like a failure or the badge
|
||||
// stays lit until navigation.
|
||||
const patch = vi.fn().mockResolvedValue(null);
|
||||
const { pane } = createTestChatPane({
|
||||
client: {} as GatewayBrowserClient,
|
||||
sessions: { patch } as unknown as SessionCapability,
|
||||
});
|
||||
const row = {
|
||||
key: "agent:main:current",
|
||||
kind: "direct" as const,
|
||||
label: "Unread",
|
||||
updatedAt: 20,
|
||||
unread: true,
|
||||
};
|
||||
|
||||
pane.markSessionRead(row);
|
||||
await Promise.resolve();
|
||||
pane.markSessionRead(row);
|
||||
|
||||
expect(patch).toHaveBeenCalledTimes(2);
|
||||
});
|
||||
|
||||
it("does not clear unread from a hidden retained pane", () => {
|
||||
const patch = vi.fn().mockResolvedValue(null);
|
||||
const { pane } = createTestChatPane({
|
||||
|
||||
Reference in New Issue
Block a user