removed the sound manipulation from Slider to manipulate only in the index

This commit is contained in:
Reinaldo Neto 2023-08-10 17:36:26 -03:00
parent 9c00ce08f4
commit 9066432ca2
3 changed files with 76 additions and 78 deletions

View File

@ -5,7 +5,7 @@ import styles from './styles';
import { useTheme } from '../../../../theme'; import { useTheme } from '../../../../theme';
import Touchable from '../../Touchable'; import Touchable from '../../Touchable';
const AudioRate = ({ onChange }: { onChange: (value: number) => void }) => { const AudioRate = ({ onChange, loaded = false }: { onChange: (value: number) => void; loaded: boolean }) => {
const [rate, setRate] = useState(1.0); const [rate, setRate] = useState(1.0);
const { colors } = useTheme(); const { colors } = useTheme();
@ -16,7 +16,11 @@ const AudioRate = ({ onChange }: { onChange: (value: number) => void }) => {
}; };
return ( return (
<Touchable onPress={onPress} style={[styles.containerAudioRate, { backgroundColor: colors.audioRateBackground }]}> <Touchable
disabled={!loaded}
onPress={onPress}
style={[styles.containerAudioRate, { backgroundColor: colors.audioRateBackground }]}
>
<Text style={[styles.audioRateText, { color: colors.audioRateText }]}>{rate}x</Text> <Text style={[styles.audioRateText, { color: colors.audioRateText }]}>{rate}x</Text>
</Touchable> </Touchable>
); );

View File

@ -1,7 +1,8 @@
import React, { useEffect, useState } from 'react'; import React from 'react';
import { LayoutChangeEvent, View, TextInput } from 'react-native'; import { LayoutChangeEvent, View, TextInput } from 'react-native';
import { PanGestureHandler } from 'react-native-gesture-handler'; import { PanGestureHandler } from 'react-native-gesture-handler';
import Animated, { import Animated, {
SharedValue,
runOnJS, runOnJS,
useAnimatedGestureHandler, useAnimatedGestureHandler,
useAnimatedProps, useAnimatedProps,
@ -9,8 +10,6 @@ import Animated, {
useDerivedValue, useDerivedValue,
useSharedValue useSharedValue
} from 'react-native-reanimated'; } from 'react-native-reanimated';
import { Sound } from 'expo-av/build/Audio/Sound';
import { AVPlaybackStatus } from 'expo-av';
import styles from './styles'; import styles from './styles';
import { useTheme } from '../../../../theme'; import { useTheme } from '../../../../theme';
@ -18,18 +17,15 @@ import { useTheme } from '../../../../theme';
const AnimatedTextInput = Animated.createAnimatedComponent(TextInput); const AnimatedTextInput = Animated.createAnimatedComponent(TextInput);
interface ISlider { interface ISlider {
thumbColor: string; duration: SharedValue<number>;
sound: Sound | null; currentTime: SharedValue<number>;
onEndCallback: () => void; loaded: boolean;
onChangeTime: (time: number) => Promise<void>;
} }
const Slider = ({ thumbColor = '', sound, onEndCallback }: ISlider) => { const Slider = ({ currentTime, duration, loaded = false, onChangeTime }: ISlider) => {
const [loaded, setLoaded] = useState(false);
const { colors } = useTheme(); const { colors } = useTheme();
const duration = useSharedValue(0);
const currentTime = useSharedValue(0);
const maxWidth = useSharedValue(1); const maxWidth = useSharedValue(1);
const x = useSharedValue(0); const x = useSharedValue(0);
const current = useSharedValue('00:00'); const current = useSharedValue('00:00');
@ -37,46 +33,6 @@ const Slider = ({ thumbColor = '', sound, onEndCallback }: ISlider) => {
const isHandlePan = useSharedValue(false); const isHandlePan = useSharedValue(false);
const onEndGestureHandler = useSharedValue(false); const onEndGestureHandler = useSharedValue(false);
const onPlaybackStatusUpdate = (status: AVPlaybackStatus) => {
if (status) {
onLoad(status);
onProgress(status);
onEnd(status);
}
};
useEffect(() => {
if (sound) {
sound.setOnPlaybackStatusUpdate(onPlaybackStatusUpdate);
}
}, [sound]);
const onLoad = (data: AVPlaybackStatus) => {
if (data.isLoaded && data.durationMillis) {
const durationSeconds = data.durationMillis / 1000;
duration.value = durationSeconds > 0 ? durationSeconds : 0;
setLoaded(true);
}
};
const onProgress = (data: AVPlaybackStatus) => {
if (data.isLoaded) {
const currentSecond = data.positionMillis / 1000;
if (currentSecond <= duration.value) {
currentTime.value = currentSecond;
}
}
};
const onEnd = (data: AVPlaybackStatus) => {
if (data.isLoaded) {
if (data.didJustFinish) {
onEndCallback();
currentTime.value = 0;
}
}
};
const styleLine = useAnimatedStyle(() => ({ const styleLine = useAnimatedStyle(() => ({
width: x.value, width: x.value,
zIndex: 2 zIndex: 2
@ -116,7 +72,7 @@ const Slider = ({ thumbColor = '', sound, onEndCallback }: ISlider) => {
}); });
const wrapper = async (time: number) => { const wrapper = async (time: number) => {
await sound?.setPositionAsync(Math.round(time * 1000)); await onChangeTime(Math.round(time * 1000));
onEndGestureHandler.value = false; onEndGestureHandler.value = false;
}; };
@ -153,6 +109,8 @@ const Slider = ({ thumbColor = '', sound, onEndCallback }: ISlider) => {
[current] [current]
); );
const thumbColor = loaded ? colors.audioPlayerPrimary : colors.tintDisabled;
return ( return (
<View style={styles.sliderContainer}> <View style={styles.sliderContainer}>
<AnimatedTextInput <AnimatedTextInput

View File

@ -1,8 +1,9 @@
import React, { useContext, useEffect, useRef, useState } from 'react'; import React, { useContext, useEffect, useRef, useState } from 'react';
import { StyleProp, TextStyle, View } from 'react-native'; import { StyleProp, TextStyle, View } from 'react-native';
import { Audio, InterruptionModeAndroid, InterruptionModeIOS } from 'expo-av'; import { AVPlaybackStatus, Audio, InterruptionModeAndroid, InterruptionModeIOS } from 'expo-av';
import { activateKeepAwakeAsync, deactivateKeepAwake } from 'expo-keep-awake'; import { activateKeepAwakeAsync, deactivateKeepAwake } from 'expo-keep-awake';
import { Sound } from 'expo-av/build/Audio/Sound'; import { Sound } from 'expo-av/build/Audio/Sound';
import { useSharedValue } from 'react-native-reanimated';
import Touchable from '../../Touchable'; import Touchable from '../../Touchable';
import Markdown from '../../../markdown'; import Markdown from '../../../markdown';
@ -79,12 +80,65 @@ const MessageAudio = ({ file, getCustomEmoji, author, isReply, style }: IMessage
const [paused, setPaused] = useState(true); const [paused, setPaused] = useState(true);
const [cached, setCached] = useState(false); const [cached, setCached] = useState(false);
const duration = useSharedValue(0);
const currentTime = useSharedValue(0);
const { baseUrl, user } = useContext(MessageContext); const { baseUrl, user } = useContext(MessageContext);
const { colors } = useTheme(); const { colors } = useTheme();
const sound = useRef<Sound | null>(null); const sound = useRef<Sound | null>(null);
const onPlaybackStatusUpdate = (status: AVPlaybackStatus) => {
if (status) {
onLoad(status);
onProgress(status);
onEnd(status);
}
};
const loadAudio = async (audio: string) => {
const { sound: soundLoaded } = await Audio.Sound.createAsync({ uri: audio });
sound.current = soundLoaded;
sound.current.setOnPlaybackStatusUpdate(onPlaybackStatusUpdate);
};
const onLoad = (data: AVPlaybackStatus) => {
if (data.isLoaded && data.durationMillis) {
const durationSeconds = data.durationMillis / 1000;
duration.value = durationSeconds > 0 ? durationSeconds : 0;
}
};
const onProgress = (data: AVPlaybackStatus) => {
if (data.isLoaded) {
const currentSecond = data.positionMillis / 1000;
if (currentSecond <= duration.value) {
currentTime.value = currentSecond;
}
}
};
const onEnd = async (data: AVPlaybackStatus) => {
if (data.isLoaded) {
if (data.didJustFinish) {
try {
await sound.current?.stopAsync();
setPaused(true);
EventEmitter.removeListener(PAUSE_AUDIO, pauseSound);
currentTime.value = 0;
} catch {
// do nothing
}
}
}
};
const setPosition = async (time: number) => {
await sound.current?.setPositionAsync(time);
};
const pauseSound = () => { const pauseSound = () => {
console.log('🚀🚀🚀🚀🚀🚀🚀 ~ file: index.tsx:141 ~ pauseSound ~ pauseSound:');
EventEmitter.removeListener(PAUSE_AUDIO, pauseSound); EventEmitter.removeListener(PAUSE_AUDIO, pauseSound);
setPaused(true); setPaused(true);
playPause(true); playPause(true);
@ -98,17 +152,8 @@ const MessageAudio = ({ file, getCustomEmoji, author, isReply, style }: IMessage
return url; return url;
}; };
const onEnd = async () => {
try {
await sound.current?.stopAsync();
setPaused(true);
EventEmitter.removeListener(PAUSE_AUDIO, pauseSound);
} catch {
// do nothing
}
};
const togglePlayPause = () => { const togglePlayPause = () => {
console.log('🚀 ~ file: index.tsx:156 ~ togglePlayPause ~ paused:', paused);
setPaused(!paused); setPaused(!paused);
playPause(!paused); playPause(!paused);
}; };
@ -143,7 +188,7 @@ const MessageAudio = ({ file, getCustomEmoji, author, isReply, style }: IMessage
type: 'audio', type: 'audio',
mimeType: file.audio_type mimeType: file.audio_type
}); });
await sound.current?.loadAsync({ uri: audio }); await loadAudio(audio);
setLoading(false); setLoading(false);
setCached(true); setCached(true);
} }
@ -190,8 +235,7 @@ const MessageAudio = ({ file, getCustomEmoji, author, isReply, style }: IMessage
urlToCache: getUrl() urlToCache: getUrl()
}); });
if (cachedAudioResult?.exists) { if (cachedAudioResult?.exists) {
const { sound: soundLoaded } = await Audio.Sound.createAsync({ uri: cachedAudioResult.uri }); await loadAudio(cachedAudioResult.uri);
sound.current = soundLoaded;
setLoading(false); setLoading(false);
setCached(true); setCached(true);
return; return;
@ -228,14 +272,6 @@ const MessageAudio = ({ file, getCustomEmoji, author, isReply, style }: IMessage
if (!baseUrl) { if (!baseUrl) {
return null; return null;
} }
let thumbColor;
if (isReply) {
thumbColor = colors.tintDisabled;
} else {
thumbColor = colors.audioPlayerPrimary;
}
return ( return (
<> <>
<Markdown msg={file.description} style={[isReply && style]} username={user.username} getCustomEmoji={getCustomEmoji} /> <Markdown msg={file.description} style={[isReply && style]} username={user.username} getCustomEmoji={getCustomEmoji} />
@ -246,8 +282,8 @@ const MessageAudio = ({ file, getCustomEmoji, author, isReply, style }: IMessage
]} ]}
> >
<Button disabled={isReply} loading={loading} paused={paused} cached={cached} onPress={onPress} /> <Button disabled={isReply} loading={loading} paused={paused} cached={cached} onPress={onPress} />
<Slider sound={sound.current} thumbColor={thumbColor} onEndCallback={onEnd} /> <Slider currentTime={currentTime} duration={duration} loaded={!isReply && cached} onChangeTime={setPosition} />
<AudioRate onChange={setRate} /> <AudioRate onChange={setRate} loaded={!isReply && cached} />
</View> </View>
</> </>
); );