Fix (#4430): Use separate hooks for shell mode animated styles (#4451)

* Fix (#4430): Use separate hooks for shell mode animated styles

* Consolidate in one file

---------

Co-authored-by: Dan Abramov <dan.abramov@gmail.com>
This commit is contained in:
Francesco Lodovici 2024-06-10 17:19:28 +02:00 committed by GitHub
parent fd03ea3fe1
commit b688da8d58
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 51 additions and 38 deletions

View file

@ -1,23 +1,15 @@
import {interpolate, useAnimatedStyle} from 'react-native-reanimated' import {interpolate, useAnimatedStyle} from 'react-native-reanimated'
import {useMinimalShellMode as useMinimalShellModeState} from '#/state/shell/minimal-mode'
import {useMinimalShellMode} from '#/state/shell/minimal-mode'
import {useShellLayout} from '#/state/shell/shell-layout' import {useShellLayout} from '#/state/shell/shell-layout'
export function useMinimalShellMode() { // Keep these separated so that we only pay for useAnimatedStyle that gets used.
const mode = useMinimalShellModeState()
const {footerHeight, headerHeight} = useShellLayout()
const footerMinimalShellTransform = useAnimatedStyle(() => { export function useMinimalShellHeaderTransform() {
return { const mode = useMinimalShellMode()
pointerEvents: mode.value === 0 ? 'auto' : 'none', const {headerHeight} = useShellLayout()
opacity: Math.pow(1 - mode.value, 2),
transform: [ const headerTransform = useAnimatedStyle(() => {
{
translateY: interpolate(mode.value, [0, 1], [0, footerHeight.value]),
},
],
}
})
const headerMinimalShellTransform = useAnimatedStyle(() => {
return { return {
pointerEvents: mode.value === 0 ? 'auto' : 'none', pointerEvents: mode.value === 0 ? 'auto' : 'none',
opacity: Math.pow(1 - mode.value, 2), opacity: Math.pow(1 - mode.value, 2),
@ -28,7 +20,32 @@ export function useMinimalShellMode() {
], ],
} }
}) })
const fabMinimalShellTransform = useAnimatedStyle(() => {
return headerTransform
}
export function useMinimalShellFooterTransform() {
const mode = useMinimalShellMode()
const {footerHeight} = useShellLayout()
const footerTransform = useAnimatedStyle(() => {
return {
pointerEvents: mode.value === 0 ? 'auto' : 'none',
opacity: Math.pow(1 - mode.value, 2),
transform: [
{
translateY: interpolate(mode.value, [0, 1], [0, footerHeight.value]),
},
],
}
})
return footerTransform
}
export function useMinimalShellFabTransform() {
const mode = useMinimalShellMode()
const fabTransform = useAnimatedStyle(() => {
return { return {
transform: [ transform: [
{ {
@ -37,9 +54,5 @@ export function useMinimalShellMode() {
], ],
} }
}) })
return { return fabTransform
footerMinimalShellTransform,
headerMinimalShellTransform,
fabMinimalShellTransform,
}
} }

View file

@ -11,7 +11,7 @@ import {useLingui} from '@lingui/react'
import {CogIcon} from '#/lib/icons' import {CogIcon} from '#/lib/icons'
import {useSession} from '#/state/session' import {useSession} from '#/state/session'
import {useShellLayout} from '#/state/shell/shell-layout' import {useShellLayout} from '#/state/shell/shell-layout'
import {useMinimalShellMode} from 'lib/hooks/useMinimalShellMode' import {useMinimalShellHeaderTransform} from 'lib/hooks/useMinimalShellTransform'
import {usePalette} from 'lib/hooks/usePalette' import {usePalette} from 'lib/hooks/usePalette'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {Logo} from '#/view/icons/Logo' import {Logo} from '#/view/icons/Logo'
@ -39,7 +39,7 @@ function HomeHeaderLayoutDesktopAndTablet({
tabBarAnchor: JSX.Element | null | undefined tabBarAnchor: JSX.Element | null | undefined
}) { }) {
const pal = usePalette('default') const pal = usePalette('default')
const {headerMinimalShellTransform} = useMinimalShellMode() const headerMinimalShellTransform = useMinimalShellHeaderTransform()
const {headerHeight} = useShellLayout() const {headerHeight} = useShellLayout()
const {hasSession} = useSession() const {hasSession} = useSession()
const {_} = useLingui() const {_} = useLingui()

View file

@ -10,7 +10,7 @@ import {useSession} from '#/state/session'
import {useSetDrawerOpen} from '#/state/shell/drawer-open' import {useSetDrawerOpen} from '#/state/shell/drawer-open'
import {useShellLayout} from '#/state/shell/shell-layout' import {useShellLayout} from '#/state/shell/shell-layout'
import {HITSLOP_10} from 'lib/constants' import {HITSLOP_10} from 'lib/constants'
import {useMinimalShellMode} from 'lib/hooks/useMinimalShellMode' import {useMinimalShellHeaderTransform} from 'lib/hooks/useMinimalShellTransform'
import {usePalette} from 'lib/hooks/usePalette' import {usePalette} from 'lib/hooks/usePalette'
import {isWeb} from 'platform/detection' import {isWeb} from 'platform/detection'
import {Logo} from '#/view/icons/Logo' import {Logo} from '#/view/icons/Logo'
@ -30,7 +30,7 @@ export function HomeHeaderLayoutMobile({
const {_} = useLingui() const {_} = useLingui()
const setDrawerOpen = useSetDrawerOpen() const setDrawerOpen = useSetDrawerOpen()
const {headerHeight} = useShellLayout() const {headerHeight} = useShellLayout()
const {headerMinimalShellTransform} = useMinimalShellMode() const headerMinimalShellTransform = useMinimalShellHeaderTransform()
const {hasSession} = useSession() const {hasSession} = useSession()
const onPressAvi = React.useCallback(() => { const onPressAvi = React.useCallback(() => {

View file

@ -8,7 +8,7 @@ import {useNavigation} from '@react-navigation/native'
import {useSetDrawerOpen} from '#/state/shell' import {useSetDrawerOpen} from '#/state/shell'
import {useAnalytics} from 'lib/analytics/analytics' import {useAnalytics} from 'lib/analytics/analytics'
import {useMinimalShellMode} from 'lib/hooks/useMinimalShellMode' import {useMinimalShellHeaderTransform} from 'lib/hooks/useMinimalShellTransform'
import {usePalette} from 'lib/hooks/usePalette' import {usePalette} from 'lib/hooks/usePalette'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {NavigationProp} from 'lib/routes/types' import {NavigationProp} from 'lib/routes/types'
@ -197,7 +197,7 @@ function Container({
showBorder?: boolean showBorder?: boolean
}) { }) {
const pal = usePalette('default') const pal = usePalette('default')
const {headerMinimalShellTransform} = useMinimalShellMode() const headerMinimalShellTransform = useMinimalShellHeaderTransform()
if (!hideOnScroll) { if (!hideOnScroll) {
return ( return (

View file

@ -4,7 +4,7 @@ import Animated, {useAnimatedStyle, withTiming} from 'react-native-reanimated'
import {useSafeAreaInsets} from 'react-native-safe-area-context' import {useSafeAreaInsets} from 'react-native-safe-area-context'
import {LinearGradient} from 'expo-linear-gradient' import {LinearGradient} from 'expo-linear-gradient'
import {useMinimalShellMode} from '#/lib/hooks/useMinimalShellMode' import {useMinimalShellFabTransform} from '#/lib/hooks/useMinimalShellTransform'
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
import {clamp} from '#/lib/numbers' import {clamp} from '#/lib/numbers'
import {gradients} from '#/lib/styles' import {gradients} from '#/lib/styles'
@ -20,7 +20,7 @@ export interface FABProps
export function FABInner({testID, icon, ...props}: FABProps) { export function FABInner({testID, icon, ...props}: FABProps) {
const insets = useSafeAreaInsets() const insets = useSafeAreaInsets()
const {isMobile, isTablet} = useWebMediaQueries() const {isMobile, isTablet} = useWebMediaQueries()
const {fabMinimalShellTransform} = useMinimalShellMode() const fabMinimalShellTransform = useMinimalShellFabTransform()
const { const {
state: pressed, state: pressed,
onIn: onPressIn, onIn: onPressIn,

View file

@ -6,7 +6,7 @@ import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {useMediaQuery} from 'react-responsive' import {useMediaQuery} from 'react-responsive'
import {HITSLOP_20} from '#/lib/constants' import {HITSLOP_20} from '#/lib/constants'
import {useMinimalShellMode} from '#/lib/hooks/useMinimalShellMode' import {useMinimalShellFabTransform} from '#/lib/hooks/useMinimalShellTransform'
import {usePalette} from '#/lib/hooks/usePalette' import {usePalette} from '#/lib/hooks/usePalette'
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
import {clamp} from '#/lib/numbers' import {clamp} from '#/lib/numbers'
@ -30,7 +30,7 @@ export function LoadLatestBtn({
const pal = usePalette('default') const pal = usePalette('default')
const {hasSession} = useSession() const {hasSession} = useSession()
const {isDesktop, isTablet, isMobile, isTabletOrMobile} = useWebMediaQueries() const {isDesktop, isTablet, isMobile, isTabletOrMobile} = useWebMediaQueries()
const {fabMinimalShellTransform} = useMinimalShellMode() const fabMinimalShellTransform = useMinimalShellFabTransform()
const insets = useSafeAreaInsets() const insets = useSafeAreaInsets()
// move button inline if it starts overlapping the left nav // move button inline if it starts overlapping the left nav

View file

@ -14,7 +14,7 @@ import {
import {useSession} from '#/state/session' import {useSession} from '#/state/session'
import {useSetMinimalShellMode} from '#/state/shell' import {useSetMinimalShellMode} from '#/state/shell'
import {useComposerControls} from '#/state/shell/composer' import {useComposerControls} from '#/state/shell/composer'
import {useMinimalShellMode} from 'lib/hooks/useMinimalShellMode' import {useMinimalShellFabTransform} from 'lib/hooks/useMinimalShellTransform'
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
import {CommonNavigatorParams, NativeStackScreenProps} from 'lib/routes/types' import {CommonNavigatorParams, NativeStackScreenProps} from 'lib/routes/types'
import {makeRecordUri} from 'lib/strings/url-helpers' import {makeRecordUri} from 'lib/strings/url-helpers'
@ -26,7 +26,7 @@ type Props = NativeStackScreenProps<CommonNavigatorParams, 'PostThread'>
export function PostThreadScreen({route}: Props) { export function PostThreadScreen({route}: Props) {
const queryClient = useQueryClient() const queryClient = useQueryClient()
const {hasSession} = useSession() const {hasSession} = useSession()
const {fabMinimalShellTransform} = useMinimalShellMode() const fabMinimalShellTransform = useMinimalShellFabTransform()
const setMinimalShellMode = useSetMinimalShellMode() const setMinimalShellMode = useSetMinimalShellMode()
const {openComposer} = useComposerControls() const {openComposer} = useComposerControls()
const safeAreaInsets = useSafeAreaInsets() const safeAreaInsets = useSafeAreaInsets()

View file

@ -10,7 +10,7 @@ import {StackActions} from '@react-navigation/native'
import {useAnalytics} from '#/lib/analytics/analytics' import {useAnalytics} from '#/lib/analytics/analytics'
import {useHaptics} from '#/lib/haptics' import {useHaptics} from '#/lib/haptics'
import {useDedupe} from '#/lib/hooks/useDedupe' import {useDedupe} from '#/lib/hooks/useDedupe'
import {useMinimalShellMode} from '#/lib/hooks/useMinimalShellMode' import {useMinimalShellFooterTransform} from '#/lib/hooks/useMinimalShellTransform'
import {useNavigationTabState} from '#/lib/hooks/useNavigationTabState' import {useNavigationTabState} from '#/lib/hooks/useNavigationTabState'
import {usePalette} from '#/lib/hooks/usePalette' import {usePalette} from '#/lib/hooks/usePalette'
import {clamp} from '#/lib/numbers' import {clamp} from '#/lib/numbers'
@ -66,7 +66,7 @@ export function BottomBar({navigation}: BottomTabBarProps) {
useNavigationTabState() useNavigationTabState()
const numUnreadNotifications = useUnreadNotifications() const numUnreadNotifications = useUnreadNotifications()
const numUnreadMessages = useUnreadMessageCount() const numUnreadMessages = useUnreadMessageCount()
const {footerMinimalShellTransform} = useMinimalShellMode() const footerMinimalShellTransform = useMinimalShellFooterTransform()
const {data: profile} = useProfileQuery({did: currentAccount?.did}) const {data: profile} = useProfileQuery({did: currentAccount?.did})
const {requestSwitchToAccount} = useLoggedOutViewControls() const {requestSwitchToAccount} = useLoggedOutViewControls()
const closeAllActiveElements = useCloseAllActiveElements() const closeAllActiveElements = useCloseAllActiveElements()

View file

@ -6,7 +6,7 @@ import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {useNavigationState} from '@react-navigation/native' import {useNavigationState} from '@react-navigation/native'
import {useMinimalShellMode} from '#/lib/hooks/useMinimalShellMode' import {useMinimalShellFooterTransform} from '#/lib/hooks/useMinimalShellTransform'
import {usePalette} from '#/lib/hooks/usePalette' import {usePalette} from '#/lib/hooks/usePalette'
import {clamp} from '#/lib/numbers' import {clamp} from '#/lib/numbers'
import {getCurrentRoute, isTab} from '#/lib/routes/helpers' import {getCurrentRoute, isTab} from '#/lib/routes/helpers'
@ -50,7 +50,7 @@ export function BottomBarWeb() {
const pal = usePalette('default') const pal = usePalette('default')
const safeAreaInsets = useSafeAreaInsets() const safeAreaInsets = useSafeAreaInsets()
const gate = useGate() const gate = useGate()
const {footerMinimalShellTransform} = useMinimalShellMode() const footerMinimalShellTransform = useMinimalShellFooterTransform()
const {requestSwitchToAccount} = useLoggedOutViewControls() const {requestSwitchToAccount} = useLoggedOutViewControls()
const closeAllActiveElements = useCloseAllActiveElements() const closeAllActiveElements = useCloseAllActiveElements()
const iconWidth = 26 const iconWidth = 26