Make lightbox use the same cache

This commit is contained in:
Dan Abramov
2024-11-01 02:19:45 +00:00
parent 6b478644e2
commit 0ae5033147
3 changed files with 11 additions and 98 deletions
@@ -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 imageDimensions = useImageDimensions({
src: imageSrc.uri,
knownDimensions: undefined, // TODO: We have those.
})
const committedTransform = useSharedValue(initialTransform)
const panTranslation = useSharedValue({x: 0, y: 0})
const pinchOrigin = useSharedValue({x: 0, y: 0})
@@ -19,8 +19,8 @@ import Animated, {
import {Image} from 'expo-image'
import {useAnimatedScrollHandler} from '#/lib/hooks/useAnimatedScrollHandler_FIXED'
import {useImageDimensions} from '#/lib/media/image-sizes'
import {Dimensions as ImageDimensions, ImageSource} from '../../@types'
import useImageDimensions from '../../hooks/useImageDimensions'
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 imageDimensions = useImageDimensions({
src: imageSrc.uri,
knownDimensions: undefined, // TODO: We have those.
})
const maxZoomScale = imageDimensions
? (imageDimensions.width / SCREEN.width) * MAX_ORIGINAL_IMAGE_ZOOM
: 1
@@ -179,7 +182,7 @@ const styles = StyleSheet.create({
})
const getZoomRectAfterDoubleTap = (
imageDimensions: ImageDimensions | null,
imageDimensions: ImageDimensions | undefined,
touchX: number,
touchY: number,
): {
@@ -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