remove mediaType and refactor audio and image
This commit is contained in:
parent
1be2326686
commit
b6ae55e57f
|
@ -19,7 +19,7 @@ import { withDimensions } from '../../dimensions';
|
||||||
import { TGetCustomEmoji } from '../../definitions/IEmoji';
|
import { TGetCustomEmoji } from '../../definitions/IEmoji';
|
||||||
import { IAttachment, IUserMessage } from '../../definitions';
|
import { IAttachment, IUserMessage } from '../../definitions';
|
||||||
import { TSupportedThemes, useTheme } from '../../theme';
|
import { TSupportedThemes, useTheme } from '../../theme';
|
||||||
import { downloadMediaFile, searchMediaFileAsync } from '../../lib/methods/handleMediaDownload';
|
import { downloadMediaFile, getMediaCache } from '../../lib/methods/handleMediaDownload';
|
||||||
import EventEmitter from '../../lib/methods/helpers/events';
|
import EventEmitter from '../../lib/methods/helpers/events';
|
||||||
import { PAUSE_AUDIO } from './constants';
|
import { PAUSE_AUDIO } from './constants';
|
||||||
import { fetchAutoDownloadEnabled } from '../../lib/methods/autoDownloadPreference';
|
import { fetchAutoDownloadEnabled } from '../../lib/methods/autoDownloadPreference';
|
||||||
|
@ -130,7 +130,7 @@ class MessageAudio extends React.Component<IMessageAudioProps, IMessageAudioStat
|
||||||
currentTime: 0,
|
currentTime: 0,
|
||||||
duration: 0,
|
duration: 0,
|
||||||
paused: true,
|
paused: true,
|
||||||
cached: true
|
cached: false
|
||||||
};
|
};
|
||||||
|
|
||||||
this.sound = new Audio.Sound();
|
this.sound = new Audio.Sound();
|
||||||
|
@ -144,7 +144,7 @@ class MessageAudio extends React.Component<IMessageAudioProps, IMessageAudioStat
|
||||||
|
|
||||||
async componentDidMount() {
|
async componentDidMount() {
|
||||||
const { file, isReply } = this.props;
|
const { file, isReply } = this.props;
|
||||||
const cachedAudioResult = await searchMediaFileAsync({
|
const cachedAudioResult = await getMediaCache({
|
||||||
type: 'audio',
|
type: 'audio',
|
||||||
mimeType: file.audio_type,
|
mimeType: file.audio_type,
|
||||||
urlToCache: this.getUrl()
|
urlToCache: this.getUrl()
|
||||||
|
@ -152,45 +152,16 @@ class MessageAudio extends React.Component<IMessageAudioProps, IMessageAudioStat
|
||||||
this.filePath = cachedAudioResult.filePath;
|
this.filePath = cachedAudioResult.filePath;
|
||||||
if (cachedAudioResult?.file?.exists) {
|
if (cachedAudioResult?.file?.exists) {
|
||||||
await this.sound.loadAsync({ uri: cachedAudioResult.file.uri });
|
await this.sound.loadAsync({ uri: cachedAudioResult.file.uri });
|
||||||
return this.setState({ loading: false });
|
this.setState({ loading: false, cached: true });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isReply) {
|
||||||
|
this.setState({ loading: false });
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (isReply) return;
|
|
||||||
await this.handleAutoDownload();
|
await this.handleAutoDownload();
|
||||||
}
|
}
|
||||||
|
|
||||||
getUrl = () => {
|
|
||||||
const { file } = this.props;
|
|
||||||
// @ts-ignore can't use declare to type this
|
|
||||||
const { baseUrl } = this.context;
|
|
||||||
|
|
||||||
let url = file.audio_url;
|
|
||||||
if (url && !url.startsWith('http')) {
|
|
||||||
url = `${baseUrl}${file.audio_url}`;
|
|
||||||
}
|
|
||||||
return url as string;
|
|
||||||
};
|
|
||||||
|
|
||||||
handleAutoDownload = async () => {
|
|
||||||
const { author } = this.props;
|
|
||||||
// @ts-ignore can't use declare to type this
|
|
||||||
const { user } = this.context;
|
|
||||||
const url = this.getUrl();
|
|
||||||
try {
|
|
||||||
if (url) {
|
|
||||||
const isCurrentUserAuthor = author?._id === user.id;
|
|
||||||
const isAutoDownloadEnabled = fetchAutoDownloadEnabled('audioPreferenceDownload');
|
|
||||||
if (isAutoDownloadEnabled || isCurrentUserAuthor) {
|
|
||||||
await this.handleDownload();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.setState({ loading: false, cached: false });
|
|
||||||
}
|
|
||||||
} catch {
|
|
||||||
// Do nothing
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps: IMessageAudioProps, nextState: IMessageAudioState) {
|
shouldComponentUpdate(nextProps: IMessageAudioProps, nextState: IMessageAudioState) {
|
||||||
const { currentTime, duration, paused, loading, cached } = this.state;
|
const { currentTime, duration, paused, loading, cached } = this.state;
|
||||||
const { file, theme } = this.props;
|
const { file, theme } = this.props;
|
||||||
|
@ -236,6 +207,39 @@ class MessageAudio extends React.Component<IMessageAudioProps, IMessageAudioStat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getUrl = () => {
|
||||||
|
const { file } = this.props;
|
||||||
|
// @ts-ignore can't use declare to type this
|
||||||
|
const { baseUrl } = this.context;
|
||||||
|
|
||||||
|
let url = file.audio_url;
|
||||||
|
if (url && !url.startsWith('http')) {
|
||||||
|
url = `${baseUrl}${file.audio_url}`;
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
};
|
||||||
|
|
||||||
|
handleAutoDownload = async () => {
|
||||||
|
const { author } = this.props;
|
||||||
|
// @ts-ignore can't use declare to type this
|
||||||
|
const { user } = this.context;
|
||||||
|
const url = this.getUrl();
|
||||||
|
try {
|
||||||
|
if (url) {
|
||||||
|
const isCurrentUserAuthor = author?._id === user.id;
|
||||||
|
const isAutoDownloadEnabled = fetchAutoDownloadEnabled('audioPreferenceDownload');
|
||||||
|
if (isAutoDownloadEnabled || isCurrentUserAuthor) {
|
||||||
|
await this.handleDownload();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({ loading: false, cached: false });
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
onPlaybackStatusUpdate = (status: AVPlaybackStatus) => {
|
onPlaybackStatusUpdate = (status: AVPlaybackStatus) => {
|
||||||
if (status) {
|
if (status) {
|
||||||
this.onLoad(status);
|
this.onLoad(status);
|
||||||
|
@ -294,21 +298,24 @@ class MessageAudio extends React.Component<IMessageAudioProps, IMessageAudioStat
|
||||||
if (url && this.filePath) {
|
if (url && this.filePath) {
|
||||||
const audio = await downloadMediaFile({
|
const audio = await downloadMediaFile({
|
||||||
downloadUrl: `${url}?rc_uid=${user.id}&rc_token=${user.token}`,
|
downloadUrl: `${url}?rc_uid=${user.id}&rc_token=${user.token}`,
|
||||||
mediaType: 'audio',
|
|
||||||
path: this.filePath
|
path: this.filePath
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.sound.loadAsync({ uri: audio });
|
await this.sound.loadAsync({ uri: audio });
|
||||||
return this.setState({ loading: false, cached: true });
|
this.setState({ loading: false, cached: true });
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
return this.setState({ loading: false, cached: false });
|
this.setState({ loading: false, cached: false });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onPress = () => {
|
onPress = () => {
|
||||||
const { cached } = this.state;
|
const { cached } = this.state;
|
||||||
return cached ? this.togglePlayPause() : this.handleDownload();
|
if (cached) {
|
||||||
|
this.togglePlayPause();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.handleDownload();
|
||||||
};
|
};
|
||||||
|
|
||||||
playPause = async () => {
|
playPause = async () => {
|
||||||
|
|
|
@ -12,7 +12,7 @@ import { TGetCustomEmoji } from '../../definitions/IEmoji';
|
||||||
import { IAttachment, IUserMessage } from '../../definitions';
|
import { IAttachment, IUserMessage } from '../../definitions';
|
||||||
import { useTheme } from '../../theme';
|
import { useTheme } from '../../theme';
|
||||||
import { formatAttachmentUrl } from '../../lib/methods/helpers/formatAttachmentUrl';
|
import { formatAttachmentUrl } from '../../lib/methods/helpers/formatAttachmentUrl';
|
||||||
import { cancelDownload, downloadMediaFile, isDownloadActive, searchMediaFileAsync } from '../../lib/methods/handleMediaDownload';
|
import { cancelDownload, downloadMediaFile, isDownloadActive, getMediaCache } from '../../lib/methods/handleMediaDownload';
|
||||||
import { fetchAutoDownloadEnabled } from '../../lib/methods/autoDownloadPreference';
|
import { fetchAutoDownloadEnabled } from '../../lib/methods/autoDownloadPreference';
|
||||||
import RCActivityIndicator from '../ActivityIndicator';
|
import RCActivityIndicator from '../ActivityIndicator';
|
||||||
import { CustomIcon } from '../CustomIcon';
|
import { CustomIcon } from '../CustomIcon';
|
||||||
|
@ -82,7 +82,7 @@ const ImageContainer = React.memo(
|
||||||
({ file, imageUrl, showAttachment, getCustomEmoji, style, isReply, author }: IMessageImage) => {
|
({ file, imageUrl, showAttachment, getCustomEmoji, style, isReply, author }: IMessageImage) => {
|
||||||
const [imageCached, setImageCached] = useState(file);
|
const [imageCached, setImageCached] = useState(file);
|
||||||
const [cached, setCached] = useState(false);
|
const [cached, setCached] = useState(false);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(true);
|
||||||
const { theme } = useTheme();
|
const { theme } = useTheme();
|
||||||
const { baseUrl, user } = useContext(MessageContext);
|
const { baseUrl, user } = useContext(MessageContext);
|
||||||
const filePath = useRef('');
|
const filePath = useRef('');
|
||||||
|
@ -93,9 +93,9 @@ const ImageContainer = React.memo(
|
||||||
const imgUrlToCache = getUrl(imageCached.title_link || imageCached.image_url);
|
const imgUrlToCache = getUrl(imageCached.title_link || imageCached.image_url);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
const handleImageSearchAndDownload = async () => {
|
const handleCache = async () => {
|
||||||
if (img) {
|
if (img) {
|
||||||
const cachedImageResult = await searchMediaFileAsync({
|
const cachedImageResult = await getMediaCache({
|
||||||
type: 'image',
|
type: 'image',
|
||||||
mimeType: imageCached.image_type,
|
mimeType: imageCached.image_type,
|
||||||
urlToCache: imgUrlToCache
|
urlToCache: imgUrlToCache
|
||||||
|
@ -106,16 +106,21 @@ const ImageContainer = React.memo(
|
||||||
...prev,
|
...prev,
|
||||||
title_link: cachedImageResult.file?.uri
|
title_link: cachedImageResult.file?.uri
|
||||||
}));
|
}));
|
||||||
return setCached(true);
|
setLoading(false);
|
||||||
|
setCached(true);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (isReply) return;
|
if (isReply) {
|
||||||
if (isDownloadActive('image', imgUrlToCache)) {
|
setLoading(false);
|
||||||
return setLoading(true);
|
return;
|
||||||
|
}
|
||||||
|
if (isDownloadActive(imgUrlToCache)) {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
await handleAutoDownload();
|
await handleAutoDownload();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
handleImageSearchAndDownload();
|
handleCache();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if (!img) {
|
if (!img) {
|
||||||
|
@ -131,11 +136,9 @@ const ImageContainer = React.memo(
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleDownload = async () => {
|
const handleDownload = async () => {
|
||||||
setLoading(true);
|
|
||||||
try {
|
try {
|
||||||
const imageUri = await downloadMediaFile({
|
const imageUri = await downloadMediaFile({
|
||||||
downloadUrl: imgUrlToCache,
|
downloadUrl: imgUrlToCache,
|
||||||
mediaType: 'image',
|
|
||||||
path: filePath.current
|
path: filePath.current
|
||||||
});
|
});
|
||||||
setImageCached(prev => ({
|
setImageCached(prev => ({
|
||||||
|
@ -146,23 +149,25 @@ const ImageContainer = React.memo(
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
return setCached(false);
|
setCached(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const onPress = () => {
|
const onPress = () => {
|
||||||
if (loading && isDownloadActive('image', imgUrlToCache)) {
|
if (loading && isDownloadActive(imgUrlToCache)) {
|
||||||
cancelDownload('image', imgUrlToCache);
|
cancelDownload(imgUrlToCache);
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
return setCached(false);
|
setCached(false);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (!cached && !loading) {
|
if (!cached && !loading) {
|
||||||
return handleDownload();
|
handleDownload();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
if (!showAttachment) {
|
if (!showAttachment) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return showAttachment(imageCached);
|
showAttachment(imageCached);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (imageCached.description) {
|
if (imageCached.description) {
|
||||||
|
|
|
@ -22,7 +22,7 @@ import {
|
||||||
cancelDownload,
|
cancelDownload,
|
||||||
downloadMediaFile,
|
downloadMediaFile,
|
||||||
isDownloadActive,
|
isDownloadActive,
|
||||||
searchMediaFileAsync
|
getMediaCache
|
||||||
} from '../../lib/methods/handleMediaDownload';
|
} from '../../lib/methods/handleMediaDownload';
|
||||||
import { fetchAutoDownloadEnabled } from '../../lib/methods/autoDownloadPreference';
|
import { fetchAutoDownloadEnabled } from '../../lib/methods/autoDownloadPreference';
|
||||||
import sharedStyles from '../../views/Styles';
|
import sharedStyles from '../../views/Styles';
|
||||||
|
@ -84,20 +84,20 @@ const Video = React.memo(
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const handleVideoSearchAndDownload = async () => {
|
const handleVideoSearchAndDownload = async () => {
|
||||||
if (video) {
|
if (video) {
|
||||||
const cachedVideoResult = await searchMediaFileAsync({
|
const cachedVideoResult = await getMediaCache({
|
||||||
type: 'video',
|
type: 'video',
|
||||||
mimeType: file.video_type,
|
mimeType: file.video_type,
|
||||||
urlToCache: video
|
urlToCache: video
|
||||||
});
|
});
|
||||||
filePath.current = cachedVideoResult.filePath;
|
filePath.current = cachedVideoResult.filePath;
|
||||||
const downloadActive = isDownloadActive('video', video);
|
const downloadActive = isDownloadActive(video);
|
||||||
if (cachedVideoResult.file?.exists) {
|
if (cachedVideoResult.file?.exists) {
|
||||||
setVideoCached(prev => ({
|
setVideoCached(prev => ({
|
||||||
...prev,
|
...prev,
|
||||||
video_url: cachedVideoResult.file?.uri
|
video_url: cachedVideoResult.file?.uri
|
||||||
}));
|
}));
|
||||||
if (downloadActive) {
|
if (downloadActive) {
|
||||||
cancelDownload('video', video);
|
cancelDownload(video);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -125,7 +125,6 @@ const Video = React.memo(
|
||||||
try {
|
try {
|
||||||
const videoUri = await downloadMediaFile({
|
const videoUri = await downloadMediaFile({
|
||||||
downloadUrl: video,
|
downloadUrl: video,
|
||||||
mediaType: 'video',
|
|
||||||
path: filePath.current
|
path: filePath.current
|
||||||
});
|
});
|
||||||
setVideoCached(prev => ({
|
setVideoCached(prev => ({
|
||||||
|
@ -154,7 +153,7 @@ const Video = React.memo(
|
||||||
|
|
||||||
const handleCancelDownload = () => {
|
const handleCancelDownload = () => {
|
||||||
if (loading) {
|
if (loading) {
|
||||||
cancelDownload('video', video);
|
cancelDownload(video);
|
||||||
return setLoading(false);
|
return setLoading(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,21 +15,22 @@ export const fetchAutoDownloadEnabled = (mediaType: TMediaType) => {
|
||||||
const { netInfoState } = store.getState().app;
|
const { netInfoState } = store.getState().app;
|
||||||
const mediaDownloadPreference = userPreferences.getString(mediaType) as MediaDownloadOption;
|
const mediaDownloadPreference = userPreferences.getString(mediaType) as MediaDownloadOption;
|
||||||
|
|
||||||
let defaultValueByMediaType = false;
|
if (mediaDownloadPreference === 'wifi_mobile_data') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mediaDownloadPreference === 'wifi' && netInfoState === NetInfoStateType.wifi) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (mediaDownloadPreference === null) {
|
if (mediaDownloadPreference === null) {
|
||||||
if (mediaType === 'imagesPreferenceDownload') {
|
if (mediaType === 'imagesPreferenceDownload') {
|
||||||
// The same as 'wifi_mobile_data'
|
return true;
|
||||||
defaultValueByMediaType = true;
|
|
||||||
}
|
}
|
||||||
if (mediaType === 'audioPreferenceDownload' || mediaType === 'videoPreferenceDownload') {
|
if (mediaType === 'audioPreferenceDownload' || mediaType === 'videoPreferenceDownload') {
|
||||||
// The same as 'wifi'
|
return netInfoState === NetInfoStateType.wifi;
|
||||||
defaultValueByMediaType = netInfoState === NetInfoStateType.wifi;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return false;
|
||||||
(mediaDownloadPreference === 'wifi' && netInfoState === NetInfoStateType.wifi) ||
|
|
||||||
mediaDownloadPreference === 'wifi_mobile_data' ||
|
|
||||||
defaultValueByMediaType
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,14 +22,14 @@ const defaultType = {
|
||||||
|
|
||||||
const downloadQueue: { [index: string]: FileSystem.DownloadResumable } = {};
|
const downloadQueue: { [index: string]: FileSystem.DownloadResumable } = {};
|
||||||
|
|
||||||
export const mediaDownloadKey = (mediaType: MediaTypes, downloadUrl: string) => `${mediaType}-${sanitizeString(downloadUrl)}`;
|
export const mediaDownloadKey = (messageUrl: string) => `${sanitizeString(messageUrl)}`;
|
||||||
|
|
||||||
export function isDownloadActive(mediaType: MediaTypes, messageId: string): boolean {
|
export function isDownloadActive(messageUrl: string): boolean {
|
||||||
return !!downloadQueue[mediaDownloadKey(mediaType, messageId)];
|
return !!downloadQueue[mediaDownloadKey(messageUrl)];
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function cancelDownload(mediaType: MediaTypes, messageId: string): Promise<void> {
|
export async function cancelDownload(messageUrl: string): Promise<void> {
|
||||||
const downloadKey = mediaDownloadKey(mediaType, messageId);
|
const downloadKey = mediaDownloadKey(messageUrl);
|
||||||
if (!isEmpty(downloadQueue[downloadKey])) {
|
if (!isEmpty(downloadQueue[downloadKey])) {
|
||||||
try {
|
try {
|
||||||
await downloadQueue[downloadKey].cancelAsync();
|
await downloadQueue[downloadKey].cancelAsync();
|
||||||
|
@ -40,18 +40,10 @@ export async function cancelDownload(mediaType: MediaTypes, messageId: string):
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function downloadMediaFile({
|
export function downloadMediaFile({ downloadUrl, path }: { downloadUrl: string; path: string }): Promise<string> {
|
||||||
mediaType,
|
|
||||||
downloadUrl,
|
|
||||||
path
|
|
||||||
}: {
|
|
||||||
mediaType: MediaTypes;
|
|
||||||
downloadUrl: string;
|
|
||||||
path: string;
|
|
||||||
}): Promise<string> {
|
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
const downloadKey = mediaDownloadKey(mediaType, downloadUrl);
|
const downloadKey = mediaDownloadKey(downloadUrl);
|
||||||
downloadQueue[downloadKey] = FileSystem.createDownloadResumable(downloadUrl, path);
|
downloadQueue[downloadKey] = FileSystem.createDownloadResumable(downloadUrl, path);
|
||||||
const result = await downloadQueue[downloadKey].downloadAsync();
|
const result = await downloadQueue[downloadKey].downloadAsync();
|
||||||
if (result?.uri) {
|
if (result?.uri) {
|
||||||
|
@ -101,15 +93,18 @@ const ensureDirAsync = async (dir: string, intermediates = true): Promise<void>
|
||||||
return ensureDirAsync(dir, intermediates);
|
return ensureDirAsync(dir, intermediates);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const searchMediaFileAsync = async ({
|
export const getMediaCache = async ({
|
||||||
type,
|
type,
|
||||||
mimeType,
|
mimeType,
|
||||||
urlToCache
|
urlToCache
|
||||||
}: {
|
}: {
|
||||||
type: MediaTypes;
|
type: MediaTypes;
|
||||||
mimeType?: string;
|
mimeType?: string;
|
||||||
urlToCache: string;
|
urlToCache?: string;
|
||||||
}) => {
|
}) => {
|
||||||
|
if (!urlToCache) {
|
||||||
|
return { file: null, filePath: '' };
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
const serverUrl = store.getState().server.server;
|
const serverUrl = store.getState().server.server;
|
||||||
const serverUrlParsed = serverUrlParsedAsPath(serverUrl);
|
const serverUrlParsed = serverUrlParsedAsPath(serverUrl);
|
||||||
|
|
Loading…
Reference in New Issue