poll for messages on chat push notification
stop polling entirely in the background (resume already triggers an immediate catch-up poll), and force an immediate poll when a chat push notification arrives while foregrounded via a new pollNow() on the event bus. APP-2415 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@ import {useAccountSwitcher} from '#/lib/hooks/useAccountSwitcher'
|
||||
import {logger as notyLogger} from '#/lib/notifications/util'
|
||||
import {type NavigationProp} from '#/lib/routes/types'
|
||||
import {useCurrentConvoId} from '#/state/messages/current-convo-id'
|
||||
import {useMaybeMessagesEventBus} from '#/state/messages/events'
|
||||
import {RQKEY as RQKEY_NOTIFS} from '#/state/queries/notifications/feed'
|
||||
import {invalidateCachedUnreadPage} from '#/state/queries/notifications/unread'
|
||||
import {truncateAndInvalidate} from '#/state/queries/util'
|
||||
@@ -114,6 +115,7 @@ export function useNotificationsHandler() {
|
||||
const {onPressSwitchAccount} = useAccountSwitcher()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
const {currentConvoId} = useCurrentConvoId()
|
||||
const messagesBus = useMaybeMessagesEventBus()
|
||||
const {setShowLoggedOut} = useLoggedOutViewControls()
|
||||
const closeAllActiveElements = useCloseAllActiveElements()
|
||||
const {_} = useLingui()
|
||||
@@ -316,6 +318,11 @@ export function useNotificationsHandler() {
|
||||
isChatNotificationPayload(payload) &&
|
||||
payload.recipientDid === currentAccount?.did
|
||||
) {
|
||||
// A chat push means new events probably exist - force an immediate
|
||||
// poll so the convo list / open convo update without waiting for the
|
||||
// next scheduled tick. No-op unless the bus is actively polling.
|
||||
messagesBus?.pollNow()
|
||||
|
||||
// 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.
|
||||
@@ -425,6 +432,7 @@ export function useNotificationsHandler() {
|
||||
navigation,
|
||||
onPressSwitchAccount,
|
||||
setShowLoggedOut,
|
||||
messagesBus,
|
||||
])
|
||||
}
|
||||
|
||||
|
||||
@@ -9,10 +9,7 @@ import {
|
||||
isNetworkError,
|
||||
} from '#/lib/strings/errors'
|
||||
import {Logger} from '#/logger'
|
||||
import {
|
||||
BACKGROUND_POLL_INTERVAL,
|
||||
DEFAULT_POLL_INTERVAL,
|
||||
} from '#/state/messages/events/const'
|
||||
import {DEFAULT_POLL_INTERVAL} from '#/state/messages/events/const'
|
||||
import {
|
||||
type MessagesEventBusDispatch,
|
||||
MessagesEventBusDispatchEvent,
|
||||
@@ -56,6 +53,17 @@ export class MessagesEventBus {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Force an immediate poll and restart the interval clock from now. Only has
|
||||
* an effect while we're actively polling (Ready) - the dispatched UpdatePoll
|
||||
* is a no-op in other states (init/resume will poll on their own). Used when
|
||||
* an external signal (a chat push notification) tells us new events probably
|
||||
* exist and we don't want to wait for the next scheduled tick.
|
||||
*/
|
||||
pollNow() {
|
||||
this.dispatch({event: MessagesEventBusDispatchEvent.UpdatePoll})
|
||||
}
|
||||
|
||||
getLatestRev() {
|
||||
return this.latestRev
|
||||
}
|
||||
@@ -122,7 +130,7 @@ export class MessagesEventBus {
|
||||
}
|
||||
case MessagesEventBusDispatchEvent.Background: {
|
||||
this.status = MessagesEventBusStatus.Backgrounded
|
||||
this.resetPoll()
|
||||
this.stopPoll()
|
||||
this.emitter.emit('event', {type: 'connect'})
|
||||
break
|
||||
}
|
||||
@@ -142,7 +150,7 @@ export class MessagesEventBus {
|
||||
switch (action.event) {
|
||||
case MessagesEventBusDispatchEvent.Background: {
|
||||
this.status = MessagesEventBusStatus.Backgrounded
|
||||
this.resetPoll()
|
||||
this.stopPoll()
|
||||
break
|
||||
}
|
||||
case MessagesEventBusDispatchEvent.Suspend: {
|
||||
@@ -181,10 +189,6 @@ export class MessagesEventBus {
|
||||
this.emitter.emit('event', {type: 'error', error: action.payload})
|
||||
break
|
||||
}
|
||||
case MessagesEventBusDispatchEvent.UpdatePoll: {
|
||||
this.resetPoll()
|
||||
break
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
@@ -197,7 +201,7 @@ export class MessagesEventBus {
|
||||
}
|
||||
case MessagesEventBusDispatchEvent.Background: {
|
||||
this.status = MessagesEventBusStatus.Backgrounded
|
||||
this.resetPoll()
|
||||
this.stopPoll()
|
||||
break
|
||||
}
|
||||
case MessagesEventBusDispatchEvent.Error: {
|
||||
@@ -313,9 +317,6 @@ export class MessagesEventBus {
|
||||
const lowest = Math.min(DEFAULT_POLL_INTERVAL, ...requested)
|
||||
return lowest
|
||||
}
|
||||
case MessagesEventBusStatus.Backgrounded: {
|
||||
return BACKGROUND_POLL_INTERVAL
|
||||
}
|
||||
default:
|
||||
return DEFAULT_POLL_INTERVAL
|
||||
}
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
export const DEFAULT_POLL_INTERVAL = 60e3
|
||||
export const BACKGROUND_POLL_INTERVAL = 60e3 * 5
|
||||
|
||||
@@ -17,6 +17,15 @@ export function useMessagesEventBus() {
|
||||
return ctx
|
||||
}
|
||||
|
||||
/**
|
||||
* Like useMessagesEventBus, but returns null instead of throwing when there's
|
||||
* no bus (e.g. when logged out, where the provider supplies a null value).
|
||||
* Use this from always-mounted consumers that may run without a session.
|
||||
*/
|
||||
export function useMaybeMessagesEventBus() {
|
||||
return useContext(MessagesEventBusContext)
|
||||
}
|
||||
|
||||
export function MessagesEventBusProvider({
|
||||
children,
|
||||
}: {
|
||||
|
||||
Reference in New Issue
Block a user