removed the sound manipulation from Slider to manipulate only in the index
This commit is contained in:
parent
9c00ce08f4
commit
9066432ca2
|
@ -5,7 +5,7 @@ import styles from './styles';
|
|||
import { useTheme } from '../../../../theme';
|
||||
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 { colors } = useTheme();
|
||||
|
||||
|
@ -16,7 +16,11 @@ const AudioRate = ({ onChange }: { onChange: (value: number) => void }) => {
|
|||
};
|
||||
|
||||
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>
|
||||
</Touchable>
|
||||
);
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import React from 'react';
|
||||
import { LayoutChangeEvent, View, TextInput } from 'react-native';
|
||||
import { PanGestureHandler } from 'react-native-gesture-handler';
|
||||
import Animated, {
|
||||
SharedValue,
|
||||
runOnJS,
|
||||
useAnimatedGestureHandler,
|
||||
useAnimatedProps,
|
||||
|
@ -9,8 +10,6 @@ import Animated, {
|
|||
useDerivedValue,
|
||||
useSharedValue
|
||||
} from 'react-native-reanimated';
|
||||
import { Sound } from 'expo-av/build/Audio/Sound';
|
||||
import { AVPlaybackStatus } from 'expo-av';
|
||||
|
||||
import styles from './styles';
|
||||
import { useTheme } from '../../../../theme';
|
||||
|
@ -18,18 +17,15 @@ import { useTheme } from '../../../../theme';
|
|||
const AnimatedTextInput = Animated.createAnimatedComponent(TextInput);
|
||||
|
||||
interface ISlider {
|
||||
thumbColor: string;
|
||||
sound: Sound | null;
|
||||
onEndCallback: () => void;
|
||||
duration: SharedValue<number>;
|
||||
currentTime: SharedValue<number>;
|
||||
loaded: boolean;
|
||||
onChangeTime: (time: number) => Promise<void>;
|
||||
}
|
||||
|
||||
const Slider = ({ thumbColor = '', sound, onEndCallback }: ISlider) => {
|
||||
const [loaded, setLoaded] = useState(false);
|
||||
|
||||
const Slider = ({ currentTime, duration, loaded = false, onChangeTime }: ISlider) => {
|
||||
const { colors } = useTheme();
|
||||
|
||||
const duration = useSharedValue(0);
|
||||
const currentTime = useSharedValue(0);
|
||||
const maxWidth = useSharedValue(1);
|
||||
const x = useSharedValue(0);
|
||||
const current = useSharedValue('00:00');
|
||||
|
@ -37,46 +33,6 @@ const Slider = ({ thumbColor = '', sound, onEndCallback }: ISlider) => {
|
|||
const isHandlePan = 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(() => ({
|
||||
width: x.value,
|
||||
zIndex: 2
|
||||
|
@ -116,7 +72,7 @@ const Slider = ({ thumbColor = '', sound, onEndCallback }: ISlider) => {
|
|||
});
|
||||
|
||||
const wrapper = async (time: number) => {
|
||||
await sound?.setPositionAsync(Math.round(time * 1000));
|
||||
await onChangeTime(Math.round(time * 1000));
|
||||
onEndGestureHandler.value = false;
|
||||
};
|
||||
|
||||
|
@ -153,6 +109,8 @@ const Slider = ({ thumbColor = '', sound, onEndCallback }: ISlider) => {
|
|||
[current]
|
||||
);
|
||||
|
||||
const thumbColor = loaded ? colors.audioPlayerPrimary : colors.tintDisabled;
|
||||
|
||||
return (
|
||||
<View style={styles.sliderContainer}>
|
||||
<AnimatedTextInput
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import React, { useContext, useEffect, useRef, useState } from 'react';
|
||||
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 { Sound } from 'expo-av/build/Audio/Sound';
|
||||
import { useSharedValue } from 'react-native-reanimated';
|
||||
|
||||
import Touchable from '../../Touchable';
|
||||
import Markdown from '../../../markdown';
|
||||
|
@ -79,12 +80,65 @@ const MessageAudio = ({ file, getCustomEmoji, author, isReply, style }: IMessage
|
|||
const [paused, setPaused] = useState(true);
|
||||
const [cached, setCached] = useState(false);
|
||||
|
||||
const duration = useSharedValue(0);
|
||||
const currentTime = useSharedValue(0);
|
||||
|
||||
const { baseUrl, user } = useContext(MessageContext);
|
||||
const { colors } = useTheme();
|
||||
|
||||
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 = () => {
|
||||
console.log('🚀🚀🚀🚀🚀🚀🚀 ~ file: index.tsx:141 ~ pauseSound ~ pauseSound:');
|
||||
EventEmitter.removeListener(PAUSE_AUDIO, pauseSound);
|
||||
setPaused(true);
|
||||
playPause(true);
|
||||
|
@ -98,17 +152,8 @@ const MessageAudio = ({ file, getCustomEmoji, author, isReply, style }: IMessage
|
|||
return url;
|
||||
};
|
||||
|
||||
const onEnd = async () => {
|
||||
try {
|
||||
await sound.current?.stopAsync();
|
||||
setPaused(true);
|
||||
EventEmitter.removeListener(PAUSE_AUDIO, pauseSound);
|
||||
} catch {
|
||||
// do nothing
|
||||
}
|
||||
};
|
||||
|
||||
const togglePlayPause = () => {
|
||||
console.log('🚀 ~ file: index.tsx:156 ~ togglePlayPause ~ paused:', paused);
|
||||
setPaused(!paused);
|
||||
playPause(!paused);
|
||||
};
|
||||
|
@ -143,7 +188,7 @@ const MessageAudio = ({ file, getCustomEmoji, author, isReply, style }: IMessage
|
|||
type: 'audio',
|
||||
mimeType: file.audio_type
|
||||
});
|
||||
await sound.current?.loadAsync({ uri: audio });
|
||||
await loadAudio(audio);
|
||||
setLoading(false);
|
||||
setCached(true);
|
||||
}
|
||||
|
@ -190,8 +235,7 @@ const MessageAudio = ({ file, getCustomEmoji, author, isReply, style }: IMessage
|
|||
urlToCache: getUrl()
|
||||
});
|
||||
if (cachedAudioResult?.exists) {
|
||||
const { sound: soundLoaded } = await Audio.Sound.createAsync({ uri: cachedAudioResult.uri });
|
||||
sound.current = soundLoaded;
|
||||
await loadAudio(cachedAudioResult.uri);
|
||||
setLoading(false);
|
||||
setCached(true);
|
||||
return;
|
||||
|
@ -228,14 +272,6 @@ const MessageAudio = ({ file, getCustomEmoji, author, isReply, style }: IMessage
|
|||
if (!baseUrl) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let thumbColor;
|
||||
if (isReply) {
|
||||
thumbColor = colors.tintDisabled;
|
||||
} else {
|
||||
thumbColor = colors.audioPlayerPrimary;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<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} />
|
||||
<Slider sound={sound.current} thumbColor={thumbColor} onEndCallback={onEnd} />
|
||||
<AudioRate onChange={setRate} />
|
||||
<Slider currentTime={currentTime} duration={duration} loaded={!isReply && cached} onChangeTime={setPosition} />
|
||||
<AudioRate onChange={setRate} loaded={!isReply && cached} />
|
||||
</View>
|
||||
</>
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue