don't need to controle the filepath in the view
This commit is contained in:
parent
c85f98955c
commit
b3f460598f
|
@ -121,7 +121,6 @@ Button.displayName = 'MessageAudioButton';
|
||||||
class MessageAudio extends React.Component<IMessageAudioProps, IMessageAudioState> {
|
class MessageAudio extends React.Component<IMessageAudioProps, IMessageAudioState> {
|
||||||
static contextType = MessageContext;
|
static contextType = MessageContext;
|
||||||
private sound: Sound;
|
private sound: Sound;
|
||||||
private filePath?: string;
|
|
||||||
|
|
||||||
constructor(props: IMessageAudioProps) {
|
constructor(props: IMessageAudioProps) {
|
||||||
super(props);
|
super(props);
|
||||||
|
@ -149,9 +148,8 @@ class MessageAudio extends React.Component<IMessageAudioProps, IMessageAudioStat
|
||||||
mimeType: file.audio_type,
|
mimeType: file.audio_type,
|
||||||
urlToCache: this.getUrl()
|
urlToCache: this.getUrl()
|
||||||
});
|
});
|
||||||
this.filePath = cachedAudioResult.filePath;
|
if (cachedAudioResult?.exists) {
|
||||||
if (cachedAudioResult?.file?.exists) {
|
await this.sound.loadAsync({ uri: cachedAudioResult.uri });
|
||||||
await this.sound.loadAsync({ uri: cachedAudioResult.file.uri });
|
|
||||||
this.setState({ loading: false, cached: true });
|
this.setState({ loading: false, cached: true });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -290,17 +288,18 @@ class MessageAudio extends React.Component<IMessageAudioProps, IMessageAudioStat
|
||||||
};
|
};
|
||||||
|
|
||||||
handleDownload = async () => {
|
handleDownload = async () => {
|
||||||
|
const { file } = this.props;
|
||||||
// @ts-ignore can't use declare to type this
|
// @ts-ignore can't use declare to type this
|
||||||
const { user } = this.context;
|
const { user } = this.context;
|
||||||
this.setState({ loading: true });
|
this.setState({ loading: true });
|
||||||
try {
|
try {
|
||||||
const url = this.getUrl();
|
const url = this.getUrl();
|
||||||
if (url && this.filePath) {
|
if (url) {
|
||||||
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}`,
|
||||||
path: this.filePath
|
type: 'audio',
|
||||||
|
mimeType: file.audio_type
|
||||||
});
|
});
|
||||||
|
|
||||||
await this.sound.loadAsync({ uri: audio });
|
await this.sound.loadAsync({ uri: audio });
|
||||||
this.setState({ loading: false, cached: true });
|
this.setState({ loading: false, cached: true });
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useContext, useLayoutEffect, useRef, useState } from 'react';
|
import React, { useContext, useLayoutEffect, useState } from 'react';
|
||||||
import { StyleProp, TextStyle, View } from 'react-native';
|
import { StyleProp, TextStyle, View } from 'react-native';
|
||||||
import FastImage from 'react-native-fast-image';
|
import FastImage from 'react-native-fast-image';
|
||||||
import { dequal } from 'dequal';
|
import { dequal } from 'dequal';
|
||||||
|
@ -68,7 +68,6 @@ const ImageContainer = React.memo(
|
||||||
const [loading, setLoading] = useState(true);
|
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 getUrl = (link?: string) => imageUrl || formatAttachmentUrl(link, user.id, user.token, baseUrl);
|
const getUrl = (link?: string) => imageUrl || formatAttachmentUrl(link, user.id, user.token, baseUrl);
|
||||||
const img = getUrl(file.image_url);
|
const img = getUrl(file.image_url);
|
||||||
// The param file.title_link is the one that point to image with best quality, however we still need to test the imageUrl
|
// The param file.title_link is the one that point to image with best quality, however we still need to test the imageUrl
|
||||||
|
@ -83,11 +82,10 @@ const ImageContainer = React.memo(
|
||||||
mimeType: imageCached.image_type,
|
mimeType: imageCached.image_type,
|
||||||
urlToCache: imgUrlToCache
|
urlToCache: imgUrlToCache
|
||||||
});
|
});
|
||||||
filePath.current = cachedImageResult.filePath;
|
if (cachedImageResult?.exists) {
|
||||||
if (cachedImageResult.file?.exists) {
|
|
||||||
setImageCached(prev => ({
|
setImageCached(prev => ({
|
||||||
...prev,
|
...prev,
|
||||||
title_link: cachedImageResult.file?.uri
|
title_link: cachedImageResult?.uri
|
||||||
}));
|
}));
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setCached(true);
|
setCached(true);
|
||||||
|
@ -122,7 +120,8 @@ const ImageContainer = React.memo(
|
||||||
try {
|
try {
|
||||||
const imageUri = await downloadMediaFile({
|
const imageUri = await downloadMediaFile({
|
||||||
downloadUrl: imgUrlToCache,
|
downloadUrl: imgUrlToCache,
|
||||||
path: filePath.current
|
type: 'image',
|
||||||
|
mimeType: imageCached.image_type
|
||||||
});
|
});
|
||||||
setImageCached(prev => ({
|
setImageCached(prev => ({
|
||||||
...prev,
|
...prev,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React, { useContext, useEffect, useRef, useState } from 'react';
|
import React, { useContext, useEffect, useState } from 'react';
|
||||||
import { StyleProp, StyleSheet, TextStyle, View, Text } from 'react-native';
|
import { StyleProp, StyleSheet, TextStyle, View, Text } from 'react-native';
|
||||||
import { dequal } from 'dequal';
|
import { dequal } from 'dequal';
|
||||||
import * as VideoThumbnails from 'expo-video-thumbnails';
|
import * as VideoThumbnails from 'expo-video-thumbnails';
|
||||||
|
@ -106,7 +106,6 @@ const Video = React.memo(
|
||||||
const [cached, setCached] = useState(false);
|
const [cached, setCached] = useState(false);
|
||||||
const { baseUrl, user } = useContext(MessageContext);
|
const { baseUrl, user } = useContext(MessageContext);
|
||||||
const { theme } = useTheme();
|
const { theme } = useTheme();
|
||||||
const filePath = useRef('');
|
|
||||||
const video = formatAttachmentUrl(file.video_url, user.id, user.token, baseUrl);
|
const video = formatAttachmentUrl(file.video_url, user.id, user.token, baseUrl);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -117,12 +116,11 @@ const Video = React.memo(
|
||||||
mimeType: file.video_type,
|
mimeType: file.video_type,
|
||||||
urlToCache: video
|
urlToCache: video
|
||||||
});
|
});
|
||||||
filePath.current = cachedVideoResult.filePath;
|
|
||||||
const downloadActive = isDownloadActive(video);
|
const downloadActive = isDownloadActive(video);
|
||||||
if (cachedVideoResult.file?.exists) {
|
if (cachedVideoResult?.exists) {
|
||||||
setVideoCached(prev => ({
|
setVideoCached(prev => ({
|
||||||
...prev,
|
...prev,
|
||||||
video_url: cachedVideoResult.file?.uri
|
video_url: cachedVideoResult?.uri
|
||||||
}));
|
}));
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setCached(true);
|
setCached(true);
|
||||||
|
@ -157,7 +155,8 @@ const Video = React.memo(
|
||||||
try {
|
try {
|
||||||
const videoUri = await downloadMediaFile({
|
const videoUri = await downloadMediaFile({
|
||||||
downloadUrl: video,
|
downloadUrl: video,
|
||||||
path: filePath.current
|
type: 'video',
|
||||||
|
mimeType: file.video_type
|
||||||
});
|
});
|
||||||
setVideoCached(prev => ({
|
setVideoCached(prev => ({
|
||||||
...prev,
|
...prev,
|
||||||
|
|
|
@ -8,54 +8,12 @@ import log from './helpers/log';
|
||||||
|
|
||||||
export type MediaTypes = 'audio' | 'image' | 'video';
|
export type MediaTypes = 'audio' | 'image' | 'video';
|
||||||
|
|
||||||
const typeString = {
|
|
||||||
audio: 'audios/',
|
|
||||||
image: 'images/',
|
|
||||||
video: 'videos/'
|
|
||||||
};
|
|
||||||
|
|
||||||
const defaultType = {
|
const defaultType = {
|
||||||
audio: 'mp3',
|
audio: 'mp3',
|
||||||
image: 'jpg',
|
image: 'jpg',
|
||||||
video: 'mp4'
|
video: 'mp4'
|
||||||
};
|
};
|
||||||
|
|
||||||
const downloadQueue: { [index: string]: FileSystem.DownloadResumable } = {};
|
|
||||||
|
|
||||||
export const mediaDownloadKey = (messageUrl: string) => `${sanitizeString(messageUrl)}`;
|
|
||||||
|
|
||||||
export function isDownloadActive(messageUrl: string): boolean {
|
|
||||||
return !!downloadQueue[mediaDownloadKey(messageUrl)];
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function cancelDownload(messageUrl: string): Promise<void> {
|
|
||||||
const downloadKey = mediaDownloadKey(messageUrl);
|
|
||||||
if (!isEmpty(downloadQueue[downloadKey])) {
|
|
||||||
try {
|
|
||||||
await downloadQueue[downloadKey].cancelAsync();
|
|
||||||
} catch {
|
|
||||||
// Do nothing
|
|
||||||
}
|
|
||||||
delete downloadQueue[downloadKey];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function downloadMediaFile({ downloadUrl, path }: { downloadUrl: string; path: string }): Promise<string> {
|
|
||||||
return new Promise(async (resolve, reject) => {
|
|
||||||
try {
|
|
||||||
const downloadKey = mediaDownloadKey(downloadUrl);
|
|
||||||
downloadQueue[downloadKey] = FileSystem.createDownloadResumable(downloadUrl, path);
|
|
||||||
const result = await downloadQueue[downloadKey].downloadAsync();
|
|
||||||
if (result?.uri) {
|
|
||||||
return resolve(result.uri);
|
|
||||||
}
|
|
||||||
reject();
|
|
||||||
} catch {
|
|
||||||
reject();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export const LOCAL_DOCUMENT_DIRECTORY = FileSystem.documentDirectory;
|
export const LOCAL_DOCUMENT_DIRECTORY = FileSystem.documentDirectory;
|
||||||
|
|
||||||
const sanitizeString = (value: string) => {
|
const sanitizeString = (value: string) => {
|
||||||
|
@ -93,6 +51,24 @@ const ensureDirAsync = async (dir: string, intermediates = true): Promise<void>
|
||||||
return ensureDirAsync(dir, intermediates);
|
return ensureDirAsync(dir, intermediates);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getFilePath = ({ type, mimeType, urlToCache }: { type: MediaTypes; mimeType?: string; urlToCache?: string }) => {
|
||||||
|
if (!urlToCache) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const folderPath = getFolderPath();
|
||||||
|
const fileUrlSanitized = sanitizeString(urlToCache);
|
||||||
|
const filename = `${fileUrlSanitized}.${getExtension(type, mimeType)}`;
|
||||||
|
const filePath = `${folderPath}${filename}`;
|
||||||
|
return filePath;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getFolderPath = () => {
|
||||||
|
const serverUrl = store.getState().server.server;
|
||||||
|
const serverUrlParsed = serverUrlParsedAsPath(serverUrl);
|
||||||
|
const folderPath = `${LOCAL_DOCUMENT_DIRECTORY}${serverUrlParsed}`;
|
||||||
|
return folderPath;
|
||||||
|
};
|
||||||
|
|
||||||
export const getMediaCache = async ({
|
export const getMediaCache = async ({
|
||||||
type,
|
type,
|
||||||
mimeType,
|
mimeType,
|
||||||
|
@ -103,21 +79,20 @@ export const getMediaCache = async ({
|
||||||
urlToCache?: string;
|
urlToCache?: string;
|
||||||
}) => {
|
}) => {
|
||||||
if (!urlToCache) {
|
if (!urlToCache) {
|
||||||
return { file: null, filePath: '' };
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const serverUrl = store.getState().server.server;
|
const folderPath = getFolderPath();
|
||||||
const serverUrlParsed = serverUrlParsedAsPath(serverUrl);
|
const filePath = getFilePath({ type, mimeType, urlToCache });
|
||||||
const folderPath = `${LOCAL_DOCUMENT_DIRECTORY}${serverUrlParsed}${typeString[type]}`;
|
if (!filePath) {
|
||||||
const fileUrlSanitized = sanitizeString(urlToCache);
|
return null;
|
||||||
const filename = `${fileUrlSanitized}.${getExtension(type, mimeType)}`;
|
}
|
||||||
const filePath = `${folderPath}${filename}`;
|
|
||||||
await ensureDirAsync(folderPath);
|
await ensureDirAsync(folderPath);
|
||||||
const file = await FileSystem.getInfoAsync(filePath);
|
const file = await FileSystem.getInfoAsync(filePath);
|
||||||
return { file, filePath };
|
return file;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log(error);
|
log(error);
|
||||||
return { file: null, filePath: '' };
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -130,3 +105,52 @@ export const deleteMediaFiles = async (serverUrl: string): Promise<void> => {
|
||||||
log(error);
|
log(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const downloadQueue: { [index: string]: FileSystem.DownloadResumable } = {};
|
||||||
|
|
||||||
|
export const mediaDownloadKey = (messageUrl: string) => `${sanitizeString(messageUrl)}`;
|
||||||
|
|
||||||
|
export function isDownloadActive(messageUrl: string): boolean {
|
||||||
|
return !!downloadQueue[mediaDownloadKey(messageUrl)];
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function cancelDownload(messageUrl: string): Promise<void> {
|
||||||
|
const downloadKey = mediaDownloadKey(messageUrl);
|
||||||
|
if (!isEmpty(downloadQueue[downloadKey])) {
|
||||||
|
try {
|
||||||
|
await downloadQueue[downloadKey].cancelAsync();
|
||||||
|
} catch {
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
delete downloadQueue[downloadKey];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function downloadMediaFile({
|
||||||
|
type,
|
||||||
|
mimeType,
|
||||||
|
downloadUrl
|
||||||
|
}: {
|
||||||
|
type: MediaTypes;
|
||||||
|
mimeType?: string;
|
||||||
|
downloadUrl: string;
|
||||||
|
}): Promise<string> {
|
||||||
|
return new Promise(async (resolve, reject) => {
|
||||||
|
try {
|
||||||
|
const path = getFilePath({ type, mimeType, urlToCache: downloadUrl });
|
||||||
|
if (!path) {
|
||||||
|
reject();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const downloadKey = mediaDownloadKey(downloadUrl);
|
||||||
|
downloadQueue[downloadKey] = FileSystem.createDownloadResumable(downloadUrl, path);
|
||||||
|
const result = await downloadQueue[downloadKey].downloadAsync();
|
||||||
|
if (result?.uri) {
|
||||||
|
return resolve(result.uri);
|
||||||
|
}
|
||||||
|
reject();
|
||||||
|
} catch {
|
||||||
|
reject();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue