diff options
author | Paul Frazee <pfrazee@gmail.com> | 2023-03-31 13:17:26 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-31 13:17:26 -0500 |
commit | a3334a01a221877d3e06e02f960fda441f3460bd (patch) | |
tree | 64cdbb1232d1a3c00750c346b6e3ae529b51d1b0 /src/view/com/util/text | |
parent | 19f3a2fa92a61ddb785fc4e42d73792c1d0e772c (diff) | |
download | voidsky-a3334a01a221877d3e06e02f960fda441f3460bd.tar.zst |
Lex refactor (#362)
* Remove the hackcheck for upgrades * Rename the PostEmbeds folder to match the codebase style * Updates to latest lex refactor * Update to use new bsky agent * Update to use api package's richtext library * Switch to upsertProfile * Add TextEncoder/TextDecoder polyfill * Add Intl.Segmenter polyfill * Update composer to calculate lengths by grapheme * Fix detox * Fix login in e2e * Create account e2e passing * Implement an e2e mocking framework * Don't use private methods on mobx models as mobx can't track them * Add tooling for e2e-specific builds and add e2e media-picker mock * Add some tests and fix some bugs around profile editing * Add shell tests * Add home screen tests * Add thread screen tests * Add tests for other user profile screens * Add search screen tests * Implement profile imagery change tools and tests * Update to new embed behaviors * Add post tests * Fix to profile-screen test * Fix session resumption * Update web composer to new api * 1.11.0 * Fix pagination cursor parameters * Add quote posts to notifications * Fix embed layouts * Remove youtube inline player and improve tap handling on link cards * Reset minimal shell mode on all screen loads and feed swipes (close #299) * Update podfile.lock * Improve post notfound UI (close #366) * Bump atproto packages
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) - } -} |