mirror of
https://github.com/austinried/subtracks.git
synced 2025-12-27 00:59:28 +01:00
started player controls
This commit is contained in:
parent
b908dd87f6
commit
3c969c2972
BIN
res/next-fill.png
Normal file
BIN
res/next-fill.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.2 KiB |
BIN
res/pause_circle-fill.png
Normal file
BIN
res/pause_circle-fill.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
BIN
res/play_circle-fill.png
Normal file
BIN
res/play_circle-fill.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
BIN
res/previous-fill.png
Normal file
BIN
res/previous-fill.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.6 KiB |
@ -1,8 +1,9 @@
|
||||
import { useAtomValue } from 'jotai/utils';
|
||||
import React from 'react';
|
||||
import { StatusBar, StyleSheet, Text, useWindowDimensions, View } from 'react-native';
|
||||
import { Pressable, StatusBar, StyleSheet, Text, useWindowDimensions, View } from 'react-native';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
import { currentQueueNameAtom, currentTrackAtom } from '../state/trackplayer';
|
||||
import TrackPlayer, { State } from 'react-native-track-player';
|
||||
import { currentQueueNameAtom, currentTrackAtom, playerStateAtom } from '../state/trackplayer';
|
||||
import text from '../styles/text';
|
||||
import CoverArt from './common/CoverArt';
|
||||
import ImageGradientBackground from './common/ImageGradientBackground';
|
||||
@ -14,7 +15,7 @@ const NowPlayingHeader = () => {
|
||||
<View style={headerStyles.container}>
|
||||
<FastImage source={require('../../res/arrow_left-fill.png')} style={headerStyles.backArrow} tintColor="white" />
|
||||
<Text numberOfLines={2} style={headerStyles.queueName}>
|
||||
{queueName}
|
||||
{queueName || 'Nothing playing...'}
|
||||
</Text>
|
||||
<FastImage source={require('../../res/more_vertical.png')} style={headerStyles.more} tintColor="white" />
|
||||
</View>
|
||||
@ -48,16 +49,12 @@ const SongCoverArt = () => {
|
||||
const track = useAtomValue(currentTrackAtom);
|
||||
const layout = useWindowDimensions();
|
||||
|
||||
const size = layout.width - layout.width / 6;
|
||||
const size = layout.width - layout.width / 7;
|
||||
|
||||
return (
|
||||
<View style={coverArtStyles.container}>
|
||||
<CoverArt
|
||||
PlaceholderComponent={() => (
|
||||
<View style={{ height: size, width: size }}>
|
||||
<Text>Failed</Text>
|
||||
</View>
|
||||
)}
|
||||
PlaceholderComponent={() => <View style={{ height: size, width: size }} />}
|
||||
height={size}
|
||||
width={size}
|
||||
coverArtUri={track?.artwork as string}
|
||||
@ -70,7 +67,7 @@ const coverArtStyles = StyleSheet.create({
|
||||
container: {
|
||||
width: '100%',
|
||||
alignItems: 'center',
|
||||
marginTop: 20,
|
||||
marginTop: 10,
|
||||
},
|
||||
});
|
||||
|
||||
@ -104,6 +101,81 @@ const infoStyles = StyleSheet.create({
|
||||
},
|
||||
});
|
||||
|
||||
const PlayerControls = () => {
|
||||
const state = useAtomValue(playerStateAtom);
|
||||
|
||||
let playPauseIcon: number;
|
||||
let playPauseStyle: any;
|
||||
let playPauseAction: () => void;
|
||||
|
||||
switch (state) {
|
||||
case State.Playing:
|
||||
playPauseIcon = require('../../res/pause_circle-fill.png');
|
||||
playPauseStyle = controlsStyles.enabled;
|
||||
playPauseAction = () => TrackPlayer.pause();
|
||||
break;
|
||||
case State.Paused:
|
||||
playPauseIcon = require('../../res/play_circle-fill.png');
|
||||
playPauseStyle = controlsStyles.enabled;
|
||||
playPauseAction = () => TrackPlayer.play();
|
||||
break;
|
||||
case State.Buffering:
|
||||
case State.Connecting:
|
||||
playPauseIcon = require('../../res/pause_circle-fill.png');
|
||||
playPauseStyle = controlsStyles.disabled;
|
||||
playPauseAction = () => {};
|
||||
break;
|
||||
default:
|
||||
playPauseIcon = require('../../res/play_circle-fill.png');
|
||||
playPauseStyle = controlsStyles.disabled;
|
||||
playPauseAction = () => {};
|
||||
break;
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={controlsStyles.container}>
|
||||
<FastImage
|
||||
source={require('../../res/previous-fill.png')}
|
||||
tintColor="white"
|
||||
style={{ ...controlsStyles.skip, ...playPauseStyle }}
|
||||
/>
|
||||
<Pressable onPress={playPauseAction}>
|
||||
<FastImage source={playPauseIcon} tintColor="white" style={{ ...controlsStyles.play, ...playPauseStyle }} />
|
||||
</Pressable>
|
||||
<FastImage
|
||||
source={require('../../res/next-fill.png')}
|
||||
tintColor="white"
|
||||
style={{ ...controlsStyles.skip, ...playPauseStyle }}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const controlsStyles = StyleSheet.create({
|
||||
container: {
|
||||
width: '100%',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
marginTop: 40,
|
||||
},
|
||||
skip: {
|
||||
height: 40,
|
||||
width: 40,
|
||||
marginHorizontal: 18,
|
||||
},
|
||||
play: {
|
||||
height: 90,
|
||||
width: 90,
|
||||
},
|
||||
enabled: {
|
||||
opacity: 1,
|
||||
},
|
||||
disabled: {
|
||||
opacity: 0.35,
|
||||
},
|
||||
});
|
||||
|
||||
const NowPlayingLayout = () => {
|
||||
const track = useAtomValue(currentTrackAtom);
|
||||
|
||||
@ -117,6 +189,7 @@ const NowPlayingLayout = () => {
|
||||
<NowPlayingHeader />
|
||||
<SongCoverArt />
|
||||
<SongInfo />
|
||||
<PlayerControls />
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import React, { useCallback, useEffect } from 'react';
|
||||
import TrackPlayer, { Event, useTrackPlayerEvents } from 'react-native-track-player';
|
||||
import TrackPlayer, { Event, State, useTrackPlayerEvents } from 'react-native-track-player';
|
||||
import { useAppState } from '@react-native-community/hooks';
|
||||
import { useUpdateAtom, useAtomValue } from 'jotai/utils';
|
||||
import { currentQueueNameAtom, currentTrackAtom } from '../state/trackplayer';
|
||||
import { currentQueueNameAtom, currentTrackAtom, playerStateAtom } from '../state/trackplayer';
|
||||
import { View } from 'react-native';
|
||||
|
||||
const CurrentTrackState = () => {
|
||||
@ -67,6 +67,42 @@ const CurrentQueueName = () => {
|
||||
setCurrentQueueName(undefined);
|
||||
}, [setCurrentQueueName]);
|
||||
|
||||
useTrackPlayerEvents(
|
||||
[Event.PlaybackState, Event.PlaybackQueueEnded, Event.PlaybackMetadataReceived, Event.RemoteDuck, Event.RemoteStop],
|
||||
event => {
|
||||
if (event.type === Event.PlaybackState) {
|
||||
if (event.state === State.Stopped || event.state === State.None) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
update();
|
||||
},
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (appState === 'active') {
|
||||
update();
|
||||
}
|
||||
}, [appState, update]);
|
||||
|
||||
return <></>;
|
||||
};
|
||||
|
||||
const PlayerState = () => {
|
||||
const setPlayerState = useUpdateAtom(playerStateAtom);
|
||||
const appState = useAppState();
|
||||
|
||||
const update = useCallback(
|
||||
async (state?: State) => {
|
||||
setPlayerState(state || (await TrackPlayer.getState()));
|
||||
},
|
||||
[setPlayerState],
|
||||
);
|
||||
|
||||
useTrackPlayerEvents([Event.PlaybackState], event => {
|
||||
update(event.state);
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (appState === 'active') {
|
||||
update();
|
||||
@ -90,6 +126,7 @@ const TrackPlayerState = () => (
|
||||
<View>
|
||||
<CurrentTrackState />
|
||||
<CurrentQueueName />
|
||||
<PlayerState />
|
||||
<Debug />
|
||||
</View>
|
||||
);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { atom } from 'jotai';
|
||||
import { Track } from 'react-native-track-player';
|
||||
import { State, Track } from 'react-native-track-player';
|
||||
import equal from 'fast-deep-equal';
|
||||
|
||||
type OptionalTrack = Track | undefined;
|
||||
@ -25,3 +25,13 @@ export const currentQueueNameAtom = atom<OptionalString, OptionalString>(
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const playerState = atom<State>(State.None);
|
||||
export const playerStateAtom = atom<State, State>(
|
||||
get => get(playerState),
|
||||
(get, set, value) => {
|
||||
if (get(playerState) !== value) {
|
||||
set(playerState, value);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user