feat: fix player

This commit is contained in:
Victor
2026-02-27 15:50:57 +01:00
parent ae93cd4521
commit 006b65eed4
5 changed files with 385 additions and 166 deletions
+15 -74
View File
@@ -15,7 +15,7 @@ import { responsiveHeight, responsiveWidth } from 'react-native-responsive-dimen
import { useGlobal } from 'reactn'
import { background, icons } from '../../assets'
import PressableScale from '../../components/PressableScale'
import Slider from '../../components/Slider'
import ProgressSlider from '../../components/player/ProgressSlider'
import { arrayRemove, arrayUnion, increment, projectsRef, usersRef } from '../../config/firebase'
import useDataFromRef from '../../hooks/useDataFromRef'
import usePlayer from '../../hooks/usePlayer'
@@ -44,9 +44,6 @@ const MusicDetails = ({ route }) => {
const projectId = params?.projectId || null
const [fav, setFav] = useState(false)
const [currentUID] = useGlobal('currentUID')
const wasPlayingBeforeSeek = useRef(false)
const hasCapturedSeekStateRef = useRef(false)
const lastSeekTargetMsRef = useRef(null)
const listenedMsRef = useRef(0)
const incrementDoneRef = useRef(false)
const timerRef = useRef(null)
@@ -274,15 +271,6 @@ const MusicDetails = ({ route }) => {
return clearTimer
}, [isTrackPlaying, projectId])
const fmt = (ms) => {
const total = Math.max(0, Math.floor((ms || 0) / 1000))
const m = Math.floor(total / 60)
.toString()
.padStart(1, '0')
const s = (total % 60).toString().padStart(2, '0')
return `${m}:${s}`
}
const togglePlay = useCallback(async () => {
if (!trackDescriptor) return
try {
@@ -308,42 +296,26 @@ const MusicDetails = ({ route }) => {
resumeTrack,
])
const handleSliderSeekStart = useCallback(async () => {
const handleSliderSeekStart = useCallback(() => {
if (!trackDescriptor) return
lastSeekTargetMsRef.current = null
if (!hasCapturedSeekStateRef.current) {
hasCapturedSeekStateRef.current = true
wasPlayingBeforeSeek.current = isTrackPlaying
}
try {
if (!isCurrentTrack) {
await ensureLoaded({ startPositionMs: positionMs, autoPlay: false })
}
if (isTrackPlaying) {
await pauseTrack()
}
} catch (e) {
console.log('MusicDetails seek start error', e?.message)
}
}, [trackDescriptor, isTrackPlaying, isCurrentTrack, ensureLoaded, positionMs, pauseTrack])
}, [trackDescriptor])
const handleSliderSeek = useCallback(
async (ratio) => {
async (targetMs) => {
const dur = sliderDurationMs || 0
if (!trackDescriptor || dur <= 0) return
const targetMs = Math.max(0, Math.floor(dur * ratio))
lastSeekTargetMsRef.current = targetMs
const bounded = Math.max(0, Math.min(dur, Math.floor(targetMs)))
try {
if (!isCurrentTrack) {
await ensureLoaded({ startPositionMs: targetMs, autoPlay: false })
await ensureLoaded({ startPositionMs: bounded, autoPlay: false })
} else {
await seekTrackTo(targetMs)
await seekTrackTo(bounded)
}
} catch (e) {
console.log('MusicDetails seek error', e?.message)
}
},
[sliderDurationMs, trackDescriptor, isCurrentTrack, ensureLoaded, seekTrackTo]
[trackDescriptor, sliderDurationMs, isCurrentTrack, ensureLoaded, seekTrackTo]
)
const handleToggleLoop = useCallback(async () => {
@@ -392,34 +364,6 @@ const MusicDetails = ({ route }) => {
resumeTrack,
])
const handleSliderSeekEnd = useCallback(async () => {
const targetMs =
typeof lastSeekTargetMsRef.current === 'number'
? Math.max(0, lastSeekTargetMsRef.current)
: null
try {
if (wasPlayingBeforeSeek.current) {
if (!isCurrentTrack) {
await ensureLoaded({
startPositionMs: targetMs !== null && Number.isFinite(targetMs) ? targetMs : positionMs,
autoPlay: true,
})
} else {
if (targetMs !== null && Number.isFinite(targetMs)) {
await seekTrackTo(targetMs)
}
await resumeTrack()
}
}
} catch (e) {
console.log('MusicDetails seek end error', e?.message)
} finally {
wasPlayingBeforeSeek.current = false
hasCapturedSeekStateRef.current = false
lastSeekTargetMsRef.current = null
}
}, [ensureLoaded, isCurrentTrack, positionMs, resumeTrack, seekTrackTo])
const handleSeekBySeconds = useCallback(
async (deltaSeconds) => {
if (!trackDescriptor) return
@@ -816,18 +760,15 @@ const MusicDetails = ({ route }) => {
</View>
{songUrl && (
<View style={{ paddingTop: 22 }}>
<Slider
value={fmt(positionMs)}
maxValue={fmt(sliderDurationMs)}
progress={
sliderDurationMs
? Math.min(1, Math.max(0, (positionMs || 0) / sliderDurationMs))
: 0
}
seekEnabled={!!songUrl}
<ProgressSlider
positionMs={positionMs}
durationMs={sliderDurationMs}
isPlaying={isTrackPlaying}
onSeekStart={handleSliderSeekStart}
onSeek={handleSliderSeek}
onSeekEnd={handleSliderSeekEnd}
onPause={pauseTrack}
onPlay={resumeTrack}
disabled={!songUrl}
/>
<View style={{ ...Style.containerRow, gap: 24, alignSelf: 'center' }}>
{/* Previous (rewind 10s) */}