Skip to content

Commit

Permalink
fix(mobile): player tab animation (#2918)
Browse files Browse the repository at this point in the history
  • Loading branch information
hyoban authored Feb 28, 2025
1 parent 84b44b3 commit 7fbd2d7
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 31 deletions.
4 changes: 2 additions & 2 deletions apps/mobile/src/components/layouts/tabbar/Tabbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 }],
Expand All @@ -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]!
Expand Down
69 changes: 40 additions & 29 deletions apps/mobile/src/modules/player/PlayerTabBar.tsx
Original file line number Diff line number Diff line change
@@ -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"
Expand All @@ -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>
<View className="mr-2 flex flex-row gap-4">
<PlayPauseButton />
<SeekButton />
</View>
</Pressable>
</Animated.View>
</View>
</View>
</Pressable>
</Animated.View>
)
}

0 comments on commit 7fbd2d7

Please sign in to comment.