diff --git a/src/lib/strings/rich-text-helpers.ts b/src/lib/strings/rich-text-helpers.ts new file mode 100644 index 00000000..08971ca0 --- /dev/null +++ b/src/lib/strings/rich-text-helpers.ts @@ -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 +} diff --git a/src/view/com/post-thread/PostThreadItem.tsx b/src/view/com/post-thread/PostThreadItem.tsx index bb3c7e2c..cd218a06 100644 --- a/src/view/com/post-thread/PostThreadItem.tsx +++ b/src/view/com/post-thread/PostThreadItem.tsx @@ -336,6 +336,7 @@ let PostThreadItemLoaded = ({ postCid={post.cid} postUri={post.uri} record={record} + richText={richText} showAppealLabelItem={ post.author.did === currentAccount?.did && isModeratedPost } @@ -439,6 +440,7 @@ let PostThreadItemLoaded = ({ big post={post} record={record} + richText={richText} onPressReply={onPressReply} /> @@ -587,6 +589,7 @@ let PostThreadItemLoaded = ({ diff --git a/src/view/com/post/Post.tsx b/src/view/com/post/Post.tsx index 0e5a459f..f035c32a 100644 --- a/src/view/com/post/Post.tsx +++ b/src/view/com/post/Post.tsx @@ -213,7 +213,12 @@ function PostInner({ ) : null} - + diff --git a/src/view/com/posts/FeedItem.tsx b/src/view/com/posts/FeedItem.tsx index f2b5605d..8dee4ed4 100644 --- a/src/view/com/posts/FeedItem.tsx +++ b/src/view/com/posts/FeedItem.tsx @@ -304,6 +304,7 @@ let FeedItemInner = ({ showAppealLabelItem?: boolean }): React.ReactNode => { @@ -96,9 +104,11 @@ let PostDropdownBtn = ({ }, [rootUri, toggleThreadMute, _]) const onCopyPostText = React.useCallback(() => { - Clipboard.setString(record?.text || '') + const str = richTextToString(richText) + + Clipboard.setString(str) Toast.show(_(msg`Copied to clipboard`)) - }, [record, _]) + }, [_, richText]) const onOpenTranslate = React.useCallback(() => { Linking.openURL(translatorUrl) diff --git a/src/view/com/util/post-ctrls/PostCtrls.tsx b/src/view/com/util/post-ctrls/PostCtrls.tsx index 575f19bf..50ef8a87 100644 --- a/src/view/com/util/post-ctrls/PostCtrls.tsx +++ b/src/view/com/util/post-ctrls/PostCtrls.tsx @@ -6,7 +6,11 @@ import { View, ViewStyle, } from 'react-native' -import {AppBskyFeedDefs, AppBskyFeedPost} from '@atproto/api' +import { + AppBskyFeedDefs, + AppBskyFeedPost, + RichText as RichTextAPI, +} from '@atproto/api' import {Text} from '../text/Text' import {PostDropdownBtn} from '../forms/PostDropdownBtn' import {HeartIcon, HeartIconSolid, CommentBottomArrow} from 'lib/icons' @@ -33,6 +37,7 @@ let PostCtrls = ({ big, post, record, + richText, showAppealLabelItem, style, onPressReply, @@ -40,6 +45,7 @@ let PostCtrls = ({ big?: boolean post: Shadow record: AppBskyFeedPost.Record + richText: RichTextAPI showAppealLabelItem?: boolean style?: StyleProp onPressReply: () => void @@ -212,6 +218,7 @@ let PostCtrls = ({ postCid={post.cid} postUri={post.uri} record={record} + richText={richText} showAppealLabelItem={showAppealLabelItem} style={styles.ctrlPad} />