mirror of
https://github.com/owenlejeune/MYDex.git
synced 2025-11-17 12:30:53 -05:00
some basic details
This commit is contained in:
@@ -7,5 +7,5 @@ class ChainLink(
|
|||||||
@SerializedName("is_baby") val isBaby: Boolean,
|
@SerializedName("is_baby") val isBaby: Boolean,
|
||||||
@SerializedName("species") val species: NameAndUrl,
|
@SerializedName("species") val species: NameAndUrl,
|
||||||
@SerializedName("evolution_details") val evolutionDetails: EvolutionDetails,
|
@SerializedName("evolution_details") val evolutionDetails: EvolutionDetails,
|
||||||
@SerializedName("evolves_to") val evolves_to: List<ChainLink>?
|
@SerializedName("evolves_to") val evolves_to: List<ChainLink?>?
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -6,5 +6,5 @@ import com.owenlejeune.mydex.api.pokeapi.v2.model.misc.NameAndUrl
|
|||||||
class EvolutionChain(
|
class EvolutionChain(
|
||||||
@SerializedName("id") val id: Int,
|
@SerializedName("id") val id: Int,
|
||||||
@SerializedName("baby_trigger_item") val babyTriggerItem: NameAndUrl?,
|
@SerializedName("baby_trigger_item") val babyTriggerItem: NameAndUrl?,
|
||||||
@SerializedName("chain") val chain: ChainLink
|
@SerializedName("chain") val chain: ChainLink?
|
||||||
)
|
)
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.owenlejeune.mydex.extensions
|
||||||
|
|
||||||
|
import androidx.compose.ui.text.intl.Locale
|
||||||
|
import com.owenlejeune.mydex.api.pokeapi.v2.model.misc.NameAndLanguage
|
||||||
|
|
||||||
|
fun List<NameAndLanguage>.getNameForLanguage(): String? {
|
||||||
|
val lang = Locale.current.language
|
||||||
|
return find { it.language.name == lang }?.name
|
||||||
|
}
|
||||||
@@ -61,7 +61,7 @@ class MainActivity : MonetCompatActivity() {
|
|||||||
) {
|
) {
|
||||||
val id = it.arguments?.getInt("id")
|
val id = it.arguments?.getInt("id")
|
||||||
id?.let {
|
id?.let {
|
||||||
PokemonDetailView(pokemonId = it)
|
PokemonDetailView(pokemonId = id, appNavController = appNavController)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,195 @@
|
|||||||
package com.owenlejeune.mydex.ui.views
|
package com.owenlejeune.mydex.ui.views
|
||||||
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.ArrowBack
|
||||||
|
import androidx.compose.material3.*
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.draw.rotate
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.ColorFilter
|
||||||
|
import androidx.compose.ui.layout.ContentScale
|
||||||
|
import androidx.compose.ui.text.TextStyle
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.intl.Locale
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.navigation.NavController
|
||||||
|
import coil.compose.AsyncImage
|
||||||
|
import com.owenlejeune.mydex.R
|
||||||
|
import com.owenlejeune.mydex.api.pokeapi.v2.PokemonService
|
||||||
|
import com.owenlejeune.mydex.api.pokeapi.v2.model.pokemon.PokemonSpecies
|
||||||
|
import com.owenlejeune.mydex.api.pokeapi.v2.model.pokemon.PokemonType
|
||||||
|
import com.owenlejeune.mydex.extensions.getIdFromUrl
|
||||||
|
import com.owenlejeune.mydex.extensions.getNameForLanguage
|
||||||
|
import com.owenlejeune.mydex.ui.components.PokemonTypeLabel
|
||||||
import com.owenlejeune.mydex.utils.AppCache
|
import com.owenlejeune.mydex.utils.AppCache
|
||||||
|
import com.owenlejeune.mydex.utils.ColorUtils
|
||||||
|
import org.koin.java.KoinJavaComponent.get
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
fun PokemonDetailView(
|
fun PokemonDetailView(
|
||||||
pokemonId: Int
|
pokemonId: Int,
|
||||||
|
appNavController: NavController
|
||||||
) {
|
) {
|
||||||
val pokemon = AppCache.cachedSpecies[pokemonId]
|
val pokemonSpecies = AppCache.cachedSpecies[pokemonId]
|
||||||
Text(text = pokemon.name)
|
val pokemon = AppCache.cachedPokemon[pokemonId]
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(color = ColorUtils.pokeColorToComposeColor(color = pokemonSpecies.color.name))
|
||||||
|
) {
|
||||||
|
AsyncImage(
|
||||||
|
model = R.drawable.pokeball,
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier
|
||||||
|
.offset(y = 200.dp)
|
||||||
|
.rotate(65f)
|
||||||
|
.size(240.dp)
|
||||||
|
.align(Alignment.TopCenter),
|
||||||
|
colorFilter = ColorFilter.tint(Color.White.copy(alpha = 0.25f))
|
||||||
|
)
|
||||||
|
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
) {
|
||||||
|
Spacer(modifier = Modifier.height(120.dp))
|
||||||
|
|
||||||
|
Header(pokemonSpecies = pokemonSpecies, modifier = Modifier.padding(horizontal = 36.dp))
|
||||||
|
|
||||||
|
Box {
|
||||||
|
Card(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(top = 140.dp),
|
||||||
|
shape = RoundedCornerShape(topStart = 32.dp, topEnd = 32.dp),
|
||||||
|
colors = CardDefaults.cardColors(containerColor = MaterialTheme.colorScheme.background)
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
AsyncImage(
|
||||||
|
model = pokemon.sprites.frontDefault,
|
||||||
|
contentDescription = null,
|
||||||
|
contentScale = ContentScale.FillBounds,
|
||||||
|
modifier = Modifier
|
||||||
|
.size(250.dp)
|
||||||
|
.align(Alignment.TopCenter)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SmallTopAppBar(
|
||||||
|
modifier = Modifier
|
||||||
|
.statusBarsPadding(),
|
||||||
|
navigationIcon = {
|
||||||
|
IconButton(onClick = { appNavController.popBackStack() }) {
|
||||||
|
Icon(imageVector = Icons.Filled.ArrowBack, contentDescription = null)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
title = {},
|
||||||
|
colors = TopAppBarDefaults
|
||||||
|
.smallTopAppBarColors(
|
||||||
|
containerColor = Color.Transparent//.copy(alpha = 0.4f)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun Header(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
pokemonSpecies: PokemonSpecies,
|
||||||
|
service: PokemonService = get(PokemonService::class.java)
|
||||||
|
) {
|
||||||
|
val pokemon = AppCache.cachedPokemon.get(pokemonSpecies.id)
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = modifier
|
||||||
|
.fillMaxWidth(),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Column(
|
||||||
|
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
|
) {
|
||||||
|
val pokemonName = pokemonSpecies.names.getNameForLanguage() ?: pokemonSpecies.name
|
||||||
|
Text(
|
||||||
|
text = pokemonName,
|
||||||
|
style = TextStyle(
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
fontSize = 30.sp,
|
||||||
|
color = MaterialTheme.colorScheme.onBackground
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
Row(
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
|
) {
|
||||||
|
pokemon.types.forEach { type ->
|
||||||
|
val id = type.type.url.getIdFromUrl()
|
||||||
|
val pokemonType = remember { mutableStateOf<PokemonType?>(AppCache.cachedTypes[id]) }
|
||||||
|
LaunchedEffect(key1 = pokemonType.value) {
|
||||||
|
fetchPokemonType(id, pokemonType, service)
|
||||||
|
}
|
||||||
|
|
||||||
|
pokemonType.value?.let { t ->
|
||||||
|
val typeName = t.names.getNameForLanguage() ?: ""
|
||||||
|
PokemonTypeLabel(type = typeName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
|
|
||||||
|
Column(
|
||||||
|
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
|
) {
|
||||||
|
val dexNumber = pokemon.id.toString().padStart(3, '0')
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.align(Alignment.End),
|
||||||
|
text = "#${dexNumber}",
|
||||||
|
style = TextStyle(
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
fontSize = 18.sp,
|
||||||
|
color = MaterialTheme.colorScheme.onBackground
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
val genus = pokemonSpecies.genera.find { it.language.name == Locale.current.language }?.genus ?: ""
|
||||||
|
Text(
|
||||||
|
text = genus,
|
||||||
|
modifier = Modifier.align(Alignment.End),
|
||||||
|
style = TextStyle(
|
||||||
|
fontSize = 12.sp,
|
||||||
|
color = MaterialTheme.colorScheme.onBackground
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun fetchPokemonType(
|
||||||
|
id: Int,
|
||||||
|
pokemonType: MutableState<PokemonType?>,
|
||||||
|
service: PokemonService
|
||||||
|
) {
|
||||||
|
if (pokemonType.value == null) {
|
||||||
|
service.getPokemonType(id).apply {
|
||||||
|
if (isSuccessful) {
|
||||||
|
body()?.let {
|
||||||
|
pokemonType.value = it
|
||||||
|
AppCache.cachedTypes.put(it.id, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -32,6 +32,7 @@ import com.owenlejeune.mydex.api.pokeapi.v2.model.pokemon.PokemonSpecies
|
|||||||
import com.owenlejeune.mydex.api.pokeapi.v2.model.pokemon.PokemonType
|
import com.owenlejeune.mydex.api.pokeapi.v2.model.pokemon.PokemonType
|
||||||
import com.owenlejeune.mydex.api.pokeapi.v2.viewmodel.PokemonViewModel
|
import com.owenlejeune.mydex.api.pokeapi.v2.viewmodel.PokemonViewModel
|
||||||
import com.owenlejeune.mydex.extensions.getIdFromUrl
|
import com.owenlejeune.mydex.extensions.getIdFromUrl
|
||||||
|
import com.owenlejeune.mydex.extensions.getNameForLanguage
|
||||||
import com.owenlejeune.mydex.extensions.header
|
import com.owenlejeune.mydex.extensions.header
|
||||||
import com.owenlejeune.mydex.extensions.lazyPagingItems
|
import com.owenlejeune.mydex.extensions.lazyPagingItems
|
||||||
import com.owenlejeune.mydex.ui.components.PokemonTypeLabel
|
import com.owenlejeune.mydex.ui.components.PokemonTypeLabel
|
||||||
@@ -67,7 +68,7 @@ fun PokedexView(
|
|||||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(start = 36.dp, end = 36.dp)
|
.padding(horizontal = 36.dp)
|
||||||
.fillMaxSize()
|
.fillMaxSize()
|
||||||
) {
|
) {
|
||||||
header {
|
header {
|
||||||
@@ -95,8 +96,7 @@ fun PokedexView(
|
|||||||
|
|
||||||
SmallTopAppBar(
|
SmallTopAppBar(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.statusBarsPadding()
|
.statusBarsPadding(),
|
||||||
.blur(radius = 10.dp),
|
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
IconButton(onClick = { appNavController.popBackStack() }) {
|
IconButton(onClick = { appNavController.popBackStack() }) {
|
||||||
Icon(imageVector = Icons.Filled.ArrowBack, contentDescription = null)
|
Icon(imageVector = Icons.Filled.ArrowBack, contentDescription = null)
|
||||||
@@ -134,7 +134,7 @@ fun PokedexCard(
|
|||||||
val bgColor = remember { mutableStateOf(defBg) }
|
val bgColor = remember { mutableStateOf(defBg) }
|
||||||
Card(
|
Card(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.height(160.dp)
|
.height(130.dp)
|
||||||
.fillMaxWidth(),
|
.fillMaxWidth(),
|
||||||
shape = RoundedCornerShape(16.dp),
|
shape = RoundedCornerShape(16.dp),
|
||||||
colors = CardDefaults.cardColors(containerColor = bgColor.value),
|
colors = CardDefaults.cardColors(containerColor = bgColor.value),
|
||||||
@@ -153,7 +153,7 @@ fun PokedexCard(
|
|||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.align(Alignment.BottomEnd)
|
.align(Alignment.BottomEnd)
|
||||||
.offset(x = 20.dp, y = 0.dp)
|
.offset(x = 20.dp, y = 20.dp)
|
||||||
.size(width = 96.dp, height = 96.dp),
|
.size(width = 96.dp, height = 96.dp),
|
||||||
colorFilter = ColorFilter.tint(Color.White.copy(alpha = 0.15f))
|
colorFilter = ColorFilter.tint(Color.White.copy(alpha = 0.15f))
|
||||||
)
|
)
|
||||||
@@ -166,8 +166,7 @@ fun PokedexCard(
|
|||||||
species.value?.let { species ->
|
species.value?.let { species ->
|
||||||
bgColor.value = ColorUtils.pokeColorToComposeColor(color = species.color.name)
|
bgColor.value = ColorUtils.pokeColorToComposeColor(color = species.color.name)
|
||||||
|
|
||||||
val locale = Locale.current.language
|
val name = species.names.getNameForLanguage() ?: species.name
|
||||||
val name = species.names.find { it.language.name == locale }?.name ?: species.name
|
|
||||||
val dexNumber = pokemon.value!!.id.toString().padStart(3, '0')
|
val dexNumber = pokemon.value!!.id.toString().padStart(3, '0')
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
@@ -191,7 +190,7 @@ fun PokedexCard(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pokemonType.value?.let { t ->
|
pokemonType.value?.let { t ->
|
||||||
val typeName = t.names.find { it.language.name == locale }?.name ?: ""//type.type.name
|
val typeName = t.names.getNameForLanguage() ?: ""//type.type.name
|
||||||
PokemonTypeLabel(type = typeName)
|
PokemonTypeLabel(type = typeName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user