fix for when images are separated by empty lines

refactor to reduce duplication:
Extract RenderParagraphWithFlowRow
Extract collectConsecutiveImageParagraphs
This commit is contained in:
davotoula
2025-09-11 20:50:21 +02:00
parent 9534582141
commit 062182a7ec

View File

@@ -329,27 +329,13 @@ fun RenderRegularWithGallery(
if (isImageOnlyParagraph && paragraph.words.isNotEmpty()) { if (isImageOnlyParagraph && paragraph.words.isNotEmpty()) {
// Collect consecutive image-only paragraphs // Collect consecutive image-only paragraphs
val imageParagraphs = mutableListOf<ParagraphState>() val (imageParagraphs, totalProcessedCount) = collectConsecutiveImageParagraphs(state.paragraphs, i)
var j = i
while (j < state.paragraphs.size) {
val currentParagraph = state.paragraphs[j]
val isCurrentImageOnly =
currentParagraph.words.all { word ->
word is ImageSegment || word is Base64Segment
}
if (isCurrentImageOnly && currentParagraph.words.isNotEmpty()) {
imageParagraphs.add(currentParagraph)
j++
} else {
break
}
}
// Combine all image words from consecutive paragraphs // Combine all image words from consecutive paragraphs
val allImageWords = imageParagraphs.flatMap { it.words }.toImmutableList() val allImageWords = imageParagraphs.flatMap { it.words }.toImmutableList()
if (allImageWords.size > 1) { if (allImageWords.size > 1) {
// Multiple images - render as gallery // Multiple images - render as gallery (no FlowRow wrapper needed)
RenderWordsWithImageGallery( RenderWordsWithImageGallery(
allImageWords, allImageWords,
state, state,
@@ -361,6 +347,51 @@ fun RenderRegularWithGallery(
) )
} else { } else {
// Single image - render normally // Single image - render normally
RenderParagraphWithFlowRow(
paragraph,
paragraph.words.toImmutableList(),
spaceWidth,
state,
backgroundColor,
quotesLeft,
callbackUri,
accountViewModel,
nav,
)
}
i += totalProcessedCount // Skip processed paragraphs (including empty ones)
} else {
// Non-image paragraph - render normally
RenderParagraphWithFlowRow(
paragraph,
paragraph.words.toImmutableList(),
spaceWidth,
state,
backgroundColor,
quotesLeft,
callbackUri,
accountViewModel,
nav,
)
i++
}
}
}
}
@Composable
private fun RenderParagraphWithFlowRow(
paragraph: ParagraphState,
words: ImmutableList<Segment>,
spaceWidth: Dp,
state: RichTextViewerState,
backgroundColor: MutableState<Color>,
quotesLeft: Int,
callbackUri: String?,
accountViewModel: AccountViewModel,
nav: INav,
) {
CompositionLocalProvider( CompositionLocalProvider(
LocalLayoutDirection provides LocalLayoutDirection provides
if (paragraph.isRTL) { if (paragraph.isRTL) {
@@ -371,11 +402,10 @@ fun RenderRegularWithGallery(
LocalTextStyle provides LocalTextStyle.current, LocalTextStyle provides LocalTextStyle.current,
) { ) {
FlowRow( FlowRow(
modifier = Modifier.align(if (paragraph.isRTL) Alignment.End else Alignment.Start),
horizontalArrangement = Arrangement.spacedBy(spaceWidth), horizontalArrangement = Arrangement.spacedBy(spaceWidth),
) { ) {
RenderWordsWithImageGallery( RenderWordsWithImageGallery(
paragraph.words.toImmutableList(), words,
state, state,
backgroundColor, backgroundColor,
quotesLeft, quotesLeft,
@@ -387,37 +417,43 @@ fun RenderRegularWithGallery(
} }
} }
i = j // Skip processed paragraphs private fun collectConsecutiveImageParagraphs(
} else { paragraphs: ImmutableList<ParagraphState>,
// Non-image paragraph - render normally startIndex: Int,
CompositionLocalProvider( ): Pair<List<ParagraphState>, Int> {
LocalLayoutDirection provides val imageParagraphs = mutableListOf<ParagraphState>()
if (paragraph.isRTL) { var j = startIndex
LayoutDirection.Rtl while (j < paragraphs.size) {
} else { val currentParagraph = paragraphs[j]
LayoutDirection.Ltr val isEmpty =
}, currentParagraph.words.isEmpty() ||
LocalTextStyle provides LocalTextStyle.current, (
) { currentParagraph.words.size == 1 &&
FlowRow( currentParagraph.words.first() is RegularTextSegment &&
modifier = Modifier.align(if (paragraph.isRTL) Alignment.End else Alignment.Start), currentParagraph.words
horizontalArrangement = Arrangement.spacedBy(spaceWidth), .first()
) { .segmentText
RenderWordsWithImageGallery( .isBlank()
paragraph.words.toImmutableList(),
state,
backgroundColor,
quotesLeft,
callbackUri,
accountViewModel,
nav,
) )
val isCurrentImageOnly =
currentParagraph.words.isNotEmpty() &&
currentParagraph.words.all { word ->
word is ImageSegment || word is Base64Segment
}
if (isCurrentImageOnly) {
imageParagraphs.add(currentParagraph)
j++
} else if (isEmpty) {
// Skip empty paragraphs but continue looking for consecutive images
j++
} else {
// Hit a non-empty, non-image paragraph - stop collecting
break
} }
} }
i++ return Pair(imageParagraphs, j - startIndex) // Return paragraphs and total processed count
}
}
}
} }
@OptIn(ExperimentalLayoutApi::class) @OptIn(ExperimentalLayoutApi::class)