Improved TOC scrolling behavior and fixed incorrect content indentation logic. Added test for image-only sections.

This commit is contained in:
Sergey Chernov 2026-05-25 20:48:44 +03:00
parent 7681590992
commit 9f54c0aca0
3 changed files with 63 additions and 1 deletions

View File

@ -1551,7 +1551,7 @@ internal fun buildReaderContentPlan(book: Fb2Book): ReaderContentPlan {
} }
} }
} }
val childDepth = if (blocks.isEmpty()) readerDepth else readerDepth + 1 val childDepth = if (blocks.hasIndentBearingContent()) readerDepth + 1 else readerDepth
addSections(section.sections, childDepth) addSections(section.sections, childDepth)
} }
@ -1811,6 +1811,19 @@ private fun Fb2Section.readableBlocks(): List<Fb2Block> =
images.map(Fb2Block::Image) + paragraphs.map { Fb2Block.Paragraph(Fb2Text(listOf(Fb2TextSpan(it)))) } images.map(Fb2Block::Image) + paragraphs.map { Fb2Block.Paragraph(Fb2Text(listOf(Fb2TextSpan(it)))) }
} }
private fun List<Fb2Block>.hasIndentBearingContent(): Boolean =
any { block ->
when (block) {
Fb2Block.EmptyLine,
is Fb2Block.Image,
is Fb2Block.Subtitle -> false
is Fb2Block.Cite,
is Fb2Block.Epigraph,
is Fb2Block.Paragraph,
is Fb2Block.Poem -> true
}
}
private data class ChapterEntry( private data class ChapterEntry(
val title: String, val title: String,
val section: Fb2Section, val section: Fb2Section,

View File

@ -693,11 +693,23 @@ private fun TableOfContentsDialog(
onOpenEntry: (ReaderTocEntry) -> Unit, onOpenEntry: (ReaderTocEntry) -> Unit,
onDismiss: () -> Unit, onDismiss: () -> Unit,
) { ) {
val selectedEntryIndex = currentItemIndex?.let { itemIndex ->
contentPlan.tocEntries.indexOfFirst { it.itemIndex == itemIndex }.takeIf { it >= 0 }
}
val listState = rememberLazyListState(
initialFirstVisibleItemIndex = selectedEntryIndex?.let { it + 1 } ?: 0,
)
LaunchedEffect(contentPlan, selectedEntryIndex) {
selectedEntryIndex?.let { listState.scrollToItem(it + 1) }
}
AlertDialog( AlertDialog(
onDismissRequest = onDismiss, onDismissRequest = onDismiss,
title = { Text(strings.tableOfContents) }, title = { Text(strings.tableOfContents) },
text = { text = {
LazyColumn( LazyColumn(
state = listState,
modifier = Modifier.fillMaxWidth().heightIn(max = 480.dp), modifier = Modifier.fillMaxWidth().heightIn(max = 480.dp),
) { ) {
item(key = "back") { item(key = "back") {

View File

@ -6,6 +6,7 @@ import net.sergeych.toread.fb2.Fb2Block
import net.sergeych.toread.fb2.Fb2Book import net.sergeych.toread.fb2.Fb2Book
import net.sergeych.toread.fb2.Fb2Epigraph import net.sergeych.toread.fb2.Fb2Epigraph
import net.sergeych.toread.fb2.Fb2EpigraphBlock import net.sergeych.toread.fb2.Fb2EpigraphBlock
import net.sergeych.toread.fb2.Fb2ImageRef
import net.sergeych.toread.fb2.Fb2Poem import net.sergeych.toread.fb2.Fb2Poem
import net.sergeych.toread.fb2.Fb2PoemBlock import net.sergeych.toread.fb2.Fb2PoemBlock
import net.sergeych.toread.fb2.Fb2Section import net.sergeych.toread.fb2.Fb2Section
@ -275,6 +276,42 @@ class ReadAloudContentPlanTest {
) )
} }
@Test
fun imageOnlyPartStructureDoesNotIndentWholeBook() {
val plan = buildReaderContentPlan(
Fb2Book(
title = "Book",
sections = listOf(
Fb2Section(
title = "Wrapper title",
sections = listOf(
Fb2Section(
images = listOf(Fb2ImageRef("#front.jpg")),
),
Fb2Section(
title = "Part one",
blocks = listOf(Fb2Block.Image(Fb2ImageRef("#part.png"))),
sections = listOf(
Fb2Section(
title = "Chapter one",
blocks = listOf(paragraph("Chapter text.")),
),
),
),
),
),
),
),
)
assertEquals(0, plan.elements.filterIsInstance<ReaderElement.Paragraph>().single().depth)
assertEquals(
listOf(0, 0, 0),
plan.elements.filterIsInstance<ReaderElement.SectionTitle>().map { it.depth },
)
assertEquals(listOf(0, 0, 0, 0), plan.tocEntries.map { it.depth })
}
@Test @Test
fun realNestedSectionsKeepRelativeIndent() { fun realNestedSectionsKeepRelativeIndent() {
val plan = buildReaderContentPlan( val plan = buildReaderContentPlan(