about summary refs log tree commit diff
path: root/src/state
diff options
context:
space:
mode:
Diffstat (limited to 'src/state')
-rw-r--r--src/state/models/cache/image-sizes.ts37
-rw-r--r--src/state/models/cache/link-metas.ts (renamed from src/state/models/link-metas-view.ts)4
-rw-r--r--src/state/models/cache/my-follows.ts (renamed from src/state/models/my-follows.ts)4
-rw-r--r--src/state/models/me.ts6
-rw-r--r--src/state/models/root-store.ts6
5 files changed, 48 insertions, 9 deletions
diff --git a/src/state/models/cache/image-sizes.ts b/src/state/models/cache/image-sizes.ts
new file mode 100644
index 000000000..ff0486278
--- /dev/null
+++ b/src/state/models/cache/image-sizes.ts
@@ -0,0 +1,37 @@
+import {Image} from 'react-native'
+import {Dim} from 'lib/media/manip'
+
+export class ImageSizesCache {
+  sizes: Map<string, Dim> = new Map()
+  private activeRequests: Map<string, Promise<Dim>> = new Map()
+
+  constructor() {}
+
+  get(uri: string): Dim | undefined {
+    return this.sizes.get(uri)
+  }
+
+  async fetch(uri: string): Promise<Dim> {
+    const dim = this.sizes.get(uri)
+    if (dim) {
+      return dim
+    }
+    const prom =
+      this.activeRequests.get(uri) ||
+      new Promise<Dim>(resolve => {
+        Image.getSize(
+          uri,
+          (width: number, height: number) => resolve({width, height}),
+          (err: any) => {
+            console.error('Failed to fetch image dimensions for', uri, err)
+            resolve({width: 0, height: 0})
+          },
+        )
+      })
+    this.activeRequests.set(uri, prom)
+    const res = await prom
+    this.activeRequests.delete(uri)
+    this.sizes.set(uri, res)
+    return res
+  }
+}
diff --git a/src/state/models/link-metas-view.ts b/src/state/models/cache/link-metas.ts
index 59447008a..607968c80 100644
--- a/src/state/models/link-metas-view.ts
+++ b/src/state/models/cache/link-metas.ts
@@ -1,10 +1,10 @@
 import {makeAutoObservable} from 'mobx'
 import {LRUMap} from 'lru_map'
-import {RootStoreModel} from './root-store'
+import {RootStoreModel} from '../root-store'
 import {LinkMeta, getLinkMeta} from 'lib/link-meta/link-meta'
 
 type CacheValue = Promise<LinkMeta> | LinkMeta
-export class LinkMetasViewModel {
+export class LinkMetasCache {
   cache: LRUMap<string, CacheValue> = new LRUMap(100)
 
   constructor(public rootStore: RootStoreModel) {
diff --git a/src/state/models/my-follows.ts b/src/state/models/cache/my-follows.ts
index bf1bf9600..725b7841e 100644
--- a/src/state/models/my-follows.ts
+++ b/src/state/models/cache/my-follows.ts
@@ -1,6 +1,6 @@
 import {makeAutoObservable, runInAction} from 'mobx'
 import {FollowRecord, AppBskyActorProfile, AppBskyActorRef} from '@atproto/api'
-import {RootStoreModel} from './root-store'
+import {RootStoreModel} from '../root-store'
 import {bundleAsync} from 'lib/async/bundle'
 
 const CACHE_TTL = 1000 * 60 * 60 // hourly
@@ -16,7 +16,7 @@ type Profile =
  * follows. It should be periodically refreshed and updated any time
  * the user makes a change to their follows.
  */
-export class MyFollowsModel {
+export class MyFollowsCache {
   // data
   followDidToRecordMap: Record<string, string> = {}
   lastSync = 0
diff --git a/src/state/models/me.ts b/src/state/models/me.ts
index 192e8f19f..120749155 100644
--- a/src/state/models/me.ts
+++ b/src/state/models/me.ts
@@ -2,7 +2,7 @@ import {makeAutoObservable, runInAction} from 'mobx'
 import {RootStoreModel} from './root-store'
 import {FeedModel} from './feed-view'
 import {NotificationsViewModel} from './notifications-view'
-import {MyFollowsModel} from './my-follows'
+import {MyFollowsCache} from './cache/my-follows'
 import {isObj, hasProp} from 'lib/type-guards'
 
 export class MeModel {
@@ -15,7 +15,7 @@ export class MeModel {
   followersCount: number | undefined
   mainFeed: FeedModel
   notifications: NotificationsViewModel
-  follows: MyFollowsModel
+  follows: MyFollowsCache
 
   constructor(public rootStore: RootStoreModel) {
     makeAutoObservable(
@@ -27,7 +27,7 @@ export class MeModel {
       algorithm: 'reverse-chronological',
     })
     this.notifications = new NotificationsViewModel(this.rootStore, {})
-    this.follows = new MyFollowsModel(this.rootStore)
+    this.follows = new MyFollowsCache(this.rootStore)
   }
 
   clear() {
diff --git a/src/state/models/root-store.ts b/src/state/models/root-store.ts
index 03550f1b0..4a8d09b41 100644
--- a/src/state/models/root-store.ts
+++ b/src/state/models/root-store.ts
@@ -13,10 +13,11 @@ import {LogModel} from './log'
 import {SessionModel} from './session'
 import {ShellUiModel} from './ui/shell'
 import {ProfilesViewModel} from './profiles-view'
-import {LinkMetasViewModel} from './link-metas-view'
+import {LinkMetasCache} from './cache/link-metas'
 import {NotificationsViewItemModel} from './notifications-view'
 import {MeModel} from './me'
 import {resetToTab} from '../../Navigation'
+import {ImageSizesCache} from './cache/image-sizes'
 
 export const appInfo = z.object({
   build: z.string(),
@@ -34,7 +35,8 @@ export class RootStoreModel {
   shell = new ShellUiModel(this)
   me = new MeModel(this)
   profiles = new ProfilesViewModel(this)
-  linkMetas = new LinkMetasViewModel(this)
+  linkMetas = new LinkMetasCache(this)
+  imageSizes = new ImageSizesCache()
 
   // HACK
   // this flag is to track the lexicon breaking refactor