OverviewFilesCommitsIssuesDocsReleasesPeers

favela-android / app / RichText.jsx

42 lines · jsx ref:
// The RN half of the rich-text port. All the correctness lives in lib/richtext.js `segments()`
// (byte-offset facet walking, tested off-device); this only decides what a link LOOKS like and what
// tapping one does.
//
// ⛔ NESTED <Text>, NOT A ROW OF VIEWS. Text must wrap and reflow as one paragraph — laying segments
// out as siblings in a flex row breaks wrapping mid-sentence and puts a link on its own line. RN nests
// <Text> inside <Text> precisely for this.
import React from 'react'
import { Text, Linking, StyleSheet } from 'react-native'
import { segments } from '../lib/richtext'

export default function RichText ({ text, facets, onTag, onMention, style }) {
  const segs = segments(text, facets)
  return (
    <Text style={[s.body, style]}>
      {segs.map((seg, i) => {
        if (seg.kind === 'link') {
          return (
            <Text key={i} style={s.link} onPress={() => Linking.openURL(seg.uri).catch(() => {})}>
              {seg.text}
            </Text>
          )
        }
        if (seg.kind === 'tag') {
          return <Text key={i} style={s.tag} onPress={() => onTag && onTag(seg.tag)}>{seg.text}</Text>
        }
        if (seg.kind === 'mention') {
          return <Text key={i} style={s.mention} onPress={() => onMention && onMention(seg.did)}>{seg.text}</Text>
        }
        return <Text key={i}>{seg.text}</Text>
      })}
    </Text>
  )
}

const s = StyleSheet.create({
  body: { fontSize: 15, lineHeight: 21, color: '#111' },
  link: { color: '#06c' },
  tag: { color: '#06c' },
  mention: { color: '#06c' }
})