diff options
Diffstat (limited to 'src/lib/actor-status.ts')
-rw-r--r-- | src/lib/actor-status.ts | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/src/lib/actor-status.ts b/src/lib/actor-status.ts new file mode 100644 index 000000000..30921a88a --- /dev/null +++ b/src/lib/actor-status.ts @@ -0,0 +1,51 @@ +import {useMemo} from 'react' +import { + type $Typed, + type AppBskyActorDefs, + type AppBskyEmbedExternal, +} from '@atproto/api' +import {isAfter, parseISO} from 'date-fns' + +import {useMaybeProfileShadow} from '#/state/cache/profile-shadow' +import {useTickEveryMinute} from '#/state/shell' +import {temp__canBeLive, temp__isStatusValid} from '#/components/live/temp' +import type * as bsky from '#/types/bsky' + +export function useActorStatus(actor?: bsky.profile.AnyProfileView) { + const shadowed = useMaybeProfileShadow(actor) + const tick = useTickEveryMinute() + return useMemo(() => { + tick! // revalidate every minute + + if ( + shadowed && + temp__canBeLive(shadowed) && + 'status' in shadowed && + shadowed.status && + temp__isStatusValid(shadowed.status) && + isStatusStillActive(shadowed.status.expiresAt) + ) { + return { + isActive: true, + status: 'app.bsky.actor.status#live', + embed: shadowed.status.embed as $Typed<AppBskyEmbedExternal.View>, // temp_isStatusValid asserts this + expiresAt: shadowed.status.expiresAt!, // isStatusStillActive asserts this + record: shadowed.status.record, + } satisfies AppBskyActorDefs.StatusView + } else { + return { + status: '', + isActive: false, + record: {}, + } satisfies AppBskyActorDefs.StatusView + } + }, [shadowed, tick]) +} + +export function isStatusStillActive(timeStr: string | undefined) { + if (!timeStr) return false + const now = new Date() + const expiry = parseISO(timeStr) + + return isAfter(expiry, now) +} |