From 13ee5df721443a6d00f5d5c854128ed12feb903f Mon Sep 17 00:00:00 2001 From: Harry L <5049950+LooneyH@users.noreply.github.com> Date: Tue, 30 Jun 2026 21:59:17 +0100 Subject: [PATCH] Restore link in Go Live prompt if status record present (#10636) Co-authored-by: Eric Bailey --- .../liveNow/components/EditLiveDialog.tsx | 19 +++++--------- .../liveNow/components/GoLiveDialog.tsx | 8 +++++- src/features/liveNow/utils.ts | 25 +++++++++++++++++++ 3 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/features/liveNow/components/EditLiveDialog.tsx b/src/features/liveNow/components/EditLiveDialog.tsx index 6d95d43859..cf913541a1 100644 --- a/src/features/liveNow/components/EditLiveDialog.tsx +++ b/src/features/liveNow/components/EditLiveDialog.tsx @@ -1,10 +1,6 @@ import {useMemo, useState} from 'react' import {View} from 'react-native' -import { - type AppBskyActorDefs, - AppBskyActorStatus, - type AppBskyEmbedExternal, -} from '@atproto/api' +import {type AppBskyActorDefs, type AppBskyEmbedExternal} from '@atproto/api' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Trans} from '@lingui/react/macro' @@ -24,6 +20,7 @@ import {Loader} from '#/components/Loader' import {Text} from '#/components/Typography' import { displayDuration, + getValidLiveStatusRecord, useLiveLinkMetaQuery, useRemoveLiveStatusMutation, useUpsertLiveStatusMutation, @@ -74,14 +71,10 @@ function DialogInner({ error: linkMetaError, } = useLiveLinkMetaQuery(debouncedUrl) - const record = useMemo(() => { - if (!AppBskyActorStatus.isRecord(status.record)) return null - const validation = AppBskyActorStatus.validateRecord(status.record) - if (validation.success) { - return validation.value - } - return null - }, [status]) + const record = useMemo( + () => getValidLiveStatusRecord(status.record), + [status], + ) const { mutate: goLive, diff --git a/src/features/liveNow/components/GoLiveDialog.tsx b/src/features/liveNow/components/GoLiveDialog.tsx index b22585ab1e..72438fdddc 100644 --- a/src/features/liveNow/components/GoLiveDialog.tsx +++ b/src/features/liveNow/components/GoLiveDialog.tsx @@ -20,7 +20,9 @@ import * as Select from '#/components/Select' import {Text} from '#/components/Typography' import { displayDuration, + getLiveLinkFromStatusRecord, getLiveServiceNames, + useActorStatus, useLiveLinkMetaQuery, useLiveNowConfig, useUpsertLiveStatusMutation, @@ -50,16 +52,20 @@ function DialogInner({profile}: {profile: bsky.profile.AnyProfileView}) { const control = Dialog.useDialogContext() const {_, i18n} = useLingui() const t = useTheme() - const [liveLink, setLiveLink] = useState('') const [liveLinkError, setLiveLinkError] = useState('') const [duration, setDuration] = useState(60) const moderationOpts = useModerationOpts() const tick = useTickEveryMinute() const liveNowConfig = useLiveNowConfig() + const status = useActorStatus(profile) const {formatted: allowedServices} = getLiveServiceNames( liveNowConfig.currentAccountAllowedHosts, ) + const [liveLink, setLiveLink] = useState(() => + getLiveLinkFromStatusRecord(status.record), + ) + const time = useCallback( (offset: number) => { void tick diff --git a/src/features/liveNow/utils.ts b/src/features/liveNow/utils.ts index f2a7c8c62f..a7326cd8e9 100644 --- a/src/features/liveNow/utils.ts +++ b/src/features/liveNow/utils.ts @@ -1,7 +1,32 @@ +import {AppBskyActorStatus, AppBskyEmbedExternal} from '@atproto/api' import {type I18n} from '@lingui/core' import {plural} from '@lingui/core/macro' import psl from 'psl' +/** + * Validates a raw status record and returns the typed record, or null if the + * value is not a valid `app.bsky.actor.status` record. + */ +export function getValidLiveStatusRecord( + statusRecord: unknown, +): AppBskyActorStatus.Record | null { + if (!AppBskyActorStatus.isRecord(statusRecord)) return null + const validation = AppBskyActorStatus.validateRecord(statusRecord) + if (!validation.success) return null + return validation.value +} + +/** + * Extracts the external link URI from a status record, if present. Returns an + * empty string when the record is invalid or has no external embed. + */ +export function getLiveLinkFromStatusRecord(statusRecord: unknown): string { + const record = getValidLiveStatusRecord(statusRecord) + if (!record) return '' + if (!AppBskyEmbedExternal.isMain(record.embed)) return '' + return record.embed.external.uri +} + export function displayDuration(i18n: I18n, durationInMinutes: number) { const roundedDurationInMinutes = Math.round(durationInMinutes) const hours = Math.floor(roundedDurationInMinutes / 60)