Refactor the notifications to cache and reuse results from the unread-notifs checks (#2017)

* Refactor the notifications to cache and reuse results from the unread-notifs checks

* Fix types
This commit is contained in:
Paul Frazee 2023-11-29 10:20:14 -08:00 committed by GitHub
parent 620e002841
commit 9239efac9c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 369 additions and 246 deletions

View file

@ -35,15 +35,13 @@ export function Feed({
const [isPTRing, setIsPTRing] = React.useState(false)
const moderationOpts = useModerationOpts()
const {markAllRead} = useUnreadNotificationsApi()
const {markAllRead, checkUnread} = useUnreadNotificationsApi()
const {
data,
isLoading,
isFetching,
isFetched,
isError,
error,
refetch,
hasNextPage,
isFetchingNextPage,
fetchNextPage,
@ -52,13 +50,11 @@ export function Feed({
const firstItem = data?.pages[0]?.items[0]
// mark all read on fresh data
// (this will fire each time firstItem changes)
React.useEffect(() => {
let cleanup
if (firstItem) {
const to = setTimeout(() => markAllRead(), 250)
cleanup = () => clearTimeout(to)
markAllRead()
}
return cleanup
}, [firstItem, markAllRead])
const items = React.useMemo(() => {
@ -83,7 +79,7 @@ export function Feed({
const onRefresh = React.useCallback(async () => {
try {
setIsPTRing(true)
await refetch()
await checkUnread({invalidate: true})
} catch (err) {
logger.error('Failed to refresh notifications feed', {
error: err,
@ -91,7 +87,7 @@ export function Feed({
} finally {
setIsPTRing(false)
}
}, [refetch, setIsPTRing])
}, [checkUnread, setIsPTRing])
const onEndReached = React.useCallback(async () => {
if (isFetching || !hasNextPage || isError) return
@ -136,21 +132,6 @@ export function Feed({
[onPressRetryLoadMore, moderationOpts],
)
const showHeaderSpinner = !isPTRing && isFetching && !isLoading
const FeedHeader = React.useCallback(
() => (
<View>
{ListHeaderComponent ? <ListHeaderComponent /> : null}
{showHeaderSpinner ? (
<View style={{padding: 10}}>
<ActivityIndicator />
</View>
) : null}
</View>
),
[ListHeaderComponent, showHeaderSpinner],
)
const FeedFooter = React.useCallback(
() =>
isFetchingNextPage ? (
@ -180,7 +161,7 @@ export function Feed({
data={items}
keyExtractor={item => item._reactKey}
renderItem={renderItem}
ListHeaderComponent={FeedHeader}
ListHeaderComponent={ListHeaderComponent}
ListFooterComponent={FeedFooter}
refreshControl={
<RefreshControl

View file

@ -19,7 +19,10 @@ import {logger} from '#/logger'
import {useSetMinimalShellMode} from '#/state/shell'
import {Trans, msg} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useUnreadNotifications} from '#/state/queries/notifications/unread'
import {
useUnreadNotifications,
useUnreadNotificationsApi,
} from '#/state/queries/notifications/unread'
import {RQKEY as NOTIFS_RQKEY} from '#/state/queries/notifications/feed'
import {listenSoftReset, emitSoftReset} from '#/state/events'
@ -35,8 +38,9 @@ export function NotificationsScreen({}: Props) {
const {screen} = useAnalytics()
const pal = usePalette('default')
const {isDesktop} = useWebMediaQueries()
const unreadNotifs = useUnreadNotifications()
const queryClient = useQueryClient()
const unreadNotifs = useUnreadNotifications()
const unreadApi = useUnreadNotificationsApi()
const hasNew = !!unreadNotifs
// event handlers
@ -48,10 +52,16 @@ export function NotificationsScreen({}: Props) {
const onPressLoadLatest = React.useCallback(() => {
scrollToTop()
queryClient.invalidateQueries({
queryKey: NOTIFS_RQKEY(),
})
}, [scrollToTop, queryClient])
if (hasNew) {
// render what we have now
queryClient.invalidateQueries({
queryKey: NOTIFS_RQKEY(),
})
} else {
// check with the server
unreadApi.checkUnread({invalidate: true})
}
}, [scrollToTop, queryClient, unreadApi, hasNew])
// on-visible setup
// =