Compare commits

...

17 Commits

Author SHA1 Message Date
Eric Bailey a61dbf7707 Ah yeah let's not override types 2026-01-09 10:12:35 -06:00
Eric Bailey ef72710399 Status reports should only go to bsky 2026-01-08 17:39:53 -06:00
Eric Bailey dbe1925a96 Fix types 2026-01-08 15:57:06 -06:00
Eric Bailey 8b27043051 Go live (disabled) 2026-01-08 15:43:36 -06:00
Eric Bailey 5166f670e7 Guard against chat profile views 2026-01-08 15:42:00 -06:00
Eric Bailey 7a6a30277d Merge remote-tracking branch 'origin/main' into app-1750
* origin/main:
  [AAv2] Improve minimum age handling (#9650)
  Handle AA config failure (#9660)
  Fix full-screen back gesture over PagerView on iOS 26 (#9659)
  Bump version to v1.114 (#9661)
  Unify build concurrency to one build per platform (#9655)
2026-01-08 15:38:17 -06:00
Eric Bailey 2671f1d85e Fix types 2026-01-08 15:31:34 -06:00
Eric Bailey 6b91559a79 Refactor useActorStatus, add disablement and appeal dialog 2026-01-08 15:20:46 -06:00
Eric Bailey b9503b7df3 Bump api sdk 2026-01-08 14:37:43 -06:00
Samuel Newman c535ca82a8 Update yarn.lock 2026-01-08 10:51:13 +02:00
Samuel Newman a0c43b0dcf update dev-env 2026-01-08 10:45:29 +02:00
Eric Bailey 19f903b143 Bump api sdk 2026-01-07 20:49:32 -06:00
Eric Bailey c8008da312 Simplify parsing 2026-01-07 18:48:24 -06:00
Eric Bailey 0d066eb1a1 Copy update 2026-01-07 18:47:02 -06:00
Eric Bailey 507b6f307f Bug fix bug fix 2026-01-07 18:46:06 -06:00
Eric Bailey b9b89a8147 Mr Worldwide™ 2026-01-07 18:17:56 -06:00
Eric Bailey 57646523fb Add report dialog to LiveStatus dialog 2026-01-07 18:05:28 -06:00
16 changed files with 325 additions and 55 deletions
+1 -1
View File
@@ -73,7 +73,7 @@
"icons:optimize": "svgo -f ./assets/icons"
},
"dependencies": {
"@atproto/api": "^0.18.11",
"@atproto/api": "^0.18.13",
"@bitdrift/react-native": "^0.6.8",
"@braintree/sanitize-url": "^6.0.2",
"@bsky.app/alf": "^0.1.6",
@@ -389,6 +389,7 @@ let Card = ({
{data && moderationOpts ? (
status.isActive ? (
<LiveStatus
status={status}
profile={data}
embed={status.embed}
padding="lg"
+7
View File
@@ -3,6 +3,7 @@ import {createContext, useContext, useMemo, useState} from 'react'
import {type AgeAssuranceRedirectDialogState} from '#/components/ageAssurance/AgeAssuranceRedirectDialog'
import * as Dialog from '#/components/Dialog'
import {type Screen} from '#/components/dialogs/EmailDialog/types'
import {type ReportSubject} from '#/components/moderation/ReportDialog'
type Control = Dialog.DialogControlProps
@@ -24,6 +25,7 @@ type ControlsContext = {
share?: boolean
}>
ageAssuranceRedirectDialogControl: StatefulControl<AgeAssuranceRedirectDialogState>
reportDialogControl: StatefulControl<{subject: ReportSubject}>
}
const ControlsContext = createContext<ControlsContext | null>(null)
@@ -51,6 +53,9 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
}>()
const ageAssuranceRedirectDialogControl =
useStatefulDialogControl<AgeAssuranceRedirectDialogState>()
const reportDialogControl = useStatefulDialogControl<{
subject: ReportSubject
}>()
const ctx = useMemo<ControlsContext>(
() => ({
@@ -60,6 +65,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
emailDialogControl,
linkWarningDialogControl,
ageAssuranceRedirectDialogControl,
reportDialogControl,
}),
[
mutedWordsDialogControl,
@@ -68,6 +74,7 @@ export function Provider({children}: React.PropsWithChildren<{}>) {
emailDialogControl,
linkWarningDialogControl,
ageAssuranceRedirectDialogControl,
reportDialogControl,
],
)
@@ -0,0 +1,147 @@
import {useCallback, useState} from 'react'
import {View} from 'react-native'
import {type AppBskyActorDefs, ToolsOzoneReportDefs} from '@atproto/api'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useMutation} from '@tanstack/react-query'
import {BLUESKY_MOD_SERVICE_HEADERS} from '#/lib/constants'
import {logger} from '#/logger'
import {useAgent} from '#/state/session'
import {atoms as a, web} from '#/alf'
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
import * as Dialog from '#/components/Dialog'
import {Loader} from '#/components/Loader'
import * as Toast from '#/components/Toast'
import {Text} from '#/components/Typography'
export function GoLiveDisabledDialog({
control,
status,
}: {
control: Dialog.DialogControlProps
status: AppBskyActorDefs.StatusView
}) {
return (
<Dialog.Outer control={control} nativeOptions={{preventExpansion: true}}>
<Dialog.Handle />
<DialogInner control={control} status={status} />
</Dialog.Outer>
)
}
export function DialogInner({
control,
status,
}: {
control: Dialog.DialogControlProps
status: AppBskyActorDefs.StatusView
}) {
const {_} = useLingui()
const agent = useAgent()
const [details, setDetails] = useState('')
const {mutate, isPending} = useMutation({
mutationFn: async () => {
if (!agent.session?.did) {
throw new Error('Not logged in')
}
if (!status.uri || !status.cid) {
throw new Error('Status is missing uri or cid')
}
if (__DEV__) {
logger.info('Submitting go live appeal', {
details,
})
} else {
await agent.createModerationReport(
{
reasonType: ToolsOzoneReportDefs.REASONAPPEAL,
subject: {
$type: 'com.atproto.repo.strongRef',
uri: status.uri,
cid: status.cid,
},
reason: details,
},
{
encoding: 'application/json',
headers: BLUESKY_MOD_SERVICE_HEADERS,
},
)
}
},
onError: () => {
Toast.show(_(msg`Failed to submit appeal, please try again.`), {
type: 'error',
})
},
onSuccess: () => {
control.close()
Toast.show(_(msg({message: 'Appeal submitted', context: 'toast'})), {
type: 'success',
})
},
})
const onSubmit = useCallback(() => mutate(), [mutate])
return (
<Dialog.ScrollableInner
label={_(msg`Appeal livestream suspension`)}
style={[web({maxWidth: 400})]}>
<View style={[a.gap_lg]}>
<View style={[a.gap_md]}>
<Text
style={[
a.flex_1,
a.text_2xl,
a.font_semi_bold,
a.leading_snug,
a.pr_4xl,
]}>
<Trans>Going live is currently disabled for your account</Trans>
</Text>
<Text style={[a.text_md, a.leading_snug]}>
<Trans>
You are currently blocked from using the Go Live feature. To
appeal this moderation decision, please submit the form below.
</Trans>
</Text>
<Text style={[a.text_md, a.leading_snug]}>
<Trans>
This appeal will be sent to Bluesky's moderation service.
</Trans>
</Text>
</View>
<View style={[a.gap_md]}>
<Dialog.Input
label={_(msg`Text input field`)}
placeholder={_(
msg`Please explain why you think your Go Live access was incorrectly disabled.`,
)}
value={details}
onChangeText={setDetails}
autoFocus={true}
numberOfLines={3}
multiline
maxLength={300}
/>
<Button
testID="submitBtn"
variant="solid"
color="primary"
size="large"
onPress={onSubmit}
label={_(msg`Submit`)}>
<ButtonText>{_(msg`Submit`)}</ButtonText>
{isPending && <ButtonIcon icon={Loader} />}
</Button>
</View>
</View>
<Dialog.Close />
</Dialog.ScrollableInner>
)
}
+52 -8
View File
@@ -17,6 +17,9 @@ import {unstableCacheProfileView} from '#/state/queries/profile'
import {android, atoms as a, platform, tokens, useTheme, web} from '#/alf'
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
import * as Dialog from '#/components/Dialog'
import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfoIcon} from '#/components/icons/CircleInfo'
import {createStaticClick, SimpleInlineLinkText} from '#/components/Link'
import {useGlobalReportDialogControl} from '#/components/moderation/ReportDialog'
import * as ProfileCard from '#/components/ProfileCard'
import {Text} from '#/components/Typography'
import type * as bsky from '#/types/bsky'
@@ -28,6 +31,7 @@ export function LiveStatusDialog({
control,
profile,
embed,
status,
}: {
control: Dialog.DialogControlProps
profile: bsky.profile.AnyProfileView
@@ -38,7 +42,12 @@ export function LiveStatusDialog({
return (
<Dialog.Outer control={control} nativeOptions={{preventExpansion: true}}>
<Dialog.Handle difference={!!embed.external.thumb} />
<DialogInner profile={profile} embed={embed} navigation={navigation} />
<DialogInner
status={status}
profile={profile}
embed={embed}
navigation={navigation}
/>
</Dialog.Outer>
)
}
@@ -47,10 +56,12 @@ function DialogInner({
profile,
embed,
navigation,
status,
}: {
profile: bsky.profile.AnyProfileView
embed: AppBskyEmbedExternal.View
navigation: NavigationProp
status: AppBskyActorDefs.StatusView
}) {
const {_} = useLingui()
const control = Dialog.useDialogContext()
@@ -69,6 +80,7 @@ function DialogInner({
contentContainerStyle={[a.pt_0, a.px_0]}
style={[web({maxWidth: 420}), a.overflow_hidden]}>
<LiveStatus
status={status}
profile={profile}
embed={embed}
onPressOpenProfile={onPressOpenProfile}
@@ -79,11 +91,13 @@ function DialogInner({
}
export function LiveStatus({
status,
profile,
embed,
padding = 'xl',
onPressOpenProfile,
}: {
status: AppBskyActorDefs.StatusView
profile: bsky.profile.AnyProfileView
embed: AppBskyEmbedExternal.View
padding?: 'lg' | 'xl'
@@ -94,6 +108,8 @@ export function LiveStatus({
const queryClient = useQueryClient()
const openLink = useOpenLink()
const moderationOpts = useModerationOpts()
const reportDialogControl = useGlobalReportDialogControl()
const dialogContext = Dialog.useDialogContext()
return (
<>
@@ -205,15 +221,43 @@ export function LiveStatus({
</Button>
</ProfileCard.Header>
)}
<Text
<View
style={[
a.w_full,
a.text_center,
t.atoms.text_contrast_low,
a.text_sm,
a.flex_row,
a.align_center,
a.justify_between,
a.flex_1,
a.pt_sm,
]}>
<Trans>Live feature is in beta testing</Trans>
</Text>
<View style={[a.flex_row, a.align_center, a.gap_xs, a.flex_1]}>
<CircleInfoIcon size="sm" fill={t.atoms.text_contrast_low.color} />
<Text style={[t.atoms.text_contrast_low, a.text_sm]}>
<Trans>Live feature is in beta</Trans>
</Text>
</View>
{status && (
<SimpleInlineLinkText
label={_(msg`Report this livestream`)}
{...createStaticClick(() => {
function open() {
reportDialogControl.open({
subject: {
...status,
$type: 'app.bsky.actor.defs#statusView',
},
})
}
if (dialogContext.isWithinDialog) {
dialogContext.close(open)
} else {
open()
}
})}
style={[a.text_sm, a.underline, t.atoms.text_contrast_medium]}>
<Trans>Report</Trans>
</SimpleInlineLinkText>
)}
</View>
</View>
</>
)
@@ -70,6 +70,7 @@ export function useSubmitReportMutation() {
}
break
}
case 'status':
case 'post':
case 'list':
case 'feed':
@@ -3,6 +3,8 @@ import {
ToolsOzoneReportDefs as OzoneReportDefs,
} from '@atproto/api'
import {type ParsedReportSubject} from '#/components/moderation/ReportDialog/types'
export const DMCA_LINK = 'https://bsky.social/about/support/copyright'
export const SUPPORT_PAGE = 'https://bsky.social/about/support'
@@ -112,3 +114,10 @@ export const BSKY_LABELER_ONLY_REPORT_REASONS: Set<OzoneReportDefs.ReasonType> =
OzoneReportDefs.REASONCHILDSAFETYOTHER,
OzoneReportDefs.REASONVIOLENCEEXTREMISTCONTENT,
])
/**
* Set of _parsed_ subject types that should only be sent to Bluesky's
* moderation service.
*/
export const BSKY_LABELER_ONLY_SUBJECT_TYPES: Set<ParsedReportSubject['type']> =
new Set(['convoMessage', 'status'])
@@ -14,6 +14,12 @@ export function useCopyForSubject(subject: ParsedReportSubject) {
subtitle: _(msg`Why should this user be reviewed?`),
}
}
case 'status': {
return {
title: _(msg`Report this livestream`),
subtitle: _(msg`Why should this livestream be reviewed?`),
}
}
case 'post': {
return {
title: _(msg`Report this post`),
@@ -16,6 +16,7 @@ import {atoms as a, useGutters, useTheme} from '#/alf'
import * as Admonition from '#/components/Admonition'
import {Button, ButtonIcon, ButtonText} from '#/components/Button'
import * as Dialog from '#/components/Dialog'
import {useGlobalDialogsControlContext} from '#/components/dialogs/Context'
import {useDelayedLoading} from '#/components/hooks/useDelayedLoading'
import {ArrowRotateCounterClockwise_Stroke2_Corner0_Rounded as Retry} from '#/components/icons/ArrowRotate'
import {
@@ -31,6 +32,7 @@ import {Text} from '#/components/Typography'
import {useSubmitReportMutation} from './action'
import {
BSKY_LABELER_ONLY_REPORT_REASONS,
BSKY_LABELER_ONLY_SUBJECT_TYPES,
NEW_TO_OLD_REASONS_MAP,
SUPPORT_PAGE,
} from './const'
@@ -44,17 +46,27 @@ import {
useReportOptions,
} from './utils/useReportOptions'
export {type ReportSubject} from './types'
export {useDialogControl as useReportDialogControl} from '#/components/Dialog'
export function useGlobalReportDialogControl() {
return useGlobalDialogsControlContext().reportDialogControl
}
const logger = Logger.create(Logger.Context.ReportDialog)
export function GlobalReportDialog() {
const {value, control} = useGlobalReportDialogControl()
return <ReportDialog control={control} subject={value?.subject} />
}
export function ReportDialog(
props: Omit<ReportDialogProps, 'subject'> & {
subject: ReportSubject
subject?: ReportSubject
},
) {
const subject = React.useMemo(
() => parseReportSubject(props.subject),
() => (props.subject ? parseReportSubject(props.subject) : undefined),
[props.subject],
)
const onClose = React.useCallback(() => {
@@ -116,8 +128,10 @@ function Inner(props: ReportDialogProps) {
const isBskyOnlyReason = state?.selectedOption?.reason
? BSKY_LABELER_ONLY_REPORT_REASONS.has(state.selectedOption.reason)
: false
// some subjects (chats) only go to Bluesky
const isBskyOnlySubject = props.subject.type === 'convoMessage'
// some subjects ONLY go to Bluesky
const isBskyOnlySubject = BSKY_LABELER_ONLY_SUBJECT_TYPES.has(
props.subject.type,
)
/**
* Labelers that support this `subject` and its NSID collection
@@ -824,12 +838,7 @@ function LabelerCard({
{title}
</Text>
<Text
style={[
a.text_sm,
,
a.leading_snug,
t.atoms.text_contrast_medium,
]}>
style={[a.text_sm, a.leading_snug, t.atoms.text_contrast_medium]}>
<Trans>By {sanitizeHandle(labeler.creator.handle, '@')}</Trans>
</Text>
</View>
@@ -18,6 +18,7 @@ export type ReportSubject =
| $Typed<AppBskyActorDefs.ProfileViewBasic>
| $Typed<AppBskyActorDefs.ProfileView>
| $Typed<AppBskyActorDefs.ProfileViewDetailed>
| $Typed<AppBskyActorDefs.StatusView>
| $Typed<AppBskyGraphDefs.ListView>
| $Typed<AppBskyFeedDefs.GeneratorView>
| $Typed<AppBskyGraphDefs.StarterPackView>
@@ -38,6 +39,12 @@ export type ParsedReportSubject =
quote: boolean
}
}
| {
type: 'status'
uri: string
cid: string
nsid: string
}
| {
type: 'list'
uri: string
@@ -33,6 +33,14 @@ export function parseReportSubject(
did: subject.did,
nsid: 'app.bsky.actor.profile',
}
} else if (AppBskyActorDefs.isStatusView(subject)) {
if (!subject.uri || !subject.cid) return
return {
type: 'status',
uri: subject.uri,
cid: subject.cid,
nsid: 'app.bsky.actor.status',
}
} else if (AppBskyGraphDefs.isListView(subject)) {
return {
type: 'list',
+21 -8
View File
@@ -19,15 +19,27 @@ export function useActorStatus(actor?: bsky.profile.AnyProfileView) {
return useMemo(() => {
tick! // revalidate every minute
if (
shadowed &&
'status' in shadowed &&
shadowed.status &&
validateStatus(shadowed.did, shadowed.status, config) &&
isStatusStillActive(shadowed.status.expiresAt)
) {
if (shadowed && 'status' in shadowed && shadowed.status) {
const isValid = validateStatus(shadowed.did, shadowed.status, config)
const isDisabled = shadowed.status.isDisabled || false
const isActive = isStatusStillActive(shadowed.status.expiresAt)
if (isValid && !isDisabled && isActive) {
return {
uri: shadowed.status.uri,
cid: shadowed.status.cid,
isDisabled: false,
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
}
return {
isActive: true,
uri: shadowed.status.uri,
cid: shadowed.status.cid,
isDisabled,
isActive: false,
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
@@ -36,6 +48,7 @@ export function useActorStatus(actor?: bsky.profile.AnyProfileView) {
} else {
return {
status: '',
isDisabled: false,
isActive: false,
record: {},
} satisfies AppBskyActorDefs.StatusView
+22 -8
View File
@@ -49,6 +49,7 @@ import {SpeakerVolumeFull_Stroke2_Corner0_Rounded as Unmute} from '#/components/
import {StarterPack} from '#/components/icons/StarterPack'
import {EditLiveDialog} from '#/components/live/EditLiveDialog'
import {GoLiveDialog} from '#/components/live/GoLiveDialog'
import {GoLiveDisabledDialog} from '#/components/live/GoLiveDisabledDialog'
import * as Menu from '#/components/Menu'
import {
ReportDialog,
@@ -79,6 +80,7 @@ let ProfileMenu = ({
const [devModeEnabled] = useDevMode()
const verification = useFullVerificationState({profile})
const canGoLive = useCanGoLive(currentAccount?.did)
const status = useActorStatus(profile)
const [queueMute, queueUnmute] = useProfileMuteMutationQueue(profile)
const [queueBlock, queueUnblock] = useProfileBlockMutationQueue(profile)
@@ -90,6 +92,7 @@ let ProfileMenu = ({
const blockPromptControl = Prompt.usePromptControl()
const loggedOutWarningPromptControl = Prompt.usePromptControl()
const goLiveDialogControl = useDialogControl()
const goLiveDisabledDialogControl = useDialogControl()
const addToStarterPacksDialogControl = useDialogControl()
const showLoggedOutWarning = React.useMemo(() => {
@@ -220,8 +223,6 @@ let ProfileMenu = ({
return v.issuer === currentAccount?.did
}) ?? []
const status = useActorStatus(profile)
return (
<EventStopper onKeyDown={false}>
<Menu.Root>
@@ -330,13 +331,21 @@ let ProfileMenu = ({
<Menu.Item
testID="profileHeaderDropdownListAddRemoveBtn"
label={
status.isActive
? _(msg`Edit live status`)
: _(msg`Go live`)
status.isDisabled
? _(msg`Go live (disabled)`)
: status.isActive
? _(msg`Edit live status`)
: _(msg`Go live`)
}
onPress={goLiveDialogControl.open}>
onPress={
status.isDisabled
? goLiveDisabledDialogControl.open
: goLiveDialogControl.open
}>
<Menu.ItemText>
{status.isActive ? (
{status.isDisabled ? (
<Trans>Go live (disabled)</Trans>
) : status.isActive ? (
<Trans>Edit live status</Trans>
) : (
<Trans>Go live</Trans>
@@ -517,7 +526,12 @@ let ProfileMenu = ({
verifications={currentAccountVerifications}
/>
{status.isActive ? (
{status.isDisabled ? (
<GoLiveDisabledDialog
control={goLiveDisabledDialogControl}
status={status}
/>
) : status.isActive ? (
<EditLiveDialog
control={goLiveDialogControl}
status={status}
+2
View File
@@ -34,6 +34,7 @@ import {LinkWarningDialog} from '#/components/dialogs/LinkWarning'
import {MutedWordsDialog} from '#/components/dialogs/MutedWords'
import {NuxDialogs} from '#/components/dialogs/nuxs'
import {SigninDialog} from '#/components/dialogs/Signin'
import {GlobalReportDialog} from '#/components/moderation/ReportDialog'
import {
Outlet as PolicyUpdateOverlayPortalOutlet,
usePolicyUpdateContext,
@@ -117,6 +118,7 @@ function ShellInner() {
<LinkWarningDialog />
<Lightbox />
<NuxDialogs />
<GlobalReportDialog />
{/* Until policy update has been completed by the user, don't render anything that is portaled */}
{policyUpdateState.completed && (
+2
View File
@@ -24,6 +24,7 @@ import {MutedWordsDialog} from '#/components/dialogs/MutedWords'
import {NuxDialogs} from '#/components/dialogs/nuxs'
import {SigninDialog} from '#/components/dialogs/Signin'
import {useWelcomeModal} from '#/components/hooks/useWelcomeModal'
import {GlobalReportDialog} from '#/components/moderation/ReportDialog'
import {
Outlet as PolicyUpdateOverlayPortalOutlet,
usePolicyUpdateContext,
@@ -73,6 +74,7 @@ function ShellInner() {
<LinkWarningDialog />
<Lightbox />
<NuxDialogs />
<GlobalReportDialog />
{welcomeModalControl.isOpen && (
<WelcomeModal control={welcomeModalControl} />
+20 -20
View File
@@ -82,12 +82,12 @@
"@atproto/xrpc" "^0.7.6"
"@atproto/xrpc-server" "^0.10.0"
"@atproto/api@^0.18.11":
version "0.18.11"
resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.18.11.tgz#38b8bacecaae4c24bc29bd98b34f270d8be675b3"
integrity sha512-YhgyL4rOBFOIs+e/8s5S+EjwM3T5q65IKh30ZoIrWcQS/2uteiIzg1xB+iXmexZq4Cwug0NLfRUJDViDK/ut0w==
"@atproto/api@^0.18.13":
version "0.18.13"
resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.18.13.tgz#63eee310e6715752eb87748323cf9ab57dd91e4b"
integrity sha512-CULZ01pSJDltLS/Gc9MMrhFzB6OM3ezyZw7KoeLT/sBfwgA1ddA4mWdTh7DIRosPRigXtA05bnoiCutZbQDo+Q==
dependencies:
"@atproto/common-web" "^0.4.10"
"@atproto/common-web" "^0.4.11"
"@atproto/lexicon" "^0.6.0"
"@atproto/syntax" "^0.4.2"
"@atproto/xrpc" "^0.7.7"
@@ -208,13 +208,13 @@
pino-http "^8.2.1"
typed-emitter "^2.1.0"
"@atproto/common-web@^0.4.10":
version "0.4.10"
resolved "https://registry.yarnpkg.com/@atproto/common-web/-/common-web-0.4.10.tgz#3d29df4dc3ea8f5c149161209f55e146f27867c1"
integrity sha512-TLDZSgSKzT8ZgOrBrTGK87J1CXve9TEuY6NVVUBRkOMzRRtQzpFb9/ih5WVS/hnaWVvE30CfuyaetRoma+WKNw==
"@atproto/common-web@^0.4.11":
version "0.4.11"
resolved "https://registry.yarnpkg.com/@atproto/common-web/-/common-web-0.4.11.tgz#eb41dc02c1ea4221388630e193d181fb098186e0"
integrity sha512-VHejNmSABU8/03VrQ3e36AmT5U3UIeio+qSUqCrO1oNgrJcWfGy1rpj0FVtUugWF8Un29+yzkukzWGZfXL70rQ==
dependencies:
"@atproto/lex-data" "0.0.6"
"@atproto/lex-json" "0.0.6"
"@atproto/lex-data" "0.0.7"
"@atproto/lex-json" "0.0.7"
zod "^3.23.8"
"@atproto/common-web@^0.4.4", "@atproto/common-web@^0.4.6":
@@ -415,10 +415,10 @@
uint8arrays "3.0.0"
unicode-segmenter "^0.14.0"
"@atproto/lex-data@0.0.6":
version "0.0.6"
resolved "https://registry.yarnpkg.com/@atproto/lex-data/-/lex-data-0.0.6.tgz#280d05ec9579ab091dc4a8b696ebbeddcb8ee37d"
integrity sha512-MBNB4ghRJQzuXK1zlUPljpPbQcF1LZ5dzxy274KqPt4p3uPuRw0mHjgcCoWzRUNBQC685WMQR4IN9DHtsnG57A==
"@atproto/lex-data@0.0.7":
version "0.0.7"
resolved "https://registry.yarnpkg.com/@atproto/lex-data/-/lex-data-0.0.7.tgz#6aa87423f6d47849bec8ff3ca0b00ce93964adc8"
integrity sha512-W/Q5o9o7n2Sv3UywckChu01X5lwQUtaiiOkGJLnRsdkQTyC6813nPgY+p2sG7NwwM+82lu+FUV9fE/Ul3VqaJw==
dependencies:
"@atproto/syntax" "0.4.2"
multiformats "^9.9.0"
@@ -451,12 +451,12 @@
"@atproto/lex-data" "0.0.3"
tslib "^2.8.1"
"@atproto/lex-json@0.0.6":
version "0.0.6"
resolved "https://registry.yarnpkg.com/@atproto/lex-json/-/lex-json-0.0.6.tgz#50618efb1cc11708b3897de14dcd3bd9c06e064d"
integrity sha512-EILnN5cditPvf+PCNjXt7reMuzjugxAL1fpSzmzJbEMGMUwxOf5pPWxRsaA/M3Boip4NQZ+6DVrPOGUMlnqceg==
"@atproto/lex-json@0.0.7":
version "0.0.7"
resolved "https://registry.yarnpkg.com/@atproto/lex-json/-/lex-json-0.0.7.tgz#c06e1fc3e06d739bbb74694f5d846055bed37866"
integrity sha512-bjNPD5M/MhLfjNM7tcxuls80UgXpHqxdOxDXEUouAtZQV/nIDhGjmNUvKxOmOgnDsiZRnT2g5y3onrnjH3a44g==
dependencies:
"@atproto/lex-data" "0.0.6"
"@atproto/lex-data" "0.0.7"
tslib "^2.8.1"
"@atproto/lex-resolver@0.0.5":