fix(mobile): player tab animation (#2918)
This commit is contained in:
parent
84b44b3062
commit
7fbd2d7208
|
|
@ -44,7 +44,7 @@ export const Tabbar: FC<BottomTabBarProps> = (props) => {
|
|||
return (
|
||||
<Animated.View
|
||||
accessibilityRole="tablist"
|
||||
className="absolute inset-x-0 bottom-0 z-10 py-[7]"
|
||||
className="absolute inset-x-0 bottom-0 z-10"
|
||||
style={{
|
||||
paddingBottom: insets.bottom,
|
||||
transform: [{ translateY }],
|
||||
|
|
@ -55,7 +55,7 @@ export const Tabbar: FC<BottomTabBarProps> = (props) => {
|
|||
>
|
||||
<TabBarBackground />
|
||||
<PlayerTabBar />
|
||||
<Grid columns={routes.length} gap={10}>
|
||||
<Grid columns={routes.length} gap={10} className="mt-[7]">
|
||||
{routes.map((route, index) => {
|
||||
const focused = index === state.index
|
||||
const { options } = descriptors[route.key]!
|
||||
|
|
|
|||
|
|
@ -1,8 +1,14 @@
|
|||
import { cn } from "@follow/utils"
|
||||
import { Image } from "expo-image"
|
||||
import { router, usePathname } from "expo-router"
|
||||
import { useEffect } from "react"
|
||||
import { Pressable, Text, View } from "react-native"
|
||||
import Animated, { SlideInDown, SlideOutDown } from "react-native-reanimated"
|
||||
import Animated, {
|
||||
interpolate,
|
||||
useAnimatedStyle,
|
||||
useSharedValue,
|
||||
withTiming,
|
||||
} from "react-native-reanimated"
|
||||
|
||||
import { useActiveTrack } from "@/src/lib/player"
|
||||
import { usePrefetchImageColors } from "@/src/store/image/hooks"
|
||||
|
|
@ -14,39 +20,44 @@ const allowedRoutes = new Set(["/", "/subscriptions", "/player"])
|
|||
export function PlayerTabBar({ className }: { className?: string }) {
|
||||
const activeTrack = useActiveTrack()
|
||||
const pathname = usePathname()
|
||||
const isVisible = !!activeTrack && allowedRoutes.has(pathname)
|
||||
const isVisibleSV = useSharedValue(isVisible ? 1 : 0)
|
||||
useEffect(() => {
|
||||
isVisibleSV.value = withTiming(isVisible ? 1 : 0)
|
||||
}, [pathname, isVisible])
|
||||
const animatedStyle = useAnimatedStyle(() => {
|
||||
return {
|
||||
opacity: isVisibleSV.value,
|
||||
height: interpolate(isVisibleSV.value, [0, 1], [0, 56]),
|
||||
overflow: "hidden",
|
||||
}
|
||||
})
|
||||
|
||||
usePrefetchImageColors(activeTrack?.artwork)
|
||||
|
||||
if (!activeTrack || !allowedRoutes.has(pathname)) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<View className="mb-2 overflow-hidden">
|
||||
<Animated.View
|
||||
entering={SlideInDown}
|
||||
exiting={SlideOutDown}
|
||||
className={cn("border-opaque-separator/70 border-b px-2", className)}
|
||||
<Animated.View
|
||||
style={animatedStyle}
|
||||
className={cn("border-opaque-separator/70 border-b px-2", className)}
|
||||
>
|
||||
<Pressable
|
||||
onPress={() => {
|
||||
router.push("/player")
|
||||
}}
|
||||
>
|
||||
<Pressable
|
||||
onPress={() => {
|
||||
router.push("/player")
|
||||
}}
|
||||
>
|
||||
<View className="flex flex-row items-center gap-4 overflow-hidden rounded-2xl p-2">
|
||||
<Image source={activeTrack.artwork} className="size-12 rounded-lg" />
|
||||
<View className="flex-1 overflow-hidden">
|
||||
<Text className="text-label text-lg font-semibold" numberOfLines={1}>
|
||||
{activeTrack.title}
|
||||
</Text>
|
||||
</View>
|
||||
<View className="mr-2 flex flex-row gap-4">
|
||||
<PlayPauseButton />
|
||||
<SeekButton />
|
||||
</View>
|
||||
<View className="flex flex-row items-center gap-4 overflow-hidden rounded-2xl p-2">
|
||||
<Image source={activeTrack?.artwork} className="size-12 rounded-lg" />
|
||||
<View className="flex-1 overflow-hidden">
|
||||
<Text className="text-label text-lg font-semibold" numberOfLines={1}>
|
||||
{activeTrack?.title ?? ""}
|
||||
</Text>
|
||||
</View>
|
||||
</Pressable>
|
||||
</Animated.View>
|
||||
</View>
|
||||
<View className="mr-2 flex flex-row gap-4">
|
||||
<PlayPauseButton />
|
||||
<SeekButton />
|
||||
</View>
|
||||
</View>
|
||||
</Pressable>
|
||||
</Animated.View>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue