Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

authored by

Paul Frazee and committed by
GitHub
e358c3cc 357c752a

+34 -6
-2
src/state/queries/notifications/feed.ts
··· 12 12 import {useModerationOpts} from '../preferences' 13 13 import {shouldFilterNotif} from './util' 14 14 import {useMutedThreads} from '#/state/muted-threads' 15 - import {STALE} from '#/state/queries' 16 15 17 16 const GROUPABLE_REASONS = ['like', 'repost', 'follow'] 18 17 const PAGE_SIZE = 30 ··· 60 59 QueryKey, 61 60 RQPageParam 62 61 >({ 63 - staleTime: STALE.INFINITY, 64 62 queryKey: RQKEY(), 65 63 async queryFn({pageParam}: {pageParam: RQPageParam}) { 66 64 const res = await getAgent().listNotifications({
+4 -1
src/view/com/notifications/Feed.tsx
··· 54 54 55 55 // mark all read on fresh data 56 56 React.useEffect(() => { 57 + let cleanup 57 58 if (firstItem) { 58 - markAllRead() 59 + const to = setTimeout(() => markAllRead(), 250) 60 + cleanup = () => clearTimeout(to) 59 61 } 62 + return cleanup 60 63 }, [firstItem, markAllRead]) 61 64 62 65 const items = React.useMemo(() => {
+10 -1
src/view/shell/Drawer.tsx
··· 14 14 FontAwesomeIcon, 15 15 FontAwesomeIconStyle, 16 16 } from '@fortawesome/react-native-fontawesome' 17 + import {useQueryClient} from '@tanstack/react-query' 17 18 import {s, colors} from 'lib/styles' 18 19 import {FEEDBACK_FORM_URL, HELP_DESK_URL} from 'lib/constants' 19 20 import { ··· 50 51 import {useUnreadNotifications} from '#/state/queries/notifications/unread' 51 52 import {emitSoftReset} from '#/state/events' 52 53 import {useInviteCodesQuery} from '#/state/queries/invites' 54 + import {RQKEY as NOTIFS_RQKEY} from '#/state/queries/notifications/feed' 53 55 54 56 export function DrawerProfileCard({ 55 57 account, ··· 104 106 const theme = useTheme() 105 107 const pal = usePalette('default') 106 108 const {_} = useLingui() 109 + const queryClient = useQueryClient() 107 110 const setDrawerOpen = useSetDrawerOpen() 108 111 const navigation = useNavigation<NavigationProp>() 109 112 const {track} = useAnalytics() ··· 135 138 } else if (tabState === TabState.Inside) { 136 139 navigation.dispatch(StackActions.popToTop()) 137 140 } else { 141 + if (tab === 'Notifications') { 142 + // fetch new notifs on view 143 + queryClient.invalidateQueries({ 144 + queryKey: NOTIFS_RQKEY(), 145 + }) 146 + } 138 147 // @ts-ignore must be Home, Search, Notifications, or MyProfile 139 148 navigation.navigate(`${tab}Tab`) 140 149 } 141 150 } 142 151 }, 143 - [track, navigation, setDrawerOpen, currentAccount], 152 + [track, navigation, setDrawerOpen, currentAccount, queryClient], 144 153 ) 145 154 146 155 const onPressHome = React.useCallback(() => onPressTab('Home'), [onPressTab])
+10 -1
src/view/shell/bottom-bar/BottomBar.tsx
··· 1 1 import React, {ComponentProps} from 'react' 2 2 import {GestureResponderEvent, TouchableOpacity, View} from 'react-native' 3 3 import Animated from 'react-native-reanimated' 4 + import {useQueryClient} from '@tanstack/react-query' 4 5 import {StackActions} from '@react-navigation/native' 5 6 import {BottomTabBarProps} from '@react-navigation/bottom-tabs' 6 7 import {useSafeAreaInsets} from 'react-native-safe-area-context' ··· 30 31 import {emitSoftReset} from '#/state/events' 31 32 import {useSession} from '#/state/session' 32 33 import {useProfileQuery} from '#/state/queries/profile' 34 + import {RQKEY as NOTIFS_RQKEY} from '#/state/queries/notifications/feed' 33 35 34 36 type TabOptions = 'Home' | 'Search' | 'Notifications' | 'MyProfile' | 'Feeds' 35 37 ··· 38 40 const {currentAccount} = useSession() 39 41 const pal = usePalette('default') 40 42 const {_} = useLingui() 43 + const queryClient = useQueryClient() 41 44 const safeAreaInsets = useSafeAreaInsets() 42 45 const {track} = useAnalytics() 43 46 const {footerHeight} = useShellLayout() ··· 57 60 } else if (tabState === TabState.Inside) { 58 61 navigation.dispatch(StackActions.popToTop()) 59 62 } else { 63 + if (tab === 'Notifications') { 64 + // fetch new notifs on view 65 + queryClient.invalidateQueries({ 66 + queryKey: NOTIFS_RQKEY(), 67 + }) 68 + } 60 69 navigation.navigate(`${tab}Tab`) 61 70 } 62 71 }, 63 - [track, navigation], 72 + [track, navigation, queryClient], 64 73 ) 65 74 const onPressHome = React.useCallback(() => onPressTab('Home'), [onPressTab]) 66 75 const onPressSearch = React.useCallback(
+10 -1
src/view/shell/desktop/LeftNav.tsx
··· 45 45 import {useComposerControls} from '#/state/shell/composer' 46 46 import {useFetchHandle} from '#/state/queries/handle' 47 47 import {emitSoftReset} from '#/state/events' 48 + import {useQueryClient} from '@tanstack/react-query' 49 + import {RQKEY as NOTIFS_RQKEY} from '#/state/queries/notifications/feed' 48 50 49 51 function ProfileCard() { 50 52 const {currentAccount} = useSession() ··· 118 120 } 119 121 function NavItem({count, href, icon, iconFilled, label}: NavItemProps) { 120 122 const pal = usePalette('default') 123 + const queryClient = useQueryClient() 121 124 const {currentAccount} = useSession() 122 125 const {isDesktop, isTablet} = useWebMediaQueries() 123 126 const [pathName] = React.useMemo(() => router.matchPath(href), [href]) ··· 143 146 if (isCurrent) { 144 147 emitSoftReset() 145 148 } else { 149 + if (href === '/notifications') { 150 + // fetch new notifs on view 151 + queryClient.invalidateQueries({ 152 + queryKey: NOTIFS_RQKEY(), 153 + }) 154 + } 146 155 onPress() 147 156 } 148 157 }, 149 - [onPress, isCurrent], 158 + [onPress, isCurrent, queryClient, href], 150 159 ) 151 160 152 161 return (