mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1/**
2 * Copyright (c) JOB TODAY S.A. and its affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 *
7 */
8
9import {useEffect, useState} from 'react'
10import {Image, ImageURISource} from 'react-native'
11import {Dimensions, ImageSource} from '../@types'
12
13const CACHE_SIZE = 50
14
15type CacheStorageItem = {key: string; value: any}
16
17const createCache = (cacheSize: number) => ({
18 _storage: [] as CacheStorageItem[],
19 get(key: string): any {
20 const {value} =
21 this._storage.find(({key: storageKey}) => storageKey === key) || {}
22
23 return value
24 },
25 set(key: string, value: any) {
26 if (this._storage.length >= cacheSize) {
27 this._storage.shift()
28 }
29
30 this._storage.push({key, value})
31 },
32})
33
34const imageDimensionsCache = createCache(CACHE_SIZE)
35
36const useImageDimensions = (image: ImageSource): Dimensions | null => {
37 const [dimensions, setDimensions] = useState<Dimensions | null>(null)
38
39 // eslint-disable-next-line @typescript-eslint/no-shadow
40 const getImageDimensions = (image: ImageSource): Promise<Dimensions> => {
41 return new Promise(resolve => {
42 if (image.uri) {
43 const source = image as ImageURISource
44 const cacheKey = source.uri as string
45 const imageDimensions = imageDimensionsCache.get(cacheKey)
46 if (imageDimensions) {
47 resolve(imageDimensions)
48 } else {
49 Image.getSizeWithHeaders(
50 // @ts-ignore
51 source.uri,
52 source.headers,
53 (width: number, height: number) => {
54 imageDimensionsCache.set(cacheKey, {width, height})
55 resolve({width, height})
56 },
57 () => {
58 resolve({width: 0, height: 0})
59 },
60 )
61 }
62 } else {
63 resolve({width: 0, height: 0})
64 }
65 })
66 }
67
68 let isImageUnmounted = false
69
70 useEffect(() => {
71 // eslint-disable-next-line @typescript-eslint/no-shadow
72 getImageDimensions(image).then(dimensions => {
73 if (!isImageUnmounted) {
74 setDimensions(dimensions)
75 }
76 })
77
78 return () => {
79 // eslint-disable-next-line react-hooks/exhaustive-deps
80 isImageUnmounted = true
81 }
82 }, [image])
83
84 return dimensions
85}
86
87export default useImageDimensions