diff options
Diffstat (limited to 'src/view/com/lightbox/ImageViewing')
4 files changed, 24 insertions, 109 deletions
diff --git a/src/view/com/lightbox/ImageViewing/@types/index.ts b/src/view/com/lightbox/ImageViewing/@types/index.ts index 8fdc3f364..f5ab8bba9 100644 --- a/src/view/com/lightbox/ImageViewing/@types/index.ts +++ b/src/view/com/lightbox/ImageViewing/@types/index.ts @@ -16,4 +16,9 @@ export type Position = { y: number } -export type ImageSource = {uri: string; thumbUri: string; alt?: string} +export type ImageSource = { + uri: string + thumbUri: string + alt?: string + dimensions: Dimensions | null +} diff --git a/src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.android.tsx b/src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.android.tsx index 3de15b379..487acf931 100644 --- a/src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.android.tsx +++ b/src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.android.tsx @@ -12,8 +12,8 @@ import Animated, { } from 'react-native-reanimated' import {Image} from 'expo-image' +import {useImageDimensions} from '#/lib/media/image-sizes' import type {Dimensions as ImageDimensions, ImageSource} from '../../@types' -import useImageDimensions from '../../hooks/useImageDimensions' import { applyRounding, createTransform, @@ -52,7 +52,10 @@ const ImageItem = ({ isScrollViewBeingDragged, }: Props) => { const [isScaled, setIsScaled] = useState(false) - const imageDimensions = useImageDimensions(imageSrc) + const [imageAspect, imageDimensions] = useImageDimensions({ + src: imageSrc.uri, + knownDimensions: imageSrc.dimensions, + }) const committedTransform = useSharedValue(initialTransform) const panTranslation = useSharedValue({x: 0, y: 0}) const pinchOrigin = useSharedValue({x: 0, y: 0}) @@ -119,12 +122,12 @@ const ImageItem = ({ candidateTransform: TransformMatrix, ) { 'worklet' - if (!imageDimensions) { + if (!imageAspect) { return [0, 0] } const [nextTranslateX, nextTranslateY, nextScale] = readTransform(candidateTransform) - const scaledDimensions = getScaledDimensions(imageDimensions, nextScale) + const scaledDimensions = getScaledDimensions(imageAspect, nextScale) const clampedTranslateX = clampTranslation( nextTranslateX, scaledDimensions.width, @@ -248,7 +251,7 @@ const ImageItem = ({ .numberOfTaps(2) .onEnd(e => { 'worklet' - if (!imageDimensions) { + if (!imageDimensions || !imageAspect) { return } const [, , committedScale] = readTransform(committedTransform.value) @@ -260,7 +263,6 @@ const ImageItem = ({ } // Try to zoom in so that we get rid of the black bars (whatever the orientation was). - const imageAspect = imageDimensions.width / imageDimensions.height const screenAspect = SCREEN.width / SCREEN.height const candidateScale = Math.max( imageAspect / screenAspect, @@ -363,11 +365,10 @@ const styles = StyleSheet.create({ }) function getScaledDimensions( - imageDimensions: ImageDimensions, + imageAspect: number, scale: number, ): ImageDimensions { 'worklet' - const imageAspect = imageDimensions.width / imageDimensions.height const screenAspect = SCREEN.width / SCREEN.height const isLandscape = imageAspect > screenAspect if (isLandscape) { diff --git a/src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.ios.tsx b/src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.ios.tsx index f21953498..a96a1c913 100644 --- a/src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.ios.tsx +++ b/src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.ios.tsx @@ -19,8 +19,8 @@ import Animated, { import {Image} from 'expo-image' import {useAnimatedScrollHandler} from '#/lib/hooks/useAnimatedScrollHandler_FIXED' -import {Dimensions as ImageDimensions, ImageSource} from '../../@types' -import useImageDimensions from '../../hooks/useImageDimensions' +import {useImageDimensions} from '#/lib/media/image-sizes' +import {ImageSource} from '../../@types' const SWIPE_CLOSE_OFFSET = 75 const SWIPE_CLOSE_VELOCITY = 1 @@ -47,7 +47,10 @@ const ImageItem = ({ const scrollViewRef = useAnimatedRef<Animated.ScrollView>() const translationY = useSharedValue(0) const [scaled, setScaled] = useState(false) - const imageDimensions = useImageDimensions(imageSrc) + const [imageAspect, imageDimensions] = useImageDimensions({ + src: imageSrc.uri, + knownDimensions: imageSrc.dimensions, + }) const maxZoomScale = imageDimensions ? (imageDimensions.width / SCREEN.width) * MAX_ORIGINAL_IMAGE_ZOOM : 1 @@ -99,7 +102,7 @@ const ImageItem = ({ const willZoom = !scaled if (willZoom) { nextZoomRect = getZoomRectAfterDoubleTap( - imageDimensions, + imageAspect, absoluteX, absoluteY, ) @@ -179,7 +182,7 @@ const styles = StyleSheet.create({ }) const getZoomRectAfterDoubleTap = ( - imageDimensions: ImageDimensions | null, + imageAspect: number | undefined, touchX: number, touchY: number, ): { @@ -188,7 +191,7 @@ const getZoomRectAfterDoubleTap = ( width: number height: number } => { - if (!imageDimensions) { + if (!imageAspect) { return { x: 0, y: 0, @@ -199,7 +202,6 @@ const getZoomRectAfterDoubleTap = ( // First, let's figure out how much we want to zoom in. // We want to try to zoom in at least close enough to get rid of black bars. - const imageAspect = imageDimensions.width / imageDimensions.height const screenAspect = SCREEN.width / SCREEN.height const zoom = Math.max( imageAspect / screenAspect, diff --git a/src/view/com/lightbox/ImageViewing/hooks/useImageDimensions.ts b/src/view/com/lightbox/ImageViewing/hooks/useImageDimensions.ts deleted file mode 100644 index 8b5bc1b87..000000000 --- a/src/view/com/lightbox/ImageViewing/hooks/useImageDimensions.ts +++ /dev/null @@ -1,93 +0,0 @@ -/** - * Copyright (c) JOB TODAY S.A. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - */ - -import {useEffect, useState} from 'react' -import {Image, ImageURISource} from 'react-native' - -import {Dimensions, ImageSource} from '../@types' - -const CACHE_SIZE = 50 - -type CacheStorageItem = {key: string; value: any} - -const createCache = (cacheSize: number) => ({ - _storage: [] as CacheStorageItem[], - get(key: string): any { - const {value} = - this._storage.find(({key: storageKey}) => storageKey === key) || {} - - return value - }, - set(key: string, value: any) { - if (this._storage.length >= cacheSize) { - this._storage.shift() - } - - this._storage.push({key, value}) - }, -}) - -const imageDimensionsCache = createCache(CACHE_SIZE) - -const useImageDimensions = (image: ImageSource): Dimensions | null => { - const [dimensions, setDimensions] = useState<Dimensions | null>(null) - - const getImageDimensions = ( - image: ImageSource, - ): Promise<Dimensions | null> => { - return new Promise(resolve => { - if (image.uri) { - const source = image as ImageURISource - const cacheKey = source.uri as string - const imageDimensions = imageDimensionsCache.get(cacheKey) - if (imageDimensions) { - resolve(imageDimensions) - } else { - Image.getSizeWithHeaders( - // @ts-ignore - source.uri, - source.headers, - (width: number, height: number) => { - if (width > 0 && height > 0) { - imageDimensionsCache.set(cacheKey, {width, height}) - resolve({width, height}) - } else { - resolve(null) - } - }, - () => { - resolve(null) - }, - ) - } - } else { - resolve(null) - } - }) - } - - let isImageUnmounted = false - - useEffect(() => { - // eslint-disable-next-line @typescript-eslint/no-shadow - getImageDimensions(image).then(dimensions => { - if (!isImageUnmounted) { - setDimensions(dimensions) - } - }) - - return () => { - // eslint-disable-next-line react-hooks/exhaustive-deps - isImageUnmounted = true - } - }, [image]) - - return dimensions -} - -export default useImageDimensions |