flip the component type imports to the generated lexicons

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Samuel Newman
2026-08-04 04:20:42 +03:00
parent dd957dd123
commit e056c43116
109 changed files with 716 additions and 741 deletions
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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
+6 -5
View File
@@ -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<ButtonProps>) {
@@ -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<ButtonProps>) {
@@ -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
+2 -2
View File
@@ -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
+6 -4
View File
@@ -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<Map<string, AppBskyActorDefs.KnownFollowers>>(new Map())
const cache = useRef<Map<string, app.bsky.actor.defs.KnownFollowers>>(
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
+9 -3
View File
@@ -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 (
<ProfileCardWithFollowBtn
key={item.actor.did}
@@ -22,7 +28,7 @@ function renderItem({item, index}: {item: GetLikes.Like; index: number}) {
)
}
function keyExtractor(item: GetLikes.Like) {
function keyExtractor(item: app.bsky.feed.getLikes.Like) {
return item.actor.did
}
+5 -4
View File
@@ -1,12 +1,13 @@
import {useEffect, useMemo} from 'react'
import {View} from 'react-native'
import {type AppBskyGraphDefs, AtUri} from '@atproto/api'
import {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 {AtUri} from '@atproto/syntax'
import {app} from '#/lexicons'
import {moderateUserList} from '#/lib/moderation/subjects'
import {sanitizeHandle} from '#/lib/strings/handles'
import {useModerationOpts} from '#/state/preferences/moderation-opts'
@@ -44,7 +45,7 @@ const CURATELIST = 'app.bsky.graph.defs#curatelist'
const MODLIST = 'app.bsky.graph.defs#modlist'
type Props = {
view: AppBskyGraphDefs.ListView
view: app.bsky.graph.defs.ListView
showPinButton?: boolean
}
@@ -108,7 +109,7 @@ export function TitleAndByline({
}: {
title: string
creator?: bsky.profile.AnyProfileView
purpose?: AppBskyGraphDefs.ListView['purpose']
purpose?: app.bsky.graph.defs.ListView['purpose']
modUi?: ModerationUI
}) {
const t = useTheme()
@@ -157,7 +158,7 @@ export function TitleAndByline({
export function createProfileListHref({
list,
}: {
list: AppBskyGraphDefs.ListView
list: app.bsky.graph.defs.ListView
}) {
const urip = new AtUri(list.uri)
const handleOrDid = list.creator.handle || list.creator.did
+5 -9
View File
@@ -1,12 +1,8 @@
import {type StyleProp, StyleSheet, View, type ViewStyle} from 'react-native'
import {Image} from 'expo-image'
import {
AppBskyEmbedGallery,
type AppBskyEmbedImages,
type AppBskyFeedDefs,
} from '@atproto/api'
import {Trans, useLingui} from '@lingui/react/macro'
import {app} from '#/lexicons'
import {shareImageModal} from '#/lib/media/manip'
import {useSaveImageToMediaLibrary} from '#/lib/media/save-image'
import {isGifEmbed} from '#/lib/strings/embed-player'
@@ -27,7 +23,7 @@ export function Embed({
style,
peekable = false,
}: {
embed: AppBskyFeedDefs.PostView['embed']
embed: app.bsky.feed.defs.PostView['embed']
style?: StyleProp<ViewStyle>
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()
+3 -3
View File
@@ -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
}) {
@@ -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<ViewStyle>
}) {
@@ -34,7 +34,7 @@ function ChatInviteEmbedBody({
onOpen,
style,
}: {
link: AppBskyEmbedExternal.ViewExternal
link: app.bsky.embed.external.ViewExternal
onOpen?: () => void
style?: StyleProp<ViewStyle>
}) {
@@ -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()
@@ -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()
@@ -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<ViewStyle>
hideAlt?: boolean
+11 -8
View File
@@ -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'
@@ -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 {
@@ -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()
@@ -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'
@@ -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))
}
@@ -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 = {
@@ -1,10 +1,9 @@
import {type AppBskyEmbedExternal} from '@atproto/api'
import {isStandardSiteEmbed, isStandardSitePublicationEmbed} from './utils'
import {app} from '#/lexicons'
function makeView(
partial: Record<string, unknown>,
): AppBskyEmbedExternal.ViewExternal {
): app.bsky.embed.external.ViewExternal {
return {
uri: 'https://example.com/post',
title: 'title',
@@ -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(
@@ -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
@@ -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
@@ -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) {
@@ -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<HTMLDivElement>(null)
const {
@@ -297,7 +297,7 @@ function VideoError({
error,
retry,
}: {
embed: AppBskyEmbedVideo.View
embed: app.bsky.embed.video.View
error: unknown
retry: () => void
}) {
+5 -14
View File
@@ -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<AppBskyFeedDefs.PostView>>(
const quote = useMemo<$Typed<app.bsky.feed.defs.PostView>>(
() => ({
...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<AppBskyFeedPost.Record>(
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)})
+3 -3
View File
@@ -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']
}
+4 -7
View File
@@ -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<TextStyle>
}) {
const langPrefs = useLanguagePrefs()
@@ -46,11 +46,8 @@ export function TranslatedPost({
key: post.uri,
})
const record = useMemo<AppBskyFeedPost.Record | undefined>(() => {
return bsky.dangerousIsType<AppBskyFeedPost.Record>(
post.record,
AppBskyFeedPost.isRecord,
)
const record = useMemo<app.bsky.feed.post.Main | undefined>(() => {
return bsky.isType(app.bsky.feed.post, post.record)
? post.record
: undefined
}, [post])
@@ -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<AppBskyFeedDefs.PostView>
post: Shadow<app.bsky.feed.defs.PostView>
big?: boolean
logContext: 'FeedItem' | 'PostThreadItem' | 'Post' | 'ImmersiveVideo'
hitSlop?: Insets
@@ -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<AppBskyFeedDefs.PostView>
post: Shadow<app.bsky.feed.defs.PostView>
postFeedContext: string | undefined
postReqId: string | undefined
record: AppBskyFeedPost.Record
record: app.bsky.feed.post.Main
richText: RichTextAPI
style?: StyleProp<ViewStyle>
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 => {
@@ -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<AppBskyFeedDefs.PostView>
post: Shadow<app.bsky.feed.defs.PostView>
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
@@ -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()
@@ -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'
@@ -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<AppBskyFeedDefs.PostView>
record: AppBskyFeedPost.Record
post: Shadow<app.bsky.feed.defs.PostView>
record: app.bsky.feed.post.Main
richText: RichTextAPI
style?: StyleProp<ViewStyle>
hitSlop?: PressableProps['hitSlop']
size?: 'lg' | 'md' | 'sm'
timestamp: string
threadgateRecord?: AppBskyFeedThreadgate.Record
threadgateRecord?: app.bsky.feed.threadgate.Main
onShare: () => void
}
@@ -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'
@@ -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<AppBskyFeedDefs.PostView>
post: Shadow<app.bsky.feed.defs.PostView>
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'
+5 -9
View File
@@ -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<AppBskyFeedDefs.PostView>
record: AppBskyFeedPost.Record
post: Shadow<app.bsky.feed.defs.PostView>
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
@@ -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
}) {
@@ -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<SectionRef, ProfilesListProps>(
const renderItem = ({
item,
index,
}: ListRenderItemInfo<AppBskyFeedDefs.GeneratorView>) => {
}: ListRenderItemInfo<app.bsky.feed.defs.GeneratorView>) => {
return (
<View
style={[
@@ -1,16 +1,13 @@
import {forwardRef, useCallback, useImperativeHandle, useState} from 'react'
import {type ListRenderItemInfo, View} from 'react-native'
import {
type AppBskyActorDefs,
type AppBskyGraphGetList,
AtUri,
} from '@atproto/api'
import {type ModerationOpts} from '@bsky.app/sdk/moderation'
import {
type InfiniteData,
type UseInfiniteQueryResult,
} from '@tanstack/react-query'
import {AtUri} from '@atproto/syntax'
import {app} from '#/lexicons'
import {useBottomBarOffset} from '#/lib/hooks/useBottomBarOffset'
import {useInitialNumToRender} from '#/lib/hooks/useInitialNumToRender'
import {isBlockedOrBlocking} from '#/lib/moderation/blocked-and-muted'
@@ -23,14 +20,14 @@ import {ListFooter, ListMaybePlaceholder} from '#/components/Lists'
import {Default as ProfileCard} from '#/components/ProfileCard'
import {IS_NATIVE, IS_WEB} from '#/env'
function keyExtractor(item: AppBskyActorDefs.ProfileView, index: number) {
function keyExtractor(item: app.bsky.actor.defs.ProfileView, index: number) {
return `${item.did}-${index}`
}
interface ProfilesListProps {
listUri: string
listMembersQuery: UseInfiniteQueryResult<
InfiniteData<AppBskyGraphGetList.OutputSchema>
InfiniteData<app.bsky.graph.getList.$OutputBody>
>
moderationOpts: ModerationOpts
headerHeight: number
@@ -87,7 +84,7 @@ export const ProfilesList = forwardRef<SectionRef, ProfilesListProps>(
const renderItem = ({
item,
index,
}: ListRenderItemInfo<AppBskyActorDefs.ProfileView>) => {
}: ListRenderItemInfo<app.bsky.actor.defs.ProfileView>) => {
return (
<View
style={[
@@ -6,12 +6,12 @@ import {
View,
type ViewStyle,
} from 'react-native'
import {type AppBskyGraphDefs} 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 {useGenerateStarterPackMutation} from '#/lib/generate-starterpack'
import {useBottomBarOffset} from '#/lib/hooks/useBottomBarOffset'
import {useRequireEmailVerification} from '#/lib/hooks/useRequireEmailVerification'
@@ -57,7 +57,7 @@ interface ProfileFeedgensProps {
emptyStateIcon?: React.ComponentType<any> | 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<AppBskyGraphDefs.StarterPackViewBasic>) => {
}: ListRenderItemInfo<app.bsky.graph.defs.StarterPackViewBasic>) => {
return (
<View
style={[
+3 -8
View File
@@ -3,9 +3,9 @@ import {View} from 'react-native'
// @ts-expect-error missing types
import QRCode from 'react-native-qrcode-styled'
import type ViewShot from 'react-native-view-shot'
import {type AppBskyGraphDefs, AppBskyGraphStarterpack} from '@atproto/api'
import {Trans} from '@lingui/react/macro'
import {app} from '#/lexicons'
import {Logo} from '#/view/icons/Logo'
import {Logotype} from '#/view/icons/Logotype'
import {atoms as a, useTheme} from '#/alf'
@@ -24,18 +24,13 @@ export function QrCode({
link,
ref,
}: {
starterPack: AppBskyGraphDefs.StarterPackView
starterPack: app.bsky.graph.defs.StarterPackView
link: string
ref: React.Ref<ViewShot>
}) {
const {record} = starterPack
if (
!bsky.dangerousIsType<AppBskyGraphStarterpack.Record>(
record,
AppBskyGraphStarterpack.isRecord,
)
) {
if (!bsky.isType(app.bsky.graph.starterpack, record)) {
return null
}
+3 -8
View File
@@ -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
}
+2 -2
View File
@@ -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
+5 -17
View File
@@ -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<AppBskyGraphStarterpack.Record>(
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<AppBskyGraphStarterpack.Record>(
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<AppBskyGraphStarterpack.Record>(
record,
AppBskyGraphStarterpack.isRecord,
)
) {
if (!bsky.isType(app.bsky.graph.starterpack, record)) {
return null
}
@@ -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()
@@ -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
+4 -3
View File
@@ -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(() => {
+7 -15
View File
@@ -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<AppBskyFeedPost.Record>(
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
+8 -15
View File
@@ -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<ViewStyle>
}
@@ -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<AppBskyFeedPost.Record>(
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 <Trans>mentioned users</Trans>
@@ -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<AppBskyNotificationDefs.ActivitySubscription>,
activitySubscription: Un$Typed<app.bsky.notification.defs.ActivitySubscription>,
) => {
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<AppBskyNotificationDefs.ActivitySubscription> {
sub?: app.bsky.notification.defs.ActivitySubscription,
): Un$Typed<app.bsky.notification.defs.ActivitySubscription> {
if (!sub) return {post: false, reply: false}
const {post, reply} = sub
return {post, reply}
@@ -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
+3 -4
View File
@@ -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<number, Contact['id']>,
) {
const filteredIds = new Set<Contact['id']>()
@@ -87,7 +86,7 @@ export function filterMatchedNumbers(
export function getMatchedContacts(
contacts: Contact[],
results: AppBskyContactDefs.MatchAndContactIndex[],
results: app.bsky.contact.defs.MatchAndContactIndex[],
mapping: Map<number, Contact['id']>,
): Array<Match> {
const contactsById = new Map(contacts.map(c => [c.id, c]))
+4 -3
View File
@@ -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
}
@@ -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
}
/**
+3 -11
View File
@@ -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<AppBskyGraphStarterpack.Record>(
record,
AppBskyGraphStarterpack.isRecord,
)
) {
if (!bsky.isType(app.bsky.graph.starterpack, record)) {
return null
}
@@ -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())
@@ -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
@@ -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,
+2 -2
View File
@@ -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()
+2 -3
View File
@@ -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
}
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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
@@ -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<NavigationProp>()
+2 -2
View File
@@ -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<NavigationProp>()
+4 -2
View File
@@ -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, '@')
+4 -3
View File
@@ -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
+2 -2
View File
@@ -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
}) {
@@ -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()
+2 -2
View File
@@ -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']
+55 -41
View File
@@ -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<string, ChatBskyActorDefs.ProfileViewBasic>
relatedProfiles: Map<string, chat.bsky.actor.defs.ProfileViewBasic>
}): 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) && (
<MessageItemEmbed
embed={message.embed}
isFromSelf={isFromSelf}
@@ -528,7 +537,10 @@ let MessageItem = ({
highlightSV={highlightSV}
/>
)}
{ChatBskyEmbedJoinLink.isView(message.embed) && (
{bsky.isType(
chat.bsky.embed.joinLink.view,
message.embed,
) && (
<MessageItemInviteEmbed
embed={message.embed}
isFromSelf={isFromSelf}
@@ -666,7 +678,7 @@ function BlockedPlaceholder({
profile,
style,
}: {
profile: Shadow<ChatBskyActorDefs.ProfileViewBasic>
profile: Shadow<chat.bsky.actor.defs.ProfileViewBasic>
style?: AnimatedStyle<ViewStyle>
}) {
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<string, ChatBskyActorDefs.ProfileViewBasic>
relatedProfiles: Map<string, chat.bsky.actor.defs.ProfileViewBasic>
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<string, ChatBskyActorDefs.ProfileViewBasic>
relatedProfiles: Map<string, chat.bsky.actor.defs.ProfileViewBasic>
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',
+3 -2
View File
@@ -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<AppBskyEmbedRecord.View>
embed: $Typed<app.bsky.embed.record.View>
isFromSelf: boolean
isGroupChat: boolean
squaredTopCorner: boolean
@@ -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<ChatBskyEmbedJoinLink.View>
embed: $Typed<chat.bsky.embed.joinLink.View>
isFromSelf: boolean
isGroupChat: boolean
squaredTopCorner: boolean
+11 -11
View File
@@ -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<MessageDialogsContextType | null>(null)
@@ -52,18 +52,18 @@ export function MessageOverlays({children}: {children: React.ReactNode}) {
const reactionsControl = useDialogControl()
const [deleteTarget, setDeleteTarget] =
useState<ChatBskyConvoDefs.MessageView | null>(null)
useState<chat.bsky.convo.defs.MessageView | null>(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<ChatBskyConvoDefs.MessageView | null>(null)
useState<chat.bsky.convo.defs.MessageView | null>(null)
const [reactionsTarget, setReactionsTarget] =
useState<ChatBskyConvoDefs.MessageView | null>(null)
useState<chat.bsky.convo.defs.MessageView | null>(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)
},
[],
+2 -2
View File
@@ -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()
+6 -7
View File
@@ -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<ChatBskyConvoDefs.MessageView | null>(
null,
)
const [replyTo, setReplyTo] =
useState<chat.bsky.convo.defs.MessageView | null>(null)
const [highlightedMessage, setHighlightedMessage] =
useState<HighlightedMessage | null>(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)
}, [])
+8 -8
View File
@@ -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<string, ChatBskyActorDefs.ProfileViewBasic>
message: ChatBskyConvoDefs.MessageView
relatedProfiles: Map<string, chat.bsky.actor.defs.ProfileViewBasic>
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<React.SetStateAction<string>>
}) {
@@ -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<string, Reaction>()
for (const reaction of reactions ?? []) {
+2 -2
View File
@@ -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<string, ChatBskyActorDefs.ProfileViewBasic>
relatedProfiles: Map<string, chat.bsky.actor.defs.ProfileViewBasic>
}) {
const t = useTheme()
const {t: l} = useLingui()
+2 -2
View File
@@ -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<string, ChatBskyActorDefs.ProfileViewBasic>
relatedProfiles: Map<string, chat.bsky.actor.defs.ProfileViewBasic>
}) {
const t = useTheme()
const {i18n, t: l} = useLingui()
+10 -15
View File
@@ -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)
+9 -4
View File
@@ -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
}
+44 -18
View File
@@ -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<string, ChatBskyActorDefs.ProfileViewBasic>,
user: chat.bsky.convo.defs.SystemMessageReferredUser,
relatedProfiles: Map<string, chat.bsky.actor.defs.ProfileViewBasic>,
): Extract<SystemMessageAction, {kind: 'profile'}> | 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<string, ChatBskyActorDefs.ProfileViewBasic>,
data: chat.bsky.convo.defs.SystemMessageView['data'],
relatedProfiles: Map<string, chat.bsky.actor.defs.ProfileViewBasic>,
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`,
+24 -17
View File
@@ -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)',
+19 -33
View File
@@ -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<string, ChatBskyActorDefs.ProfileViewBasic>,
): ChatBskyConvoDefs.ReactionView[] {
reactions: chat.bsky.convo.defs.ReactionView[] | undefined,
relatedProfiles: Map<string, chat.bsky.actor.defs.ProfileViewBasic>,
): 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<ChatBskyActorDefs.GroupConvoMember>
kind?: $Typed<chat.bsky.actor.defs.GroupConvoMember>
}
export type DirectConvoMember = ChatBskyActorDefs.ProfileViewBasic & {
kind: $Typed<ChatBskyActorDefs.DirectConvoMember>
export type DirectConvoMember = chat.bsky.actor.defs.ProfileViewBasic & {
kind: $Typed<chat.bsky.actor.defs.DirectConvoMember>
}
export type ConvoWithDetails = {view: ChatBskyConvoDefs.ConvoView} & (
export type ConvoWithDetails = {view: chat.bsky.convo.defs.ConvoView} & (
| {
kind: 'group'
details: $Typed<ChatBskyConvoDefs.GroupConvo>
details: $Typed<chat.bsky.convo.defs.GroupConvo>
primaryMember?: GroupConvoMember // the owner - may have left, thus optional
members: Array<GroupConvoMember>
}
| {
kind: 'direct'
details: $Typed<ChatBskyConvoDefs.DirectConvo>
details: $Typed<chat.bsky.convo.defs.DirectConvo>
primaryMember: DirectConvoMember // the other user
members: Array<DirectConvoMember>
}
@@ -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<ChatBskyConvoDefs.GroupConvo>(
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<ChatBskyActorDefs.GroupConvoMember>(
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<GroupConvoMember>,
}
} else if (
bsky.dangerousIsType<ChatBskyConvoDefs.DirectConvo>(
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
@@ -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,
+2 -2
View File
@@ -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<any>,
+3 -3
View File
@@ -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<any>[],
@@ -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
@@ -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<AppBskyFeedPost.Record>(
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<AppBskyEmbedImages.Main>(
embed,
AppBskyEmbedImages.isMain,
)
const isImageEmbed = embed && bsky.isType(app.bsky.embed.images.main, embed)
const isGalleryEmbed =
embed &&
bsky.dangerousIsType<AppBskyEmbedGallery.Main>(
embed,
AppBskyEmbedGallery.isMain,
)
embed && bsky.isType(app.bsky.embed.gallery.main, embed)
const isRecordWithMedia =
embed &&
bsky.dangerousIsType<AppBskyEmbedRecordWithMedia.Main>(
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<AppBskyEmbedImages.Main>(
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<AppBskyEmbedGallery.Main>(
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
+3 -3
View File
@@ -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<any>[],
@@ -45,7 +45,7 @@ export function ImageLayoutGrid({
}
interface ImageLayoutGridInnerProps {
images: AppBskyEmbedImages.ViewImage[]
images: app.bsky.embed.images.ViewImage[]
onPress?: (
index: number,
containerRefs: AnimatedRef<any>[],
@@ -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,
@@ -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 (
<>
<View style={[a.py_lg, a.align_center]}>
@@ -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()
@@ -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])
+3 -4
View File
@@ -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
+2 -3
View File
@@ -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
+2 -2
View File
@@ -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<ViewStyle>
}) {
@@ -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()
+4 -4
View File
@@ -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
+2 -2
View File
@@ -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<typeof Link> {
iconSize: number
iconStyles: StyleProp<ViewStyle>
modui: ModerationUI
profile: AppBskyActorDefs.ProfileViewBasic
profile: app.bsky.actor.defs.ProfileViewBasic
interpretFilterAsBlur?: boolean
hiderStyle?: StyleProp<ViewStyle>
}
+125 -74
View File
@@ -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<string, string> = {}
* @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<RootReportDefs.ReasonType, OzoneReportDefs.ReasonType>,
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<OzoneReportDefs.ReasonType> = new Set([
OzoneReportDefs.REASONVIOLENCEOTHER,
OzoneReportDefs.REASONSEXUALOTHER,
OzoneReportDefs.REASONCHILDSAFETYOTHER,
OzoneReportDefs.REASONHARASSMENTOTHER,
OzoneReportDefs.REASONMISLEADINGOTHER,
OzoneReportDefs.REASONRULEOTHER,
OzoneReportDefs.REASONSELFHARMOTHER,
OzoneReportDefs.REASONOTHER,
])
export const OTHER_REPORT_REASONS: Set<tools.ozone.report.defs.ReasonType> =
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<OzoneReportDefs.ReasonType> =
export const BSKY_LABELER_ONLY_REPORT_REASONS: Set<tools.ozone.report.defs.ReasonType> =
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,
])
/**

Some files were not shown because too many files have changed in this diff Show More