switch minimal shell mode to refcounting

This commit is contained in:
Samuel Newman
2026-04-21 21:04:14 +03:00
parent 2ab1e2c9e9
commit cb1ce33512
40 changed files with 186 additions and 402 deletions
+2 -6
View File
@@ -13,7 +13,7 @@ import {
useLoggedOutView,
useLoggedOutViewControls,
} from '#/state/shell/logged-out'
import {useSetMinimalShellMode} from '#/state/shell/minimal-mode'
import {useEnableMinimalShellMode} from '#/state/shell/minimal-mode'
import {ErrorBoundary} from '#/view/com/util/ErrorBoundary'
import {Login} from '#/screens/Login'
import {Signup} from '#/screens/Signup'
@@ -37,7 +37,7 @@ export function LoggedOut({onDismiss}: {onDismiss?: () => void}) {
const ax = useAnalytics()
const t = useTheme()
const insets = useSafeAreaInsets()
const setMinimalShellMode = useSetMinimalShellMode()
useEnableMinimalShellMode()
const {requestedAccountSwitchTo} = useLoggedOutView()
const [screenState, setScreenState] = useState<ScreenState>(() => {
if (requestedAccountSwitchTo === 'new') {
@@ -68,10 +68,6 @@ export function LoggedOut({onDismiss}: {onDismiss?: () => void}) {
})
}, [accounts, agent, queryClient])
useEffect(() => {
setMinimalShellMode(true)
}, [setMinimalShellMode])
const onPressDismiss = useCallback(() => {
if (onDismiss) {
onDismiss()
+1 -4
View File
@@ -30,7 +30,6 @@ import {
} from '#/state/queries/post-feed'
import {truncateAndInvalidate} from '#/state/queries/util'
import {useSession} from '#/state/session'
import {useSetMinimalShellMode} from '#/state/shell'
import {useHeaderOffset} from '#/components/hooks/useHeaderOffset'
import {useAnalytics} from '#/analytics'
import {IS_NATIVE} from '#/env'
@@ -70,7 +69,6 @@ export function FeedPage({
const queryClient = useQueryClient()
const {openComposer} = useOpenComposer()
const [isScrolledDown, setIsScrolledDown] = useState(false)
const setMinimalShellMode = useSetMinimalShellMode()
const headerOffset = useHeaderOffset()
const feedFeedback = useFeedFeedback(feedInfo, hasSession)
const scrollElRef = useRef<ListMethods>(null)
@@ -95,8 +93,7 @@ export function FeedPage({
animated: IS_NATIVE,
offset: -headerOffset,
})
setMinimalShellMode(false)
}, [headerOffset, setMinimalShellMode])
}, [headerOffset])
const onSoftReset = useCallback(() => {
const isScreenFocused =
-10
View File
@@ -1,9 +1,7 @@
import {useCallback} from 'react'
import {View} from 'react-native'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {Trans} from '@lingui/react/macro'
import {useFocusEffect} from '@react-navigation/native'
import {usePalette} from '#/lib/hooks/usePalette'
import {
@@ -11,7 +9,6 @@ import {
type NativeStackScreenProps,
} from '#/lib/routes/types'
import {s} from '#/lib/styles'
import {useSetMinimalShellMode} from '#/state/shell'
import {TextLink} from '#/view/com/util/Link'
import {Text} from '#/view/com/util/text/Text'
import {ScrollView} from '#/view/com/util/Views'
@@ -25,13 +22,6 @@ type Props = NativeStackScreenProps<
export const CommunityGuidelinesScreen = (_props: Props) => {
const pal = usePalette('default')
const {_} = useLingui()
const setMinimalShellMode = useSetMinimalShellMode()
useFocusEffect(
useCallback(() => {
setMinimalShellMode(false)
}, [setMinimalShellMode]),
)
return (
<Layout.Screen>
-10
View File
@@ -1,9 +1,7 @@
import {useCallback} from 'react'
import {View} from 'react-native'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {Trans} from '@lingui/react/macro'
import {useFocusEffect} from '@react-navigation/native'
import {usePalette} from '#/lib/hooks/usePalette'
import {
@@ -11,7 +9,6 @@ import {
type NativeStackScreenProps,
} from '#/lib/routes/types'
import {s} from '#/lib/styles'
import {useSetMinimalShellMode} from '#/state/shell'
import {TextLink} from '#/view/com/util/Link'
import {Text} from '#/view/com/util/text/Text'
import {ScrollView} from '#/view/com/util/Views'
@@ -22,13 +19,6 @@ type Props = NativeStackScreenProps<CommonNavigatorParams, 'CopyrightPolicy'>
export const CopyrightPolicyScreen = (_props: Props) => {
const pal = usePalette('default')
const {_} = useLingui()
const setMinimalShellMode = useSetMinimalShellMode()
useFocusEffect(
useCallback(() => {
setMinimalShellMode(false)
}, [setMinimalShellMode]),
)
return (
<Layout.Screen>
-9
View File
@@ -4,7 +4,6 @@ import {type AppBskyFeedDefs} from '@atproto/api'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {Trans} from '@lingui/react/macro'
import {useFocusEffect} from '@react-navigation/native'
import debounce from 'lodash.debounce'
import {useOpenComposer} from '#/lib/hooks/useOpenComposer'
@@ -24,7 +23,6 @@ import {
useSearchPopularFeedsMutation,
} from '#/state/queries/feed'
import {useSession} from '#/state/session'
import {useSetMinimalShellMode} from '#/state/shell'
import {ErrorMessage} from '#/view/com/util/error/ErrorMessage'
import {FAB} from '#/view/com/util/fab/FAB'
import {List, type ListMethods} from '#/view/com/util/List'
@@ -126,7 +124,6 @@ export function FeedsScreen(_props: Props) {
hasNextPage: hasNextPopularFeedsPage,
} = useGetPopularFeedsQuery()
const {_} = useLingui()
const setMinimalShellMode = useSetMinimalShellMode()
const {
data: searchResults,
mutate: search,
@@ -193,12 +190,6 @@ export function FeedsScreen(_props: Props) {
fetchNextPopularFeedsPage,
])
useFocusEffect(
useCallback(() => {
setMinimalShellMode(false)
}, [setMinimalShellMode]),
)
const items = useMemo(() => {
let slices: FlatlistSlice[] = []
const hasActualSavedCount =
+2 -8
View File
@@ -20,7 +20,7 @@ import {type FeedDescriptor, type FeedParams} from '#/state/queries/post-feed'
import {usePreferencesQuery} from '#/state/queries/preferences'
import {type UsePreferencesQueryResponse} from '#/state/queries/preferences/types'
import {useSession} from '#/state/session'
import {useSetMinimalShellMode} from '#/state/shell'
import {useDangerouslyImperativelySetMinimalShellMode} from '#/state/shell'
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
import {useSelectedFeed, useSetSelectedFeed} from '#/state/shell/selected-feed'
import {FeedPage} from '#/view/com/feeds/FeedPage'
@@ -138,12 +138,7 @@ function HomeScreenReady({
}, [selectedIndex])
const {hasSession} = useSession()
const setMinimalShellMode = useSetMinimalShellMode()
useFocusEffect(
useCallback(() => {
setMinimalShellMode(false)
}, [setMinimalShellMode]),
)
const setMinimalShellMode = useDangerouslyImperativelySetMinimalShellMode()
useFocusEffect(
useNonReactiveCallback(() => {
@@ -247,7 +242,6 @@ function HomeScreenReady({
ref={pagerRef}
testID="homeScreen"
onPageSelected={onPageSelected}
onPageScrollStateChanged={onPageScrollStateChanged}
renderTabBar={renderTabBar}
initialPage={selectedIndex}>
<FeedPage
+1 -9
View File
@@ -3,7 +3,7 @@ import {AtUri} from '@atproto/api'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {Trans} from '@lingui/react/macro'
import {useFocusEffect, useNavigation} from '@react-navigation/native'
import {useNavigation} from '@react-navigation/native'
import {useRequireEmailVerification} from '#/lib/hooks/useRequireEmailVerification'
import {
@@ -11,7 +11,6 @@ import {
type NativeStackScreenProps,
type NavigationProp,
} from '#/lib/routes/types'
import {useSetMinimalShellMode} from '#/state/shell'
import {MyLists} from '#/view/com/lists/MyLists'
import {atoms as a} from '#/alf'
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
@@ -23,17 +22,10 @@ import * as Layout from '#/components/Layout'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'Lists'>
export function ListsScreen({}: Props) {
const {_} = useLingui()
const setMinimalShellMode = useSetMinimalShellMode()
const navigation = useNavigation<NavigationProp>()
const requireEmailVerification = useRequireEmailVerification()
const createListDialogControl = useDialogControl()
useFocusEffect(
useCallback(() => {
setMinimalShellMode(false)
}, [setMinimalShellMode]),
)
const onPressNewList = useCallback(() => {
createListDialogControl.open()
}, [createListDialogControl])
@@ -2,7 +2,6 @@ import {useCallback, useMemo, useState} from 'react'
import {type StyleProp, View, type ViewStyle} from 'react-native'
import {type AppBskyActorDefs as ActorDefs} from '@atproto/api'
import {Trans} from '@lingui/react/macro'
import {useFocusEffect} from '@react-navigation/native'
import {type NativeStackScreenProps} from '@react-navigation/native-stack'
import {type CommonNavigatorParams} from '#/lib/routes/types'
@@ -10,7 +9,6 @@ import {cleanError} from '#/lib/strings/errors'
import {logger} from '#/logger'
import {useModerationOpts} from '#/state/preferences/moderation-opts'
import {useMyBlockedAccountsQuery} from '#/state/queries/my-blocked-accounts'
import {useSetMinimalShellMode} from '#/state/shell'
import {ErrorScreen} from '#/view/com/util/error/ErrorScreen'
import {List} from '#/view/com/util/List'
import {atoms as a, useTheme} from '#/alf'
@@ -25,7 +23,6 @@ type Props = NativeStackScreenProps<
>
export function ModerationBlockedAccounts({}: Props) {
const t = useTheme()
const setMinimalShellMode = useSetMinimalShellMode()
const moderationOpts = useModerationOpts()
const [isPTRing, setIsPTRing] = useState(false)
@@ -47,12 +44,6 @@ export function ModerationBlockedAccounts({}: Props) {
return []
}, [data])
useFocusEffect(
useCallback(() => {
setMinimalShellMode(false)
}, [setMinimalShellMode]),
)
const onRefresh = useCallback(async () => {
setIsPTRing(true)
try {
+1 -9
View File
@@ -3,7 +3,7 @@ import {AtUri} from '@atproto/api'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {Trans} from '@lingui/react/macro'
import {useFocusEffect, useNavigation} from '@react-navigation/native'
import {useNavigation} from '@react-navigation/native'
import {useRequireEmailVerification} from '#/lib/hooks/useRequireEmailVerification'
import {
@@ -11,7 +11,6 @@ import {
type NativeStackScreenProps,
type NavigationProp,
} from '#/lib/routes/types'
import {useSetMinimalShellMode} from '#/state/shell'
import {MyLists} from '#/view/com/lists/MyLists'
import {atoms as a} from '#/alf'
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
@@ -23,17 +22,10 @@ import * as Layout from '#/components/Layout'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'ModerationModlists'>
export function ModerationModlistsScreen({}: Props) {
const {_} = useLingui()
const setMinimalShellMode = useSetMinimalShellMode()
const navigation = useNavigation<NavigationProp>()
const requireEmailVerification = useRequireEmailVerification()
const createListDialogControl = useDialogControl()
useFocusEffect(
useCallback(() => {
setMinimalShellMode(false)
}, [setMinimalShellMode]),
)
const onPressNewList = useCallback(() => {
createListDialogControl.open()
}, [createListDialogControl])
@@ -2,7 +2,6 @@ import {useCallback, useMemo, useState} from 'react'
import {type StyleProp, View, type ViewStyle} from 'react-native'
import {type AppBskyActorDefs as ActorDefs} from '@atproto/api'
import {Trans} from '@lingui/react/macro'
import {useFocusEffect} from '@react-navigation/native'
import {type NativeStackScreenProps} from '@react-navigation/native-stack'
import {type CommonNavigatorParams} from '#/lib/routes/types'
@@ -10,7 +9,6 @@ import {cleanError} from '#/lib/strings/errors'
import {logger} from '#/logger'
import {useModerationOpts} from '#/state/preferences/moderation-opts'
import {useMyMutedAccountsQuery} from '#/state/queries/my-muted-accounts'
import {useSetMinimalShellMode} from '#/state/shell'
import {ErrorScreen} from '#/view/com/util/error/ErrorScreen'
import {List} from '#/view/com/util/List'
import {atoms as a, useTheme} from '#/alf'
@@ -26,7 +24,6 @@ type Props = NativeStackScreenProps<
export function ModerationMutedAccounts({}: Props) {
const t = useTheme()
const moderationOpts = useModerationOpts()
const setMinimalShellMode = useSetMinimalShellMode()
const [isPTRing, setIsPTRing] = useState(false)
const {
@@ -47,12 +44,6 @@ export function ModerationMutedAccounts({}: Props) {
return []
}, [data])
useFocusEffect(
useCallback(() => {
setMinimalShellMode(false)
}, [setMinimalShellMode]),
)
const onRefresh = useCallback(async () => {
setIsPTRing(true)
try {
+1 -13
View File
@@ -3,16 +3,11 @@ import {StyleSheet, View} from 'react-native'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {Trans} from '@lingui/react/macro'
import {
StackActions,
useFocusEffect,
useNavigation,
} from '@react-navigation/native'
import {StackActions, useNavigation} from '@react-navigation/native'
import {usePalette} from '#/lib/hooks/usePalette'
import {type NavigationProp} from '#/lib/routes/types'
import {s} from '#/lib/styles'
import {useSetMinimalShellMode} from '#/state/shell'
import {Button} from '#/view/com/util/forms/Button'
import {Text} from '#/view/com/util/text/Text'
import {ViewHeader} from '#/view/com/util/ViewHeader'
@@ -22,13 +17,6 @@ export const NotFoundScreen = () => {
const pal = usePalette('default')
const {_} = useLingui()
const navigation = useNavigation<NavigationProp>()
const setMinimalShellMode = useSetMinimalShellMode()
useFocusEffect(
useCallback(() => {
setMinimalShellMode(false)
}, [setMinimalShellMode]),
)
const canGoBack = navigation.canGoBack()
const onPressHome = useCallback(() => {
+2 -6
View File
@@ -23,7 +23,6 @@ import {
useUnreadNotificationsApi,
} from '#/state/queries/notifications/unread'
import {truncateAndInvalidate} from '#/state/queries/util'
import {useSetMinimalShellMode} from '#/state/shell'
import {NotificationFeed} from '#/view/com/notifications/NotificationFeed'
import {Pager} from '#/view/com/pager/Pager'
import {TabBar} from '#/view/com/pager/TabBar'
@@ -187,7 +186,6 @@ function NotificationsTab({
setIsLoadingLatest: (v: boolean) => void
}) {
const {_} = useLingui()
const setMinimalShellMode = useSetMinimalShellMode()
const [isScrolledDown, setIsScrolledDown] = useState(false)
const scrollElRef = useRef<ListMethods>(null)
const queryClient = useQueryClient()
@@ -198,8 +196,7 @@ function NotificationsTab({
// =
const scrollToTop = useCallback(() => {
scrollElRef.current?.scrollToOffset({animated: IS_NATIVE, offset: 0})
setMinimalShellMode(false)
}, [scrollElRef, setMinimalShellMode])
}, [scrollElRef])
const onPressLoadLatest = useCallback(() => {
scrollToTop()
@@ -242,11 +239,10 @@ function NotificationsTab({
useFocusEffect(
useCallback(() => {
if (isFocusedAndActive) {
setMinimalShellMode(false)
logger.debug('NotificationsScreen: Focus')
onFocusCheckLatest()
}
}, [setMinimalShellMode, onFocusCheckLatest, isFocusedAndActive]),
}, [onFocusCheckLatest, isFocusedAndActive]),
)
useEffect(() => {
-12
View File
@@ -1,28 +1,16 @@
import {useCallback} from 'react'
import {useFocusEffect} from '@react-navigation/native'
import {
type CommonNavigatorParams,
type NativeStackScreenProps,
} from '#/lib/routes/types'
import {makeRecordUri} from '#/lib/strings/url-helpers'
import {useSetMinimalShellMode} from '#/state/shell'
import {PostThread} from '#/screens/PostThread'
import * as Layout from '#/components/Layout'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'PostThread'>
export function PostThreadScreen({route}: Props) {
const setMinimalShellMode = useSetMinimalShellMode()
const {name, rkey} = route.params
const uri = makeRecordUri(name, 'app.bsky.feed.post', rkey)
useFocusEffect(
useCallback(() => {
setMinimalShellMode(false)
}, [setMinimalShellMode]),
)
return (
<Layout.Screen testID="postThreadScreen">
<PostThread uri={uri} />
-10
View File
@@ -1,9 +1,7 @@
import {useCallback} from 'react'
import {View} from 'react-native'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {Trans} from '@lingui/react/macro'
import {useFocusEffect} from '@react-navigation/native'
import {usePalette} from '#/lib/hooks/usePalette'
import {
@@ -11,7 +9,6 @@ import {
type NativeStackScreenProps,
} from '#/lib/routes/types'
import {s} from '#/lib/styles'
import {useSetMinimalShellMode} from '#/state/shell'
import {TextLink} from '#/view/com/util/Link'
import {Text} from '#/view/com/util/text/Text'
import {ScrollView} from '#/view/com/util/Views'
@@ -22,13 +19,6 @@ type Props = NativeStackScreenProps<CommonNavigatorParams, 'PrivacyPolicy'>
export const PrivacyPolicyScreen = (_props: Props) => {
const pal = usePalette('default')
const {_} = useLingui()
const setMinimalShellMode = useSetMinimalShellMode()
useFocusEffect(
useCallback(() => {
setMinimalShellMode(false)
}, [setMinimalShellMode]),
)
return (
<Layout.Screen>
+1 -4
View File
@@ -34,7 +34,6 @@ import {resetProfilePostsQueries} from '#/state/queries/post-feed'
import {useProfileQuery} from '#/state/queries/profile'
import {useResolveDidQuery} from '#/state/queries/resolve-uri'
import {useAgent, useSession} from '#/state/session'
import {useSetMinimalShellMode} from '#/state/shell'
import {ProfileFeedgens} from '#/view/com/feeds/ProfileFeedgens'
import {ProfileLists} from '#/view/com/lists/ProfileLists'
import {PagerWithHeader} from '#/view/com/pager/PagerWithHeader'
@@ -175,7 +174,6 @@ function ProfileScreenLoaded({
}) {
const profile = useProfileShadow(profileUnshadowed)
const {hasSession, currentAccount} = useSession()
const setMinimalShellMode = useSetMinimalShellMode()
const {openComposer} = useOpenComposer()
const navigation = useNavigation<NavigationProp>()
const requireEmailVerification = useRequireEmailVerification()
@@ -317,11 +315,10 @@ function ProfileScreenLoaded({
useFocusEffect(
useCallback(() => {
setMinimalShellMode(false)
return listenSoftReset(() => {
scrollSectionToTop(currentPage)
})
}, [setMinimalShellMode, currentPage, scrollSectionToTop]),
}, [currentPage, scrollSectionToTop]),
)
// events
-10
View File
@@ -1,28 +1,18 @@
import {useCallback} from 'react'
import {Trans} from '@lingui/react/macro'
import {useFocusEffect} from '@react-navigation/native'
import {
type CommonNavigatorParams,
type NativeStackScreenProps,
} from '#/lib/routes/types'
import {makeRecordUri} from '#/lib/strings/url-helpers'
import {useSetMinimalShellMode} from '#/state/shell'
import {PostLikedBy as PostLikedByComponent} from '#/view/com/post-thread/PostLikedBy'
import * as Layout from '#/components/Layout'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'ProfileFeedLikedBy'>
export const ProfileFeedLikedByScreen = ({route}: Props) => {
const setMinimalShellMode = useSetMinimalShellMode()
const {name, rkey} = route.params
const uri = makeRecordUri(name, 'app.bsky.feed.generator', rkey)
useFocusEffect(
useCallback(() => {
setMinimalShellMode(false)
}, [setMinimalShellMode]),
)
return (
<Layout.Screen testID="postLikedByScreen">
<Layout.Header.Outer>
-10
View File
@@ -1,8 +1,6 @@
import {useCallback} from 'react'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {Trans} from '@lingui/react/macro'
import {useFocusEffect} from '@react-navigation/native'
import {HELP_DESK_URL} from '#/lib/constants'
import {usePalette} from '#/lib/hooks/usePalette'
@@ -11,7 +9,6 @@ import {
type NativeStackScreenProps,
} from '#/lib/routes/types'
import {s} from '#/lib/styles'
import {useSetMinimalShellMode} from '#/state/shell'
import {TextLink} from '#/view/com/util/Link'
import {Text} from '#/view/com/util/text/Text'
import {ViewHeader} from '#/view/com/util/ViewHeader'
@@ -21,15 +18,8 @@ import * as Layout from '#/components/Layout'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'Support'>
export const SupportScreen = (_props: Props) => {
const pal = usePalette('default')
const setMinimalShellMode = useSetMinimalShellMode()
const {_} = useLingui()
useFocusEffect(
useCallback(() => {
setMinimalShellMode(false)
}, [setMinimalShellMode]),
)
return (
<Layout.Screen>
<ViewHeader title={_(msg`Support`)} />
-10
View File
@@ -1,9 +1,7 @@
import {useCallback} from 'react'
import {View} from 'react-native'
import {msg} from '@lingui/core/macro'
import {useLingui} from '@lingui/react'
import {Trans} from '@lingui/react/macro'
import {useFocusEffect} from '@react-navigation/native'
import {usePalette} from '#/lib/hooks/usePalette'
import {
@@ -11,7 +9,6 @@ import {
type NativeStackScreenProps,
} from '#/lib/routes/types'
import {s} from '#/lib/styles'
import {useSetMinimalShellMode} from '#/state/shell'
import {TextLink} from '#/view/com/util/Link'
import {Text} from '#/view/com/util/text/Text'
import {ScrollView} from '#/view/com/util/Views'
@@ -21,15 +18,8 @@ import {ViewHeader} from '../com/util/ViewHeader'
type Props = NativeStackScreenProps<CommonNavigatorParams, 'TermsOfService'>
export const TermsOfServiceScreen = (_props: Props) => {
const pal = usePalette('default')
const setMinimalShellMode = useSetMinimalShellMode()
const {_} = useLingui()
useFocusEffect(
useCallback(() => {
setMinimalShellMode(false)
}, [setMinimalShellMode]),
)
return (
<Layout.Screen>
<ViewHeader title={_(msg`Terms of Service`)} />