From 8be92f41342caeb121b0028b153d088df5202a70 Mon Sep 17 00:00:00 2001 From: Anthony Date: Sun, 9 Jun 2024 22:03:39 +0200 Subject: [PATCH] feat(app): show json data in list --- composeApp/build.gradle.kts | 2 + composeApp/src/commonMain/kotlin/App.kt | 3 +- .../src/commonMain/kotlin/data/EGroup.kt | 9 ++ .../src/commonMain/kotlin/data/ENumber.kt | 12 ++ .../src/commonMain/kotlin/tab/ENumberList.kt | 123 ++++++++++++++++++ composeApp/src/commonMain/kotlin/tab/List.kt | 39 ------ gradle/libs.versions.toml | 3 + 7 files changed, 151 insertions(+), 40 deletions(-) create mode 100644 composeApp/src/commonMain/kotlin/data/EGroup.kt create mode 100644 composeApp/src/commonMain/kotlin/data/ENumber.kt create mode 100644 composeApp/src/commonMain/kotlin/tab/ENumberList.kt delete mode 100644 composeApp/src/commonMain/kotlin/tab/List.kt diff --git a/composeApp/build.gradle.kts b/composeApp/build.gradle.kts index 77561d1..8921cfc 100644 --- a/composeApp/build.gradle.kts +++ b/composeApp/build.gradle.kts @@ -7,6 +7,7 @@ plugins { alias(libs.plugins.androidApplication) alias(libs.plugins.jetbrainsCompose) alias(libs.plugins.compose.compiler) + alias(libs.plugins.kotlinxSerialization) } kotlin { @@ -42,6 +43,7 @@ kotlin { implementation(compose.ui) implementation(compose.components.resources) implementation(compose.components.uiToolingPreview) + implementation(libs.kotlinx.serialization.json) implementation(libs.voyager.navigator) } } diff --git a/composeApp/src/commonMain/kotlin/App.kt b/composeApp/src/commonMain/kotlin/App.kt index eeea2b7..8e92a1f 100644 --- a/composeApp/src/commonMain/kotlin/App.kt +++ b/composeApp/src/commonMain/kotlin/App.kt @@ -10,6 +10,7 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.text.style.TextOverflow import cafe.adriel.voyager.navigator.Navigator import org.jetbrains.compose.ui.tooling.preview.Preview +import tab.ENumberList @Composable @Preview @@ -33,7 +34,7 @@ fun AppScaffold() { Column( modifier = Modifier.padding(innerPadding) ) { - Navigator(tab.List()) + Navigator(ENumberList()) } } } diff --git a/composeApp/src/commonMain/kotlin/data/EGroup.kt b/composeApp/src/commonMain/kotlin/data/EGroup.kt new file mode 100644 index 0000000..e49a986 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/data/EGroup.kt @@ -0,0 +1,9 @@ +package data + +import kotlinx.serialization.Serializable + +@Serializable +data class EGroup( + val group: Int, + val numbers: List +) diff --git a/composeApp/src/commonMain/kotlin/data/ENumber.kt b/composeApp/src/commonMain/kotlin/data/ENumber.kt new file mode 100644 index 0000000..d25e3e4 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/data/ENumber.kt @@ -0,0 +1,12 @@ +package data + +import kotlinx.serialization.Serializable + +@Serializable +data class ENumber( + val number: String, + val name: String, + val vegan: Boolean, + val notVegan: Boolean, + val note: String? = null +) diff --git a/composeApp/src/commonMain/kotlin/tab/ENumberList.kt b/composeApp/src/commonMain/kotlin/tab/ENumberList.kt new file mode 100644 index 0000000..4bc93f5 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/tab/ENumberList.kt @@ -0,0 +1,123 @@ +package tab + +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Check +import androidx.compose.material.icons.outlined.Close +import androidx.compose.material.icons.outlined.Info +import androidx.compose.material.icons.outlined.Warning +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.mutableStateListOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import cafe.adriel.voyager.core.screen.Screen +import data.EGroup +import data.ENumber +import kotlinx.serialization.json.Json +import org.jetbrains.compose.resources.ExperimentalResourceApi +import veganenumbers.composeapp.generated.resources.Res.readBytes + +class ENumberList : Screen { + + /** + * Reads JSON file containing all e numbers + * @return List of grouped E Numbers in `EGroup` type + */ + @OptIn(ExperimentalResourceApi::class) + private suspend fun getENumbers(): List { + val bytes = readBytes("files/enumbers.json") + + println("Loading") + + val eNumbers = Json.decodeFromString>(bytes.decodeToString()) + + println("Loaded") + + return eNumbers + } + + @OptIn(ExperimentalFoundationApi::class) + @Composable + override fun Content() { + val eNumbers = remember { + mutableStateListOf() + } + println("Starting") + + LaunchedEffect(Unit) { + eNumbers.addAll(getENumbers()) + } + + LazyColumn(contentPadding = PaddingValues(6.dp)) { + eNumbers.forEach { eGroup -> + stickyHeader { + Header(group = eGroup.group) + } + + items(eGroup.numbers) { eNumber -> + ItemList(eNumber = eNumber) + } + } + } + } + + @Composable + private fun Header(group: Int) { + val text = if (group < 10) { + "E${group}00 - E${group}99" + } else { + "E1000 - E1599" + } + + Text( + text = text, + modifier = Modifier + .fillMaxWidth() + .background(MaterialTheme.colorScheme.surface) + .padding(8.dp) + ) + } + + @Composable + private fun ItemList(eNumber: ENumber) { + ListItem( + headlineContent = { + Text(text = "E${eNumber.number}") + }, + leadingContent = { + VeganStatusIcon( + vegan = eNumber.vegan, + notVegan = eNumber.notVegan + ) + } + ) + HorizontalDivider() + } + + @Composable + private fun VeganStatusIcon(vegan: Boolean, notVegan: Boolean) { + val (icon, status) = if (vegan and !notVegan) { + Pair(Icons.Outlined.Check, "Vegan") + } else if (vegan and notVegan) { + Pair(Icons.Outlined.Warning, "Potentially Not Vegan") + } else if (!vegan and notVegan) { + Pair(Icons.Outlined.Close, "Not Vegan") + } else { + Pair(Icons.Outlined.Info, "Unknown") + } + + Icon( + imageVector = icon, + contentDescription = status + ) + } +} diff --git a/composeApp/src/commonMain/kotlin/tab/List.kt b/composeApp/src/commonMain/kotlin/tab/List.kt deleted file mode 100644 index 058e0e8..0000000 --- a/composeApp/src/commonMain/kotlin/tab/List.kt +++ /dev/null @@ -1,39 +0,0 @@ -package tab - -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.Info -import androidx.compose.material3.HorizontalDivider -import androidx.compose.material3.Icon -import androidx.compose.material3.ListItem -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import cafe.adriel.voyager.core.screen.Screen - -class List : Screen { - - @Composable - override fun Content() { - LazyColumn { - items(1000) { index -> - ItemList(index) - } - } - } - - @Composable - private fun ItemList(number: Int) { - ListItem( - headlineContent = { - Text(text = "E${number + 100}") - }, - leadingContent = { - Icon( - imageVector = Icons.Outlined.Info, - contentDescription = "Unknown" - ) - } - ) - HorizontalDivider() - } -} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8656804..160480d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -14,12 +14,14 @@ androidx-test-junit = "1.1.5" compose-plugin = "1.6.10" junit = "4.13.2" kotlin = "2.0.0" +kotlinx = "1.7.0" material3Android = "1.2.1" voyager = "1.1.0-beta02" [libraries] kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } kotlin-test-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin" } +kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx"} junit = { group = "junit", name = "junit", version.ref = "junit" } androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "androidx-core-ktx" } androidx-test-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidx-test-junit" } @@ -40,3 +42,4 @@ androidLibrary = { id = "com.android.library", version.ref = "agp" } jetbrainsCompose = { id = "org.jetbrains.compose", version.ref = "compose-plugin" } compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } +kotlinxSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }