From ba24c7c35752b8ba278d4402ad9cde9b79240344 Mon Sep 17 00:00:00 2001 From: DS Boyce <260543580+ds-boyce@users.noreply.github.com> Date: Mon, 1 Jun 2026 14:32:36 -0700 Subject: [PATCH] Display join requests on chat list (#10679) --- .../MembersAndRequests.tsx | 2 +- .../Messages/components/ChatListItem.tsx | 15 +++++++ .../queries/messages/list-conversations.tsx | 41 +++++++++++++++++-- 3 files changed, 53 insertions(+), 5 deletions(-) diff --git a/src/screens/Messages/ConversationSettings/MembersAndRequests.tsx b/src/screens/Messages/ConversationSettings/MembersAndRequests.tsx index 837e553923..b9d9ecc2b2 100644 --- a/src/screens/Messages/ConversationSettings/MembersAndRequests.tsx +++ b/src/screens/Messages/ConversationSettings/MembersAndRequests.tsx @@ -48,7 +48,7 @@ export function MembersAndRequests({ ? l({ message: `${requestCount}+ requests`, comment: - 'Displayed when there are more than 50 requests to join a group chat', + 'Displayed when there are more than 20 requests to join a group chat', }) : l({ message: plural(requestCount, { diff --git a/src/screens/Messages/components/ChatListItem.tsx b/src/screens/Messages/components/ChatListItem.tsx index aba3295170..eb002c581d 100644 --- a/src/screens/Messages/components/ChatListItem.tsx +++ b/src/screens/Messages/components/ChatListItem.tsx @@ -6,6 +6,7 @@ import { type ModerationDecision, type ModerationOpts, } from '@atproto/api' +import {plural} from '@lingui/core/macro' import {useLingui} from '@lingui/react/macro' import {useQueryClient} from '@tanstack/react-query' @@ -213,6 +214,20 @@ function GroupChatItem({ primaryProfileModeration={moderation} isBlockedAccount={false} isDeletedAccount={false} + subtitle={ + convo.details.joinRequestCount + ? convo.details.joinRequestCount > 20 + ? l({ + message: '20+ new join requests', + context: + 'Displayed when there are more than 20 requests to join a group chat', + }) + : plural(convo.details.joinRequestCount, { + one: '# new join request', + other: '# new join requests', + }) + : undefined + } showProfileBadges={false} selected={selected} showMenu={showMenu}> diff --git a/src/state/queries/messages/list-conversations.tsx b/src/state/queries/messages/list-conversations.tsx index 56c8a5d4a1..f026e57d33 100644 --- a/src/state/queries/messages/list-conversations.tsx +++ b/src/state/queries/messages/list-conversations.tsx @@ -489,12 +489,22 @@ export function ListConvosProviderInner({ // Join link data not included in the log event, trigger refetch to get it debouncedRefetch() } else if ( - ChatBskyConvoDefs.isLogIncomingJoinRequest(log) || ChatBskyConvoDefs.isLogApproveJoinRequest(log) || - ChatBskyConvoDefs.isLogRejectJoinRequest(log) || - ChatBskyConvoDefs.isLogOutgoingJoinRequest(log) + ChatBskyConvoDefs.isLogRejectJoinRequest(log) ) { - // TODO Update join request count here when available. -dsb + queryClient.setQueriesData( + {queryKey: [RQKEY_ROOT]}, + (old?: ConvoListQueryData) => + updateGroupConvoJoinRequestCount(log, old, -1), + ) + } else if (ChatBskyConvoDefs.isLogIncomingJoinRequest(log)) { + queryClient.setQueriesData( + {queryKey: [RQKEY_ROOT]}, + (old?: ConvoListQueryData) => + updateGroupConvoJoinRequestCount(log, old, 1), + ) + } else if (ChatBskyConvoDefs.isLogOutgoingJoinRequest(log)) { + // Viewer isn't in the chat yet, no need to do anything } else if (ChatBskyConvoDefs.isLogAddReaction(log)) { queryClient.setQueriesData( {queryKey: [RQKEY_ROOT]}, @@ -762,6 +772,29 @@ function optimisticUpdate( } } +function updateGroupConvoJoinRequestCount( + log: {convoId: string; rev: string}, + old: ConvoListQueryData | undefined, + delta: 1 | -1, +) { + return optimisticUpdate(log.convoId, old, convo => { + // Join requests are only meaningful for group convos. + if (!ChatBskyConvoDefs.isGroupConvo(convo.kind)) { + return {...convo, rev: log.rev} + } + const current = convo.kind.joinRequestCount ?? 0 + const next = Math.max(0, current + delta) + return { + ...convo, + kind: { + ...convo.kind, + joinRequestCount: next === 0 ? undefined : next, + }, + rev: log.rev, + } + }) +} + function removeMemberFromConvoView( convo: ChatBskyConvoDefs.ConvoView, did: string,