From 858d4c8c8811ca8e16bffe3bfe0d541e576177ec Mon Sep 17 00:00:00 2001
From: Paul Frazee <pfrazee@gmail.com>
Date: Tue, 21 Mar 2023 12:59:10 -0500
Subject: Introduce an image sizes cache to improve feed layouts (close #213)
 (#335)

* Introduce an image sizes cache to improve feed layouts (close #213)

* Clear out resolved promises from the image cache
---
 src/view/com/util/images/AutoSizedImage.tsx | 56 ++++++++++++++++++++---------
 1 file changed, 39 insertions(+), 17 deletions(-)

(limited to 'src/view/com/util/images/AutoSizedImage.tsx')

diff --git a/src/view/com/util/images/AutoSizedImage.tsx b/src/view/com/util/images/AutoSizedImage.tsx
index 0443c7be4..24dbe6a52 100644
--- a/src/view/com/util/images/AutoSizedImage.tsx
+++ b/src/view/com/util/images/AutoSizedImage.tsx
@@ -1,7 +1,15 @@
 import React from 'react'
-import {StyleProp, StyleSheet, TouchableOpacity, ViewStyle} from 'react-native'
-import Image, {OnLoadEvent} from 'view/com/util/images/Image'
+import {
+  Image,
+  StyleProp,
+  StyleSheet,
+  TouchableOpacity,
+  ViewStyle,
+} from 'react-native'
+// import Image from 'view/com/util/images/Image'
 import {clamp} from 'lib/numbers'
+import {useStores} from 'state/index'
+import {Dim} from 'lib/media/manip'
 
 export const DELAY_PRESS_IN = 500
 const MIN_ASPECT_RATIO = 0.33 // 1/3
@@ -22,16 +30,27 @@ export function AutoSizedImage({
   style?: StyleProp<ViewStyle>
   children?: React.ReactNode
 }) {
-  const [aspectRatio, setAspectRatio] = React.useState<number>(1)
-  const onLoad = (e: OnLoadEvent) => {
-    setAspectRatio(
-      clamp(
-        e.nativeEvent.width / e.nativeEvent.height,
-        MIN_ASPECT_RATIO,
-        MAX_ASPECT_RATIO,
-      ),
-    )
-  }
+  const store = useStores()
+  const [dim, setDim] = React.useState<Dim | undefined>(
+    store.imageSizes.get(uri),
+  )
+  const [aspectRatio, setAspectRatio] = React.useState<number>(
+    dim ? calc(dim) : 1,
+  )
+  React.useEffect(() => {
+    let aborted = false
+    if (dim) {
+      return
+    }
+    store.imageSizes.fetch(uri).then(newDim => {
+      if (aborted) {
+        return
+      }
+      setDim(newDim)
+      setAspectRatio(calc(newDim))
+    })
+  }, [dim, setDim, setAspectRatio, store, uri])
+
   return (
     <TouchableOpacity
       onPress={onPress}
@@ -39,16 +58,19 @@ export function AutoSizedImage({
       onPressIn={onPressIn}
       delayPressIn={DELAY_PRESS_IN}
       style={[styles.container, style]}>
-      <Image
-        style={[styles.image, {aspectRatio}]}
-        source={{uri}}
-        onLoad={onLoad}
-      />
+      <Image style={[styles.image, {aspectRatio}]} source={{uri}} />
       {children}
     </TouchableOpacity>
   )
 }
 
+function calc(dim: Dim) {
+  if (dim.width === 0 || dim.height === 0) {
+    return 1
+  }
+  return clamp(dim.width / dim.height, MIN_ASPECT_RATIO, MAX_ASPECT_RATIO)
+}
+
 const styles = StyleSheet.create({
   container: {
     overflow: 'hidden',
-- 
cgit 1.4.1

