feat: image base64 (#5264)

* improvement: handle base64

* update tests

* minor tweak

* remove imageprocess and remove the save to gallery from image base64

* Update app/containers/message/Image.tsx

* Update app/views/AttachmentView.tsx

* Update app/views/AttachmentView.tsx

* Update app/views/AttachmentView.tsx

* Update app/containers/message/Image.tsx

* chore: change file name and fix implementation

* chore: remove useless const

* chore: update regex

* chore: update name

* Update app/lib/methods/isImageBase64.ts

* Update app/lib/methods/isImageBase64.ts

* early return

---------

Co-authored-by: Gleidson Daniel Silva <gleidson10daniel@hotmail.com>
Co-authored-by: Diego Mello <diegolmello@gmail.com>
This commit is contained in:
Reinaldo Neto 2023-10-11 11:23:11 -03:00 committed by GitHub
parent 6a02fde453
commit 74cd85a069
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 56 additions and 8 deletions

File diff suppressed because one or more lines are too long

View File

@ -13,6 +13,7 @@ import BlurComponent from './Components/BlurComponent';
import MessageContext from './Context'; import MessageContext from './Context';
import Touchable from './Touchable'; import Touchable from './Touchable';
import styles from './styles'; import styles from './styles';
import { isImageBase64 } from '../../lib/methods';
interface IMessageButton { interface IMessageButton {
children: React.ReactElement; children: React.ReactElement;
@ -110,7 +111,12 @@ const ImageContainer = ({
await handleAutoDownload(); await handleAutoDownload();
} }
}; };
handleCache(); if (isImageBase64(imgUrlToCache)) {
setLoading(false);
setCached(true);
} else {
handleCache();
}
}, []); }, []);
if (!img) { if (!img) {

File diff suppressed because one or more lines are too long

View File

@ -199,8 +199,7 @@ export function downloadMediaFile({
try { try {
const path = getFilePath({ type, mimeType, urlToCache: downloadUrl }); const path = getFilePath({ type, mimeType, urlToCache: downloadUrl });
if (!path) { if (!path) {
reject(); return reject();
return;
} }
downloadKey = mediaDownloadKey(downloadUrl); downloadKey = mediaDownloadKey(downloadUrl);
downloadQueue[downloadKey] = FileSystem.createDownloadResumable(downloadUrl, path); downloadQueue[downloadKey] = FileSystem.createDownloadResumable(downloadUrl, path);
@ -208,9 +207,9 @@ export function downloadMediaFile({
if (result?.uri) { if (result?.uri) {
return resolve(result.uri); return resolve(result.uri);
} }
reject(); return reject();
} catch { } catch {
reject(); return reject();
} finally { } finally {
delete downloadQueue[downloadKey]; delete downloadQueue[downloadKey];
} }

View File

@ -1,6 +1,7 @@
import { URL } from 'react-native-url-polyfill'; import { URL } from 'react-native-url-polyfill';
import { LOCAL_DOCUMENT_DIRECTORY } from '../handleMediaDownload'; import { LOCAL_DOCUMENT_DIRECTORY } from '../handleMediaDownload';
import { isImageBase64 } from '../isImageBase64';
function setParamInUrl({ url, token, userId }: { url: string; token: string; userId: string }) { function setParamInUrl({ url, token, userId }: { url: string; token: string; userId: string }) {
const urlObj = new URL(url); const urlObj = new URL(url);
@ -10,7 +11,10 @@ function setParamInUrl({ url, token, userId }: { url: string; token: string; use
} }
export const formatAttachmentUrl = (attachmentUrl: string | undefined, userId: string, token: string, server: string): string => { export const formatAttachmentUrl = (attachmentUrl: string | undefined, userId: string, token: string, server: string): string => {
if (LOCAL_DOCUMENT_DIRECTORY && attachmentUrl?.startsWith(LOCAL_DOCUMENT_DIRECTORY)) { if (
(attachmentUrl && isImageBase64(attachmentUrl)) ||
(LOCAL_DOCUMENT_DIRECTORY && attachmentUrl?.startsWith(LOCAL_DOCUMENT_DIRECTORY))
) {
return attachmentUrl; return attachmentUrl;
} }
if (attachmentUrl && attachmentUrl.startsWith('http')) { if (attachmentUrl && attachmentUrl.startsWith('http')) {

View File

@ -38,3 +38,4 @@ export * from './parseSettings';
export * from './subscribeRooms'; export * from './subscribeRooms';
export * from './serializeAsciiUrl'; export * from './serializeAsciiUrl';
export * from './isRoomFederated'; export * from './isRoomFederated';
export * from './isImageBase64';

View File

@ -0,0 +1,16 @@
import { isImageBase64 } from './isImageBase64';
// We aren't testing the content, only the header
const base64 =
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKkAAADcCAIAAACEWBYKAAAAA3NCSVQICAjb4U/gAAAgAElEQVR4nO29aZAc13WoeXOtrMza967qHd1ooAGRBLQNTcnUxmHMmPo3CjvGEdZo7PAP/fDzs2fscbw/Hr14EYrwNhMeWZbMkCY0YZJiaB4FkwxRFkiAIgACDZAAutFbVXft+55Vua/z40g9EJaWWN0Al8rvR0d1Va735M177jnnnoPZto0cxhL8/b4Ah/cNR/bjiyP78cWR/fjiyH58cWQ/vjiyH18c2Y8vjuzHF0f244sj+/HFkf344sh+fHFkP76MLntLkg/xOhwePiPK3pKV0vLTpf/+fxy8fp4/e07e2PpN9lJ3c3d+s5P9lcOKkt5q37GN3myZojjadTrsw4iyx90M8z8';
describe('Test the isImageBase64', () => {
it.each([
['test', false],
['/file-upload/oTQmb2zRCsYF4pdHv/help-image-url.png', false],
[base64, true]
])('return properly the boolean', (data, res) => {
const result = isImageBase64(data);
expect(result).toBe(res);
});
});

View File

@ -0,0 +1,8 @@
const imageBase64RegExp = new RegExp(/^data:image\/([a-zA-Z]*);base64,([^\"]*)$/);
export function isImageBase64(data?: string): boolean {
if (!data) {
return false;
}
return imageBase64RegExp.test(data);
}

View File

@ -8,6 +8,7 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { shallowEqual } from 'react-redux'; import { shallowEqual } from 'react-redux';
import RNFetchBlob from 'rn-fetch-blob'; import RNFetchBlob from 'rn-fetch-blob';
import { isImageBase64 } from '../lib/methods';
import RCActivityIndicator from '../containers/ActivityIndicator'; import RCActivityIndicator from '../containers/ActivityIndicator';
import * as HeaderButton from '../containers/HeaderButton'; import * as HeaderButton from '../containers/HeaderButton';
import { ImageViewer } from '../containers/ImageViewer'; import { ImageViewer } from '../containers/ImageViewer';
@ -109,6 +110,7 @@ const AttachmentView = (): React.ReactElement => {
const setHeader = () => { const setHeader = () => {
let { title } = attachment; let { title } = attachment;
try { try {
if (title) { if (title) {
title = decodeURI(title); title = decodeURI(title);
@ -128,7 +130,7 @@ const AttachmentView = (): React.ReactElement => {
<HeaderButton.CloseModal testID='close-attachment-view' navigation={navigation} color={colors.previewTintColor} /> <HeaderButton.CloseModal testID='close-attachment-view' navigation={navigation} color={colors.previewTintColor} />
), ),
headerRight: () => headerRight: () =>
Allow_Save_Media_to_Gallery ? ( Allow_Save_Media_to_Gallery && !isImageBase64(attachment.image_url) ? (
<HeaderButton.Download testID='save-image' onPress={handleSave} color={colors.previewTintColor} /> <HeaderButton.Download testID='save-image' onPress={handleSave} color={colors.previewTintColor} />
) : null, ) : null,
headerBackground: () => ( headerBackground: () => (