refactor audio component
This commit is contained in:
parent
8b053f630e
commit
2b379ee281
|
@ -11,18 +11,18 @@ interface IButton {
|
|||
paused: boolean;
|
||||
disabled?: boolean;
|
||||
onPress: () => void;
|
||||
cached: boolean;
|
||||
isReadyToPlay: boolean;
|
||||
}
|
||||
|
||||
const BUTTON_HIT_SLOP = { top: 12, right: 12, bottom: 12, left: 12 };
|
||||
|
||||
type TCustomIconName = 'arrow-down' | 'play-shape-filled' | 'pause-shape-filled';
|
||||
|
||||
const PlayButton = React.memo(({ loading, paused, onPress, disabled, cached }: IButton) => {
|
||||
const PlayButton = React.memo(({ loading, paused, onPress, disabled, isReadyToPlay }: IButton) => {
|
||||
const { colors } = useTheme();
|
||||
|
||||
let customIconName: TCustomIconName = 'arrow-down';
|
||||
if (cached) {
|
||||
if (isReadyToPlay) {
|
||||
customIconName = paused ? 'play-shape-filled' : 'pause-shape-filled';
|
||||
}
|
||||
return (
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { StyleProp, TextStyle, View } from 'react-native';
|
||||
import { View } from 'react-native';
|
||||
import { AVPlaybackStatus } from 'expo-av';
|
||||
import { activateKeepAwake, deactivateKeepAwake } from 'expo-keep-awake';
|
||||
import { useSharedValue } from 'react-native-reanimated';
|
||||
|
||||
import { IAttachment, IUserMessage } from '../../definitions';
|
||||
import { useTheme } from '../../theme';
|
||||
import { downloadMediaFile, getMediaCache } from '../../lib/methods/handleMediaDownload';
|
||||
import { fetchAutoDownloadEnabled } from '../../lib/methods/autoDownloadPreference';
|
||||
import styles from './styles';
|
||||
import Seek from './Seek';
|
||||
import PlaybackSpeed from './PlaybackSpeed';
|
||||
|
@ -15,19 +12,21 @@ import PlayButton from './PlayButton';
|
|||
import audioPlayer from '../../lib/methods/audioPlayer';
|
||||
|
||||
interface IAudioPlayerProps {
|
||||
file: IAttachment;
|
||||
isReply?: boolean;
|
||||
style?: StyleProp<TextStyle>[];
|
||||
author?: IUserMessage;
|
||||
msg?: string;
|
||||
baseUrl: string;
|
||||
user: any;
|
||||
fileUri: string;
|
||||
loading: boolean;
|
||||
isReadyToPlay: boolean;
|
||||
disabled?: boolean;
|
||||
onPressCallback?: Function;
|
||||
}
|
||||
|
||||
const AudioPlayer = ({ file, author, isReply = false, baseUrl, user }: IAudioPlayerProps) => {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const AudioPlayer = ({
|
||||
fileUri,
|
||||
disabled = false,
|
||||
loading = true,
|
||||
isReadyToPlay = false,
|
||||
onPressCallback = () => {}
|
||||
}: IAudioPlayerProps) => {
|
||||
const [paused, setPaused] = useState(true);
|
||||
const [cached, setCached] = useState(false);
|
||||
const [rate, setRate] = useState(1);
|
||||
|
||||
const duration = useSharedValue(0);
|
||||
|
@ -45,12 +44,6 @@ const AudioPlayer = ({ file, author, isReply = false, baseUrl, user }: IAudioPla
|
|||
}
|
||||
};
|
||||
|
||||
const loadAudio = async (audio: string) => {
|
||||
await audioPlayer.loadAudio(audio);
|
||||
audioUri.current = audio;
|
||||
audioPlayer.setOnPlaybackStatusUpdate(audio, onPlaybackStatusUpdate);
|
||||
};
|
||||
|
||||
const onPlaying = (data: AVPlaybackStatus) => {
|
||||
if (data.isLoaded && data.isPlaying) {
|
||||
setPaused(false);
|
||||
|
@ -88,14 +81,6 @@ const AudioPlayer = ({ file, author, isReply = false, baseUrl, user }: IAudioPla
|
|||
await audioPlayer.setPositionAsync(audioUri.current, time);
|
||||
};
|
||||
|
||||
const getUrl = () => {
|
||||
let url = file.audio_url;
|
||||
if (url && !url.startsWith('http')) {
|
||||
url = `${baseUrl}${file.audio_url}`;
|
||||
}
|
||||
return url;
|
||||
};
|
||||
|
||||
const togglePlayPause = async () => {
|
||||
try {
|
||||
if (!paused) {
|
||||
|
@ -112,76 +97,24 @@ const AudioPlayer = ({ file, author, isReply = false, baseUrl, user }: IAudioPla
|
|||
await audioPlayer.setRateAsync(audioUri.current, value);
|
||||
};
|
||||
|
||||
const handleDownload = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const url = getUrl();
|
||||
if (url) {
|
||||
const audio = await downloadMediaFile({
|
||||
downloadUrl: `${url}?rc_uid=${user.id}&rc_token=${user.token}`,
|
||||
type: 'audio',
|
||||
mimeType: file.audio_type
|
||||
});
|
||||
await loadAudio(audio);
|
||||
setLoading(false);
|
||||
setCached(true);
|
||||
}
|
||||
} catch {
|
||||
setLoading(false);
|
||||
setCached(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleAutoDownload = async () => {
|
||||
const url = getUrl();
|
||||
try {
|
||||
if (url) {
|
||||
const isCurrentUserAuthor = author?._id === user.id;
|
||||
const isAutoDownloadEnabled = fetchAutoDownloadEnabled('audioPreferenceDownload');
|
||||
if (isAutoDownloadEnabled || isCurrentUserAuthor) {
|
||||
await handleDownload();
|
||||
return;
|
||||
}
|
||||
setLoading(false);
|
||||
setCached(false);
|
||||
}
|
||||
} catch {
|
||||
// Do nothing
|
||||
}
|
||||
};
|
||||
|
||||
const onPress = () => {
|
||||
onPressCallback();
|
||||
if (loading) {
|
||||
return;
|
||||
}
|
||||
if (cached) {
|
||||
if (isReadyToPlay) {
|
||||
togglePlayPause();
|
||||
return;
|
||||
}
|
||||
handleDownload();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const handleCache = async () => {
|
||||
const cachedAudioResult = await getMediaCache({
|
||||
type: 'audio',
|
||||
mimeType: file.audio_type,
|
||||
urlToCache: getUrl()
|
||||
});
|
||||
if (cachedAudioResult?.exists) {
|
||||
await loadAudio(cachedAudioResult.uri);
|
||||
setLoading(false);
|
||||
setCached(true);
|
||||
return;
|
||||
}
|
||||
if (isReply) {
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
await handleAutoDownload();
|
||||
const loadAudio = async (audio: string) => {
|
||||
await audioPlayer.loadAudio(audio);
|
||||
audioUri.current = audio;
|
||||
audioPlayer.setOnPlaybackStatusUpdate(audio, onPlaybackStatusUpdate);
|
||||
};
|
||||
handleCache();
|
||||
}, []);
|
||||
loadAudio(fileUri);
|
||||
}, [fileUri]);
|
||||
|
||||
useEffect(() => {
|
||||
if (paused) {
|
||||
|
@ -191,15 +124,12 @@ const AudioPlayer = ({ file, author, isReply = false, baseUrl, user }: IAudioPla
|
|||
}
|
||||
}, [paused]);
|
||||
|
||||
if (!baseUrl) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<View style={[styles.audioContainer, { backgroundColor: colors.surfaceTint, borderColor: colors.strokeExtraLight }]}>
|
||||
<PlayButton disabled={isReply} loading={loading} paused={paused} cached={cached} onPress={onPress} />
|
||||
<Seek currentTime={currentTime} duration={duration} loaded={!isReply && cached} onChangeTime={setPosition} />
|
||||
<PlaybackSpeed onChange={onChangeRate} loaded={!isReply && cached} rate={rate} />
|
||||
<PlayButton disabled={disabled} loading={loading} paused={paused} isReadyToPlay={isReadyToPlay} onPress={onPress} />
|
||||
<Seek currentTime={currentTime} duration={duration} loaded={!disabled && isReadyToPlay} onChangeTime={setPosition} />
|
||||
<PlaybackSpeed onChange={onChangeRate} loaded={!disabled && isReadyToPlay} rate={rate} />
|
||||
</View>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
import React, { useContext } from 'react';
|
||||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import { StyleProp, TextStyle } from 'react-native';
|
||||
|
||||
import Markdown from '../../../markdown';
|
||||
import MessageContext from '../../Context';
|
||||
import { TGetCustomEmoji } from '../../../../definitions/IEmoji';
|
||||
import { IAttachment, IUserMessage } from '../../../../definitions';
|
||||
import { downloadMediaFile, getMediaCache } from '../../../../lib/methods/handleMediaDownload';
|
||||
import { fetchAutoDownloadEnabled } from '../../../../lib/methods/autoDownloadPreference';
|
||||
import AudioPlayer from '../../../AudioPlayer';
|
||||
|
||||
interface IMessageAudioProps {
|
||||
|
@ -17,15 +19,93 @@ interface IMessageAudioProps {
|
|||
}
|
||||
|
||||
const MessageAudio = ({ file, getCustomEmoji, author, isReply, style, msg }: IMessageAudioProps) => {
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [cached, setCached] = useState(false);
|
||||
const [fileUri, setFileUri] = useState('');
|
||||
|
||||
const { baseUrl, user } = useContext(MessageContext);
|
||||
|
||||
const getUrl = () => {
|
||||
let url = file.audio_url;
|
||||
if (url && !url.startsWith('http')) {
|
||||
url = `${baseUrl}${file.audio_url}`;
|
||||
}
|
||||
return url;
|
||||
};
|
||||
|
||||
const onPress = () => {
|
||||
if (!cached) {
|
||||
handleDownload();
|
||||
}
|
||||
};
|
||||
|
||||
const handleDownload = async () => {
|
||||
setLoading(true);
|
||||
try {
|
||||
const url = getUrl();
|
||||
if (url) {
|
||||
const audio = await downloadMediaFile({
|
||||
downloadUrl: `${url}?rc_uid=${user.id}&rc_token=${user.token}`,
|
||||
type: 'audio',
|
||||
mimeType: file.audio_type
|
||||
});
|
||||
setFileUri(audio);
|
||||
setLoading(false);
|
||||
setCached(true);
|
||||
}
|
||||
} catch {
|
||||
setLoading(false);
|
||||
setCached(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleAutoDownload = async () => {
|
||||
const url = getUrl();
|
||||
try {
|
||||
if (url) {
|
||||
const isCurrentUserAuthor = author?._id === user.id;
|
||||
const isAutoDownloadEnabled = fetchAutoDownloadEnabled('audioPreferenceDownload');
|
||||
if (isAutoDownloadEnabled || isCurrentUserAuthor) {
|
||||
await handleDownload();
|
||||
return;
|
||||
}
|
||||
setLoading(false);
|
||||
setCached(false);
|
||||
}
|
||||
} catch {
|
||||
// Do nothing
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const handleCache = async () => {
|
||||
const cachedAudioResult = await getMediaCache({
|
||||
type: 'audio',
|
||||
mimeType: file.audio_type,
|
||||
urlToCache: getUrl()
|
||||
});
|
||||
if (cachedAudioResult?.exists) {
|
||||
setFileUri(cachedAudioResult.uri);
|
||||
setLoading(false);
|
||||
setCached(true);
|
||||
return;
|
||||
}
|
||||
if (isReply) {
|
||||
setLoading(false);
|
||||
return;
|
||||
}
|
||||
await handleAutoDownload();
|
||||
};
|
||||
handleCache();
|
||||
}, []);
|
||||
|
||||
if (!baseUrl) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<Markdown msg={msg} style={[isReply && style]} username={user.username} getCustomEmoji={getCustomEmoji} />
|
||||
<AudioPlayer file={file} baseUrl={baseUrl} user={user} author={author} isReply={isReply} />
|
||||
<AudioPlayer fileUri={fileUri} isReadyToPlay={cached} loading={loading} disabled={isReply} onPressCallback={onPress} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue