[SDK] Adopt @bsky.app/sdk and migrate RichText (#11369)

This commit is contained in:
Samuel Newman
2026-08-13 22:26:18 +03:00
committed by GitHub
parent d991118215
commit f6a22c4f05
47 changed files with 231 additions and 124 deletions
+2 -1
View File
@@ -49,10 +49,10 @@ import {
AppBskyUnspeccedDefs,
AtUri,
ChatBskyGroupDefs,
type RichText,
} from '@atproto/api'
import {type Client} from '@atproto/lex'
import {type AtUriString} from '@atproto/syntax'
import {type RichText} from '@bsky.app/sdk/richtext'
import {plural} from '@lingui/core/macro'
import {Trans, useLingui} from '@lingui/react/macro'
import {useNavigation} from '@react-navigation/native'
@@ -1083,6 +1083,7 @@ export const ComposePost = ({
replyTo: replyTo?.uri,
onStateChange: setPublishingStage,
langs: currentLanguages,
appviewClient: client,
})
).uris[0]
+2 -1
View File
@@ -1,7 +1,8 @@
/**
* Type converters for Draft API - convert between ComposerState and server Draft types.
*/
import {AppBskyDraftDefs, AtUri, RichText} from '@atproto/api'
import {AppBskyDraftDefs, AtUri} from '@atproto/api'
import {RichText} from '@bsky.app/sdk/richtext'
import {nanoid} from 'nanoid/non-secure'
import {resolveLink} from '#/lib/api/resolve'
@@ -1,11 +1,11 @@
import {useEffect, useMemo, useRef, useState} from 'react'
import {Platform, Text as RNText, View} from 'react-native'
import {RichText} from '@atproto/api'
import {parseLanguageString} from '@atproto/syntax'
import {
guessLanguageAsync,
type LanguageResult,
} from '@bsky.app/expo-guess-language'
import {RichText} from '@bsky.app/sdk/richtext'
import {Trans, useLingui} from '@lingui/react/macro'
import debounce from 'lodash.debounce'
+4 -3
View File
@@ -3,9 +3,8 @@ import {
type AppBskyActorDefs,
type AppBskyDraftDefs,
type AppBskyFeedPostgate,
AppBskyRichtextFacet,
RichText,
} from '@atproto/api'
import {RichText} from '@bsky.app/sdk/richtext'
import {nanoid} from 'nanoid/non-secure'
import {type VideoTelemetry} from '#/lib/media/video/telemetry'
@@ -28,6 +27,8 @@ import {
suggestLinkCardUri,
} from '#/view/com/composer/text-input/text-input-util'
import {type Gif} from '#/features/gifPicker/types'
import {app} from '#/lexicons'
import * as bsky from '#/types/bsky'
import {
createVideoState,
type VideoAction,
@@ -677,7 +678,7 @@ export function createComposerState({
if (initRichText.facets) {
for (const facet of initRichText.facets) {
for (const feature of facet.features) {
if (AppBskyRichtextFacet.isLink(feature)) {
if (bsky.isType(app.bsky.richtext.facet.link, feature)) {
if (isBskyPostUrl(feature.uri)) {
detectedPostUris.set(feature.uri, {facet, rt: initRichText})
} else {
@@ -12,7 +12,7 @@ import {
View,
} from 'react-native'
import {type PasteEventPayload, TextInputWrapper} from 'expo-paste-input'
import {AppBskyRichtextFacet, RichText} from '@atproto/api'
import {RichText} from '@bsky.app/sdk/richtext'
import {useLingui} from '@lingui/react/macro'
import {IMAGE_SIZE_CONFIG_POSTS} from '#/lib/constants'
@@ -27,6 +27,8 @@ import {
import {atoms as a, useAlf} from '#/alf'
import {normalizeTextStyles} from '#/alf/typography'
import {IS_ANDROID} from '#/env'
import {app} from '#/lexicons'
import * as bsky from '#/types/bsky'
import {Autocomplete} from './mobile/Autocomplete'
import {type TextInputProps} from './TextInput.types'
@@ -88,7 +90,7 @@ export function TextInput({
if (newRt.facets) {
for (const facet of newRt.facets) {
for (const feature of facet.features) {
if (AppBskyRichtextFacet.isLink(feature)) {
if (bsky.isType(app.bsky.richtext.facet.link, feature)) {
if (isUriImage(feature.uri)) {
const res = await downloadAndResize({
uri: feature.uri,
@@ -1,5 +1,5 @@
import {type TextInput} from 'react-native'
import {type RichText} from '@atproto/api'
import {type RichText} from '@bsky.app/sdk/richtext'
export type TextInputRef = {
focus: () => void
@@ -8,7 +8,7 @@ import {
} from 'react'
import {StyleSheet, View} from 'react-native'
import Animated, {FadeIn, FadeOut} from 'react-native-reanimated'
import {AppBskyRichtextFacet, RichText} from '@atproto/api'
import {RichText} from '@bsky.app/sdk/richtext'
import {Trans} from '@lingui/react/macro'
import {getSchema} from '@tiptap/core'
import {Document} from '@tiptap/extension-document'
@@ -40,6 +40,8 @@ import {normalizeTextStyles} from '#/alf/typography'
import {type Emoji} from '#/components/EmojiPicker'
import {Portal} from '#/components/Portal'
import {Text} from '#/components/Typography'
import {app} from '#/lexicons'
import * as bsky from '#/types/bsky'
import {type TextInputProps} from './TextInput.types'
import {type AutocompleteRef, createSuggestion} from './web/Autocomplete'
import {LinkDecorator} from './web/LinkDecorator'
@@ -265,7 +267,7 @@ export function TextInput({
if (newRt.facets) {
for (const facet of newRt.facets) {
for (const feature of facet.features) {
if (AppBskyRichtextFacet.isLink(feature)) {
if (bsky.isType(app.bsky.richtext.facet.link, feature)) {
nextDetectedUris.set(feature.uri, {facet, rt: newRt})
}
}
@@ -1,8 +1,10 @@
import {type AppBskyRichtextFacet, type RichText} from '@atproto/api'
import {type RichText} from '@bsky.app/sdk/richtext'
import {type app} from '#/lexicons'
export type LinkFacetMatch = {
rt: RichText
facet: AppBskyRichtextFacet.Main
facet: app.bsky.richtext.facet.Main
}
export function suggestLinkCardUri(
+3 -2
View File
@@ -6,14 +6,15 @@ import {
AtUri,
moderatePost,
type ModerationDecision,
RichText as RichTextAPI,
} from '@atproto/api'
import {RichText as RichTextAPI} from '@bsky.app/sdk/richtext'
import {useQueryClient} from '@tanstack/react-query'
import {MAX_POST_LINES} from '#/lib/constants'
import {useOpenComposer} from '#/lib/hooks/useOpenComposer'
import {makeProfileLink} from '#/lib/routes/links'
import {countLines} from '#/lib/strings/helpers'
import {asSdkFacets} from '#/lib/strings/rich-text-helpers'
import {
POST_TOMBSTONE,
type Shadow,
@@ -68,7 +69,7 @@ export function Post({
record
? new RichTextAPI({
text: record.text,
facets: record.facets,
facets: asSdkFacets(record.facets),
})
: undefined,
[record],
+1 -1
View File
@@ -25,8 +25,8 @@ import {
AppBskyEmbedImages,
AppBskyEmbedVideo,
type AppBskyFeedDefs,
type RichText as RichTextType,
} from '@atproto/api'
import {type RichText as RichTextType} from '@bsky.app/sdk/richtext'
import {useLingui} from '@lingui/react/macro'
import {useQueryClient} from '@tanstack/react-query'
+3 -2
View File
@@ -7,8 +7,8 @@ import {
AppBskyFeedThreadgate,
AtUri,
type ModerationDecision,
RichText as RichTextAPI,
} from '@atproto/api'
import {RichText as RichTextAPI} from '@bsky.app/sdk/richtext'
import {useQueryClient} from '@tanstack/react-query'
import {type ReasonFeedSource} from '#/lib/api/feed/types'
@@ -17,6 +17,7 @@ import {useOpenComposer} from '#/lib/hooks/useOpenComposer'
import {usePalette} from '#/lib/hooks/usePalette'
import {makeProfileLink} from '#/lib/routes/links'
import {countLines} from '#/lib/strings/helpers'
import {asSdkFacets} from '#/lib/strings/rich-text-helpers'
import {
POST_TOMBSTONE,
type Shadow,
@@ -104,7 +105,7 @@ export function PostFeedItem({
() =>
new RichTextAPI({
text: record.text,
facets: record.facets,
facets: asSdkFacets(record.facets),
}),
[record],
)