86 lines
3.5 KiB
TypeScript
86 lines
3.5 KiB
TypeScript
import { View, Text, TouchableOpacity, PanResponder } from 'react-native'
|
||
import { useRouter } from 'expo-router'
|
||
import { useState, useCallback } from 'react'
|
||
import { usePlayerStore } from '../src/store/playerStore'
|
||
|
||
export default function NowPlayingScreen() {
|
||
const router = useRouter()
|
||
const currentSong = usePlayerStore(s => s.currentSong)
|
||
const isPlaying = usePlayerStore(s => s.isPlaying)
|
||
const progress = usePlayerStore(s => s.progress)
|
||
const togglePlay = usePlayerStore(s => s.togglePlay)
|
||
const toggleShuffle = usePlayerStore(s => s.toggleShuffle)
|
||
const next = usePlayerStore(s => s.next)
|
||
const previous = usePlayerStore(s => s.previous)
|
||
const seek = usePlayerStore(s => s.seek)
|
||
const shuffle = usePlayerStore(s => s.shuffle)
|
||
|
||
const progressPercent = currentSong ? (progress / currentSong.duration) * 100 : 0
|
||
|
||
const panResponder = PanResponder.create({
|
||
onStartShouldSetPanResponder: () => true,
|
||
onMoveShouldSetPanResponder: () => true,
|
||
onPanResponderMove: (evt) => {
|
||
if (!currentSong) return
|
||
const x = evt.nativeEvent.locationX
|
||
const ratio = Math.max(0, Math.min(x / 375, 1))
|
||
seek(currentSong.duration * ratio)
|
||
},
|
||
})
|
||
|
||
return (
|
||
<View className="flex-1 bg-music-black justify-between py-8 px-6" {...panResponder.panHandlers}>
|
||
<TouchableOpacity onPress={() => router.back()} className="self-start">
|
||
<Text className="text-music-muted text-2xl">←</Text>
|
||
</TouchableOpacity>
|
||
|
||
<View className="w-64 h-64 rounded-2xl bg-music-vinyl items-center justify-center self-center">
|
||
<Text className="text-6xl">🎵</Text>
|
||
</View>
|
||
|
||
<View className="items-center">
|
||
<Text className="text-2xl font-semibold text-music-text">{currentSong?.title || 'No song'}</Text>
|
||
<Text className="text-music-muted mt-1">{currentSong?.artist}</Text>
|
||
</View>
|
||
|
||
<View className="w-full">
|
||
<View className="h-1 bg-music-border rounded-full">
|
||
<View className="h-full bg-music-accent rounded-full" style={{ width: `${progressPercent}%` }} />
|
||
</View>
|
||
<View className="flex-row justify-between mt-2">
|
||
<Text className="text-xs text-music-muted">{formatTime(progress)}</Text>
|
||
<Text className="text-xs text-music-muted">{currentSong ? formatTime(currentSong.duration) : '0:00'}</Text>
|
||
</View>
|
||
</View>
|
||
|
||
<View className="flex-row items-center justify-center gap-6">
|
||
<TouchableOpacity onPress={toggleShuffle}>
|
||
<Text className={`${shuffle ? 'text-music-accent' : 'text-music-muted'} text-2xl`}>🔀</Text>
|
||
</TouchableOpacity>
|
||
<TouchableOpacity onPress={previous}>
|
||
<Text className="text-3xl">⏮️</Text>
|
||
</TouchableOpacity>
|
||
<TouchableOpacity onPress={togglePlay}>
|
||
<Text className="text-5xl text-music-accent">{isPlaying ? '⏸' : '▶️'}</Text>
|
||
</TouchableOpacity>
|
||
<TouchableOpacity onPress={next}>
|
||
<Text className="text-3xl">⏭️</Text>
|
||
</TouchableOpacity>
|
||
<Text className="text-music-muted text-2xl">➕</Text>
|
||
</View>
|
||
|
||
<View className="flex-row items-center justify-center gap-2">
|
||
<TouchableOpacity onPress={() => router.push('/shareplay' as any)}>
|
||
<Text className="text-music-muted">📢</Text>
|
||
</TouchableOpacity>
|
||
<Text className="text-xs text-music-muted">Speaker</Text>
|
||
</View>
|
||
</View>
|
||
)
|
||
}
|
||
|
||
function formatTime(sec: number): string {
|
||
const m = Math.floor(sec / 60)
|
||
const s = Math.floor(sec % 60)
|
||
return `${m}:${s.toString().padStart(2, '0')}`
|
||
} |