Add global unified state for audio files

This commit is contained in:
Danish Ahmed Mirza 2022-06-17 03:09:20 +05:30 committed by Danish
parent aa0b9f164e
commit 0f8920203d
4 changed files with 122 additions and 31 deletions

View File

@ -4,6 +4,8 @@ import moment from 'moment';
import { activateKeepAwake, deactivateKeepAwake } from 'expo-keep-awake';
// import Slider from '@react-native-community/slider';
import TrackPlayer, { Event, useTrackPlayerEvents, State, useProgress } from 'react-native-track-player';
import { Easing } from 'react-native-reanimated';
import { useMMKVStorage } from 'react-native-mmkv-storage';
import Touchable from '../../Touchable';
import Markdown from '../../../markdown';
@ -21,6 +23,7 @@ import { IAttachment } from '../../../../definitions';
import { TSupportedThemes } from '../../../../theme';
import { setupService } from './services';
import Slider from './Slider';
import { TracksStorage, addTrack, clearTracks, getCurrentTrack, setCurrentTrack } from './tracks';
interface IButton {
loading: boolean;
@ -106,40 +109,48 @@ IMessageAudioProps) => {
const { baseUrl, user } = useContext(MessageContext);
const { position, duration } = useProgress();
const { duration } = useProgress();
useEffect(() => {
setCurrentTime(position);
}, [position]);
const [tracks] = useMMKVStorage('tracks', TracksStorage);
let url = file.audio_url;
if (url && !url.startsWith('http')) {
url = `${baseUrl}${file.audio_url}`;
}
const track = {
id: `${url}?rc_uid=${user.id}&rc_token=${user.token}`,
url: `${url}?rc_uid=${user.id}&rc_token=${user.token}`,
title: file.title,
artist: file.author_name,
duration
};
useEffect(() => {
const setup = async () => {
setupService();
let url = file.audio_url;
if (url && !url.startsWith('http')) {
url = `${baseUrl}${file.audio_url}`;
}
setLoading(true);
try {
await TrackPlayer.add([
{
url: `${url}?rc_uid=${user.id}&rc_token=${user.token}`,
title: file.title,
artist: file.author_name,
duration
}
]);
} catch {
// Do nothing
}
await setupService();
addTrack({ trackId: track.id, title: file.title, artist: file.author_name, isPlaying: false });
setLoading(false);
};
setup();
return () => {
TrackPlayer.stop();
TrackPlayer.reset();
clearTracks();
};
}, []);
useEffect(() => {
const currentTrack = getCurrentTrack();
if (currentTrack && currentTrack.trackId !== track.id) {
setPaused(true);
}
}, [tracks]);
// useEffect(() => {
// setCurrentTime(position);
// }, [position]);
useEffect(() => {
playPause();
}, [paused]);
@ -161,7 +172,6 @@ IMessageAudioProps) => {
// do nothing
}
}
if (state === State.Ready) setLoading(false);
});
const getDuration = () => formatTime(currentTime || duration);
@ -171,11 +181,19 @@ IMessageAudioProps) => {
};
const playPause = () => {
const currentPlaying = getCurrentTrack();
try {
if (paused) {
TrackPlayer.pause();
} else {
if (currentPlaying?.trackId === track.id) {
TrackPlayer.pause();
}
} else if (currentPlaying?.trackId === track.id) {
TrackPlayer.play();
} else {
TrackPlayer.reset();
TrackPlayer.add(track);
TrackPlayer.play();
setCurrentTrack(track.id);
}
} catch {
// Do nothing
@ -183,9 +201,17 @@ IMessageAudioProps) => {
};
const onValueChange = async (value: number) => {
const currentTrack = getCurrentTrack();
try {
setCurrentTime(value);
await TrackPlayer.seekTo(value);
if (currentTrack && currentTrack.trackId === track.id) {
await TrackPlayer.seekTo(value);
} else {
TrackPlayer.reset();
TrackPlayer.add(track);
TrackPlayer.seekTo(value);
setCurrentTrack(track.id);
}
} catch {
// Do nothing
}
@ -204,6 +230,11 @@ IMessageAudioProps) => {
thumbColor = themes[theme].tintColor;
}
const sliderAnimatedConfig = {
duration: 250,
easing: Easing.linear
};
return (
<>
<Markdown
@ -228,6 +259,7 @@ IMessageAudioProps) => {
minimumTrackTintColor={themes[theme].tintColor}
disabled={isReply}
maximumTrackTintColor={themes[theme].auxiliaryText}
animationConfig={sliderAnimatedConfig}
// thumbImage={isIOS ? { uri: 'audio_thumb', scale } : undefined}
/>
{/* <Slider

View File

@ -50,6 +50,8 @@ export const playbackService = async () => {
export const setupService = async () => {
try {
await TrackPlayer.getCurrentTrack();
} catch {
await TrackPlayer.setupPlayer();
await TrackPlayer.updateOptions({
stopWithApp: false,
@ -66,7 +68,5 @@ export const setupService = async () => {
// Capability.SkipToNext
]
});
} catch {
// Do nothing
}
};

View File

@ -0,0 +1,58 @@
import MMKVStorage from 'react-native-mmkv-storage';
export const TracksStorage = new MMKVStorage.Loader().withInstanceID('tracks').initialize();
interface Track {
trackId: string;
isPlaying: boolean;
title?: string;
artist?: string;
}
export const initializeTracks = () => {
const tracks = TracksStorage.getArray('tracks');
if (!tracks) TracksStorage.setArray('tracks', []);
};
export const addTrack = (track: Track) => {
initializeTracks();
const tracks: Track[] = TracksStorage.getArray('tracks') || [];
if (tracks.find((t: Track) => t.trackId === track.trackId)) {
return;
}
TracksStorage.setArray('tracks', [...tracks, track]);
};
export const getTrack = (track: Track) => {
const tracks: Track[] = TracksStorage.getArray('tracks') || [];
return tracks.find((t: Track) => t.trackId === track.trackId);
};
export const updateTrack = (track: Track) => {
const tracks: Track[] = TracksStorage.getArray('tracks') || [];
const index = tracks.findIndex((t: Track) => t.trackId === track.trackId);
if (index !== -1) {
tracks[index] = track;
}
TracksStorage.setArray('tracks', tracks);
};
export const clearTracks = () => {
TracksStorage.setArray('tracks', []);
};
export const getCurrentTrack: () => Track | undefined = () => {
const tracks: Track[] = TracksStorage.getArray('tracks') || [];
const currentTrack = tracks.find((t: Track) => t.isPlaying);
return currentTrack;
};
export const setCurrentTrack = (trackId: string) => {
const tracks: Track[] = TracksStorage.getArray('tracks') || [];
const currentTrack = tracks.find((t: Track) => t.isPlaying);
const trackToToggle = tracks.find((t: Track) => t.trackId === trackId);
currentTrack && updateTrack({ ...currentTrack, isPlaying: false });
if (trackToToggle) {
updateTrack({ ...trackToToggle, isPlaying: true });
}
};

View File

@ -173,7 +173,8 @@ export default StyleSheet.create({
marginLeft: 12
},
sliderContainer: {
flex: 1
flex: 1,
paddingHorizontal: 10
},
track: {
justifyContent: 'center'
@ -185,7 +186,7 @@ export default StyleSheet.create({
sliderThumb: {
height: SLIDER_THUMB_RADIUS * 2,
width: SLIDER_THUMB_RADIUS * 2,
borderRadius: SLIDER_THUMB_RADIUS,
borderRadius: 2 * SLIDER_THUMB_RADIUS,
position: 'absolute',
zIndex: 2
}