mirror of
https://github.com/austinried/subtracks.git
synced 2026-02-11 07:12:44 +01:00
central management of track player state
currentTrack implemented and working well now (only updates on change)
This commit is contained in:
72
src/components/TrackPlayerState.tsx
Normal file
72
src/components/TrackPlayerState.tsx
Normal file
@@ -0,0 +1,72 @@
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import TrackPlayer, { Event, State, Track, useTrackPlayerEvents } from 'react-native-track-player';
|
||||
import { useAppState } from '@react-native-community/hooks';
|
||||
import { useUpdateAtom, useAtomValue } from 'jotai/utils';
|
||||
import { currentTrackAtom } from '../state/trackplayer';
|
||||
import { View } from 'react-native';
|
||||
|
||||
const TrackPlayerState = () => {
|
||||
const setCurrentTrack = useUpdateAtom(currentTrackAtom);
|
||||
const appState = useAppState();
|
||||
|
||||
const updateCurrentTrack = useCallback(async () => {
|
||||
const index = await TrackPlayer.getCurrentTrack();
|
||||
|
||||
if (index !== null && index >= 0) {
|
||||
const track = await TrackPlayer.getTrack(index);
|
||||
if (track !== null) {
|
||||
setCurrentTrack(track);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
setCurrentTrack(undefined);
|
||||
}, [setCurrentTrack]);
|
||||
|
||||
useTrackPlayerEvents(
|
||||
[
|
||||
// Event.PlaybackState,
|
||||
// Event.PlaybackTrackChanged,
|
||||
Event.PlaybackQueueEnded,
|
||||
Event.PlaybackMetadataReceived,
|
||||
Event.RemoteDuck,
|
||||
Event.RemoteNext,
|
||||
Event.RemotePrevious,
|
||||
Event.RemoteStop,
|
||||
],
|
||||
event => {
|
||||
if (event.type === Event.PlaybackQueueEnded && 'track' in event) {
|
||||
setCurrentTrack(undefined);
|
||||
return;
|
||||
}
|
||||
updateCurrentTrack();
|
||||
},
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (appState === 'active') {
|
||||
updateCurrentTrack();
|
||||
}
|
||||
}, [appState, updateCurrentTrack]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
|
||||
const CurrentTrack = () => {
|
||||
const currentTrack = useAtomValue(currentTrackAtom);
|
||||
|
||||
useEffect(() => {
|
||||
console.log(currentTrack?.title);
|
||||
}, [currentTrack]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
|
||||
const ASDFSADFSAF = () => (
|
||||
<View>
|
||||
<TrackPlayerState />
|
||||
<CurrentTrack />
|
||||
</View>
|
||||
);
|
||||
|
||||
export default ASDFSADFSAF;
|
||||
@@ -10,8 +10,9 @@ import {
|
||||
useWindowDimensions,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import { useCurrentTrackId, useSetQueue } from '../../hooks/player';
|
||||
import { useSetQueue } from '../../hooks/player';
|
||||
import { albumAtomFamily } from '../../state/music';
|
||||
import { currentTrackAtom } from '../../state/trackplayer';
|
||||
import colors from '../../styles/colors';
|
||||
import text from '../../styles/text';
|
||||
import AlbumArt from './AlbumArt';
|
||||
@@ -27,7 +28,7 @@ const SongItem: React.FC<{
|
||||
onPress: (event: GestureResponderEvent) => void;
|
||||
}> = ({ id, title, artist, onPress }) => {
|
||||
const [opacity, setOpacity] = useState(1);
|
||||
const currentTrackId = useCurrentTrackId();
|
||||
const currentTrack = useAtomValue(currentTrackAtom);
|
||||
|
||||
return (
|
||||
<View
|
||||
@@ -50,7 +51,7 @@ const SongItem: React.FC<{
|
||||
<Text
|
||||
style={{
|
||||
...text.songListTitle,
|
||||
color: currentTrackId === id ? colors.accent : colors.text.primary,
|
||||
color: currentTrack?.id === id ? colors.accent : colors.text.primary,
|
||||
}}>
|
||||
{title}
|
||||
</Text>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useState } from 'react';
|
||||
import TrackPlayer, { Track, useTrackPlayerEvents, Event, State } from 'react-native-track-player';
|
||||
import { useUpdateAtom } from 'jotai/utils';
|
||||
import TrackPlayer, { Track } from 'react-native-track-player';
|
||||
import { Song } from '../models/music';
|
||||
import { currentTrackAtom } from '../state/trackplayer';
|
||||
|
||||
function mapSongToTrack(song: Song): Track {
|
||||
return {
|
||||
@@ -13,41 +14,17 @@ function mapSongToTrack(song: Song): Track {
|
||||
};
|
||||
}
|
||||
|
||||
const currentTrackEvents = [Event.PlaybackState, Event.PlaybackTrackChanged, Event.RemoteStop];
|
||||
|
||||
export const useCurrentTrackId = () => {
|
||||
const [currentTrackId, setCurrentTrackId] = useState<string | null>(null);
|
||||
|
||||
useTrackPlayerEvents(currentTrackEvents, async event => {
|
||||
switch (event.type) {
|
||||
case Event.PlaybackState:
|
||||
switch (event.state) {
|
||||
case State.None:
|
||||
case State.Stopped:
|
||||
setCurrentTrackId(null);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case Event.PlaybackTrackChanged:
|
||||
const trackIndex = await TrackPlayer.getCurrentTrack();
|
||||
setCurrentTrackId((await TrackPlayer.getTrack(trackIndex)).id);
|
||||
break;
|
||||
case Event.RemoteStop:
|
||||
setCurrentTrackId(null);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
return currentTrackId;
|
||||
};
|
||||
|
||||
export const useSetQueue = () => {
|
||||
const setCurrentTrack = useUpdateAtom(currentTrackAtom);
|
||||
|
||||
return async (songs: Song[], playId?: string) => {
|
||||
await TrackPlayer.reset();
|
||||
const tracks = songs.map(mapSongToTrack);
|
||||
|
||||
if (playId) {
|
||||
setCurrentTrack(tracks.find(t => t.id === playId));
|
||||
}
|
||||
|
||||
if (!playId) {
|
||||
await TrackPlayer.add(tracks);
|
||||
} else if (playId === tracks[0].id) {
|
||||
@@ -63,8 +40,8 @@ export const useSetQueue = () => {
|
||||
|
||||
await TrackPlayer.add(tracks1, 0);
|
||||
|
||||
const queue = await TrackPlayer.getQueue();
|
||||
console.log(`queue: ${JSON.stringify(queue.map(x => x.title))}`);
|
||||
// const queue = await TrackPlayer.getQueue();
|
||||
// console.log(`queue: ${JSON.stringify(queue.map(x => x.title))}`);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
16
src/state/trackplayer.ts
Normal file
16
src/state/trackplayer.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { atom } from 'jotai';
|
||||
import { Track } from 'react-native-track-player';
|
||||
import equal from 'fast-deep-equal';
|
||||
|
||||
type OptionalTrack = Track | undefined;
|
||||
|
||||
const currentTrack = atom<OptionalTrack>(undefined);
|
||||
export const currentTrackAtom = atom<OptionalTrack, OptionalTrack>(
|
||||
get => get(currentTrack),
|
||||
(get, set, value) => {
|
||||
if (equal(get(currentTrack), value)) {
|
||||
return;
|
||||
}
|
||||
set(currentTrack, value);
|
||||
},
|
||||
);
|
||||
Reference in New Issue
Block a user