mirror of
https://github.com/austinried/subtracks.git
synced 2025-12-29 09:29:29 +01:00
fixed progress hook with my own state wrap/update
This commit is contained in:
parent
b5473ee568
commit
49b5ce3f6c
@ -2,8 +2,15 @@ import { useAtomValue } from 'jotai/utils'
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { StatusBar, StyleSheet, Text, useWindowDimensions, View } from 'react-native'
|
import { StatusBar, StyleSheet, Text, useWindowDimensions, View } from 'react-native'
|
||||||
import FastImage from 'react-native-fast-image'
|
import FastImage from 'react-native-fast-image'
|
||||||
import TrackPlayer, { State, useProgress } from 'react-native-track-player'
|
import TrackPlayer, { State } from 'react-native-track-player'
|
||||||
import { queueNameAtom, currentTrackAtom, playerStateAtom, useNext, usePrevious } from '../state/trackplayer'
|
import {
|
||||||
|
queueNameAtom,
|
||||||
|
currentTrackAtom,
|
||||||
|
playerStateAtom,
|
||||||
|
useNext,
|
||||||
|
usePrevious,
|
||||||
|
useProgress,
|
||||||
|
} from '../state/trackplayer'
|
||||||
import colors from '../styles/colors'
|
import colors from '../styles/colors'
|
||||||
import text, { Font } from '../styles/text'
|
import text, { Font } from '../styles/text'
|
||||||
import { formatDuration } from '../util'
|
import { formatDuration } from '../util'
|
||||||
@ -100,7 +107,7 @@ const infoStyles = StyleSheet.create({
|
|||||||
})
|
})
|
||||||
|
|
||||||
const SeekBar = () => {
|
const SeekBar = () => {
|
||||||
const { position, duration } = useProgress(250)
|
const { position, duration } = useProgress()
|
||||||
|
|
||||||
let progress = 0
|
let progress = 0
|
||||||
if (duration > 0) {
|
if (duration > 0) {
|
||||||
|
|||||||
@ -2,12 +2,16 @@ import { useAppState } from '@react-native-community/hooks'
|
|||||||
import { useAtomValue, useUpdateAtom } from 'jotai/utils'
|
import { useAtomValue, useUpdateAtom } from 'jotai/utils'
|
||||||
import React, { useEffect } from 'react'
|
import React, { useEffect } from 'react'
|
||||||
import { View } from 'react-native'
|
import { View } from 'react-native'
|
||||||
import TrackPlayer, { Event, State, useTrackPlayerEvents } from 'react-native-track-player'
|
import { Event, State, useProgress, useTrackPlayerEvents } from 'react-native-track-player'
|
||||||
import {
|
import {
|
||||||
currentTrackAtom,
|
currentTrackAtom,
|
||||||
playerStateAtom,
|
playerStateAtom,
|
||||||
|
progressAtom,
|
||||||
|
progressSubsAtom,
|
||||||
queueWriteAtom,
|
queueWriteAtom,
|
||||||
useRefreshCurrentTrack,
|
useRefreshCurrentTrack,
|
||||||
|
useRefreshPlayerState,
|
||||||
|
useRefreshProgress,
|
||||||
useRefreshQueue,
|
useRefreshQueue,
|
||||||
} from '../state/trackplayer'
|
} from '../state/trackplayer'
|
||||||
|
|
||||||
@ -67,13 +71,14 @@ const CurrentTrackState = () => {
|
|||||||
|
|
||||||
const PlayerState = () => {
|
const PlayerState = () => {
|
||||||
const setPlayerState = useUpdateAtom(playerStateAtom)
|
const setPlayerState = useUpdateAtom(playerStateAtom)
|
||||||
|
const refreshPlayerState = useRefreshPlayerState()
|
||||||
|
|
||||||
const update = async (payload?: Payload) => {
|
const update = async (payload?: Payload) => {
|
||||||
if (payload?.type === Event.RemoteStop) {
|
if (payload?.type === Event.RemoteStop) {
|
||||||
setPlayerState(State.None)
|
setPlayerState(State.None)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
setPlayerState(payload?.state || (await TrackPlayer.getState()))
|
await refreshPlayerState()
|
||||||
}
|
}
|
||||||
|
|
||||||
return <TrackPlayerEventResponder events={[Event.PlaybackState, Event.RemoteStop]} update={update} />
|
return <TrackPlayerEventResponder events={[Event.PlaybackState, Event.RemoteStop]} update={update} />
|
||||||
@ -94,6 +99,41 @@ const QueueState = () => {
|
|||||||
return <TrackPlayerEventResponder events={[Event.RemoteStop]} update={update} />
|
return <TrackPlayerEventResponder events={[Event.RemoteStop]} update={update} />
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ProgressHook = () => {
|
||||||
|
const setProgress = useUpdateAtom(progressAtom)
|
||||||
|
const progress = useProgress(250)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setProgress(progress)
|
||||||
|
}, [setProgress, progress])
|
||||||
|
|
||||||
|
return <></>
|
||||||
|
}
|
||||||
|
|
||||||
|
const ProgressState = () => {
|
||||||
|
const setProgress = useUpdateAtom(progressAtom)
|
||||||
|
const refreshProgress = useRefreshProgress()
|
||||||
|
const progressSubs = useAtomValue(progressSubsAtom)
|
||||||
|
|
||||||
|
const update = async (payload?: Payload) => {
|
||||||
|
if (payload) {
|
||||||
|
setProgress({ position: 0, duration: 0, buffered: 0 })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
await refreshProgress()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (progressSubs > 0) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ProgressHook />
|
||||||
|
<TrackPlayerEventResponder events={[Event.RemoteStop]} update={update} />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return <TrackPlayerEventResponder events={[Event.RemoteStop]} update={update} />
|
||||||
|
}
|
||||||
|
|
||||||
const Debug = () => {
|
const Debug = () => {
|
||||||
const value = useAtomValue(currentTrackAtom)
|
const value = useAtomValue(currentTrackAtom)
|
||||||
|
|
||||||
@ -109,6 +149,7 @@ const TrackPlayerState = () => (
|
|||||||
<CurrentTrackState />
|
<CurrentTrackState />
|
||||||
<PlayerState />
|
<PlayerState />
|
||||||
<QueueState />
|
<QueueState />
|
||||||
|
<ProgressState />
|
||||||
<Debug />
|
<Debug />
|
||||||
</View>
|
</View>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
import { atom } from 'jotai'
|
|
||||||
import TrackPlayer, { State, Track } from 'react-native-track-player'
|
|
||||||
import equal from 'fast-deep-equal'
|
import equal from 'fast-deep-equal'
|
||||||
import { useUpdateAtom } from 'jotai/utils'
|
import { atom } from 'jotai'
|
||||||
|
import { useAtomValue, useUpdateAtom } from 'jotai/utils'
|
||||||
|
import { useEffect } from 'react'
|
||||||
|
import TrackPlayer, { State, Track } from 'react-native-track-player'
|
||||||
import { Song } from '../models/music'
|
import { Song } from '../models/music'
|
||||||
import { PromiseQueue } from '../util'
|
import { PromiseQueue } from '../util'
|
||||||
|
|
||||||
@ -12,6 +13,12 @@ type TrackExt = Track & {
|
|||||||
|
|
||||||
type OptionalTrackExt = TrackExt | undefined
|
type OptionalTrackExt = TrackExt | undefined
|
||||||
|
|
||||||
|
type Progress = {
|
||||||
|
position: number
|
||||||
|
duration: number
|
||||||
|
buffered: number
|
||||||
|
}
|
||||||
|
|
||||||
const playerState = atom<State>(State.None)
|
const playerState = atom<State>(State.None)
|
||||||
export const playerStateAtom = atom<State, State>(
|
export const playerStateAtom = atom<State, State>(
|
||||||
get => get(playerState),
|
get => get(playerState),
|
||||||
@ -33,7 +40,7 @@ export const currentTrackAtom = atom<OptionalTrackExt, OptionalTrackExt>(
|
|||||||
)
|
)
|
||||||
|
|
||||||
const _queue = atom<TrackExt[]>([])
|
const _queue = atom<TrackExt[]>([])
|
||||||
export const queueAtom = atom<TrackExt[]>(get => get(_queue))
|
export const queueReadAtom = atom<TrackExt[]>(get => get(_queue))
|
||||||
export const queueWriteAtom = atom<TrackExt[], TrackExt[]>(
|
export const queueWriteAtom = atom<TrackExt[], TrackExt[]>(
|
||||||
get => get(_queue),
|
get => get(_queue),
|
||||||
(get, set, update) => {
|
(get, set, update) => {
|
||||||
@ -51,6 +58,25 @@ export const queueNameAtom = atom<string | undefined>(get => {
|
|||||||
return undefined
|
return undefined
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const _progress = atom<Progress>({ position: 0, duration: 0, buffered: 0 })
|
||||||
|
export const progressAtom = atom<Progress, Progress>(
|
||||||
|
get => get(_progress),
|
||||||
|
(get, set, update) => {
|
||||||
|
if (!equal(get(_progress), update)) {
|
||||||
|
set(_progress, update)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
const progressSubs = atom(0)
|
||||||
|
export const progressSubsAtom = atom(get => get(progressSubs))
|
||||||
|
const addProgressSub = atom(null, (get, set) => {
|
||||||
|
set(progressSubs, get(progressSubs) + 1)
|
||||||
|
})
|
||||||
|
const removeProgressSub = atom(null, (get, set) => {
|
||||||
|
set(progressSubs, get(progressSubs) - 1)
|
||||||
|
})
|
||||||
|
|
||||||
const trackPlayerCommands = new PromiseQueue(1)
|
const trackPlayerCommands = new PromiseQueue(1)
|
||||||
|
|
||||||
const getQueue = async (): Promise<TrackExt[]> => {
|
const getQueue = async (): Promise<TrackExt[]> => {
|
||||||
@ -61,6 +87,23 @@ const getTrack = async (index: number): Promise<TrackExt> => {
|
|||||||
return ((await TrackPlayer.getTrack(index)) as TrackExt) || undefined
|
return ((await TrackPlayer.getTrack(index)) as TrackExt) || undefined
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getPlayerState = async (): Promise<State> => {
|
||||||
|
return (await TrackPlayer.getState()) || State.None
|
||||||
|
}
|
||||||
|
|
||||||
|
const getProgress = async (): Promise<Progress> => {
|
||||||
|
const [position, duration, buffered] = await Promise.all([
|
||||||
|
TrackPlayer.getPosition(),
|
||||||
|
TrackPlayer.getDuration(),
|
||||||
|
TrackPlayer.getBufferedPosition(),
|
||||||
|
])
|
||||||
|
return {
|
||||||
|
position: position || 0,
|
||||||
|
duration: duration || 0,
|
||||||
|
buffered: buffered || 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const useRefreshQueue = () => {
|
export const useRefreshQueue = () => {
|
||||||
const setQueue = useUpdateAtom(queueWriteAtom)
|
const setQueue = useUpdateAtom(queueWriteAtom)
|
||||||
|
|
||||||
@ -84,6 +127,24 @@ export const useRefreshCurrentTrack = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const useRefreshPlayerState = () => {
|
||||||
|
const setPlayerState = useUpdateAtom(playerStateAtom)
|
||||||
|
|
||||||
|
return () =>
|
||||||
|
trackPlayerCommands.enqueue(async () => {
|
||||||
|
setPlayerState(await getPlayerState())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useRefreshProgress = () => {
|
||||||
|
const setProgress = useUpdateAtom(progressAtom)
|
||||||
|
|
||||||
|
return () =>
|
||||||
|
trackPlayerCommands.enqueue(async () => {
|
||||||
|
setProgress(await getProgress())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
export const usePrevious = () => {
|
export const usePrevious = () => {
|
||||||
const setCurrentTrack = useUpdateAtom(currentTrackAtom)
|
const setCurrentTrack = useUpdateAtom(currentTrackAtom)
|
||||||
|
|
||||||
@ -179,6 +240,19 @@ export const useSetQueue = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const useProgress = () => {
|
||||||
|
const progress = useAtomValue(progressAtom)
|
||||||
|
const addSub = useUpdateAtom(addProgressSub)
|
||||||
|
const removeSub = useUpdateAtom(removeProgressSub)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
addSub()
|
||||||
|
return removeSub
|
||||||
|
}, [addSub, removeSub])
|
||||||
|
|
||||||
|
return progress
|
||||||
|
}
|
||||||
|
|
||||||
function mapSongToTrack(song: Song, queueName: string): TrackExt {
|
function mapSongToTrack(song: Song, queueName: string): TrackExt {
|
||||||
return {
|
return {
|
||||||
id: song.id,
|
id: song.id,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user