Fixing Right To Left Text

This commit is contained in:
Vitor Pamplona
2023-07-13 19:23:26 -04:00
parent 9b62cf563a
commit 0d9399a1a4
2 changed files with 51 additions and 31 deletions
@@ -30,9 +30,11 @@ data class RichTextViewerState(
val imagesForPager: ImmutableMap<String, ZoomableUrlContent>, val imagesForPager: ImmutableMap<String, ZoomableUrlContent>,
val imageList: ImmutableList<ZoomableUrlContent>, val imageList: ImmutableList<ZoomableUrlContent>,
val customEmoji: ImmutableMap<String, String>, val customEmoji: ImmutableMap<String, String>,
val paragraphs: ImmutableList<ImmutableList<Segment>> val paragraphs: ImmutableList<ParagraphState>
) )
data class ParagraphState(val words: ImmutableList<Segment>, val isRTL: Boolean)
object CachedRichTextParser { object CachedRichTextParser {
val richTextCache = LruCache<String, RichTextViewerState>(200) val richTextCache = LruCache<String, RichTextViewerState>(200)
@@ -108,13 +110,15 @@ class RichTextParser() {
) )
} }
private fun findTextSegments(content: String, images: Set<String>, urls: Set<String>, emojis: Map<String, String>, tags: ImmutableListOfLists<String>): ImmutableList<ImmutableList<Segment>> { private fun findTextSegments(content: String, images: Set<String>, urls: Set<String>, emojis: Map<String, String>, tags: ImmutableListOfLists<String>): ImmutableList<ParagraphState> {
var paragraphSegments = persistentListOf<ImmutableList<Segment>>() var paragraphSegments = persistentListOf<ParagraphState>()
content.split('\n').forEach { paragraph -> content.split('\n').forEach { paragraph ->
var segments = persistentListOf<Segment>() var segments = persistentListOf<Segment>()
var isDirty = false var isDirty = false
val isRTL = isArabic(paragraph)
val wordList = paragraph.split(' ') val wordList = paragraph.split(' ')
wordList.forEach { word -> wordList.forEach { word ->
val wordSegment = wordIdentifier(word, images, urls, emojis, tags) val wordSegment = wordIdentifier(word, images, urls, emojis, tags)
@@ -125,13 +129,9 @@ class RichTextParser() {
} }
val newSegments = if (isDirty) { val newSegments = if (isDirty) {
if (isArabic(paragraph)) { ParagraphState(segments, isRTL)
segments.asReversed().toImmutableList()
} else {
segments
}
} else { } else {
persistentListOf<Segment>(RegularTextSegment(paragraph)) ParagraphState(persistentListOf<Segment>(RegularTextSegment(paragraph)), isRTL)
} }
paragraphSegments = paragraphSegments.add(newSegments) paragraphSegments = paragraphSegments.add(newSegments)
@@ -17,16 +17,19 @@ import androidx.compose.material.ProvideTextStyle
import androidx.compose.material.Text import androidx.compose.material.Text
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.takeOrElse import androidx.compose.ui.graphics.takeOrElse
import androidx.compose.ui.layout.SubcomposeLayout import androidx.compose.ui.layout.SubcomposeLayout
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.platform.LocalUriHandler import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.* import androidx.compose.ui.text.*
import androidx.compose.ui.text.style.TextDirection import androidx.compose.ui.text.style.TextDirection
import androidx.compose.ui.unit.Constraints import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.em import androidx.compose.ui.unit.em
import androidx.lifecycle.distinctUntilChanged import androidx.lifecycle.distinctUntilChanged
import androidx.lifecycle.map import androidx.lifecycle.map
@@ -136,7 +139,6 @@ private fun RenderRegular(
val currentTextStyle = LocalTextStyle.current val currentTextStyle = LocalTextStyle.current
val textStyle = currentTextStyle.copy( val textStyle = currentTextStyle.copy(
textDirection = TextDirection.Content,
lineHeight = 1.4.em, lineHeight = 1.4.em,
color = currentTextStyle.color.takeOrElse { color = currentTextStyle.color.takeOrElse {
LocalContentColor.current.copy(alpha = LocalContentAlpha.current) LocalContentColor.current.copy(alpha = LocalContentAlpha.current)
@@ -144,36 +146,54 @@ private fun RenderRegular(
) )
MeasureSpaceWidth() { spaceWidth -> MeasureSpaceWidth() { spaceWidth ->
Column { Column() {
if (canPreview) { if (canPreview) {
// FlowRow doesn't work well with paragraphs. So we need to split them // FlowRow doesn't work well with paragraphs. So we need to split them
state.paragraphs.forEach { paragraph -> state.paragraphs.forEach { paragraph ->
FlowRow(horizontalArrangement = Arrangement.spacedBy(spaceWidth)) { val direction = if (paragraph.isRTL) {
paragraph.forEach { word -> LayoutDirection.Rtl
RenderWordWithPreview( } else LayoutDirection.Ltr
word,
state, CompositionLocalProvider(LocalLayoutDirection provides direction) {
backgroundColor, FlowRow(
textStyle, modifier = Modifier.align(if (paragraph.isRTL) Alignment.End else Alignment.Start),
accountViewModel, horizontalArrangement = Arrangement.spacedBy(spaceWidth)
nav ) {
) paragraph.words.forEach { word ->
RenderWordWithPreview(
word,
state,
backgroundColor,
textStyle,
accountViewModel,
nav
)
}
} }
} }
} }
} else { } else {
// FlowRow doesn't work well with paragraphs. So we need to split them // FlowRow doesn't work well with paragraphs. So we need to split them
state.paragraphs.forEach { paragraph -> state.paragraphs.forEach { paragraph ->
FlowRow(horizontalArrangement = Arrangement.spacedBy(spaceWidth)) { val direction = if (paragraph.isRTL) {
paragraph.forEach { word -> LayoutDirection.Rtl
RenderWordWithoutPreview( } else LayoutDirection.Ltr
word,
state, CompositionLocalProvider(LocalLayoutDirection provides direction) {
backgroundColor, FlowRow(
textStyle, horizontalArrangement = Arrangement.spacedBy(spaceWidth),
accountViewModel, modifier = Modifier.align(if (paragraph.isRTL) Alignment.End else Alignment.Start),
nav ) {
) paragraph.words.forEach { word ->
RenderWordWithoutPreview(
word,
state,
backgroundColor,
textStyle,
accountViewModel,
nav
)
}
} }
} }
} }