Improvements to notifications screen [APP-520] (#501)

* Refresh or sync notifications when the tab is navigated to

* Fix to bad textnode render

* Speed up initial session load

* Fix lint

* Restore updateSessionState() on session resumption
zio/stable
Paul Frazee 2023-04-20 17:36:25 -05:00 committed by GitHub
parent f2fe4abdce
commit e02c926c8a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 57 additions and 10 deletions

View File

@ -0,0 +1,27 @@
import {useEffect, useState} from 'react'
import {useNavigation} from '@react-navigation/native'
import {getTabState, TabState} from 'lib/routes/helpers'
export function useTabFocusEffect(
tabName: string,
cb: (isInside: boolean) => void,
) {
const [isInside, setIsInside] = useState(false)
// get root navigator state
let nav = useNavigation()
while (nav.getParent()) {
nav = nav.getParent()
}
const state = nav.getState()
useEffect(() => {
// check if inside
let v = getTabState(state, tabName) !== TabState.Outside
if (v !== isInside) {
// fire
setIsInside(v)
cb(v)
}
}, [state, isInside, setIsInside, tabName, cb])
}

View File

@ -99,14 +99,12 @@ export class MeModel {
this.handle = sess.currentSession?.handle || '' this.handle = sess.currentSession?.handle || ''
await this.fetchProfile() await this.fetchProfile()
this.mainFeed.clear() this.mainFeed.clear()
await Promise.all([ /* dont await */ this.mainFeed.setup().catch(e => {
this.mainFeed.setup().catch(e => { this.rootStore.log.error('Failed to setup main feed model', e)
this.rootStore.log.error('Failed to setup main feed model', e) })
}), /* dont await */ this.notifications.setup().catch(e => {
this.notifications.setup().catch(e => { this.rootStore.log.error('Failed to setup notifications model', e)
this.rootStore.log.error('Failed to setup notifications model', e) })
}),
])
this.rootStore.emitSessionLoaded() this.rootStore.emitSessionLoaded()
await this.fetchInviteCodes() await this.fetchInviteCodes()
} else { } else {

View File

@ -13,6 +13,7 @@ import {InvitedUsers} from '../com/notifications/InvitedUsers'
import {LoadLatestBtn} from 'view/com/util/load-latest/LoadLatestBtn' import {LoadLatestBtn} from 'view/com/util/load-latest/LoadLatestBtn'
import {useStores} from 'state/index' import {useStores} from 'state/index'
import {useOnMainScroll} from 'lib/hooks/useOnMainScroll' import {useOnMainScroll} from 'lib/hooks/useOnMainScroll'
import {useTabFocusEffect} from 'lib/hooks/useTabFocusEffect'
import {s} from 'lib/styles' import {s} from 'lib/styles'
import {useAnalytics} from 'lib/analytics' import {useAnalytics} from 'lib/analytics'
@ -58,6 +59,27 @@ export const NotificationsScreen = withAuthRequired(
} }
}, [store, screen, onPressLoadLatest]), }, [store, screen, onPressLoadLatest]),
) )
useTabFocusEffect(
'Notifications',
React.useCallback(
isInside => {
// on mobile:
// fires with `isInside=true` when the user navigates to the root tab
// but not when the user goes back to the screen by pressing back
// on web:
// essentially equivalent to useFocusEffect because we dont used tabbed
// navigation
if (isInside) {
if (store.me.notifications.unreadCount > 0) {
store.me.notifications.refresh()
} else {
store.me.notifications.syncQueue()
}
}
},
[store],
),
)
return ( return (
<View testID="notificationsScreen" style={s.hContentRegion}> <View testID="notificationsScreen" style={s.hContentRegion}>

View File

@ -95,11 +95,11 @@ const NavItem = observer(
<Link href={href} style={styles.navItem}> <Link href={href} style={styles.navItem}>
<View style={[styles.navItemIconWrapper]}> <View style={[styles.navItemIconWrapper]}>
{isCurrent ? iconFilled : icon} {isCurrent ? iconFilled : icon}
{typeof count === 'string' && count && ( {typeof count === 'string' && count ? (
<Text type="button" style={styles.navItemCount}> <Text type="button" style={styles.navItemCount}>
{count} {count}
</Text> </Text>
)} ) : null}
</View> </View>
<Text type="title" style={[isCurrent ? s.bold : s.normal, pal.text]}> <Text type="title" style={[isCurrent ? s.bold : s.normal, pal.text]}>
{label} {label}