Fix stuck bottom bar on Home and use the Reanimated 4 spring curve

The header and bottom bar were being handed the same `withSpring()` animation
object. Animation objects carry their own state, so the second shared value
to receive it could stop partway, leaving the bar stuck half hidden after a
slow scroll on Home. Each shared value now gets its own animation.

Shell show/hide springs now share one config based on Reanimated 4's default
critically damped curve, with the perceptual duration shortened from 550ms to
400ms.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JWQciPDiipBhqiW922Nivs
This commit is contained in:
Claude
2026-09-07 20:50:38 +00:00
parent 2dc7071e7d
commit 6671bd9f42
7 changed files with 38 additions and 51 deletions
+4 -7
View File
@@ -3,7 +3,6 @@ import {type NativeScrollEvent} from 'react-native'
import {
clamp,
interpolate,
Reanimated3DefaultSpringConfig,
type SharedValue,
useAnimatedStyle,
useSharedValue,
@@ -12,6 +11,7 @@ import {
import {useSafeAreaInsets} from 'react-native-safe-area-context'
import {EventEmitter} from 'eventemitter3'
import {SHELL_SPRING_CONFIG} from '#/lib/custom-animations/springs'
import {ScrollProvider} from '#/lib/ScrollContext'
import {useMinimalShellScrollMode} from '#/state/shell/minimal-mode'
import {useShellLayout} from '#/state/shell/shell-layout'
@@ -106,12 +106,9 @@ export function MainScrollProvider({children}: {children: React.ReactNode}) {
const setMode = useCallback(
(v: boolean) => {
'worklet'
const target = withSpring(v ? 1 : 0, {
...Reanimated3DefaultSpringConfig,
overshootClamping: true,
})
headerMode.set(target)
footerScrollMode.set(target)
// animation objects are stateful, so each shared value needs its own
headerMode.set(withSpring(v ? 1 : 0, SHELL_SPRING_CONFIG))
footerScrollMode.set(withSpring(v ? 1 : 0, SHELL_SPRING_CONFIG))
},
[headerMode, footerScrollMode],
)