diff --git a/src/lib/hooks/useNotificationHandler.ts b/src/lib/hooks/useNotificationHandler.ts index 9621cafc88..db08d18238 100644 --- a/src/lib/hooks/useNotificationHandler.ts +++ b/src/lib/hooks/useNotificationHandler.ts @@ -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() 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, ]) } diff --git a/src/state/messages/events/agent.ts b/src/state/messages/events/agent.ts index 7794204447..324142a761 100644 --- a/src/state/messages/events/agent.ts +++ b/src/state/messages/events/agent.ts @@ -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 } diff --git a/src/state/messages/events/const.ts b/src/state/messages/events/const.ts index 59af713608..13b954e1d7 100644 --- a/src/state/messages/events/const.ts +++ b/src/state/messages/events/const.ts @@ -1,2 +1 @@ export const DEFAULT_POLL_INTERVAL = 60e3 -export const BACKGROUND_POLL_INTERVAL = 60e3 * 5 diff --git a/src/state/messages/events/index.tsx b/src/state/messages/events/index.tsx index 5d1e2ec505..7521f3af2c 100644 --- a/src/state/messages/events/index.tsx +++ b/src/state/messages/events/index.tsx @@ -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, }: {