about summary refs log tree commit diff
path: root/src/state/cache
diff options
context:
space:
mode:
authorPaul Frazee <pfrazee@gmail.com>2023-11-14 12:10:39 -0800
committerGitHub <noreply@github.com>2023-11-14 12:10:39 -0800
commit8e4a3ad5b6c5abac57559f5711261b9868eb0cd1 (patch)
treedaef1dca0312ae135a05cbdad209154ffe80b7c3 /src/state/cache
parent00f8c8b06d2f789c38c5c3416ec195072bbfd450 (diff)
downloadvoidsky-8e4a3ad5b6c5abac57559f5711261b9868eb0cd1.tar.zst
Add Shadow type (#1900)
Diffstat (limited to 'src/state/cache')
-rw-r--r--src/state/cache/post-shadow.ts17
-rw-r--r--src/state/cache/profile-shadow.ts25
-rw-r--r--src/state/cache/types.ts1
3 files changed, 33 insertions, 10 deletions
diff --git a/src/state/cache/post-shadow.ts b/src/state/cache/post-shadow.ts
index c06ed60c4..c49097700 100644
--- a/src/state/cache/post-shadow.ts
+++ b/src/state/cache/post-shadow.ts
@@ -1,6 +1,8 @@
 import {useEffect, useState, useCallback, useRef} from 'react'
 import EventEmitter from 'eventemitter3'
 import {AppBskyFeedDefs} from '@atproto/api'
+import {Shadow} from './types'
+export type {Shadow} from './types'
 
 const emitter = new EventEmitter()
 
@@ -22,7 +24,7 @@ interface CacheEntry {
 export function usePostShadow(
   post: AppBskyFeedDefs.PostView,
   ifAfterTS: number,
-): AppBskyFeedDefs.PostView | typeof POST_TOMBSTONE {
+): Shadow<AppBskyFeedDefs.PostView> | typeof POST_TOMBSTONE {
   const [state, setState] = useState<CacheEntry>({
     ts: Date.now(),
     value: fromPost(post),
@@ -53,13 +55,21 @@ export function usePostShadow(
     firstRun.current = false
   }, [post])
 
-  return state.ts > ifAfterTS ? mergeShadow(post, state.value) : post
+  return state.ts > ifAfterTS
+    ? mergeShadow(post, state.value)
+    : {...post, isShadowed: true}
 }
 
 export function updatePostShadow(uri: string, value: Partial<PostShadow>) {
   emitter.emit(uri, value)
 }
 
+export function isPostShadowed(
+  v: AppBskyFeedDefs.PostView | Shadow<AppBskyFeedDefs.PostView>,
+): v is Shadow<AppBskyFeedDefs.PostView> {
+  return 'isShadowed' in v && !!v.isShadowed
+}
+
 function fromPost(post: AppBskyFeedDefs.PostView): PostShadow {
   return {
     likeUri: post.viewer?.like,
@@ -73,7 +83,7 @@ function fromPost(post: AppBskyFeedDefs.PostView): PostShadow {
 function mergeShadow(
   post: AppBskyFeedDefs.PostView,
   shadow: PostShadow,
-): AppBskyFeedDefs.PostView | typeof POST_TOMBSTONE {
+): Shadow<AppBskyFeedDefs.PostView> | typeof POST_TOMBSTONE {
   if (shadow.isDeleted) {
     return POST_TOMBSTONE
   }
@@ -86,5 +96,6 @@ function mergeShadow(
       like: shadow.likeUri,
       repost: shadow.repostUri,
     },
+    isShadowed: true,
   }
 }
diff --git a/src/state/cache/profile-shadow.ts b/src/state/cache/profile-shadow.ts
index a1cf59954..59f79634d 100644
--- a/src/state/cache/profile-shadow.ts
+++ b/src/state/cache/profile-shadow.ts
@@ -1,6 +1,8 @@
 import {useEffect, useState, useCallback, useRef} from 'react'
 import EventEmitter from 'eventemitter3'
 import {AppBskyActorDefs} from '@atproto/api'
+import {Shadow} from './types'
+export type {Shadow} from './types'
 
 const emitter = new EventEmitter()
 
@@ -20,10 +22,10 @@ type ProfileView =
   | AppBskyActorDefs.ProfileViewBasic
   | AppBskyActorDefs.ProfileViewDetailed
 
-export function useProfileShadow<T extends ProfileView>(
-  profile: T,
+export function useProfileShadow(
+  profile: ProfileView,
   ifAfterTS: number,
-): T {
+): Shadow<ProfileView> {
   const [state, setState] = useState<CacheEntry>({
     ts: Date.now(),
     value: fromProfile(profile),
@@ -54,7 +56,9 @@ export function useProfileShadow<T extends ProfileView>(
     firstRun.current = false
   }, [profile])
 
-  return state.ts > ifAfterTS ? mergeShadow(profile, state.value) : profile
+  return state.ts > ifAfterTS
+    ? mergeShadow(profile, state.value)
+    : {...profile, isShadowed: true}
 }
 
 export function updateProfileShadow(
@@ -64,6 +68,12 @@ export function updateProfileShadow(
   emitter.emit(uri, value)
 }
 
+export function isProfileShadowed<T extends ProfileView>(
+  v: T | Shadow<T>,
+): v is Shadow<T> {
+  return 'isShadowed' in v && !!v.isShadowed
+}
+
 function fromProfile(profile: ProfileView): ProfileShadow {
   return {
     followingUri: profile.viewer?.following,
@@ -72,10 +82,10 @@ function fromProfile(profile: ProfileView): ProfileShadow {
   }
 }
 
-function mergeShadow<T extends ProfileView>(
-  profile: T,
+function mergeShadow(
+  profile: ProfileView,
   shadow: ProfileShadow,
-): T {
+): Shadow<ProfileView> {
   return {
     ...profile,
     viewer: {
@@ -84,5 +94,6 @@ function mergeShadow<T extends ProfileView>(
       muted: shadow.muted,
       blocking: shadow.blockingUri,
     },
+    isShadowed: true,
   }
 }
diff --git a/src/state/cache/types.ts b/src/state/cache/types.ts
new file mode 100644
index 000000000..8bfcc867c
--- /dev/null
+++ b/src/state/cache/types.ts
@@ -0,0 +1 @@
+export type Shadow<T> = T & {isShadowed: true}