fix(web): 文件助手 duplicated as its own chat-list row once slf has real history

文件助手 is a permanent pinned entry that redirects into a real conversation on
the slf topic (see PINNED_ENTRIES's own doc comment -- there's no dedicated
file-browser API to back a real one). Once that topic has any message
history it also comes back from useChatList() as an ordinary contact, so it
rendered a second time as its own chronologically-sorted row further down --
confirmed live: navigating to /messages/slf via either row satisfied both
rows' own "am I active" check at once, highlighting both simultaneously.

Filters the slf topic out of the ordinary contacts list; 文件助手 stays the
one and only way it's represented there.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Your Name
2026-09-09 22:01:50 +08:00
co-authored by Claude Sonnet 5
parent db0f8e4543
commit d1c81d432e
+8 -1
View File
@@ -68,7 +68,14 @@ export function ChatListColumn() {
const memberCountByTopic = new Map(groupsQuery.data?.map((g) => [g.topic, g.member_count]));
const [query, setQuery] = useState('');
const [creatingGroup, setCreatingGroup] = useState(false);
const sorted = [...contacts].sort((a, b) => {
// `slf` (self-chat) is permanently represented by the pinned 文件助手 entry above (see
// PINNED_ENTRIES's own doc comment) -- it also comes back as an ordinary contact once it has any
// real message history (e.g. the very first time something gets sent through 文件助手), which
// without this filter renders it a SECOND time as its own chronologically-sorted row further down.
// Confirmed live: with both rows present, navigating to /messages/slf (via either one) satisfies
// both rows' own "am I the active one" check at once, highlighting them simultaneously -- a real,
// reproducible duplicate-representation bug, not just a cosmetic double-highlight.
const sorted = [...contacts].filter((c) => c.topic !== 'slf').sort((a, b) => {
const pinDelta = (b.private?.pinned ? 1 : 0) - (a.private?.pinned ? 1 : 0);
return pinDelta || (b.touched?.getTime() ?? 0) - (a.touched?.getTime() ?? 0);
});