Multiple notifications fixes (#2154)
* Dont reset notifications feed on push notification event * Dont separate notifications by read state to avoid jank * On notifications screen focus, check latest and only rerender if not scrolled down * Reuse the cached notifs page when its not stale * Bump ios build number * Improve comments * Change the 'mark all read' condition to avoid firing too early
This commit is contained in:
parent
d854e88218
commit
6b3eb401b0
12 changed files with 162 additions and 146 deletions
|
@ -37,6 +37,7 @@ export function NotificationsScreen({}: Props) {
|
|||
const setMinimalShellMode = useSetMinimalShellMode()
|
||||
const [onMainScroll, isScrolledDown, resetMainScroll] = useOnMainScroll()
|
||||
const scrollElRef = React.useRef<FlatList>(null)
|
||||
const checkLatestRef = React.useRef<() => void | null>()
|
||||
const {screen} = useAnalytics()
|
||||
const pal = usePalette('default')
|
||||
const {isDesktop} = useWebMediaQueries()
|
||||
|
@ -63,16 +64,26 @@ export function NotificationsScreen({}: Props) {
|
|||
}
|
||||
}, [scrollToTop, queryClient, unreadApi, hasNew])
|
||||
|
||||
const onFocusCheckLatest = React.useCallback(() => {
|
||||
// on focus, check for latest, but only invalidate if the user
|
||||
// isnt scrolled down to avoid moving content underneath them
|
||||
unreadApi.checkUnread({invalidate: !isScrolledDown})
|
||||
}, [unreadApi, isScrolledDown])
|
||||
checkLatestRef.current = onFocusCheckLatest
|
||||
|
||||
// on-visible setup
|
||||
// =
|
||||
useFocusEffect(
|
||||
React.useCallback(() => {
|
||||
setMinimalShellMode(false)
|
||||
logger.debug('NotificationsScreen: Updating feed')
|
||||
logger.debug('NotificationsScreen: Focus')
|
||||
screen('Notifications')
|
||||
return listenSoftReset(onPressLoadLatest)
|
||||
}, [screen, onPressLoadLatest, setMinimalShellMode]),
|
||||
checkLatestRef.current?.()
|
||||
}, [screen, setMinimalShellMode]),
|
||||
)
|
||||
React.useEffect(() => {
|
||||
return listenSoftReset(onPressLoadLatest)
|
||||
}, [onPressLoadLatest])
|
||||
|
||||
const ListHeaderComponent = React.useCallback(() => {
|
||||
if (isDesktop) {
|
||||
|
|
|
@ -14,7 +14,6 @@ import {
|
|||
FontAwesomeIcon,
|
||||
FontAwesomeIconStyle,
|
||||
} from '@fortawesome/react-native-fontawesome'
|
||||
import {useQueryClient} from '@tanstack/react-query'
|
||||
import {s, colors} from 'lib/styles'
|
||||
import {FEEDBACK_FORM_URL, HELP_DESK_URL} from 'lib/constants'
|
||||
import {
|
||||
|
@ -51,9 +50,7 @@ import {useProfileQuery} from '#/state/queries/profile'
|
|||
import {useUnreadNotifications} from '#/state/queries/notifications/unread'
|
||||
import {emitSoftReset} from '#/state/events'
|
||||
import {useInviteCodesQuery} from '#/state/queries/invites'
|
||||
import {RQKEY as NOTIFS_RQKEY} from '#/state/queries/notifications/feed'
|
||||
import {NavSignupCard} from '#/view/shell/NavSignupCard'
|
||||
import {truncateAndInvalidate} from '#/state/queries/util'
|
||||
|
||||
let DrawerProfileCard = ({
|
||||
account,
|
||||
|
@ -109,7 +106,6 @@ export {DrawerProfileCard}
|
|||
let DrawerContent = ({}: {}): React.ReactNode => {
|
||||
const theme = useTheme()
|
||||
const pal = usePalette('default')
|
||||
const queryClient = useQueryClient()
|
||||
const setDrawerOpen = useSetDrawerOpen()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
const {track} = useAnalytics()
|
||||
|
@ -140,16 +136,12 @@ let DrawerContent = ({}: {}): React.ReactNode => {
|
|||
} else if (tabState === TabState.Inside) {
|
||||
navigation.dispatch(StackActions.popToTop())
|
||||
} else {
|
||||
if (tab === 'Notifications') {
|
||||
// fetch new notifs on view
|
||||
truncateAndInvalidate(queryClient, NOTIFS_RQKEY())
|
||||
}
|
||||
// @ts-ignore must be Home, Search, Notifications, or MyProfile
|
||||
navigation.navigate(`${tab}Tab`)
|
||||
}
|
||||
}
|
||||
},
|
||||
[track, navigation, setDrawerOpen, currentAccount, queryClient],
|
||||
[track, navigation, setDrawerOpen, currentAccount],
|
||||
)
|
||||
|
||||
const onPressHome = React.useCallback(() => onPressTab('Home'), [onPressTab])
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import React, {ComponentProps} from 'react'
|
||||
import {GestureResponderEvent, TouchableOpacity, View} from 'react-native'
|
||||
import Animated from 'react-native-reanimated'
|
||||
import {useQueryClient} from '@tanstack/react-query'
|
||||
import {StackActions} from '@react-navigation/native'
|
||||
import {BottomTabBarProps} from '@react-navigation/bottom-tabs'
|
||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||
|
@ -31,8 +30,6 @@ import {useUnreadNotifications} from '#/state/queries/notifications/unread'
|
|||
import {emitSoftReset} from '#/state/events'
|
||||
import {useSession} from '#/state/session'
|
||||
import {useProfileQuery} from '#/state/queries/profile'
|
||||
import {RQKEY as NOTIFS_RQKEY} from '#/state/queries/notifications/feed'
|
||||
import {truncateAndInvalidate} from '#/state/queries/util'
|
||||
|
||||
type TabOptions = 'Home' | 'Search' | 'Notifications' | 'MyProfile' | 'Feeds'
|
||||
|
||||
|
@ -41,7 +38,6 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
|||
const {hasSession, currentAccount} = useSession()
|
||||
const pal = usePalette('default')
|
||||
const {_} = useLingui()
|
||||
const queryClient = useQueryClient()
|
||||
const safeAreaInsets = useSafeAreaInsets()
|
||||
const {track} = useAnalytics()
|
||||
const {footerHeight} = useShellLayout()
|
||||
|
@ -61,14 +57,10 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
|||
} else if (tabState === TabState.Inside) {
|
||||
navigation.dispatch(StackActions.popToTop())
|
||||
} else {
|
||||
if (tab === 'Notifications') {
|
||||
// fetch new notifs on view
|
||||
truncateAndInvalidate(queryClient, NOTIFS_RQKEY())
|
||||
}
|
||||
navigation.navigate(`${tab}Tab`)
|
||||
}
|
||||
},
|
||||
[track, navigation, queryClient],
|
||||
[track, navigation],
|
||||
)
|
||||
const onPressHome = React.useCallback(() => onPressTab('Home'), [onPressTab])
|
||||
const onPressSearch = React.useCallback(
|
||||
|
|
|
@ -45,10 +45,7 @@ import {useUnreadNotifications} from '#/state/queries/notifications/unread'
|
|||
import {useComposerControls} from '#/state/shell/composer'
|
||||
import {useFetchHandle} from '#/state/queries/handle'
|
||||
import {emitSoftReset} from '#/state/events'
|
||||
import {useQueryClient} from '@tanstack/react-query'
|
||||
import {RQKEY as NOTIFS_RQKEY} from '#/state/queries/notifications/feed'
|
||||
import {NavSignupCard} from '#/view/shell/NavSignupCard'
|
||||
import {truncateAndInvalidate} from '#/state/queries/util'
|
||||
|
||||
function ProfileCard() {
|
||||
const {currentAccount} = useSession()
|
||||
|
@ -123,7 +120,6 @@ interface NavItemProps {
|
|||
}
|
||||
function NavItem({count, href, icon, iconFilled, label}: NavItemProps) {
|
||||
const pal = usePalette('default')
|
||||
const queryClient = useQueryClient()
|
||||
const {currentAccount} = useSession()
|
||||
const {isDesktop, isTablet} = useWebMediaQueries()
|
||||
const [pathName] = React.useMemo(() => router.matchPath(href), [href])
|
||||
|
@ -149,14 +145,10 @@ function NavItem({count, href, icon, iconFilled, label}: NavItemProps) {
|
|||
if (isCurrent) {
|
||||
emitSoftReset()
|
||||
} else {
|
||||
if (href === '/notifications') {
|
||||
// fetch new notifs on view
|
||||
truncateAndInvalidate(queryClient, NOTIFS_RQKEY())
|
||||
}
|
||||
onPress()
|
||||
}
|
||||
},
|
||||
[onPress, isCurrent, queryClient, href],
|
||||
[onPress, isCurrent],
|
||||
)
|
||||
|
||||
return (
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue