From fd6b8fcbf140f178180134753374d1baa918878c Mon Sep 17 00:00:00 2001 From: Eric Bailey Date: Tue, 27 Jan 2026 12:16:54 -0600 Subject: [PATCH] Fix Live Now not showing for non-streamer (#9773) * Fix Live Now not showing for non-streamer * Rename for clarity * Logged out users too --- src/lib/actor-status.ts | 10 +++++++--- src/state/service-config.tsx | 12 +++++++++++- src/view/com/posts/PostFeed.tsx | 4 ++-- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/lib/actor-status.ts b/src/lib/actor-status.ts index 495d6f4e66..02d5eabed6 100644 --- a/src/lib/actor-status.ts +++ b/src/lib/actor-status.ts @@ -20,7 +20,7 @@ export function useActorStatus(actor?: bsky.profile.AnyProfileView) { void tick // revalidate every minute if (shadowed && 'status' in shadowed && shadowed.status) { - const isValid = validateStatus(shadowed.status, config) + const isValid = isStatusValidForViewers(shadowed.status, config) const isDisabled = shadowed.status.isDisabled || false const isActive = isStatusStillActive(shadowed.status.expiresAt) if (isValid && !isDisabled && isActive) { @@ -64,7 +64,11 @@ export function isStatusStillActive(timeStr: string | undefined) { return isAfter(expiry, now) } -export function validateStatus( +/** + * Validates whether the live status is valid for display in the app. Does NOT + * validate if the status is valid for the acting user e.g. as they go live. + */ +export function isStatusValidForViewers( status: AppBskyActorDefs.StatusView, config: LiveNowConfig, ) { @@ -72,7 +76,7 @@ export function validateStatus( try { if (AppBskyEmbedExternal.isView(status.embed)) { const url = new URL(status.embed.external.uri) - return config.allowedDomains.has(url.hostname) + return config.allSupportedDomains.has(url.hostname) } else { return false } diff --git a/src/state/service-config.tsx b/src/state/service-config.tsx index 21c450de46..7612f5825c 100644 --- a/src/state/service-config.tsx +++ b/src/state/service-config.tsx @@ -90,17 +90,27 @@ const DEFAULT_LIVE_ALLOWED_DOMAINS = [ ] export type LiveNowConfig = { allowedDomains: Set + allSupportedDomains: Set } export function useLiveNowConfig(): LiveNowConfig { const ctx = useContext(LiveNowContext) const canGoLive = useCanGoLive() const {currentAccount} = useSession() - if (!currentAccount?.did || !canGoLive) return {allowedDomains: new Set()} + const allVipDomains = new Set(ctx.flatMap(live => live.domains)) + const allSupportedDomains = new Set( + DEFAULT_LIVE_ALLOWED_DOMAINS.concat(Array.from(allVipDomains)), + ) + if (!currentAccount?.did || !canGoLive) + return { + allowedDomains: new Set(), + allSupportedDomains, + } const vip = ctx.find(live => live.did === currentAccount.did) return { allowedDomains: new Set( DEFAULT_LIVE_ALLOWED_DOMAINS.concat(vip ? vip.domains : []), ), + allSupportedDomains, } } diff --git a/src/view/com/posts/PostFeed.tsx b/src/view/com/posts/PostFeed.tsx index de006965aa..3c8d25faf8 100644 --- a/src/view/com/posts/PostFeed.tsx +++ b/src/view/com/posts/PostFeed.tsx @@ -27,7 +27,7 @@ import {msg} from '@lingui/macro' import {useLingui} from '@lingui/react' import {useQueryClient} from '@tanstack/react-query' -import {isStatusStillActive, validateStatus} from '#/lib/actor-status' +import {isStatusStillActive, isStatusValidForViewers} from '#/lib/actor-status' import {DISCOVER_FEED_URI, KNOWN_SHUTDOWN_FEEDS} from '#/lib/constants' import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender' import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback' @@ -948,7 +948,7 @@ let PostFeed = ({ const actor = post.author if ( actor.status && - validateStatus(actor.status, liveNowConfig) && + isStatusValidForViewers(actor.status, liveNowConfig) && isStatusStillActive(actor.status.expiresAt) ) { if (!seenActorWithStatusRef.current.has(actor.did)) {