Extract shell state into separate context (#1824)

* WIP

* Add shell state

* Integrate new shell state for drawer and minimal shell mode

* Replace isDrawerSwipeDisabled

* Split shell state into separate contexts to avoid needless re-renders

* Fix typo

---------

Co-authored-by: Paul Frazee <pfrazee@gmail.com>
This commit is contained in:
Eric Bailey 2023-11-07 13:37:47 -06:00 committed by GitHub
parent 7158157f5f
commit bfe196bac5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
51 changed files with 368 additions and 238 deletions

View file

@ -9,6 +9,7 @@ import {usePalette} from 'lib/hooks/usePalette'
import {useStores} from 'state/index'
import {useAnalytics} from 'lib/analytics/analytics'
import {SplashScreen} from './SplashScreen'
import {useSetMinimalShellMode} from '#/state/shell/minimal-mode'
enum ScreenState {
S_LoginOrCreateAccount,
@ -19,6 +20,7 @@ enum ScreenState {
export const LoggedOut = observer(function LoggedOutImpl() {
const pal = usePalette('default')
const store = useStores()
const setMinimalShellMode = useSetMinimalShellMode()
const {screen} = useAnalytics()
const [screenState, setScreenState] = React.useState<ScreenState>(
ScreenState.S_LoginOrCreateAccount,
@ -26,8 +28,8 @@ export const LoggedOut = observer(function LoggedOutImpl() {
React.useEffect(() => {
screen('Login')
store.shell.setMinimalShellMode(true)
}, [store, screen])
setMinimalShellMode(true)
}, [screen, setMinimalShellMode])
if (
store.session.isResumingSession ||

View file

@ -8,14 +8,16 @@ import {useStores} from 'state/index'
import {Welcome} from './onboarding/Welcome'
import {RecommendedFeeds} from './onboarding/RecommendedFeeds'
import {RecommendedFollows} from './onboarding/RecommendedFollows'
import {useSetMinimalShellMode} from '#/state/shell/minimal-mode'
export const Onboarding = observer(function OnboardingImpl() {
const pal = usePalette('default')
const store = useStores()
const setMinimalShellMode = useSetMinimalShellMode()
React.useEffect(() => {
store.shell.setMinimalShellMode(true)
}, [store])
setMinimalShellMode(true)
}, [setMinimalShellMode])
const next = () => store.onboarding.next()
const skip = () => store.onboarding.skip()

View file

@ -38,7 +38,7 @@ export const FeedPage = observer(function FeedPageImpl({
const store = useStores()
const pal = usePalette('default')
const {isDesktop} = useWebMediaQueries()
const [onMainScroll, isScrolledDown, resetMainScroll] = useOnMainScroll(store)
const [onMainScroll, isScrolledDown, resetMainScroll] = useOnMainScroll()
const {screen, track} = useAnalytics()
const headerOffset = useHeaderOffset()
const scrollElRef = React.useRef<FlatList>(null)

View file

@ -13,21 +13,23 @@ import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {FontAwesomeIconStyle} from '@fortawesome/react-native-fontawesome'
import {s} from 'lib/styles'
import {HITSLOP_10} from 'lib/constants'
import {useMinimalShellMode} from 'lib/hooks/useMinimalShellMode'
import Animated from 'react-native-reanimated'
import {useMinimalShellMode} from 'lib/hooks/useMinimalShellMode'
import {useSetDrawerOpen} from '#/state/shell/drawer-open'
export const FeedsTabBar = observer(function FeedsTabBarImpl(
props: RenderTabBarFnProps & {testID?: string; onPressSelected: () => void},
) {
const pal = usePalette('default')
const store = useStores()
const setDrawerOpen = useSetDrawerOpen()
const items = useHomeTabs(store.preferences.pinnedFeeds)
const brandBlue = useColorSchemeStyle(s.brandBlue, s.blue3)
const {headerMinimalShellTransform} = useMinimalShellMode()
const {minimalShellMode, headerMinimalShellTransform} = useMinimalShellMode()
const onPressAvi = React.useCallback(() => {
store.shell.openDrawer()
}, [store])
setDrawerOpen(true)
}, [setDrawerOpen])
return (
<Animated.View
@ -36,7 +38,7 @@ export const FeedsTabBar = observer(function FeedsTabBarImpl(
pal.border,
styles.tabBar,
headerMinimalShellTransform,
store.shell.minimalShellMode && styles.disabled,
minimalShellMode && styles.disabled,
]}>
<View style={[pal.view, styles.topBar]}>
<View style={[pal.view]}>

View file

@ -17,6 +17,7 @@ import {NavigationProp} from 'lib/routes/types'
import {BACK_HITSLOP} from 'lib/constants'
import {isNative} from 'platform/detection'
import {ImagesLightbox} from 'state/models/ui/shell'
import {useSetDrawerOpen} from '#/state/shell'
export const ProfileSubpageHeader = observer(function HeaderImpl({
isLoading,
@ -42,6 +43,7 @@ export const ProfileSubpageHeader = observer(function HeaderImpl({
avatarType: UserAvatarType
}>) {
const store = useStores()
const setDrawerOpen = useSetDrawerOpen()
const navigation = useNavigation<NavigationProp>()
const {isMobile} = useWebMediaQueries()
const pal = usePalette('default')
@ -56,8 +58,8 @@ export const ProfileSubpageHeader = observer(function HeaderImpl({
}, [navigation])
const onPressMenu = React.useCallback(() => {
store.shell.openDrawer()
}, [store])
setDrawerOpen(true)
}, [setDrawerOpen])
const onPressAvi = React.useCallback(() => {
if (

View file

@ -8,10 +8,10 @@ import {Text} from 'view/com/util/text/Text'
import {MagnifyingGlassIcon} from 'lib/icons'
import {useTheme} from 'lib/ThemeContext'
import {usePalette} from 'lib/hooks/usePalette'
import {useStores} from 'state/index'
import {useAnalytics} from 'lib/analytics/analytics'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {HITSLOP_10} from 'lib/constants'
import {useSetDrawerOpen} from '#/state/shell'
interface Props {
isInputFocused: boolean
@ -33,7 +33,7 @@ export function HeaderWithInput({
onSubmitQuery,
showMenu = true,
}: Props) {
const store = useStores()
const setDrawerOpen = useSetDrawerOpen()
const theme = useTheme()
const pal = usePalette('default')
const {track} = useAnalytics()
@ -42,8 +42,8 @@ export function HeaderWithInput({
const onPressMenu = React.useCallback(() => {
track('ViewHeader:MenuButtonClicked')
store.shell.openDrawer()
}, [track, store])
setDrawerOpen(true)
}, [track, setDrawerOpen])
const onPressCancelSearchInner = React.useCallback(() => {
onPressCancelSearch()

View file

@ -10,11 +10,11 @@ import {
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {useNavigation} from '@react-navigation/native'
import {CenteredView} from './Views'
import {useStores} from 'state/index'
import {usePalette} from 'lib/hooks/usePalette'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {useAnalytics} from 'lib/analytics/analytics'
import {NavigationProp} from 'lib/routes/types'
import {useSetDrawerOpen} from '#/state/shell'
const BACK_HITSLOP = {left: 20, top: 20, right: 50, bottom: 20}
@ -27,7 +27,7 @@ export const SimpleViewHeader = observer(function SimpleViewHeaderImpl({
style?: StyleProp<ViewStyle>
}>) {
const pal = usePalette('default')
const store = useStores()
const setDrawerOpen = useSetDrawerOpen()
const navigation = useNavigation<NavigationProp>()
const {track} = useAnalytics()
const {isMobile} = useWebMediaQueries()
@ -43,8 +43,8 @@ export const SimpleViewHeader = observer(function SimpleViewHeaderImpl({
const onPressMenu = React.useCallback(() => {
track('ViewHeader:MenuButtonClicked')
store.shell.openDrawer()
}, [track, store])
setDrawerOpen(true)
}, [track, setDrawerOpen])
const Container = isMobile ? View : CenteredView
return (

View file

@ -5,13 +5,13 @@ import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {useNavigation} from '@react-navigation/native'
import {CenteredView} from './Views'
import {Text} from './text/Text'
import {useStores} from 'state/index'
import {usePalette} from 'lib/hooks/usePalette'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {useAnalytics} from 'lib/analytics/analytics'
import {NavigationProp} from 'lib/routes/types'
import {useMinimalShellMode} from 'lib/hooks/useMinimalShellMode'
import Animated from 'react-native-reanimated'
import {useSetDrawerOpen} from '#/state/shell'
const BACK_HITSLOP = {left: 20, top: 20, right: 50, bottom: 20}
@ -33,7 +33,7 @@ export const ViewHeader = observer(function ViewHeaderImpl({
renderButton?: () => JSX.Element
}) {
const pal = usePalette('default')
const store = useStores()
const setDrawerOpen = useSetDrawerOpen()
const navigation = useNavigation<NavigationProp>()
const {track} = useAnalytics()
const {isDesktop, isTablet} = useWebMediaQueries()
@ -48,8 +48,8 @@ export const ViewHeader = observer(function ViewHeaderImpl({
const onPressMenu = React.useCallback(() => {
track('ViewHeader:MenuButtonClicked')
store.shell.openDrawer()
}, [track, store])
setDrawerOpen(true)
}, [track, setDrawerOpen])
if (isDesktop) {
if (showOnDesktop) {