From ab31afa13d5dfeaff919b413df39ab3943ab3107 Mon Sep 17 00:00:00 2001 From: hzhang Date: Fri, 15 May 2026 15:00:24 +0100 Subject: [PATCH] feat(frontend): split members sidebar into channel + guild sections MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a channel is selected the Members panel shows 'In channel — N' (that channel's members) above 'Guild — N' (all guild members). Co-Authored-By: Claude Opus 4.7 (1M context) --- src/pages/ChatPage.tsx | 64 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 53 insertions(+), 11 deletions(-) diff --git a/src/pages/ChatPage.tsx b/src/pages/ChatPage.tsx index ad7ab39..e5792e0 100644 --- a/src/pages/ChatPage.tsx +++ b/src/pages/ChatPage.tsx @@ -40,6 +40,7 @@ export default function ChatPage() { const { session, logout, ensureFreshToken, refreshGuilds, updateName } = useAuth() const [selectedGuildId, setSelectedGuildId] = useState('') const [selectedChannelId, setSelectedChannelId] = useState('') + const [channelMemberIds, setChannelMemberIds] = useState([]) const [channels, setChannels] = useState([]) const [guildDbId, setGuildDbId] = useState('') const [members, setMembers] = useState([]) @@ -134,6 +135,20 @@ export default function ChatPage() { } } + async function loadChannelMembers() { + if (!guild || !guildToken || !selectedChannelId) { + setChannelMemberIds([]) + return + } + try { + const res = await guildApi().get(`/channels/${selectedChannelId}/members`) + const list = Array.isArray(res.data) ? (res.data as Array<{ userId: string }>) : [] + setChannelMemberIds(list.map((x) => x.userId)) + } catch { + setChannelMemberIds([]) + } + } + async function pullMessages() { if (!selectedChannelId || !guild || !guildToken) return setLoading(true) @@ -242,6 +257,7 @@ export default function ChatPage() { await guildApi().post(`/channels/${c.id}/join`) await loadChannels() await loadMembers() + await loadChannelMembers() } catch { setError('Failed to join channel') } @@ -257,6 +273,7 @@ export default function ChatPage() { } await loadChannels() await loadMembers() + await loadChannelMembers() } catch { setError('Failed to leave channel') } @@ -290,6 +307,7 @@ export default function ChatPage() { useEffect(() => { void pullMessages() + void loadChannelMembers() }, [selectedChannelId]) useEffect(() => { @@ -318,6 +336,23 @@ export default function ChatPage() { const authorLabel = (uid?: string) => uid ? (uid === session?.user.id ? session?.user.name || 'You' : nameById.get(uid) || uid.slice(0, 8)) : 'unknown' + const guildById = new Map(members.map((m) => [m.userId, m])) + const channelMembers = channelMemberIds.map( + (id) => guildById.get(id) ?? { userId: id, email: '', name: '', status: 'active' }, + ) + const renderMember = (m: { userId: string; name?: string; email?: string }) => { + const label = m.name || m.email || m.userId.slice(0, 8) + return ( +
+
{initials(label)}
+
+ {label} + {m.userId === session?.user.id ? you : null} +
+
+ ) + } + return (