Skip to content

Commit

Permalink
fix: image preview size (#5813)
Browse files Browse the repository at this point in the history
  • Loading branch information
diegolmello authored Jul 31, 2024
1 parent 1b7ab31 commit 3933932
Show file tree
Hide file tree
Showing 7 changed files with 211 additions and 163 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Button } from './Button';
import { MessageImage } from './Image';
import { IImageContainer } from './definitions';
import MessageContext from '../../../Context';
import { WidthAwareView } from '../../WidthAwareView';

const ImageContainer = ({
file,
Expand All @@ -24,7 +25,9 @@ const ImageContainer = ({

const image = (
<Button onPress={onPress}>
<MessageImage uri={url} status={status} encrypted={isEncrypted} />
<WidthAwareView>
<MessageImage uri={url} status={status} encrypted={isEncrypted} />
</WidthAwareView>
</Button>
);

Expand Down
57 changes: 44 additions & 13 deletions app/containers/message/Components/Attachments/Image/Image.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,71 @@
import React from 'react';
import { View } from 'react-native';
import React, { useContext, useEffect, useState } from 'react';
import { View, ViewStyle, Image } from 'react-native';
import FastImage from 'react-native-fast-image';

import { isValidUrl } from '../../../../../lib/methods/helpers/isValidUrl';
import { useTheme } from '../../../../../theme';
import styles from '../../../styles';
import OverlayComponent from '../../OverlayComponent';
import { IMessageImage } from './definitions';
import { WidthAwareContext } from '../../WidthAwareView';

export const MessageImage = React.memo(({ uri, status, encrypted = false }: IMessageImage) => {
const { colors } = useTheme();
const [imageDimensions, setImageDimensions] = useState({ width: 0, height: 0 });
const maxSize = useContext(WidthAwareContext);
const showImage = isValidUrl(uri) && imageDimensions.width && status === 'downloaded';

useEffect(() => {
if (status === 'downloaded') {
Image.getSize(uri, (width, height) => {
setImageDimensions({ width, height });
});
}
}, [uri, status]);

const width = Math.min(imageDimensions.width, maxSize) || 0;
const height = Math.min((imageDimensions.height * ((width * 100) / imageDimensions.width)) / 100, maxSize) || 0;
const imageStyle = {
width,
height
};

const containerStyle: ViewStyle = {
alignItems: 'center',
justifyContent: 'center',
...(imageDimensions.width <= 64 && { width: 64 }),
...(imageDimensions.height <= 64 && { height: 64 })
};

const borderStyle: ViewStyle = {
borderColor: colors.strokeLight,
borderWidth: 1,
borderRadius: 4,
overflow: 'hidden'
};

if (encrypted && status === 'downloaded') {
return (
<>
<View style={styles.image} />
<OverlayComponent loading={false} style={[styles.image, styles.imageBlurContainer]} iconName='encrypted' />
<OverlayComponent loading={false} style={styles.image} iconName='encrypted' />
</>
);
}

return (
<>
{isValidUrl(uri) && status === 'downloaded' ? (
<FastImage
style={[styles.image, { borderColor: colors.strokeLight }]}
source={{ uri: encodeURI(uri) }}
resizeMode={FastImage.resizeMode.cover}
/>
{showImage ? (
<View style={[containerStyle, borderStyle]}>
<FastImage style={imageStyle} source={{ uri: encodeURI(uri) }} resizeMode={FastImage.resizeMode.cover} />
</View>
) : (
<View style={styles.image} />
<View style={[styles.image, borderStyle]} />
)}
{['loading', 'to-download'].includes(status) ? (
{['loading', 'to-download'].includes(status) || (status === 'downloaded' && !showImage) ? (
<OverlayComponent
loading={status === 'loading'}
style={[styles.image, styles.imageBlurContainer]}
loading={['loading', 'downloaded'].includes(status)}
style={[styles.image, borderStyle]}
iconName='arrow-down-circle'
/>
) : null}
Expand Down
6 changes: 3 additions & 3 deletions app/containers/message/Components/Attachments/Reply.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -223,9 +223,9 @@ const Reply = React.memo(
openLink(url, theme);
};

let { strokeExtraLight } = themes[theme];
let { strokeLight } = themes[theme];
if (attachment.color) {
strokeExtraLight = attachment.color;
strokeLight = attachment.color;
}

return (
Expand All @@ -239,7 +239,7 @@ const Reply = React.memo(
index > 0 && styles.marginTop,
msg && styles.marginBottom,
{
borderColor: strokeExtraLight
borderColor: strokeLight
}
]}
background={Touchable.Ripple(themes[theme].surfaceNeutral)}
Expand Down
25 changes: 9 additions & 16 deletions app/containers/message/Components/Attachments/Video.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { IUserMessage } from '../../../../definitions';
import { IAttachment } from '../../../../definitions/IAttachment';
import { TGetCustomEmoji } from '../../../../definitions/IEmoji';
import I18n from '../../../../i18n';
import { themes } from '../../../../lib/constants';
import { fileDownload, isIOS } from '../../../../lib/methods/helpers';
import EventEmitter from '../../../../lib/methods/helpers/events';
import { useTheme } from '../../../../theme';
Expand All @@ -16,22 +15,14 @@ import Markdown from '../../../markdown';
import MessageContext from '../../Context';
import Touchable from '../../Touchable';
import { useMediaAutoDownload } from '../../hooks/useMediaAutoDownload';
import { DEFAULT_MESSAGE_HEIGHT } from '../../utils';
import BlurComponent from '../OverlayComponent';
import { TDownloadState } from '../../../../lib/methods/handleMediaDownload';
import messageStyles from '../../styles';

const SUPPORTED_TYPES = ['video/quicktime', 'video/mp4', ...(isIOS ? [] : ['video/3gp', 'video/mkv'])];
const isTypeSupported = (type: string) => SUPPORTED_TYPES.indexOf(type) !== -1;

const styles = StyleSheet.create({
button: {
flex: 1,
borderRadius: 4,
height: DEFAULT_MESSAGE_HEIGHT,
marginBottom: 6,
alignItems: 'center',
justifyContent: 'center'
},
cancelContainer: {
position: 'absolute',
top: 8,
Expand Down Expand Up @@ -63,14 +54,19 @@ const CancelIndicator = () => {
};

const Thumbnail = ({ status, encrypted = false }: { status: TDownloadState; encrypted: boolean }) => {
const { colors } = useTheme();
let icon: TIconsName = status === 'downloaded' ? 'play-filled' : 'arrow-down-circle';
if (encrypted && status === 'downloaded') {
icon = 'encrypted';
}

return (
<>
<BlurComponent iconName={icon} loading={status === 'loading'} style={styles.button} />
<BlurComponent
iconName={icon}
loading={status === 'loading'}
style={[messageStyles.image, { borderColor: colors.strokeLight, borderWidth: 1 }]}
/>
{status === 'loading' ? <CancelIndicator /> : null}
</>
);
Expand All @@ -86,7 +82,7 @@ const Video = ({
msg
}: IMessageVideo): React.ReactElement | null => {
const { user } = useContext(MessageContext);
const { theme } = useTheme();
const { theme, colors } = useTheme();
const { status, onPress, url, isEncrypted, currentFile } = useMediaAutoDownload({ file, author, showAttachment });

const _onPress = async () => {
Expand Down Expand Up @@ -115,10 +111,7 @@ const Video = ({
return (
<>
<Markdown msg={msg} username={user.username} getCustomEmoji={getCustomEmoji} style={[isReply && style]} theme={theme} />
<Touchable
onPress={_onPress}
style={[styles.button, { backgroundColor: themes[theme].surfaceDark }]}
background={Touchable.Ripple(themes[theme].surfaceNeutral)}>
<Touchable onPress={_onPress} style={messageStyles.image} background={Touchable.Ripple(colors.surfaceNeutral)}>
<Thumbnail status={status} encrypted={isEncrypted} />
</Touchable>
</>
Expand Down
26 changes: 26 additions & 0 deletions app/containers/message/Components/WidthAwareView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { createContext, ReactElement, useState } from 'react';
import { View, StyleSheet } from 'react-native';

export const WidthAwareContext = createContext(0);

const styles = StyleSheet.create({
container: {
flexDirection: 'row'
}
});

export const WidthAwareView = ({ children }: { children: ReactElement }) => {
const [width, setWidth] = useState(0);

return (
<View
style={styles.container}
onLayout={ev => {
if (ev.nativeEvent.layout.width) {
setWidth(ev.nativeEvent.layout.width);
}
}}>
<WidthAwareContext.Provider value={width}>{children}</WidthAwareContext.Provider>
</View>
);
};
Loading

0 comments on commit 3933932

Please sign in to comment.