diff --git a/src/components/AccountList.tsx b/src/components/AccountList.tsx index a65eeb0722..d639166bb2 100644 --- a/src/components/AccountList.tsx +++ b/src/components/AccountList.tsx @@ -1,10 +1,10 @@ import {Fragment, useCallback} from 'react' import {View} from 'react-native' -import {type AppBskyActorDefs} from '@atproto/api' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Trans} from '@lingui/react/macro' +import {app} from '#/lexicons' import {isJwtExpired} from '#/lib/jwt' import {sanitizeDisplayName} from '#/lib/strings/display-names' import {sanitizeHandle} from '#/lib/strings/handles' @@ -107,7 +107,7 @@ function AccountItem({ isCurrentAccount, isPendingAccount, }: { - profile?: AppBskyActorDefs.ProfileViewDetailed + profile?: app.bsky.actor.defs.ProfileViewDetailed account: SessionAccount onSelect: (account: SessionAccount) => void isCurrentAccount: boolean diff --git a/src/components/BotBadge.tsx b/src/components/BotBadge.tsx index b5e6f867b6..af0fb3654f 100644 --- a/src/components/BotBadge.tsx +++ b/src/components/BotBadge.tsx @@ -1,7 +1,7 @@ import {type Insets, View} from 'react-native' -import {type ComAtprotoLabelDefs} from '@atproto/api' import {useLingui} from '@lingui/react/macro' +import {com} from '#/lexicons' import {atoms as a, useTheme} from '#/alf' import {BotAccountAlert} from '#/components/BotAccountAlert' import {Button} from '#/components/Button' @@ -12,7 +12,7 @@ import type * as bsky from '#/types/bsky' export function isBotAccount(profile: { did: string - labels?: ComAtprotoLabelDefs.Label[] + labels?: com.atproto.label.defs.Label[] }): boolean { return ( profile.labels?.some(l => l.val === 'bot' && l.src === profile.did) ?? false diff --git a/src/components/FeedCard.tsx b/src/components/FeedCard.tsx index 2e7b070fb1..5782325ae5 100644 --- a/src/components/FeedCard.tsx +++ b/src/components/FeedCard.tsx @@ -1,10 +1,11 @@ import {useCallback, useEffect, useMemo} from 'react' import {type GestureResponderEvent, View} from 'react-native' -import {type AppBskyFeedDefs, type AppBskyGraphDefs, AtUri} from '@atproto/api' import {RichText as RichTextApi} from '@bsky.app/sdk/richtext' import {Plural, Trans, useLingui} from '@lingui/react/macro' import {useQueryClient} from '@tanstack/react-query' +import {AtUri} from '@atproto/syntax' +import {app} from '#/lexicons' import {sanitizeHandle} from '#/lib/strings/handles' import {logger} from '#/logger' import {precacheFeedFromGeneratorView} from '#/state/queries/feed' @@ -35,7 +36,7 @@ import type * as bsky from '#/types/bsky' import {Trash_Stroke2_Corner0_Rounded as TrashIcon} from './icons/Trash' type Props = { - view: AppBskyFeedDefs.GeneratorView + view: app.bsky.feed.defs.GeneratorView onPress?: () => void } @@ -254,7 +255,7 @@ export function SaveButton({ pin, ...props }: { - view: AppBskyFeedDefs.GeneratorView | AppBskyGraphDefs.ListView + view: app.bsky.feed.defs.GeneratorView | app.bsky.graph.defs.ListView pin?: boolean text?: boolean } & Partial) { @@ -269,7 +270,7 @@ function SaveButtonInner({ text = true, ...buttonProps }: { - view: AppBskyFeedDefs.GeneratorView | AppBskyGraphDefs.ListView + view: app.bsky.feed.defs.GeneratorView | app.bsky.graph.defs.ListView pin?: boolean text?: boolean } & Partial) { @@ -379,7 +380,7 @@ function SaveButtonInner({ export function createProfileFeedHref({ feed, }: { - feed: AppBskyFeedDefs.GeneratorView + feed: app.bsky.feed.defs.GeneratorView }) { const urip = new AtUri(feed.uri) const handleOrDid = feed.creator.handle || feed.creator.did diff --git a/src/components/FeedInterstitials.tsx b/src/components/FeedInterstitials.tsx index fec0447b61..67e227cd14 100644 --- a/src/components/FeedInterstitials.tsx +++ b/src/components/FeedInterstitials.tsx @@ -7,10 +7,10 @@ import Animated, { LayoutAnimationConfig, LinearTransition, } from 'react-native-reanimated' -import {type AppBskyFeedDefs} from '@atproto/api' import {Trans, useLingui} from '@lingui/react/macro' import {useNavigation} from '@react-navigation/native' +import {app} from '#/lexicons' import {type NavigationProp} from '#/lib/routes/types' import {useModerationOpts} from '#/state/preferences/moderation-opts' import {useGetPopularFeedsQuery} from '#/state/queries/feed' @@ -569,7 +569,7 @@ export function SuggestedFeeds() { const {gtMobile} = useBreakpoints() const feeds = useMemo(() => { - const items: AppBskyFeedDefs.GeneratorView[] = [] + const items: app.bsky.feed.defs.GeneratorView[] = [] if (!data) return items diff --git a/src/components/KnownFollowers.tsx b/src/components/KnownFollowers.tsx index bda482c1c0..164e25ec84 100644 --- a/src/components/KnownFollowers.tsx +++ b/src/components/KnownFollowers.tsx @@ -1,9 +1,9 @@ import {useRef} from 'react' import {View} from 'react-native' -import {type AppBskyActorDefs} from '@atproto/api' import {type ModerationOpts} from '@bsky.app/sdk/moderation' import {Plural, Trans, useLingui} from '@lingui/react/macro' +import {app} from '#/lexicons' import {moderateProfile} from '#/lib/moderation/subjects' import {makeProfileLink} from '#/lib/routes/links' import {sanitizeDisplayName} from '#/lib/strings/display-names' @@ -24,7 +24,7 @@ const AVI_BORDER = 1 * `count` includes blocked users and `followers` does not. */ export function shouldShowKnownFollowers( - knownFollowers?: AppBskyActorDefs.KnownFollowers, + knownFollowers?: app.bsky.actor.defs.KnownFollowers, ) { return knownFollowers && knownFollowers.followers.length > 0 } @@ -42,7 +42,9 @@ export function KnownFollowers({ minimal?: boolean showIfEmpty?: boolean }) { - const cache = useRef>(new Map()) + const cache = useRef>( + new Map(), + ) /* * Results for `knownFollowers` are not sorted consistently, so when @@ -83,7 +85,7 @@ function KnownFollowersInner({ }: { profile: bsky.profile.AnyProfileView moderationOpts: ModerationOpts - cachedKnownFollowers: AppBskyActorDefs.KnownFollowers + cachedKnownFollowers: app.bsky.actor.defs.KnownFollowers onLinkPress?: LinkProps['onPress'] minimal?: boolean showIfEmpty?: boolean diff --git a/src/components/LikedByList.tsx b/src/components/LikedByList.tsx index fcaa50bbcc..a851a17cf9 100644 --- a/src/components/LikedByList.tsx +++ b/src/components/LikedByList.tsx @@ -1,8 +1,8 @@ import {useCallback, useMemo, useState} from 'react' -import {type AppBskyFeedGetLikes as GetLikes} from '@atproto/api' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' +import {app} from '#/lexicons' import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender' import {cleanError} from '#/lib/strings/errors' import {logger} from '#/logger' @@ -12,7 +12,13 @@ import {ProfileCardWithFollowBtn} from '#/view/com/profile/ProfileCard' import {List} from '#/view/com/util/List' import {ListFooter, ListMaybePlaceholder} from '#/components/Lists' -function renderItem({item, index}: {item: GetLikes.Like; index: number}) { +function renderItem({ + item, + index, +}: { + item: app.bsky.feed.getLikes.Like + index: number +}) { return ( peekable?: boolean }) { @@ -59,9 +55,9 @@ export function Embed({ const tiles: React.ReactNode[] = [] for (const item of e.view.items) { if (tiles.length >= 4) break - if (!AppBskyEmbedGallery.isViewImage(item)) continue + if (!bsky.isType(app.bsky.embed.gallery.viewImage, item)) continue if (peekable) { - const image: AppBskyEmbedImages.ViewImage = { + const image: app.bsky.embed.images.ViewImage = { thumb: item.thumbnail, fullsize: item.fullsize, alt: item.alt, @@ -202,7 +198,7 @@ export function VideoItem({ ) } -function PeekableImageItem({image}: {image: AppBskyEmbedImages.ViewImage}) { +function PeekableImageItem({image}: {image: app.bsky.embed.images.ViewImage}) { const {t: l} = useLingui() const saveImage = useSaveImageToMediaLibrary() diff --git a/src/components/NewskieDialog.tsx b/src/components/NewskieDialog.tsx index 7df67d80dc..fda20c2a58 100644 --- a/src/components/NewskieDialog.tsx +++ b/src/components/NewskieDialog.tsx @@ -1,11 +1,11 @@ import {useMemo, useState} from 'react' import {View} from 'react-native' -import {type AppBskyActorDefs} from '@atproto/api' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Trans} from '@lingui/react/macro' import {differenceInSeconds} from 'date-fns' +import {app} from '#/lexicons' import {HITSLOP_10} from '#/lib/constants' import {useGetTimeAgo} from '#/lib/hooks/useTimeAgo' import {moderateProfile} from '#/lib/moderation/subjects' @@ -25,7 +25,7 @@ export function NewskieDialog({ profile, disabled, }: { - profile: AppBskyActorDefs.ProfileViewDetailed + profile: app.bsky.actor.defs.ProfileViewDetailed disabled?: boolean }) { const t = useTheme() @@ -75,7 +75,7 @@ function DialogInner({ createdAt, now, }: { - profile: AppBskyActorDefs.ProfileViewDetailed + profile: app.bsky.actor.defs.ProfileViewDetailed createdAt: string now: number }) { diff --git a/src/components/Post/Embed/ChatInviteEmbed.tsx b/src/components/Post/Embed/ChatInviteEmbed.tsx index d5f69f49e9..05dec19a92 100644 --- a/src/components/Post/Embed/ChatInviteEmbed.tsx +++ b/src/components/Post/Embed/ChatInviteEmbed.tsx @@ -1,6 +1,6 @@ import {type StyleProp, type ViewStyle} from 'react-native' -import {type AppBskyEmbedExternal} from '@atproto/api' +import {app} from '#/lexicons' import {atoms as a} from '#/alf' import * as ChatInvite from '#/components/dms/ChatInvite' import {ExternalEmbed} from '#/components/Post/Embed/ExternalEmbed' @@ -18,7 +18,7 @@ export function ChatInviteEmbed({ style, }: { code: string - link: AppBskyEmbedExternal.ViewExternal + link: app.bsky.embed.external.ViewExternal onOpen?: () => void style?: StyleProp }) { @@ -34,7 +34,7 @@ function ChatInviteEmbedBody({ onOpen, style, }: { - link: AppBskyEmbedExternal.ViewExternal + link: app.bsky.embed.external.ViewExternal onOpen?: () => void style?: StyleProp }) { diff --git a/src/components/Post/Embed/ExternalEmbed/ExternalGif.tsx b/src/components/Post/Embed/ExternalEmbed/ExternalGif.tsx index 529952f08e..c1580566d0 100644 --- a/src/components/Post/Embed/ExternalEmbed/ExternalGif.tsx +++ b/src/components/Post/Embed/ExternalEmbed/ExternalGif.tsx @@ -5,10 +5,10 @@ import { Pressable, } from 'react-native' import {Image} from 'expo-image' -import {type AppBskyEmbedExternal} from '@atproto/api' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' +import {app} from '#/lexicons' import {type EmbedPlayerParams} from '#/lib/strings/embed-player' import {useExternalEmbedsPrefs} from '#/state/preferences' import {atoms as a, useTheme} from '#/alf' @@ -22,7 +22,7 @@ export function ExternalGif({ link, params, }: { - link: AppBskyEmbedExternal.ViewExternal + link: app.bsky.embed.external.ViewExternal params: EmbedPlayerParams }) { const t = useTheme() diff --git a/src/components/Post/Embed/ExternalEmbed/ExternalPlayer.tsx b/src/components/Post/Embed/ExternalEmbed/ExternalPlayer.tsx index 9decdea95b..317b1cd92b 100644 --- a/src/components/Post/Embed/ExternalEmbed/ExternalPlayer.tsx +++ b/src/components/Post/Embed/ExternalEmbed/ExternalPlayer.tsx @@ -15,11 +15,11 @@ import {useSafeAreaInsets} from 'react-native-safe-area-context' import {WebView} from 'react-native-webview' import {scheduleOnRN} from 'react-native-worklets' import {Image} from 'expo-image' -import {type AppBskyEmbedExternal} from '@atproto/api' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {useNavigation} from '@react-navigation/native' +import {app} from '#/lexicons' import {type NavigationProp} from '#/lib/routes/types' import { type EmbedPlayerParams, @@ -122,7 +122,7 @@ export function ExternalPlayer({ link, params, }: { - link: AppBskyEmbedExternal.ViewExternal + link: app.bsky.embed.external.ViewExternal params: EmbedPlayerParams }) { const t = useTheme() diff --git a/src/components/Post/Embed/ExternalEmbed/index.tsx b/src/components/Post/Embed/ExternalEmbed/index.tsx index 4432eb6632..f58001f4fb 100644 --- a/src/components/Post/Embed/ExternalEmbed/index.tsx +++ b/src/components/Post/Embed/ExternalEmbed/index.tsx @@ -1,10 +1,10 @@ import {useMemo} from 'react' import {type StyleProp, View, type ViewStyle} from 'react-native' import {Image} from 'expo-image' -import {type AppBskyEmbedExternal} from '@atproto/api' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' +import {app} from '#/lexicons' import {parseAltFromGIFDescription} from '#/lib/gif-alt-text' import {useHaptics} from '#/lib/haptics' import {shareUrl} from '#/lib/sharing' @@ -30,7 +30,7 @@ export const ExternalEmbed = ({ style, hideAlt, }: { - link: AppBskyEmbedExternal.ViewExternal + link: app.bsky.embed.external.ViewExternal onOpen?: () => void style?: StyleProp hideAlt?: boolean diff --git a/src/components/Post/Embed/ImageEmbed.tsx b/src/components/Post/Embed/ImageEmbed.tsx index 073c47fbb1..0188f2fedf 100644 --- a/src/components/Post/Embed/ImageEmbed.tsx +++ b/src/components/Post/Embed/ImageEmbed.tsx @@ -2,8 +2,9 @@ import {useRef} from 'react' import {InteractionManager, View} from 'react-native' import {type AnimatedRef} from 'react-native-reanimated' import {Image} from 'expo-image' -import {AppBskyEmbedGallery, type AppBskyEmbedImages} from '@atproto/api' +import * as bsky from '#/types/bsky' +import {app} from '#/lexicons' import {atoms as a, tokens} from '#/alf' import {AutoSizedImage} from '#/components/images/AutoSizedImage' import {Gallery} from '#/components/images/Gallery' @@ -29,14 +30,16 @@ export function ImageEmbed({ }) { const ax = useAnalytics() const {openLightbox} = useLightboxControls() - const images: AppBskyEmbedImages.ViewImage[] = + const images: app.bsky.embed.images.ViewImage[] = embed.type === 'gallery' - ? embed.view.items.filter(AppBskyEmbedGallery.isViewImage).map(item => ({ - thumb: item.thumbnail, - fullsize: item.fullsize, - alt: item.alt, - aspectRatio: item.aspectRatio, - })) + ? embed.view.items + .filter(item => bsky.isType(app.bsky.embed.gallery.viewImage, item)) + .map(item => ({ + thumb: item.thumbnail, + fullsize: item.fullsize, + alt: item.alt, + aspectRatio: item.aspectRatio, + })) : embed.view.images const useExpandedLayout = embed.type === 'gallery' diff --git a/src/components/Post/Embed/StandardSiteEmbed/StandardSiteMetaRow.tsx b/src/components/Post/Embed/StandardSiteEmbed/StandardSiteMetaRow.tsx index 837f1b4a05..a5b8030214 100644 --- a/src/components/Post/Embed/StandardSiteEmbed/StandardSiteMetaRow.tsx +++ b/src/components/Post/Embed/StandardSiteEmbed/StandardSiteMetaRow.tsx @@ -1,8 +1,8 @@ import {Fragment, type ReactNode} from 'react' import {View} from 'react-native' -import {AtUri} from '@atproto/api' import {Trans} from '@lingui/react/macro' +import {AtUri} from '@atproto/syntax' import {toNiceDomain} from '#/lib/strings/url-helpers' import {atoms as a, useTheme} from '#/alf' import { diff --git a/src/components/Post/Embed/StandardSiteEmbed/StandardSiteThemeProvider.tsx b/src/components/Post/Embed/StandardSiteEmbed/StandardSiteThemeProvider.tsx index 00c15c4401..bd8dcd3362 100644 --- a/src/components/Post/Embed/StandardSiteEmbed/StandardSiteThemeProvider.tsx +++ b/src/components/Post/Embed/StandardSiteEmbed/StandardSiteThemeProvider.tsx @@ -1,5 +1,4 @@ -import {type AppBskyEmbedExternal} from '@atproto/api' - +import {app} from '#/lexicons' import {Context, useAlf, utils} from '#/alf' /** @@ -12,7 +11,7 @@ export function StandardSiteThemeProvider({ view, children, }: { - view: AppBskyEmbedExternal.ViewExternal + view: app.bsky.embed.external.ViewExternal children: React.ReactNode }) { const alf = useAlf() diff --git a/src/components/Post/Embed/StandardSiteEmbed/index.tsx b/src/components/Post/Embed/StandardSiteEmbed/index.tsx index bb4c030fcc..3bb1e0cd68 100644 --- a/src/components/Post/Embed/StandardSiteEmbed/index.tsx +++ b/src/components/Post/Embed/StandardSiteEmbed/index.tsx @@ -1,9 +1,9 @@ import {type StyleProp, View, type ViewStyle} from 'react-native' import {Image} from 'expo-image' -import {AtUri} from '@atproto/api' import {plural} from '@lingui/core/macro' import {useLingui} from '@lingui/react/macro' +import {AtUri} from '@atproto/syntax' import {useHaptics} from '#/lib/haptics' import {shareUrl} from '#/lib/sharing' import {niceDate} from '#/lib/strings/time' diff --git a/src/components/Post/Embed/StandardSiteEmbed/publishers.ts b/src/components/Post/Embed/StandardSiteEmbed/publishers.ts index aba3e28cc2..56a44c22aa 100644 --- a/src/components/Post/Embed/StandardSiteEmbed/publishers.ts +++ b/src/components/Post/Embed/StandardSiteEmbed/publishers.ts @@ -1,5 +1,4 @@ -import {type AppBskyEmbedExternal} from '@atproto/api' - +import {app} from '#/lexicons' import {Leaflet} from '#/components/icons/community/Leaflet' import {Offprint} from '#/components/icons/community/Offprint' import {Pckt} from '#/components/icons/community/Pckt' @@ -25,7 +24,7 @@ function hostFromUri(uri: string | undefined): string | null { } export function getStandardSitePublisherHost( - view: AppBskyEmbedExternal.ViewExternal, + view: app.bsky.embed.external.ViewExternal, ): string | null { return hostFromUri(view.source?.uri) } @@ -40,7 +39,7 @@ function matchByHost(host: string | null): StandardSitePublisher | null { } export function matchStandardSitePublisher( - view: AppBskyEmbedExternal.ViewExternal, + view: app.bsky.embed.external.ViewExternal, ): StandardSitePublisher | null { return matchByHost(getStandardSitePublisherHost(view)) } diff --git a/src/components/Post/Embed/StandardSiteEmbed/types.ts b/src/components/Post/Embed/StandardSiteEmbed/types.ts index 208f01b7a6..708fe55309 100644 --- a/src/components/Post/Embed/StandardSiteEmbed/types.ts +++ b/src/components/Post/Embed/StandardSiteEmbed/types.ts @@ -1,7 +1,7 @@ -import {type AppBskyEmbedExternal} from '@atproto/api' +import {app} from '#/lexicons' export type CommonProps = { - view: AppBskyEmbedExternal.ViewExternal + view: app.bsky.embed.external.ViewExternal } export type PreviewProps = { diff --git a/src/components/Post/Embed/StandardSiteEmbed/utils.test.ts b/src/components/Post/Embed/StandardSiteEmbed/utils.test.ts index 5f5dd23d60..f18f366767 100644 --- a/src/components/Post/Embed/StandardSiteEmbed/utils.test.ts +++ b/src/components/Post/Embed/StandardSiteEmbed/utils.test.ts @@ -1,10 +1,9 @@ -import {type AppBskyEmbedExternal} from '@atproto/api' - import {isStandardSiteEmbed, isStandardSitePublicationEmbed} from './utils' +import {app} from '#/lexicons' function makeView( partial: Record, -): AppBskyEmbedExternal.ViewExternal { +): app.bsky.embed.external.ViewExternal { return { uri: 'https://example.com/post', title: 'title', diff --git a/src/components/Post/Embed/StandardSiteEmbed/utils.ts b/src/components/Post/Embed/StandardSiteEmbed/utils.ts index 2338ca59a3..bc041d2855 100644 --- a/src/components/Post/Embed/StandardSiteEmbed/utils.ts +++ b/src/components/Post/Embed/StandardSiteEmbed/utils.ts @@ -1,29 +1,30 @@ -import { - type AppBskyEmbedExternal, - AtUri, - type ComAtprotoRepoStrongRef, -} from '@atproto/api' +import {AtUri} from '@atproto/syntax' +import {app, com} from '#/lexicons' -export function isStandardSiteDocumentUri(ref: ComAtprotoRepoStrongRef.Main) { +export function isStandardSiteDocumentUri( + ref: com.atproto.repo.strongRef.Main, +) { return new AtUri(ref.uri).collection.startsWith('site.standard.document') } export function isStandardSitePublicationUri( - ref: ComAtprotoRepoStrongRef.Main, + ref: com.atproto.repo.strongRef.Main, ) { return new AtUri(ref.uri).collection.startsWith('site.standard.publication') } -export function isStandardSiteUri(ref: ComAtprotoRepoStrongRef.Main) { +export function isStandardSiteUri(ref: com.atproto.repo.strongRef.Main) { return new AtUri(ref.uri).collection.startsWith('site.standard.') } -export function isStandardSiteEmbed(view: AppBskyEmbedExternal.ViewExternal) { +export function isStandardSiteEmbed( + view: app.bsky.embed.external.ViewExternal, +) { return view.associatedRefs?.some(ref => isStandardSiteUri(ref)) } export function isStandardSitePublicationEmbed( - view: AppBskyEmbedExternal.ViewExternal, + view: app.bsky.embed.external.ViewExternal, ) { return ( view.associatedRefs?.some( diff --git a/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx b/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx index bcc33ba50b..2879f43b34 100644 --- a/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx +++ b/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerNative.tsx @@ -1,9 +1,9 @@ import {useImperativeHandle, useRef, useState} from 'react' import {Pressable, type StyleProp, View, type ViewStyle} from 'react-native' -import {type AppBskyEmbedVideo} from '@atproto/api' import {BlueskyVideoView} from '@bsky.app/video' import {useLingui} from '@lingui/react/macro' +import {app} from '#/lexicons' import {HITSLOP_30} from '#/lib/constants' import {useAutoplayDisabled} from '#/state/preferences' import {atoms as a, useTheme} from '#/alf' @@ -29,7 +29,7 @@ export function VideoEmbedInnerNative({ onError, }: { ref: React.Ref<{togglePlayback: () => void}> - embed: AppBskyEmbedVideo.View + embed: app.bsky.embed.video.View setStatus: (status: 'playing' | 'paused') => void setIsLoading: (isLoading: boolean) => void setIsActive: (isActive: boolean) => void diff --git a/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.shared.ts b/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.shared.ts index 9184ccf37c..3855603408 100644 --- a/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.shared.ts +++ b/src/components/Post/Embed/VideoEmbed/VideoEmbedInner/VideoEmbedInnerWeb.shared.ts @@ -1,7 +1,7 @@ -import {type AppBskyEmbedVideo} from '@atproto/api' +import {app} from '#/lexicons' export type VideoEmbedInnerWebProps = { - embed: AppBskyEmbedVideo.View + embed: app.bsky.embed.video.View active: boolean setActive: () => void onScreen: boolean diff --git a/src/components/Post/Embed/VideoEmbed/index.tsx b/src/components/Post/Embed/VideoEmbed/index.tsx index d78aad4985..4f789e1e4a 100644 --- a/src/components/Post/Embed/VideoEmbed/index.tsx +++ b/src/components/Post/Embed/VideoEmbed/index.tsx @@ -1,7 +1,6 @@ import {useCallback, useEffect, useRef, useState} from 'react' import {ActivityIndicator, View} from 'react-native' import {ImageBackground} from 'expo-image' -import {type AppBskyEmbedVideo} from '@atproto/api' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Trans} from '@lingui/react/macro' @@ -10,6 +9,7 @@ import { createPlaybackTelemetry, type PlaybackTelemetry, } from '#/lib/media/video/playbackTelemetry' +import {app} from '#/lexicons' import {ErrorBoundary} from '#/view/com/util/ErrorBoundary' import {atoms as a, platform} from '#/alf' import {Button} from '#/components/Button' @@ -22,7 +22,7 @@ import {VideoEmbedInnerNative} from './VideoEmbedInner/VideoEmbedInnerNative' import * as VideoFallback from './VideoEmbedInner/VideoFallback' interface Props { - embed: AppBskyEmbedVideo.View + embed: app.bsky.embed.video.View } export function VideoEmbed({embed}: Props) { diff --git a/src/components/Post/Embed/VideoEmbed/index.web.tsx b/src/components/Post/Embed/VideoEmbed/index.web.tsx index 0eb622bad7..7118f65bc8 100644 --- a/src/components/Post/Embed/VideoEmbed/index.web.tsx +++ b/src/components/Post/Embed/VideoEmbed/index.web.tsx @@ -7,10 +7,10 @@ import { useState, } from 'react' import {View} from 'react-native' -import {type AppBskyEmbedVideo} from '@atproto/api' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' +import {app} from '#/lexicons' import {ErrorBoundary} from '#/view/com/util/ErrorBoundary' import {atoms as a, useTheme} from '#/alf' import {useIsWithinMessage} from '#/components/dms/MessageContext' @@ -37,7 +37,7 @@ const noop = () => {} */ const MIN_CARD_WIDTH = 280 -export function VideoEmbed({embed}: {embed: AppBskyEmbedVideo.View}) { +export function VideoEmbed({embed}: {embed: app.bsky.embed.video.View}) { const t = useTheme() const ref = useRef(null) const { @@ -297,7 +297,7 @@ function VideoError({ error, retry, }: { - embed: AppBskyEmbedVideo.View + embed: app.bsky.embed.video.View error: unknown retry: () => void }) { diff --git a/src/components/Post/Embed/index.tsx b/src/components/Post/Embed/index.tsx index 3c31bd72a4..4f4a5ae05f 100644 --- a/src/components/Post/Embed/index.tsx +++ b/src/components/Post/Embed/index.tsx @@ -1,15 +1,12 @@ import {useCallback, useMemo} from 'react' import {View} from 'react-native' -import { - type $Typed, - type AppBskyFeedDefs, - AppBskyFeedPost, - AtUri, -} from '@atproto/api' import {RichText as RichTextAPI} from '@bsky.app/sdk/richtext' import {Trans} from '@lingui/react/macro' import {useQueryClient} from '@tanstack/react-query' +import {type $Typed} from '@atproto/lex' +import {AtUri} from '@atproto/syntax' +import {app} from '#/lexicons' import {moderatePost} from '#/lib/moderation/subjects' import {makeProfileLink} from '#/lib/routes/links' import {asSdkFacets} from '#/lib/strings/rich-text-helpers' @@ -267,7 +264,7 @@ export function QuoteEmbed({ linkDisabled?: boolean }) { const moderationOpts = useModerationOpts() - const quote = useMemo<$Typed>( + const quote = useMemo<$Typed>( () => ({ ...embed.view, $type: 'app.bsky.feed.defs#postView', @@ -287,13 +284,7 @@ export function QuoteEmbed({ const itemTitle = `Post by ${quote.author.handle}` const richText = useMemo(() => { - if ( - !bsky.dangerousIsType( - quote.record, - AppBskyFeedPost.isRecord, - ) - ) - return undefined + if (!bsky.isType(app.bsky.feed.post, quote.record)) return undefined const {text, facets} = quote.record return text.trim() ? new RichTextAPI({text: text, facets: asSdkFacets(facets)}) diff --git a/src/components/Post/Embed/types.ts b/src/components/Post/Embed/types.ts index 41031fdf05..2e2a13da08 100644 --- a/src/components/Post/Embed/types.ts +++ b/src/components/Post/Embed/types.ts @@ -1,6 +1,6 @@ import {type StyleProp, type ViewStyle} from 'react-native' -import {type AppBskyFeedDefs} from '@atproto/api' import {type ModerationDecision} from '@bsky.app/sdk/moderation' +import {app} from '#/lexicons' export enum PostEmbedViewContext { ThreadHighlighted = 'ThreadHighlighted', @@ -20,10 +20,10 @@ export type CommonProps = { * events (post:photoEmbed:*). When the embed has no owning post (e.g. * composer previews), leave this undefined and no events will be emitted. */ - post?: AppBskyFeedDefs.PostView + post?: app.bsky.feed.defs.PostView feedDescriptor?: string } export type EmbedProps = CommonProps & { - embed?: AppBskyFeedDefs.PostView['embed'] + embed?: app.bsky.feed.defs.PostView['embed'] } diff --git a/src/components/Post/Translated/index.tsx b/src/components/Post/Translated/index.tsx index 94e0ea697a..5ba1f9c41f 100644 --- a/src/components/Post/Translated/index.tsx +++ b/src/components/Post/Translated/index.tsx @@ -1,8 +1,8 @@ import {useCallback, useMemo} from 'react' import {Platform, type StyleProp, type TextStyle, View} from 'react-native' -import {type AppBskyFeedDefs, AppBskyFeedPost} from '@atproto/api' import {Trans, useLingui} from '@lingui/react/macro' +import {app} from '#/lexicons' import {HITSLOP_30} from '#/lib/constants' import {useTranslate} from '#/lib/translation' import { @@ -38,7 +38,7 @@ export function TranslatedPost({ postTextStyle = a.text_md, }: { hideTranslateLink?: boolean - post: AppBskyFeedDefs.PostView + post: app.bsky.feed.defs.PostView postTextStyle?: StyleProp }) { const langPrefs = useLanguagePrefs() @@ -46,11 +46,8 @@ export function TranslatedPost({ key: post.uri, }) - const record = useMemo(() => { - return bsky.dangerousIsType( - post.record, - AppBskyFeedPost.isRecord, - ) + const record = useMemo(() => { + return bsky.isType(app.bsky.feed.post, post.record) ? post.record : undefined }, [post]) diff --git a/src/components/PostControls/BookmarkButton.tsx b/src/components/PostControls/BookmarkButton.tsx index b2ed043365..1866df07c7 100644 --- a/src/components/PostControls/BookmarkButton.tsx +++ b/src/components/PostControls/BookmarkButton.tsx @@ -1,10 +1,10 @@ import {memo} from 'react' import {type Insets} from 'react-native' -import {type AppBskyFeedDefs} from '@atproto/api' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Trans} from '@lingui/react/macro' +import {app} from '#/lexicons' import {useCleanError} from '#/lib/hooks/useCleanError' import {type Shadow} from '#/state/cache/post-shadow' import {useFeedFeedbackContext} from '#/state/feed-feedback' @@ -23,7 +23,7 @@ export const BookmarkButton = memo(function BookmarkButton({ logContext, hitSlop, }: { - post: Shadow + post: Shadow big?: boolean logContext: 'FeedItem' | 'PostThreadItem' | 'Post' | 'ImmersiveVideo' hitSlop?: Insets diff --git a/src/components/PostControls/PostMenu/PostMenuItems.tsx b/src/components/PostControls/PostMenu/PostMenuItems.tsx index 43fdaaf1cd..abfc888213 100644 --- a/src/components/PostControls/PostMenu/PostMenuItems.tsx +++ b/src/components/PostControls/PostMenu/PostMenuItems.tsx @@ -6,17 +6,13 @@ import { type ViewStyle, } from 'react-native' import * as Clipboard from 'expo-clipboard' -import { - type AppBskyFeedDefs, - type AppBskyFeedPost, - type AppBskyFeedThreadgate, - AtUri, -} from '@atproto/api' import {type RichText as RichTextAPI} from '@bsky.app/sdk/richtext' import {plural} from '@lingui/core/macro' import {useLingui} from '@lingui/react/macro' import {useNavigation} from '@react-navigation/native' +import {AtUri} from '@atproto/syntax' +import {app} from '#/lexicons' import {DISCOVER_DEBUG_DIDS} from '#/lib/constants' import {useOpenLink} from '#/lib/hooks/useOpenLink' import {getCurrentRoute} from '#/lib/routes/helpers' @@ -110,17 +106,17 @@ let PostMenuItems = ({ forceGoogleTranslate, }: { testID: string - post: Shadow + post: Shadow postFeedContext: string | undefined postReqId: string | undefined - record: AppBskyFeedPost.Record + record: app.bsky.feed.post.Main richText: RichTextAPI style?: StyleProp hitSlop?: PressableProps['hitSlop'] size?: 'lg' | 'md' | 'sm' timestamp: string - threadgateRecord?: AppBskyFeedThreadgate.Record - onShowLess?: (interaction: AppBskyFeedDefs.Interaction) => void + threadgateRecord?: app.bsky.feed.threadgate.Main + onShowLess?: (interaction: app.bsky.feed.defs.Interaction) => void logContext: 'FeedItem' | 'PostThreadItem' | 'Post' | 'ImmersiveVideo' forceGoogleTranslate: boolean }): React.ReactNode => { diff --git a/src/components/PostControls/PostMenu/index.tsx b/src/components/PostControls/PostMenu/index.tsx index c0826683b6..8d9da5f03d 100644 --- a/src/components/PostControls/PostMenu/index.tsx +++ b/src/components/PostControls/PostMenu/index.tsx @@ -1,13 +1,9 @@ import {memo, useMemo, useState} from 'react' import {type Insets} from 'react-native' -import { - type AppBskyFeedDefs, - type AppBskyFeedPost, - type AppBskyFeedThreadgate, -} from '@atproto/api' import {type RichText as RichTextAPI} from '@bsky.app/sdk/richtext' import {useLingui} from '@lingui/react/macro' +import {app} from '#/lexicons' import {type Shadow} from '#/state/cache/post-shadow' import {EventStopper} from '#/view/com/util/EventStopper' import {DotGrid3x1_Stroke2_Corner0_Rounded as DotsHorizontal} from '#/components/icons/DotGrid' @@ -32,15 +28,15 @@ let PostMenuButton = ({ forceGoogleTranslate, }: { testID: string - post: Shadow + post: Shadow postFeedContext: string | undefined postReqId: string | undefined big?: boolean - record: AppBskyFeedPost.Record + record: app.bsky.feed.post.Main richText: RichTextAPI timestamp: string - threadgateRecord?: AppBskyFeedThreadgate.Record - onShowLess?: (interaction: AppBskyFeedDefs.Interaction) => void + threadgateRecord?: app.bsky.feed.threadgate.Main + onShowLess?: (interaction: app.bsky.feed.defs.Interaction) => void hitSlop?: Insets logContext: 'FeedItem' | 'PostThreadItem' | 'Post' | 'ImmersiveVideo' forceGoogleTranslate: boolean diff --git a/src/components/PostControls/ShareMenu/RecentChats.tsx b/src/components/PostControls/ShareMenu/RecentChats.tsx index 94086c420d..9a7f0c4923 100644 --- a/src/components/PostControls/ShareMenu/RecentChats.tsx +++ b/src/components/PostControls/ShareMenu/RecentChats.tsx @@ -1,11 +1,11 @@ import {ScrollView, View} from 'react-native' -import {type ChatBskyActorDefs} from '@atproto/api' import {type ModerationOpts} from '@bsky.app/sdk/moderation' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Trans} from '@lingui/react/macro' import {useNavigation} from '@react-navigation/native' +import {chat} from '#/lexicons' import {isBlockedOrBlocking, isMuted} from '#/lib/moderation/blocked-and-muted' import {createSanitizedDisplayName} from '#/lib/moderation/create-sanitized-display-name' import {moderateProfile} from '#/lib/moderation/subjects' @@ -114,7 +114,7 @@ function RecentChatItem({ onPress: () => void moderationOpts: ModerationOpts convo: ConvoWithDetails - primaryMember: ChatBskyActorDefs.ProfileViewBasic + primaryMember: chat.bsky.actor.defs.ProfileViewBasic }) { const {_} = useLingui() const t = useTheme() diff --git a/src/components/PostControls/ShareMenu/ShareMenuItems.tsx b/src/components/PostControls/ShareMenu/ShareMenuItems.tsx index dc66340fd3..000c7f2595 100644 --- a/src/components/PostControls/ShareMenu/ShareMenuItems.tsx +++ b/src/components/PostControls/ShareMenu/ShareMenuItems.tsx @@ -1,10 +1,10 @@ import {memo, useMemo} from 'react' import * as ExpoClipboard from 'expo-clipboard' -import {AtUri} from '@atproto/api' import {Trans, useLingui} from '@lingui/react/macro' import {useNavigation} from '@react-navigation/native' import {useQueryClient} from '@tanstack/react-query' +import {AtUri} from '@atproto/syntax' import {makeProfileLink} from '#/lib/routes/links' import {type NavigationProp} from '#/lib/routes/types' import {shareText, shareUrl} from '#/lib/sharing' diff --git a/src/components/PostControls/ShareMenu/ShareMenuItems.types.tsx b/src/components/PostControls/ShareMenu/ShareMenuItems.types.tsx index ef93865513..3b3da16e60 100644 --- a/src/components/PostControls/ShareMenu/ShareMenuItems.types.tsx +++ b/src/components/PostControls/ShareMenu/ShareMenuItems.types.tsx @@ -1,22 +1,18 @@ import {type PressableProps, type StyleProp, type ViewStyle} from 'react-native' -import { - type AppBskyFeedDefs, - type AppBskyFeedPost, - type AppBskyFeedThreadgate, -} from '@atproto/api' import {type RichText as RichTextAPI} from '@bsky.app/sdk/richtext' +import {app} from '#/lexicons' import {type Shadow} from '#/state/cache/post-shadow' export interface ShareMenuItemsProps { testID: string - post: Shadow - record: AppBskyFeedPost.Record + post: Shadow + record: app.bsky.feed.post.Main richText: RichTextAPI style?: StyleProp hitSlop?: PressableProps['hitSlop'] size?: 'lg' | 'md' | 'sm' timestamp: string - threadgateRecord?: AppBskyFeedThreadgate.Record + threadgateRecord?: app.bsky.feed.threadgate.Main onShare: () => void } diff --git a/src/components/PostControls/ShareMenu/ShareMenuItems.web.tsx b/src/components/PostControls/ShareMenu/ShareMenuItems.web.tsx index 1950be0c4b..298654d9eb 100644 --- a/src/components/PostControls/ShareMenu/ShareMenuItems.web.tsx +++ b/src/components/PostControls/ShareMenu/ShareMenuItems.web.tsx @@ -1,8 +1,8 @@ import {memo, useMemo} from 'react' -import {AtUri} from '@atproto/api' import {Trans, useLingui} from '@lingui/react/macro' import {useNavigation} from '@react-navigation/native' +import {AtUri} from '@atproto/syntax' import {makeProfileLink} from '#/lib/routes/links' import {type NavigationProp} from '#/lib/routes/types' import {shareText, shareUrl} from '#/lib/sharing' diff --git a/src/components/PostControls/ShareMenu/index.tsx b/src/components/PostControls/ShareMenu/index.tsx index 121cd2a779..bd5c397400 100644 --- a/src/components/PostControls/ShareMenu/index.tsx +++ b/src/components/PostControls/ShareMenu/index.tsx @@ -1,15 +1,11 @@ import {memo, useMemo, useState} from 'react' import {type Insets} from 'react-native' -import { - type AppBskyFeedDefs, - type AppBskyFeedPost, - type AppBskyFeedThreadgate, - AtUri, -} from '@atproto/api' import {type RichText as RichTextAPI} from '@bsky.app/sdk/richtext' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' +import {AtUri} from '@atproto/syntax' +import {app} from '#/lexicons' import {makeProfileLink} from '#/lib/routes/links' import {shareUrl} from '#/lib/sharing' import {toShareUrl} from '#/lib/strings/url-helpers' @@ -37,12 +33,12 @@ let ShareMenuButton = ({ logContext, }: { testID: string - post: Shadow + post: Shadow big?: boolean - record: AppBskyFeedPost.Record + record: app.bsky.feed.post.Main richText: RichTextAPI timestamp: string - threadgateRecord?: AppBskyFeedThreadgate.Record + threadgateRecord?: app.bsky.feed.threadgate.Main onShare: () => void hitSlop?: Insets logContext: 'FeedItem' | 'PostThreadItem' | 'Post' | 'ImmersiveVideo' diff --git a/src/components/PostControls/index.tsx b/src/components/PostControls/index.tsx index 88f30b0561..697ffd8b77 100644 --- a/src/components/PostControls/index.tsx +++ b/src/components/PostControls/index.tsx @@ -1,14 +1,10 @@ import {memo, useMemo, useState} from 'react' import {type StyleProp, View, type ViewStyle} from 'react-native' -import { - type AppBskyFeedDefs, - type AppBskyFeedPost, - type AppBskyFeedThreadgate, -} from '@atproto/api' import {type RichText as RichTextAPI} from '@bsky.app/sdk/richtext' import {plural} from '@lingui/core/macro' import {useLingui} from '@lingui/react/macro' +import {app} from '#/lexicons' import {CountWheel} from '#/lib/custom-animations/CountWheel' import {AnimatedLikeIcon} from '#/lib/custom-animations/LikeIcon' import {useOpenComposer} from '#/lib/hooks/useOpenComposer' @@ -57,8 +53,8 @@ let PostControls = ({ forceGoogleTranslate = false, }: { big?: boolean - post: Shadow - record: AppBskyFeedPost.Record + post: Shadow + record: app.bsky.feed.post.Main richText: RichTextAPI feedContext?: string | undefined reqId?: string | undefined @@ -66,8 +62,8 @@ let PostControls = ({ onPressReply: () => void onPostReply?: (postUri: string | undefined) => void logContext: 'FeedItem' | 'PostThreadItem' | 'Post' | 'ImmersiveVideo' - threadgateRecord?: AppBskyFeedThreadgate.Record - onShowLess?: (interaction: AppBskyFeedDefs.Interaction) => void + threadgateRecord?: app.bsky.feed.threadgate.Main + onShowLess?: (interaction: app.bsky.feed.defs.Interaction) => void viaRepost?: {uri: string; cid: string} variant?: 'compact' | 'normal' | 'large' forceGoogleTranslate?: boolean diff --git a/src/components/ProfileHoverCard/index.web.tsx b/src/components/ProfileHoverCard/index.web.tsx index 74dbb33f28..39fa40233a 100644 --- a/src/components/ProfileHoverCard/index.web.tsx +++ b/src/components/ProfileHoverCard/index.web.tsx @@ -1,12 +1,12 @@ import {memo, useCallback, useEffect, useMemo, useReducer, useRef} from 'react' import {View} from 'react-native' -import {type AppBskyActorDefs} from '@atproto/api' import {type ModerationOpts} from '@bsky.app/sdk/moderation' import {flip, offset, shift, size, useFloating} from '@floating-ui/react-dom' import {msg, plural} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {useNavigation} from '@react-navigation/native' +import {app} from '#/lexicons' import {getModerationCauseKey} from '#/lib/moderation' import {moderateProfile} from '#/lib/moderation/subjects' import {makeProfileLink} from '#/lib/routes/links' @@ -416,7 +416,7 @@ function Inner({ moderationOpts, hide, }: { - profile: AppBskyActorDefs.ProfileViewDetailed + profile: app.bsky.actor.defs.ProfileViewDetailed moderationOpts: ModerationOpts hide: () => void }) { diff --git a/src/components/StarterPack/Main/FeedsList.tsx b/src/components/StarterPack/Main/FeedsList.tsx index 43ceacc629..87320831b0 100644 --- a/src/components/StarterPack/Main/FeedsList.tsx +++ b/src/components/StarterPack/Main/FeedsList.tsx @@ -1,7 +1,7 @@ import {forwardRef, useCallback, useImperativeHandle, useState} from 'react' import {type ListRenderItemInfo, View} from 'react-native' -import {type AppBskyFeedDefs} from '@atproto/api' +import {app} from '#/lexicons' import {useBottomBarOffset} from '#/lib/hooks/useBottomBarOffset' import {List, type ListRef} from '#/view/com/util/List' import {type SectionRef} from '#/screens/Profile/Sections/types' @@ -9,12 +9,12 @@ import {atoms as a, useTheme} from '#/alf' import * as FeedCard from '#/components/FeedCard' import {IS_NATIVE, IS_WEB} from '#/env' -function keyExtractor(item: AppBskyFeedDefs.GeneratorView) { +function keyExtractor(item: app.bsky.feed.defs.GeneratorView) { return item.uri } interface ProfilesListProps { - feeds: AppBskyFeedDefs.GeneratorView[] + feeds: app.bsky.feed.defs.GeneratorView[] headerHeight: number scrollElRef: ListRef } @@ -39,7 +39,7 @@ export const FeedsList = forwardRef( const renderItem = ({ item, index, - }: ListRenderItemInfo) => { + }: ListRenderItemInfo) => { return ( + InfiniteData > moderationOpts: ModerationOpts headerHeight: number @@ -87,7 +84,7 @@ export const ProfilesList = forwardRef( const renderItem = ({ item, index, - }: ListRenderItemInfo) => { + }: ListRenderItemInfo) => { return ( | React.ReactElement } -function keyExtractor(item: AppBskyGraphDefs.StarterPackViewBasic) { +function keyExtractor(item: app.bsky.graph.defs.StarterPackViewBasic) { return item.uri } @@ -147,7 +147,7 @@ export function ProfileStarterPacks({ ({ item, index, - }: ListRenderItemInfo) => { + }: ListRenderItemInfo) => { return ( }) { const {record} = starterPack - if ( - !bsky.dangerousIsType( - record, - AppBskyGraphStarterpack.isRecord, - ) - ) { + if (!bsky.isType(app.bsky.graph.starterpack, record)) { return null } diff --git a/src/components/StarterPack/QrCodeDialog.tsx b/src/components/StarterPack/QrCodeDialog.tsx index e239eee9a4..35dea682ca 100644 --- a/src/components/StarterPack/QrCodeDialog.tsx +++ b/src/components/StarterPack/QrCodeDialog.tsx @@ -3,11 +3,11 @@ import {View} from 'react-native' import type ViewShot from 'react-native-view-shot' import {requestPermissionsAsync, saveToLibraryAsync} from 'expo-media-library' import * as Sharing from 'expo-sharing' -import {type AppBskyGraphDefs, AppBskyGraphStarterpack} from '@atproto/api' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Trans} from '@lingui/react/macro' +import {app} from '#/lexicons' import {logger} from '#/logger' import {atoms as a, useBreakpoints} from '#/alf' import {Button, ButtonIcon, ButtonText} from '#/components/Button' @@ -28,7 +28,7 @@ export function QrCodeDialog({ link, control, }: { - starterPack: AppBskyGraphDefs.StarterPackView + starterPack: app.bsky.graph.defs.StarterPackView link?: string control: DialogControlProps }) { @@ -87,12 +87,7 @@ export function QrCodeDialog({ } else { setIsSaveProcessing(true) - if ( - !bsky.validate( - starterPack.record, - AppBskyGraphStarterpack.validateRecord, - ) - ) { + if (!bsky.matches(app.bsky.graph.starterpack, starterPack.record)) { return } diff --git a/src/components/StarterPack/ShareDialog.tsx b/src/components/StarterPack/ShareDialog.tsx index 0dd640d3c0..db0e6cd7c5 100644 --- a/src/components/StarterPack/ShareDialog.tsx +++ b/src/components/StarterPack/ShareDialog.tsx @@ -1,10 +1,10 @@ import {View} from 'react-native' import {Image} from 'expo-image' -import {type AppBskyGraphDefs} from '@atproto/api' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Trans} from '@lingui/react/macro' +import {app} from '#/lexicons' import {useSaveImageToMediaLibrary} from '#/lib/media/save-image' import {shareUrl} from '#/lib/sharing' import {getStarterPackOgCard} from '#/lib/strings/starter-pack' @@ -21,7 +21,7 @@ import {useAnalytics} from '#/analytics' import {IS_NATIVE, IS_WEB} from '#/env' interface Props { - starterPack: AppBskyGraphDefs.StarterPackView + starterPack: app.bsky.graph.defs.StarterPackView link?: string imageLoaded?: boolean qrDialogControl: DialogControlProps diff --git a/src/components/StarterPack/StarterPackCard.tsx b/src/components/StarterPack/StarterPackCard.tsx index 97c5c6fe82..247ce56434 100644 --- a/src/components/StarterPack/StarterPackCard.tsx +++ b/src/components/StarterPack/StarterPackCard.tsx @@ -1,12 +1,13 @@ import {useMemo} from 'react' import {View} from 'react-native' import {Image} from 'expo-image' -import {AppBskyGraphStarterpack, AtUri} from '@atproto/api' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Plural, Trans} from '@lingui/react/macro' import {useQueryClient} from '@tanstack/react-query' +import {AtUri} from '@atproto/syntax' +import {app} from '#/lexicons' import {sanitizeHandle} from '#/lib/strings/handles' import {getStarterPackOgCard} from '#/lib/strings/starter-pack' import {precacheResolvedUri} from '#/state/queries/resolve-uri' @@ -62,12 +63,7 @@ export function Card({ const t = useTheme() const {currentAccount} = useSession() - if ( - !bsky.dangerousIsType( - record, - AppBskyGraphStarterpack.isRecord, - ) - ) { + if (!bsky.isType(app.bsky.graph.starterpack, record)) { return null } @@ -127,10 +123,7 @@ export function useStarterPackLink({ return { to: `/starter-pack/${handleOrDid}/${rkey}`, - label: bsky.dangerousIsType( - view.record, - AppBskyGraphStarterpack.isRecord, - ) + label: bsky.isType(app.bsky.graph.starterpack, view.record) ? _(msg`Navigate to ${view.record.name}`) : _(msg`Navigate to starter pack`), precache, @@ -154,12 +147,7 @@ export function Link({ return {rkey, handleOrDid: creator.handle || creator.did} }, [starterPack]) - if ( - !bsky.dangerousIsType( - record, - AppBskyGraphStarterpack.isRecord, - ) - ) { + if (!bsky.isType(app.bsky.graph.starterpack, record)) { return null } diff --git a/src/components/StarterPack/Wizard/WizardEditListDialog.tsx b/src/components/StarterPack/Wizard/WizardEditListDialog.tsx index 498300491d..933046612c 100644 --- a/src/components/StarterPack/Wizard/WizardEditListDialog.tsx +++ b/src/components/StarterPack/Wizard/WizardEditListDialog.tsx @@ -1,12 +1,12 @@ import {useRef} from 'react' import {type ListRenderItemInfo} from 'react-native' import {View} from 'react-native' -import {type AppBskyActorDefs, type AppBskyFeedDefs} from '@atproto/api' import {type ModerationOpts} from '@bsky.app/sdk/moderation' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Trans} from '@lingui/react/macro' +import {app} from '#/lexicons' import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender' import {type ListMethods} from '#/view/com/util/List' import { @@ -24,7 +24,7 @@ import {Text} from '#/components/Typography' import {IS_WEB} from '#/env' function keyExtractor( - item: AppBskyActorDefs.ProfileViewBasic | AppBskyFeedDefs.GeneratorView, + item: app.bsky.actor.defs.ProfileViewBasic | app.bsky.feed.defs.GeneratorView, index: number, ) { return `${item.did}-${index}` @@ -41,7 +41,7 @@ export function WizardEditListDialog({ state: WizardState dispatch: (action: WizardAction) => void moderationOpts: ModerationOpts - profile: AppBskyActorDefs.ProfileViewDetailed + profile: app.bsky.actor.defs.ProfileViewDetailed }) { const {_} = useLingui() const t = useTheme() diff --git a/src/components/StarterPack/Wizard/WizardListCard.tsx b/src/components/StarterPack/Wizard/WizardListCard.tsx index 353fd77b13..ef9c647b54 100644 --- a/src/components/StarterPack/Wizard/WizardListCard.tsx +++ b/src/components/StarterPack/Wizard/WizardListCard.tsx @@ -1,10 +1,10 @@ import {Keyboard, View} from 'react-native' -import {type AppBskyActorDefs, type AppBskyFeedDefs} from '@atproto/api' import {type ModerationOpts, type ModerationUI} from '@bsky.app/sdk/moderation' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Trans} from '@lingui/react/macro' +import {app} from '#/lexicons' import {DISCOVER_FEED_URI, STARTER_PACK_MAX_SIZE} from '#/lib/constants' import {moderateFeedGenerator, moderateProfile} from '#/lib/moderation/subjects' import {sanitizeDisplayName} from '#/lib/strings/display-names' @@ -36,8 +36,8 @@ function WizardListCard({ }: { type: 'user' | 'algo' btnType: 'checkbox' | 'remove' - profile?: AppBskyActorDefs.ProfileViewBasic - feed?: AppBskyFeedDefs.GeneratorView + profile?: app.bsky.actor.defs.ProfileViewBasic + feed?: app.bsky.feed.defs.GeneratorView displayName: string subtitle: string onPress: () => void @@ -178,7 +178,7 @@ export function WizardFeedCard({ moderationOpts, }: { btnType: 'checkbox' | 'remove' - generator: AppBskyFeedDefs.GeneratorView + generator: app.bsky.feed.defs.GeneratorView state: WizardState dispatch: (action: WizardAction) => void moderationOpts: ModerationOpts diff --git a/src/components/TrendingTopics.tsx b/src/components/TrendingTopics.tsx index 56fe08ccc9..3a01a46649 100644 --- a/src/components/TrendingTopics.tsx +++ b/src/components/TrendingTopics.tsx @@ -1,7 +1,8 @@ import {useEffect, useMemo} from 'react' -import {type AppBskyUnspeccedDefs, type AtUri} from '@atproto/api' import {useLingui} from '@lingui/react/macro' +import {type AtUri} from '@atproto/syntax' +import {app} from '#/lexicons' import {PressableScale} from '#/lib/custom-animations/PressableScale' import {useCallOnce} from '#/lib/once' // import {makeProfileLink} from '#/lib/routes/links' @@ -18,7 +19,7 @@ export function TrendingTopicLink({ children, ...rest }: { - topic: AppBskyUnspeccedDefs.TrendView + topic: app.bsky.unspecced.defs.TrendView metricContext: Metrics['trendingTopic:seen']['context'] rank: number recId?: string @@ -75,7 +76,7 @@ type ParsedTrendingTopic = } export function useTopic( - raw: AppBskyUnspeccedDefs.TrendView, + raw: app.bsky.unspecced.defs.TrendView, ): ParsedTrendingTopic { const {t: l} = useLingui() return useMemo(() => { diff --git a/src/components/VideoPostCard.tsx b/src/components/VideoPostCard.tsx index bb79fa6a78..f675a20aa0 100644 --- a/src/components/VideoPostCard.tsx +++ b/src/components/VideoPostCard.tsx @@ -2,15 +2,10 @@ import {useMemo} from 'react' import {View} from 'react-native' import {Image} from 'expo-image' import {LinearGradient} from 'expo-linear-gradient' -import { - type AppBskyActorDefs, - AppBskyEmbedVideo, - type AppBskyFeedDefs, - AppBskyFeedPost, -} from '@atproto/api' import {type ModerationDecision} from '@bsky.app/sdk/moderation' import {useLingui} from '@lingui/react/macro' +import {app} from '#/lexicons' import {sanitizeHandle} from '#/lib/strings/handles' import {formatCount} from '#/view/com/util/numeric/format' import {UserAvatar} from '#/view/com/util/UserAvatar' @@ -42,7 +37,7 @@ export function VideoPostCard({ moderation, onInteract, }: { - post: AppBskyFeedDefs.PostView + post: app.bsky.feed.defs.PostView sourceContext: VideoFeedSourceContext moderation: ModerationDecision /** @@ -75,13 +70,10 @@ export function VideoPostCard({ * Filtering should be done at a higher level, such as `PostFeed` or * `PostFeedVideoGridRow`, but we need to protect here as well. */ - if (!AppBskyEmbedVideo.isView(embed)) return null + if (!bsky.isType(app.bsky.embed.video.view, embed)) return null const author = post.author - const text = bsky.dangerousIsType( - post.record, - AppBskyFeedPost.isRecord, - ) + const text = bsky.isType(app.bsky.feed.post, post.record) ? post.record?.text : '' const likeCount = post?.likeCount ?? 0 @@ -275,7 +267,7 @@ export function VideoPostCardPlaceholder() { export function VideoPostCardTextPlaceholder({ author, }: { - author?: AppBskyActorDefs.ProfileViewBasic + author?: app.bsky.actor.defs.ProfileViewBasic }) { const t = useTheme() @@ -355,7 +347,7 @@ export function CompactVideoPostCard({ moderation, onInteract, }: { - post: AppBskyFeedDefs.PostView + post: app.bsky.feed.defs.PostView sourceContext: VideoFeedSourceContext moderation: ModerationDecision /** @@ -386,7 +378,7 @@ export function CompactVideoPostCard({ * Filtering should be done at a higher level, such as `PostFeed` or * `PostFeedVideoGridRow`, but we need to protect here as well. */ - if (!AppBskyEmbedVideo.isView(embed)) return null + if (!bsky.isType(app.bsky.embed.video.view, embed)) return null const likeCount = post?.likeCount ?? 0 const showLikeCount = false diff --git a/src/components/WhoCanReply.tsx b/src/components/WhoCanReply.tsx index be7636ff4b..1e2aca2a84 100644 --- a/src/components/WhoCanReply.tsx +++ b/src/components/WhoCanReply.tsx @@ -6,16 +6,12 @@ import { View, type ViewStyle, } from 'react-native' -import { - type AppBskyFeedDefs, - AppBskyFeedPost, - type AppBskyGraphDefs, - AtUri, -} from '@atproto/api' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Trans} from '@lingui/react/macro' +import {AtUri} from '@atproto/syntax' +import {app} from '#/lexicons' import {HITSLOP_10} from '#/lib/constants' import {makeListLink, makeProfileLink} from '#/lib/routes/links' import { @@ -41,7 +37,7 @@ import {IS_NATIVE} from '#/env' import * as bsky from '#/types/bsky' interface WhoCanReplyProps { - post: AppBskyFeedDefs.PostView + post: app.bsky.feed.defs.PostView isThreadAuthor: boolean style?: StyleProp } @@ -58,10 +54,7 @@ export function WhoCanReply({post, isThreadAuthor, style}: WhoCanReplyProps) { * unexpectedly, we should check to make sure it's for sure the root URI. */ const rootUri = - bsky.dangerousIsType( - post.record, - AppBskyFeedPost.isRecord, - ) && post.record.reply?.root + bsky.isType(app.bsky.feed.post, post.record) && post.record.reply?.root ? post.record.reply.root.uri : post.uri const settings = useMemo(() => { @@ -209,7 +202,7 @@ function WhoCanReplyDialog({ embeddingDisabled, }: { control: Dialog.DialogControlProps - post: AppBskyFeedDefs.PostView + post: app.bsky.feed.defs.PostView settings: ThreadgateAllowUISetting[] embeddingDisabled: boolean }) { @@ -255,7 +248,7 @@ function Rules({ settings, embeddingDisabled, }: { - post: AppBskyFeedDefs.PostView + post: app.bsky.feed.defs.PostView settings: ThreadgateAllowUISetting[] embeddingDisabled: boolean }) { @@ -313,8 +306,8 @@ function Rule({ lists, }: { rule: ThreadgateAllowUISetting - post: AppBskyFeedDefs.PostView - lists: AppBskyGraphDefs.ListViewBasic[] | undefined + post: app.bsky.feed.defs.PostView + lists: app.bsky.graph.defs.ListViewBasic[] | undefined }) { if (rule.type === 'mention') { return mentioned users diff --git a/src/components/activity-notifications/SubscribeProfileDialog.tsx b/src/components/activity-notifications/SubscribeProfileDialog.tsx index 51d6622407..bdcf658e43 100644 --- a/src/components/activity-notifications/SubscribeProfileDialog.tsx +++ b/src/components/activity-notifications/SubscribeProfileDialog.tsx @@ -1,6 +1,5 @@ import {useMemo, useState} from 'react' import {View} from 'react-native' -import {type AppBskyNotificationDefs, type Un$Typed} from '@atproto/api' import {type DidString} from '@atproto/syntax' import {type ModerationOpts} from '@bsky.app/sdk/moderation' import {msg} from '@lingui/core/macro' @@ -12,6 +11,7 @@ import { useQueryClient, } from '@tanstack/react-query' +import {type Un$Typed} from '@atproto/lex' import {createSanitizedDisplayName} from '#/lib/moderation/create-sanitized-display-name' import {cleanError} from '#/lib/strings/errors' import {sanitizeHandle} from '#/lib/strings/handles' @@ -118,7 +118,7 @@ function DialogInner({ error, } = useMutation({ mutationFn: async ( - activitySubscription: Un$Typed, + activitySubscription: Un$Typed, ) => { await client.call(app.bsky.notification.putActivitySubscription, { // the profile view carries an already-resolved did @@ -307,8 +307,8 @@ function DialogInner({ } function parseActivitySubscription( - sub?: AppBskyNotificationDefs.ActivitySubscription, -): Un$Typed { + sub?: app.bsky.notification.defs.ActivitySubscription, +): Un$Typed { if (!sub) return {post: false, reply: false} const {post, reply} = sub return {post, reply} diff --git a/src/components/ageAssurance/AgeAssuranceAppealDialog.tsx b/src/components/ageAssurance/AgeAssuranceAppealDialog.tsx index 59df413324..db8b169bcc 100644 --- a/src/components/ageAssurance/AgeAssuranceAppealDialog.tsx +++ b/src/components/ageAssurance/AgeAssuranceAppealDialog.tsx @@ -1,6 +1,5 @@ import {useState} from 'react' import {View} from 'react-native' -import {ToolsOzoneReportDefs} from '@atproto/api' import {type DidString} from '@atproto/syntax' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' @@ -18,7 +17,7 @@ import * as Toast from '#/components/Toast' import {Text} from '#/components/Typography' import {logger} from '#/ageAssurance' import {useAnalytics} from '#/analytics' -import {com} from '#/lexicons' +import {com, tools} from '#/lexicons' export function AgeAssuranceAppealDialog({ control, @@ -60,7 +59,7 @@ function Inner({control}: {control: Dialog.DialogControlProps}) { await client.call( com.atproto.moderation.createReport, { - reasonType: ToolsOzoneReportDefs.REASONAPPEAL, + reasonType: tools.ozone.report.defs.reasonAppeal, subject: { $type: 'com.atproto.admin.defs#repoRef', // the persisted account did is already resolved diff --git a/src/components/contacts/contacts.ts b/src/components/contacts/contacts.ts index 205c2ccb49..4f4df359e0 100644 --- a/src/components/contacts/contacts.ts +++ b/src/components/contacts/contacts.ts @@ -1,5 +1,4 @@ -import {type AppBskyContactDefs} from '@atproto/api' - +import {app} from '#/lexicons' import {type CountryCode} from '#/lib/international-telephone-codes' import {normalizePhoneNumber} from './phone-number' import {type Contact, type Match} from './state' @@ -70,7 +69,7 @@ export function normalizeContactBook( export function filterMatchedNumbers( contacts: Contact[], - results: AppBskyContactDefs.MatchAndContactIndex[], + results: app.bsky.contact.defs.MatchAndContactIndex[], mapping: Map, ) { const filteredIds = new Set() @@ -87,7 +86,7 @@ export function filterMatchedNumbers( export function getMatchedContacts( contacts: Contact[], - results: AppBskyContactDefs.MatchAndContactIndex[], + results: app.bsky.contact.defs.MatchAndContactIndex[], mapping: Map, ): Array { const contactsById = new Map(contacts.map(c => [c.id, c])) diff --git a/src/components/dialogs/Embed.tsx b/src/components/dialogs/Embed.tsx index 105895ce3d..b958b0f0ae 100644 --- a/src/components/dialogs/Embed.tsx +++ b/src/components/dialogs/Embed.tsx @@ -1,10 +1,11 @@ import {memo, useEffect, useMemo, useState} from 'react' import {View} from 'react-native' -import {type AppBskyActorDefs, type AppBskyFeedPost, AtUri} from '@atproto/api' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Trans} from '@lingui/react/macro' +import {AtUri} from '@atproto/syntax' +import {app} from '#/lexicons' import {EMBED_SCRIPT} from '#/lib/constants' import {niceDate} from '#/lib/strings/time' import {toShareUrl} from '#/lib/strings/url-helpers' @@ -25,10 +26,10 @@ export type ColorModeValues = 'system' | 'light' | 'dark' type EmbedDialogProps = { control: Dialog.DialogControlProps - postAuthor: AppBskyActorDefs.ProfileViewBasic + postAuthor: app.bsky.actor.defs.ProfileViewBasic postCid: string postUri: string - record: AppBskyFeedPost.Record + record: app.bsky.feed.post.Main timestamp: string } diff --git a/src/components/dialogs/PostInteractionSettingsDialog.tsx b/src/components/dialogs/PostInteractionSettingsDialog.tsx index 63684f4831..70715ca122 100644 --- a/src/components/dialogs/PostInteractionSettingsDialog.tsx +++ b/src/components/dialogs/PostInteractionSettingsDialog.tsx @@ -1,6 +1,5 @@ import {useCallback, useMemo, useState} from 'react' import {LayoutAnimation, Text as NestedText, View} from 'react-native' -import {type AppBskyFeedDefs} from '@atproto/api' import {AtUri} from '@atproto/syntax' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' @@ -50,7 +49,7 @@ import * as Toast from '#/components/Toast' import {Text} from '#/components/Typography' import {useAnalytics} from '#/analytics' import {IS_IOS} from '#/env' -import {type app} from '#/lexicons' +import {app} from '#/lexicons' export type PostInteractionSettingsFormProps = { canSave?: boolean @@ -133,10 +132,10 @@ export type PostInteractionSettingsDialogProps = { */ rootPostUri: string /** - * Optional initial {@link AppBskyFeedDefs.ThreadgateView} to use if we + * Optional initial {@link app.bsky.feed.defs.ThreadgateView} to use if we * happen to have one before opening the settings dialog. */ - initialThreadgateView?: AppBskyFeedDefs.ThreadgateView + initialThreadgateView?: app.bsky.feed.defs.ThreadgateView } /** diff --git a/src/components/dialogs/StarterPackDialog.tsx b/src/components/dialogs/StarterPackDialog.tsx index ac1cb6aaef..e893e95cc4 100644 --- a/src/components/dialogs/StarterPackDialog.tsx +++ b/src/components/dialogs/StarterPackDialog.tsx @@ -1,14 +1,11 @@ import {useCallback} from 'react' import {View} from 'react-native' -import { - type AppBskyGraphGetStarterPacksWithMembership, - AppBskyGraphStarterpack, -} from '@atproto/api' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Plural, Trans} from '@lingui/react/macro' import {useNavigation} from '@react-navigation/native' +import {app} from '#/lexicons' import {useRequireEmailVerification} from '#/lib/hooks/useRequireEmailVerification' import {type NavigationProp} from '#/lib/routes/types' import {isNetworkError} from '#/lib/strings/errors' @@ -36,7 +33,7 @@ import {IS_WEB} from '#/env' import * as bsky from '#/types/bsky' type StarterPackWithMembership = - AppBskyGraphGetStarterPacksWithMembership.StarterPackWithMembership + app.bsky.graph.getStarterPacksWithMembership.StarterPackWithMembership export type StarterPackDialogProps = { control: Dialog.DialogControlProps @@ -324,12 +321,7 @@ function StarterPackItem({ const {record} = starterPack - if ( - !bsky.dangerousIsType( - record, - AppBskyGraphStarterpack.isRecord, - ) - ) { + if (!bsky.isType(app.bsky.graph.starterpack, record)) { return null } diff --git a/src/components/dialogs/lists/CreateListFromStarterPackDialog.tsx b/src/components/dialogs/lists/CreateListFromStarterPackDialog.tsx index e6d14b2405..b9979554cd 100644 --- a/src/components/dialogs/lists/CreateListFromStarterPackDialog.tsx +++ b/src/components/dialogs/lists/CreateListFromStarterPackDialog.tsx @@ -1,5 +1,4 @@ import {View} from 'react-native' -import {type AppBskyGraphDefs, type AppBskyGraphStarterpack} from '@atproto/api' import {TID} from '@atproto/common-web' import {type $Typed} from '@atproto/lex' import { @@ -37,7 +36,7 @@ export function CreateListFromStarterPackDialog({ starterPack, }: { control: Dialog.DialogControlProps - starterPack: AppBskyGraphDefs.StarterPackView + starterPack: app.bsky.graph.defs.StarterPackView }) { const {_} = useLingui() const t = useTheme() @@ -50,7 +49,7 @@ export function CreateListFromStarterPackDialog({ const createDialogControl = Dialog.useDialogControl() const loadingDialogControl = Dialog.useDialogControl() - const record = starterPack.record as AppBskyGraphStarterpack.Record + const record = starterPack.record as app.bsky.graph.starterpack.Main const onPressCreate = () => { control.close(() => createDialogControl.open()) diff --git a/src/components/dialogs/lists/CreateOrEditListDialog.tsx b/src/components/dialogs/lists/CreateOrEditListDialog.tsx index 1f3ec8b7c9..32e52fb18c 100644 --- a/src/components/dialogs/lists/CreateOrEditListDialog.tsx +++ b/src/components/dialogs/lists/CreateOrEditListDialog.tsx @@ -1,11 +1,11 @@ import {useCallback, useEffect, useMemo, useState} from 'react' import {View} from 'react-native' -import {type AppBskyGraphDefs} from '@atproto/api' import {RichText as RichTextAPI} from '@bsky.app/sdk/richtext' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Plural, Trans} from '@lingui/react/macro' +import {app} from '#/lexicons' import {cleanError} from '#/lib/strings/errors' import {isOverMaxGraphemeCount} from '#/lib/strings/helpers' import {asSdkFacets, richTextToString} from '#/lib/strings/rich-text-helpers' @@ -46,8 +46,8 @@ export function CreateOrEditListDialog({ initialValues, }: { control: Dialog.DialogControlProps - list?: AppBskyGraphDefs.ListView - purpose?: AppBskyGraphDefs.ListPurpose + list?: app.bsky.graph.defs.ListView + purpose?: app.bsky.graph.defs.ListPurpose onSave?: (uri: string) => void initialValues?: InitialListValues }) { @@ -114,8 +114,8 @@ function DialogInner({ onPressCancel, initialValues, }: { - list?: AppBskyGraphDefs.ListView - purpose?: AppBskyGraphDefs.ListPurpose + list?: app.bsky.graph.defs.ListView + purpose?: app.bsky.graph.defs.ListPurpose onSave?: (uri: string) => void setDirty: (dirty: boolean) => void onPressCancel: () => void diff --git a/src/components/dialogs/lists/ListAddRemoveUsersDialog.tsx b/src/components/dialogs/lists/ListAddRemoveUsersDialog.tsx index a8f04e2857..76c692e582 100644 --- a/src/components/dialogs/lists/ListAddRemoveUsersDialog.tsx +++ b/src/components/dialogs/lists/ListAddRemoveUsersDialog.tsx @@ -1,11 +1,11 @@ import {useCallback, useMemo} from 'react' import {View} from 'react-native' -import {type AppBskyGraphDefs} from '@atproto/api' import {type ModerationOpts} from '@bsky.app/sdk/moderation' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Trans} from '@lingui/react/macro' +import {app} from '#/lexicons' import {cleanError} from '#/lib/strings/errors' import {useModerationOpts} from '#/state/preferences/moderation-opts' import {useAllListMembersQuery} from '#/state/queries/list-members' @@ -31,7 +31,7 @@ export function ListAddRemoveUsersDialog({ onChange, }: { control: Dialog.DialogControlProps - list: AppBskyGraphDefs.ListView + list: app.bsky.graph.defs.ListView onChange?: ( type: 'add' | 'remove', profile: bsky.profile.AnyProfileView, @@ -52,7 +52,7 @@ function DialogInner({ list, onChange, }: { - list: AppBskyGraphDefs.ListView + list: app.bsky.graph.defs.ListView onChange?: ( type: 'add' | 'remove', profile: bsky.profile.AnyProfileView, @@ -89,7 +89,7 @@ function DialogInner({ * Returns undefined for pending, false for not a member, and string for a member (the URI of the membership record) */ function getMembership( - listMembers: AppBskyGraphDefs.ListItemView[] | undefined, + listMembers: app.bsky.graph.defs.ListItemView[] | undefined, actorDid: string, ): string | false | undefined { if (!listMembers) { @@ -107,8 +107,8 @@ function UserResult({ moderationOpts, }: { profile: bsky.profile.AnyProfileView - list: AppBskyGraphDefs.ListView - listMembers: AppBskyGraphDefs.ListItemView[] | undefined + list: app.bsky.graph.defs.ListView + listMembers: app.bsky.graph.defs.ListItemView[] | undefined onChange?: ( type: 'add' | 'remove', profile: bsky.profile.AnyProfileView, diff --git a/src/components/dialogs/nuxs/index.tsx b/src/components/dialogs/nuxs/index.tsx index 2fa8780d95..6c1533ac8b 100644 --- a/src/components/dialogs/nuxs/index.tsx +++ b/src/components/dialogs/nuxs/index.tsx @@ -6,8 +6,8 @@ import { useMemo, useState, } from 'react' -import {type AppBskyActorDefs} from '@atproto/api' +import {app} from '#/lexicons' import {logger} from '#/logger' import {STALE} from '#/state/queries' import {Nux, useNuxs, useResetNuxs, useSaveNux} from '#/state/queries/nuxs' @@ -93,7 +93,7 @@ function Inner({ preferences, }: { currentAccount: SessionAccount - currentProfile: AppBskyActorDefs.ProfileViewDetailed + currentProfile: app.bsky.actor.defs.ProfileViewDetailed preferences: UsePreferencesQueryResponse }) { const ax = useAnalytics() diff --git a/src/components/dialogs/nuxs/utils.ts b/src/components/dialogs/nuxs/utils.ts index 315908cc85..d8876dbb7b 100644 --- a/src/components/dialogs/nuxs/utils.ts +++ b/src/components/dialogs/nuxs/utils.ts @@ -1,5 +1,4 @@ -import {type AppBskyActorDefs} from '@atproto/api' - +import {app} from '#/lexicons' import {type UsePreferencesQueryResponse} from '#/state/queries/preferences' import {type SessionAccount} from '#/state/session' import {type AnalyticsContextType} from '#/analytics' @@ -8,7 +7,7 @@ import {type Geolocation} from '#/geolocation' export type EnabledCheckProps = { features: AnalyticsContextType['features'] currentAccount: SessionAccount - currentProfile: AppBskyActorDefs.ProfileViewDetailed + currentProfile: app.bsky.actor.defs.ProfileViewDetailed preferences: UsePreferencesQueryResponse geolocation: Geolocation } diff --git a/src/components/dms/ActionsWrapper.tsx b/src/components/dms/ActionsWrapper.tsx index b9782949b6..3a7b2a9fa8 100644 --- a/src/components/dms/ActionsWrapper.tsx +++ b/src/components/dms/ActionsWrapper.tsx @@ -1,8 +1,8 @@ import {View} from 'react-native' -import {type ChatBskyConvoDefs} from '@atproto/api' import {type ModerationOpts} from '@bsky.app/sdk/moderation' import {useLingui} from '@lingui/react/macro' +import {chat} from '#/lexicons' import {MessageContextMenu} from '#/components/dms/MessageContextMenu' import {useMessageReplies} from '#/components/dms/MessageReplies' import {SwipeToReply} from '#/components/dms/SwipeToReply' @@ -15,7 +15,7 @@ export function ActionsWrapper({ moderationOpts, children, }: { - message: ChatBskyConvoDefs.MessageView + message: chat.bsky.convo.defs.MessageView isFromSelf: boolean senderProfile?: bsky.profile.AnyProfileView moderationOpts: ModerationOpts | undefined diff --git a/src/components/dms/ActionsWrapper.web.tsx b/src/components/dms/ActionsWrapper.web.tsx index 0ef5503370..0771c490ed 100644 --- a/src/components/dms/ActionsWrapper.web.tsx +++ b/src/components/dms/ActionsWrapper.web.tsx @@ -1,10 +1,10 @@ import {useCallback, useRef, useState} from 'react' import {Pressable, View} from 'react-native' -import {type ChatBskyConvoDefs} from '@atproto/api' import {type ModerationOpts} from '@bsky.app/sdk/moderation' import {plural} from '@lingui/core/macro' import {useLingui} from '@lingui/react/macro' +import {chat} from '#/lexicons' import {EMOJI_REACTION_LIMIT} from '#/lib/constants' import {useMaybeProfileShadow} from '#/state/cache/profile-shadow' import {useConvoActive} from '#/state/messages/convo' @@ -29,7 +29,7 @@ export function ActionsWrapper({ moderationOpts, children, }: { - message: ChatBskyConvoDefs.MessageView + message: chat.bsky.convo.defs.MessageView isFromSelf: boolean senderProfile?: bsky.profile.AnyProfileView moderationOpts: ModerationOpts | undefined diff --git a/src/components/dms/AfterReportConversationDialog.tsx b/src/components/dms/AfterReportConversationDialog.tsx index 8e484156f4..541c13066e 100644 --- a/src/components/dms/AfterReportConversationDialog.tsx +++ b/src/components/dms/AfterReportConversationDialog.tsx @@ -1,9 +1,9 @@ import {memo, useState} from 'react' import {View} from 'react-native' -import {type AppBskyActorDefs} from '@atproto/api' import {Trans, useLingui} from '@lingui/react/macro' import {StackActions, useNavigation} from '@react-navigation/native' +import {app} from '#/lexicons' import {type NavigationProp} from '#/lib/routes/types' import {useProfileShadow} from '#/state/cache/profile-shadow' import {useLeaveConvo} from '#/state/queries/messages/leave-conversation' @@ -113,7 +113,7 @@ function DoneStep({ }: { convoId: string currentScreen: 'list' | 'conversation' - profile: AppBskyActorDefs.ProfileViewDetailed + profile: app.bsky.actor.defs.ProfileViewDetailed }) { const {t: l} = useLingui() const navigation = useNavigation() diff --git a/src/components/dms/AfterReportDialog.tsx b/src/components/dms/AfterReportDialog.tsx index 060ea1fcfb..0986599fc3 100644 --- a/src/components/dms/AfterReportDialog.tsx +++ b/src/components/dms/AfterReportDialog.tsx @@ -1,9 +1,9 @@ import {memo, useState} from 'react' import {View} from 'react-native' -import {type AppBskyActorDefs} from '@atproto/api' import {Trans, useLingui} from '@lingui/react/macro' import {StackActions, useNavigation} from '@react-navigation/native' +import {app} from '#/lexicons' import {type NavigationProp} from '#/lib/routes/types' import {useProfileShadow} from '#/state/cache/profile-shadow' import {useLeaveConvo} from '#/state/queries/messages/leave-conversation' @@ -116,7 +116,7 @@ function DoneStep({ }: { convoId: string currentScreen: 'list' | 'conversation' - profile: AppBskyActorDefs.ProfileViewDetailed + profile: app.bsky.actor.defs.ProfileViewDetailed }) { const {t: l} = useLingui() const navigation = useNavigation() diff --git a/src/components/dms/ChatInvite/Card.tsx b/src/components/dms/ChatInvite/Card.tsx index 92e0e96814..8d05972614 100644 --- a/src/components/dms/ChatInvite/Card.tsx +++ b/src/components/dms/ChatInvite/Card.tsx @@ -1,7 +1,8 @@ import {View} from 'react-native' -import {ChatBskyGroupDefs} from '@atproto/api' import {Plural, Trans} from '@lingui/react/macro' +import * as bsky from '#/types/bsky' +import {chat} from '#/lexicons' import {createSanitizedDisplayName} from '#/lib/moderation/create-sanitized-display-name' import {makeProfileLink} from '#/lib/routes/links' import {sanitizeHandle} from '#/lib/strings/handles' @@ -21,7 +22,8 @@ export function Card({size}: {size: 'large' | 'small'}) { const t = useTheme() const {preview, hasFixedHeight} = useChatInvite() - if (!ChatBskyGroupDefs.isJoinLinkPreviewView(preview)) return null + if (!bsky.isType(chat.bsky.group.defs.joinLinkPreviewView, preview)) + return null const ownerDisplayName = createSanitizedDisplayName(preview.owner) const ownerHandle = sanitizeHandle(preview.owner.handle, '@') diff --git a/src/components/dms/ChatInvite/Root.tsx b/src/components/dms/ChatInvite/Root.tsx index 16f5bdfae4..e1c491afd3 100644 --- a/src/components/dms/ChatInvite/Root.tsx +++ b/src/components/dms/ChatInvite/Root.tsx @@ -1,8 +1,9 @@ import {setStringAsync} from 'expo-clipboard' -import {ChatBskyGroupDefs} from '@atproto/api' import {useLingui} from '@lingui/react/macro' import {useNavigation} from '@react-navigation/native' +import * as bsky from '#/types/bsky' +import {chat} from '#/lexicons' import {type NavigationProp} from '#/lib/routes/types' import { type ChatInvitePreview, @@ -71,7 +72,7 @@ export function Root({ status = 'loading' } else if (error) { status = 'error' - } else if (ChatBskyGroupDefs.isJoinLinkPreviewView(preview)) { + } else if (bsky.isType(chat.bsky.group.defs.joinLinkPreviewView, preview)) { status = 'available' } else { // Resolved to a disabled/invalid/unrecognized preview - nothing to join. @@ -79,7 +80,7 @@ export function Root({ } let action: ChatInviteAction | undefined - if (ChatBskyGroupDefs.isJoinLinkPreviewView(preview)) { + if (bsky.isType(chat.bsky.group.defs.joinLinkPreviewView, preview)) { const convoId = preview.convo?.id const isFollowing = preview.owner.viewer?.followedBy ?? false const hasRequested = !convoId && preview.viewer?.requestedAt != null diff --git a/src/components/dms/EmojiReactionPicker.tsx b/src/components/dms/EmojiReactionPicker.tsx index de2b818b96..fa478602e5 100644 --- a/src/components/dms/EmojiReactionPicker.tsx +++ b/src/components/dms/EmojiReactionPicker.tsx @@ -1,9 +1,9 @@ import {useMemo, useState} from 'react' import {useWindowDimensions, View} from 'react-native' -import {type ChatBskyConvoDefs} from '@atproto/api' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' +import {chat} from '#/lexicons' import {useSession} from '#/state/session' import {atoms as a, tokens, useTheme} from '#/alf' import * as ContextMenu from '#/components/ContextMenu' @@ -21,7 +21,7 @@ export function EmojiReactionPicker({ message, onEmojiSelect, }: { - message: ChatBskyConvoDefs.MessageView + message: chat.bsky.convo.defs.MessageView children?: TriggerProps['children'] onEmojiSelect: (emoji: string) => void }) { diff --git a/src/components/dms/EmojiReactionPicker.web.tsx b/src/components/dms/EmojiReactionPicker.web.tsx index 8740330575..c53b786ab1 100644 --- a/src/components/dms/EmojiReactionPicker.web.tsx +++ b/src/components/dms/EmojiReactionPicker.web.tsx @@ -1,9 +1,9 @@ import {useState} from 'react' import {Pressable, View} from 'react-native' -import {type ChatBskyConvoDefs} from '@atproto/api' import {useLingui} from '@lingui/react/macro' import {DropdownMenu} from 'radix-ui' +import {chat} from '#/lexicons' import {useSession} from '#/state/session' import {atoms as a, flatten, useTheme} from '#/alf' import * as EmojiPicker from '#/components/EmojiPicker' @@ -17,7 +17,7 @@ export function EmojiReactionPicker({ children, onEmojiSelect, }: { - message: ChatBskyConvoDefs.MessageView + message: chat.bsky.convo.defs.MessageView children?: EmojiPicker.TriggerProps['children'] onEmojiSelect: (emoji: string) => void }) { @@ -40,7 +40,7 @@ function MenuInner({ message, onEmojiSelect, }: { - message: ChatBskyConvoDefs.MessageView + message: chat.bsky.convo.defs.MessageView onEmojiSelect: (emoji: string) => void }) { const t = useTheme() diff --git a/src/components/dms/MessageContextMenu.tsx b/src/components/dms/MessageContextMenu.tsx index 0bfa156eed..e080ed49e1 100644 --- a/src/components/dms/MessageContextMenu.tsx +++ b/src/components/dms/MessageContextMenu.tsx @@ -2,12 +2,12 @@ import {memo, useCallback} from 'react' import {Platform} from 'react-native' import {type GestureType} from 'react-native-gesture-handler' import * as Clipboard from 'expo-clipboard' -import {type ChatBskyConvoDefs} from '@atproto/api' import {type ModerationOpts} from '@bsky.app/sdk/moderation' import {RichText} from '@bsky.app/sdk/richtext' import {plural} from '@lingui/core/macro' import {useLingui} from '@lingui/react/macro' +import {chat} from '#/lexicons' import {EMOJI_REACTION_LIMIT} from '#/lib/constants' import {useGoogleTranslate} from '#/lib/hooks/useGoogleTranslate' import {asSdkFacets, richTextToString} from '#/lib/strings/rich-text-helpers' @@ -39,7 +39,7 @@ export let MessageContextMenu = ({ children, swipeGesture, }: { - message: ChatBskyConvoDefs.MessageView + message: chat.bsky.convo.defs.MessageView senderProfile?: bsky.profile.AnyProfileView moderationOpts: ModerationOpts | undefined children: TriggerProps['children'] diff --git a/src/components/dms/MessageItem.tsx b/src/components/dms/MessageItem.tsx index a835230db2..4c33d772b1 100644 --- a/src/components/dms/MessageItem.tsx +++ b/src/components/dms/MessageItem.tsx @@ -22,17 +22,13 @@ import Animated, { ZoomIn, ZoomOut, } from 'react-native-reanimated' -import { - AppBskyEmbedRecord, - type ChatBskyActorDefs, - ChatBskyConvoDefs, - ChatBskyEmbedJoinLink, -} from '@atproto/api' import {RichText as RichTextAPI} from '@bsky.app/sdk/richtext' import {plural} from '@lingui/core/macro' import {Trans, useLingui} from '@lingui/react/macro' import {useQueryClient} from '@tanstack/react-query' +import * as bsky from '#/types/bsky' +import {app, chat} from '#/lexicons' import {isBlockedOrBlocking} from '#/lib/moderation/blocked-and-muted' import {createSanitizedDisplayName} from '#/lib/moderation/create-sanitized-display-name' import {moderateProfile} from '#/lib/moderation/subjects' @@ -77,16 +73,19 @@ const SQUARED_BORDER_RADIUS = 4 const DISPLAY_NAME_INSET = 20 export type MessageItemNeighbor = - | ChatBskyConvoDefs.MessageView - | ChatBskyConvoDefs.DeletedMessageView + | chat.bsky.convo.defs.MessageView + | chat.bsky.convo.defs.DeletedMessageView | null function messageIsReply(message: MessageItemNeighbor): boolean { return ( - ChatBskyConvoDefs.isMessageView(message) && - (ChatBskyConvoDefs.isMessageView(message.replyTo) || - ChatBskyConvoDefs.isDeletedMessageView(message.replyTo) || - ChatBskyConvoDefs.isMessageBeforeUserJoinedGroupView(message.replyTo)) + bsky.isType(chat.bsky.convo.defs.messageView, message) && + (bsky.isType(chat.bsky.convo.defs.messageView, message.replyTo) || + bsky.isType(chat.bsky.convo.defs.deletedMessageView, message.replyTo) || + bsky.isType( + chat.bsky.convo.defs.messageBeforeUserJoinedGroupView, + message.replyTo, + )) ) } @@ -98,7 +97,7 @@ function isWithinClusterBoundary({ direction, }: { isPending: boolean - message: ChatBskyConvoDefs.MessageView + message: chat.bsky.convo.defs.MessageView adjacentMessage: MessageItemNeighbor isFromSameSender: boolean direction: 'prev' | 'next' @@ -110,7 +109,7 @@ function isWithinClusterBoundary({ return true } if (!isFromSameSender) return true - if (ChatBskyConvoDefs.isMessageView(adjacentMessage)) { + if (bsky.isType(chat.bsky.convo.defs.messageView, adjacentMessage)) { const currentSentAt = message.sentAt const thisDate = new Date(currentSentAt) const adjDate = new Date(adjacentMessage.sentAt) @@ -137,7 +136,7 @@ let MessageItem = ({ isGroupChat?: boolean prevMessage: MessageItemNeighbor nextMessage: MessageItemNeighbor - relatedProfiles: Map + relatedProfiles: Map }): React.ReactNode => { const t = useTheme() const {currentAccount} = useSession() @@ -155,13 +154,17 @@ let MessageItem = ({ // tombstone, or a before-joined placeholder. Narrow away the open-union // fallback so we only render shapes we understand. const replyTo = - ChatBskyConvoDefs.isMessageView(message.replyTo) || - ChatBskyConvoDefs.isDeletedMessageView(message.replyTo) || - ChatBskyConvoDefs.isMessageBeforeUserJoinedGroupView(message.replyTo) + bsky.isType(chat.bsky.convo.defs.messageView, message.replyTo) || + bsky.isType(chat.bsky.convo.defs.deletedMessageView, message.replyTo) || + bsky.isType( + chat.bsky.convo.defs.messageBeforeUserJoinedGroupView, + message.replyTo, + ) ? message.replyTo : undefined const replyToMessageId = - replyTo && !ChatBskyConvoDefs.isMessageBeforeUserJoinedGroupView(replyTo) + replyTo && + !bsky.isType(chat.bsky.convo.defs.messageBeforeUserJoinedGroupView, replyTo) ? replyTo.id : undefined const onPressReplyTo = replyToMessageId @@ -175,8 +178,14 @@ let MessageItem = ({ const isFromSelf = message.sender?.did != null && message.sender.did === currentAccount?.did - const prevIsMessage = ChatBskyConvoDefs.isMessageView(prevMessage) - const nextIsMessage = ChatBskyConvoDefs.isMessageView(nextMessage) + const prevIsMessage = bsky.isType( + chat.bsky.convo.defs.messageView, + prevMessage, + ) + const nextIsMessage = bsky.isType( + chat.bsky.convo.defs.messageView, + nextMessage, + ) const isPrevFromSameSender = prevIsMessage && @@ -204,7 +213,7 @@ let MessageItem = ({ }) const hasLargeGapFromPrev = - !ChatBskyConvoDefs.isMessageView(prevMessage) || + !bsky.isType(chat.bsky.convo.defs.messageView, prevMessage) || new Date(message.sentAt).getTime() - new Date(prevMessage.sentAt).getTime() > MESSAGE_GAP_THRESHOLD_MS @@ -254,8 +263,8 @@ let MessageItem = ({ const isEmojiOnly = isOnlyEmoji(message.text) const hasEmbed = - AppBskyEmbedRecord.isView(message.embed) || - ChatBskyEmbedJoinLink.isView(message.embed) + bsky.isType(app.bsky.embed.record.view, message.embed) || + bsky.isType(chat.bsky.embed.joinLink.view, message.embed) const hasEmbedAndText = hasEmbed && rt.text.length > 0 const targetBottomRadius = squaredBottomCorner @@ -516,7 +525,7 @@ let MessageItem = ({ message={message} senderProfile={profile} moderationOpts={moderationOpts}> - {AppBskyEmbedRecord.isView(message.embed) && ( + {bsky.isType(app.bsky.embed.record.view, message.embed) && ( )} - {ChatBskyEmbedJoinLink.isView(message.embed) && ( + {bsky.isType( + chat.bsky.embed.joinLink.view, + message.embed, + ) && ( + profile: Shadow style?: AnimatedStyle }) { const {t: l} = useLingui() @@ -776,13 +788,13 @@ function ReplyCaption({ onPress, }: { replyTo: - | ChatBskyConvoDefs.MessageView - | ChatBskyConvoDefs.DeletedMessageView - | ChatBskyConvoDefs.MessageBeforeUserJoinedGroupView + | chat.bsky.convo.defs.MessageView + | chat.bsky.convo.defs.DeletedMessageView + | chat.bsky.convo.defs.MessageBeforeUserJoinedGroupView isFromSelf: boolean isGroupChat: boolean replierDisplayName: string | null - relatedProfiles: Map + relatedProfiles: Map onPress?: () => void }) { const t = useTheme() @@ -791,8 +803,8 @@ function ReplyCaption({ let caption: string = '' if ( - ChatBskyConvoDefs.isMessageView(replyTo) || - ChatBskyConvoDefs.isDeletedMessageView(replyTo) + bsky.isType(chat.bsky.convo.defs.messageView, replyTo) || + bsky.isType(chat.bsky.convo.defs.deletedMessageView, replyTo) ) { const originalSenderIsSelf = replyTo.sender.did === currentAccount?.did const originalProfile = relatedProfiles.get(replyTo.sender.did) @@ -865,11 +877,11 @@ function ReplyQuote({ onPress, }: { replyTo: - | ChatBskyConvoDefs.MessageView - | ChatBskyConvoDefs.DeletedMessageView - | ChatBskyConvoDefs.MessageBeforeUserJoinedGroupView + | chat.bsky.convo.defs.MessageView + | chat.bsky.convo.defs.DeletedMessageView + | chat.bsky.convo.defs.MessageBeforeUserJoinedGroupView isFromSelf: boolean - relatedProfiles: Map + relatedProfiles: Map onPress?: () => void }) { const t = useTheme() @@ -877,8 +889,8 @@ function ReplyQuote({ const getReplyPreviewText = useReplyPreviewText() const senderDid = - ChatBskyConvoDefs.isMessageView(replyTo) || - ChatBskyConvoDefs.isDeletedMessageView(replyTo) + bsky.isType(chat.bsky.convo.defs.messageView, replyTo) || + bsky.isType(chat.bsky.convo.defs.deletedMessageView, replyTo) ? replyTo.sender.did : undefined const senderProfile = useMaybeProfileShadow( @@ -908,9 +920,11 @@ function ReplyQuote({ comment: 'A reply summary in chat', }) subtle = true - } else if (ChatBskyConvoDefs.isMessageView(replyTo)) { + } else if (bsky.isType(chat.bsky.convo.defs.messageView, replyTo)) { ;({text, subtle} = getReplyPreviewText(replyTo)) - } else if (ChatBskyConvoDefs.isMessageBeforeUserJoinedGroupView(replyTo)) { + } else if ( + bsky.isType(chat.bsky.convo.defs.messageBeforeUserJoinedGroupView, replyTo) + ) { text = l({ message: `(message sent before you joined)`, comment: 'A reply summary in chat', diff --git a/src/components/dms/MessageItemEmbed.tsx b/src/components/dms/MessageItemEmbed.tsx index 5014a9ff11..3e44e5d200 100644 --- a/src/components/dms/MessageItemEmbed.tsx +++ b/src/components/dms/MessageItemEmbed.tsx @@ -5,8 +5,9 @@ import Animated, { type SharedValue, useAnimatedStyle, } from 'react-native-reanimated' -import {type $Typed, type AppBskyEmbedRecord} from '@atproto/api' +import {type $Typed} from '@atproto/lex' +import {app} from '#/lexicons' import {atoms as a, native, useTheme, web} from '#/alf' import {Embed, PostEmbedViewContext} from '#/components/Post/Embed' import {MessageContextProvider} from './MessageContext' @@ -22,7 +23,7 @@ let MessageItemEmbed = ({ squaredBottomCorner, highlightSV, }: { - embed: $Typed + embed: $Typed isFromSelf: boolean isGroupChat: boolean squaredTopCorner: boolean diff --git a/src/components/dms/MessageItemInviteEmbed.tsx b/src/components/dms/MessageItemInviteEmbed.tsx index 5d6acd93d1..23e0379d43 100644 --- a/src/components/dms/MessageItemInviteEmbed.tsx +++ b/src/components/dms/MessageItemInviteEmbed.tsx @@ -5,8 +5,9 @@ import Animated, { type SharedValue, useAnimatedStyle, } from 'react-native-reanimated' -import {type $Typed, type ChatBskyEmbedJoinLink} from '@atproto/api' +import {type $Typed} from '@atproto/lex' +import {chat} from '#/lexicons' import {useConvoActive} from '#/state/messages/convo' import {isKnownJoinLinkPreview} from '#/state/queries/join-links' import {atoms as a, native, useTheme, web} from '#/alf' @@ -24,7 +25,7 @@ let MessageItemInviteEmbed = ({ squaredBottomCorner, highlightSV, }: { - embed: $Typed + embed: $Typed isFromSelf: boolean isGroupChat: boolean squaredTopCorner: boolean diff --git a/src/components/dms/MessageOverlays.tsx b/src/components/dms/MessageOverlays.tsx index 2384aad88d..3c0ad83a21 100644 --- a/src/components/dms/MessageOverlays.tsx +++ b/src/components/dms/MessageOverlays.tsx @@ -7,10 +7,10 @@ import { useState, } from 'react' import {LayoutAnimation} from 'react-native' -import {type ChatBskyConvoDefs} from '@atproto/api' import {useLingui} from '@lingui/react/macro' import {useQueryClient} from '@tanstack/react-query' +import {chat} from '#/lexicons' import {useConvoActive} from '#/state/messages/convo' import {unstableCacheProfileView} from '#/state/queries/unstable-profile-cache' import {useDialogControl} from '#/components/Dialog' @@ -23,12 +23,12 @@ import * as Toast from '#/components/Toast' import type * as bsky from '#/types/bsky' type MessageDialogsContextType = { - openDeleteMessage: (message: ChatBskyConvoDefs.MessageView) => void + openDeleteMessage: (message: chat.bsky.convo.defs.MessageView) => void openReportMessage: ( - message: ChatBskyConvoDefs.MessageView, + message: chat.bsky.convo.defs.MessageView, senderProfile: bsky.profile.AnyProfileView | undefined, ) => void - openReactions: (message: ChatBskyConvoDefs.MessageView) => void + openReactions: (message: chat.bsky.convo.defs.MessageView) => void } const Context = createContext(null) @@ -52,18 +52,18 @@ export function MessageOverlays({children}: {children: React.ReactNode}) { const reactionsControl = useDialogControl() const [deleteTarget, setDeleteTarget] = - useState(null) + useState(null) const [reportTarget, setReportTarget] = useState<{ - message: ChatBskyConvoDefs.MessageView + message: chat.bsky.convo.defs.MessageView senderProfile: bsky.profile.AnyProfileView | undefined } | null>(null) const [afterReportTarget, setAfterReportTarget] = - useState(null) + useState(null) const [reactionsTarget, setReactionsTarget] = - useState(null) + useState(null) const openDeleteMessage = useCallback( - (message: ChatBskyConvoDefs.MessageView) => { + (message: chat.bsky.convo.defs.MessageView) => { setDeleteTarget(message) deleteControl.open() }, @@ -72,7 +72,7 @@ export function MessageOverlays({children}: {children: React.ReactNode}) { const openReportMessage = useCallback( ( - message: ChatBskyConvoDefs.MessageView, + message: chat.bsky.convo.defs.MessageView, senderProfile: bsky.profile.AnyProfileView | undefined, ) => { setReportTarget({message, senderProfile}) @@ -82,7 +82,7 @@ export function MessageOverlays({children}: {children: React.ReactNode}) { ) const openReactions = useCallback( - (message: ChatBskyConvoDefs.MessageView) => { + (message: chat.bsky.convo.defs.MessageView) => { setReactionsTarget(message) }, [], diff --git a/src/components/dms/MessageProfileButton.tsx b/src/components/dms/MessageProfileButton.tsx index ede352218b..33087eee3d 100644 --- a/src/components/dms/MessageProfileButton.tsx +++ b/src/components/dms/MessageProfileButton.tsx @@ -1,11 +1,11 @@ import {useCallback} from 'react' import {View} from 'react-native' -import {type AppBskyActorDefs} from '@atproto/api' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Trans} from '@lingui/react/macro' import {useNavigation} from '@react-navigation/native' +import {app} from '#/lexicons' import {useRequireEmailVerification} from '#/lib/hooks/useRequireEmailVerification' import {type NavigationProp} from '#/lib/routes/types' import {useGetConvoAvailabilityQuery} from '#/state/queries/messages/get-convo-availability' @@ -20,7 +20,7 @@ import {useAnalytics} from '#/analytics' export function MessageProfileButton({ profile, }: { - profile: AppBskyActorDefs.ProfileViewDetailed + profile: app.bsky.actor.defs.ProfileViewDetailed }) { const {_} = useLingui() const t = useTheme() diff --git a/src/components/dms/MessageReplies.tsx b/src/components/dms/MessageReplies.tsx index 5093d8d157..391079fed0 100644 --- a/src/components/dms/MessageReplies.tsx +++ b/src/components/dms/MessageReplies.tsx @@ -1,3 +1,4 @@ +import {chat} from '#/lexicons' import { createContext, useCallback, @@ -7,7 +8,6 @@ import { useRef, useState, } from 'react' -import {type ChatBskyConvoDefs} from '@atproto/api' /** * How long a message stays highlighted after scrolling to it, before the flash @@ -28,8 +28,8 @@ type MessageRepliesContextType = { /** * The message currently staged for reply in the composer, or null. */ - replyTo: ChatBskyConvoDefs.MessageView | null - setReply: (message: ChatBskyConvoDefs.MessageView) => void + replyTo: chat.bsky.convo.defs.MessageView | null + setReply: (message: chat.bsky.convo.defs.MessageView) => void clearReply: () => void /** * Scroll the list to a message, if it's currently loaded, and flash it. No-op @@ -66,9 +66,8 @@ export function MessageRepliesProvider({ */ scrollToMessage: (messageId: string) => boolean }) { - const [replyTo, setReplyTo] = useState( - null, - ) + const [replyTo, setReplyTo] = + useState(null) const [highlightedMessage, setHighlightedMessage] = useState(null) const highlightKey = useRef(0) @@ -76,7 +75,7 @@ export function MessageRepliesProvider({ null, ) - const setReply = useCallback((message: ChatBskyConvoDefs.MessageView) => { + const setReply = useCallback((message: chat.bsky.convo.defs.MessageView) => { setReplyTo(message) }, []) diff --git a/src/components/dms/ReactionsDialog.tsx b/src/components/dms/ReactionsDialog.tsx index 3918143d37..2c244b73b2 100644 --- a/src/components/dms/ReactionsDialog.tsx +++ b/src/components/dms/ReactionsDialog.tsx @@ -6,9 +6,9 @@ import { useWindowDimensions, View, } from 'react-native' -import {type ChatBskyActorDefs, type ChatBskyConvoDefs} from '@atproto/api' import {Trans, useLingui} from '@lingui/react/macro' +import {chat} from '#/lexicons' import {HITSLOP_10} from '#/lib/constants' import {createSanitizedDisplayName} from '#/lib/moderation/create-sanitized-display-name' import {sanitizeHandle} from '#/lib/strings/handles' @@ -28,7 +28,7 @@ import type * as bsky from '#/types/bsky' type Reaction = { key: string value: string - senders: ChatBskyConvoDefs.ReactionViewSender[] + senders: chat.bsky.convo.defs.ReactionViewSender[] count: number } @@ -41,8 +41,8 @@ export function ReactionsDialog({ onClose, }: { control: Dialog.DialogControlProps - relatedProfiles: Map - message: ChatBskyConvoDefs.MessageView + relatedProfiles: Map + message: chat.bsky.convo.defs.MessageView onClose?: () => void }) { const {t: l} = useLingui() @@ -142,10 +142,10 @@ function ReactionRow({ control: Dialog.DialogControlProps convo: ActiveConvoStates currentAccount?: SessionAccount - message: ChatBskyConvoDefs.MessageView + message: chat.bsky.convo.defs.MessageView profile: bsky.profile.AnyProfileView - reaction: ChatBskyConvoDefs.ReactionView - allReactions: ChatBskyConvoDefs.ReactionView[] + reaction: chat.bsky.convo.defs.ReactionView + allReactions: chat.bsky.convo.defs.ReactionView[] selected: string setSelected: React.Dispatch> }) { @@ -398,7 +398,7 @@ function ReactionTab({ } export function groupReactions( - reactions: ChatBskyConvoDefs.ReactionView[] | undefined, + reactions: chat.bsky.convo.defs.ReactionView[] | undefined, ): Reaction[] { const grouped = new Map() for (const reaction of reactions ?? []) { diff --git a/src/components/dms/SystemMessageGroup.tsx b/src/components/dms/SystemMessageGroup.tsx index 930242ca46..a4a5b5f9fa 100644 --- a/src/components/dms/SystemMessageGroup.tsx +++ b/src/components/dms/SystemMessageGroup.tsx @@ -7,10 +7,10 @@ import Animated, { useDerivedValue, withTiming, } from 'react-native-reanimated' -import {type ChatBskyActorDefs} from '@atproto/api' import {plural} from '@lingui/core/macro' import {useLingui} from '@lingui/react/macro' +import {chat} from '#/lexicons' import {HITSLOP_10} from '#/lib/constants' import {type SystemMessageGroupItem} from '#/screens/Messages/components/groupSystemMessages' import {atoms as a, useTheme} from '#/alf' @@ -29,7 +29,7 @@ export function SystemMessageGroup({ item: SystemMessageGroupItem expanded: boolean onToggle: (key: string) => void - relatedProfiles: Map + relatedProfiles: Map }) { const t = useTheme() const {t: l} = useLingui() diff --git a/src/components/dms/SystemMessageItem.tsx b/src/components/dms/SystemMessageItem.tsx index 7de6a0cd91..3aad1517fb 100644 --- a/src/components/dms/SystemMessageItem.tsx +++ b/src/components/dms/SystemMessageItem.tsx @@ -1,7 +1,7 @@ import {View} from 'react-native' -import {type ChatBskyActorDefs} from '@atproto/api' import {useLingui} from '@lingui/react/macro' +import {chat} from '#/lexicons' import {makeProfileLink} from '#/lib/routes/links' import {type ConvoItem} from '#/state/messages/convo/types' import {useInviteLinkDialog} from '#/screens/Messages/components/InviteLinkDialogProvider' @@ -16,7 +16,7 @@ export function SystemMessageItem({ relatedProfiles, }: { item: ConvoItem & {type: 'system-message'} - relatedProfiles: Map + relatedProfiles: Map }) { const t = useTheme() const {i18n, t: l} = useLingui() diff --git a/src/components/dms/getMessageInfo.ts b/src/components/dms/getMessageInfo.ts index 5aaa3a8d7d..c41d1eebe8 100644 --- a/src/components/dms/getMessageInfo.ts +++ b/src/components/dms/getMessageInfo.ts @@ -1,12 +1,7 @@ -import { - AppBskyEmbedRecord, - type ChatBskyActorDefs, - ChatBskyConvoDefs, - ChatBskyEmbedJoinLink, -} from '@atproto/api' import {type I18n} from '@lingui/core' import {msg} from '@lingui/core/macro' +import {app, chat} from '#/lexicons' import {isBlockedOrBlocking} from '#/lib/moderation/blocked-and-muted' import {createSanitizedDisplayName} from '#/lib/moderation/create-sanitized-display-name' import { @@ -14,12 +9,12 @@ import { toBskyAppUrl, toShortUrl, } from '#/lib/strings/url-helpers' -import type * as bsky from '#/types/bsky' +import * as bsky from '#/types/bsky' export type UserMessageInfo = { message: string | null sentAt: string - reportableMessage?: ChatBskyConvoDefs.MessageView + reportableMessage?: chat.bsky.convo.defs.MessageView isBlockedMessage: boolean } @@ -36,7 +31,7 @@ export function isDidBlockedInConvo({ primaryProfile, }: { did: string | undefined - members: ChatBskyActorDefs.ProfileViewBasic[] + members: chat.bsky.actor.defs.ProfileViewBasic[] primaryProfile?: bsky.profile.AnyProfileView }): boolean { if (!did) return false @@ -53,12 +48,12 @@ export function getMessageInfo({ primaryProfile, i18n, }: { - convo: ChatBskyConvoDefs.ConvoView + convo: chat.bsky.convo.defs.ConvoView currentAccountDid: string | undefined primaryProfile?: bsky.profile.AnyProfileView i18n: I18n }): UserMessageInfo | null { - if (!ChatBskyConvoDefs.isMessageView(convo.lastMessage)) { + if (!bsky.isType(chat.bsky.convo.defs.messageView, convo.lastMessage)) { return null } @@ -67,7 +62,7 @@ export function getMessageInfo({ const senderDid = lastMessage.sender?.did const sender = convo.members.find(m => m.did === senderDid) const name = sender ? createSanitizedDisplayName(sender) : null - const isGroup = ChatBskyConvoDefs.isGroupConvo(convo.kind) + const isGroup = bsky.isType(chat.bsky.convo.defs.groupConvo, convo.kind) const reportableMessage = isFromMe ? undefined : lastMessage const isBlockedMessage = isDidBlockedInConvo({ @@ -105,10 +100,10 @@ export function getMessageInfo({ msg`(contains embedded content)`, ) - if (AppBskyEmbedRecord.isView(lastMessage.embed)) { + if (bsky.isType(app.bsky.embed.record.view, lastMessage.embed)) { const embed = lastMessage.embed - if (AppBskyEmbedRecord.isViewRecord(embed.record)) { + if (bsky.isType(app.bsky.embed.record.viewRecord, embed.record)) { const record = embed.record const path = postUriToRelativePath(record.uri, { handle: record.author.handle, @@ -119,7 +114,7 @@ export function getMessageInfo({ } else { message = prefix(defaultEmbeddedContentMessage) } - } else if (ChatBskyEmbedJoinLink.isView(lastMessage.embed)) { + } else if (bsky.isType(chat.bsky.embed.joinLink.view, lastMessage.embed)) { message = prefix(i18n._(msg`(chat invite link)`)) } else { message = prefix(defaultEmbeddedContentMessage) diff --git a/src/components/dms/getReactionInfo.ts b/src/components/dms/getReactionInfo.ts index 307eebdea7..2c8ddc6f71 100644 --- a/src/components/dms/getReactionInfo.ts +++ b/src/components/dms/getReactionInfo.ts @@ -1,10 +1,10 @@ -import {ChatBskyConvoDefs} from '@atproto/api' import {type I18n} from '@lingui/core' import {msg} from '@lingui/core/macro' +import {chat} from '#/lexicons' import {createSanitizedDisplayName} from '#/lib/moderation/create-sanitized-display-name' import {isDidBlockedInConvo} from '#/components/dms/getMessageInfo' -import type * as bsky from '#/types/bsky' +import * as bsky from '#/types/bsky' export type UserReactionInfo = { message: string @@ -18,12 +18,17 @@ export function getReactionInfo({ primaryProfile, i18n, }: { - convo: ChatBskyConvoDefs.ConvoView + convo: chat.bsky.convo.defs.ConvoView currentAccountDid: string | undefined primaryProfile?: bsky.profile.AnyProfileView i18n: I18n }): UserReactionInfo | null { - if (!ChatBskyConvoDefs.isMessageAndReactionView(convo.lastReaction)) { + if ( + !bsky.isType( + chat.bsky.convo.defs.messageAndReactionView, + convo.lastReaction, + ) + ) { return null } diff --git a/src/components/dms/getSystemMessageInfo.ts b/src/components/dms/getSystemMessageInfo.ts index 756f178566..8163cdf3b5 100644 --- a/src/components/dms/getSystemMessageInfo.ts +++ b/src/components/dms/getSystemMessageInfo.ts @@ -1,7 +1,8 @@ -import {type ChatBskyActorDefs, ChatBskyConvoDefs} from '@atproto/api' import {type MessageDescriptor} from '@lingui/core' import {msg} from '@lingui/core/macro' +import * as bsky from '#/types/bsky' +import {chat} from '#/lexicons' import {createSanitizedDisplayName} from '#/lib/moderation/create-sanitized-display-name' import {ArrowBoxLeft_Stroke2_Corner0_Rounded as LeaveIcon} from '#/components/icons/ArrowBoxLeft' import {ArrowBoxRight_Stroke2_Corner3_Rounded as JoinIcon} from '#/components/icons/ArrowBoxRight' @@ -19,7 +20,7 @@ import {PencilLine_Stroke2_Corner0_Rounded as PencilIcon} from '#/components/ico export type SystemMessageAction = | { kind: 'profile' - profile: ChatBskyActorDefs.ProfileViewBasic + profile: chat.bsky.actor.defs.ProfileViewBasic displayName: string } | {kind: 'inviteLink'} @@ -31,8 +32,8 @@ export type SystemMessageInfo = { } function getProfileAction( - user: ChatBskyConvoDefs.SystemMessageReferredUser, - relatedProfiles: Map, + user: chat.bsky.convo.defs.SystemMessageReferredUser, + relatedProfiles: Map, ): Extract | null { const profile = relatedProfiles.get(user.did) if (!profile) return null @@ -44,11 +45,11 @@ function getProfileAction( } export function getSystemMessageInfo( - data: ChatBskyConvoDefs.SystemMessageView['data'], - relatedProfiles: Map, + data: chat.bsky.convo.defs.SystemMessageView['data'], + relatedProfiles: Map, opts = {short: false}, ): SystemMessageInfo | null { - if (ChatBskyConvoDefs.isSystemMessageDataAddMember(data)) { + if (bsky.isType(chat.bsky.convo.defs.systemMessageDataAddMember, data)) { const action = getProfileAction(data.member, relatedProfiles) return { Icon: JoinIcon, @@ -61,7 +62,9 @@ export function getSystemMessageInfo( : msg`Someone was added to the group`, action: action ?? undefined, } - } else if (ChatBskyConvoDefs.isSystemMessageDataRemoveMember(data)) { + } else if ( + bsky.isType(chat.bsky.convo.defs.systemMessageDataRemoveMember, data) + ) { const action = getProfileAction(data.member, relatedProfiles) return { Icon: LeaveIcon, @@ -74,7 +77,9 @@ export function getSystemMessageInfo( : msg`Someone was removed from the group`, action: action ?? undefined, } - } else if (ChatBskyConvoDefs.isSystemMessageDataMemberJoin(data)) { + } else if ( + bsky.isType(chat.bsky.convo.defs.systemMessageDataMemberJoin, data) + ) { const action = getProfileAction(data.member, relatedProfiles) return { Icon: JoinIcon, @@ -87,7 +92,9 @@ export function getSystemMessageInfo( : msg`Someone joined the group`, action: action ?? undefined, } - } else if (ChatBskyConvoDefs.isSystemMessageDataMemberLeave(data)) { + } else if ( + bsky.isType(chat.bsky.convo.defs.systemMessageDataMemberLeave, data) + ) { const action = getProfileAction(data.member, relatedProfiles) return { Icon: LeaveIcon, @@ -100,13 +107,24 @@ export function getSystemMessageInfo( : msg`Someone left the group`, action: action ?? undefined, } - } else if (ChatBskyConvoDefs.isSystemMessageDataLockConvo(data)) { + } else if ( + bsky.isType(chat.bsky.convo.defs.systemMessageDataLockConvo, data) + ) { return {Icon: LockIcon, message: msg`Chat locked`} - } else if (ChatBskyConvoDefs.isSystemMessageDataUnlockConvo(data)) { + } else if ( + bsky.isType(chat.bsky.convo.defs.systemMessageDataUnlockConvo, data) + ) { return {Icon: UnlockIcon, message: msg`Chat unlocked`} - } else if (ChatBskyConvoDefs.isSystemMessageDataLockConvoPermanently(data)) { + } else if ( + bsky.isType( + chat.bsky.convo.defs.systemMessageDataLockConvoPermanently, + data, + ) + ) { return {Icon: LockIcon, message: msg`Chat ended`} - } else if (ChatBskyConvoDefs.isSystemMessageDataEditGroup(data)) { + } else if ( + bsky.isType(chat.bsky.convo.defs.systemMessageDataEditGroup, data) + ) { return { Icon: PencilIcon, message: @@ -114,25 +132,33 @@ export function getSystemMessageInfo( ? msg`Chat title changed to ${data.newName}` : msg`Chat title changed`, } - } else if (ChatBskyConvoDefs.isSystemMessageDataCreateJoinLink(data)) { + } else if ( + bsky.isType(chat.bsky.convo.defs.systemMessageDataCreateJoinLink, data) + ) { return { Icon: ChainLinkIcon, message: msg`Invite link created`, action: {kind: 'inviteLink'}, } - } else if (ChatBskyConvoDefs.isSystemMessageDataEditJoinLink(data)) { + } else if ( + bsky.isType(chat.bsky.convo.defs.systemMessageDataEditJoinLink, data) + ) { return { Icon: ChainLinkIcon, message: msg`Invite link edited`, action: {kind: 'inviteLink'}, } - } else if (ChatBskyConvoDefs.isSystemMessageDataEnableJoinLink(data)) { + } else if ( + bsky.isType(chat.bsky.convo.defs.systemMessageDataEnableJoinLink, data) + ) { return { Icon: ChainLinkIcon, message: msg`Invite link enabled`, action: {kind: 'inviteLink'}, } - } else if (ChatBskyConvoDefs.isSystemMessageDataDisableJoinLink(data)) { + } else if ( + bsky.isType(chat.bsky.convo.defs.systemMessageDataDisableJoinLink, data) + ) { return { Icon: ChainLinkBrokenIcon, message: msg`Invite link disabled`, diff --git a/src/components/dms/replyPreview.ts b/src/components/dms/replyPreview.ts index 53c78b2c46..753b611020 100644 --- a/src/components/dms/replyPreview.ts +++ b/src/components/dms/replyPreview.ts @@ -1,12 +1,7 @@ -import { - AppBskyEmbedExternal, - AppBskyEmbedRecord, - type ChatBskyConvoDefs, - ChatBskyEmbedJoinLink, - ChatBskyGroupDefs, -} from '@atproto/api' import {useLingui} from '@lingui/react/macro' +import * as bsky from '#/types/bsky' +import {app, chat} from '#/lexicons' import {BSKY_APP_HOST, toShortUrl} from '#/lib/strings/url-helpers' /** @@ -21,13 +16,13 @@ type ReplyEmbedSummary = | {type: 'unknown'} function summarizeReplyEmbed( - embed: ChatBskyConvoDefs.MessageView['embed'], + embed: chat.bsky.convo.defs.MessageView['embed'], ): ReplyEmbedSummary { - if (!AppBskyEmbedRecord.isView(embed)) return {type: 'unknown'} + if (!bsky.isType(app.bsky.embed.record.view, embed)) return {type: 'unknown'} const {record} = embed - if (AppBskyEmbedRecord.isViewRecord(record)) { + if (bsky.isType(app.bsky.embed.record.viewRecord, record)) { const inner = record.embeds?.[0] - if (AppBskyEmbedExternal.isView(inner)) { + if (bsky.isType(app.bsky.embed.external.view, inner)) { return {type: 'external', uri: inner.external.uri} } return {type: 'post'} @@ -45,25 +40,32 @@ function summarizeReplyEmbed( * callers can render it in a muted/italic style. */ export function useReplyPreviewText(): ( - message: ChatBskyConvoDefs.MessageView, + message: chat.bsky.convo.defs.MessageView, ) => {text: string; subtle: boolean} { const {t: l} = useLingui() - return (message: ChatBskyConvoDefs.MessageView) => { + return (message: chat.bsky.convo.defs.MessageView) => { const text = message.text if (text.trim()) { return {text, subtle: false} } - if (ChatBskyEmbedJoinLink.isView(message.embed)) { + if (bsky.isType(chat.bsky.embed.joinLink.view, message.embed)) { const {joinLinkPreview} = message.embed - if (ChatBskyGroupDefs.isJoinLinkPreviewView(joinLinkPreview)) { + if ( + bsky.isType(chat.bsky.group.defs.joinLinkPreviewView, joinLinkPreview) + ) { return { text: `${BSKY_APP_HOST}/chat/${joinLinkPreview.code}`, subtle: true, } } - if (ChatBskyGroupDefs.isDisabledJoinLinkPreviewView(joinLinkPreview)) { + if ( + bsky.isType( + chat.bsky.group.defs.disabledJoinLinkPreviewView, + joinLinkPreview, + ) + ) { return { text: l({ message: '(disabled chat invite link)', @@ -72,7 +74,12 @@ export function useReplyPreviewText(): ( subtle: true, } } - if (ChatBskyGroupDefs.isInvalidJoinLinkPreviewView(joinLinkPreview)) { + if ( + bsky.isType( + chat.bsky.group.defs.invalidJoinLinkPreviewView, + joinLinkPreview, + ) + ) { return { text: l({ message: '(invalid chat invite link)', diff --git a/src/components/dms/util.ts b/src/components/dms/util.ts index 7347d1512d..be2f821182 100644 --- a/src/components/dms/util.ts +++ b/src/components/dms/util.ts @@ -1,6 +1,7 @@ -import {type $Typed, ChatBskyActorDefs, ChatBskyConvoDefs} from '@atproto/api' import {type ModerationOpts} from '@bsky.app/sdk/moderation' +import {type $Typed} from '@atproto/lex' +import {chat} from '#/lexicons' import {EMOJI_REACTION_LIMIT} from '#/lib/constants' import {isBlockedOrBlocking} from '#/lib/moderation/blocked-and-muted' import {moderateProfile} from '#/lib/moderation/subjects' @@ -77,7 +78,7 @@ export function localDateString(date: Date) { } export function hasAlreadyReacted( - message: ChatBskyConvoDefs.MessageView, + message: chat.bsky.convo.defs.MessageView, myDid: string | undefined, emoji: string, ): boolean { @@ -98,9 +99,9 @@ export function hasAlreadyReacted( * already render anonymously ("Someone reacted"). */ export function filterBlockedReactions( - reactions: ChatBskyConvoDefs.ReactionView[] | undefined, - relatedProfiles: Map, -): ChatBskyConvoDefs.ReactionView[] { + reactions: chat.bsky.convo.defs.ReactionView[] | undefined, + relatedProfiles: Map, +): chat.bsky.convo.defs.ReactionView[] { if (!reactions) return [] return reactions.filter(reaction => { const profile = relatedProfiles.get(reaction.sender.did) @@ -109,7 +110,7 @@ export function filterBlockedReactions( } export function hasReachedReactionLimit( - message: ChatBskyConvoDefs.MessageView, + message: chat.bsky.convo.defs.MessageView, myDid: string | undefined, ): boolean { if (!message.reactions) { @@ -170,25 +171,25 @@ export function canReact({ return true } -export type GroupConvoMember = ChatBskyActorDefs.ProfileViewBasic & { +export type GroupConvoMember = chat.bsky.actor.defs.ProfileViewBasic & { // can be missing if account deleted - kind?: $Typed + kind?: $Typed } -export type DirectConvoMember = ChatBskyActorDefs.ProfileViewBasic & { - kind: $Typed +export type DirectConvoMember = chat.bsky.actor.defs.ProfileViewBasic & { + kind: $Typed } -export type ConvoWithDetails = {view: ChatBskyConvoDefs.ConvoView} & ( +export type ConvoWithDetails = {view: chat.bsky.convo.defs.ConvoView} & ( | { kind: 'group' - details: $Typed + details: $Typed primaryMember?: GroupConvoMember // the owner - may have left, thus optional members: Array } | { kind: 'direct' - details: $Typed + details: $Typed primaryMember: DirectConvoMember // the other user members: Array } @@ -199,24 +200,14 @@ export type ConvoWithDetails = {view: ChatBskyConvoDefs.ConvoView} & ( * and enforces the correct type for convo members. */ export function parseConvoView( - convoView: ChatBskyConvoDefs.ConvoView, + convoView: chat.bsky.convo.defs.ConvoView, ownDid: string | undefined, ): ConvoWithDetails | null { - if ( - bsky.dangerousIsType( - convoView.kind, - ChatBskyConvoDefs.isGroupConvo, - ) - ) { + if (bsky.isType(chat.bsky.convo.defs.groupConvo, convoView.kind)) { let owner: GroupConvoMember | undefined = undefined for (const member of convoView.members) { - if ( - bsky.dangerousIsType( - member.kind, - ChatBskyActorDefs.isGroupConvoMember, - ) - ) { + if (bsky.isType(chat.bsky.actor.defs.groupConvoMember, member.kind)) { if (member.kind.role === 'owner') { // have to do a type assertion here // this works: {...member, kind: member.kind} @@ -238,12 +229,7 @@ export function parseConvoView( primaryMember: owner, members: convoView.members as Array, } - } else if ( - bsky.dangerousIsType( - convoView.kind, - ChatBskyConvoDefs.isDirectConvo, - ) - ) { + } else if (bsky.isType(chat.bsky.convo.defs.directConvo, convoView.kind)) { const otherUser = convoView.members.find(m => m.did !== ownDid) if (!otherUser) { @@ -286,7 +272,7 @@ export function getConvoReportSubject( const lastMessage = convo.view.lastMessage const reportableMessage = - ChatBskyConvoDefs.isMessageView(lastMessage) && + bsky.isType(chat.bsky.convo.defs.messageView, lastMessage) && lastMessage.sender?.did !== ownDid ? lastMessage : null diff --git a/src/components/feeds/PostFeedVideoGridRow.tsx b/src/components/feeds/PostFeedVideoGridRow.tsx index 53bc99d2f0..252c4ce7e6 100644 --- a/src/components/feeds/PostFeedVideoGridRow.tsx +++ b/src/components/feeds/PostFeedVideoGridRow.tsx @@ -1,6 +1,7 @@ import {View} from 'react-native' -import {AppBskyEmbedVideo} from '@atproto/api' +import * as bsky from '#/types/bsky' +import {app} from '#/lexicons' import {type FeedPostSliceItem} from '#/state/queries/post-feed' import {type VideoFeedSourceContext} from '#/screens/VideoFeed/types' import {atoms as a, useGutters} from '#/alf' @@ -21,7 +22,7 @@ export function PostFeedVideoGridRow({ const ax = useAnalytics() const gutters = useGutters(['base', 'base', 0, 'base']) const posts = slices - .filter(slice => AppBskyEmbedVideo.isView(slice.post.embed)) + .filter(slice => bsky.isType(app.bsky.embed.video.view, slice.post.embed)) .map(slice => ({ post: slice.post, moderation: slice.moderation, diff --git a/src/components/images/AutoSizedImage.tsx b/src/components/images/AutoSizedImage.tsx index fdc7d1988a..d2484f1009 100644 --- a/src/components/images/AutoSizedImage.tsx +++ b/src/components/images/AutoSizedImage.tsx @@ -5,12 +5,12 @@ import Animated, { useAnimatedRef, } from 'react-native-reanimated' import {Image} from 'expo-image' -import {type AppBskyEmbedImages} from '@atproto/api' import {utils} from '@bsky.app/alf' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Trans} from '@lingui/react/macro' +import {app} from '#/lexicons' import {type Dimensions} from '#/lib/media/types' import {useLargeAltBadgeEnabled} from '#/state/preferences/large-alt-badge' import {atoms as a, useTheme, web} from '#/alf' @@ -71,7 +71,7 @@ export function AutoSizedImage({ onContainerRef, onDimsChange, }: { - image: AppBskyEmbedImages.ViewImage + image: app.bsky.embed.images.ViewImage crop?: 'none' | 'square' | 'constrained' onPress?: ( containerRef: AnimatedRef, diff --git a/src/components/images/Gallery/index.tsx b/src/components/images/Gallery/index.tsx index c87957503f..a0239441b0 100644 --- a/src/components/images/Gallery/index.tsx +++ b/src/components/images/Gallery/index.tsx @@ -14,11 +14,11 @@ import Animated, { useAnimatedRef, } from 'react-native-reanimated' import {Image} from 'expo-image' -import {type AppBskyEmbedImages} from '@atproto/api' import {utils} from '@bsky.app/alf' import {Trans, useLingui} from '@lingui/react/macro' import debounce from 'lodash.debounce' +import {app} from '#/lexicons' import {type Dimensions} from '#/lib/media/types' import {mergeRefs} from '#/lib/merge-refs' import {useA11y} from '#/state/a11y' @@ -46,7 +46,7 @@ export * from './const' export * from './maybeApplyGalleryOffsetStyles' interface GalleryProps { - images: AppBskyEmbedImages.ViewImage[] + images: app.bsky.embed.images.ViewImage[] onPress?: ( index: number, containerRefs: AnimatedRef[], @@ -404,7 +404,7 @@ function GalleryImage({ onPreviewPress, }: { contentHeight: number - image: AppBskyEmbedImages.ViewImage + image: app.bsky.embed.images.ViewImage index: number imageCount: number onWidthChange: (index: number, width: number) => void diff --git a/src/components/images/Gallery/maybeApplyGalleryOffsetStyles.ts b/src/components/images/Gallery/maybeApplyGalleryOffsetStyles.ts index 5989497c12..cb314eb71d 100644 --- a/src/components/images/Gallery/maybeApplyGalleryOffsetStyles.ts +++ b/src/components/images/Gallery/maybeApplyGalleryOffsetStyles.ts @@ -1,12 +1,6 @@ -import { - AppBskyEmbedGallery, - AppBskyEmbedImages, - AppBskyEmbedRecordWithMedia, - type AppBskyFeedDefs, - AppBskyFeedPost, -} from '@atproto/api' import {type ModerationCause, type ModerationUI} from '@bsky.app/sdk/moderation' +import {app} from '#/lexicons' import {unique} from '#/lib/moderation' import {type AppModerationCause} from '#/components/Pills' import {Features, features} from '#/analytics/features' @@ -22,17 +16,12 @@ export function maybeApplyGalleryOffsetStyles( modui, additionalCauses, }: { - post: AppBskyFeedDefs.PostView + post: app.bsky.feed.defs.PostView modui: ModerationUI additionalCauses?: ModerationCause[] | AppModerationCause[] }, ) { - if ( - !bsky.dangerousIsType( - post.record, - AppBskyFeedPost.isRecord, - ) - ) { + if (!bsky.isType(app.bsky.feed.post, post.record)) { return } @@ -47,24 +36,11 @@ export function maybeApplyGalleryOffsetStyles( * First check if we even have images */ const embed = post.record.embed - const isImageEmbed = - embed && - bsky.dangerousIsType( - embed, - AppBskyEmbedImages.isMain, - ) + const isImageEmbed = embed && bsky.isType(app.bsky.embed.images.main, embed) const isGalleryEmbed = - embed && - bsky.dangerousIsType( - embed, - AppBskyEmbedGallery.isMain, - ) + embed && bsky.isType(app.bsky.embed.gallery.main, embed) const isRecordWithMedia = - embed && - bsky.dangerousIsType( - embed, - AppBskyEmbedRecordWithMedia.isMain, - ) + embed && bsky.isType(app.bsky.embed.recordWithMedia.main, embed) let hasImages = false if (isImageEmbed) { if (!isPostGalleryEmbedEnabled) return @@ -78,23 +54,13 @@ export function maybeApplyGalleryOffsetStyles( hasImages = true } if (isRecordWithMedia) { - if ( - bsky.dangerousIsType( - embed.media, - AppBskyEmbedImages.isMain, - ) - ) { + if (bsky.isType(app.bsky.embed.images.main, embed.media)) { if (!isPostGalleryEmbedEnabled) return // one image, not a gallery if (embed.media.images.length === 1) return hasImages = true } - if ( - bsky.dangerousIsType( - embed.media, - AppBskyEmbedGallery.isMain, - ) - ) { + if (bsky.isType(app.bsky.embed.gallery.main, embed.media)) { // single (or empty) gallery - no offset needed if (embed.media.items.length <= 1) return hasImages = true diff --git a/src/components/images/ImageLayoutGrid.tsx b/src/components/images/ImageLayoutGrid.tsx index f69de63bd1..d7e4db3b6c 100644 --- a/src/components/images/ImageLayoutGrid.tsx +++ b/src/components/images/ImageLayoutGrid.tsx @@ -1,15 +1,15 @@ import {useRef} from 'react' import {type StyleProp, View, type ViewStyle} from 'react-native' import {type AnimatedRef, useAnimatedRef} from 'react-native-reanimated' -import {type AppBskyEmbedImages} from '@atproto/api' +import {app} from '#/lexicons' import {atoms as a, useBreakpoints} from '#/alf' import {type Dimensions} from '#/components/Lightbox/types' import {type PostEmbedViewContext} from '#/components/Post/Embed/types' import {GalleryItem} from './ImageLayoutGridItem' interface ImageLayoutGridProps { - images: AppBskyEmbedImages.ViewImage[] + images: app.bsky.embed.images.ViewImage[] onPress?: ( index: number, containerRefs: AnimatedRef[], @@ -45,7 +45,7 @@ export function ImageLayoutGrid({ } interface ImageLayoutGridInnerProps { - images: AppBskyEmbedImages.ViewImage[] + images: app.bsky.embed.images.ViewImage[] onPress?: ( index: number, containerRefs: AnimatedRef[], diff --git a/src/components/images/ImageLayoutGridItem.tsx b/src/components/images/ImageLayoutGridItem.tsx index 8a3202df37..caca2b060f 100644 --- a/src/components/images/ImageLayoutGridItem.tsx +++ b/src/components/images/ImageLayoutGridItem.tsx @@ -1,12 +1,12 @@ import {Pressable, type StyleProp, View, type ViewStyle} from 'react-native' import {type AnimatedRef} from 'react-native-reanimated' import {Image, type ImageStyle} from 'expo-image' -import {type AppBskyEmbedImages} from '@atproto/api' import {utils} from '@bsky.app/alf' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Trans} from '@lingui/react/macro' +import {app} from '#/lexicons' import {type Dimensions} from '#/lib/media/types' import {useLargeAltBadgeEnabled} from '#/state/preferences/large-alt-badge' import {atoms as a, tokens, useTheme} from '#/alf' @@ -18,7 +18,7 @@ import {Text} from '#/components/Typography' type EventFunction = (index: number) => void interface Props { - images: AppBskyEmbedImages.ViewImage[] + images: app.bsky.embed.images.ViewImage[] index: number onPress?: ( index: number, diff --git a/src/components/intents/GroupChatJoinDialog.tsx b/src/components/intents/GroupChatJoinDialog.tsx index b2ec975503..c8d5b34b33 100644 --- a/src/components/intents/GroupChatJoinDialog.tsx +++ b/src/components/intents/GroupChatJoinDialog.tsx @@ -1,10 +1,10 @@ import {useEffect} from 'react' import {View} from 'react-native' -import {ChatBskyGroupDefs} from '@atproto/api' import {Plural, Trans, useLingui} from '@lingui/react/macro' import {useNavigation} from '@react-navigation/native' import {useQueryClient} from '@tanstack/react-query' +import * as bsky from '#/types/bsky' import {createSanitizedDisplayName} from '#/lib/moderation/create-sanitized-display-name' import {moderateProfile} from '#/lib/moderation/subjects' import {useCallOnce} from '#/lib/once' @@ -163,7 +163,10 @@ function GroupChatJoinDialogContent({code}: {code?: string}) { errorMessage = l`The member limit has been reached.` const preview = data?.joinLinkPreviews[0] if ( - ChatBskyGroupDefs.isJoinLinkPreviewView(preview) && + bsky.isType( + chat.bsky.group.defs.joinLinkPreviewView, + preview, + ) && preview.convo?.id ) { ax.metric('groupchat:join:memberLimitReached', { @@ -254,7 +257,7 @@ function GroupChatJoinDialogContent({code}: {code?: string}) { const joinLinkPreview = data.joinLinkPreviews[0] - if (!ChatBskyGroupDefs.isJoinLinkPreviewView(joinLinkPreview)) { + if (!bsky.isType(chat.bsky.group.defs.joinLinkPreviewView, joinLinkPreview)) { return ( <> diff --git a/src/components/interstitials/FeedTrendingTopics.tsx b/src/components/interstitials/FeedTrendingTopics.tsx index a50b8652d3..965d47f45e 100644 --- a/src/components/interstitials/FeedTrendingTopics.tsx +++ b/src/components/interstitials/FeedTrendingTopics.tsx @@ -1,8 +1,8 @@ import {useMemo} from 'react' import {Pressable, View} from 'react-native' -import {type AppBskyUnspeccedDefs} from '@atproto/api' import {Plural, Trans, useLingui} from '@lingui/react/macro' +import {app} from '#/lexicons' import {moderateProfile} from '#/lib/moderation/subjects' import {useModerationOpts} from '#/state/preferences/moderation-opts' import { @@ -183,7 +183,7 @@ function TrendRow({ recId, onPress, }: ViewStyleProp & { - trend: AppBskyUnspeccedDefs.TrendView + trend: app.bsky.unspecced.defs.TrendView rank: number feedSliceIndex: number recId?: string @@ -291,7 +291,7 @@ function TrendingTopicRowSkeleton({rank}: {rank: number}) { } function useModerateTrendingActors( - actors: AppBskyUnspeccedDefs.TrendView['actors'], + actors: app.bsky.unspecced.defs.TrendView['actors'], ) { const moderationOpts = useModerationOpts() diff --git a/src/components/interstitials/TrendingVideos.tsx b/src/components/interstitials/TrendingVideos.tsx index d3047001a4..5089042333 100644 --- a/src/components/interstitials/TrendingVideos.tsx +++ b/src/components/interstitials/TrendingVideos.tsx @@ -1,9 +1,11 @@ import {useCallback, useEffect, useMemo} from 'react' import {ScrollView, View} from 'react-native' -import {AppBskyEmbedVideo, AtUri} from '@atproto/api' import {Trans, useLingui} from '@lingui/react/macro' import {useQueryClient} from '@tanstack/react-query' +import {AtUri} from '@atproto/syntax' +import * as bsky from '#/types/bsky' +import {app} from '#/lexicons' import {VIDEO_FEED_URI} from '#/lib/constants' import {makeCustomFeedLink} from '#/lib/routes/links' import {useTrendingSettingsApi} from '#/state/preferences/trending' @@ -153,7 +155,7 @@ function VideoCards({ .flatMap(page => page.slices) .map(slice => slice.items[0]) .filter(Boolean) - .filter(item => AppBskyEmbedVideo.isView(item.post.embed)) + .filter(item => bsky.isType(app.bsky.embed.video.view, item.post.embed)) .slice(0, 8) }, [data]) diff --git a/src/components/moderation/AppealForm.tsx b/src/components/moderation/AppealForm.tsx index 606e8162ec..0511825ea7 100644 --- a/src/components/moderation/AppealForm.tsx +++ b/src/components/moderation/AppealForm.tsx @@ -1,6 +1,5 @@ import {useState} from 'react' import {View} from 'react-native' -import {type ComAtprotoLabelDefs, ToolsOzoneReportDefs} from '@atproto/api' import {XrpcResponseError} from '@atproto/lex' import {type AtUriString, type DidString} from '@atproto/syntax' import {msg} from '@lingui/core/macro' @@ -23,14 +22,14 @@ import {Loader} from '#/components/Loader' import * as Toast from '#/components/Toast' import {Text} from '#/components/Typography' import {IS_ANDROID} from '#/env' -import {com} from '#/lexicons' +import {com, tools} from '#/lexicons' export function AppealForm({ label, control, onPressBack, }: { - label: ComAtprotoLabelDefs.Label + label: com.atproto.label.defs.Label control: Dialog.DialogOuterProps['control'] onPressBack: () => void }) { @@ -51,7 +50,7 @@ export function AppealForm({ await client.call( com.atproto.moderation.createReport, { - reasonType: ToolsOzoneReportDefs.REASONAPPEAL, + reasonType: tools.ozone.report.defs.reasonAppeal, /* * `useLabelSubject` derives one shape or the other from the label's * `cid`: an at-uri plus cid for a record, or the label's `uri` reused diff --git a/src/components/moderation/BlockDialog.tsx b/src/components/moderation/BlockDialog.tsx index d576e071d7..b49f6444c6 100644 --- a/src/components/moderation/BlockDialog.tsx +++ b/src/components/moderation/BlockDialog.tsx @@ -1,6 +1,5 @@ import {useState} from 'react' import {View} from 'react-native' -import {type ChatBskyConvoDefs} from '@atproto/api' import {Trans, useLingui} from '@lingui/react/macro' import {useQueryClient} from '@tanstack/react-query' @@ -27,7 +26,7 @@ import {Text} from '#/components/Typography' import {chat} from '#/lexicons' import {type AnyProfileView} from '#/types/bsky/profile' -type Item = ChatBskyConvoDefs.ConvoView +type Item = chat.bsky.convo.defs.ConvoView type BlockDialogProps = { control: DialogControlProps @@ -252,7 +251,7 @@ function MutualGroupChat({ onOptimisticallyRemoveConvo, onRestoreConvo, }: { - view: ChatBskyConvoDefs.ConvoView + view: chat.bsky.convo.defs.ConvoView profileDid: string currentConvoId?: string onOptimisticallyRemoveConvo: (convoId: string) => void diff --git a/src/components/moderation/LabelsOnMe.tsx b/src/components/moderation/LabelsOnMe.tsx index 85cb1e4a3a..91793f4386 100644 --- a/src/components/moderation/LabelsOnMe.tsx +++ b/src/components/moderation/LabelsOnMe.tsx @@ -1,9 +1,9 @@ import {type StyleProp, View, type ViewStyle} from 'react-native' -import {type ComAtprotoLabelDefs} from '@atproto/api' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Plural} from '@lingui/react/macro' +import {com} from '#/lexicons' import {filterUserFacingLabels} from '#/lib/moderation' import {useSession} from '#/state/session' import {atoms as a} from '#/alf' @@ -24,7 +24,7 @@ export function LabelsOnMe({ size, style, }: { - labels: ComAtprotoLabelDefs.Label[] | undefined + labels: com.atproto.label.defs.Label[] | undefined size?: ButtonSize style?: StyleProp }) { diff --git a/src/components/moderation/LabelsOnMeDialog.tsx b/src/components/moderation/LabelsOnMeDialog.tsx index 963e4b762a..e9ac1afb85 100644 --- a/src/components/moderation/LabelsOnMeDialog.tsx +++ b/src/components/moderation/LabelsOnMeDialog.tsx @@ -1,10 +1,10 @@ import {useMemo, useState} from 'react' import {View} from 'react-native' -import {type ComAtprotoLabelDefs} from '@atproto/api' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Trans} from '@lingui/react/macro' +import {com} from '#/lexicons' import {useGetTimeAgo} from '#/lib/hooks/useTimeAgo' import {useLabelInfo} from '#/lib/moderation/useLabelInfo' import {makeProfileLink} from '#/lib/routes/links' @@ -23,7 +23,7 @@ export {useDialogControl as useLabelsOnMeDialogControl} from '#/components/Dialo export interface LabelsOnMeDialogProps { control: Dialog.DialogOuterProps['control'] - labels: ComAtprotoLabelDefs.Label[] + labels: com.atproto.label.defs.Label[] /** * Whether the labels are being shown on the user's account or on a post. * With `content`, the list may include account-level labels, which get a @@ -47,7 +47,7 @@ function LabelsOnMeDialogInner(props: LabelsOnMeDialogProps) { const {_} = useLingui() const {currentAccount} = useSession() const [appealingLabel, setAppealingLabel] = useState< - ComAtprotoLabelDefs.Label | undefined + com.atproto.label.defs.Label | undefined >(undefined) const {labels} = props const isAccount = props.type === 'account' @@ -118,7 +118,7 @@ function Label({ control, onPressAppeal, }: { - label: ComAtprotoLabelDefs.Label + label: com.atproto.label.defs.Label isSelfLabel: boolean /** * Call out that the label applies to the whole account, for contexts that @@ -126,7 +126,7 @@ function Label({ */ showAccountCallout?: boolean control: Dialog.DialogOuterProps['control'] - onPressAppeal: (label: ComAtprotoLabelDefs.Label) => void + onPressAppeal: (label: com.atproto.label.defs.Label) => void }) { const t = useTheme() const {_} = useLingui() diff --git a/src/components/moderation/PostAlerts.tsx b/src/components/moderation/PostAlerts.tsx index 4aa3c92a6c..5a187f4011 100644 --- a/src/components/moderation/PostAlerts.tsx +++ b/src/components/moderation/PostAlerts.tsx @@ -1,5 +1,4 @@ import {type StyleProp, View, type ViewStyle} from 'react-native' -import {type AppBskyFeedDefs, type ComAtprotoLabelDefs} from '@atproto/api' import {type ModerationCause, type ModerationUI} from '@bsky.app/sdk/moderation' import {plural} from '@lingui/core/macro' import {useLingui} from '@lingui/react/macro' @@ -9,6 +8,7 @@ import { getModerationCauseKey, unique, } from '#/lib/moderation' +import {app, com} from '#/lexicons' import {useSession} from '#/state/session' import {atoms as a} from '#/alf' import { @@ -24,7 +24,7 @@ export function PostAlerts({ style, additionalCauses, }: { - post?: AppBskyFeedDefs.PostView + post?: app.bsky.feed.defs.PostView modui: ModerationUI /** * Expanded views (e.g. the thread anchor post) render larger pills and @@ -48,7 +48,7 @@ export function PostAlerts({ * author's only entry point to appeal labels on their content. */ const isOwnPost = !!post && post.author.did === currentAccount?.did - const allLabels: ComAtprotoLabelDefs.Label[] = + const allLabels: com.atproto.label.defs.Label[] = isOwnPost && view === 'expanded' ? [ ...(post.labels ?? []), @@ -134,7 +134,7 @@ function AdditionalLabels({ size, hasPrecedingPills, }: { - labels: ComAtprotoLabelDefs.Label[] + labels: com.atproto.label.defs.Label[] size?: Pills.CommonProps['size'] /** * The compact "+n" syntax only makes sense as a continuation of other diff --git a/src/components/moderation/PostHider.tsx b/src/components/moderation/PostHider.tsx index 54d4acf945..6941c085b1 100644 --- a/src/components/moderation/PostHider.tsx +++ b/src/components/moderation/PostHider.tsx @@ -7,13 +7,13 @@ import { View, type ViewStyle, } from 'react-native' -import {type AppBskyActorDefs} from '@atproto/api' import {type ModerationCause, type ModerationUI} from '@bsky.app/sdk/moderation' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Trans} from '@lingui/react/macro' import {useQueryClient} from '@tanstack/react-query' +import {app} from '#/lexicons' import {useModerationCauseDescription} from '#/lib/moderation/useModerationCauseDescription' import {addStyle} from '#/lib/styles' import {unstableCacheProfileView} from '#/state/queries/unstable-profile-cache' @@ -31,7 +31,7 @@ interface Props extends React.ComponentProps { iconSize: number iconStyles: StyleProp modui: ModerationUI - profile: AppBskyActorDefs.ProfileViewBasic + profile: app.bsky.actor.defs.ProfileViewBasic interpretFilterAsBlur?: boolean hiderStyle?: StyleProp } diff --git a/src/components/moderation/ReportDialog/const.ts b/src/components/moderation/ReportDialog/const.ts index 727b2f90e9..5707f62635 100644 --- a/src/components/moderation/ReportDialog/const.ts +++ b/src/components/moderation/ReportDialog/const.ts @@ -1,9 +1,5 @@ import {applicationId} from 'expo-application' -import { - ComAtprotoModerationDefs as RootReportDefs, - ToolsOzoneReportDefs as OzoneReportDefs, -} from '@atproto/api' - +import {com, tools} from '#/lexicons' import {type ParsedReportSubject} from '#/components/moderation/ReportDialog/types' import {IS_ANDROID, IS_IOS, IS_WEB} from '#/env' @@ -31,59 +27,96 @@ export const NEW_TO_OLD_REASON_MAPPING: Record = {} * @see https://github.com/bluesky-social/atproto/blob/4c15fb47cec26060bff2e710e95869a90c9d7fdd/packages/ozone/src/mod-service/profile.ts#L16-L64 */ export const NEW_TO_OLD_REASONS_MAP: Record< - OzoneReportDefs.ReasonType, - RootReportDefs.ReasonType + tools.ozone.report.defs.ReasonType, + com.atproto.moderation.defs.ReasonType > = { - [OzoneReportDefs.REASONAPPEAL]: RootReportDefs.REASONAPPEAL, - [OzoneReportDefs.REASONOTHER]: RootReportDefs.REASONOTHER, + [tools.ozone.report.defs.reasonAppeal]: + com.atproto.moderation.defs.reasonAppeal, + [tools.ozone.report.defs.reasonOther]: + com.atproto.moderation.defs.reasonOther, - [OzoneReportDefs.REASONVIOLENCEANIMAL]: RootReportDefs.REASONVIOLATION, - [OzoneReportDefs.REASONVIOLENCETHREATS]: RootReportDefs.REASONVIOLATION, - [OzoneReportDefs.REASONVIOLENCEGRAPHICCONTENT]: - RootReportDefs.REASONVIOLATION, - [OzoneReportDefs.REASONVIOLENCEGLORIFICATION]: RootReportDefs.REASONVIOLATION, - [OzoneReportDefs.REASONVIOLENCEEXTREMISTCONTENT]: - RootReportDefs.REASONVIOLATION, - [OzoneReportDefs.REASONVIOLENCETRAFFICKING]: RootReportDefs.REASONVIOLATION, - [OzoneReportDefs.REASONVIOLENCEOTHER]: RootReportDefs.REASONVIOLATION, + [tools.ozone.report.defs.reasonViolenceAnimal]: + com.atproto.moderation.defs.reasonViolation, + [tools.ozone.report.defs.reasonViolenceThreats]: + com.atproto.moderation.defs.reasonViolation, + [tools.ozone.report.defs.reasonViolenceGraphicContent]: + com.atproto.moderation.defs.reasonViolation, + [tools.ozone.report.defs.reasonViolenceGlorification]: + com.atproto.moderation.defs.reasonViolation, + [tools.ozone.report.defs.reasonViolenceExtremistContent]: + com.atproto.moderation.defs.reasonViolation, + [tools.ozone.report.defs.reasonViolenceTrafficking]: + com.atproto.moderation.defs.reasonViolation, + [tools.ozone.report.defs.reasonViolenceOther]: + com.atproto.moderation.defs.reasonViolation, - [OzoneReportDefs.REASONSEXUALABUSECONTENT]: RootReportDefs.REASONSEXUAL, - [OzoneReportDefs.REASONSEXUALNCII]: RootReportDefs.REASONSEXUAL, - [OzoneReportDefs.REASONSEXUALDEEPFAKE]: RootReportDefs.REASONSEXUAL, - [OzoneReportDefs.REASONSEXUALANIMAL]: RootReportDefs.REASONSEXUAL, - [OzoneReportDefs.REASONSEXUALUNLABELED]: RootReportDefs.REASONSEXUAL, - [OzoneReportDefs.REASONSEXUALOTHER]: RootReportDefs.REASONSEXUAL, + [tools.ozone.report.defs.reasonSexualAbuseContent]: + com.atproto.moderation.defs.reasonSexual, + [tools.ozone.report.defs.reasonSexualNCII]: + com.atproto.moderation.defs.reasonSexual, + [tools.ozone.report.defs.reasonSexualDeepfake]: + com.atproto.moderation.defs.reasonSexual, + [tools.ozone.report.defs.reasonSexualAnimal]: + com.atproto.moderation.defs.reasonSexual, + [tools.ozone.report.defs.reasonSexualUnlabeled]: + com.atproto.moderation.defs.reasonSexual, + [tools.ozone.report.defs.reasonSexualOther]: + com.atproto.moderation.defs.reasonSexual, - [OzoneReportDefs.REASONCHILDSAFETYCSAM]: RootReportDefs.REASONVIOLATION, - [OzoneReportDefs.REASONCHILDSAFETYGROOM]: RootReportDefs.REASONVIOLATION, - [OzoneReportDefs.REASONCHILDSAFETYPRIVACY]: RootReportDefs.REASONVIOLATION, - [OzoneReportDefs.REASONCHILDSAFETYHARASSMENT]: RootReportDefs.REASONVIOLATION, - [OzoneReportDefs.REASONCHILDSAFETYOTHER]: RootReportDefs.REASONVIOLATION, + [tools.ozone.report.defs.reasonChildSafetyCSAM]: + com.atproto.moderation.defs.reasonViolation, + [tools.ozone.report.defs.reasonChildSafetyGroom]: + com.atproto.moderation.defs.reasonViolation, + [tools.ozone.report.defs.reasonChildSafetyPrivacy]: + com.atproto.moderation.defs.reasonViolation, + [tools.ozone.report.defs.reasonChildSafetyHarassment]: + com.atproto.moderation.defs.reasonViolation, + [tools.ozone.report.defs.reasonChildSafetyOther]: + com.atproto.moderation.defs.reasonViolation, - [OzoneReportDefs.REASONHARASSMENTTROLL]: RootReportDefs.REASONRUDE, - [OzoneReportDefs.REASONHARASSMENTTARGETED]: RootReportDefs.REASONRUDE, - [OzoneReportDefs.REASONHARASSMENTHATESPEECH]: RootReportDefs.REASONRUDE, - [OzoneReportDefs.REASONHARASSMENTDOXXING]: RootReportDefs.REASONRUDE, - [OzoneReportDefs.REASONHARASSMENTOTHER]: RootReportDefs.REASONRUDE, + [tools.ozone.report.defs.reasonHarassmentTroll]: + com.atproto.moderation.defs.reasonRude, + [tools.ozone.report.defs.reasonHarassmentTargeted]: + com.atproto.moderation.defs.reasonRude, + [tools.ozone.report.defs.reasonHarassmentHateSpeech]: + com.atproto.moderation.defs.reasonRude, + [tools.ozone.report.defs.reasonHarassmentDoxxing]: + com.atproto.moderation.defs.reasonRude, + [tools.ozone.report.defs.reasonHarassmentOther]: + com.atproto.moderation.defs.reasonRude, - [OzoneReportDefs.REASONMISLEADINGBOT]: RootReportDefs.REASONMISLEADING, - [OzoneReportDefs.REASONMISLEADINGIMPERSONATION]: - RootReportDefs.REASONMISLEADING, - [OzoneReportDefs.REASONMISLEADINGSPAM]: RootReportDefs.REASONSPAM, - [OzoneReportDefs.REASONMISLEADINGSCAM]: RootReportDefs.REASONMISLEADING, - [OzoneReportDefs.REASONMISLEADINGELECTIONS]: RootReportDefs.REASONMISLEADING, - [OzoneReportDefs.REASONMISLEADINGOTHER]: RootReportDefs.REASONMISLEADING, + [tools.ozone.report.defs.reasonMisleadingBot]: + com.atproto.moderation.defs.reasonMisleading, + [tools.ozone.report.defs.reasonMisleadingImpersonation]: + com.atproto.moderation.defs.reasonMisleading, + [tools.ozone.report.defs.reasonMisleadingSpam]: + com.atproto.moderation.defs.reasonSpam, + [tools.ozone.report.defs.reasonMisleadingScam]: + com.atproto.moderation.defs.reasonMisleading, + [tools.ozone.report.defs.reasonMisleadingElections]: + com.atproto.moderation.defs.reasonMisleading, + [tools.ozone.report.defs.reasonMisleadingOther]: + com.atproto.moderation.defs.reasonMisleading, - [OzoneReportDefs.REASONRULESITESECURITY]: RootReportDefs.REASONVIOLATION, - [OzoneReportDefs.REASONRULEPROHIBITEDSALES]: RootReportDefs.REASONVIOLATION, - [OzoneReportDefs.REASONRULEBANEVASION]: RootReportDefs.REASONVIOLATION, - [OzoneReportDefs.REASONRULEOTHER]: RootReportDefs.REASONVIOLATION, + [tools.ozone.report.defs.reasonRuleSiteSecurity]: + com.atproto.moderation.defs.reasonViolation, + [tools.ozone.report.defs.reasonRuleProhibitedSales]: + com.atproto.moderation.defs.reasonViolation, + [tools.ozone.report.defs.reasonRuleBanEvasion]: + com.atproto.moderation.defs.reasonViolation, + [tools.ozone.report.defs.reasonRuleOther]: + com.atproto.moderation.defs.reasonViolation, - [OzoneReportDefs.REASONSELFHARMCONTENT]: RootReportDefs.REASONVIOLATION, - [OzoneReportDefs.REASONSELFHARMED]: RootReportDefs.REASONVIOLATION, - [OzoneReportDefs.REASONSELFHARMSTUNTS]: RootReportDefs.REASONVIOLATION, - [OzoneReportDefs.REASONSELFHARMSUBSTANCES]: RootReportDefs.REASONVIOLATION, - [OzoneReportDefs.REASONSELFHARMOTHER]: RootReportDefs.REASONVIOLATION, + [tools.ozone.report.defs.reasonSelfHarmContent]: + com.atproto.moderation.defs.reasonViolation, + [tools.ozone.report.defs.reasonSelfHarmED]: + com.atproto.moderation.defs.reasonViolation, + [tools.ozone.report.defs.reasonSelfHarmStunts]: + com.atproto.moderation.defs.reasonViolation, + [tools.ozone.report.defs.reasonSelfHarmSubstances]: + com.atproto.moderation.defs.reasonViolation, + [tools.ozone.report.defs.reasonSelfHarmOther]: + com.atproto.moderation.defs.reasonViolation, } /** @@ -91,42 +124,60 @@ export const NEW_TO_OLD_REASONS_MAP: Record< * @see https://github.com/bluesky-social/proposals/tree/main/0009-mod-report-granularity#backwards-compatibility */ export const OLD_TO_NEW_REASONS_MAP: Record< - Exclude, - OzoneReportDefs.ReasonType + Exclude< + com.atproto.moderation.defs.ReasonType, + tools.ozone.report.defs.ReasonType + >, + tools.ozone.report.defs.ReasonType > = { - [RootReportDefs.REASONSPAM]: [OzoneReportDefs.REASONMISLEADINGSPAM], - [RootReportDefs.REASONVIOLATION]: [OzoneReportDefs.REASONRULEOTHER], - [RootReportDefs.REASONMISLEADING]: [OzoneReportDefs.REASONMISLEADINGOTHER], - [RootReportDefs.REASONSEXUAL]: [OzoneReportDefs.REASONSEXUALUNLABELED], - [RootReportDefs.REASONRUDE]: [OzoneReportDefs.REASONHARASSMENTOTHER], - [RootReportDefs.REASONOTHER]: [OzoneReportDefs.REASONOTHER], - [RootReportDefs.REASONAPPEAL]: [OzoneReportDefs.REASONAPPEAL], + [com.atproto.moderation.defs.reasonSpam]: [ + tools.ozone.report.defs.reasonMisleadingSpam, + ], + [com.atproto.moderation.defs.reasonViolation]: [ + tools.ozone.report.defs.reasonRuleOther, + ], + [com.atproto.moderation.defs.reasonMisleading]: [ + tools.ozone.report.defs.reasonMisleadingOther, + ], + [com.atproto.moderation.defs.reasonSexual]: [ + tools.ozone.report.defs.reasonSexualUnlabeled, + ], + [com.atproto.moderation.defs.reasonRude]: [ + tools.ozone.report.defs.reasonHarassmentOther, + ], + [com.atproto.moderation.defs.reasonOther]: [ + tools.ozone.report.defs.reasonOther, + ], + [com.atproto.moderation.defs.reasonAppeal]: [ + tools.ozone.report.defs.reasonAppeal, + ], } /** * Set of report reasons that should optionally include additional details from * the reporter. */ -export const OTHER_REPORT_REASONS: Set = new Set([ - OzoneReportDefs.REASONVIOLENCEOTHER, - OzoneReportDefs.REASONSEXUALOTHER, - OzoneReportDefs.REASONCHILDSAFETYOTHER, - OzoneReportDefs.REASONHARASSMENTOTHER, - OzoneReportDefs.REASONMISLEADINGOTHER, - OzoneReportDefs.REASONRULEOTHER, - OzoneReportDefs.REASONSELFHARMOTHER, - OzoneReportDefs.REASONOTHER, -]) +export const OTHER_REPORT_REASONS: Set = + new Set([ + tools.ozone.report.defs.reasonViolenceOther, + tools.ozone.report.defs.reasonSexualOther, + tools.ozone.report.defs.reasonChildSafetyOther, + tools.ozone.report.defs.reasonHarassmentOther, + tools.ozone.report.defs.reasonMisleadingOther, + tools.ozone.report.defs.reasonRuleOther, + tools.ozone.report.defs.reasonSelfHarmOther, + tools.ozone.report.defs.reasonOther, + ]) /** * Set of report reasons that should only be sent to Bluesky's moderation service. */ -export const BSKY_LABELER_ONLY_REPORT_REASONS: Set = +export const BSKY_LABELER_ONLY_REPORT_REASONS: Set = new Set([ - OzoneReportDefs.REASONCHILDSAFETYCSAM, - OzoneReportDefs.REASONCHILDSAFETYGROOM, - OzoneReportDefs.REASONCHILDSAFETYOTHER, - OzoneReportDefs.REASONVIOLENCEEXTREMISTCONTENT, + tools.ozone.report.defs.reasonChildSafetyCSAM, + tools.ozone.report.defs.reasonChildSafetyGroom, + tools.ozone.report.defs.reasonChildSafetyOther, + tools.ozone.report.defs.reasonViolenceExtremistContent, ]) /** diff --git a/src/components/moderation/ReportDialog/errors.test.ts b/src/components/moderation/ReportDialog/errors.test.ts index 4a469c5eb2..bef4d2a38d 100644 --- a/src/components/moderation/ReportDialog/errors.test.ts +++ b/src/components/moderation/ReportDialog/errors.test.ts @@ -1,11 +1,24 @@ -import {XRPCError} from '@atproto/api' +import {XrpcResponseError} from '@atproto/lex' +import {com} from '#/lexicons' import {classifyReportError} from './errors' +/** + * An error as the lex client builds one from a JSON error response body. The + * classifier only reads `error`, `message` and `status` back off it. + */ +function xrpcError(status: number, error: string, message: string) { + return new XrpcResponseError( + com.atproto.moderation.createReport.main, + new Response(null, {status}), + {encoding: 'application/json', body: {error, message}}, + ) +} + describe('classifyReportError', () => { it('treats account takedown as an expected rejection', () => { const result = classifyReportError( - new XRPCError( + xrpcError( 403, 'AccountTakedown', 'Report not accepted from takendown account', @@ -27,7 +40,7 @@ describe('classifyReportError', () => { it.each([ { - error: new XRPCError( + error: xrpcError( 502, 'InternalServerError', 'Failed to perform upstream request', @@ -35,11 +48,11 @@ describe('classifyReportError', () => { bucket: 'upstream-fetch', }, { - error: new XRPCError(502, 'UpstreamFailure', 'Internal Server Error'), + error: xrpcError(502, 'UpstreamFailure', 'Internal Server Error'), bucket: 'upstream-internal', }, { - error: new XRPCError( + error: xrpcError( 502, 'UpstreamFailure', 'Upstream server responded with a 502 error', @@ -47,7 +60,7 @@ describe('classifyReportError', () => { bucket: 'upstream-http-502', }, { - error: new XRPCError( + error: xrpcError( 504, 'UpstreamTimeout', 'Upstream server responded with a 504 error', @@ -64,7 +77,7 @@ describe('classifyReportError', () => { it('classifies an invalid reason type separately', () => { const result = classifyReportError( - new XRPCError( + xrpcError( 400, 'InvalidRequest', 'Invalid reason type: tools.ozone.report.defs#reasonOther', @@ -82,7 +95,7 @@ describe('classifyReportError', () => { 'separates a non-retryable upstream %i without calling it temporary', status => { const result = classifyReportError( - new XRPCError( + xrpcError( 502, 'UpstreamFailure', `Upstream server responded with a ${status} error`, diff --git a/src/components/moderation/ReportDialog/errors.ts b/src/components/moderation/ReportDialog/errors.ts index 2dc71c8d23..2edb2bfc95 100644 --- a/src/components/moderation/ReportDialog/errors.ts +++ b/src/components/moderation/ReportDialog/errors.ts @@ -1,4 +1,4 @@ -import {XRPCError} from '@atproto/api' +import {XrpcResponseError} from '@atproto/lex' import {isRetryableHttpStatus, shouldRetryError} from '#/lib/strings/errors' @@ -16,7 +16,7 @@ export type ReportErrorClassification = { } export function classifyReportError(error: unknown): ReportErrorClassification { - if (!(error instanceof XRPCError)) { + if (!(error instanceof XrpcResponseError)) { return classification('unexpected', 'unexpected', true) } diff --git a/src/components/moderation/ReportDialog/state.test.ts b/src/components/moderation/ReportDialog/state.test.ts index 4129cdc9e5..ccea65f72d 100644 --- a/src/components/moderation/ReportDialog/state.test.ts +++ b/src/components/moderation/ReportDialog/state.test.ts @@ -1,6 +1,4 @@ -import {ToolsOzoneReportDefs as OzoneReportDefs} from '@atproto/api' - -import {type app} from '#/lexicons' +import {type app, tools} from '#/lexicons' import { getNciiQualificationOutcome, initialState, @@ -10,12 +8,12 @@ import { const nciiOption = { title: 'Non-consensual intimate imagery', - reason: OzoneReportDefs.REASONSEXUALNCII, + reason: tools.ozone.report.defs.reasonSexualNCII, } const otherOption = { title: 'Unlabeled adult content', - reason: OzoneReportDefs.REASONSEXUALUNLABELED, + reason: tools.ozone.report.defs.reasonSexualUnlabeled, } function selectNciiOption(state: ReportState = initialState) { diff --git a/src/components/moderation/ReportDialog/state.ts b/src/components/moderation/ReportDialog/state.ts index 2dc55a6638..feb5e01339 100644 --- a/src/components/moderation/ReportDialog/state.ts +++ b/src/components/moderation/ReportDialog/state.ts @@ -1,11 +1,9 @@ -import {ToolsOzoneReportDefs as OzoneReportDefs} from '@atproto/api' - import {OTHER_REPORT_REASONS} from '#/components/moderation/ReportDialog/const' import { type ReportCategoryConfig, type ReportOption, } from '#/components/moderation/ReportDialog/utils/useReportOptions' -import {type app} from '#/lexicons' +import {type app, tools} from '#/lexicons' export type NciiQualification = { isDepicted?: boolean @@ -125,7 +123,8 @@ export function reducer(state: ReportState, action: ReportAction): ReportState { includeVideoTimestamp: false, } case 'selectOption': { - const isNcii = action.option.reason === OzoneReportDefs.REASONSEXUALNCII + const isNcii = + action.option.reason === tools.ozone.report.defs.reasonSexualNCII return { ...state, selectedOption: action.option, diff --git a/src/components/moderation/ReportDialog/types.ts b/src/components/moderation/ReportDialog/types.ts index 57ed3cd279..bd9c0d247f 100644 --- a/src/components/moderation/ReportDialog/types.ts +++ b/src/components/moderation/ReportDialog/types.ts @@ -1,17 +1,11 @@ -import { - type $Typed, - type AppBskyActorDefs, - type AppBskyFeedDefs, - type AppBskyGraphDefs, - type ChatBskyConvoDefs, -} from '@atproto/api' - +import {type $Typed} from '@atproto/lex' +import {app, chat} from '#/lexicons' import type * as Dialog from '#/components/Dialog' export type ReportSubjectConvoMessage = { view: 'convo' | 'message' convoId: string - message: ChatBskyConvoDefs.MessageView + message: chat.bsky.convo.defs.MessageView } export type ReportSubjectConvo = { @@ -20,14 +14,14 @@ export type ReportSubjectConvo = { } export type ReportSubject = - | $Typed - | $Typed - | $Typed - | $Typed - | $Typed - | $Typed - | $Typed - | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed + | $Typed | ReportSubjectConvoMessage | ReportSubjectConvo diff --git a/src/components/moderation/ReportDialog/utils/parseReportSubject.ts b/src/components/moderation/ReportDialog/utils/parseReportSubject.ts index a7d4b94c32..8b03c7b02a 100644 --- a/src/components/moderation/ReportDialog/utils/parseReportSubject.ts +++ b/src/components/moderation/ReportDialog/utils/parseReportSubject.ts @@ -1,14 +1,8 @@ -import { - AppBskyActorDefs, - AppBskyFeedDefs, - AppBskyFeedPost, - AppBskyGraphDefs, -} from '@atproto/api' - import { type ParsedReportSubject, type ReportSubject, } from '#/components/moderation/ReportDialog/types' +import {app} from '#/lexicons' import * as bsky from '#/types/bsky' export function parseReportSubject( @@ -31,16 +25,16 @@ export function parseReportSubject( } if ( - AppBskyActorDefs.isProfileViewBasic(subject) || - AppBskyActorDefs.isProfileView(subject) || - AppBskyActorDefs.isProfileViewDetailed(subject) + bsky.isType(app.bsky.actor.defs.profileViewBasic, subject) || + bsky.isType(app.bsky.actor.defs.profileView, subject) || + bsky.isType(app.bsky.actor.defs.profileViewDetailed, subject) ) { return { type: 'account', did: subject.did, nsid: 'app.bsky.actor.profile', } - } else if (AppBskyActorDefs.isStatusView(subject)) { + } else if (bsky.isType(app.bsky.actor.defs.statusView, subject)) { if (!subject.uri || !subject.cid) return return { type: 'status', @@ -48,36 +42,31 @@ export function parseReportSubject( cid: subject.cid, nsid: 'app.bsky.actor.status', } - } else if (AppBskyGraphDefs.isListView(subject)) { + } else if (bsky.isType(app.bsky.graph.defs.listView, subject)) { return { type: 'list', uri: subject.uri, cid: subject.cid, nsid: 'app.bsky.graph.list', } - } else if (AppBskyFeedDefs.isGeneratorView(subject)) { + } else if (bsky.isType(app.bsky.feed.defs.generatorView, subject)) { return { type: 'feed', uri: subject.uri, cid: subject.cid, nsid: 'app.bsky.feed.generator', } - } else if (AppBskyGraphDefs.isStarterPackView(subject)) { + } else if (bsky.isType(app.bsky.graph.defs.starterPackView, subject)) { return { type: 'starterPack', uri: subject.uri, cid: subject.cid, nsid: 'app.bsky.graph.starterPack', } - } else if (AppBskyFeedDefs.isPostView(subject)) { + } else if (bsky.isType(app.bsky.feed.defs.postView, subject)) { const record = subject.record const embed = bsky.post.parseEmbed(subject.embed) - if ( - bsky.dangerousIsType( - record, - AppBskyFeedPost.isRecord, - ) - ) { + if (bsky.isType(app.bsky.feed.post, record)) { return { type: 'post', uri: subject.uri, diff --git a/src/components/moderation/ReportDialog/utils/useReportOptions.ts b/src/components/moderation/ReportDialog/utils/useReportOptions.ts index 87553ce6ed..581e8b7b52 100644 --- a/src/components/moderation/ReportDialog/utils/useReportOptions.ts +++ b/src/components/moderation/ReportDialog/utils/useReportOptions.ts @@ -1,7 +1,7 @@ import {useMemo} from 'react' -import {ToolsOzoneReportDefs as OzoneReportDefs} from '@atproto/api' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' +import {tools} from '#/lexicons' export type ReportCategory = | 'childSafety' @@ -22,7 +22,7 @@ export type ReportCategoryConfig = { export type ReportOption = { title: string - reason: OzoneReportDefs.ReasonType + reason: tools.ozone.report.defs.ReasonType } export function useReportOptions() { @@ -37,27 +37,27 @@ export function useReportOptions() { options: [ { title: _(msg`Spam`), - reason: OzoneReportDefs.REASONMISLEADINGSPAM, + reason: tools.ozone.report.defs.reasonMisleadingSpam, }, { title: _(msg`Scam`), - reason: OzoneReportDefs.REASONMISLEADINGSCAM, + reason: tools.ozone.report.defs.reasonMisleadingScam, }, { title: _(msg`Fake account or bot`), - reason: OzoneReportDefs.REASONMISLEADINGBOT, + reason: tools.ozone.report.defs.reasonMisleadingBot, }, { title: _(msg`Impersonation`), - reason: OzoneReportDefs.REASONMISLEADINGIMPERSONATION, + reason: tools.ozone.report.defs.reasonMisleadingImpersonation, }, { title: _(msg`False information about elections`), - reason: OzoneReportDefs.REASONMISLEADINGELECTIONS, + reason: tools.ozone.report.defs.reasonMisleadingElections, }, { title: _(msg`Other misleading content`), - reason: OzoneReportDefs.REASONMISLEADINGOTHER, + reason: tools.ozone.report.defs.reasonMisleadingOther, }, ], }, @@ -70,27 +70,27 @@ export function useReportOptions() { options: [ { title: _(msg`Unlabeled adult content`), - reason: OzoneReportDefs.REASONSEXUALUNLABELED, + reason: tools.ozone.report.defs.reasonSexualUnlabeled, }, { title: _(msg`Adult sexual abuse content`), - reason: OzoneReportDefs.REASONSEXUALABUSECONTENT, + reason: tools.ozone.report.defs.reasonSexualAbuseContent, }, { title: _(msg`Non-consensual intimate imagery`), - reason: OzoneReportDefs.REASONSEXUALNCII, + reason: tools.ozone.report.defs.reasonSexualNCII, }, { title: _(msg`Deepfake adult content`), - reason: OzoneReportDefs.REASONSEXUALDEEPFAKE, + reason: tools.ozone.report.defs.reasonSexualDeepfake, }, { title: _(msg`Animal sexual abuse`), - reason: OzoneReportDefs.REASONSEXUALANIMAL, + reason: tools.ozone.report.defs.reasonSexualAnimal, }, { title: _(msg`Other sexual violence content`), - reason: OzoneReportDefs.REASONSEXUALOTHER, + reason: tools.ozone.report.defs.reasonSexualOther, }, ], }, @@ -101,23 +101,23 @@ export function useReportOptions() { options: [ { title: _(msg`Trolling`), - reason: OzoneReportDefs.REASONHARASSMENTTROLL, + reason: tools.ozone.report.defs.reasonHarassmentTroll, }, { title: _(msg`Targeted harassment`), - reason: OzoneReportDefs.REASONHARASSMENTTARGETED, + reason: tools.ozone.report.defs.reasonHarassmentTargeted, }, { title: _(msg`Hate speech`), - reason: OzoneReportDefs.REASONHARASSMENTHATESPEECH, + reason: tools.ozone.report.defs.reasonHarassmentHateSpeech, }, { title: _(msg`Doxxing`), - reason: OzoneReportDefs.REASONHARASSMENTDOXXING, + reason: tools.ozone.report.defs.reasonHarassmentDoxxing, }, { title: _(msg`Other harassing or hateful content`), - reason: OzoneReportDefs.REASONHARASSMENTOTHER, + reason: tools.ozone.report.defs.reasonHarassmentOther, }, ], }, @@ -128,31 +128,31 @@ export function useReportOptions() { options: [ { title: _(msg`Animal welfare`), - reason: OzoneReportDefs.REASONVIOLENCEANIMAL, + reason: tools.ozone.report.defs.reasonViolenceAnimal, }, { title: _(msg`Threats or incitement`), - reason: OzoneReportDefs.REASONVIOLENCETHREATS, + reason: tools.ozone.report.defs.reasonViolenceThreats, }, { title: _(msg`Graphic violent content`), - reason: OzoneReportDefs.REASONVIOLENCEGRAPHICCONTENT, + reason: tools.ozone.report.defs.reasonViolenceGraphicContent, }, { title: _(msg`Glorification of violence`), - reason: OzoneReportDefs.REASONVIOLENCEGLORIFICATION, + reason: tools.ozone.report.defs.reasonViolenceGlorification, }, { title: _(msg`Extremist content`), - reason: OzoneReportDefs.REASONVIOLENCEEXTREMISTCONTENT, + reason: tools.ozone.report.defs.reasonViolenceExtremistContent, }, { title: _(msg`Human trafficking`), - reason: OzoneReportDefs.REASONVIOLENCETRAFFICKING, + reason: tools.ozone.report.defs.reasonViolenceTrafficking, }, { title: _(msg`Other violent content`), - reason: OzoneReportDefs.REASONVIOLENCEOTHER, + reason: tools.ozone.report.defs.reasonViolenceOther, }, ], }, @@ -163,23 +163,23 @@ export function useReportOptions() { options: [ { title: _(msg`Child Sexual Abuse Material (CSAM)`), - reason: OzoneReportDefs.REASONCHILDSAFETYCSAM, + reason: tools.ozone.report.defs.reasonChildSafetyCSAM, }, { title: _(msg`Grooming or predatory behavior`), - reason: OzoneReportDefs.REASONCHILDSAFETYGROOM, + reason: tools.ozone.report.defs.reasonChildSafetyGroom, }, { title: _(msg`Privacy violation of a minor`), - reason: OzoneReportDefs.REASONCHILDSAFETYPRIVACY, + reason: tools.ozone.report.defs.reasonChildSafetyPrivacy, }, { title: _(msg`Minor harassment or bullying`), - reason: OzoneReportDefs.REASONCHILDSAFETYHARASSMENT, + reason: tools.ozone.report.defs.reasonChildSafetyHarassment, }, { title: _(msg`Other child safety issue`), - reason: OzoneReportDefs.REASONCHILDSAFETYOTHER, + reason: tools.ozone.report.defs.reasonChildSafetyOther, }, ], }, @@ -190,23 +190,23 @@ export function useReportOptions() { options: [ { title: _(msg`Content promoting or depicting self-harm`), - reason: OzoneReportDefs.REASONSELFHARMCONTENT, + reason: tools.ozone.report.defs.reasonSelfHarmContent, }, { title: _(msg`Eating disorders`), - reason: OzoneReportDefs.REASONSELFHARMED, + reason: tools.ozone.report.defs.reasonSelfHarmED, }, { title: _(msg`Dangerous challenges or activities`), - reason: OzoneReportDefs.REASONSELFHARMSTUNTS, + reason: tools.ozone.report.defs.reasonSelfHarmStunts, }, { title: _(msg`Dangerous substances or drug abuse`), - reason: OzoneReportDefs.REASONSELFHARMSUBSTANCES, + reason: tools.ozone.report.defs.reasonSelfHarmSubstances, }, { title: _(msg`Other dangerous content`), - reason: OzoneReportDefs.REASONSELFHARMOTHER, + reason: tools.ozone.report.defs.reasonSelfHarmOther, }, ], }, @@ -217,19 +217,19 @@ export function useReportOptions() { options: [ { title: _(msg`Hacking or system attacks`), - reason: OzoneReportDefs.REASONRULESITESECURITY, + reason: tools.ozone.report.defs.reasonRuleSiteSecurity, }, { title: _(msg`Promoting or selling prohibited items or services`), - reason: OzoneReportDefs.REASONRULEPROHIBITEDSALES, + reason: tools.ozone.report.defs.reasonRuleProhibitedSales, }, { title: _(msg`Banned user returning`), - reason: OzoneReportDefs.REASONRULEBANEVASION, + reason: tools.ozone.report.defs.reasonRuleBanEvasion, }, { title: _(msg`Other network rule-breaking`), - reason: OzoneReportDefs.REASONRULEOTHER, + reason: tools.ozone.report.defs.reasonRuleOther, }, ], }, @@ -240,7 +240,7 @@ export function useReportOptions() { options: [ { title: _(msg`Other`), - reason: OzoneReportDefs.REASONOTHER, + reason: tools.ozone.report.defs.reasonOther, }, ], }, diff --git a/src/components/verification/VerificationRemovePrompt.tsx b/src/components/verification/VerificationRemovePrompt.tsx index 96b119ceb1..62307ccd82 100644 --- a/src/components/verification/VerificationRemovePrompt.tsx +++ b/src/components/verification/VerificationRemovePrompt.tsx @@ -1,8 +1,8 @@ import {useCallback} from 'react' -import {type AppBskyActorDefs} from '@atproto/api' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' +import {app} from '#/lexicons' import {logger} from '#/logger' import {useVerificationsRemoveMutation} from '#/state/queries/verification/useVerificationsRemoveMutation' import {type DialogControlProps} from '#/components/Dialog' @@ -20,7 +20,7 @@ export function VerificationRemovePrompt({ }: { control: DialogControlProps profile: bsky.profile.AnyProfileView - verifications: AppBskyActorDefs.VerificationView[] + verifications: app.bsky.actor.defs.VerificationView[] onConfirm?: () => void }) { const {_} = useLingui() diff --git a/src/components/verification/VerificationsDialog.tsx b/src/components/verification/VerificationsDialog.tsx index cb24b182a5..bcb46bd919 100644 --- a/src/components/verification/VerificationsDialog.tsx +++ b/src/components/verification/VerificationsDialog.tsx @@ -1,9 +1,9 @@ import {View} from 'react-native' -import {type AppBskyActorDefs} from '@atproto/api' import {msg} from '@lingui/core/macro' import {useLingui} from '@lingui/react' import {Trans} from '@lingui/react/macro' +import {app} from '#/lexicons' import {urls} from '#/lib/constants' import {getUserDisplayName} from '#/lib/getUserDisplayName' import {useModerationOpts} from '#/state/preferences/moderation-opts' @@ -180,7 +180,7 @@ function VerifierCard({ subject, outerDialogControl, }: { - verification: AppBskyActorDefs.VerificationView + verification: app.bsky.actor.defs.VerificationView subject: bsky.profile.AnyProfileView outerDialogControl: Dialog.DialogControlProps }) {