Add custom AnimatedImage component

This also fixes the white flashing when loading images

Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
2023-07-29 20:56:37 +03:00
parent a5911ff617
commit 391e232bf7
6 changed files with 62 additions and 27 deletions

18
package-lock.json generated
View File

@@ -10,7 +10,6 @@
"hasInstallScript": true,
"dependencies": {
"@bankify/redux-persist-realm": "^0.1.3",
"@likashefqet/react-native-image-zoom": "^1.3.0",
"@react-native-clipboard/clipboard": "^1.11.2",
"@react-native-community/hooks": "^3.0.0",
"@react-navigation/bottom-tabs": "^6.5.8",
@@ -2991,17 +2990,6 @@
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
"integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw=="
},
"node_modules/@likashefqet/react-native-image-zoom": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@likashefqet/react-native-image-zoom/-/react-native-image-zoom-1.3.0.tgz",
"integrity": "sha512-PLRd1hNMHe9LUn8b4rmLt86282geuaqP4Qd2rFWIloxMS2ePNTIaNlEUu3T3LaO8Pg9vhVV97TxfFeU8F+tcYQ==",
"peerDependencies": {
"react": ">=16.x.x",
"react-native": ">=0.62.x",
"react-native-gesture-handler": ">=2.x.x",
"react-native-reanimated": ">=2.x.x"
}
},
"node_modules/@nicolo-ribaudo/eslint-scope-5-internals": {
"version": "5.1.1-v1",
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz",
@@ -17940,12 +17928,6 @@
}
}
},
"@likashefqet/react-native-image-zoom": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@likashefqet/react-native-image-zoom/-/react-native-image-zoom-1.3.0.tgz",
"integrity": "sha512-PLRd1hNMHe9LUn8b4rmLt86282geuaqP4Qd2rFWIloxMS2ePNTIaNlEUu3T3LaO8Pg9vhVV97TxfFeU8F+tcYQ==",
"requires": {}
},
"@nicolo-ribaudo/eslint-scope-5-internals": {
"version": "5.1.1-v1",
"resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz",

View File

@@ -15,7 +15,6 @@
},
"dependencies": {
"@bankify/redux-persist-realm": "^0.1.3",
"@likashefqet/react-native-image-zoom": "^1.3.0",
"@react-native-clipboard/clipboard": "^1.11.2",
"@react-native-community/hooks": "^3.0.0",
"@react-navigation/bottom-tabs": "^6.5.8",

View File

@@ -0,0 +1,56 @@
import React, { ComponentProps, useMemo } from 'react';
import { Image } from 'react-native';
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
import Animated, {
useAnimatedStyle,
useSharedValue,
withSpring,
} from 'react-native-reanimated';
const AnimatedImage = ({ ...props }: ComponentProps<typeof Image>) => {
const scale = useSharedValue(1);
const translateX = useSharedValue(0);
const translateY = useSharedValue(0);
const animatedStyles = useAnimatedStyle(() => {
return {
transform: [
{ translateX: translateX.value },
{ translateY: translateY.value },
{ scale: scale.value },
],
};
});
const gesture = useMemo(
() =>
Gesture.Simultaneous(
Gesture.Pinch()
.onUpdate(event => {
scale.value = event.scale;
})
.onFinalize(() => {
scale.value = withSpring(1);
}),
Gesture.Pan()
.minPointers(2)
.onUpdate(event => {
translateX.value = event.translationX;
translateY.value = event.translationY;
})
.onFinalize(() => {
translateX.value = withSpring(0);
translateY.value = withSpring(0);
}),
),
[scale, translateX, translateY],
);
return (
<GestureDetector gesture={gesture}>
<Animated.Image {...props} style={[props.style, animatedStyles]} />
</GestureDetector>
);
};
export default AnimatedImage;

View File

@@ -1,11 +1,13 @@
export {
MemesList,
MemeEditor,
MemeFail,
MemesHeader,
MemeTagSelector,
MemeViewItem,
} from './memes';
export { TagChip, TagEditor, TagPreview, TagRow, TagsHeader } from './tags';
export { default as AnimatedImage } from './animatedImage';
export { default as FloatingActionButton } from './floatingActionButton';
export { default as HideableBottomNavigationBar } from './hideableBottomNavigationBar';
export { default as HideableHeader } from './hideableHeader';

View File

@@ -3,8 +3,7 @@ import { HelperText, Text, TextInput, useTheme } from 'react-native-paper';
import { Image } from 'react-native';
import { useSafeAreaFrame } from 'react-native-safe-area-context';
import { useImageDimensions } from '@react-native-community/hooks/lib/useImageDimensions';
import LoadingView from '../loadingView';
import { MemeFail, MemeTagSelector } from '.';
import { MemeFail, MemeTagSelector, LoadingView } from '..';
import { Tag } from '../../database';
import { StringValidationResult, validateMemeTitle } from '../../utilities';

View File

@@ -1,14 +1,12 @@
import React from 'react';
import { ImageZoom } from '@likashefqet/react-native-image-zoom';
import { StyleSheet, View } from 'react-native';
import { useSafeAreaFrame } from 'react-native-safe-area-context';
import { useImageDimensions } from '@react-native-community/hooks';
import { AndroidScoped } from 'react-native-file-access';
import LoadingView from '../loadingView';
import { Meme } from '../../database';
import MemeFail from './memeFail';
import { useSelector } from 'react-redux';
import { Meme } from '../../database';
import { RootState } from '../../state';
import { AnimatedImage, LoadingView, MemeFail } from '..';
const memeViewItemStyles = StyleSheet.create({
view: {
@@ -47,7 +45,7 @@ const MemeViewItem = ({ meme }: { meme: Meme }) => {
iconSize={50}
/>
) : (
<ImageZoom
<AnimatedImage
source={{ uri }}
style={
dimensions.aspectRatio > width / (height - 128)
@@ -61,7 +59,6 @@ const MemeViewItem = ({ meme }: { meme: Meme }) => {
height: height - 128,
}
}
minScale={0.5}
/>
)}
</View>