feat(app): show json data in list

This commit is contained in:
Anthony 2024-06-09 22:03:39 +02:00
parent 0eb68afb49
commit 8be92f4134
7 changed files with 151 additions and 40 deletions

View File

@ -7,6 +7,7 @@ plugins {
alias(libs.plugins.androidApplication) alias(libs.plugins.androidApplication)
alias(libs.plugins.jetbrainsCompose) alias(libs.plugins.jetbrainsCompose)
alias(libs.plugins.compose.compiler) alias(libs.plugins.compose.compiler)
alias(libs.plugins.kotlinxSerialization)
} }
kotlin { kotlin {
@ -42,6 +43,7 @@ kotlin {
implementation(compose.ui) implementation(compose.ui)
implementation(compose.components.resources) implementation(compose.components.resources)
implementation(compose.components.uiToolingPreview) implementation(compose.components.uiToolingPreview)
implementation(libs.kotlinx.serialization.json)
implementation(libs.voyager.navigator) implementation(libs.voyager.navigator)
} }
} }

View File

@ -10,6 +10,7 @@ import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import cafe.adriel.voyager.navigator.Navigator import cafe.adriel.voyager.navigator.Navigator
import org.jetbrains.compose.ui.tooling.preview.Preview import org.jetbrains.compose.ui.tooling.preview.Preview
import tab.ENumberList
@Composable @Composable
@Preview @Preview
@ -33,7 +34,7 @@ fun AppScaffold() {
Column( Column(
modifier = Modifier.padding(innerPadding) modifier = Modifier.padding(innerPadding)
) { ) {
Navigator(tab.List()) Navigator(ENumberList())
} }
} }
} }

View File

@ -0,0 +1,9 @@
package data
import kotlinx.serialization.Serializable
@Serializable
data class EGroup(
val group: Int,
val numbers: List<ENumber>
)

View File

@ -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
)

View File

@ -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<EGroup> {
val bytes = readBytes("files/enumbers.json")
println("Loading")
val eNumbers = Json.decodeFromString<List<EGroup>>(bytes.decodeToString())
println("Loaded")
return eNumbers
}
@OptIn(ExperimentalFoundationApi::class)
@Composable
override fun Content() {
val eNumbers = remember {
mutableStateListOf<EGroup>()
}
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
)
}
}

View File

@ -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()
}
}

View File

@ -14,12 +14,14 @@ androidx-test-junit = "1.1.5"
compose-plugin = "1.6.10" compose-plugin = "1.6.10"
junit = "4.13.2" junit = "4.13.2"
kotlin = "2.0.0" kotlin = "2.0.0"
kotlinx = "1.7.0"
material3Android = "1.2.1" material3Android = "1.2.1"
voyager = "1.1.0-beta02" voyager = "1.1.0-beta02"
[libraries] [libraries]
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" } kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin" }
kotlin-test-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", 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" } junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "androidx-core-ktx" } 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" } 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" } jetbrainsCompose = { id = "org.jetbrains.compose", version.ref = "compose-plugin" }
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" } compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
kotlinxSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }