mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-22 17:49:48 +02:00
The aggregate chat unread badge used two different definitions: web/ desktop's sidebar summed unread messages while mobile's tab badge (and the since-removed ChatFab badge it mirrored) counted sessions — the same account state showed e.g. 5 on web and 2 on iOS. The sidebar also summed ALL sessions while the thread list zeroes the row being viewed, so a reply landing in the open conversation flashed a sidebar count with no matching row. - packages/core/chat/unread.ts: countUnreadChatMessages() as the single shared definition (IM-style message total, optional viewed-session exclusion); pure so mobile can import it. - app-sidebar: use the helper and exclude the actively-viewed session, but only while a chat surface is actually showing it (chat route or floating window open) — a remembered selection with both surfaces closed still counts, since nothing will auto mark-read there. - mobile: tab badge switches to the shared message count (99+ cap like the sidebar), ChatSessionSchema parses unread_count, and markRead's optimistic patch zeroes unread_count alongside has_unread. Co-authored-by: Lambda <lambda@multica.ai> Co-authored-by: multica-agent <github@multica.ai>
47 lines
1.5 KiB
TypeScript
47 lines
1.5 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
import { countUnreadChatMessages } from "./unread";
|
|
import type { ChatSession } from "../types/chat";
|
|
|
|
function session(id: string, unread_count?: number): ChatSession {
|
|
return {
|
|
id,
|
|
workspace_id: "ws-1",
|
|
agent_id: "agent-1",
|
|
creator_id: "user-1",
|
|
title: id,
|
|
status: "active",
|
|
has_unread: (unread_count ?? 0) > 0,
|
|
unread_count,
|
|
created_at: "2026-07-10T00:00:00Z",
|
|
updated_at: "2026-07-10T00:00:00Z",
|
|
};
|
|
}
|
|
|
|
describe("countUnreadChatMessages", () => {
|
|
it("sums unread messages across sessions (not session count)", () => {
|
|
expect(
|
|
countUnreadChatMessages([session("a", 2), session("b", 3), session("c", 0)]),
|
|
).toBe(5);
|
|
});
|
|
|
|
it("treats a missing unread_count (older server) as 0", () => {
|
|
expect(countUnreadChatMessages([session("a"), session("b", 4)])).toBe(4);
|
|
});
|
|
|
|
it("returns 0 for an empty or unloaded list", () => {
|
|
expect(countUnreadChatMessages([])).toBe(0);
|
|
expect(countUnreadChatMessages(undefined)).toBe(0);
|
|
});
|
|
|
|
it("excludes the session being viewed from the sum", () => {
|
|
const sessions = [session("a", 2), session("b", 3)];
|
|
expect(countUnreadChatMessages(sessions, "a")).toBe(3);
|
|
expect(countUnreadChatMessages(sessions, "b")).toBe(2);
|
|
});
|
|
|
|
it("ignores an exclude id that is not in the list", () => {
|
|
expect(countUnreadChatMessages([session("a", 2)], "ghost")).toBe(2);
|
|
expect(countUnreadChatMessages([session("a", 2)], null)).toBe(2);
|
|
});
|
|
});
|