some basic details

This commit is contained in:
Owen LeJeune
2022-09-16 14:55:13 -04:00
parent 2f5b197a81
commit 0af10c1eab
6 changed files with 206 additions and 16 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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