From e9fa8ebb43fe61834cb63f3e1ebd48a307d0f11f Mon Sep 17 00:00:00 2001 From: YugaJ7 Date: Thu, 5 Jun 2025 20:17:04 +0530 Subject: [PATCH 1/7] - Refactor `DetailContent` to use `LazyColumn` for improved performance and scrolling. - Dynamically build Table of Contents items based on available sections. - Enable smooth scrolling to sections when a Table of Contents item is clicked. --- .../ui/screens/detail/DetailContent.kt | 73 ++++++++++++++++--- .../ui/screens/detail/DetailScreenUI.kt | 12 +-- 2 files changed, 66 insertions(+), 19 deletions(-) diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailContent.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailContent.kt index 501cb24..f3046e6 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailContent.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailContent.kt @@ -1,28 +1,83 @@ package com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail -import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.runtime.Composable +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp import com.developersbreach.kotlindictionarymultiplatform.data.detail.model.KotlinTopicDetails import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.components.IntroductionSection import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.components.PitfallsSection import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.components.RelatedTopicsSection -import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.components.SectionsList +import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.components.SectionBlock import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.components.SyntaxSection import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.components.TableOfContents +import kotlindictionarymultiplatform.composeapp.generated.resources.Res +import kotlindictionarymultiplatform.composeapp.generated.resources.bullet_item +import kotlindictionarymultiplatform.composeapp.generated.resources.introduction_bullet +import kotlindictionarymultiplatform.composeapp.generated.resources.pitfalls_bullet +import kotlindictionarymultiplatform.composeapp.generated.resources.related_topics_bullet +import kotlindictionarymultiplatform.composeapp.generated.resources.syntax_bullet +import kotlinx.coroutines.launch +import org.jetbrains.compose.resources.stringResource @Composable fun DetailContent( topic: KotlinTopicDetails, modifier: Modifier = Modifier, ) { - Column(modifier = modifier.fillMaxSize()) { - TableOfContents(topic) - IntroductionSection(topic) - SyntaxSection(topic) - SectionsList(topic) - PitfallsSection(topic) - RelatedTopicsSection(topic) + val listState = rememberLazyListState() + val coroutineScope = rememberCoroutineScope() + + val tocItems = buildList { + var index = 1 + add(stringResource(Res.string.introduction_bullet) to index++) + if (topic.syntax.signature.isNotBlank()) add(stringResource(Res.string.syntax_bullet) to index++) + topic.sections.forEach { section -> + section.heading?.let { add(stringResource(Res.string.bullet_item, it) to index++) } + } + if (topic.pitfalls.isNotEmpty()) add(stringResource(Res.string.pitfalls_bullet) to index++) + if (topic.relatedTopics.isNotEmpty()) add(stringResource(Res.string.related_topics_bullet) to index) + } + + LazyColumn( + state = listState, + modifier = modifier + .fillMaxSize() + .padding(horizontal = 16.dp), + ) { + // Table of Contents + item { + TableOfContents( + items = tocItems, + onClick = { index -> + coroutineScope.launch { + listState.animateScrollToItem(index) + } + }, + ) + } + + // Sections + item { IntroductionSection(topic) } + + if (topic.syntax.signature.isNotBlank()) { + item { SyntaxSection(topic) } + } + + topic.sections.forEach { section -> + item { SectionBlock(section) } + } + + if (topic.pitfalls.isNotEmpty()) { + item { PitfallsSection(topic) } + } + + if (topic.relatedTopics.isNotEmpty()) { + item { RelatedTopicsSection(topic) } + } } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreenUI.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreenUI.kt index 509559e..c741842 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreenUI.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreenUI.kt @@ -1,29 +1,21 @@ package com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.rememberScrollState -import androidx.compose.foundation.verticalScroll import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp import com.developersbreach.kotlindictionarymultiplatform.data.detail.model.KotlinTopicDetails @Composable fun DetailScreenUI(topic: KotlinTopicDetails) { - val scrollState = rememberScrollState() - Scaffold( - containerColor = MaterialTheme.colorScheme.background, topBar = { DetailTopBar(title = topic.topicName) }, + containerColor = MaterialTheme.colorScheme.background, ) { innerPadding -> DetailContent( topic = topic, - modifier = Modifier - .padding(innerPadding) - .verticalScroll(scrollState) - .padding(16.dp), + modifier = Modifier.padding(innerPadding), ) } } \ No newline at end of file From e81c18c63290cadee5a74cf2fb87ec1c7df509fc Mon Sep 17 00:00:00 2001 From: YugaJ7 Date: Thu, 5 Jun 2025 20:18:05 +0530 Subject: [PATCH 2/7] - Introduce `SectionBlock` composable for consistent section rendering. - Update `TableOfContents` to handle clicks and accept a list of items. --- .../detail/components/IntroductionSection.kt | 3 +- .../detail/components/PitfallsSection.kt | 14 ++++---- .../detail/components/RelatedTopicsSection.kt | 11 +++--- .../screens/detail/components/SectionsList.kt | 36 +++++++++---------- .../detail/components/SyntaxSection.kt | 22 ++++++------ .../detail/components/TableOfContents.kt | 31 +++++++--------- 6 files changed, 55 insertions(+), 62 deletions(-) diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/IntroductionSection.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/IntroductionSection.kt index 0868acd..153aa3e 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/IntroductionSection.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/IntroductionSection.kt @@ -15,6 +15,7 @@ import org.jetbrains.compose.resources.stringResource @Composable fun IntroductionSection(topic: KotlinTopicDetails) { Text(stringResource(Res.string.introduction), style = MaterialTheme.typography.headlineLarge, color = MaterialTheme.colorScheme.onPrimary) - Spacer(modifier = Modifier.height(4.dp)) + Spacer(Modifier.height(4.dp)) Text(text = topic.intro, style = MaterialTheme.typography.bodyMedium) + Spacer(Modifier.height(16.dp)) } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/PitfallsSection.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/PitfallsSection.kt index df446aa..1ee8b88 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/PitfallsSection.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/PitfallsSection.kt @@ -15,12 +15,12 @@ import org.jetbrains.compose.resources.stringResource @Composable fun PitfallsSection(topic: KotlinTopicDetails) { - if (topic.pitfalls.isNotEmpty()) { - Text(stringResource(Res.string.pitfalls), style = MaterialTheme.typography.headlineLarge, color = MaterialTheme.colorScheme.onPrimary) - Spacer(Modifier.height(4.dp)) - topic.pitfalls.forEach { - Text(stringResource(Res.string.bullet_item, it), style = MaterialTheme.typography.bodyMedium) - } - Spacer(Modifier.height(16.dp)) + Text(stringResource(Res.string.pitfalls), style = MaterialTheme.typography.headlineLarge, color = MaterialTheme.colorScheme.onPrimary) + Spacer(Modifier.height(4.dp)) + + topic.pitfalls.forEach { + Text(text = stringResource(Res.string.bullet_item, it), style = MaterialTheme.typography.bodyMedium) } + + Spacer(Modifier.height(16.dp)) } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/RelatedTopicsSection.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/RelatedTopicsSection.kt index 75137db..732c6f0 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/RelatedTopicsSection.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/RelatedTopicsSection.kt @@ -15,11 +15,10 @@ import org.jetbrains.compose.resources.stringResource @Composable fun RelatedTopicsSection(topic: KotlinTopicDetails) { - if (topic.relatedTopics.isNotEmpty()) { - Text(stringResource(Res.string.related_topics), style = MaterialTheme.typography.headlineLarge, color = MaterialTheme.colorScheme.onPrimary) - Spacer(Modifier.height(4.dp)) - topic.relatedTopics.forEach { - Text(stringResource(Res.string.bullet_item, it), style = MaterialTheme.typography.bodyMedium) - } + Text(stringResource(Res.string.related_topics), style = MaterialTheme.typography.headlineLarge, color = MaterialTheme.colorScheme.onPrimary) + Spacer(Modifier.height(4.dp)) + + topic.relatedTopics.forEach { + Text(text = stringResource(Res.string.bullet_item, it), style = MaterialTheme.typography.bodyMedium) } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/SectionsList.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/SectionsList.kt index e9522fd..a6b1c67 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/SectionsList.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/SectionsList.kt @@ -8,27 +8,27 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp -import com.developersbreach.kotlindictionarymultiplatform.data.detail.model.KotlinTopicDetails +import com.developersbreach.kotlindictionarymultiplatform.data.detail.model.Section import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.CodeExampleBox @Composable -fun SectionsList(topic: KotlinTopicDetails) { - topic.sections.forEach { section -> - section.heading?.let { - Text(it, style = MaterialTheme.typography.headlineLarge, color = MaterialTheme.colorScheme.onPrimary) - Spacer(Modifier.height(4.dp)) - } - section.content?.let { - Text(it, style = MaterialTheme.typography.bodyMedium) - Spacer(Modifier.height(8.dp)) - } - section.codeExamples.forEach { example -> - example.description?.let { - Text(it, fontWeight = FontWeight.Bold, style = MaterialTheme.typography.bodyMedium) - } - Spacer(Modifier.height(16.dp)) - CodeExampleBox(code = example.code) - Spacer(Modifier.height(16.dp)) +fun SectionBlock(section: Section) { + section.heading?.let { + Text(it, style = MaterialTheme.typography.headlineLarge, color = MaterialTheme.colorScheme.onPrimary) + Spacer(Modifier.height(4.dp)) + } + + section.content?.let { + Text(it, style = MaterialTheme.typography.bodyMedium) + Spacer(Modifier.height(8.dp)) + } + + section.codeExamples.forEach { example -> + example.description?.let { + Text(it, fontWeight = FontWeight.Bold, style = MaterialTheme.typography.bodyMedium) } + Spacer(Modifier.height(16.dp)) + CodeExampleBox(code = example.code) + Spacer(Modifier.height(16.dp)) } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/SyntaxSection.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/SyntaxSection.kt index 2ad56a3..ce8a85a 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/SyntaxSection.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/SyntaxSection.kt @@ -15,17 +15,17 @@ import org.jetbrains.compose.resources.stringResource @Composable fun SyntaxSection(topic: KotlinTopicDetails) { - if (topic.syntax.signature.isNotBlank()) { - Text(stringResource(Res.string.syntax), style = MaterialTheme.typography.headlineLarge, color = MaterialTheme.colorScheme.onPrimary) + Text(stringResource(Res.string.syntax), style = MaterialTheme.typography.headlineLarge, color = MaterialTheme.colorScheme.onPrimary) + Spacer(Modifier.height(4.dp)) + Text(text = topic.syntax.signature, style = MaterialTheme.typography.bodyMedium) + + topic.syntax.notes?.let { Spacer(Modifier.height(4.dp)) - Text(text = topic.syntax.signature, style = MaterialTheme.typography.bodyMedium) - topic.syntax.notes?.let { - Spacer(Modifier.height(4.dp)) - Text( - text = stringResource(Res.string.notes_with_value, it), - style = MaterialTheme.typography.bodyMedium, - ) - } - Spacer(Modifier.height(16.dp)) + Text( + text = stringResource(Res.string.notes_with_value, it), + style = MaterialTheme.typography.bodyMedium, + ) } + + Spacer(Modifier.height(16.dp)) } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/TableOfContents.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/TableOfContents.kt index 4413978..91a5bfd 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/TableOfContents.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/TableOfContents.kt @@ -9,33 +9,26 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import com.developersbreach.kotlindictionarymultiplatform.data.detail.model.KotlinTopicDetails import kotlindictionarymultiplatform.composeapp.generated.resources.Res -import kotlindictionarymultiplatform.composeapp.generated.resources.introduction_bullet -import kotlindictionarymultiplatform.composeapp.generated.resources.pitfalls_bullet -import kotlindictionarymultiplatform.composeapp.generated.resources.related_topics_bullet -import kotlindictionarymultiplatform.composeapp.generated.resources.sections_bullet -import kotlindictionarymultiplatform.composeapp.generated.resources.syntax_bullet import kotlindictionarymultiplatform.composeapp.generated.resources.table_of_contents import org.jetbrains.compose.resources.stringResource @Composable -fun TableOfContents(topic: KotlinTopicDetails) { - val items = buildList { - add(stringResource(Res.string.introduction_bullet)) - if (topic.syntax.signature.isNotBlank()) add(stringResource(Res.string.syntax_bullet)) - if (topic.sections.isNotEmpty()) add(stringResource(Res.string.sections_bullet)) - if (topic.pitfalls.isNotEmpty()) add(stringResource(Res.string.pitfalls_bullet)) - if (topic.relatedTopics.isNotEmpty()) add(stringResource(Res.string.related_topics_bullet)) - } - - Text(text = stringResource(Res.string.table_of_contents), style = MaterialTheme.typography.titleLarge, color = MaterialTheme.colorScheme.onPrimary) +fun TableOfContents( + items: List>, + onClick: (Int) -> Unit, +) { + Text( + text = stringResource(Res.string.table_of_contents), + style = MaterialTheme.typography.titleLarge, + color = MaterialTheme.colorScheme.onPrimary, + ) Spacer(Modifier.height(4.dp)) - items.forEach { + items.forEach { (label, index) -> Text( - text = it, + text = label, modifier = Modifier - .clickable { /* scroll-to support later */ } + .clickable { onClick(index) } .padding(vertical = 4.dp), color = MaterialTheme.colorScheme.onSurface, ) From 372e7e05d7777d4775d51e15d64cbe8a0ae6e542 Mon Sep 17 00:00:00 2001 From: YugaJ7 Date: Thu, 5 Jun 2025 20:18:26 +0530 Subject: [PATCH 3/7] - Update previews for `TableOfContents` and `SectionsList`. --- .../kotlindictionarymultiplatform/previews/PreviewUtils.kt | 7 +++++++ .../previews/detail/SectionsListPreview.kt | 5 +++-- .../previews/detail/TableOfContentsPreview.kt | 7 +++++-- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/PreviewUtils.kt b/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/PreviewUtils.kt index f17da62..d07a7cb 100644 --- a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/PreviewUtils.kt +++ b/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/PreviewUtils.kt @@ -52,4 +52,11 @@ fun sampleTopicList(): List = listOf( Topic("Coroutines"), Topic("Lambdas"), Topic("Sealed Classes"), +) + +val faketopiclist = listOf( + "Introduction" to 0, + "Examples" to 1, + "Use Cases" to 2, + "Best Practices" to 3, ) \ No newline at end of file diff --git a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/SectionsListPreview.kt b/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/SectionsListPreview.kt index 5fa52ca..b484fad 100644 --- a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/SectionsListPreview.kt +++ b/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/SectionsListPreview.kt @@ -3,13 +3,14 @@ package com.developersbreach.kotlindictionarymultiplatform.previews.detail import androidx.compose.runtime.Composable import androidx.compose.ui.tooling.preview.PreviewLightDark import com.developersbreach.kotlindictionarymultiplatform.previews.fakeTopicDetails -import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.components.SectionsList +import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.components.SectionBlock import com.developersbreach.kotlindictionarymultiplatform.ui.theme.KotlinDictionaryTheme @PreviewLightDark @Composable fun SectionsListPreview() { + val section = fakeTopicDetails().sections.first() KotlinDictionaryTheme { - SectionsList(topic = fakeTopicDetails()) + SectionBlock(section = section) } } \ No newline at end of file diff --git a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/TableOfContentsPreview.kt b/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/TableOfContentsPreview.kt index b9e22c9..8bdf97c 100644 --- a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/TableOfContentsPreview.kt +++ b/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/TableOfContentsPreview.kt @@ -2,7 +2,7 @@ package com.developersbreach.kotlindictionarymultiplatform.previews.detail import androidx.compose.runtime.Composable import androidx.compose.ui.tooling.preview.PreviewLightDark -import com.developersbreach.kotlindictionarymultiplatform.previews.fakeTopicDetails +import com.developersbreach.kotlindictionarymultiplatform.previews.faketopiclist import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.components.TableOfContents import com.developersbreach.kotlindictionarymultiplatform.ui.theme.KotlinDictionaryTheme @@ -10,6 +10,9 @@ import com.developersbreach.kotlindictionarymultiplatform.ui.theme.KotlinDiction @Composable fun TableOfContentsPreview() { KotlinDictionaryTheme { - TableOfContents(topic = fakeTopicDetails()) + TableOfContents( + items = faketopiclist, + onClick = {}, + ) } } \ No newline at end of file From 31a5e050ca3a3232fac48e248d8e3375fb0ab130 Mon Sep 17 00:00:00 2001 From: YugaJ7 Date: Sat, 7 Jun 2025 19:53:51 +0530 Subject: [PATCH 4/7] Tried isolating the ViewModel/UI --- .../ui/screens/detail/DetailContent.kt | 27 ++++++------ .../ui/screens/detail/DetailViewModel.kt | 41 +++++++++++++++++-- .../detail/components/IntroductionSection.kt | 5 +-- 3 files changed, 55 insertions(+), 18 deletions(-) diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailContent.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailContent.kt index f3046e6..e148fb4 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailContent.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailContent.kt @@ -3,6 +3,7 @@ package com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.runtime.Composable import androidx.compose.runtime.rememberCoroutineScope @@ -31,24 +32,26 @@ fun DetailContent( ) { val listState = rememberLazyListState() val coroutineScope = rememberCoroutineScope() - - val tocItems = buildList { - var index = 1 - add(stringResource(Res.string.introduction_bullet) to index++) - if (topic.syntax.signature.isNotBlank()) add(stringResource(Res.string.syntax_bullet) to index++) - topic.sections.forEach { section -> - section.heading?.let { add(stringResource(Res.string.bullet_item, it) to index++) } - } - if (topic.pitfalls.isNotEmpty()) add(stringResource(Res.string.pitfalls_bullet) to index++) - if (topic.relatedTopics.isNotEmpty()) add(stringResource(Res.string.related_topics_bullet) to index) - } - + val tocItems = list(topic) LazyColumn( state = listState, modifier = modifier .fillMaxSize() .padding(horizontal = 16.dp), ) { + items( + tocItems + ){ + + when(it){ + DetailViewModel.ItemTableOfContent.Introduction(intro = topic.intro) -> IntroductionSection(it.) + DetailViewModel.ItemTableOfContent.Pitfall -> SyntaxSection(it.) + DetailViewModel.ItemTableOfContent.RelatedTopic -> TODO() + is DetailViewModel.ItemTableOfContent.Section -> TODO() + DetailViewModel.ItemTableOfContent.Syntax -> TODO() + } + } + // Table of Contents item { TableOfContents( diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailViewModel.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailViewModel.kt index 3525326..320888c 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailViewModel.kt @@ -6,12 +6,13 @@ import androidx.lifecycle.viewModelScope import androidx.navigation.toRoute import com.developersbreach.kotlindictionarymultiplatform.Log import com.developersbreach.kotlindictionarymultiplatform.data.detail.model.KotlinTopicDetails -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.launch import com.developersbreach.kotlindictionarymultiplatform.data.detail.repository.DetailRepository import com.developersbreach.kotlindictionarymultiplatform.ui.components.UiState import com.developersbreach.kotlindictionarymultiplatform.ui.navigation.AppDestinations +import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.DetailViewModel.ItemTableOfContent +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.launch import kotlinx.io.IOException class DetailViewModel( @@ -40,4 +41,38 @@ class DetailViewModel( ifRight = { UiState.Success(it) }, ) } + + + +// data class ItemTableOfContent( +// val index : Int, +// val isVisible : Boolean, +// ) + + sealed class ItemTableOfContent{ + // abstract val index : Int + data class Introduction(val intro : String):ItemTableOfContent() + data object Syntax: ItemTableOfContent() + data class Section ( + val index : Int + ):ItemTableOfContent() + data object Pitfall: ItemTableOfContent() + data object RelatedTopic: ItemTableOfContent() + } +} + +fun list(topic: KotlinTopicDetails): List { + val tocItems = buildList { + //add(stringResource(Res.string.introduction_bullet) to index++) + add(ItemTableOfContent.Introduction(intro = topic.intro)) + if (topic.syntax.signature.isNotBlank()) add(ItemTableOfContent.Syntax) + topic.sections.forEachIndexed {index, section -> + section.heading?.let { + add(ItemTableOfContent.Section(index)) + } + } + if (topic.pitfalls.isNotEmpty()) add(ItemTableOfContent.Pitfall) + if (topic.relatedTopics.isNotEmpty()) add(ItemTableOfContent.RelatedTopic) + } + return tocItems } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/IntroductionSection.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/IntroductionSection.kt index 153aa3e..4893fb0 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/IntroductionSection.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/IntroductionSection.kt @@ -7,15 +7,14 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp -import com.developersbreach.kotlindictionarymultiplatform.data.detail.model.KotlinTopicDetails import kotlindictionarymultiplatform.composeapp.generated.resources.Res import kotlindictionarymultiplatform.composeapp.generated.resources.introduction import org.jetbrains.compose.resources.stringResource @Composable -fun IntroductionSection(topic: KotlinTopicDetails) { +fun IntroductionSection(intro : String) { Text(stringResource(Res.string.introduction), style = MaterialTheme.typography.headlineLarge, color = MaterialTheme.colorScheme.onPrimary) Spacer(Modifier.height(4.dp)) - Text(text = topic.intro, style = MaterialTheme.typography.bodyMedium) + Text(text = intro, style = MaterialTheme.typography.bodyMedium) Spacer(Modifier.height(16.dp)) } \ No newline at end of file From b2265d70582bb67bd280075d7359f7dff07e4577 Mon Sep 17 00:00:00 2001 From: Raj Date: Mon, 9 Jun 2025 19:25:46 +0530 Subject: [PATCH 5/7] Delete redundant granular ui previews and components --- .../previews/detail/DetailContentPreview.kt | 15 ---- .../previews/detail/DetailTopAppBarPreview.kt | 15 ---- .../detail/IntroductionSectionPreview.kt | 15 ---- .../detail/PitfallsSectionPreviews.kt | 15 ---- .../detail/RelatedTopicsSectionPreview.kt | 15 ---- .../previews/detail/SectionsListPreview.kt | 16 ---- .../previews/detail/SyntaxSectionPreview.kt | 15 ---- .../previews/detail/TableOfContentsPreview.kt | 18 ---- .../ui/screens/detail/DetailContent.kt | 86 ------------------- .../detail/components/IntroductionSection.kt | 20 ----- .../detail/components/PitfallsSection.kt | 26 ------ .../detail/components/RelatedTopicsSection.kt | 24 ------ .../screens/detail/components/SectionsList.kt | 34 -------- .../detail/components/SyntaxSection.kt | 31 ------- .../detail/components/TableOfContents.kt | 37 -------- 15 files changed, 382 deletions(-) delete mode 100644 composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/DetailContentPreview.kt delete mode 100644 composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/DetailTopAppBarPreview.kt delete mode 100644 composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/IntroductionSectionPreview.kt delete mode 100644 composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/PitfallsSectionPreviews.kt delete mode 100644 composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/RelatedTopicsSectionPreview.kt delete mode 100644 composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/SectionsListPreview.kt delete mode 100644 composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/SyntaxSectionPreview.kt delete mode 100644 composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/TableOfContentsPreview.kt delete mode 100644 composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailContent.kt delete mode 100644 composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/IntroductionSection.kt delete mode 100644 composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/PitfallsSection.kt delete mode 100644 composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/RelatedTopicsSection.kt delete mode 100644 composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/SectionsList.kt delete mode 100644 composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/SyntaxSection.kt delete mode 100644 composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/TableOfContents.kt diff --git a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/DetailContentPreview.kt b/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/DetailContentPreview.kt deleted file mode 100644 index 1506c42..0000000 --- a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/DetailContentPreview.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.developersbreach.kotlindictionarymultiplatform.previews.detail - -import androidx.compose.runtime.Composable -import androidx.compose.ui.tooling.preview.PreviewLightDark -import com.developersbreach.kotlindictionarymultiplatform.previews.fakeTopicDetails -import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.DetailContent -import com.developersbreach.kotlindictionarymultiplatform.ui.theme.KotlinDictionaryTheme - -@PreviewLightDark -@Composable -fun DetailContentPreview() { - KotlinDictionaryTheme { - DetailContent(topic = fakeTopicDetails()) - } -} \ No newline at end of file diff --git a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/DetailTopAppBarPreview.kt b/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/DetailTopAppBarPreview.kt deleted file mode 100644 index 809203a..0000000 --- a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/DetailTopAppBarPreview.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.developersbreach.kotlindictionarymultiplatform.previews.detail - -import androidx.compose.runtime.Composable -import androidx.compose.ui.tooling.preview.PreviewLightDark -import com.developersbreach.kotlindictionarymultiplatform.previews.fakeTopicDetails -import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.DetailTopBar -import com.developersbreach.kotlindictionarymultiplatform.ui.theme.KotlinDictionaryTheme - -@PreviewLightDark -@Composable -fun DetailTopBarPreview() { - KotlinDictionaryTheme { - DetailTopBar(title = fakeTopicDetails().topicName) - } -} \ No newline at end of file diff --git a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/IntroductionSectionPreview.kt b/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/IntroductionSectionPreview.kt deleted file mode 100644 index 0452750..0000000 --- a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/IntroductionSectionPreview.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.developersbreach.kotlindictionarymultiplatform.previews.detail - -import androidx.compose.runtime.Composable -import androidx.compose.ui.tooling.preview.PreviewLightDark -import com.developersbreach.kotlindictionarymultiplatform.previews.fakeTopicDetails -import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.components.IntroductionSection -import com.developersbreach.kotlindictionarymultiplatform.ui.theme.KotlinDictionaryTheme - -@PreviewLightDark -@Composable -fun IntroductionSectionPreview() { - KotlinDictionaryTheme { - IntroductionSection(topic = fakeTopicDetails()) - } -} \ No newline at end of file diff --git a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/PitfallsSectionPreviews.kt b/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/PitfallsSectionPreviews.kt deleted file mode 100644 index a37a2cb..0000000 --- a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/PitfallsSectionPreviews.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.developersbreach.kotlindictionarymultiplatform.previews.detail - -import androidx.compose.runtime.Composable -import androidx.compose.ui.tooling.preview.PreviewLightDark -import com.developersbreach.kotlindictionarymultiplatform.previews.fakeTopicDetails -import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.components.PitfallsSection -import com.developersbreach.kotlindictionarymultiplatform.ui.theme.KotlinDictionaryTheme - -@PreviewLightDark -@Composable -fun PitfallsSectionPreview() { - KotlinDictionaryTheme { - PitfallsSection(topic = fakeTopicDetails()) - } -} \ No newline at end of file diff --git a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/RelatedTopicsSectionPreview.kt b/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/RelatedTopicsSectionPreview.kt deleted file mode 100644 index c9be028..0000000 --- a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/RelatedTopicsSectionPreview.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.developersbreach.kotlindictionarymultiplatform.previews.detail - -import androidx.compose.runtime.Composable -import androidx.compose.ui.tooling.preview.PreviewLightDark -import com.developersbreach.kotlindictionarymultiplatform.previews.fakeTopicDetails -import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.components.RelatedTopicsSection -import com.developersbreach.kotlindictionarymultiplatform.ui.theme.KotlinDictionaryTheme - -@PreviewLightDark -@Composable -fun RelatedTopicsSectionPreview() { - KotlinDictionaryTheme { - RelatedTopicsSection(topic = fakeTopicDetails()) - } -} \ No newline at end of file diff --git a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/SectionsListPreview.kt b/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/SectionsListPreview.kt deleted file mode 100644 index b484fad..0000000 --- a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/SectionsListPreview.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.developersbreach.kotlindictionarymultiplatform.previews.detail - -import androidx.compose.runtime.Composable -import androidx.compose.ui.tooling.preview.PreviewLightDark -import com.developersbreach.kotlindictionarymultiplatform.previews.fakeTopicDetails -import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.components.SectionBlock -import com.developersbreach.kotlindictionarymultiplatform.ui.theme.KotlinDictionaryTheme - -@PreviewLightDark -@Composable -fun SectionsListPreview() { - val section = fakeTopicDetails().sections.first() - KotlinDictionaryTheme { - SectionBlock(section = section) - } -} \ No newline at end of file diff --git a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/SyntaxSectionPreview.kt b/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/SyntaxSectionPreview.kt deleted file mode 100644 index df89e19..0000000 --- a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/SyntaxSectionPreview.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.developersbreach.kotlindictionarymultiplatform.previews.detail - -import androidx.compose.runtime.Composable -import androidx.compose.ui.tooling.preview.PreviewLightDark -import com.developersbreach.kotlindictionarymultiplatform.previews.fakeTopicDetails -import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.components.SyntaxSection -import com.developersbreach.kotlindictionarymultiplatform.ui.theme.KotlinDictionaryTheme - -@PreviewLightDark -@Composable -fun SyntaxSectionPreview() { - KotlinDictionaryTheme { - SyntaxSection(topic = fakeTopicDetails()) - } -} \ No newline at end of file diff --git a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/TableOfContentsPreview.kt b/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/TableOfContentsPreview.kt deleted file mode 100644 index 8bdf97c..0000000 --- a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/TableOfContentsPreview.kt +++ /dev/null @@ -1,18 +0,0 @@ -package com.developersbreach.kotlindictionarymultiplatform.previews.detail - -import androidx.compose.runtime.Composable -import androidx.compose.ui.tooling.preview.PreviewLightDark -import com.developersbreach.kotlindictionarymultiplatform.previews.faketopiclist -import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.components.TableOfContents -import com.developersbreach.kotlindictionarymultiplatform.ui.theme.KotlinDictionaryTheme - -@PreviewLightDark -@Composable -fun TableOfContentsPreview() { - KotlinDictionaryTheme { - TableOfContents( - items = faketopiclist, - onClick = {}, - ) - } -} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailContent.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailContent.kt deleted file mode 100644 index e148fb4..0000000 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailContent.kt +++ /dev/null @@ -1,86 +0,0 @@ -package com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail - -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.foundation.lazy.rememberLazyListState -import androidx.compose.runtime.Composable -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import com.developersbreach.kotlindictionarymultiplatform.data.detail.model.KotlinTopicDetails -import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.components.IntroductionSection -import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.components.PitfallsSection -import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.components.RelatedTopicsSection -import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.components.SectionBlock -import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.components.SyntaxSection -import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.components.TableOfContents -import kotlindictionarymultiplatform.composeapp.generated.resources.Res -import kotlindictionarymultiplatform.composeapp.generated.resources.bullet_item -import kotlindictionarymultiplatform.composeapp.generated.resources.introduction_bullet -import kotlindictionarymultiplatform.composeapp.generated.resources.pitfalls_bullet -import kotlindictionarymultiplatform.composeapp.generated.resources.related_topics_bullet -import kotlindictionarymultiplatform.composeapp.generated.resources.syntax_bullet -import kotlinx.coroutines.launch -import org.jetbrains.compose.resources.stringResource - -@Composable -fun DetailContent( - topic: KotlinTopicDetails, - modifier: Modifier = Modifier, -) { - val listState = rememberLazyListState() - val coroutineScope = rememberCoroutineScope() - val tocItems = list(topic) - LazyColumn( - state = listState, - modifier = modifier - .fillMaxSize() - .padding(horizontal = 16.dp), - ) { - items( - tocItems - ){ - - when(it){ - DetailViewModel.ItemTableOfContent.Introduction(intro = topic.intro) -> IntroductionSection(it.) - DetailViewModel.ItemTableOfContent.Pitfall -> SyntaxSection(it.) - DetailViewModel.ItemTableOfContent.RelatedTopic -> TODO() - is DetailViewModel.ItemTableOfContent.Section -> TODO() - DetailViewModel.ItemTableOfContent.Syntax -> TODO() - } - } - - // Table of Contents - item { - TableOfContents( - items = tocItems, - onClick = { index -> - coroutineScope.launch { - listState.animateScrollToItem(index) - } - }, - ) - } - - // Sections - item { IntroductionSection(topic) } - - if (topic.syntax.signature.isNotBlank()) { - item { SyntaxSection(topic) } - } - - topic.sections.forEach { section -> - item { SectionBlock(section) } - } - - if (topic.pitfalls.isNotEmpty()) { - item { PitfallsSection(topic) } - } - - if (topic.relatedTopics.isNotEmpty()) { - item { RelatedTopicsSection(topic) } - } - } -} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/IntroductionSection.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/IntroductionSection.kt deleted file mode 100644 index 4893fb0..0000000 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/IntroductionSection.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.components - -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.height -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import kotlindictionarymultiplatform.composeapp.generated.resources.Res -import kotlindictionarymultiplatform.composeapp.generated.resources.introduction -import org.jetbrains.compose.resources.stringResource - -@Composable -fun IntroductionSection(intro : String) { - Text(stringResource(Res.string.introduction), style = MaterialTheme.typography.headlineLarge, color = MaterialTheme.colorScheme.onPrimary) - Spacer(Modifier.height(4.dp)) - Text(text = intro, style = MaterialTheme.typography.bodyMedium) - Spacer(Modifier.height(16.dp)) -} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/PitfallsSection.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/PitfallsSection.kt deleted file mode 100644 index 1ee8b88..0000000 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/PitfallsSection.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.components - -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.height -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import com.developersbreach.kotlindictionarymultiplatform.data.detail.model.KotlinTopicDetails -import kotlindictionarymultiplatform.composeapp.generated.resources.Res -import kotlindictionarymultiplatform.composeapp.generated.resources.bullet_item -import kotlindictionarymultiplatform.composeapp.generated.resources.pitfalls -import org.jetbrains.compose.resources.stringResource - -@Composable -fun PitfallsSection(topic: KotlinTopicDetails) { - Text(stringResource(Res.string.pitfalls), style = MaterialTheme.typography.headlineLarge, color = MaterialTheme.colorScheme.onPrimary) - Spacer(Modifier.height(4.dp)) - - topic.pitfalls.forEach { - Text(text = stringResource(Res.string.bullet_item, it), style = MaterialTheme.typography.bodyMedium) - } - - Spacer(Modifier.height(16.dp)) -} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/RelatedTopicsSection.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/RelatedTopicsSection.kt deleted file mode 100644 index 732c6f0..0000000 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/RelatedTopicsSection.kt +++ /dev/null @@ -1,24 +0,0 @@ -package com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.components - -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.height -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import com.developersbreach.kotlindictionarymultiplatform.data.detail.model.KotlinTopicDetails -import kotlindictionarymultiplatform.composeapp.generated.resources.Res -import kotlindictionarymultiplatform.composeapp.generated.resources.bullet_item -import kotlindictionarymultiplatform.composeapp.generated.resources.related_topics -import org.jetbrains.compose.resources.stringResource - -@Composable -fun RelatedTopicsSection(topic: KotlinTopicDetails) { - Text(stringResource(Res.string.related_topics), style = MaterialTheme.typography.headlineLarge, color = MaterialTheme.colorScheme.onPrimary) - Spacer(Modifier.height(4.dp)) - - topic.relatedTopics.forEach { - Text(text = stringResource(Res.string.bullet_item, it), style = MaterialTheme.typography.bodyMedium) - } -} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/SectionsList.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/SectionsList.kt deleted file mode 100644 index a6b1c67..0000000 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/SectionsList.kt +++ /dev/null @@ -1,34 +0,0 @@ -package com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.components - -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.height -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import com.developersbreach.kotlindictionarymultiplatform.data.detail.model.Section -import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.CodeExampleBox - -@Composable -fun SectionBlock(section: Section) { - section.heading?.let { - Text(it, style = MaterialTheme.typography.headlineLarge, color = MaterialTheme.colorScheme.onPrimary) - Spacer(Modifier.height(4.dp)) - } - - section.content?.let { - Text(it, style = MaterialTheme.typography.bodyMedium) - Spacer(Modifier.height(8.dp)) - } - - section.codeExamples.forEach { example -> - example.description?.let { - Text(it, fontWeight = FontWeight.Bold, style = MaterialTheme.typography.bodyMedium) - } - Spacer(Modifier.height(16.dp)) - CodeExampleBox(code = example.code) - Spacer(Modifier.height(16.dp)) - } -} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/SyntaxSection.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/SyntaxSection.kt deleted file mode 100644 index ce8a85a..0000000 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/SyntaxSection.kt +++ /dev/null @@ -1,31 +0,0 @@ -package com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.components - -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.height -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import com.developersbreach.kotlindictionarymultiplatform.data.detail.model.KotlinTopicDetails -import kotlindictionarymultiplatform.composeapp.generated.resources.Res -import kotlindictionarymultiplatform.composeapp.generated.resources.notes_with_value -import kotlindictionarymultiplatform.composeapp.generated.resources.syntax -import org.jetbrains.compose.resources.stringResource - -@Composable -fun SyntaxSection(topic: KotlinTopicDetails) { - Text(stringResource(Res.string.syntax), style = MaterialTheme.typography.headlineLarge, color = MaterialTheme.colorScheme.onPrimary) - Spacer(Modifier.height(4.dp)) - Text(text = topic.syntax.signature, style = MaterialTheme.typography.bodyMedium) - - topic.syntax.notes?.let { - Spacer(Modifier.height(4.dp)) - Text( - text = stringResource(Res.string.notes_with_value, it), - style = MaterialTheme.typography.bodyMedium, - ) - } - - Spacer(Modifier.height(16.dp)) -} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/TableOfContents.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/TableOfContents.kt deleted file mode 100644 index 91a5bfd..0000000 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/components/TableOfContents.kt +++ /dev/null @@ -1,37 +0,0 @@ -package com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.components - -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import kotlindictionarymultiplatform.composeapp.generated.resources.Res -import kotlindictionarymultiplatform.composeapp.generated.resources.table_of_contents -import org.jetbrains.compose.resources.stringResource - -@Composable -fun TableOfContents( - items: List>, - onClick: (Int) -> Unit, -) { - Text( - text = stringResource(Res.string.table_of_contents), - style = MaterialTheme.typography.titleLarge, - color = MaterialTheme.colorScheme.onPrimary, - ) - Spacer(Modifier.height(4.dp)) - items.forEach { (label, index) -> - Text( - text = label, - modifier = Modifier - .clickable { onClick(index) } - .padding(vertical = 4.dp), - color = MaterialTheme.colorScheme.onSurface, - ) - } - Spacer(Modifier.height(16.dp)) -} \ No newline at end of file From 4bacb59e659c75d71463a0d67d143e5b1127229b Mon Sep 17 00:00:00 2001 From: Raj Date: Mon, 9 Jun 2025 19:27:41 +0530 Subject: [PATCH 6/7] Improve table of contents implementation/readability and render logic with better mapping/configuration --- .../previews/detail/DetailScreenPreview.kt | 6 +- .../ui/navigation/AppNavigation.kt | 5 +- .../ui/screens/detail/DetailScreen.kt | 12 +- .../screens/detail/DetailScreenComponents.kt | 136 ++++++++++++++++++ .../ui/screens/detail/DetailScreenUI.kt | 82 ++++++++++- .../ui/screens/detail/DetailTopAppBar.kt | 7 +- .../ui/screens/detail/DetailUiState.kt | 108 ++++++++++++++ .../ui/screens/detail/DetailViewModel.kt | 42 +----- 8 files changed, 348 insertions(+), 50 deletions(-) create mode 100644 composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreenComponents.kt create mode 100644 composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailUiState.kt diff --git a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/DetailScreenPreview.kt b/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/DetailScreenPreview.kt index 71b7ea4..05ad985 100644 --- a/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/DetailScreenPreview.kt +++ b/composeApp/src/androidMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/previews/detail/DetailScreenPreview.kt @@ -4,12 +4,16 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.tooling.preview.PreviewLightDark import com.developersbreach.kotlindictionarymultiplatform.previews.fakeTopicDetails import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.DetailScreenUI +import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.toDetailUi import com.developersbreach.kotlindictionarymultiplatform.ui.theme.KotlinDictionaryTheme @PreviewLightDark @Composable fun DetailScreenPreview() { KotlinDictionaryTheme { - DetailScreenUI(topic = fakeTopicDetails()) + DetailScreenUI( + detailUiState = fakeTopicDetails().toDetailUi(), + navigateUp = {}, + ) } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/navigation/AppNavigation.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/navigation/AppNavigation.kt index 0df1a95..547e993 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/navigation/AppNavigation.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/navigation/AppNavigation.kt @@ -34,7 +34,10 @@ fun AppNavigation( composable { val viewModel: DetailViewModel = koinViewModel() - DetailScreen(viewModel = viewModel) + DetailScreen( + viewModel = viewModel, + navigateUp = { navController.navigateUp() }, + ) } } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreen.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreen.kt index 10acca5..779e70d 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreen.kt @@ -6,10 +6,16 @@ import androidx.compose.runtime.getValue import com.developersbreach.kotlindictionarymultiplatform.ui.components.UiStateHandler @Composable -fun DetailScreen(viewModel: DetailViewModel) { +fun DetailScreen( + viewModel: DetailViewModel, + navigateUp: () -> Unit, +) { val topicState by viewModel.state.collectAsState() - UiStateHandler(uiState = topicState) { topic -> - DetailScreenUI(topic) + UiStateHandler(uiState = topicState) { detailUiState -> + DetailScreenUI( + detailUiState = detailUiState, + navigateUp = navigateUp, + ) } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreenComponents.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreenComponents.kt new file mode 100644 index 0000000..665b795 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreenComponents.kt @@ -0,0 +1,136 @@ +package com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.height +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import com.developersbreach.kotlindictionarymultiplatform.data.detail.model.Section +import com.developersbreach.kotlindictionarymultiplatform.data.detail.model.Syntax +import kotlindictionarymultiplatform.composeapp.generated.resources.Res +import kotlindictionarymultiplatform.composeapp.generated.resources.bullet_item +import kotlindictionarymultiplatform.composeapp.generated.resources.introduction +import kotlindictionarymultiplatform.composeapp.generated.resources.notes_with_value +import kotlindictionarymultiplatform.composeapp.generated.resources.pitfalls +import kotlindictionarymultiplatform.composeapp.generated.resources.related_topics +import kotlindictionarymultiplatform.composeapp.generated.resources.syntax +import org.jetbrains.compose.resources.stringResource + +@Composable +fun TableOfContents( + item: String, + onClick: () -> Unit, +) { + Text( + text = item, + modifier = Modifier.clickable { onClick() }, + color = MaterialTheme.colorScheme.onSurface, + ) + Spacer(Modifier.height(4.dp)) +} + +@Composable +fun IntroductionSection( + intro: String, +) { + Text( + text = stringResource(resource = Res.string.introduction), + style = MaterialTheme.typography.headlineLarge, + color = MaterialTheme.colorScheme.onPrimary, + ) + Spacer(Modifier.height(4.dp)) + Text( + text = intro, + style = MaterialTheme.typography.bodyMedium, + ) + Spacer(Modifier.height(16.dp)) +} + +@Composable +fun SyntaxSection( + syntax: Syntax, +) { + Text( + text = stringResource(resource = Res.string.syntax), + style = MaterialTheme.typography.headlineLarge, + color = MaterialTheme.colorScheme.onPrimary, + ) + Spacer(Modifier.height(4.dp)) + Text( + text = syntax.signature, + style = MaterialTheme.typography.bodyMedium, + ) + syntax.notes?.let { + Spacer(Modifier.height(4.dp)) + Text( + text = stringResource(Res.string.notes_with_value, it), + style = MaterialTheme.typography.bodyMedium, + ) + } + Spacer(Modifier.height(16.dp)) +} + +@Composable +fun SectionBlock( + section: Section, +) { + section.heading?.let { + Text(it, style = MaterialTheme.typography.headlineLarge, color = MaterialTheme.colorScheme.onPrimary) + Spacer(Modifier.height(4.dp)) + } + + section.content?.let { + Text(it, style = MaterialTheme.typography.bodyMedium) + Spacer(Modifier.height(8.dp)) + } + + section.codeExamples.forEach { example -> + example.description?.let { + Text(it, fontWeight = FontWeight.Bold, style = MaterialTheme.typography.bodyMedium) + } + Spacer(Modifier.height(16.dp)) + CodeExampleBox(code = example.code) + Spacer(Modifier.height(16.dp)) + } +} + +@Composable +fun PitfallsSection( + pitfalls: List, +) { + Text( + text = stringResource(resource = Res.string.pitfalls), + style = MaterialTheme.typography.headlineLarge, + color = MaterialTheme.colorScheme.onPrimary, + ) + Spacer(Modifier.height(4.dp)) + pitfalls.forEach { + Text( + text = stringResource(Res.string.bullet_item, it), + style = MaterialTheme.typography.bodyMedium, + ) + } + Spacer(Modifier.height(16.dp)) +} + +@Composable +fun RelatedTopicsSection( + relatedTopics: List, +) { + Text( + text = stringResource(resource = Res.string.related_topics), + style = MaterialTheme.typography.headlineLarge, + color = MaterialTheme.colorScheme.onPrimary, + ) + Spacer(Modifier.height(4.dp)) + relatedTopics.forEach { + Text( + text = stringResource(Res.string.bullet_item, it), + style = MaterialTheme.typography.bodyMedium, + ) + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreenUI.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreenUI.kt index c741842..8c63f81 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreenUI.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreenUI.kt @@ -1,21 +1,95 @@ package com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier -import com.developersbreach.kotlindictionarymultiplatform.data.detail.model.KotlinTopicDetails +import androidx.compose.ui.unit.dp +import kotlindictionarymultiplatform.composeapp.generated.resources.Res +import kotlindictionarymultiplatform.composeapp.generated.resources.table_of_contents +import kotlinx.coroutines.launch +import org.jetbrains.compose.resources.stringResource @Composable -fun DetailScreenUI(topic: KotlinTopicDetails) { +fun DetailScreenUI( + detailUiState: DetailUiState, + navigateUp: () -> Unit, +) { Scaffold( - topBar = { DetailTopBar(title = topic.topicName) }, + topBar = { + DetailTopBar( + title = detailUiState.topicName, + navigateUp = navigateUp, + ) + }, containerColor = MaterialTheme.colorScheme.background, ) { innerPadding -> DetailContent( - topic = topic, + detailUiState = detailUiState, modifier = Modifier.padding(innerPadding), ) } +} + +@Composable +private fun DetailContent( + detailUiState: DetailUiState, + modifier: Modifier = Modifier, +) { + val listState = rememberLazyListState() + val coroutineScope = rememberCoroutineScope() + + LazyColumn( + state = listState, + modifier = modifier + .fillMaxSize() + .padding(horizontal = 16.dp), + ) { + item { + Text( + text = stringResource(Res.string.table_of_contents), + style = MaterialTheme.typography.titleLarge, + color = MaterialTheme.colorScheme.onPrimary, + ) + Spacer(Modifier.height(4.dp)) + } + + items( + items = detailUiState.tocEntries, + ) { + TableOfContents( + item = stringResource(it.titleRes, *it.formatArgs.toTypedArray()), + onClick = { + coroutineScope.launch { + listState.animateScrollToItem(it.destinationIndex) + } + }, + ) + } + + item { + Spacer(Modifier.height(16.dp)) + } + + items( + items = detailUiState.contentItems, + ) { toc: ItemTableOfContent -> + when (toc) { + is ItemTableOfContent.Introduction -> IntroductionSection(toc.intro) + is ItemTableOfContent.Syntax -> SyntaxSection(toc.syntax) + is ItemTableOfContent.Section -> SectionBlock(toc.sections) + is ItemTableOfContent.Pitfall -> PitfallsSection(toc.pitfalls) + is ItemTableOfContent.RelatedTopic -> RelatedTopicsSection(toc.relatedTopics) + } + } + } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailTopAppBar.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailTopAppBar.kt index 16736f5..28f53d7 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailTopAppBar.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailTopAppBar.kt @@ -18,7 +18,10 @@ import org.jetbrains.compose.resources.stringResource @OptIn(ExperimentalMaterial3Api::class) @Composable -fun DetailTopBar(title: String) { +fun DetailTopBar( + title: String, + navigateUp: () -> Unit, +) { TopAppBar( title = { Text( @@ -29,7 +32,7 @@ fun DetailTopBar(title: String) { ) }, navigationIcon = { - IconButton(onClick = { /* TODO: Navigate back */ }) { + IconButton(onClick = navigateUp) { Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = stringResource(Res.string.back)) } }, diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailUiState.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailUiState.kt new file mode 100644 index 0000000..a5354b5 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailUiState.kt @@ -0,0 +1,108 @@ +package com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail + +import com.developersbreach.kotlindictionarymultiplatform.data.detail.model.KotlinTopicDetails +import kotlindictionarymultiplatform.composeapp.generated.resources.Res +import kotlindictionarymultiplatform.composeapp.generated.resources.bullet_item +import kotlindictionarymultiplatform.composeapp.generated.resources.introduction_bullet +import kotlindictionarymultiplatform.composeapp.generated.resources.pitfalls_bullet +import kotlindictionarymultiplatform.composeapp.generated.resources.related_topics_bullet +import kotlindictionarymultiplatform.composeapp.generated.resources.syntax_bullet +import org.jetbrains.compose.resources.StringResource + +data class DetailUiState( + val tocEntries: List, + val contentItems: List, + val topicName: String, +) + +sealed class TocItem { + data object Header : TocItem() + + data class Toc( + val toc: ItemTableOfContent, + ) : TocItem() + + data class Content( + val toc: ItemTableOfContent, + ) : TocItem() +} + +data class TocEntry( + val titleRes: StringResource, + val formatArgs: List = emptyList(), + val destinationIndex: Int, +) + +sealed class ItemTableOfContent { + + abstract val title: StringResource + + data class Introduction( + val intro: String, + override val title: StringResource = Res.string.introduction_bullet, + ) : ItemTableOfContent() + + data class Syntax( + val syntax: com.developersbreach.kotlindictionarymultiplatform.data.detail.model.Syntax, + override val title: StringResource = Res.string.syntax_bullet, + ) : ItemTableOfContent() + + data class Section( + val index: Int, + val sections: com.developersbreach.kotlindictionarymultiplatform.data.detail.model.Section, + override val title: StringResource = Res.string.bullet_item, + ) : ItemTableOfContent() + + data class Pitfall( + val pitfalls: List, + override val title: StringResource = Res.string.pitfalls_bullet, + ) : ItemTableOfContent() + + data class RelatedTopic( + val relatedTopics: List, + override val title: StringResource = Res.string.related_topics_bullet, + ) : ItemTableOfContent() +} + +fun KotlinTopicDetails.toDetailUi(): DetailUiState { + val contentList = this.toContents() + + val flatList = buildList { + this.add(TocItem.Header) + contentList.forEach { this.add(TocItem.Toc(it)) } + contentList.forEach { this.add(TocItem.Content(it)) } + } + + val tocEntries = contentList.map { tocItem -> + TocEntry( + titleRes = tocItem.title, + formatArgs = when (tocItem) { + is ItemTableOfContent.Section -> listOf(tocItem.sections.heading ?: "") + else -> emptyList() + }, + destinationIndex = flatList.indexOfFirst { + it is TocItem.Content && it.toc == tocItem + }, + ) + } + + return DetailUiState( + tocEntries = tocEntries, + contentItems = contentList, + topicName = topicName, + ) +} + +private fun KotlinTopicDetails.toContents(): List { + return buildList { + add(ItemTableOfContent.Introduction(intro = intro)) + if (syntax.signature.isNotBlank()) add(ItemTableOfContent.Syntax(syntax)) + sections.forEachIndexed { index, section -> + section.heading?.let { + add(ItemTableOfContent.Section(index, section)) + } + } + if (pitfalls.isNotEmpty()) add(ItemTableOfContent.Pitfall(pitfalls)) + if (relatedTopics.isNotEmpty()) add(ItemTableOfContent.RelatedTopic(relatedTopics)) + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailViewModel.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailViewModel.kt index 320888c..7801e49 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailViewModel.kt @@ -5,11 +5,9 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import androidx.navigation.toRoute import com.developersbreach.kotlindictionarymultiplatform.Log -import com.developersbreach.kotlindictionarymultiplatform.data.detail.model.KotlinTopicDetails import com.developersbreach.kotlindictionarymultiplatform.data.detail.repository.DetailRepository import com.developersbreach.kotlindictionarymultiplatform.ui.components.UiState import com.developersbreach.kotlindictionarymultiplatform.ui.navigation.AppDestinations -import com.developersbreach.kotlindictionarymultiplatform.ui.screens.detail.DetailViewModel.ItemTableOfContent import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.launch @@ -22,8 +20,8 @@ class DetailViewModel( private val topicId = savedStateHandle.toRoute().topicId - private val _state = MutableStateFlow>(UiState.Loading) - val state: StateFlow> = _state + private val _state = MutableStateFlow>(UiState.Loading) + val state: StateFlow> = _state init { viewModelScope.launch { @@ -38,41 +36,7 @@ class DetailViewModel( private suspend fun fetchTopic() { _state.value = repository.fetchTopic(topicId).fold( ifLeft = { UiState.Error(it) }, - ifRight = { UiState.Success(it) }, + ifRight = { UiState.Success(it.toDetailUi()) }, ) } - - - -// data class ItemTableOfContent( -// val index : Int, -// val isVisible : Boolean, -// ) - - sealed class ItemTableOfContent{ - // abstract val index : Int - data class Introduction(val intro : String):ItemTableOfContent() - data object Syntax: ItemTableOfContent() - data class Section ( - val index : Int - ):ItemTableOfContent() - data object Pitfall: ItemTableOfContent() - data object RelatedTopic: ItemTableOfContent() - } -} - -fun list(topic: KotlinTopicDetails): List { - val tocItems = buildList { - //add(stringResource(Res.string.introduction_bullet) to index++) - add(ItemTableOfContent.Introduction(intro = topic.intro)) - if (topic.syntax.signature.isNotBlank()) add(ItemTableOfContent.Syntax) - topic.sections.forEachIndexed {index, section -> - section.heading?.let { - add(ItemTableOfContent.Section(index)) - } - } - if (topic.pitfalls.isNotEmpty()) add(ItemTableOfContent.Pitfall) - if (topic.relatedTopics.isNotEmpty()) add(ItemTableOfContent.RelatedTopic) - } - return tocItems } \ No newline at end of file From 4aade5d04d5a27839f29cba6ec71a070944473e1 Mon Sep 17 00:00:00 2001 From: Raj Date: Mon, 9 Jun 2025 20:12:58 +0530 Subject: [PATCH 7/7] Fix ktlint violations --- .../screens/detail/DetailScreenComponents.kt | 32 +++++++++++++++---- .../ui/screens/detail/DetailScreenUI.kt | 5 ++- .../ui/screens/detail/DetailTopAppBar.kt | 5 ++- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreenComponents.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreenComponents.kt index 665b795..7f38b24 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreenComponents.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreenComponents.kt @@ -67,7 +67,10 @@ fun SyntaxSection( syntax.notes?.let { Spacer(Modifier.height(4.dp)) Text( - text = stringResource(Res.string.notes_with_value, it), + text = stringResource( + Res.string.notes_with_value, + it, + ), style = MaterialTheme.typography.bodyMedium, ) } @@ -79,18 +82,29 @@ fun SectionBlock( section: Section, ) { section.heading?.let { - Text(it, style = MaterialTheme.typography.headlineLarge, color = MaterialTheme.colorScheme.onPrimary) + Text( + text = it, + style = MaterialTheme.typography.headlineLarge, + color = MaterialTheme.colorScheme.onPrimary, + ) Spacer(Modifier.height(4.dp)) } section.content?.let { - Text(it, style = MaterialTheme.typography.bodyMedium) + Text( + text = it, + style = MaterialTheme.typography.bodyMedium, + ) Spacer(Modifier.height(8.dp)) } section.codeExamples.forEach { example -> example.description?.let { - Text(it, fontWeight = FontWeight.Bold, style = MaterialTheme.typography.bodyMedium) + Text( + text = it, + fontWeight = FontWeight.Bold, + style = MaterialTheme.typography.bodyMedium, + ) } Spacer(Modifier.height(16.dp)) CodeExampleBox(code = example.code) @@ -110,7 +124,10 @@ fun PitfallsSection( Spacer(Modifier.height(4.dp)) pitfalls.forEach { Text( - text = stringResource(Res.string.bullet_item, it), + text = stringResource( + Res.string.bullet_item, + it, + ), style = MaterialTheme.typography.bodyMedium, ) } @@ -129,7 +146,10 @@ fun RelatedTopicsSection( Spacer(Modifier.height(4.dp)) relatedTopics.forEach { Text( - text = stringResource(Res.string.bullet_item, it), + text = stringResource( + Res.string.bullet_item, + it, + ), style = MaterialTheme.typography.bodyMedium, ) } diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreenUI.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreenUI.kt index 8c63f81..4a32901 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreenUI.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailScreenUI.kt @@ -67,7 +67,10 @@ private fun DetailContent( items = detailUiState.tocEntries, ) { TableOfContents( - item = stringResource(it.titleRes, *it.formatArgs.toTypedArray()), + item = stringResource( + resource = it.titleRes, + formatArgs = it.formatArgs.toTypedArray(), + ), onClick = { coroutineScope.launch { listState.animateScrollToItem(it.destinationIndex) diff --git a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailTopAppBar.kt b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailTopAppBar.kt index 28f53d7..ad1912f 100644 --- a/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailTopAppBar.kt +++ b/composeApp/src/commonMain/kotlin/com/developersbreach/kotlindictionarymultiplatform/ui/screens/detail/DetailTopAppBar.kt @@ -33,7 +33,10 @@ fun DetailTopBar( }, navigationIcon = { IconButton(onClick = navigateUp) { - Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = stringResource(Res.string.back)) + Icon( + imageVector = Icons.AutoMirrored.Filled.ArrowBack, + contentDescription = stringResource(Res.string.back), + ) } }, colors = TopAppBarDefaults.topAppBarColors(