Activity notification public preference settings (#8504)

This commit is contained in:
Samuel Newman
2025-06-25 17:24:50 +03:00
parent 9180aa10be
commit 64b669685c
19 changed files with 406 additions and 141 deletions
+1
View File
@@ -275,6 +275,7 @@ func serve(cctx *cli.Context) error {
e.GET("/settings/appearance", server.WebGeneric)
e.GET("/settings/account", server.WebGeneric)
e.GET("/settings/privacy-and-security", server.WebGeneric)
e.GET("/settings/privacy-and-security/activity", server.WebGeneric)
e.GET("/settings/content-and-media", server.WebGeneric)
e.GET("/settings/interests", server.WebGeneric)
e.GET("/settings/about", server.WebGeneric)
+2 -2
View File
@@ -69,7 +69,7 @@
"icons:optimize": "svgo -f ./assets/icons"
},
"dependencies": {
"@atproto/api": "^0.15.16",
"@atproto/api": "^0.15.17",
"@bitdrift/react-native": "^0.6.8",
"@braintree/sanitize-url": "^6.0.2",
"@discord/bottom-sheet": "bluesky-social/react-native-bottom-sheet",
@@ -218,7 +218,7 @@
"zod": "^3.20.2"
},
"devDependencies": {
"@atproto/dev-env": "^0.3.144",
"@atproto/dev-env": "^0.3.146",
"@babel/core": "^7.26.0",
"@babel/preset-env": "^7.26.0",
"@babel/runtime": "^7.26.0",
+9
View File
@@ -84,6 +84,7 @@ import {SearchScreen} from '#/screens/Search'
import {AboutSettingsScreen} from '#/screens/Settings/AboutSettings'
import {AccessibilitySettingsScreen} from '#/screens/Settings/AccessibilitySettings'
import {AccountSettingsScreen} from '#/screens/Settings/AccountSettings'
import {ActivityPrivacySettingsScreen} from '#/screens/Settings/ActivityPrivacySettings'
import {AppearanceSettingsScreen} from '#/screens/Settings/AppearanceSettings'
import {AppIconSettingsScreen} from '#/screens/Settings/AppIconSettings'
import {AppPasswordsScreen} from '#/screens/Settings/AppPasswords'
@@ -391,6 +392,14 @@ function commonScreens(Stack: typeof Flat, unreadCountLabel?: string) {
requireAuth: true,
}}
/>
<Stack.Screen
name="ActivityPrivacySettings"
getComponent={() => ActivityPrivacySettingsScreen}
options={{
title: title(msg`Privacy and Security`),
requireAuth: true,
}}
/>
<Stack.Screen
name="NotificationSettings"
getComponent={() => NotificationSettingsScreen}
+1
View File
@@ -51,6 +51,7 @@ export type CommonNavigatorParams = {
AppearanceSettings: undefined
AccountSettings: undefined
PrivacyAndSecuritySettings: undefined
ActivityPrivacySettings: undefined
ContentAndMediaSettings: undefined
NotificationSettings: undefined
ReplyNotificationSettings: undefined
+1
View File
@@ -50,6 +50,7 @@ export const router = new Router<AllNavigatableRoutes>({
SavedFeeds: '/settings/saved-feeds',
AccountSettings: '/settings/account',
PrivacyAndSecuritySettings: '/settings/privacy-and-security',
ActivityPrivacySettings: '/settings/privacy-and-security/activity',
ContentAndMediaSettings: '/settings/content-and-media',
InterestsSettings: '/settings/interests',
AboutSettings: '/settings/about',
+2 -17
View File
@@ -1,8 +1,8 @@
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {NativeStackScreenProps} from '@react-navigation/native-stack'
import {type NativeStackScreenProps} from '@react-navigation/native-stack'
import {CommonNavigatorParams} from '#/lib/routes/types'
import {type CommonNavigatorParams} from '#/lib/routes/types'
import {isNative} from '#/platform/detection'
import {
useHapticsDisabled,
@@ -16,12 +16,10 @@ import {
} from '#/state/preferences/large-alt-badge'
import * as SettingsList from '#/screens/Settings/components/SettingsList'
import {atoms as a} from '#/alf'
import {Admonition} from '#/components/Admonition'
import * as Toggle from '#/components/forms/Toggle'
import {Accessibility_Stroke2_Corner2_Rounded as AccessibilityIcon} from '#/components/icons/Accessibility'
import {Haptic_Stroke2_Corner2_Rounded as HapticIcon} from '#/components/icons/Haptic'
import * as Layout from '#/components/Layout'
import {InlineLinkText} from '#/components/Link'
type Props = NativeStackScreenProps<
CommonNavigatorParams,
@@ -100,19 +98,6 @@ export function AccessibilitySettingsScreen({}: Props) {
</SettingsList.Group>
</>
)}
<SettingsList.Item>
<Admonition type="info" style={[a.flex_1]}>
<Trans>
Autoplay options have moved to the{' '}
<InlineLinkText
to="/settings/content-and-media"
label={_(msg`Content and media`)}>
Content and Media settings
</InlineLinkText>
.
</Trans>
</Admonition>
</SettingsList.Item>
</SettingsList.Container>
</Layout.Content>
</Layout.Screen>
@@ -0,0 +1,138 @@
import {View} from 'react-native'
import {type AppBskyNotificationDeclaration} from '@atproto/api'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {
type AllNavigatorParams,
type NativeStackScreenProps,
} from '#/lib/routes/types'
import {
useNotificationDeclarationMutation,
useNotificationDeclarationQuery,
} from '#/state/queries/activity-subscriptions'
import {atoms as a, useTheme} from '#/alf'
import {Admonition} from '#/components/Admonition'
import * as Toggle from '#/components/forms/Toggle'
import {BellRinging_Stroke2_Corner0_Rounded as BellRingingIcon} from '#/components/icons/BellRinging'
import * as Layout from '#/components/Layout'
import {Loader} from '#/components/Loader'
import * as SettingsList from './components/SettingsList'
import {ItemTextWithSubtitle} from './NotificationSettings/components/ItemTextWithSubtitle'
type Props = NativeStackScreenProps<
AllNavigatorParams,
'ActivityPrivacySettings'
>
export function ActivityPrivacySettingsScreen({}: Props) {
const {
data: notificationDeclaration,
isPending,
isError,
} = useNotificationDeclarationQuery()
return (
<Layout.Screen>
<Layout.Header.Outer>
<Layout.Header.BackButton />
<Layout.Header.Content>
<Layout.Header.TitleText>
<Trans>Privacy and Security</Trans>
</Layout.Header.TitleText>
</Layout.Header.Content>
<Layout.Header.Slot />
</Layout.Header.Outer>
<Layout.Content>
<SettingsList.Container>
<SettingsList.Item style={[a.align_start]}>
<SettingsList.ItemIcon icon={BellRingingIcon} />
<ItemTextWithSubtitle
bold
titleText={
<Trans>Allow others to get notified of your posts</Trans>
}
subtitleText={
<Trans>
This feature allows users to receive notifications for your
new posts and replies. Who do you want to enable this for?
</Trans>
}
/>
</SettingsList.Item>
<View style={[a.px_xl, a.pt_md]}>
{isError ? (
<Admonition type="error">
<Trans>Failed to load preference.</Trans>
</Admonition>
) : isPending ? (
<View style={[a.w_full, a.pt_5xl, a.align_center]}>
<Loader size="xl" />
</View>
) : (
<Inner notificationDeclaration={notificationDeclaration} />
)}
</View>
</SettingsList.Container>
</Layout.Content>
</Layout.Screen>
)
}
export function Inner({
notificationDeclaration,
}: {
notificationDeclaration: {
uri?: string
cid?: string
value: AppBskyNotificationDeclaration.Record
}
}) {
const t = useTheme()
const {_} = useLingui()
const {mutate} = useNotificationDeclarationMutation()
const onChangeFilter = ([declaration]: string[]) => {
mutate({
$type: 'app.bsky.notification.declaration',
allowSubscriptions: declaration,
})
}
return (
<Toggle.Group
type="radio"
label={_('Filter who can opt to receive notifications for your activity')}
values={[notificationDeclaration.value.allowSubscriptions]}
onChange={onChangeFilter}>
<View style={[a.gap_sm]}>
<Toggle.Item
label={_(msg`Anyone who follows me`)}
name="followers"
style={[a.flex_row, a.py_xs, a.gap_sm]}>
<Toggle.Radio />
<Toggle.LabelText style={[t.atoms.text, a.font_normal, a.text_md]}>
<Trans>Anyone who follows me</Trans>
</Toggle.LabelText>
</Toggle.Item>
<Toggle.Item
label={_(msg`Only followers who I follow`)}
name="mutuals"
style={[a.flex_row, a.py_xs, a.gap_sm]}>
<Toggle.Radio />
<Toggle.LabelText style={[t.atoms.text, a.font_normal, a.text_md]}>
<Trans>Only followers who I follow</Trans>
</Toggle.LabelText>
</Toggle.Item>
<Toggle.Item
label={_(msg`No one`)}
name="none"
style={[a.flex_row, a.py_xs, a.gap_sm]}>
<Toggle.Radio />
<Toggle.LabelText style={[t.atoms.text, a.font_normal, a.text_md]}>
<Trans>No one</Trans>
</Toggle.LabelText>
</Toggle.Item>
</View>
</Toggle.Group>
)
}
+3 -3
View File
@@ -7,12 +7,12 @@ import Animated, {
LinearTransition,
StretchOutY,
} from 'react-native-reanimated'
import {ComAtprotoServerListAppPasswords} from '@atproto/api'
import {type ComAtprotoServerListAppPasswords} from '@atproto/api'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {NativeStackScreenProps} from '@react-navigation/native-stack'
import {type NativeStackScreenProps} from '@react-navigation/native-stack'
import {CommonNavigatorParams} from '#/lib/routes/types'
import {type CommonNavigatorParams} from '#/lib/routes/types'
import {cleanError} from '#/lib/strings/errors'
import {isWeb} from '#/platform/detection'
import {
+6 -3
View File
@@ -1,4 +1,4 @@
import React, {useCallback} from 'react'
import {useCallback} from 'react'
import Animated, {
FadeInUp,
FadeOutUp,
@@ -9,14 +9,17 @@ import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {IS_INTERNAL} from '#/lib/app-info'
import {CommonNavigatorParams, NativeStackScreenProps} from '#/lib/routes/types'
import {
type CommonNavigatorParams,
type NativeStackScreenProps,
} from '#/lib/routes/types'
import {useGate} from '#/lib/statsig/statsig'
import {isNative} from '#/platform/detection'
import {useSetThemePrefs, useThemePrefs} from '#/state/shell'
import {SettingsListItem as AppIconSettingsListItem} from '#/screens/Settings/AppIconSettings/SettingsListItem'
import {atoms as a, native, useAlf, useTheme} from '#/alf'
import * as ToggleButton from '#/components/forms/ToggleButton'
import {Props as SVGIconProps} from '#/components/icons/common'
import {type Props as SVGIconProps} from '#/components/icons/common'
import {Moon_Stroke2_Corner0_Rounded as MoonIcon} from '#/components/icons/Moon'
import {Phone_Stroke2_Corner0_Rounded as PhoneIcon} from '#/components/icons/Phone'
import {TextSize_Stroke2_Corner0_Rounded as TextSize} from '#/components/icons/TextSize'
@@ -2,9 +2,12 @@ import {Fragment} from 'react'
import {View} from 'react-native'
import {Trans} from '@lingui/macro'
import {CommonNavigatorParams, NativeStackScreenProps} from '#/lib/routes/types'
import {
EmbedPlayerSource,
type CommonNavigatorParams,
type NativeStackScreenProps,
} from '#/lib/routes/types'
import {
type EmbedPlayerSource,
externalEmbedLabels,
} from '#/lib/strings/embed-player'
import {
@@ -1,7 +1,10 @@
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {CommonNavigatorParams, NativeStackScreenProps} from '#/lib/routes/types'
import {
type CommonNavigatorParams,
type NativeStackScreenProps,
} from '#/lib/routes/types'
import {
usePreferencesQuery,
useSetFeedViewPreferencesMutation,
@@ -114,7 +114,7 @@ export function Inner({
a.py_xs,
platform({
native: [a.justify_between],
web: [a.flex_row_reverse, a.gap_md],
web: [a.flex_row_reverse, a.gap_sm],
}),
]}>
<Toggle.LabelText
@@ -131,7 +131,7 @@ export function Inner({
a.py_xs,
platform({
native: [a.justify_between],
web: [a.flex_row_reverse, a.gap_md],
web: [a.flex_row_reverse, a.gap_sm],
}),
]}>
<Toggle.LabelText
@@ -159,11 +159,7 @@ export function Inner({
<Toggle.Item
label={_(msg`Everyone`)}
name="all"
style={[
a.flex_row,
a.py_xs,
platform({native: [a.gap_sm], web: [a.gap_md]}),
]}>
style={[a.flex_row, a.py_xs, a.gap_sm]}>
<Toggle.Radio />
<Toggle.LabelText
style={[
@@ -177,11 +173,7 @@ export function Inner({
<Toggle.Item
label={_(msg`People I follow`)}
name="follows"
style={[
a.flex_row,
a.py_xs,
platform({native: [a.gap_sm], web: [a.gap_md]}),
]}>
style={[a.flex_row, a.py_xs, a.gap_sm]}>
<Toggle.Radio />
<Toggle.LabelText
style={[
@@ -188,7 +188,6 @@ export function NotificationSettingsScreen({}: Props) {
to={{screen: 'ActivityNotificationSettings'}}
contentContainerStyle={[a.align_start]}>
<SettingsList.ItemIcon icon={BellRingingIcon} />
<ItemTextWithSubtitle
titleText={<Trans>Activity from others</Trans>}
subtitleText={
@@ -1,14 +1,17 @@
import {View} from 'react-native'
import {type AppBskyNotificationDeclaration} from '@atproto/api'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {type NativeStackScreenProps} from '@react-navigation/native-stack'
import {type CommonNavigatorParams} from '#/lib/routes/types'
import {useNotificationDeclarationQuery} from '#/state/queries/activity-subscriptions'
import {useAppPasswordsQuery} from '#/state/queries/app-passwords'
import {useSession} from '#/state/session'
import * as SettingsList from '#/screens/Settings/components/SettingsList'
import {atoms as a, useTheme} from '#/alf'
import * as Admonition from '#/components/Admonition'
import {BellRinging_Stroke2_Corner0_Rounded as BellRingingIcon} from '#/components/icons/BellRinging'
import {EyeSlash_Stroke2_Corner0_Rounded as EyeSlashIcon} from '#/components/icons/EyeSlash'
import {Key_Stroke2_Corner2_Rounded as KeyIcon} from '#/components/icons/Key'
import {ShieldCheck_Stroke2_Corner0_Rounded as ShieldIcon} from '#/components/icons/Shield'
@@ -16,6 +19,7 @@ import * as Layout from '#/components/Layout'
import {InlineLinkText} from '#/components/Link'
import {Email2FAToggle} from './components/Email2FAToggle'
import {PwiOptOut} from './components/PwiOptOut'
import {ItemTextWithSubtitle} from './NotificationSettings/components/ItemTextWithSubtitle'
type Props = NativeStackScreenProps<
CommonNavigatorParams,
@@ -26,6 +30,11 @@ export function PrivacyAndSecuritySettingsScreen({}: Props) {
const t = useTheme()
const {data: appPasswords} = useAppPasswordsQuery()
const {currentAccount} = useSession()
const {
data: notificationDeclaration,
isPending,
isError,
} = useNotificationDeclarationQuery()
return (
<Layout.Screen>
@@ -71,6 +80,22 @@ export function PrivacyAndSecuritySettingsScreen({}: Props) {
</SettingsList.BadgeText>
)}
</SettingsList.LinkItem>
<SettingsList.LinkItem
label={_(msg`Settings for activity alerts`)}
to={{screen: 'ActivityPrivacySettings'}}
contentContainerStyle={[a.align_start]}>
<SettingsList.ItemIcon icon={BellRingingIcon} />
<ItemTextWithSubtitle
titleText={<Trans>Allow others get notified of your posts</Trans>}
subtitleText={
<NotificationDeclaration
data={notificationDeclaration}
isError={isError}
/>
}
showSkeleton={isPending}
/>
</SettingsList.LinkItem>
<SettingsList.Divider />
<SettingsList.Group>
<SettingsList.ItemIcon icon={EyeSlashIcon} />
@@ -111,3 +136,26 @@ export function PrivacyAndSecuritySettingsScreen({}: Props) {
</Layout.Screen>
)
}
function NotificationDeclaration({
data,
isError,
}: {
data?: {
value: AppBskyNotificationDeclaration.Record
}
isError?: boolean
}) {
if (isError) {
return <Trans>Error loading preference</Trans>
}
switch (data?.value?.allowSubscriptions) {
case 'mutuals':
return <Trans>Only people you follow</Trans>
case 'none':
return <Trans>No one</Trans>
case 'followers':
default:
return <Trans>Only your followers</Trans>
}
}
+2 -2
View File
@@ -3,7 +3,7 @@ import {LayoutAnimation, Pressable, View} from 'react-native'
import {Linking} from 'react-native'
import {useReducedMotion} from 'react-native-reanimated'
import {type AppBskyActorDefs, moderateProfile} from '@atproto/api'
import {msg, t, Trans} from '@lingui/macro'
import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react'
import {useNavigation} from '@react-navigation/native'
import {type NativeStackScreenProps} from '@react-navigation/native-stack'
@@ -384,7 +384,7 @@ function DevOptions() {
...persisted.get('reminders'),
lastEmailConfirm: lastEmailConfirm.toISOString(),
})
Toast.show(t`You probably want to restart the app now.`)
Toast.show(_(msg`You probably want to restart the app now.`))
}
return (
@@ -1,15 +1,20 @@
import React, {useContext, useMemo} from 'react'
import {GestureResponderEvent, StyleProp, View, ViewStyle} from 'react-native'
import {createContext, useContext, useMemo} from 'react'
import {
type GestureResponderEvent,
type StyleProp,
View,
type ViewStyle,
} from 'react-native'
import {HITSLOP_10} from '#/lib/constants'
import {atoms as a, useTheme, ViewStyleProp} from '#/alf'
import {atoms as a, useTheme, type ViewStyleProp} from '#/alf'
import * as Button from '#/components/Button'
import {ChevronRight_Stroke2_Corner0_Rounded as ChevronRightIcon} from '#/components/icons/Chevron'
import {Link, LinkProps} from '#/components/Link'
import {Link, type LinkProps} from '#/components/Link'
import {createPortalGroup} from '#/components/Portal'
import {Text} from '#/components/Typography'
const ItemContext = React.createContext({
const ItemContext = createContext({
destructive: false,
withinGroup: false,
})
@@ -91,7 +96,7 @@ export function Item({
a.px_xl,
a.py_sm,
a.align_center,
a.gap_md,
a.gap_sm,
a.w_full,
a.flex_row,
{minHeight: 48},
@@ -100,9 +105,9 @@ export function Item({
// existing padding
a.pl_xl.paddingLeft +
// icon
28 +
24 +
// gap
a.gap_md.gap,
a.gap_sm.gap,
},
style,
]}>
@@ -175,7 +180,7 @@ export function PressableItem({
export function ItemIcon({
icon: Comp,
size = 'xl',
size = 'lg',
color: colorProp,
}: Omit<React.ComponentProps<typeof Button.ButtonIcon>, 'position'> & {
color?: string
@@ -0,0 +1,77 @@
import {type AppBskyNotificationDeclaration} from '@atproto/api'
import {t} from '@lingui/macro'
import {useMutation, useQuery, useQueryClient} from '@tanstack/react-query'
import {useAgent, useSession} from '#/state/session'
import * as Toast from '#/view/com/util/Toast'
const RQKEY_getNotificationDeclaration = ['notification-declaration']
export function useNotificationDeclarationQuery() {
const agent = useAgent()
const {currentAccount} = useSession()
return useQuery({
queryKey: RQKEY_getNotificationDeclaration,
queryFn: async () => {
try {
const response = await agent.app.bsky.notification.declaration.get({
repo: currentAccount!.did,
rkey: 'self',
})
return response
} catch (err) {
if (
err instanceof Error &&
err.message.startsWith('Could not locate record')
) {
return {
value: {
$type: 'app.bsky.notification.declaration',
allowSubscriptions: 'followers',
} satisfies AppBskyNotificationDeclaration.Record,
}
} else {
throw err
}
}
},
})
}
export function useNotificationDeclarationMutation() {
const agent = useAgent()
const {currentAccount} = useSession()
const queryClient = useQueryClient()
return useMutation({
mutationFn: async (record: AppBskyNotificationDeclaration.Record) => {
const response = await agent.com.atproto.repo.putRecord({
repo: currentAccount!.did,
collection: 'app.bsky.notification.declaration',
rkey: 'self',
record,
})
return response
},
onMutate: value => {
queryClient.setQueryData(
RQKEY_getNotificationDeclaration,
(old?: {
uri: string
cid: string
value: AppBskyNotificationDeclaration.Record
}) => {
if (!old) return old
return {
value,
}
},
)
},
onError: () => {
Toast.show(t`Failed to update notification declaration`)
queryClient.invalidateQueries({
queryKey: RQKEY_getNotificationDeclaration,
})
},
})
}
@@ -1,4 +1,4 @@
import {AppBskyActorDefs} from '@atproto/api'
import {type AppBskyActorDefs} from '@atproto/api'
import {useMutation, useQueryClient} from '@tanstack/react-query'
import {logger} from '#/logger'
@@ -19,7 +19,7 @@ export function useUpdateActorDeclaration({
return useMutation({
mutationFn: async (allowIncoming: 'all' | 'none' | 'following') => {
if (!currentAccount) throw new Error('Not signed in')
const result = await agent.api.com.atproto.repo.putRecord({
const result = await agent.com.atproto.repo.putRecord({
repo: currentAccount.did,
collection: 'chat.bsky.actor.declaration',
rkey: 'self',
+87 -87
View File
@@ -63,10 +63,10 @@
"@atproto/xrpc" "^0.7.0"
"@atproto/xrpc-server" "^0.8.0"
"@atproto/api@^0.15.16":
version "0.15.16"
resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.15.16.tgz#1962e7067e03a661e17c3164874596ef1e7ed7ad"
integrity sha512-ZNBrzBg2l0lHreKik1lJn8lrhAktwlY8NUPBU/hO9dwjAnDHQTiSzNFZt65dp9djmqZ75sX/VJ+heNuaJBvnhQ==
"@atproto/api@^0.15.17":
version "0.15.17"
resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.15.17.tgz#851f0bb138817509b5d453661eeb694db1f953a8"
integrity sha512-spHsfs052kamVX2foY4gz+wc8y4VdteXCG60xpG0pFsXJ47ueLVM8qdT/v9+Ii9FNRAvE+VVcGyAo/94P9Smrw==
dependencies:
"@atproto/common-web" "^0.4.2"
"@atproto/lexicon" "^0.4.11"
@@ -77,14 +77,14 @@
tlds "^1.234.0"
zod "^3.23.8"
"@atproto/aws@^0.2.22":
version "0.2.22"
resolved "https://registry.yarnpkg.com/@atproto/aws/-/aws-0.2.22.tgz#14a664c06e3569945e4ab143d3a8a03400c7d1de"
integrity sha512-xZ+0/zHHmpgzdLJGTDkFl5Wd39Wm5MyyMLdGYSzyt0wGTBmH6Ktp7ZgR8rmQVNYN1+VkMcdClAiNhg+BSH3mRw==
"@atproto/aws@^0.2.24":
version "0.2.24"
resolved "https://registry.yarnpkg.com/@atproto/aws/-/aws-0.2.24.tgz#c8e7a804710d70be3aa2fa292c1ece4c05127891"
integrity sha512-4XZQGitPJR56tFt1bzPJKOqp3vTVcfVsEAFo9FGWp7Es+jj742aVgfWEe64O0VoZp3ZTiD7XhwsLJArz7NJTlQ==
dependencies:
"@atproto/common" "^0.4.11"
"@atproto/crypto" "^0.4.4"
"@atproto/repo" "^0.8.2"
"@atproto/repo" "^0.8.4"
"@aws-sdk/client-cloudfront" "^3.261.0"
"@aws-sdk/client-kms" "^3.196.0"
"@aws-sdk/client-s3" "^3.224.0"
@@ -94,21 +94,21 @@
multiformats "^9.9.0"
uint8arrays "3.0.0"
"@atproto/bsky@^0.0.161":
version "0.0.161"
resolved "https://registry.yarnpkg.com/@atproto/bsky/-/bsky-0.0.161.tgz#671280c1d40f5c4eb0cc31d338a9e950acbf0ce0"
integrity sha512-L4uzadjt+oyVq3+W7rc1A+X2DyZDsTfeSD15w7k6+6JzICp32qavDuVjut3CIBqXCt7ykvSDujApyLsB/lcWJQ==
"@atproto/bsky@^0.0.163":
version "0.0.163"
resolved "https://registry.yarnpkg.com/@atproto/bsky/-/bsky-0.0.163.tgz#b58445a255419452c62d45f8954973927bc7f220"
integrity sha512-dOcO4KTSutw4nTCvYfe7d4EdBAxjTOQBubbD3rTGHpFhGxFxudk0oXccvmNSaPolGIn2xJu6MSFKgXI7HIZXGg==
dependencies:
"@atproto-labs/fetch-node" "0.1.9"
"@atproto-labs/xrpc-utils" "0.0.16"
"@atproto/api" "^0.15.16"
"@atproto/api" "^0.15.17"
"@atproto/common" "^0.4.11"
"@atproto/crypto" "^0.4.4"
"@atproto/did" "^0.1.5"
"@atproto/identity" "^0.4.8"
"@atproto/lexicon" "^0.4.11"
"@atproto/repo" "^0.8.2"
"@atproto/sync" "^0.1.26"
"@atproto/repo" "^0.8.4"
"@atproto/sync" "^0.1.28"
"@atproto/syntax" "^0.4.0"
"@atproto/xrpc-server" "^0.8.0"
"@bufbuild/protobuf" "^1.5.0"
@@ -218,21 +218,21 @@
"@noble/hashes" "^1.6.1"
uint8arrays "3.0.0"
"@atproto/dev-env@^0.3.144":
version "0.3.144"
resolved "https://registry.yarnpkg.com/@atproto/dev-env/-/dev-env-0.3.144.tgz#cd2949ff870ca4cde23b4c377b08740a2e64151f"
integrity sha512-ND0oGp7itSnXxlAHlFxYjGFyCcu0f4eSucImVtKRxTcW8UeyyTtJcQP8OyNvtC8j13YjbW124r0g25Wlm0j9XQ==
"@atproto/dev-env@^0.3.146":
version "0.3.146"
resolved "https://registry.yarnpkg.com/@atproto/dev-env/-/dev-env-0.3.146.tgz#dfe6bff226f580eaa9aa8bb8d2e1a7205fa1ca11"
integrity sha512-V1iVpMx281dPIAyyAd7ApgggNHWAyXmgXpXQ2WbejtyjAbcpH0y8swheCxpVdPKgH2PVUaJWXOvjUCaQ8fpmsA==
dependencies:
"@atproto/api" "^0.15.16"
"@atproto/bsky" "^0.0.161"
"@atproto/api" "^0.15.17"
"@atproto/bsky" "^0.0.163"
"@atproto/bsync" "^0.0.20"
"@atproto/common-web" "^0.4.2"
"@atproto/crypto" "^0.4.4"
"@atproto/identity" "^0.4.8"
"@atproto/lexicon" "^0.4.11"
"@atproto/ozone" "^0.1.121"
"@atproto/pds" "^0.4.150"
"@atproto/sync" "^0.1.26"
"@atproto/ozone" "^0.1.122"
"@atproto/pds" "^0.4.152"
"@atproto/sync" "^0.1.28"
"@atproto/syntax" "^0.4.0"
"@atproto/xrpc-server" "^0.8.0"
"@did-plc/lib" "^0.0.1"
@@ -259,18 +259,18 @@
"@atproto/common-web" "^0.4.2"
"@atproto/crypto" "^0.4.4"
"@atproto/jwk-jose@0.1.8":
version "0.1.8"
resolved "https://registry.yarnpkg.com/@atproto/jwk-jose/-/jwk-jose-0.1.8.tgz#2dc8ad2cc900e7bc231add293f6518b06dc017ec"
integrity sha512-aoU2Q0GpIl388KhCcv9YvAxNscALUv3xzLq5gjVPdJ+zmqw94nGZNcjiNvpnbfS+VQM9e2DrrTuwmDXnxfrrSA==
"@atproto/jwk-jose@0.1.9":
version "0.1.9"
resolved "https://registry.yarnpkg.com/@atproto/jwk-jose/-/jwk-jose-0.1.9.tgz#bd4a899ea2d497808300c40106795f5645c01f75"
integrity sha512-HT9GcUe6htDxI5OSYXWdeS6QZ9lpuDDvJk508ppi8a48E/1f8eumoM0QhgbFRF9IKAnnFrtnZDOAvljQzFKwwQ==
dependencies:
"@atproto/jwk" "0.3.0"
"@atproto/jwk" "0.4.0"
jose "^5.2.0"
"@atproto/jwk@0.3.0":
version "0.3.0"
resolved "https://registry.yarnpkg.com/@atproto/jwk/-/jwk-0.3.0.tgz#275fa676f6b5988ddedf4ee0475dd285de9b831b"
integrity sha512-MIAXyNMGu1tCNHjqW/8jqfE/wgWCIoK2cJ0mR6UxwhNPvkbe35TcpRYJdtQu/E6MUd7TziyDBa/GO4dKAiePhQ==
"@atproto/jwk@0.4.0":
version "0.4.0"
resolved "https://registry.yarnpkg.com/@atproto/jwk/-/jwk-0.4.0.tgz#f32265be172492c38434c556a124b954f249cee8"
integrity sha512-tvp4iZrzqEzKCeTOKz50/o6WdsZzOuWmWjF6On5QAp04fLwLpsFu2Hixgx/lA1KBO0O4sns7YSGcAqSSX6Rdog==
dependencies:
multiformats "^9.9.0"
zod "^3.23.8"
@@ -286,32 +286,32 @@
multiformats "^9.9.0"
zod "^3.23.8"
"@atproto/oauth-provider-api@0.1.4":
version "0.1.4"
resolved "https://registry.yarnpkg.com/@atproto/oauth-provider-api/-/oauth-provider-api-0.1.4.tgz#a775182e3648dc693a04e3cb604eb62cd9ddfd8c"
integrity sha512-3PRrf0gTAVMCETjtIH/3AaQaHBDbjsRBc/OYrlWBZ9IPplchBXtQGH/KcnjE4kK2Ef8p45qQSl3dNWg3EXsbHQ==
"@atproto/oauth-provider-api@0.1.6":
version "0.1.6"
resolved "https://registry.yarnpkg.com/@atproto/oauth-provider-api/-/oauth-provider-api-0.1.6.tgz#769a70caaac9b5144f9f867518523d1568a6b47c"
integrity sha512-4Q6ZCnTmmdiWiA+KMrfbZmqjxTSgMe+YE68+3RccwOCIgPt171TiDHGKIayep9n1RDnuucVQoqvVXOT4kmAsjw==
dependencies:
"@atproto/jwk" "0.3.0"
"@atproto/oauth-types" "0.3.0"
"@atproto/jwk" "0.4.0"
"@atproto/oauth-types" "0.4.0"
"@atproto/oauth-provider-frontend@0.1.8":
version "0.1.8"
resolved "https://registry.yarnpkg.com/@atproto/oauth-provider-frontend/-/oauth-provider-frontend-0.1.8.tgz#21d944566c63f54524f239a10f7c65d150982f40"
integrity sha512-uqfHv+n2xq7vTpuBP1Red7PhpaAbbJbwSbRsSfplJQ16XmF5NCMU8dHGCGRTEHngLZ9UquuIefN3w1QTrNzD0w==
"@atproto/oauth-provider-frontend@0.1.10":
version "0.1.10"
resolved "https://registry.yarnpkg.com/@atproto/oauth-provider-frontend/-/oauth-provider-frontend-0.1.10.tgz#d7176819d0ae1401ca5d70f7afec253621901a79"
integrity sha512-bOFpi5OIxWv4Q9ci1+PAXEzIZaiu5inepC7pRFYqgqgLoCO0MWH/5Qkn/f6jMpDwPdtBqAiPg9tjE7E3le6NJA==
optionalDependencies:
"@atproto/oauth-provider-api" "0.1.4"
"@atproto/oauth-provider-api" "0.1.6"
"@atproto/oauth-provider-ui@0.1.9":
version "0.1.9"
resolved "https://registry.yarnpkg.com/@atproto/oauth-provider-ui/-/oauth-provider-ui-0.1.9.tgz#8c43a1affa94ecb537072e6d569b8a24cdd42e72"
integrity sha512-a6/VAeQWRMxpgnqo/TuqXg3EW2tO68jLh8Mv1uyV1NiZbT7fNlgkII/djIl3fLoEa95I3p236NZxjhKELSBbGg==
"@atproto/oauth-provider-ui@0.1.11":
version "0.1.11"
resolved "https://registry.yarnpkg.com/@atproto/oauth-provider-ui/-/oauth-provider-ui-0.1.11.tgz#cb6194ac0b93f1d4b5d6717f80c55a3a20a8c690"
integrity sha512-9fflyDt4Y3RDJIfbonxVeMbQtLLQrkQSDhWhPXp9xbZ/uYBddaAw+svBfFoMY7dxdlJbQeUPobsUctEm3qAILg==
optionalDependencies:
"@atproto/oauth-provider-api" "0.1.4"
"@atproto/oauth-provider-api" "0.1.6"
"@atproto/oauth-provider@^0.9.1":
version "0.9.1"
resolved "https://registry.yarnpkg.com/@atproto/oauth-provider/-/oauth-provider-0.9.1.tgz#0147b75d1ad444455159f0a687ce87b3b49a2894"
integrity sha512-2Gm3jv45cGLmUQV0C4/orCJBsHu4wajy+JTN9f/ATX3vvjnFtAd/1GRvAMKDGXtdF7VIjNFlD+4lqhoDxYJpng==
"@atproto/oauth-provider@^0.9.3":
version "0.9.3"
resolved "https://registry.yarnpkg.com/@atproto/oauth-provider/-/oauth-provider-0.9.3.tgz#047b2e520e5cf127385adddc1dca47207b0ca113"
integrity sha512-TAhsCYDB/1twEA1vqjLAz7lxKI8W59eNs239MujE35Cc9l4lRHyMopoFv5JmgNnxDvloB5l6RxpTbXVC6wnKpQ==
dependencies:
"@atproto-labs/fetch" "0.2.3"
"@atproto-labs/fetch-node" "0.1.9"
@@ -320,12 +320,12 @@
"@atproto-labs/simple-store-memory" "0.1.3"
"@atproto/common" "^0.4.11"
"@atproto/did" "0.1.5"
"@atproto/jwk" "0.3.0"
"@atproto/jwk-jose" "0.1.8"
"@atproto/oauth-provider-api" "0.1.4"
"@atproto/oauth-provider-frontend" "0.1.8"
"@atproto/oauth-provider-ui" "0.1.9"
"@atproto/oauth-types" "0.3.0"
"@atproto/jwk" "0.4.0"
"@atproto/jwk-jose" "0.1.9"
"@atproto/oauth-provider-api" "0.1.6"
"@atproto/oauth-provider-frontend" "0.1.10"
"@atproto/oauth-provider-ui" "0.1.11"
"@atproto/oauth-types" "0.4.0"
"@atproto/syntax" "0.4.0"
"@hapi/accept" "^6.0.3"
"@hapi/address" "^5.1.1"
@@ -339,20 +339,20 @@
jose "^5.2.0"
zod "^3.23.8"
"@atproto/oauth-types@0.3.0":
version "0.3.0"
resolved "https://registry.yarnpkg.com/@atproto/oauth-types/-/oauth-types-0.3.0.tgz#8d49d939486ac281bc13d0b1fe4462b7e519fdf0"
integrity sha512-ptfsJARKODXfuOoDQag4a6PpEkDEj4Urz3jOmnQZy2YspPc/TNm1o0HglU0YehELv1vfhh9gEz40BJztPPhiLA==
"@atproto/oauth-types@0.4.0":
version "0.4.0"
resolved "https://registry.yarnpkg.com/@atproto/oauth-types/-/oauth-types-0.4.0.tgz#fb110717dd1e8593adffc6eaa85e7ab4f0713740"
integrity sha512-FrRH9JsPw9H4JxfPDrbrI+pB102tbHTygajfHay7xwz78HPOjSbWPRgWW2hYS4w8vDYdB3PYbBj1jPoKetW7LA==
dependencies:
"@atproto/jwk" "0.3.0"
"@atproto/jwk" "0.4.0"
zod "^3.23.8"
"@atproto/ozone@^0.1.121":
version "0.1.121"
resolved "https://registry.yarnpkg.com/@atproto/ozone/-/ozone-0.1.121.tgz#309b7e876f3b598ed4e79bb5a79e2346931588fe"
integrity sha512-kc3NxiXSPqQmWz8yXlV5cFnZ469ViQd0AexEMw467AcB8ikK1WSxhLsa1EiNAQuLOOpyeXSmAKGAUFHzSOIMpw==
"@atproto/ozone@^0.1.122":
version "0.1.122"
resolved "https://registry.yarnpkg.com/@atproto/ozone/-/ozone-0.1.122.tgz#4eabeb20aa68b9a7c65169a2e8db45cbe4376c86"
integrity sha512-yn/lCL+o+Lpj2+XABGx3cvjRU0YXKlrXfJHaGvGbG5KyY0qs8TcK5RV6aL33DqEacF07wXql/D8Ccwj1b1qCqA==
dependencies:
"@atproto/api" "^0.15.16"
"@atproto/api" "^0.15.17"
"@atproto/common" "^0.4.11"
"@atproto/crypto" "^0.4.4"
"@atproto/identity" "^0.4.8"
@@ -377,21 +377,21 @@
undici "^6.14.1"
ws "^8.12.0"
"@atproto/pds@^0.4.150":
version "0.4.150"
resolved "https://registry.yarnpkg.com/@atproto/pds/-/pds-0.4.150.tgz#45686b05b8ed46e265efa5231ab16e6eda72a8e8"
integrity sha512-CPT6H2uDTe4ZAyxQbws2dIlmdFFf6GQGwMc0OE3kI1wBBaLHprpexjM2Gd4ObtYNxGOOV0fwoCDAth8qqZ4XVw==
"@atproto/pds@^0.4.152":
version "0.4.152"
resolved "https://registry.yarnpkg.com/@atproto/pds/-/pds-0.4.152.tgz#4a7b5ebda2eb0c8b7dbd60df5660ba30169b73e9"
integrity sha512-weXY6M5QHGa0hQ92tJn78OLENf3q0E72tPKE8lCASgj2YTyxaIy0vckfUyaAlyxkR0KpQqRF+WJuAAs04PJwUA==
dependencies:
"@atproto-labs/fetch-node" "0.1.9"
"@atproto-labs/xrpc-utils" "0.0.16"
"@atproto/api" "^0.15.16"
"@atproto/aws" "^0.2.22"
"@atproto/api" "^0.15.17"
"@atproto/aws" "^0.2.24"
"@atproto/common" "^0.4.11"
"@atproto/crypto" "^0.4.4"
"@atproto/identity" "^0.4.8"
"@atproto/lexicon" "^0.4.11"
"@atproto/oauth-provider" "^0.9.1"
"@atproto/repo" "^0.8.2"
"@atproto/oauth-provider" "^0.9.3"
"@atproto/repo" "^0.8.4"
"@atproto/syntax" "^0.4.0"
"@atproto/xrpc" "^0.7.0"
"@atproto/xrpc-server" "^0.8.0"
@@ -424,10 +424,10 @@
undici "^6.19.8"
zod "^3.23.8"
"@atproto/repo@^0.8.2":
version "0.8.2"
resolved "https://registry.yarnpkg.com/@atproto/repo/-/repo-0.8.2.tgz#7953cb2c637c94505da76f74a784b2aae050c204"
integrity sha512-lP0g5Uw3TUC2Tc7te8YKCpRoIhBYI+Uvn11fupGEaMcMjgLdYtB0Kc0AiqWXF42KqlBG9dAEoJITi2GRzDNHUg==
"@atproto/repo@^0.8.4":
version "0.8.4"
resolved "https://registry.yarnpkg.com/@atproto/repo/-/repo-0.8.4.tgz#f6a1b4bce8cf86cd1825069f9cd2916a5f86e774"
integrity sha512-WgyARo6UcOnhbRsRVuNjXOH5MPTTHVDsaIavPeQl5erq5foE/pQKC7B7FLTJmhpC6GPZHJ5M2doAyXRXv5UHGA==
dependencies:
"@atproto/common" "^0.4.11"
"@atproto/common-web" "^0.4.2"
@@ -439,15 +439,15 @@
varint "^6.0.0"
zod "^3.23.8"
"@atproto/sync@^0.1.26":
version "0.1.26"
resolved "https://registry.yarnpkg.com/@atproto/sync/-/sync-0.1.26.tgz#6be2876be612d9cd704452598ee679b2e912cfe3"
integrity sha512-bpUIajtPrE3RgFW8mIfrI4EM/LJ4JjQhI5fsqc78zCHZawuflpllf1aH70roDWWiskMWoiLWnVRxdYXdeEgbXA==
"@atproto/sync@^0.1.28":
version "0.1.28"
resolved "https://registry.yarnpkg.com/@atproto/sync/-/sync-0.1.28.tgz#7c5c469dd899b4be86e5d993af66646c71d63eaf"
integrity sha512-faCsOwcYQHxHmNWRPykV0hTccXaG15XoUMZozfmoFOKFSliTgDETTovSAVe05mNSBUvMWUGl8fdEwHRzq1Q8sA==
dependencies:
"@atproto/common" "^0.4.11"
"@atproto/identity" "^0.4.8"
"@atproto/lexicon" "^0.4.11"
"@atproto/repo" "^0.8.2"
"@atproto/repo" "^0.8.4"
"@atproto/syntax" "^0.4.0"
"@atproto/xrpc-server" "^0.8.0"
multiformats "^9.9.0"