about summary refs log tree commit diff
path: root/src/view/com/lightbox/ImageViewing
diff options
context:
space:
mode:
Diffstat (limited to 'src/view/com/lightbox/ImageViewing')
-rw-r--r--src/view/com/lightbox/ImageViewing/@types/index.ts7
-rw-r--r--src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.android.tsx17
-rw-r--r--src/view/com/lightbox/ImageViewing/components/ImageItem/ImageItem.ios.tsx16
-rw-r--r--src/view/com/lightbox/ImageViewing/hooks/useImageDimensions.ts93
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