wip fancy banner

This commit is contained in:
Samuel Newman
2024-12-11 23:56:58 +00:00
parent 3e384f6314
commit 83233c2225
4 changed files with 49 additions and 17 deletions
+33 -11
View File
@@ -2,6 +2,7 @@ import React, {useEffect, useState} from 'react'
import {View} from 'react-native' import {View} from 'react-native'
import {ActivityIndicator} from 'react-native' import {ActivityIndicator} from 'react-native'
import Animated, { import Animated, {
clamp,
Extrapolation, Extrapolation,
interpolate, interpolate,
runOnJS, runOnJS,
@@ -14,7 +15,7 @@ import {useSafeAreaInsets} from 'react-native-safe-area-context'
import {BlurView} from 'expo-blur' import {BlurView} from 'expo-blur'
import {useIsFetching} from '@tanstack/react-query' import {useIsFetching} from '@tanstack/react-query'
import {isIOS} from '#/platform/detection' import {isIOS, isWeb} from '#/platform/detection'
import {RQKEY_ROOT as STARTERPACK_RQKEY_ROOT} from '#/state/queries/actor-starter-packs' import {RQKEY_ROOT as STARTERPACK_RQKEY_ROOT} from '#/state/queries/actor-starter-packs'
import {RQKEY_ROOT as FEED_RQKEY_ROOT} from '#/state/queries/post-feed' import {RQKEY_ROOT as FEED_RQKEY_ROOT} from '#/state/queries/post-feed'
import {RQKEY_ROOT as FEEDGEN_RQKEY_ROOT} from '#/state/queries/profile-feedgens' import {RQKEY_ROOT as FEEDGEN_RQKEY_ROOT} from '#/state/queries/profile-feedgens'
@@ -33,8 +34,8 @@ export function GrowableBanner({
}) { }) {
const pagerContext = usePagerHeaderContext() const pagerContext = usePagerHeaderContext()
// plain non-growable mode for Android/Web // plain non-growable mode for Web
if (!pagerContext || !isIOS) { if (!pagerContext || isWeb) {
return ( return (
<View style={[a.w_full, a.h_full]}> <View style={[a.w_full, a.h_full]}>
{children} {children}
@@ -43,20 +44,28 @@ export function GrowableBanner({
) )
} }
const {scrollY} = pagerContext const {scrollY, headerHeight, minimumHeaderHeight} = pagerContext
return ( return (
<GrowableBannerInner scrollY={scrollY} backButton={backButton}> <GrowableBannerInner
scrollY={scrollY}
backButton={backButton}
headerHeight={headerHeight}
minimumHeaderHeight={minimumHeaderHeight}>
{children} {children}
</GrowableBannerInner> </GrowableBannerInner>
) )
} }
function GrowableBannerInner({ function GrowableBannerInner({
headerHeight,
minimumHeaderHeight,
scrollY, scrollY,
backButton, backButton,
children, children,
}: { }: {
headerHeight: number
minimumHeaderHeight: number
scrollY: SharedValue<number> scrollY: SharedValue<number>
backButton?: React.ReactNode backButton?: React.ReactNode
children: React.ReactNode children: React.ReactNode
@@ -68,20 +77,33 @@ function GrowableBannerInner({
const animatedStyle = useAnimatedStyle(() => ({ const animatedStyle = useAnimatedStyle(() => ({
transform: [ transform: [
{ {
scale: interpolate(scrollY.get(), [-150, 0], [2, 1], { scale: interpolate(
extrapolateRight: Extrapolation.CLAMP, scrollY.get(),
}), [-150, 0],
[2, 1],
Extrapolation.CLAMP,
),
},
{
translateY: clamp(scrollY.get() - minimumHeaderHeight, 0, headerHeight),
}, },
], ],
})) }))
const animatedBlurViewProps = useAnimatedProps(() => { const animatedBlurViewProps = useAnimatedProps(() => {
console.log(
'scrollY',
scrollY.get(),
'headerHeight',
headerHeight,
topInset,
)
return { return {
intensity: interpolate( intensity: interpolate(
scrollY.get(), scrollY.get(),
[-300, -65, -15], [-300, -65, -15, minimumHeaderHeight - 10, minimumHeaderHeight],
[50, 40, 0], [50, 40, 0, 0, 50],
Extrapolation.CLAMP, {extrapolateLeft: Extrapolation.CLAMP},
), ),
} }
}) })
-2
View File
@@ -97,7 +97,6 @@ const MinimalHeader = React.memo(function MinimalHeader({
profile: AppBskyActorDefs.ProfileViewDetailed profile: AppBskyActorDefs.ProfileViewDetailed
hideBackButton?: boolean hideBackButton?: boolean
}) { }) {
const t = useTheme()
const insets = useSafeAreaInsets() const insets = useSafeAreaInsets()
const ctx = usePagerHeaderContext() const ctx = usePagerHeaderContext()
const [visible, setVisible] = useState(false) const [visible, setVisible] = useState(false)
@@ -153,7 +152,6 @@ const MinimalHeader = React.memo(function MinimalHeader({
style={[ style={[
a.absolute, a.absolute,
a.z_50, a.z_50,
t.atoms.bg,
{ {
top: 0, top: 0,
left: 0, left: 0,
+5 -2
View File
@@ -6,6 +6,7 @@ import {isNative} from '#/platform/detection'
export const PagerHeaderContext = React.createContext<{ export const PagerHeaderContext = React.createContext<{
scrollY: SharedValue<number> scrollY: SharedValue<number>
headerHeight: number headerHeight: number
minimumHeaderHeight: number
} | null>(null) } | null>(null)
/** /**
@@ -17,15 +18,17 @@ export const PagerHeaderContext = React.createContext<{
export function PagerHeaderProvider({ export function PagerHeaderProvider({
scrollY, scrollY,
headerHeight, headerHeight,
minimumHeaderHeight,
children, children,
}: { }: {
scrollY: SharedValue<number> scrollY: SharedValue<number>
headerHeight: number headerHeight: number
minimumHeaderHeight: number
children: React.ReactNode children: React.ReactNode
}) { }) {
const value = React.useMemo( const value = React.useMemo(
() => ({scrollY, headerHeight}), () => ({scrollY, headerHeight, minimumHeaderHeight}),
[scrollY, headerHeight], [scrollY, headerHeight, minimumHeaderHeight],
) )
return ( return (
<PagerHeaderContext.Provider value={value}> <PagerHeaderContext.Provider value={value}>
+11 -2
View File
@@ -66,6 +66,7 @@ export const PagerWithHeader = React.forwardRef<PagerRef, PagerWithHeaderProps>(
const [currentPage, setCurrentPage] = React.useState(0) const [currentPage, setCurrentPage] = React.useState(0)
const [tabBarHeight, setTabBarHeight] = React.useState(0) const [tabBarHeight, setTabBarHeight] = React.useState(0)
const [headerOnlyHeight, setHeaderOnlyHeight] = React.useState(0) const [headerOnlyHeight, setHeaderOnlyHeight] = React.useState(0)
const [minimumHeaderHeight, setMinimumHeaderHeight] = React.useState(0)
const scrollY = useSharedValue(0) const scrollY = useSharedValue(0)
const headerHeight = headerOnlyHeight + tabBarHeight const headerHeight = headerOnlyHeight + tabBarHeight
@@ -89,7 +90,8 @@ export const PagerWithHeader = React.forwardRef<PagerRef, PagerWithHeaderProps>(
return ( return (
<PagerHeaderProvider <PagerHeaderProvider
scrollY={scrollY} scrollY={scrollY}
headerHeight={headerOnlyHeight}> headerHeight={headerOnlyHeight}
minimumHeaderHeight={minimumHeaderHeight}>
<PagerTabBar <PagerTabBar
headerOnlyHeight={headerOnlyHeight} headerOnlyHeight={headerOnlyHeight}
items={items} items={items}
@@ -105,6 +107,8 @@ export const PagerWithHeader = React.forwardRef<PagerRef, PagerWithHeaderProps>(
allowHeaderOverScroll={allowHeaderOverScroll} allowHeaderOverScroll={allowHeaderOverScroll}
dragProgress={props.dragProgress} dragProgress={props.dragProgress}
dragState={props.dragState} dragState={props.dragState}
minimumHeaderHeight={minimumHeaderHeight}
setMinimumHeaderHeight={setMinimumHeaderHeight}
/> />
</PagerHeaderProvider> </PagerHeaderProvider>
) )
@@ -121,6 +125,8 @@ export const PagerWithHeader = React.forwardRef<PagerRef, PagerWithHeaderProps>(
scrollY, scrollY,
testID, testID,
allowHeaderOverScroll, allowHeaderOverScroll,
minimumHeaderHeight,
setMinimumHeaderHeight,
], ],
) )
@@ -236,6 +242,8 @@ let PagerTabBar = ({
allowHeaderOverScroll, allowHeaderOverScroll,
dragProgress, dragProgress,
dragState, dragState,
minimumHeaderHeight,
setMinimumHeaderHeight,
}: { }: {
currentPage: number currentPage: number
headerOnlyHeight: number headerOnlyHeight: number
@@ -255,8 +263,9 @@ let PagerTabBar = ({
allowHeaderOverScroll?: boolean allowHeaderOverScroll?: boolean
dragProgress: SharedValue<number> dragProgress: SharedValue<number>
dragState: SharedValue<'idle' | 'dragging' | 'settling'> dragState: SharedValue<'idle' | 'dragging' | 'settling'>
minimumHeaderHeight: number
setMinimumHeaderHeight: (height: number) => void
}): React.ReactNode => { }): React.ReactNode => {
const [minimumHeaderHeight, setMinimumHeaderHeight] = React.useState(0)
const headerTransform = useAnimatedStyle(() => { const headerTransform = useAnimatedStyle(() => {
const translateY = const translateY =
Math.min( Math.min(