MM-40530 Support SVG for markdown inline images (#5869)

* MM-40530 Support SVG for markdown inline images

* Update app/components/markdown/markdown_image/markdown_image.js

Co-authored-by: Daniel Espino García <larkox@gmail.com>

Co-authored-by: Daniel Espino García <larkox@gmail.com>
This commit is contained in:
Elias Nahum 2021-12-15 16:43:45 +02:00 committed by GitHub
parent 1a58dd8a0d
commit b7455853e5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 45 additions and 21 deletions

View file

@ -13,6 +13,7 @@ import {
Text,
View,
} from 'react-native';
import {SvgUri} from 'react-native-svg';
import parseUrl from 'url-parse';
import CompassIcon from '@components/compass_icon';
@ -50,18 +51,19 @@ export default class MarkdownImage extends ImageViewPort {
constructor(props) {
super(props);
const metadata = props.imagesMetadata?.[props.source] || Object.values(props.imagesMetadata || {})[0];
const metadata = props.imagesMetadata?.[props.source] || Object.values(props.imagesMetadata || {})?.[0];
this.fileId = generateId();
this.state = {
originalHeight: metadata?.height || 0,
originalWidth: metadata?.width || 0,
failed: isGifTooLarge(metadata),
format: metadata?.format,
uri: null,
};
}
getFileInfo = () => {
const {originalHeight, originalWidth} = this.state;
const {format, originalHeight, originalWidth} = this.state;
const link = decodeURIComponent(this.getSource());
let filename = parseUrl(link.substr(link.lastIndexOf('/'))).pathname.replace('/', '');
let extension = filename.split('.').pop();
@ -76,6 +78,7 @@ export default class MarkdownImage extends ImageViewPort {
id: this.fileId,
name: filename,
extension,
format,
has_preview_image: true,
post_id: this.props.postId,
uri: link,
@ -175,12 +178,12 @@ export default class MarkdownImage extends ImageViewPort {
render() {
let image = null;
const fileInfo = this.getFileInfo();
const {height, width} = calculateDimensions(fileInfo.height, fileInfo.width, getViewPortWidth(this.props.isReplyPost, this.hasPermanentSidebar()));
const {height, width} = calculateDimensions(fileInfo?.height, fileInfo?.width, getViewPortWidth(this.props.isReplyPost, this.hasPermanentSidebar()));
if (this.state.failed) {
image = (
<CompassIcon
name='jumbo-attachment-image-broken'
name='file-image-broken-outline-large'
size={24}
/>
);
@ -204,11 +207,7 @@ export default class MarkdownImage extends ImageViewPort {
);
} else {
// React Native complains if we try to pass resizeMode as a style
let source = null;
if (fileInfo.uri) {
source = {uri: fileInfo.uri};
}
const source = fileInfo.uri ? {uri: fileInfo.uri} : null;
image = (
<TouchableWithFeedback
onLongPress={this.handleLinkLongPress}
@ -224,6 +223,13 @@ export default class MarkdownImage extends ImageViewPort {
</TouchableWithFeedback>
);
}
} else if (fileInfo?.format === 'svg') {
image = (
<SvgUri
uri={fileInfo.uri}
style={{flex: 1}}
/>
);
}
if (image && this.props.linkDestination) {

View file

@ -3,6 +3,7 @@
import React, {useCallback, useRef, useState} from 'react';
import {StyleSheet, View} from 'react-native';
import {SvgUri} from 'react-native-svg';
import parseUrl from 'url-parse';
import CompassIcon from '@components/compass_icon';
@ -32,7 +33,7 @@ const styles = StyleSheet.create({
});
const MarkTableImage = ({disable, imagesMetadata, postId, serverURL, source}: MarkdownTableImageProps) => {
const metadata = imagesMetadata[source];
const metadata = imagesMetadata[source] || Object.values(imagesMetadata || {})?.[0];
const fileId = useRef(generateId()).current;
const [failed, setFailed] = useState(isGifTooLarge(metadata));
@ -95,17 +96,24 @@ const MarkTableImage = ({disable, imagesMetadata, postId, serverURL, source}: Ma
if (failed) {
image = (
<CompassIcon
name='jumbo-attachment-image-broken'
name='file-image-broken-outline-large'
size={24}
/>
);
} else {
const {height, width} = calculateDimensions(metadata.height, metadata.width, 100, 100);
image = (
<TouchableWithFeedback
onPress={handlePreviewImage}
style={{width, height}}
>
const {height, width} = calculateDimensions(metadata?.height, metadata?.width, 100, 100);
let imageComponent;
if (metadata?.format === 'svg') {
imageComponent = (
<View style={{height: 100}}>
<SvgUri
uri={source}
style={styles.container}
/>
</View>
);
} else {
imageComponent = (
<ProgressiveImage
id={fileId}
defaultSource={{uri: source}}
@ -113,6 +121,16 @@ const MarkTableImage = ({disable, imagesMetadata, postId, serverURL, source}: Ma
resizeMode='contain'
style={{width, height}}
/>
);
}
image = (
<TouchableWithFeedback
onPress={handlePreviewImage}
style={{width, height}}
>
{imageComponent}
</TouchableWithFeedback>
);
}

View file

@ -15,7 +15,7 @@ describe('Images calculateDimensions', () => {
falsyHeights.forEach((falsyHeight) => {
const {height, width} = calculateDimensions(falsyHeight as number, 20, PORTRAIT_VIEWPORT);
expect(height).toEqual(0);
expect(width).toEqual(0);
expect(width).toEqual(PORTRAIT_VIEWPORT);
});
});
@ -24,7 +24,7 @@ describe('Images calculateDimensions', () => {
falsyWidths.forEach((falsyWidth) => {
const {height, width} = calculateDimensions(20, falsyWidth as number, PORTRAIT_VIEWPORT);
expect(height).toEqual(0);
expect(width).toEqual(0);
expect(width).toEqual(PORTRAIT_VIEWPORT);
});
});

View file

@ -16,8 +16,8 @@ import {PostImage} from '@mm-redux/types/posts';
export const calculateDimensions = (height: number, width: number, viewPortWidth = 0, viewPortHeight = 0) => {
if (!height || !width) {
return {
height: 0,
width: 0,
height: viewPortHeight,
width: viewPortWidth,
};
}