Fixing Right To Left Text
This commit is contained in:
@@ -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
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user