From 4cb6674eb4bf18ec498640d2ce2d910f196deee1 Mon Sep 17 00:00:00 2001 From: Danish Ahmed Mirza Date: Sun, 24 Jul 2022 18:38:48 +0530 Subject: [PATCH] Add onSlidingStart and onSLidingEnd callbacks --- .../message/Components/Audio/Slider.tsx | 8 +- .../message/Components/Audio/index.tsx | 129 +++++++++++------- .../message/Components/Audio/services.ts | 54 ++------ .../message/Components/Audio/tracks.ts | 58 -------- .../message/Components/Audio/tracksStorage.ts | 9 ++ jest.setup.js | 59 ++++++++ 6 files changed, 165 insertions(+), 152 deletions(-) delete mode 100644 app/containers/message/Components/Audio/tracks.ts create mode 100644 app/containers/message/Components/Audio/tracksStorage.ts diff --git a/app/containers/message/Components/Audio/Slider.tsx b/app/containers/message/Components/Audio/Slider.tsx index 592b4af22..04b6ac8ca 100644 --- a/app/containers/message/Components/Audio/Slider.tsx +++ b/app/containers/message/Components/Audio/Slider.tsx @@ -10,7 +10,9 @@ import { useTheme } from '../../../../theme'; interface ISliderProps { value: number; maximumValue: number; - onValueChange: (value: number) => Promise; + onValueChange: (value: number) => void; + onSlidingStart: () => void; + onSlidingEnd: (value: number) => void; thumbTintColor?: string; minimumTrackTintColor?: string; maximumTrackTintColor?: string; @@ -25,6 +27,8 @@ const Slider = React.memo( value, maximumValue, onValueChange, + onSlidingStart, + onSlidingEnd, thumbTintColor, minimumTrackTintColor, maximumTrackTintColor, @@ -68,6 +72,7 @@ const Slider = React.memo( .hitSlop({ horizontal: 5, vertical: 20 }) .onStart(() => { setSliding(true); + onSlidingStart(); sliderThumbWidth.value = withTiming(3 * SLIDER_THUMB_RADIUS, { duration: 100 }); }) .onChange(e => { @@ -78,6 +83,7 @@ const Slider = React.memo( sliderThumbWidth.value = withTiming(2 * SLIDER_THUMB_RADIUS, { duration: 100 }); currentValue.value = equivalentValue(clamp(e.x, 0, sliderWidth)); onValueChange(equivalentValue(clamp(e.x, 0, sliderWidth))); + onSlidingEnd(equivalentValue(clamp(e.x, 0, sliderWidth))); setSliding(false); }); diff --git a/app/containers/message/Components/Audio/index.tsx b/app/containers/message/Components/Audio/index.tsx index a35f328ac..36a20fca8 100644 --- a/app/containers/message/Components/Audio/index.tsx +++ b/app/containers/message/Components/Audio/index.tsx @@ -2,10 +2,9 @@ import React, { useContext, useEffect, useState } from 'react'; import { StyleProp, StyleSheet, Text, TextStyle, View } from 'react-native'; import moment from 'moment'; import { activateKeepAwake, deactivateKeepAwake } from 'expo-keep-awake'; -// import Slider from '@react-native-community/slider'; +import { Audio, AVPlaybackStatus } from 'expo-av'; 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'; @@ -23,7 +22,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'; +import { useTracks } from './tracksStorage'; interface IButton { loading: boolean; @@ -103,15 +102,16 @@ const MessageAudio = ({ getCustomEmoji }: // scale IMessageAudioProps) => { - const [loading, setLoading] = useState(false); - const [paused, setPaused] = useState(true); - const [currentTime, setCurrentTime] = useState(0); - const { baseUrl, user } = useContext(MessageContext); - const { duration } = useProgress(); + const [loading, setLoading] = useState(false); + const [paused, setPaused] = useState(true); + const [currentPosition, setCurrentPosition] = useState(0); + const [duration, setDuration] = useState(0); + const [isSliding, setIsSliding] = useState(false); + const { position } = useProgress(); - const [tracks] = useMMKVStorage('tracks', TracksStorage); + const [currentTrackId, setCurrentTrackId] = useTracks('currentTrackId'); let url = file.audio_url; if (url && !url.startsWith('http')) { @@ -122,34 +122,48 @@ IMessageAudioProps) => { 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 + artist: file.author_name + }; + + const updateTrackDuration = (status: AVPlaybackStatus) => { + if (status.isLoaded && status.durationMillis) { + const trackDuration = status.durationMillis / 1000; + setDuration(trackDuration > 0 ? trackDuration : 0); + } }; useEffect(() => { const setup = async () => { setLoading(true); - await setupService(); - addTrack({ trackId: track.id, title: file.title, artist: file.author_name, isPlaying: false }); + try { + await setupService(); + const sound = new Audio.Sound(); + sound.setOnPlaybackStatusUpdate(updateTrackDuration); + await sound.loadAsync({ uri: `${url}?rc_uid=${user.id}&rc_token=${user.token}` }); + } catch { + // Do nothing + } setLoading(false); }; setup(); return () => { - TrackPlayer.reset(); - clearTracks(); + TrackPlayer.destroy(); + setCurrentTrackId(null); }; }, []); useEffect(() => { - const currentTrack = getCurrentTrack(); - if (currentTrack && currentTrack.trackId !== track.id) { + if (currentTrackId && currentTrackId !== track.id) { + setCurrentPosition(0); setPaused(true); } - }, [tracks]); + }, [currentTrackId]); - // useEffect(() => { - // setCurrentTime(position); - // }, [position]); + useEffect(() => { + if (currentTrackId === track.id && !isSliding) { + setCurrentPosition(position); + } + }, [position]); useEffect(() => { playPause(); @@ -161,7 +175,7 @@ IMessageAudioProps) => { } else { activateKeepAwake(); } - }, [paused, currentTime, duration, file, loading, theme]); + }, [paused, currentPosition, duration, file, loading, theme]); useTrackPlayerEvents([Event.PlaybackState], ({ state }) => { if (state === State.Stopped) { @@ -172,51 +186,72 @@ IMessageAudioProps) => { // do nothing } } + if (state === State.Paused) { + setPaused(true); + } + if (state === State.Playing && currentTrackId?.trackId === track.id) { + setPaused(false); + } }); - const getDuration = () => formatTime(currentTime || duration); + const getDuration = () => formatTime(currentPosition || duration); const togglePlayPause = () => { setPaused(!paused); }; - const playPause = () => { - const currentPlaying = getCurrentTrack(); + const playPause = async () => { try { if (paused) { - if (currentPlaying?.trackId === track.id) { + if (currentTrackId === track.id) { TrackPlayer.pause(); } - } else if (currentPlaying?.trackId === track.id) { + } else if (currentTrackId === track.id) { TrackPlayer.play(); } else { TrackPlayer.reset(); - TrackPlayer.add(track); + await TrackPlayer.add(track); TrackPlayer.play(); - setCurrentTrack(track.id); + setCurrentTrackId(track.id); } } catch { // Do nothing } }; - const onValueChange = async (value: number) => { - const currentTrack = getCurrentTrack(); + const onValueChange = (value: number) => { + setCurrentPosition(value); try { - setCurrentTime(value); - if (currentTrack && currentTrack.trackId === track.id) { - await TrackPlayer.seekTo(value); - } else { - TrackPlayer.reset(); - TrackPlayer.add(track); - TrackPlayer.seekTo(value); - setCurrentTrack(track.id); + if (currentTrackId === track.id && !paused && isSliding) { + setPaused(true); + TrackPlayer.pause(); } } catch { // Do nothing } }; + const onSlidingEnd = async (value: number) => { + setCurrentPosition(value); + try { + if (currentTrackId === track.id) { + await TrackPlayer.seekTo(value); + } else { + TrackPlayer.reset(); + await TrackPlayer.add(track); + await TrackPlayer.seekTo(value); + setCurrentTrackId(track.id); + } + if (paused) { + TrackPlayer.play(); + setPaused(false); + } + } catch { + // Do nothing + } + setIsSliding(false); + }; + const { description } = file; if (!baseUrl) { @@ -252,7 +287,7 @@ IMessageAudioProps) => { ]}>