Bluesky app fork with some witchin' additions 💫
0
fork

Configure Feed

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

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

authored by

Paul Frazee and committed by
GitHub
e02c926c f2fe4abd

+57 -10
+27
src/lib/hooks/useTabFocusEffect.ts
··· 1 + import {useEffect, useState} from 'react' 2 + import {useNavigation} from '@react-navigation/native' 3 + import {getTabState, TabState} from 'lib/routes/helpers' 4 + 5 + export function useTabFocusEffect( 6 + tabName: string, 7 + cb: (isInside: boolean) => void, 8 + ) { 9 + const [isInside, setIsInside] = useState(false) 10 + 11 + // get root navigator state 12 + let nav = useNavigation() 13 + while (nav.getParent()) { 14 + nav = nav.getParent() 15 + } 16 + const state = nav.getState() 17 + 18 + useEffect(() => { 19 + // check if inside 20 + let v = getTabState(state, tabName) !== TabState.Outside 21 + if (v !== isInside) { 22 + // fire 23 + setIsInside(v) 24 + cb(v) 25 + } 26 + }, [state, isInside, setIsInside, tabName, cb]) 27 + }
+6 -8
src/state/models/me.ts
··· 99 99 this.handle = sess.currentSession?.handle || '' 100 100 await this.fetchProfile() 101 101 this.mainFeed.clear() 102 - await Promise.all([ 103 - this.mainFeed.setup().catch(e => { 104 - this.rootStore.log.error('Failed to setup main feed model', e) 105 - }), 106 - this.notifications.setup().catch(e => { 107 - this.rootStore.log.error('Failed to setup notifications model', e) 108 - }), 109 - ]) 102 + /* dont await */ this.mainFeed.setup().catch(e => { 103 + this.rootStore.log.error('Failed to setup main feed model', e) 104 + }) 105 + /* dont await */ this.notifications.setup().catch(e => { 106 + this.rootStore.log.error('Failed to setup notifications model', e) 107 + }) 110 108 this.rootStore.emitSessionLoaded() 111 109 await this.fetchInviteCodes() 112 110 } else {
+22
src/view/screens/Notifications.tsx
··· 13 13 import {LoadLatestBtn} from 'view/com/util/load-latest/LoadLatestBtn' 14 14 import {useStores} from 'state/index' 15 15 import {useOnMainScroll} from 'lib/hooks/useOnMainScroll' 16 + import {useTabFocusEffect} from 'lib/hooks/useTabFocusEffect' 16 17 import {s} from 'lib/styles' 17 18 import {useAnalytics} from 'lib/analytics' 18 19 ··· 57 58 store.me.notifications.markAllRead() 58 59 } 59 60 }, [store, screen, onPressLoadLatest]), 61 + ) 62 + useTabFocusEffect( 63 + 'Notifications', 64 + React.useCallback( 65 + isInside => { 66 + // on mobile: 67 + // fires with `isInside=true` when the user navigates to the root tab 68 + // but not when the user goes back to the screen by pressing back 69 + // on web: 70 + // essentially equivalent to useFocusEffect because we dont used tabbed 71 + // navigation 72 + if (isInside) { 73 + if (store.me.notifications.unreadCount > 0) { 74 + store.me.notifications.refresh() 75 + } else { 76 + store.me.notifications.syncQueue() 77 + } 78 + } 79 + }, 80 + [store], 81 + ), 60 82 ) 61 83 62 84 return (
+2 -2
src/view/shell/desktop/LeftNav.tsx
··· 95 95 <Link href={href} style={styles.navItem}> 96 96 <View style={[styles.navItemIconWrapper]}> 97 97 {isCurrent ? iconFilled : icon} 98 - {typeof count === 'string' && count && ( 98 + {typeof count === 'string' && count ? ( 99 99 <Text type="button" style={styles.navItemCount}> 100 100 {count} 101 101 </Text> 102 - )} 102 + ) : null} 103 103 </View> 104 104 <Text type="title" style={[isCurrent ? s.bold : s.normal, pal.text]}> 105 105 {label}