mirror of
https://github.com/smyalygames/vegan-e-numbers.git
synced 2025-05-18 16:44:13 +02:00
feat(app): show json data in list
This commit is contained in:
parent
0eb68afb49
commit
8be92f4134
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
9
composeApp/src/commonMain/kotlin/data/EGroup.kt
Normal file
9
composeApp/src/commonMain/kotlin/data/EGroup.kt
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package data
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class EGroup(
|
||||||
|
val group: Int,
|
||||||
|
val numbers: List<ENumber>
|
||||||
|
)
|
12
composeApp/src/commonMain/kotlin/data/ENumber.kt
Normal file
12
composeApp/src/commonMain/kotlin/data/ENumber.kt
Normal 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
|
||||||
|
)
|
123
composeApp/src/commonMain/kotlin/tab/ENumberList.kt
Normal file
123
composeApp/src/commonMain/kotlin/tab/ENumberList.kt
Normal 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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
@ -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()
|
|
||||||
}
|
|
||||||
}
|
|
@ -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" }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user