From 39e7132fd8446532e6150a9ab164461dd04d3008 Mon Sep 17 00:00:00 2001 From: Eric Bailey Date: Tue, 27 Jan 2026 16:44:27 -0600 Subject: [PATCH] [APP-1784] Proper fix for Live Now status not showing (#9779) * Be sure to validate if actor is allowed to be live on certain domain * Rename for clarity * Memoize --- src/components/live/GoLiveDialog.tsx | 2 +- src/components/live/queries.ts | 6 ++-- src/lib/actor-status.ts | 8 +++++- src/state/service-config.tsx | 43 +++++++++++++++++----------- 4 files changed, 38 insertions(+), 21 deletions(-) diff --git a/src/components/live/GoLiveDialog.tsx b/src/components/live/GoLiveDialog.tsx index 72627e0248..ac51e87527 100644 --- a/src/components/live/GoLiveDialog.tsx +++ b/src/components/live/GoLiveDialog.tsx @@ -55,7 +55,7 @@ function DialogInner({profile}: {profile: bsky.profile.AnyProfileView}) { const tick = useTickEveryMinute() const liveNowConfig = useLiveNowConfig() const {formatted: allowedServices} = getLiveServiceNames( - liveNowConfig.allowedDomains, + liveNowConfig.currentAccountAllowedHosts, ) const time = useCallback( diff --git a/src/components/live/queries.ts b/src/components/live/queries.ts index 21a5e9048e..3c2534872c 100644 --- a/src/components/live/queries.ts +++ b/src/components/live/queries.ts @@ -31,8 +31,10 @@ export function useLiveLinkMetaQuery(url: string | null) { queryFn: async () => { if (!url) return undefined const urlp = new URL(url) - if (!liveNowConfig.allowedDomains.has(urlp.hostname)) { - const {formatted} = getLiveServiceNames(liveNowConfig.allowedDomains) + if (!liveNowConfig.currentAccountAllowedHosts.has(urlp.hostname)) { + const {formatted} = getLiveServiceNames( + liveNowConfig.currentAccountAllowedHosts, + ) throw new Error( _( msg`This service is not supported while the Live feature is in beta. Allowed services: ${formatted}.`, diff --git a/src/lib/actor-status.ts b/src/lib/actor-status.ts index 02d5eabed6..89a3a163de 100644 --- a/src/lib/actor-status.ts +++ b/src/lib/actor-status.ts @@ -3,6 +3,7 @@ import { type $Typed, type AppBskyActorDefs, AppBskyEmbedExternal, + AtUri, } from '@atproto/api' import {isAfter, parseISO} from 'date-fns' @@ -73,10 +74,15 @@ export function isStatusValidForViewers( config: LiveNowConfig, ) { if (status.status !== 'app.bsky.actor.status#live') return false + if (!status.uri) return false // should not happen, just backwards compat try { + const {host: liveDid} = new AtUri(status.uri) if (AppBskyEmbedExternal.isView(status.embed)) { const url = new URL(status.embed.external.uri) - return config.allSupportedDomains.has(url.hostname) + const exception = config.allowedHostsExceptionsByDid.get(liveDid) + const isValidException = exception ? exception.has(url.hostname) : false + const isValidForAnyone = config.defaultAllowedHosts.has(url.hostname) + return isValidException || isValidForAnyone } else { return false } diff --git a/src/state/service-config.tsx b/src/state/service-config.tsx index 7612f5825c..29fa6bec90 100644 --- a/src/state/service-config.tsx +++ b/src/state/service-config.tsx @@ -89,29 +89,38 @@ const DEFAULT_LIVE_ALLOWED_DOMAINS = [ 'www.bluecast.app', ] export type LiveNowConfig = { - allowedDomains: Set - allSupportedDomains: Set + currentAccountAllowedHosts: Set + defaultAllowedHosts: Set + allowedHostsExceptionsByDid: Map> } export function useLiveNowConfig(): LiveNowConfig { const ctx = useContext(LiveNowContext) const canGoLive = useCanGoLive() const {currentAccount} = useSession() - 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, + return useMemo(() => { + const defaultAllowedHosts = new Set(DEFAULT_LIVE_ALLOWED_DOMAINS) + const allowedHostsExceptionsByDid = new Map>() + for (const live of ctx) { + allowedHostsExceptionsByDid.set( + live.did, + new Set(DEFAULT_LIVE_ALLOWED_DOMAINS.concat(live.domains)), + ) } - const vip = ctx.find(live => live.did === currentAccount.did) - return { - allowedDomains: new Set( - DEFAULT_LIVE_ALLOWED_DOMAINS.concat(vip ? vip.domains : []), - ), - allSupportedDomains, - } + if (!currentAccount?.did || !canGoLive) + return { + currentAccountAllowedHosts: new Set(), + defaultAllowedHosts, + allowedHostsExceptionsByDid, + } + const vip = ctx.find(live => live.did === currentAccount.did) + return { + currentAccountAllowedHosts: new Set( + DEFAULT_LIVE_ALLOWED_DOMAINS.concat(vip ? vip.domains : []), + ), + defaultAllowedHosts, + allowedHostsExceptionsByDid, + } + }, [ctx, currentAccount, canGoLive]) } export function useCanGoLive() {