diff --git a/src/components/Album/index.tsx b/src/components/Album/index.tsx index 1150a6c2..0b2cd529 100644 --- a/src/components/Album/index.tsx +++ b/src/components/Album/index.tsx @@ -170,7 +170,15 @@ function AlbumTrackListHeader({ album }: { album: BaseItemDto }): React.JSX.Elem return ( - +
diff --git a/src/components/Player/index.tsx b/src/components/Player/index.tsx index 51559343..e692d331 100644 --- a/src/components/Player/index.tsx +++ b/src/components/Player/index.tsx @@ -1,11 +1,8 @@ -import React, { useCallback, useMemo, useState } from 'react' +import React from 'react' import { useSafeAreaInsets } from 'react-native-safe-area-context' -import { YStack, useTheme, ZStack, useWindowDimensions, View, getTokenValue } from 'tamagui' +import { YStack, ZStack, useWindowDimensions, View, getTokenValue } from 'tamagui' import Scrubber from './components/scrubber' import Controls from './components/controls' -import Toast from 'react-native-toast-message' -import JellifyToastConfig from '../../configs/toast.config' -import { useFocusEffect } from '@react-navigation/native' import Footer from './components/footer' import BlurredBackground from './components/blurred-background' import PlayerHeader from './components/header' @@ -29,22 +26,11 @@ import { useCurrentTrack } from '../../stores/player/queue' export default function PlayerScreen(): React.JSX.Element { usePerformanceMonitor('PlayerScreen', 5) - const [showToast, setShowToast] = useState(true) - const skip = useSkip() const previous = usePrevious() const trigger = useHapticFeedback() const nowPlaying = useCurrentTrack() - const theme = useTheme() - - useFocusEffect( - useCallback(() => { - setShowToast(true) - return () => setShowToast(false) - }, []), - ) - const isAndroid = Platform.OS === 'android' const { width, height } = useWindowDimensions() @@ -63,49 +49,43 @@ export default function PlayerScreen(): React.JSX.Element { })) // Let the native sheet gesture handle vertical dismissals; we only own horizontal swipes - const sheetDismissGesture = useMemo(() => Gesture.Native(), []) + const sheetDismissGesture = Gesture.Native() // Gesture logic for central big swipe area - const swipeGesture = useMemo( - () => - Gesture.Pan() - .activeOffsetX([-12, 12]) - // Bail on vertical intent so native sheet dismiss keeps working - .failOffsetY([-8, 8]) - .simultaneousWithExternalGesture(sheetDismissGesture) - .onUpdate((e) => { - if (Math.abs(e.translationY) < 40) { - translateX.value = Math.max(-160, Math.min(160, e.translationX)) - } - }) - .onEnd((e) => { - const threshold = 120 - const minVelocity = 600 - const isHorizontal = Math.abs(e.translationY) < 40 - if ( - isHorizontal && - (Math.abs(e.translationX) > threshold || - Math.abs(e.velocityX) > minVelocity) - ) { - if (e.translationX > 0) { - // Inverted: swipe right = previous - translateX.value = withSpring(220) - runOnJS(trigger)('notificationSuccess') - runOnJS(previous)() - } else { - // Inverted: swipe left = next - translateX.value = withSpring(-220) - runOnJS(trigger)('notificationSuccess') - runOnJS(skip)(undefined) - } - translateX.value = withDelay(160, withSpring(0)) - } else { - translateX.value = withSpring(0) - } - }), - [previous, skip, trigger, translateX, sheetDismissGesture], - ) - + const swipeGesture = Gesture.Pan() + .activeOffsetX([-12, 12]) + // Bail on vertical intent so native sheet dismiss keeps working + .failOffsetY([-8, 8]) + .simultaneousWithExternalGesture(sheetDismissGesture) + .onUpdate((e) => { + if (Math.abs(e.translationY) < 40) { + translateX.value = Math.max(-160, Math.min(160, e.translationX)) + } + }) + .onEnd((e) => { + const threshold = 120 + const minVelocity = 600 + const isHorizontal = Math.abs(e.translationY) < 40 + if ( + isHorizontal && + (Math.abs(e.translationX) > threshold || Math.abs(e.velocityX) > minVelocity) + ) { + if (e.translationX > 0) { + // Inverted: swipe right = previous + translateX.value = withSpring(220) + runOnJS(trigger)('notificationSuccess') + runOnJS(previous)() + } else { + // Inverted: swipe left = next + translateX.value = withSpring(-220) + runOnJS(trigger)('notificationSuccess') + runOnJS(skip)(undefined) + } + translateX.value = withDelay(160, withSpring(0)) + } else { + translateX.value = withSpring(0) + } + }) /** * Styling for the top layer of Player ZStack * @@ -114,81 +94,69 @@ export default function PlayerScreen(): React.JSX.Element { * * Apple devices get a small amount of margin */ - const mainContainerStyle = useMemo( - () => ({ - marginTop: isAndroid ? top : getTokenValue('$4'), - marginBottom: bottom + getTokenValue('$10'), - }), - [top, bottom, isAndroid], - ) + const mainContainerStyle = { + marginTop: isAndroid ? top : getTokenValue('$4'), + marginBottom: bottom + getTokenValue('$12'), + } - return ( - - {nowPlaying && ( - - + return nowPlaying ? ( + + - {/* Swipe feedback icons (topmost overlay) */} - - - - - - - - - + {/* Swipe feedback icons (topmost overlay) */} + + + + + + + + + - {/* Central large swipe area overlay (captures swipe like big album art) */} - - - + {/* Central large swipe area overlay (captures swipe like big album art) */} + + + - - {/* flexGrow 1 */} - + + {/* flexGrow 1 */} + - - - - -