all state migrated to zustand, jotai removed

splash page now waits on state hydration from db
This commit is contained in:
austinried
2021-08-04 13:13:32 +09:00
parent 33dc0be02b
commit 706e57aa77
23 changed files with 427 additions and 660 deletions

View File

@@ -36,8 +36,7 @@ const ArtistImageFallback: React.FC<{
}> = ({ enableLoading }) => {
useEffect(() => {
enableLoading()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
}, [enableLoading])
return <></>
}

View File

@@ -1,9 +1,9 @@
import { ListableItem } from '@app/models/music'
import { currentTrackAtom } from '@app/state/trackplayer'
import { useStore } from '@app/state/store'
import { selectTrackPlayer } from '@app/state/trackplayer'
import colors from '@app/styles/colors'
import font from '@app/styles/font'
import { useNavigation } from '@react-navigation/native'
import { useAtomValue } from 'jotai/utils'
import React, { useState } from 'react'
import { GestureResponderEvent, StyleSheet, Text, View } from 'react-native'
import IconFA from 'react-native-vector-icons/FontAwesome'
@@ -16,7 +16,7 @@ const TitleTextSong = React.memo<{
id: string
title?: string
}>(({ id, title }) => {
const currentTrack = useAtomValue(currentTrackAtom)
const currentTrack = useStore(selectTrackPlayer.currentTrack)
const playing = currentTrack?.id === id
return (

View File

@@ -1,6 +1,6 @@
import Button from '@app/components/Button'
import { useSetQueue } from '@app/hooks/trackplayer'
import { Song } from '@app/models/music'
import { useSetQueue } from '@app/state/trackplayer'
import colors from '@app/styles/colors'
import React, { useState } from 'react'
import { StyleProp, StyleSheet, View, ViewStyle } from 'react-native'

View File

@@ -1,17 +1,18 @@
import React from 'react'
import { Pressable, StyleSheet, Text, View } from 'react-native'
import { useNavigation } from '@react-navigation/native'
import { useAtomValue } from 'jotai/utils'
import { currentTrackAtom, playerStateAtom, usePause, usePlay, useProgress } from '@app/state/trackplayer'
import CoverArt from '@app/components/CoverArt'
import PressableOpacity from '@app/components/PressableOpacity'
import { usePause, usePlay } from '@app/hooks/trackplayer'
import { useStore } from '@app/state/store'
import { selectTrackPlayer } from '@app/state/trackplayer'
import colors from '@app/styles/colors'
import font from '@app/styles/font'
import { useNavigation } from '@react-navigation/native'
import React from 'react'
import { Pressable, StyleSheet, Text, View } from 'react-native'
import { State } from 'react-native-track-player'
import PressableOpacity from '@app/components/PressableOpacity'
import IconFA5 from 'react-native-vector-icons/FontAwesome5'
const ProgressBar = () => {
const { position, duration } = useProgress()
const { position, duration } = useStore(selectTrackPlayer.progress)
let progress = 0
if (duration > 0) {
@@ -41,8 +42,8 @@ const progressStyles = StyleSheet.create({
const NowPlayingBar = () => {
const navigation = useNavigation()
const track = useAtomValue(currentTrackAtom)
const playerState = useAtomValue(playerStateAtom)
const track = useStore(selectTrackPlayer.currentTrack)
const playerState = useStore(selectTrackPlayer.playerState)
const play = usePlay()
const pause = usePause()

View File

@@ -0,0 +1,17 @@
import { useStore } from '@app/state/store'
import { selectTrackPlayer } from '@app/state/trackplayer'
import React, { useEffect } from 'react'
import { useProgress } from 'react-native-track-player'
const ProgressHook = () => {
const setProgress = useStore(selectTrackPlayer.setProgress)
const progress = useProgress(250)
useEffect(() => {
setProgress(progress)
}, [setProgress, progress])
return <></>
}
export default ProgressHook

View File

@@ -1,192 +0,0 @@
import { useAppState } from '@react-native-community/hooks'
import { useAtomValue, useUpdateAtom } from 'jotai/utils'
import React, { useEffect } from 'react'
import { View } from 'react-native'
import { Event, State, useProgress, useTrackPlayerEvents } from 'react-native-track-player'
import {
currentTrackAtom,
playerStateAtom,
progressAtom,
progressSubsAtom,
queueAtom,
useRefreshCurrentTrack,
useRefreshPlayerState,
useRefreshProgress,
useRefreshQueue,
} from '@app/state/trackplayer'
const AppActiveResponder: React.FC<{
update: () => void
}> = ({ update }) => {
const appState = useAppState()
useEffect(() => {
if (appState === 'active') {
update()
}
}, [appState, update])
return <></>
}
type Payload = { type: Event; [key: string]: any }
const TrackPlayerEventResponder: React.FC<{
update: (payload?: Payload) => void
events: Event[]
}> = ({ update, events }) => {
useTrackPlayerEvents(events, update)
return <AppActiveResponder update={update} />
}
const CurrentTrackState = () => {
const setCurrentTrack = useUpdateAtom(currentTrackAtom)
const refreshCurrentTrack = useRefreshCurrentTrack()
const update = async (payload?: Payload) => {
const queueEnded = payload?.type === Event.PlaybackQueueEnded && 'track' in payload
const remoteStop = payload?.type === Event.RemoteStop
if (queueEnded || remoteStop) {
setCurrentTrack(undefined)
return
}
await refreshCurrentTrack()
}
return (
<TrackPlayerEventResponder
events={[
Event.PlaybackQueueEnded,
Event.PlaybackTrackChanged,
Event.PlaybackMetadataReceived,
Event.RemoteDuck,
Event.RemoteStop,
]}
update={update}
/>
)
}
const PlayerState = () => {
const setPlayerState = useUpdateAtom(playerStateAtom)
const refreshPlayerState = useRefreshPlayerState()
const update = async (payload?: Payload) => {
if (payload?.type === Event.RemoteStop) {
setPlayerState(State.None)
return
}
await refreshPlayerState()
}
return <TrackPlayerEventResponder events={[Event.PlaybackState, Event.RemoteStop]} update={update} />
}
const QueueState = () => {
const setQueue = useUpdateAtom(queueAtom)
const refreshQueue = useRefreshQueue()
const update = async (payload?: Payload) => {
if (payload) {
setQueue([])
return
}
await refreshQueue()
}
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, Event.PlaybackTrackChanged]} update={update} />
</>
)
}
return <TrackPlayerEventResponder events={[Event.RemoteStop]} update={update} />
}
const Debug = () => {
const value = useAtomValue(queueAtom)
useEffect(() => {
console.log(value.map(t => t.title))
}, [value])
return <></>
}
// const DebugEvents = () => {
// const update = (payload?: Payload) => {
// console.log(`${payload?.type}: ${JSON.stringify(payload)}`)
// }
// return (
// <TrackPlayerEventResponder
// events={[
// Event.PlaybackError,
// Event.PlaybackMetadataReceived,
// Event.PlaybackQueueEnded,
// Event.PlaybackState,
// Event.PlaybackTrackChanged,
// Event.RemoteBookmark,
// Event.RemoteDislike,
// Event.RemoteDuck,
// Event.RemoteJumpBackward,
// Event.RemoteJumpForward,
// Event.RemoteLike,
// Event.RemoteNext,
// Event.RemotePause,
// Event.RemotePlay,
// Event.RemotePlayId,
// Event.RemotePlaySearch,
// Event.RemotePrevious,
// Event.RemoteSeek,
// Event.RemoteSetRating,
// Event.RemoteSkip,
// Event.RemoteStop,
// ]}
// update={update}
// />
// )
// }
const TrackPlayerState = () => (
<View>
<CurrentTrackState />
<PlayerState />
<QueueState />
<ProgressState />
<Debug />
{/* <DebugEvents /> */}
</View>
)
export default TrackPlayerState