Files
bsky-social-app/src/lib/media/image-sizes.ts
T
Dan Abramov af11271ff7 Make image-sizes LRU
Code is copy paste from useImageDimensions.ts
2024-11-01 22:53:14 +00:00

56 lines
1.4 KiB
TypeScript

import {Image} from 'react-native'
import type {Dimensions} from '#/lib/media/types'
type CacheStorageItem<T> = {key: string; value: T}
const createCache = <T>(cacheSize: number) => ({
_storage: [] as CacheStorageItem<T>[],
get(key: string) {
const {value} =
this._storage.find(({key: storageKey}) => storageKey === key) || {}
return value
},
set(key: string, value: T) {
if (this._storage.length >= cacheSize) {
this._storage.shift()
}
this._storage.push({key, value})
},
})
const sizes = createCache<Dimensions>(50)
const activeRequests: Map<string, Promise<Dimensions>> = new Map()
export function get(uri: string): Dimensions | undefined {
return sizes.get(uri)
}
export function fetch(uri: string): Promise<Dimensions> {
const dims = sizes.get(uri)
if (dims) {
return Promise.resolve(dims)
}
const activeRequest = activeRequests.get(uri)
if (activeRequest) {
return activeRequest
}
const prom = new Promise<Dimensions>((resolve, reject) => {
Image.getSize(
uri,
(width: number, height: number) => {
const size = {width, height}
sizes.set(uri, size)
resolve(size)
},
(err: any) => {
console.error('Failed to fetch image dimensions for', uri, err)
reject(new Error('Could not fetch dimensions'))
},
)
}).finally(() => {
activeRequests.delete(uri)
})
activeRequests.set(uri, prom)
return prom
}