1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
/**
* 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)
// eslint-disable-next-line @typescript-eslint/no-shadow
const getImageDimensions = (image: ImageSource): Promise<Dimensions> => {
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) => {
imageDimensionsCache.set(cacheKey, {width, height})
resolve({width, height})
},
() => {
resolve({width: 0, height: 0})
},
)
}
} else {
resolve({width: 0, height: 0})
}
})
}
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
|