Make landing page dynamic based on the character sheets
|
|
@ -13,7 +13,7 @@ object AlterationSortUseCase {
|
||||||
}.thenByDescending {
|
}.thenByDescending {
|
||||||
PLAYER == it
|
PLAYER == it
|
||||||
}.thenByDescending {
|
}.thenByDescending {
|
||||||
sheet?.characterClass?.any { clazz -> clazz.value == it }
|
sheet?.characterClass?.any { clazz -> clazz.id == it }
|
||||||
}.thenByDescending {
|
}.thenByDescending {
|
||||||
sheet?.race == it
|
sheet?.race == it
|
||||||
}.thenByDescending {
|
}.thenByDescending {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.pixelized.rplexicon.data.model
|
package com.pixelized.rplexicon.data.model
|
||||||
|
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
|
import androidx.annotation.StringRes
|
||||||
import com.pixelized.rplexicon.R
|
import com.pixelized.rplexicon.R
|
||||||
|
|
||||||
data class CharacterSheet(
|
data class CharacterSheet(
|
||||||
|
|
@ -57,45 +58,84 @@ data class CharacterSheet(
|
||||||
val others: List<String>, // others masteries
|
val others: List<String>, // others masteries
|
||||||
) {
|
) {
|
||||||
val isWarlock: Boolean get() = characterClass.contains(Class.WARLOCK)
|
val isWarlock: Boolean get() = characterClass.contains(Class.WARLOCK)
|
||||||
val resource: String? get() = characterClass.firstNotNullOfOrNull { it.resource }
|
val resource: String? get() = characterClass.firstNotNullOfOrNull { it.resourceId }
|
||||||
|
|
||||||
enum class Class(
|
enum class Class(
|
||||||
val value: String,
|
val id: String,
|
||||||
val resource: String? = null,
|
@StringRes
|
||||||
val label: Int? = null,
|
val label: Int,
|
||||||
|
val resourceId: String? = null,
|
||||||
|
@StringRes
|
||||||
|
val resourceLabel: Int? = null,
|
||||||
@DrawableRes val icon: Int,
|
@DrawableRes val icon: Int,
|
||||||
) {
|
) {
|
||||||
BARBARIAN(
|
BARBARIAN(
|
||||||
value = "Barbare",
|
id = "Barbare",
|
||||||
resource = "Rage",
|
label = R.string.class_barbarian,
|
||||||
label = R.string.character_sheet_title_rage,
|
resourceId = "Rage",
|
||||||
icon = R.drawable.ic_class_barbarian_24
|
resourceLabel = R.string.character_sheet_title_rage,
|
||||||
|
icon = R.drawable.icbg_class_barbarian,
|
||||||
),
|
),
|
||||||
BARD(
|
BARD(
|
||||||
value = "Barde",
|
id = "Barde",
|
||||||
resource = "Inspiration bardique",
|
label = R.string.class_bard,
|
||||||
label = R.string.character_sheet_title_inspiration,
|
resourceId = "Inspiration bardique",
|
||||||
icon = R.drawable.ic_class_bard_24
|
resourceLabel = R.string.character_sheet_title_inspiration,
|
||||||
|
icon = R.drawable.icbg_class_bard,
|
||||||
),
|
),
|
||||||
CLERIC(
|
CLERIC(
|
||||||
value = "Clerc",
|
id = "Clerc",
|
||||||
resource = "Conduit divin",
|
label = R.string.class_cleric,
|
||||||
label = R.string.character_sheet_title_conduit,
|
resourceId = "Conduit divin",
|
||||||
icon = R.drawable.ic_class_cleric_24
|
resourceLabel = R.string.character_sheet_title_conduit,
|
||||||
|
icon = R.drawable.icbg_class_cleric,
|
||||||
),
|
),
|
||||||
DRUID(
|
DRUID(
|
||||||
value = "Druide",
|
id = "Druide",
|
||||||
resource = "Forme sauvage",
|
label = R.string.class_druid,
|
||||||
label = R.string.character_sheet_title_wild_shape,
|
resourceId = "Forme sauvage",
|
||||||
|
resourceLabel = R.string.character_sheet_title_wild_shape,
|
||||||
icon = R.drawable.ic_class_druid_24,
|
icon = R.drawable.ic_class_druid_24,
|
||||||
),
|
),
|
||||||
FIGHTER(value = "Guerrier", icon = R.drawable.ic_class_fighter_24),
|
FIGHTER(
|
||||||
MONK(value = "Moine", icon = R.drawable.ic_class_monk_24),
|
id = "Guerrier",
|
||||||
PALADIN(value = "Paladin", icon = R.drawable.ic_class_paladin_24),
|
label = R.string.class_fighter,
|
||||||
RANGER(value = "Rodeur", icon = R.drawable.ic_class_ranger_24),
|
icon = R.drawable.ic_class_fighter_24,
|
||||||
ROGUE(value = "Roublard", icon = R.drawable.ic_class_rogue_24),
|
),
|
||||||
SORCERER(value = "Ensorceleur", icon = R.drawable.ic_class_sorcerer_24),
|
MONK(
|
||||||
WARLOCK(value = "Occultiste", icon = R.drawable.ic_class_warlock_24),
|
id = "Moine",
|
||||||
WIZARD(value = "Magicien", icon = R.drawable.ic_class_wizard_24),
|
label = R.string.class_monk,
|
||||||
|
icon = R.drawable.ic_class_monk_24,
|
||||||
|
),
|
||||||
|
PALADIN(
|
||||||
|
id = "Paladin",
|
||||||
|
label = R.string.class_paladin,
|
||||||
|
icon = R.drawable.ic_class_paladin_24,
|
||||||
|
),
|
||||||
|
RANGER(
|
||||||
|
id = "Rodeur",
|
||||||
|
label = R.string.class_ranger,
|
||||||
|
icon = R.drawable.icbg_class_ranger,
|
||||||
|
),
|
||||||
|
ROGUE(
|
||||||
|
id = "Roublard",
|
||||||
|
label = R.string.class_rogue,
|
||||||
|
icon = R.drawable.ic_class_rogue_24,
|
||||||
|
),
|
||||||
|
SORCERER(
|
||||||
|
id = "Ensorceleur",
|
||||||
|
label = R.string.class_sorcerer,
|
||||||
|
icon = R.drawable.ic_class_sorcerer_24,
|
||||||
|
),
|
||||||
|
WARLOCK(
|
||||||
|
id = "Occultiste",
|
||||||
|
label = R.string.class_warlock,
|
||||||
|
icon = R.drawable.icbg_class_warlock,
|
||||||
|
),
|
||||||
|
WIZARD(
|
||||||
|
id = "Magicien",
|
||||||
|
label = R.string.class_wizard,
|
||||||
|
icon = R.drawable.ic_class_wizard_24,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -51,7 +51,7 @@ class AlterationParser @Inject constructor(
|
||||||
characterSheets
|
characterSheets
|
||||||
.filter { // check if the alteration is applicable to the character
|
.filter { // check if the alteration is applicable to the character
|
||||||
alteration.target.let { target ->
|
alteration.target.let { target ->
|
||||||
target == ALL || target == it.name || target == it.race || it.characterClass.any { it.value == target }
|
target == ALL || target == it.name || target == it.race || it.characterClass.any { it.id == target }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.forEach { sheet -> // check the default alteration state for that character
|
.forEach { sheet -> // check the default alteration state for that character
|
||||||
|
|
|
||||||
|
|
@ -12,18 +12,18 @@ class CharacterClassParser @Inject constructor() {
|
||||||
?.map { it.trim() }
|
?.map { it.trim() }
|
||||||
?.mapNotNull {
|
?.mapNotNull {
|
||||||
when (it) {
|
when (it) {
|
||||||
CharacterSheet.Class.BARBARIAN.value -> CharacterSheet.Class.BARBARIAN
|
CharacterSheet.Class.BARBARIAN.id -> CharacterSheet.Class.BARBARIAN
|
||||||
CharacterSheet.Class.BARD.value -> CharacterSheet.Class.BARD
|
CharacterSheet.Class.BARD.id -> CharacterSheet.Class.BARD
|
||||||
CharacterSheet.Class.CLERIC.value -> CharacterSheet.Class.CLERIC
|
CharacterSheet.Class.CLERIC.id -> CharacterSheet.Class.CLERIC
|
||||||
CharacterSheet.Class.DRUID.value -> CharacterSheet.Class.DRUID
|
CharacterSheet.Class.DRUID.id -> CharacterSheet.Class.DRUID
|
||||||
CharacterSheet.Class.FIGHTER.value -> CharacterSheet.Class.FIGHTER
|
CharacterSheet.Class.FIGHTER.id -> CharacterSheet.Class.FIGHTER
|
||||||
CharacterSheet.Class.MONK.value -> CharacterSheet.Class.MONK
|
CharacterSheet.Class.MONK.id -> CharacterSheet.Class.MONK
|
||||||
CharacterSheet.Class.PALADIN.value -> CharacterSheet.Class.PALADIN
|
CharacterSheet.Class.PALADIN.id -> CharacterSheet.Class.PALADIN
|
||||||
CharacterSheet.Class.RANGER.value -> CharacterSheet.Class.RANGER
|
CharacterSheet.Class.RANGER.id -> CharacterSheet.Class.RANGER
|
||||||
CharacterSheet.Class.ROGUE.value -> CharacterSheet.Class.ROGUE
|
CharacterSheet.Class.ROGUE.id -> CharacterSheet.Class.ROGUE
|
||||||
CharacterSheet.Class.SORCERER.value -> CharacterSheet.Class.SORCERER
|
CharacterSheet.Class.SORCERER.id -> CharacterSheet.Class.SORCERER
|
||||||
CharacterSheet.Class.WARLOCK.value -> CharacterSheet.Class.WARLOCK
|
CharacterSheet.Class.WARLOCK.id -> CharacterSheet.Class.WARLOCK
|
||||||
CharacterSheet.Class.WIZARD.value -> CharacterSheet.Class.WIZARD
|
CharacterSheet.Class.WIZARD.id -> CharacterSheet.Class.WIZARD
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,10 +18,10 @@ class CharacterSheetHeaderUioFactory @Inject constructor(
|
||||||
sheetHeaderData: HeaderViewModel.SheetHeaderData?,
|
sheetHeaderData: HeaderViewModel.SheetHeaderData?,
|
||||||
fireHeaderData: HeaderViewModel.FireHeaderData?,
|
fireHeaderData: HeaderViewModel.FireHeaderData?,
|
||||||
): CharacterSheetHeaderUio {
|
): CharacterSheetHeaderUio {
|
||||||
val classWithResource = sheetHeaderData?.characterClass?.firstOrNull { it.resource != null }
|
val classWithResource = sheetHeaderData?.characterClass?.firstOrNull { it.resourceId != null }
|
||||||
val favoriteSkill = skillRepository.find(
|
val favoriteSkill = skillRepository.find(
|
||||||
character = character,
|
character = character,
|
||||||
skill = classWithResource?.resource
|
skill = classWithResource?.resourceId
|
||||||
)
|
)
|
||||||
return CharacterSheetHeaderUio(
|
return CharacterSheetHeaderUio(
|
||||||
initiative = LabelPointUio(
|
initiative = LabelPointUio(
|
||||||
|
|
@ -47,10 +47,10 @@ class CharacterSheetHeaderUioFactory @Inject constructor(
|
||||||
value = "$it",
|
value = "$it",
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
resource = if (classWithResource?.label != null && favoriteSkill?.amount != null) {
|
resource = if (classWithResource?.resourceLabel != null && favoriteSkill?.amount != null) {
|
||||||
ResourcePointUio(
|
ResourcePointUio(
|
||||||
id = favoriteSkill.name,
|
id = favoriteSkill.name,
|
||||||
label = classWithResource.label,
|
label = classWithResource.resourceLabel,
|
||||||
value = fireHeaderData?.resource ?: 0,
|
value = fireHeaderData?.resource ?: 0,
|
||||||
max = favoriteSkill.amount,
|
max = favoriteSkill.amount,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package com.pixelized.rplexicon.ui.screens.landing
|
||||||
import android.content.res.Configuration.UI_MODE_NIGHT_NO
|
import android.content.res.Configuration.UI_MODE_NIGHT_NO
|
||||||
import android.content.res.Configuration.UI_MODE_NIGHT_YES
|
import android.content.res.Configuration.UI_MODE_NIGHT_YES
|
||||||
import androidx.annotation.DrawableRes
|
import androidx.annotation.DrawableRes
|
||||||
|
import androidx.annotation.FloatRange
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
|
|
@ -42,7 +43,7 @@ import com.pixelized.rplexicon.utilitary.extentions.lexicon
|
||||||
|
|
||||||
@Stable
|
@Stable
|
||||||
data class LandingItemUio(
|
data class LandingItemUio(
|
||||||
@DrawableRes val icon: Int,
|
@DrawableRes val icon: Int?,
|
||||||
val title: String?,
|
val title: String?,
|
||||||
val subTitle: String?,
|
val subTitle: String?,
|
||||||
)
|
)
|
||||||
|
|
@ -54,6 +55,9 @@ fun LandingItem(
|
||||||
paddings: PaddingValues = PaddingValues(),
|
paddings: PaddingValues = PaddingValues(),
|
||||||
imagePadding: PaddingValues = PaddingValues(all = 16.dp),
|
imagePadding: PaddingValues = PaddingValues(all = 16.dp),
|
||||||
shape: Shape = remember { RoundedCornerShape(size = 8.dp) },
|
shape: Shape = remember { RoundedCornerShape(size = 8.dp) },
|
||||||
|
backgroundFilter: ColorFilter? = ColorFilter.tint(color = MaterialTheme.colorScheme.onSurface),
|
||||||
|
@FloatRange(from = 0.0, to = 1.0) backgroundGradientFrom: Float = 0.5f,
|
||||||
|
@FloatRange(from = 0.0, to = 1.0) backgroundGradientTo: Float = 1f,
|
||||||
rotation: Float = 0f,
|
rotation: Float = 0f,
|
||||||
alpha: Float = 0.6f,
|
alpha: Float = 0.6f,
|
||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
|
|
@ -66,23 +70,30 @@ fun LandingItem(
|
||||||
.then(other = modifier),
|
.then(other = modifier),
|
||||||
contentAlignment = Alignment.BottomCenter
|
contentAlignment = Alignment.BottomCenter
|
||||||
) {
|
) {
|
||||||
Image(
|
item.icon?.let {
|
||||||
modifier = Modifier
|
Image(
|
||||||
.matchParentSize()
|
modifier = Modifier
|
||||||
.padding(paddingValues = imagePadding)
|
.matchParentSize()
|
||||||
.rotate(degrees = rotation),
|
.padding(paddingValues = imagePadding)
|
||||||
painter = painterResource(id = item.icon),
|
.rotate(degrees = rotation),
|
||||||
alpha = alpha,
|
painter = painterResource(id = it),
|
||||||
contentScale = ContentScale.FillHeight,
|
alpha = alpha,
|
||||||
alignment = Alignment.TopCenter,
|
contentScale = ContentScale.Fit,
|
||||||
colorFilter = ColorFilter.tint(color = MaterialTheme.colorScheme.onSurface),
|
alignment = Alignment.TopCenter,
|
||||||
contentDescription = null,
|
colorFilter = backgroundFilter,
|
||||||
)
|
contentDescription = null,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.matchParentSize()
|
.matchParentSize()
|
||||||
.background(brush = rememberBackgroundGradient())
|
.background(
|
||||||
|
brush = rememberBackgroundGradient(
|
||||||
|
from = backgroundGradientFrom,
|
||||||
|
to = backgroundGradientTo,
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
|
|
@ -118,13 +129,16 @@ fun LandingItem(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun rememberBackgroundGradient(): Brush {
|
private fun rememberBackgroundGradient(
|
||||||
|
@FloatRange(from = 0.0, to = 1.0) from: Float = 0.5f,
|
||||||
|
@FloatRange(from = 0.0, to = 1.0) to: Float = 1f,
|
||||||
|
): Brush {
|
||||||
val colorScheme = MaterialTheme.colorScheme
|
val colorScheme = MaterialTheme.colorScheme
|
||||||
return remember {
|
return remember {
|
||||||
Brush.verticalGradient(
|
Brush.verticalGradient(
|
||||||
colors = listOf(
|
colors = listOf(
|
||||||
colorScheme.surface.copy(alpha = 0.5f),
|
colorScheme.surface.copy(alpha = from),
|
||||||
colorScheme.surface.copy(alpha = 1.0f),
|
colorScheme.surface.copy(alpha = to),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,10 @@ import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Surface
|
import androidx.compose.material3.Surface
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.State
|
||||||
|
import androidx.compose.runtime.derivedStateOf
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.composed
|
import androidx.compose.ui.composed
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
|
|
@ -44,6 +48,7 @@ import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import com.pixelized.rplexicon.R
|
import com.pixelized.rplexicon.R
|
||||||
import com.pixelized.rplexicon.ui.composable.rememberBackgroundGradient
|
import com.pixelized.rplexicon.ui.composable.rememberBackgroundGradient
|
||||||
import com.pixelized.rplexicon.ui.navigation.LocalScreenNavHost
|
import com.pixelized.rplexicon.ui.navigation.LocalScreenNavHost
|
||||||
|
|
@ -59,7 +64,9 @@ import com.pixelized.rplexicon.utilitary.extentions.lexicon
|
||||||
import com.pixelized.rplexicon.utilitary.extentions.modifier.scrollOffset
|
import com.pixelized.rplexicon.utilitary.extentions.modifier.scrollOffset
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LandingScreen() {
|
fun LandingScreen(
|
||||||
|
viewModel: LandingViewModel = hiltViewModel(),
|
||||||
|
) {
|
||||||
val screen = LocalScreenNavHost.current
|
val screen = LocalScreenNavHost.current
|
||||||
|
|
||||||
Surface(
|
Surface(
|
||||||
|
|
@ -75,7 +82,10 @@ fun LandingScreen() {
|
||||||
end = 16.dp,
|
end = 16.dp,
|
||||||
bottom = 16.dp,
|
bottom = 16.dp,
|
||||||
),
|
),
|
||||||
onCharacter = { screen.navigateToCharacterSheet(name = it) },
|
characters = viewModel.landing,
|
||||||
|
onCharacter = { character ->
|
||||||
|
character.title?.let { screen.navigateToCharacterSheet(name = it) }
|
||||||
|
},
|
||||||
onSearch = {
|
onSearch = {
|
||||||
screen.navigateToSearch(
|
screen.navigateToSearch(
|
||||||
enableLexicon = true,
|
enableLexicon = true,
|
||||||
|
|
@ -103,13 +113,22 @@ private fun LandingContent(
|
||||||
bottom = 16.dp,
|
bottom = 16.dp,
|
||||||
),
|
),
|
||||||
sectionPadding: Dp = 32.dp,
|
sectionPadding: Dp = 32.dp,
|
||||||
onCharacter: (String) -> Unit,
|
characters: State<List<LandingItemUio>>,
|
||||||
|
onCharacter: (LandingItemUio) -> Unit,
|
||||||
onSearch: () -> Unit,
|
onSearch: () -> Unit,
|
||||||
onGameMaster: () -> Unit,
|
onGameMaster: () -> Unit,
|
||||||
onLexicon: () -> Unit,
|
onLexicon: () -> Unit,
|
||||||
onQuest: () -> Unit,
|
onQuest: () -> Unit,
|
||||||
onMap: () -> Unit,
|
onMap: () -> Unit,
|
||||||
) {
|
) {
|
||||||
|
val charactersSection = remember {
|
||||||
|
derivedStateOf {
|
||||||
|
characters.value
|
||||||
|
.groupBy { characters.value.indexOf(it) / 3 }
|
||||||
|
.values.toList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier.verticalScroll(scrollState),
|
modifier = modifier.verticalScroll(scrollState),
|
||||||
) {
|
) {
|
||||||
|
|
@ -174,86 +193,28 @@ private fun LandingContent(
|
||||||
text = stringResource(id = R.string.landing__caterogy__character),
|
text = stringResource(id = R.string.landing__caterogy__character),
|
||||||
)
|
)
|
||||||
|
|
||||||
Row(
|
charactersSection.value.forEach { charactersGroup ->
|
||||||
modifier = Modifier.fillMaxWidth(),
|
Row(
|
||||||
horizontalArrangement = Arrangement.spacedBy(space = 8.dp),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
) {
|
horizontalArrangement = Arrangement.spacedBy(space = 8.dp),
|
||||||
stringResource(id = R.string.landing__character_brulkhai).let { character ->
|
) {
|
||||||
LandingItem(
|
charactersGroup.forEach { character ->
|
||||||
modifier = Modifier
|
LandingItem(
|
||||||
.height(128.dp)
|
modifier = Modifier
|
||||||
.weight(1f),
|
.aspectRatio(0.8f)
|
||||||
imagePadding = PaddingValues(all = 8.dp),
|
.weight(1f),
|
||||||
item = LandingItemUio(
|
imagePadding = PaddingValues(bottom = 8.dp),
|
||||||
icon = R.drawable.ic_class_barbarian_24,
|
item = character,
|
||||||
title = character,
|
backgroundFilter = null,
|
||||||
subTitle = stringResource(id = R.string.class_barbarian),
|
backgroundGradientFrom = 0f,
|
||||||
),
|
backgroundGradientTo = 0.5f,
|
||||||
onClick = { onCharacter(character) },
|
onClick = { onCharacter(character) },
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
repeat(3 - charactersGroup.size) {
|
||||||
|
Spacer(modifier = Modifier.weight(1f))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
stringResource(id = R.string.landing__character_leandre).let { character ->
|
|
||||||
LandingItem(
|
|
||||||
modifier = Modifier
|
|
||||||
.height(128.dp)
|
|
||||||
.weight(1f),
|
|
||||||
imagePadding = PaddingValues(all = 8.dp),
|
|
||||||
item = LandingItemUio(
|
|
||||||
icon = R.drawable.ic_class_cleric_24,
|
|
||||||
title = character,
|
|
||||||
subTitle = stringResource(id = R.string.class_cleric),
|
|
||||||
),
|
|
||||||
onClick = { onCharacter(character) },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
stringResource(id = R.string.landing__character_nelia).let { character ->
|
|
||||||
LandingItem(
|
|
||||||
modifier = Modifier
|
|
||||||
.height(128.dp)
|
|
||||||
.weight(1f),
|
|
||||||
imagePadding = PaddingValues(all = 8.dp),
|
|
||||||
item = LandingItemUio(
|
|
||||||
icon = R.drawable.ic_class_ranger_24,
|
|
||||||
title = character,
|
|
||||||
subTitle = stringResource(id = R.string.class_ranger),
|
|
||||||
),
|
|
||||||
onClick = { onCharacter(character) },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Row(
|
|
||||||
modifier = Modifier.fillMaxWidth(),
|
|
||||||
horizontalArrangement = Arrangement.spacedBy(space = 8.dp),
|
|
||||||
) {
|
|
||||||
stringResource(id = R.string.landing__character_tigrane).let { character ->
|
|
||||||
LandingItem(
|
|
||||||
modifier = Modifier
|
|
||||||
.height(128.dp)
|
|
||||||
.weight(1f),
|
|
||||||
imagePadding = PaddingValues(all = 8.dp),
|
|
||||||
item = LandingItemUio(
|
|
||||||
icon = R.drawable.ic_class_warlock_24,
|
|
||||||
title = character,
|
|
||||||
subTitle = stringResource(id = R.string.class_warlock),
|
|
||||||
),
|
|
||||||
onClick = { onCharacter(character) },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
stringResource(id = R.string.landing__character_unathana).let { character ->
|
|
||||||
LandingItem(
|
|
||||||
modifier = Modifier
|
|
||||||
.height(128.dp)
|
|
||||||
.weight(1f),
|
|
||||||
imagePadding = PaddingValues(all = 8.dp),
|
|
||||||
item = LandingItemUio(
|
|
||||||
icon = R.drawable.ic_class_bard_24,
|
|
||||||
title = character,
|
|
||||||
subTitle = stringResource(id = R.string.class_bard),
|
|
||||||
),
|
|
||||||
onClick = { onCharacter(character) },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Spacer(modifier = Modifier.weight(1f))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
|
|
@ -392,6 +353,37 @@ private fun LandingPreview() {
|
||||||
Surface {
|
Surface {
|
||||||
LandingContent(
|
LandingContent(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
characters = remember {
|
||||||
|
mutableStateOf(
|
||||||
|
listOf(
|
||||||
|
LandingItemUio(
|
||||||
|
icon = R.drawable.icbg_class_barbarian,
|
||||||
|
title = "Brulkhai",
|
||||||
|
subTitle = "Barbarian, Warrior",
|
||||||
|
),
|
||||||
|
LandingItemUio(
|
||||||
|
icon = R.drawable.icbg_class_cleric,
|
||||||
|
title = "Léandre",
|
||||||
|
subTitle = "Cleric",
|
||||||
|
),
|
||||||
|
LandingItemUio(
|
||||||
|
icon = R.drawable.icbg_class_ranger,
|
||||||
|
title = "Nelia",
|
||||||
|
subTitle = "Ranger, Druid",
|
||||||
|
),
|
||||||
|
LandingItemUio(
|
||||||
|
icon = R.drawable.icbg_class_warlock,
|
||||||
|
title = "Tigrane",
|
||||||
|
subTitle = "Warlock",
|
||||||
|
),
|
||||||
|
LandingItemUio(
|
||||||
|
icon = R.drawable.icbg_class_bard,
|
||||||
|
title = "Unathana",
|
||||||
|
subTitle = "Bard",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
},
|
||||||
onCharacter = { },
|
onCharacter = { },
|
||||||
onSearch = { },
|
onSearch = { },
|
||||||
onGameMaster = { },
|
onGameMaster = { },
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.pixelized.rplexicon.ui.screens.landing
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import androidx.compose.runtime.State
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.lifecycle.AndroidViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
|
||||||
|
import com.pixelized.rplexicon.utilitary.extentions.context
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@HiltViewModel
|
||||||
|
class LandingViewModel @Inject constructor(
|
||||||
|
private val sheetRepository: CharacterSheetRepository,
|
||||||
|
application: Application,
|
||||||
|
) : AndroidViewModel(application = application) {
|
||||||
|
|
||||||
|
private val _landing = mutableStateOf<List<LandingItemUio>>(emptyList())
|
||||||
|
val landing: State<List<LandingItemUio>> = _landing
|
||||||
|
|
||||||
|
init {
|
||||||
|
viewModelScope.launch(Dispatchers.Default) {
|
||||||
|
sheetRepository.data.collectLatest { sheets ->
|
||||||
|
val landing = sheets.mapNotNull { entry ->
|
||||||
|
val icon = entry.value.characterClass.firstOrNull()?.icon
|
||||||
|
val title = entry.key
|
||||||
|
val subTitle = entry.value.characterClass
|
||||||
|
.map { context.getString(it.label) }
|
||||||
|
.joinToString(separator = ", ") { it }
|
||||||
|
|
||||||
|
LandingItemUio(
|
||||||
|
icon = icon,
|
||||||
|
title = title,
|
||||||
|
subTitle = subTitle,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
_landing.value = landing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -546,7 +546,7 @@ class SummaryFactory @Inject constructor(
|
||||||
} ?: none()
|
} ?: none()
|
||||||
|
|
||||||
// Update spells
|
// Update spells
|
||||||
val skill = sheet.characterClass.firstOrNull()?.resource?.let { skill ->
|
val skill = sheet.characterClass.firstOrNull()?.resourceId?.let { skill ->
|
||||||
fire?.skills?.get(skill)
|
fire?.skills?.get(skill)
|
||||||
}?.let { skill ->
|
}?.let { skill ->
|
||||||
label(label = "$skill")
|
label(label = "$skill")
|
||||||
|
|
|
||||||
|
|
@ -146,7 +146,7 @@ private object ResourcesCache {
|
||||||
"Transe" to R.drawable.icbg_focused_conjuration,
|
"Transe" to R.drawable.icbg_focused_conjuration,
|
||||||
"Attaque supplémentaire" to R.drawable.icbg_extra_attack,
|
"Attaque supplémentaire" to R.drawable.icbg_extra_attack,
|
||||||
"Apanage de la Noblesse" to R.drawable.icbg_natures_ward,
|
"Apanage de la Noblesse" to R.drawable.icbg_natures_ward,
|
||||||
"Druidique" to R.drawable.icbg_class_druid_badge,
|
"Druidique" to R.drawable.icbg_class_druid,
|
||||||
"Appel de familier" to R.drawable.icbg_find_familiar_cat,
|
"Appel de familier" to R.drawable.icbg_find_familiar_cat,
|
||||||
"Détection de la magie" to R.drawable.icbg_generic_psychic,
|
"Détection de la magie" to R.drawable.icbg_generic_psychic,
|
||||||
"Vision dans le noir (Tieffelin)" to R.drawable.icbg_darkvision,
|
"Vision dans le noir (Tieffelin)" to R.drawable.icbg_darkvision,
|
||||||
|
|
|
||||||
BIN
app/src/main/res/drawable/icbg_class_barbarian.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
app/src/main/res/drawable/icbg_class_bard.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
app/src/main/res/drawable/icbg_class_cleric.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
BIN
app/src/main/res/drawable/icbg_class_ranger.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
app/src/main/res/drawable/icbg_class_warlock.png
Normal file
|
After Width: | Height: | Size: 23 KiB |