From 855e800c4a5b0c279fc05c88bd532b225b0c5912 Mon Sep 17 00:00:00 2001 From: Evie Gauthier Date: Sat, 2 May 2026 19:30:16 -0400 Subject: [PATCH] fix(presence): show presence dot in account switcher, DM sidebar, and members drawer - AccountSwitcherTab: wrap SidebarAvatar in AvatarPresence with current user's dot - DirectDMsList: add AvatarPresence badge on 1:1 DM icons using the DM user's presence - MembersDrawer: replace lastActiveTs !== 0 guard with presence !== Offline so online users show a dot --- src/app/features/room/MembersDrawer.tsx | 4 +-- .../client/sidebar/AccountSwitcherTab.tsx | 36 ++++++++++++------- .../pages/client/sidebar/DirectDMsList.tsx | 21 +++++++++-- 3 files changed, 44 insertions(+), 17 deletions(-) diff --git a/src/app/features/room/MembersDrawer.tsx b/src/app/features/room/MembersDrawer.tsx index 29c630bf6..a853f27ed 100644 --- a/src/app/features/room/MembersDrawer.tsx +++ b/src/app/features/room/MembersDrawer.tsx @@ -26,7 +26,7 @@ import { useVirtualizer } from '@tanstack/react-virtual'; import classNames from 'classnames'; import { AvatarPresence, PresenceBadge } from '$components/presence'; -import { useUserPresence } from '$hooks/useUserPresence'; +import { Presence, useUserPresence } from '$hooks/useUserPresence'; import { useMatrixClient } from '$hooks/useMatrixClient'; import { UseStateProvider } from '$components/UseStateProvider'; import type { SearchItemStrGetter, UseAsyncSearchOptions } from '$hooks/useAsyncSearch'; @@ -150,7 +150,7 @@ function MemberItem({ > ) : undefined } diff --git a/src/app/pages/client/sidebar/AccountSwitcherTab.tsx b/src/app/pages/client/sidebar/AccountSwitcherTab.tsx index a3ec48466..ed29252e5 100644 --- a/src/app/pages/client/sidebar/AccountSwitcherTab.tsx +++ b/src/app/pages/client/sidebar/AccountSwitcherTab.tsx @@ -45,6 +45,8 @@ import { createLogger } from '$utils/debug'; import { createDebugLogger } from '$utils/debugLogger'; import { useClientConfig } from '$hooks/useClientConfig'; import { UnreadBadge, UnreadBadgeCenter } from '$components/unread-badge'; +import { Presence, useUserPresence } from '$hooks/useUserPresence'; +import { AvatarPresence, PresenceBadge } from '$components/presence'; const log = createLogger('AccountSwitcherTab'); const debugLog = createDebugLogger('AccountSwitcherTab'); @@ -174,6 +176,7 @@ export function AccountSwitcherTab() { ? (mxcUrlToHttp(mx, activeProfile.avatarUrl, useAuthentication, 96, 96, 'crop') ?? undefined) : undefined; const activeDisplayName = activeProfile.displayName; + const myPresence = useUserPresence(myUserId); const sessionProfiles = useSessionProfiles(sessions); @@ -269,19 +272,28 @@ export function AccountSwitcherTab() { {(triggerRef) => ( - 1} + + ) + } > - {nameInitials(label)}} - /> - + 1} + > + {nameInitials(label)}} + /> + + )} {(totalBackgroundUnread > 0 || anyBackgroundHighlight) && ( diff --git a/src/app/pages/client/sidebar/DirectDMsList.tsx b/src/app/pages/client/sidebar/DirectDMsList.tsx index 8c3313335..31d17d68a 100644 --- a/src/app/pages/client/sidebar/DirectDMsList.tsx +++ b/src/app/pages/client/sidebar/DirectDMsList.tsx @@ -22,6 +22,8 @@ import { getCanonicalAliasOrRoomId, mxcUrlToHttp } from '$utils/matrix'; import { useSelectedRoom } from '$hooks/router/useSelectedRoom'; import { useGroupDMMembers } from '$hooks/useGroupDMMembers'; import { useSidebarDirectRoomIds } from './useSidebarDirectRoomIds'; +import { Presence, useUserPresence } from '$hooks/useUserPresence'; +import { AvatarPresence, PresenceBadge } from '$components/presence'; import * as css from './DirectDMsList.css'; const MAX_GROUP_MEMBERS = 3; @@ -44,6 +46,9 @@ function DMItem({ room, selected }: DMItemProps) { // Check if this is a group DM (more than 2 members) const isGroupDM = room.getJoinedMemberCount() > 2; + const dmUserId = !isGroupDM ? room.getAvatarFallbackMember()?.userId : undefined; + const dmPresence = useUserPresence(dmUserId ?? ''); + // Get member info for group DMs using m.direct and profile API (doesn't require full room state) // Members are sorted by who last sent messages (most recent first) const groupMembers = useGroupDMMembers(mx, room, MAX_GROUP_MEMBERS); @@ -135,9 +140,19 @@ function DMItem({ room, selected }: DMItemProps) { {(triggerRef) => ( - - {renderAvatar()} - + + ) + } + > + + {renderAvatar()} + + )} {unread && (unread.total > 0 || unread.highlight > 0) && (