Improve notification load behaviors (#1943)

* Dont use the stale cache for notifs-feed

* Add a delay to marking all read to avoid marking upcoming posts as read

* Trigger automatic notifications refresh when navigating to the tab, in certain conditions
zio/stable
Paul Frazee 2023-11-16 18:27:05 -08:00 committed by GitHub
parent 357c752a21
commit e358c3cc30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 34 additions and 6 deletions

View File

@ -12,7 +12,6 @@ import {getAgent} from '../../session'
import {useModerationOpts} from '../preferences' import {useModerationOpts} from '../preferences'
import {shouldFilterNotif} from './util' import {shouldFilterNotif} from './util'
import {useMutedThreads} from '#/state/muted-threads' import {useMutedThreads} from '#/state/muted-threads'
import {STALE} from '#/state/queries'
const GROUPABLE_REASONS = ['like', 'repost', 'follow'] const GROUPABLE_REASONS = ['like', 'repost', 'follow']
const PAGE_SIZE = 30 const PAGE_SIZE = 30
@ -60,7 +59,6 @@ export function useNotificationFeedQuery(opts?: {enabled?: boolean}) {
QueryKey, QueryKey,
RQPageParam RQPageParam
>({ >({
staleTime: STALE.INFINITY,
queryKey: RQKEY(), queryKey: RQKEY(),
async queryFn({pageParam}: {pageParam: RQPageParam}) { async queryFn({pageParam}: {pageParam: RQPageParam}) {
const res = await getAgent().listNotifications({ const res = await getAgent().listNotifications({

View File

@ -54,9 +54,12 @@ export function Feed({
// mark all read on fresh data // mark all read on fresh data
React.useEffect(() => { React.useEffect(() => {
let cleanup
if (firstItem) { if (firstItem) {
markAllRead() const to = setTimeout(() => markAllRead(), 250)
cleanup = () => clearTimeout(to)
} }
return cleanup
}, [firstItem, markAllRead]) }, [firstItem, markAllRead])
const items = React.useMemo(() => { const items = React.useMemo(() => {

View File

@ -14,6 +14,7 @@ import {
FontAwesomeIcon, FontAwesomeIcon,
FontAwesomeIconStyle, FontAwesomeIconStyle,
} from '@fortawesome/react-native-fontawesome' } from '@fortawesome/react-native-fontawesome'
import {useQueryClient} from '@tanstack/react-query'
import {s, colors} from 'lib/styles' import {s, colors} from 'lib/styles'
import {FEEDBACK_FORM_URL, HELP_DESK_URL} from 'lib/constants' import {FEEDBACK_FORM_URL, HELP_DESK_URL} from 'lib/constants'
import { import {
@ -50,6 +51,7 @@ import {useProfileQuery} from '#/state/queries/profile'
import {useUnreadNotifications} from '#/state/queries/notifications/unread' import {useUnreadNotifications} from '#/state/queries/notifications/unread'
import {emitSoftReset} from '#/state/events' import {emitSoftReset} from '#/state/events'
import {useInviteCodesQuery} from '#/state/queries/invites' import {useInviteCodesQuery} from '#/state/queries/invites'
import {RQKEY as NOTIFS_RQKEY} from '#/state/queries/notifications/feed'
export function DrawerProfileCard({ export function DrawerProfileCard({
account, account,
@ -104,6 +106,7 @@ export function DrawerContent() {
const theme = useTheme() const theme = useTheme()
const pal = usePalette('default') const pal = usePalette('default')
const {_} = useLingui() const {_} = useLingui()
const queryClient = useQueryClient()
const setDrawerOpen = useSetDrawerOpen() const setDrawerOpen = useSetDrawerOpen()
const navigation = useNavigation<NavigationProp>() const navigation = useNavigation<NavigationProp>()
const {track} = useAnalytics() const {track} = useAnalytics()
@ -135,12 +138,18 @@ export function DrawerContent() {
} else if (tabState === TabState.Inside) { } else if (tabState === TabState.Inside) {
navigation.dispatch(StackActions.popToTop()) navigation.dispatch(StackActions.popToTop())
} else { } else {
if (tab === 'Notifications') {
// fetch new notifs on view
queryClient.invalidateQueries({
queryKey: NOTIFS_RQKEY(),
})
}
// @ts-ignore must be Home, Search, Notifications, or MyProfile // @ts-ignore must be Home, Search, Notifications, or MyProfile
navigation.navigate(`${tab}Tab`) navigation.navigate(`${tab}Tab`)
} }
} }
}, },
[track, navigation, setDrawerOpen, currentAccount], [track, navigation, setDrawerOpen, currentAccount, queryClient],
) )
const onPressHome = React.useCallback(() => onPressTab('Home'), [onPressTab]) const onPressHome = React.useCallback(() => onPressTab('Home'), [onPressTab])

View File

@ -1,6 +1,7 @@
import React, {ComponentProps} from 'react' import React, {ComponentProps} from 'react'
import {GestureResponderEvent, TouchableOpacity, View} from 'react-native' import {GestureResponderEvent, TouchableOpacity, View} from 'react-native'
import Animated from 'react-native-reanimated' import Animated from 'react-native-reanimated'
import {useQueryClient} from '@tanstack/react-query'
import {StackActions} from '@react-navigation/native' import {StackActions} from '@react-navigation/native'
import {BottomTabBarProps} from '@react-navigation/bottom-tabs' import {BottomTabBarProps} from '@react-navigation/bottom-tabs'
import {useSafeAreaInsets} from 'react-native-safe-area-context' import {useSafeAreaInsets} from 'react-native-safe-area-context'
@ -30,6 +31,7 @@ import {useUnreadNotifications} from '#/state/queries/notifications/unread'
import {emitSoftReset} from '#/state/events' import {emitSoftReset} from '#/state/events'
import {useSession} from '#/state/session' import {useSession} from '#/state/session'
import {useProfileQuery} from '#/state/queries/profile' import {useProfileQuery} from '#/state/queries/profile'
import {RQKEY as NOTIFS_RQKEY} from '#/state/queries/notifications/feed'
type TabOptions = 'Home' | 'Search' | 'Notifications' | 'MyProfile' | 'Feeds' type TabOptions = 'Home' | 'Search' | 'Notifications' | 'MyProfile' | 'Feeds'
@ -38,6 +40,7 @@ export function BottomBar({navigation}: BottomTabBarProps) {
const {currentAccount} = useSession() const {currentAccount} = useSession()
const pal = usePalette('default') const pal = usePalette('default')
const {_} = useLingui() const {_} = useLingui()
const queryClient = useQueryClient()
const safeAreaInsets = useSafeAreaInsets() const safeAreaInsets = useSafeAreaInsets()
const {track} = useAnalytics() const {track} = useAnalytics()
const {footerHeight} = useShellLayout() const {footerHeight} = useShellLayout()
@ -57,10 +60,16 @@ export function BottomBar({navigation}: BottomTabBarProps) {
} else if (tabState === TabState.Inside) { } else if (tabState === TabState.Inside) {
navigation.dispatch(StackActions.popToTop()) navigation.dispatch(StackActions.popToTop())
} else { } else {
if (tab === 'Notifications') {
// fetch new notifs on view
queryClient.invalidateQueries({
queryKey: NOTIFS_RQKEY(),
})
}
navigation.navigate(`${tab}Tab`) navigation.navigate(`${tab}Tab`)
} }
}, },
[track, navigation], [track, navigation, queryClient],
) )
const onPressHome = React.useCallback(() => onPressTab('Home'), [onPressTab]) const onPressHome = React.useCallback(() => onPressTab('Home'), [onPressTab])
const onPressSearch = React.useCallback( const onPressSearch = React.useCallback(

View File

@ -45,6 +45,8 @@ import {useUnreadNotifications} from '#/state/queries/notifications/unread'
import {useComposerControls} from '#/state/shell/composer' import {useComposerControls} from '#/state/shell/composer'
import {useFetchHandle} from '#/state/queries/handle' import {useFetchHandle} from '#/state/queries/handle'
import {emitSoftReset} from '#/state/events' import {emitSoftReset} from '#/state/events'
import {useQueryClient} from '@tanstack/react-query'
import {RQKEY as NOTIFS_RQKEY} from '#/state/queries/notifications/feed'
function ProfileCard() { function ProfileCard() {
const {currentAccount} = useSession() const {currentAccount} = useSession()
@ -118,6 +120,7 @@ interface NavItemProps {
} }
function NavItem({count, href, icon, iconFilled, label}: NavItemProps) { function NavItem({count, href, icon, iconFilled, label}: NavItemProps) {
const pal = usePalette('default') const pal = usePalette('default')
const queryClient = useQueryClient()
const {currentAccount} = useSession() const {currentAccount} = useSession()
const {isDesktop, isTablet} = useWebMediaQueries() const {isDesktop, isTablet} = useWebMediaQueries()
const [pathName] = React.useMemo(() => router.matchPath(href), [href]) const [pathName] = React.useMemo(() => router.matchPath(href), [href])
@ -143,10 +146,16 @@ function NavItem({count, href, icon, iconFilled, label}: NavItemProps) {
if (isCurrent) { if (isCurrent) {
emitSoftReset() emitSoftReset()
} else { } else {
if (href === '/notifications') {
// fetch new notifs on view
queryClient.invalidateQueries({
queryKey: NOTIFS_RQKEY(),
})
}
onPress() onPress()
} }
}, },
[onPress, isCurrent], [onPress, isCurrent, queryClient, href],
) )
return ( return (