From eae15aca3ea591201d2b37b90da32d549b3cd8ff Mon Sep 17 00:00:00 2001 From: DS Boyce <260543580+ds-boyce@users.noreply.github.com> Date: Thu, 25 Jun 2026 14:57:03 -0700 Subject: [PATCH] Increase unread cap to 99+ (#10985) --- src/screens/Messages/Inbox.tsx | 13 +++---------- .../Messages/components/InboxRequests.tsx | 14 ++++++-------- .../queries/messages/get-unread-counts.ts | 13 ++++++------- .../queries/messages/list-conversations.tsx | 10 ++++------ src/view/shell/bottom-bar/BottomBar.tsx | 18 ++++++++++++------ 5 files changed, 31 insertions(+), 37 deletions(-) diff --git a/src/screens/Messages/Inbox.tsx b/src/screens/Messages/Inbox.tsx index 2fb58253a5..f6b4216b2c 100644 --- a/src/screens/Messages/Inbox.tsx +++ b/src/screens/Messages/Inbox.tsx @@ -23,6 +23,7 @@ import {cleanError} from '#/lib/strings/errors' import {logger} from '#/logger' import {MESSAGE_SCREEN_POLL_INTERVAL} from '#/state/messages/convo/const' import {useMessagesEventBus} from '#/state/messages/events' +import {useUnreadCountsQuery} from '#/state/queries/messages/get-unread-counts' import {useListConvoRequests} from '#/state/queries/messages/list-conversation-requests' import {useUpdateAllRead} from '#/state/queries/messages/update-all-read' import {EmptyState} from '#/view/com/util/EmptyState' @@ -84,16 +85,8 @@ export function MessagesInboxScreenInner({}: Props) { return items }, [data]) - const hasUnreadConvos = useMemo(() => { - return conversations.some( - item => - item.type === 'incoming' && - item.view.members.every( - member => member.handle !== 'missing.invalid', - ) && - item.view.unreadCount > 0, - ) - }, [conversations]) + const {data: unreadCounts} = useUnreadCountsQuery() + const hasUnreadConvos = (unreadCounts?.unreadRequestConvos ?? 0) > 0 return ( diff --git a/src/screens/Messages/components/InboxRequests.tsx b/src/screens/Messages/components/InboxRequests.tsx index ba5f2bf385..bcea519100 100644 --- a/src/screens/Messages/components/InboxRequests.tsx +++ b/src/screens/Messages/components/InboxRequests.tsx @@ -1,14 +1,12 @@ import {plural} from '@lingui/core/macro' import {useLingui} from '@lingui/react/macro' +import {UNREAD_REQUEST_CAP} from '#/state/queries/messages/get-unread-counts' import {atoms as a} from '#/alf' import {ButtonIcon, ButtonText} from '#/components/Button' import {Inbox_Stroke2_Corner2_Rounded as InboxIcon} from '#/components/icons/Inbox' import {Link} from '#/components/Link' -// The server caps unreadRequestConvos at 11, where 11 means "any more than 10". -const REQUEST_COUNT_CAP = 11 - export function InboxRequests({ count, variant, @@ -21,7 +19,7 @@ export function InboxRequests({ const {t: l} = useLingui() const unread = count > 0 - const overflow = count >= REQUEST_COUNT_CAP + const overflow = count >= UNREAD_REQUEST_CAP const label = !unread ? l({ @@ -30,8 +28,8 @@ export function InboxRequests({ }) : overflow ? l({ - message: `10+ requests`, - comment: 'Displayed when the number of requests is greater than 10', + message: `${UNREAD_REQUEST_CAP - 1}+ requests`, + comment: 'Displayed when the number of requests exceeds the cap', }) : plural(count, { one: '# request', @@ -55,9 +53,9 @@ export function InboxRequests({ {overflow ? l({ - message: `10+`, + message: `${UNREAD_REQUEST_CAP - 1}+`, comment: - 'Displayed when the number of requests is greater than 10', + 'Displayed when the number of requests exceeds the cap – for example, 99+ requests', }) : count} diff --git a/src/state/queries/messages/get-unread-counts.ts b/src/state/queries/messages/get-unread-counts.ts index 57b565fa17..8c276d67f7 100644 --- a/src/state/queries/messages/get-unread-counts.ts +++ b/src/state/queries/messages/get-unread-counts.ts @@ -10,13 +10,12 @@ export const RQKEY = (includeGroupChats: boolean) => [RQKEY_ROOT, includeGroupChats] as const export const RQKEY_PARTIAL = [RQKEY_ROOT] as const -// the server sentinel-caps the badge counts: unreadAcceptedConvos maxes at 31 -// (meaning "more than 30") and unreadRequestConvos at 11 (meaning "more than -// 10"). at the cap the value is no longer an exact count, so consumers must not -// treat it as one - both the optimistic decrement and the badge display ceiling -// key off these. -export const UNREAD_ACCEPTED_CAP = 31 -export const UNREAD_REQUEST_CAP = 11 +// the server sentinel-caps the badge counts: unreadAcceptedConvos and +// unreadRequestConvos max out at 100 (meaning "more than 99"). at the cap the +// value is no longer an exact count, so consumers must not treat it as one - +// both the optimistic decrement and the badge display ceiling key off these. +export const UNREAD_ACCEPTED_CAP = 100 +export const UNREAD_REQUEST_CAP = 100 export function useUnreadCountsQuery() { const agent = useAgent() diff --git a/src/state/queries/messages/list-conversations.tsx b/src/state/queries/messages/list-conversations.tsx index 3a3183bad1..1f73c720bd 100644 --- a/src/state/queries/messages/list-conversations.tsx +++ b/src/state/queries/messages/list-conversations.tsx @@ -856,18 +856,16 @@ export function useUnreadMessageCount(): { const request = data?.unreadRequestConvos ?? 0 if (accepted > 0) { - const total = accepted + Math.min(request, 1) return { - count: total, + count: accepted, // accepted is sentinel-capped at UNREAD_ACCEPTED_CAP (meaning "more than // cap - 1"). show the "+" overflow label only when accepted is actually - // capped - the +1 request nudge must not trip it at exactly cap - 1 - // accepted convos. otherwise clamp the number to cap - 1 so the nudge - // never surfaces the sentinel value (31) itself + // capped, otherwise clamp the number to cap - 1 so we never surface the + // sentinel value (100) itself numUnread: accepted >= UNREAD_ACCEPTED_CAP ? `${UNREAD_ACCEPTED_CAP - 1}+` - : String(Math.min(total, UNREAD_ACCEPTED_CAP - 1)), + : String(Math.min(accepted, UNREAD_ACCEPTED_CAP - 1)), // only needed when numUnread is undefined hasNew: false, } diff --git a/src/view/shell/bottom-bar/BottomBar.tsx b/src/view/shell/bottom-bar/BottomBar.tsx index 8650e99b89..717921a092 100644 --- a/src/view/shell/bottom-bar/BottomBar.tsx +++ b/src/view/shell/bottom-bar/BottomBar.tsx @@ -242,12 +242,18 @@ export function BottomBar({navigation}: BottomTabBarProps) { accessibilityLabel={l`Chat`} accessibilityHint={ !aa.flags.chatDisabled && numUnreadMessages.count > 0 - ? l({ - message: plural(numUnreadMessages.numUnread ?? 0, { - one: '# unread item', - other: '# unread items', - }), - }) + ? numUnreadMessages.numUnread?.includes('+') + ? l({ + message: `${numUnreadMessages.numUnread} unread items`, + comment: + 'Accessibility hint for the bottom bar chat icon when the number of unread messages exceeds the cap, with the + symbol already included – for example, 99+ unread items', + }) + : l({ + message: plural(numUnreadMessages.numUnread ?? 0, { + one: '# unread item', + other: '# unread items', + }), + }) : '' } />