PokeDex/composeApp/src/commonMain/kotlin/App.kt

179 lines
7.3 KiB
Kotlin
Raw Normal View History

2024-04-11 13:55:19 +02:00
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
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.layout.size
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.CornerRadius
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import io.kamel.image.KamelImage
import io.kamel.image.asyncPainterResource
2024-04-11 16:13:38 +02:00
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
2024-04-11 13:55:19 +02:00
import org.jetbrains.compose.ui.tooling.preview.Preview
import org.json.JSONObject
import org.jetbrains.compose.resources.ExperimentalResourceApi
import pokedex.composeapp.generated.resources.Res
import pokedex.composeapp.generated.resources.*;
import java.net.URL
2024-04-11 16:29:28 +02:00
import java.util.Locale
2024-04-11 13:55:19 +02:00
@OptIn(ExperimentalResourceApi::class)
@Composable
@Preview
fun App() {
2024-04-11 16:13:38 +02:00
var pokemap = ArrayList<Pokemon>()
2024-04-11 13:55:19 +02:00
val apiString = "https://pokeapi.co/api/v2/pokemon/"
2024-04-11 16:13:38 +02:00
var dataLoaded by remember { mutableStateOf(false) }
2024-04-11 13:55:19 +02:00
val orange = Color(0xFFffa500)
val pokemonTypeDrawableMap = hashMapOf(
"normal" to Res.drawable.normal,
"fire" to Res.drawable.fire,
"water" to Res.drawable.water,
"electric" to Res.drawable.electric,
"grass" to Res.drawable.grass,
"ice" to Res.drawable.ice,
"fighting" to Res.drawable.fighting,
"poison" to Res.drawable.poison,
"ground" to Res.drawable.ground,
"flying" to Res.drawable.flying,
"psychic" to Res.drawable.psychic,
"bug" to Res.drawable.bug,
"rock" to Res.drawable.rock,
"ghost" to Res.drawable.ghost,
"dragon" to Res.drawable.dragon,
"dark" to Res.drawable.dark,
"steel" to Res.drawable.steel,
"fairy" to Res.drawable.fairy
)
MaterialTheme {
2024-04-11 16:13:38 +02:00
if (!dataLoaded) {
// Load data asynchronously
LaunchedEffect(Unit) {
2024-04-11 16:29:28 +02:00
pokemap = withContext(Dispatchers.IO) {
loadPokemonData(apiString, 1, 10)
} as ArrayList<Pokemon>
2024-04-11 16:13:38 +02:00
pokemap.forEach { pokemon ->
println(pokemon)
}
dataLoaded = true
}
2024-04-11 16:29:28 +02:00
2024-04-11 16:13:38 +02:00
//Show Loading Circle
Box(modifier = Modifier.background(color = orange).fillMaxSize()) {
2024-04-11 13:55:19 +02:00
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
2024-04-11 16:13:38 +02:00
CircularProgressIndicator(
modifier = Modifier.size(128.dp),
color = Color.White
)
2024-04-11 13:55:19 +02:00
Text(
"Fetching data from API...",
color = Color.White,
fontWeight = FontWeight.Bold,
modifier = Modifier.height(200.dp)
)
}
2024-04-11 16:13:38 +02:00
}
} else {
println("Pokemon should show up any second!")
//Display Pokemon Grid
Box(modifier = Modifier.background(color = orange).fillMaxSize()) {
2024-04-11 13:55:19 +02:00
LazyVerticalGrid(
columns = GridCells.Adaptive(minSize = 256.dp),
) {
items(pokemap.size) { index ->
Box(modifier = Modifier.size(256.dp).padding(5.dp)) {
Canvas(modifier = Modifier.matchParentSize()) {
drawRoundRect(
color = Color.White,
topLeft = Offset(0f, 0f),
size = Size(size.width, size.height),
cornerRadius = CornerRadius(20f, 20f),
)
}
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
KamelImage(
resource = asyncPainterResource(pokemap[index].imageUrl),
modifier = Modifier.size(128.dp),
contentDescription = "",
alignment = Alignment.Center
)
}
Column(
modifier = Modifier.fillMaxSize().padding(vertical = 8.dp),
verticalArrangement = Arrangement.Bottom,
horizontalAlignment = Alignment.CenterHorizontally
) {
val type: String = pokemap[index].type
Box(modifier = Modifier.size(32.dp)) {
Image(
org.jetbrains.compose.resources.painterResource(
pokemonTypeDrawableMap[type]!!
2024-04-11 16:13:38 +02:00
), contentDescription = null
2024-04-11 13:55:19 +02:00
)
}
Spacer(modifier = Modifier.height(8.dp))
Text(
text = pokemap[index].name,
textAlign = TextAlign.Center,
color = Color.Black,
fontWeight = FontWeight.Bold
)
}
}
}
}
}
}
}
2024-04-11 16:13:38 +02:00
}
2024-04-11 13:55:19 +02:00
2024-04-11 16:13:38 +02:00
// Function to load Pokemon data asynchronously
2024-04-11 16:29:28 +02:00
suspend fun loadPokemonData(apiString: String, startId: Int, endId: Int): List<Pokemon> {
2024-04-11 16:13:38 +02:00
val pokemap = ArrayList<Pokemon>()
2024-04-11 16:29:28 +02:00
for (i in startId..endId) {
2024-04-11 16:13:38 +02:00
val json = JSONObject(URL(apiString + i).readText());
val sprites = json.optJSONObject("sprites")
val types = json.getJSONArray("types")
val firstType = types.optJSONObject(0)
val type: String = firstType.optJSONObject("type").optString("name")
2024-04-11 16:29:28 +02:00
val name: String = json.optString("name")
.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else it.toString() }
2024-04-11 13:55:19 +02:00
2024-04-11 16:13:38 +02:00
val pokemon = Pokemon(
2024-04-11 16:29:28 +02:00
name, URL(sprites.optString("front_default")), type, json.optInt("id")
2024-04-11 16:13:38 +02:00
)
2024-04-11 13:55:19 +02:00
2024-04-11 16:13:38 +02:00
pokemap.add(pokemon)
2024-04-11 13:55:19 +02:00
}
2024-04-11 16:13:38 +02:00
return pokemap
2024-04-11 13:55:19 +02:00
}