Use the RichText facets when copying post text (#2481)

* feat: serialize rich text to string

* feat: wire richTextToString to copy post text
zio/stable
Mary 2024-01-11 13:56:45 +07:00 committed by GitHub
parent f7b01c3542
commit 0b2daa787c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 60 additions and 5 deletions

View File

@ -0,0 +1,29 @@
import {AppBskyRichtextFacet, RichText} from '@atproto/api'
import {linkRequiresWarning} from './url-helpers'
export function richTextToString(rt: RichText): string {
const {text, facets} = rt
if (!facets?.length) {
return text
}
let result = ''
for (const segment of rt.segments()) {
const link = segment.link
if (link && AppBskyRichtextFacet.validateLink(link).success) {
const href = link.uri
const text = segment.text
const requiresWarning = linkRequiresWarning(href, text)
result += !requiresWarning ? href : `[${text}](${href})`
} else {
result += segment.text
}
}
return result
}

View File

@ -336,6 +336,7 @@ let PostThreadItemLoaded = ({
postCid={post.cid} postCid={post.cid}
postUri={post.uri} postUri={post.uri}
record={record} record={record}
richText={richText}
showAppealLabelItem={ showAppealLabelItem={
post.author.did === currentAccount?.did && isModeratedPost post.author.did === currentAccount?.did && isModeratedPost
} }
@ -439,6 +440,7 @@ let PostThreadItemLoaded = ({
big big
post={post} post={post}
record={record} record={record}
richText={richText}
onPressReply={onPressReply} onPressReply={onPressReply}
/> />
</View> </View>
@ -587,6 +589,7 @@ let PostThreadItemLoaded = ({
<PostCtrls <PostCtrls
post={post} post={post}
record={record} record={record}
richText={richText}
onPressReply={onPressReply} onPressReply={onPressReply}
/> />
</View> </View>

View File

@ -213,7 +213,12 @@ function PostInner({
</ContentHider> </ContentHider>
) : null} ) : null}
</ContentHider> </ContentHider>
<PostCtrls post={post} record={record} onPressReply={onPressReply} /> <PostCtrls
post={post}
record={record}
richText={richText}
onPressReply={onPressReply}
/>
</View> </View>
</View> </View>
</Link> </Link>

View File

@ -304,6 +304,7 @@ let FeedItemInner = ({
<PostCtrls <PostCtrls
post={post} post={post}
record={record} record={record}
richText={richText}
onPressReply={onPressReply} onPressReply={onPressReply}
showAppealLabelItem={ showAppealLabelItem={
post.author.did === currentAccount?.did && isModeratedPost post.author.did === currentAccount?.did && isModeratedPost

View File

@ -2,7 +2,12 @@ import React, {memo} from 'react'
import {Linking, StyleProp, View, ViewStyle} from 'react-native' import {Linking, StyleProp, View, ViewStyle} from 'react-native'
import Clipboard from '@react-native-clipboard/clipboard' import Clipboard from '@react-native-clipboard/clipboard'
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome' import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
import {AppBskyActorDefs, AppBskyFeedPost, AtUri} from '@atproto/api' import {
AppBskyActorDefs,
AppBskyFeedPost,
AtUri,
RichText as RichTextAPI,
} from '@atproto/api'
import {toShareUrl} from 'lib/strings/url-helpers' import {toShareUrl} from 'lib/strings/url-helpers'
import {useTheme} from 'lib/ThemeContext' import {useTheme} from 'lib/ThemeContext'
import {shareUrl} from 'lib/sharing' import {shareUrl} from 'lib/sharing'
@ -24,6 +29,7 @@ import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {useSession} from '#/state/session' import {useSession} from '#/state/session'
import {isWeb} from '#/platform/detection' import {isWeb} from '#/platform/detection'
import {richTextToString} from '#/lib/strings/rich-text-helpers'
let PostDropdownBtn = ({ let PostDropdownBtn = ({
testID, testID,
@ -31,6 +37,7 @@ let PostDropdownBtn = ({
postCid, postCid,
postUri, postUri,
record, record,
richText,
style, style,
showAppealLabelItem, showAppealLabelItem,
}: { }: {
@ -39,6 +46,7 @@ let PostDropdownBtn = ({
postCid: string postCid: string
postUri: string postUri: string
record: AppBskyFeedPost.Record record: AppBskyFeedPost.Record
richText: RichTextAPI
style?: StyleProp<ViewStyle> style?: StyleProp<ViewStyle>
showAppealLabelItem?: boolean showAppealLabelItem?: boolean
}): React.ReactNode => { }): React.ReactNode => {
@ -96,9 +104,11 @@ let PostDropdownBtn = ({
}, [rootUri, toggleThreadMute, _]) }, [rootUri, toggleThreadMute, _])
const onCopyPostText = React.useCallback(() => { const onCopyPostText = React.useCallback(() => {
Clipboard.setString(record?.text || '') const str = richTextToString(richText)
Clipboard.setString(str)
Toast.show(_(msg`Copied to clipboard`)) Toast.show(_(msg`Copied to clipboard`))
}, [record, _]) }, [_, richText])
const onOpenTranslate = React.useCallback(() => { const onOpenTranslate = React.useCallback(() => {
Linking.openURL(translatorUrl) Linking.openURL(translatorUrl)

View File

@ -6,7 +6,11 @@ import {
View, View,
ViewStyle, ViewStyle,
} from 'react-native' } from 'react-native'
import {AppBskyFeedDefs, AppBskyFeedPost} from '@atproto/api' import {
AppBskyFeedDefs,
AppBskyFeedPost,
RichText as RichTextAPI,
} from '@atproto/api'
import {Text} from '../text/Text' import {Text} from '../text/Text'
import {PostDropdownBtn} from '../forms/PostDropdownBtn' import {PostDropdownBtn} from '../forms/PostDropdownBtn'
import {HeartIcon, HeartIconSolid, CommentBottomArrow} from 'lib/icons' import {HeartIcon, HeartIconSolid, CommentBottomArrow} from 'lib/icons'
@ -33,6 +37,7 @@ let PostCtrls = ({
big, big,
post, post,
record, record,
richText,
showAppealLabelItem, showAppealLabelItem,
style, style,
onPressReply, onPressReply,
@ -40,6 +45,7 @@ let PostCtrls = ({
big?: boolean big?: boolean
post: Shadow<AppBskyFeedDefs.PostView> post: Shadow<AppBskyFeedDefs.PostView>
record: AppBskyFeedPost.Record record: AppBskyFeedPost.Record
richText: RichTextAPI
showAppealLabelItem?: boolean showAppealLabelItem?: boolean
style?: StyleProp<ViewStyle> style?: StyleProp<ViewStyle>
onPressReply: () => void onPressReply: () => void
@ -212,6 +218,7 @@ let PostCtrls = ({
postCid={post.cid} postCid={post.cid}
postUri={post.uri} postUri={post.uri}
record={record} record={record}
richText={richText}
showAppealLabelItem={showAppealLabelItem} showAppealLabelItem={showAppealLabelItem}
style={styles.ctrlPad} style={styles.ctrlPad}
/> />