diff options
Diffstat (limited to 'src/view/com/util/text')
-rw-r--r-- | src/view/com/util/text/RichText.tsx | 106 |
1 files changed, 40 insertions, 66 deletions
diff --git a/src/view/com/util/text/RichText.tsx b/src/view/com/util/text/RichText.tsx index d4cf19172..804db002a 100644 --- a/src/view/com/util/text/RichText.tsx +++ b/src/view/com/util/text/RichText.tsx @@ -1,20 +1,22 @@ import React from 'react' import {TextStyle, StyleProp} from 'react-native' +import {RichText as RichTextObj, AppBskyRichtextFacet} from '@atproto/api' import {TextLink} from '../Link' import {Text} from './Text' import {lh} from 'lib/styles' import {toShortUrl} from 'lib/strings/url-helpers' -import {RichText as RichTextObj, Entity} from 'lib/strings/rich-text' import {useTheme, TypographyVariant} from 'lib/ThemeContext' import {usePalette} from 'lib/hooks/usePalette' export function RichText({ + testID, type = 'md', richText, lineHeight = 1.2, style, numberOfLines, }: { + testID?: string type?: TypographyVariant richText?: RichTextObj lineHeight?: number @@ -29,17 +31,24 @@ export function RichText({ return null } - const {text, entities} = richText - if (!entities?.length) { + const {text, facets} = richText + if (!facets?.length) { if (/^\p{Extended_Pictographic}+$/u.test(text) && text.length <= 5) { style = { fontSize: 26, lineHeight: 30, } - return <Text style={[style, pal.text]}>{text}</Text> + return ( + <Text testID={testID} style={[style, pal.text]}> + {text} + </Text> + ) } return ( - <Text type={type} style={[style, pal.text, lineHeightStyle]}> + <Text + testID={testID} + type={type} + style={[style, pal.text, lineHeightStyle]}> {text} </Text> ) @@ -49,40 +58,40 @@ export function RichText({ } else if (!Array.isArray(style)) { style = [style] } - entities.sort(sortByIndex) - const segments = Array.from(toSegments(text, entities)) + const els = [] let key = 0 - for (const segment of segments) { - if (typeof segment === 'string') { - els.push(segment) + for (const segment of richText.segments()) { + const link = segment.link + const mention = segment.mention + if (mention && AppBskyRichtextFacet.validateMention(mention).success) { + els.push( + <TextLink + key={key} + type={type} + text={segment.text} + href={`/profile/${mention.did}`} + style={[style, lineHeightStyle, pal.link]} + />, + ) + } else if (link && AppBskyRichtextFacet.validateLink(link).success) { + els.push( + <TextLink + key={key} + type={type} + text={toShortUrl(segment.text)} + href={link.uri} + style={[style, lineHeightStyle, pal.link]} + />, + ) } else { - if (segment.entity.type === 'mention') { - els.push( - <TextLink - key={key} - type={type} - text={segment.text} - href={`/profile/${segment.entity.value}`} - style={[style, lineHeightStyle, pal.link]} - />, - ) - } else if (segment.entity.type === 'link') { - els.push( - <TextLink - key={key} - type={type} - text={toShortUrl(segment.text)} - href={segment.entity.value} - style={[style, lineHeightStyle, pal.link]} - />, - ) - } + els.push(segment.text) } key++ } return ( <Text + testID={testID} type={type} style={[style, pal.text, lineHeightStyle]} numberOfLines={numberOfLines}> @@ -90,38 +99,3 @@ export function RichText({ </Text> ) } - -function sortByIndex(a: Entity, b: Entity) { - return a.index.start - b.index.start -} - -function* toSegments(text: string, entities: Entity[]) { - let cursor = 0 - let i = 0 - do { - let currEnt = entities[i] - if (cursor < currEnt.index.start) { - yield text.slice(cursor, currEnt.index.start) - } else if (cursor > currEnt.index.start) { - i++ - continue - } - if (currEnt.index.start < currEnt.index.end) { - let subtext = text.slice(currEnt.index.start, currEnt.index.end) - if (!subtext.trim()) { - // dont yield links to empty strings - yield subtext - } else { - yield { - entity: currEnt, - text: subtext, - } - } - } - cursor = currEnt.index.end - i++ - } while (i < entities.length) - if (cursor < text.length) { - yield text.slice(cursor, text.length) - } -} |