[Chat] Handle new chat notification reasons (#10530)

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Samuel Newman
2026-05-20 18:20:35 +03:00
committed by GitHub
parent 9cad883ab8
commit c1817d3425
3 changed files with 136 additions and 20 deletions
+52 -11
View File
@@ -30,6 +30,9 @@ export type NotificationReason =
| 'quote'
| 'chat-message'
| 'chat-reaction'
| 'chat-added-to-group'
| 'chat-removed-from-group'
| 'chat-join-request-rejected'
| 'starterpack-joined'
| 'like-via-repost'
| 'repost-via-repost'
@@ -37,6 +40,8 @@ export type NotificationReason =
| 'unverified'
| 'subscribed-post'
type ChatNotificationReason = Extract<NotificationReason, `chat-${string}`>
/**
* Manually overridden type, but retains the possibility of
* `notification.request.trigger.payload` being `undefined`, as specified in
@@ -45,7 +50,7 @@ export type NotificationReason =
export type NotificationPayload =
| undefined
| {
reason: Exclude<NotificationReason, 'chat-message' | 'chat-reaction'>
reason: Exclude<NotificationReason, ChatNotificationReason>
uri: string
subject: string
recipientDid: string
@@ -62,6 +67,25 @@ export type NotificationPayload =
messageId: string
recipientDid: string
}
| {
reason:
| 'chat-added-to-group'
| 'chat-removed-from-group'
| 'chat-join-request-rejected'
convoId: string
recipientDid: string
}
export type ChatNotificationPayload = Extract<
NonNullable<NotificationPayload>,
{reason: ChatNotificationReason}
>
export function isChatNotificationPayload(
payload: NonNullable<NotificationPayload>,
): payload is ChatNotificationPayload {
return payload.reason.startsWith('chat-')
}
const DEFAULT_HANDLER_OPTIONS = {
shouldShowBanner: false,
@@ -199,10 +223,7 @@ export function useNotificationsHandler() {
const handleNotification = (payload?: NotificationPayload) => {
if (!payload) return
if (
payload.reason === 'chat-message' ||
payload.reason === 'chat-reaction'
) {
if (isChatNotificationPayload(payload)) {
logger.debug(`useNotificationsHandler: handling chat notification`, {
payload,
})
@@ -220,7 +241,13 @@ export function useNotificationsHandler() {
} else {
setShowLoggedOut(true)
}
} else {
} else if (
payload.reason === 'chat-message' ||
payload.reason === 'chat-reaction' ||
payload.reason === 'chat-added-to-group'
) {
// chat-added-to-group routes to the convo because the recipient was
// just added and now has access.
navigation.dispatch(state => {
if (state.routes[0].name === 'Messages') {
if (
@@ -253,6 +280,12 @@ export function useNotificationsHandler() {
})
}
})
} else {
// chat-removed-from-group, chat-join-request-rejected: the convo is
// no longer accessible to the recipient, so just open the list.
navigation.dispatch(
CommonActions.navigate('MessagesTab', {screen: 'Messages'}),
)
}
} else {
const url = notificationToURL(payload)
@@ -280,11 +313,16 @@ export function useNotificationsHandler() {
logger.debug('useNotificationsHandler: incoming', {e, payload})
if (
(payload.reason === 'chat-message' ||
payload.reason === 'chat-reaction') &&
isChatNotificationPayload(payload) &&
payload.recipientDid === currentAccount?.did
) {
const shouldAlert = payload.convoId !== currentConvoId
// chat-removed-from-group / chat-join-request-rejected always alert,
// even if the recipient is currently viewing the affected convo -
// they need to know they were removed/rejected.
const shouldAlert =
payload.reason === 'chat-removed-from-group' ||
payload.reason === 'chat-join-request-rejected' ||
payload.convoId !== currentConvoId
return {
shouldShowList: shouldAlert,
shouldShowBanner: shouldAlert,
@@ -352,8 +390,8 @@ export function useNotificationsHandler() {
// Whenever there's a stored payload, that means we had to switch accounts before handling the notification.
// Whenever currentAccount changes, we should try to handle it again.
if (
(storedAccountSwitchPayload?.reason === 'chat-message' ||
storedAccountSwitchPayload?.reason === 'chat-reaction') &&
storedAccountSwitchPayload &&
isChatNotificationPayload(storedAccountSwitchPayload) &&
currentAccount?.did === storedAccountSwitchPayload.recipientDid
) {
handleNotification(storedAccountSwitchPayload)
@@ -442,6 +480,9 @@ export function notificationToURL(payload: NotificationPayload): string | null {
}
case 'chat-message':
case 'chat-reaction':
case 'chat-added-to-group':
case 'chat-removed-from-group':
case 'chat-join-request-rejected':
// should be handled separately
return null
case 'verified':