Change a bit the UI on the alteration drawer menu.

This commit is contained in:
Thomas Andres Gomez 2023-09-27 18:28:20 +02:00
parent 03dd4939b4
commit 255ad7aed8
6 changed files with 209 additions and 77 deletions

View file

@ -37,10 +37,12 @@ fun IndicatorStep(
selectedIndex: Int?, selectedIndex: Int?,
defaultSize: Dp = 4.dp, defaultSize: Dp = 4.dp,
selectedWidth: Dp = 16.dp, selectedWidth: Dp = 16.dp,
indicatorSpacing: Dp = 8.dp, indicatorSpacing: Dp = 4.dp,
defaultColor: Color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.35f),
selectedColor: Color = MaterialTheme.colorScheme.primary,
) { ) {
val colorScheme = MaterialTheme.colorScheme
val defaultColor = remember { colorScheme.onSurface.copy(alpha = 0.35f) }
val selectedColor = remember { colorScheme.primary }
Row(modifier = modifier) { Row(modifier = modifier) {
repeat(count) { index -> repeat(count) { index ->
val transition = rememberIndicatorTransition( val transition = rememberIndicatorTransition(

View file

@ -0,0 +1,51 @@
package com.pixelized.rplexicon.ui.composable
import androidx.compose.material3.DrawerDefaults
import androidx.compose.material3.DrawerState
import androidx.compose.material3.DrawerValue
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.rememberDrawerState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.unit.LayoutDirection
@Composable
fun ModalNavigationDrawer(
drawerContent: @Composable () -> Unit,
modifier: Modifier = Modifier,
drawerState: DrawerState = rememberDrawerState(DrawerValue.Closed),
gesturesEnabled: Boolean = true,
scrimColor: Color = DrawerDefaults.scrimColor,
layoutDirection: LayoutDirection = LayoutDirection.Ltr,
content: @Composable () -> Unit
) {
val currentLayoutDirection = LocalLayoutDirection.current
CompositionLocalProvider(
LocalLayoutDirection provides layoutDirection,
) {
androidx.compose.material3.ModalNavigationDrawer(
modifier = modifier,
drawerState = drawerState,
gesturesEnabled = gesturesEnabled,
scrimColor = scrimColor,
drawerContent = {
CompositionLocalProvider(
LocalLayoutDirection provides currentLayoutDirection,
) {
drawerContent()
}
},
content = {
CompositionLocalProvider(
LocalLayoutDirection provides currentLayoutDirection,
) {
content()
}
},
)
}
}

View file

@ -108,12 +108,11 @@ fun ActionsPageContent(
LazyColumn( LazyColumn(
modifier = modifier, modifier = modifier,
state = lazyListState, state = lazyListState,
contentPadding = PaddingValues(vertical = 16.dp), contentPadding = PaddingValues(vertical = 8.dp),
verticalArrangement = Arrangement.spacedBy(space = 16.dp),
) { ) {
items(items = attacks.value) { items(items = attacks.value) {
Attack( Attack(
modifier = Modifier.padding(horizontal = 16.dp), modifier = Modifier.padding(vertical = 8.dp, horizontal = 16.dp),
weapon = it, weapon = it,
onHit = onAttackHit, onHit = onAttackHit,
onDamage = onAttackDamage, onDamage = onAttackDamage,
@ -123,13 +122,14 @@ fun ActionsPageContent(
spells.value.forEach { entry -> spells.value.forEach { entry ->
stickyHeader { stickyHeader {
SpellHeader( SpellHeader(
modifier = Modifier.padding(top = 8.dp, bottom = 4.dp),
header = entry.first, header = entry.first,
) )
} }
items(items = entry.second) { items(items = entry.second) {
Spell( Spell(
modifier = Modifier.padding(horizontal = 16.dp), modifier = Modifier.padding(vertical = 8.dp, horizontal = 16.dp),
spell = it, spell = it,
onClick = onSpell, onClick = onSpell,
onHit = onSpellHit, onHit = onSpellHit,

View file

@ -12,7 +12,7 @@ import androidx.compose.animation.slideOutVertically
import androidx.compose.animation.togetherWith import androidx.compose.animation.togetherWith
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
@ -20,15 +20,16 @@ import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Close import androidx.compose.material.icons.outlined.Close
import androidx.compose.material.icons.outlined.Menu
import androidx.compose.material3.DrawerState import androidx.compose.material3.DrawerState
import androidx.compose.material3.DrawerValue import androidx.compose.material3.DrawerValue
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.ModalNavigationDrawer import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberDrawerState import androidx.compose.material3.rememberDrawerState
@ -47,9 +48,12 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import com.pixelized.rplexicon.LocalRollOverlay import com.pixelized.rplexicon.LocalRollOverlay
@ -57,6 +61,7 @@ import com.pixelized.rplexicon.NO_WINDOW_INSETS
import com.pixelized.rplexicon.R import com.pixelized.rplexicon.R
import com.pixelized.rplexicon.model.Roll import com.pixelized.rplexicon.model.Roll
import com.pixelized.rplexicon.ui.composable.BlurredOverlayHostState import com.pixelized.rplexicon.ui.composable.BlurredOverlayHostState
import com.pixelized.rplexicon.ui.composable.ModalNavigationDrawer
import com.pixelized.rplexicon.ui.screens.rolls.composable.RollAlteration import com.pixelized.rplexicon.ui.screens.rolls.composable.RollAlteration
import com.pixelized.rplexicon.ui.screens.rolls.composable.RollAlterationUio import com.pixelized.rplexicon.ui.screens.rolls.composable.RollAlterationUio
import com.pixelized.rplexicon.ui.screens.rolls.composable.RollDice import com.pixelized.rplexicon.ui.screens.rolls.composable.RollDice
@ -64,6 +69,7 @@ import com.pixelized.rplexicon.ui.screens.rolls.composable.RollDiceUio
import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowsCard import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowsCard
import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowsCardUio import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowsCardUio
import com.pixelized.rplexicon.ui.theme.LexiconTheme import com.pixelized.rplexicon.ui.theme.LexiconTheme
import com.pixelized.rplexicon.utilitary.extentions.lexicon
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@Composable @Composable
@ -84,6 +90,9 @@ fun RollOverlay(
onMenu = { onMenu = {
scope.launch { drawer.open() } scope.launch { drawer.open() }
}, },
onMenuClose = {
scope.launch { drawer.close() }
},
onClose = { onClose = {
overlay.hideOverlay() overlay.hideOverlay()
}, },
@ -113,6 +122,7 @@ private fun RollOverlayContent(
alterations: State<List<RollAlterationUio>>, alterations: State<List<RollAlterationUio>>,
showDetail: State<Boolean>, showDetail: State<Boolean>,
onMenu: () -> Unit, onMenu: () -> Unit,
onMenuClose: () -> Unit,
onClose: () -> Unit, onClose: () -> Unit,
onDice: () -> Unit, onDice: () -> Unit,
onCard: () -> Unit, onCard: () -> Unit,
@ -129,18 +139,48 @@ private fun RollOverlayContent(
modifier = modifier, modifier = modifier,
drawerState = drawer, drawerState = drawer,
gesturesEnabled = enableDrawer.value, gesturesEnabled = enableDrawer.value,
layoutDirection = LayoutDirection.Rtl,
drawerContent = { drawerContent = {
Surface { Surface {
LazyColumn( Column {
modifier = Modifier Text(
.fillMaxHeight() modifier = Modifier.padding(horizontal = 16.dp),
.fillMaxWidth(4f / 5f), style = MaterialTheme.typography.titleMedium,
) { text = stringResource(id = R.string.dice_roll_alteraton_action).let {
items(items = alterations.value) { AnnotatedString(
RollAlteration( text = it,
modifier = Modifier.fillMaxWidth(), spanStyles = listOf(
alteration = it, AnnotatedString.Range(
onClick = onAlteration, item = MaterialTheme.lexicon.typography.bodyDropCapSpan,
start = 0,
end = Integer.min(1, it.length),
)
)
)
},
)
LazyColumn(
modifier = Modifier
.weight(weight = 1f)
.fillMaxWidth(4f / 5f),
) {
items(items = alterations.value) {
RollAlteration(
modifier = Modifier.fillMaxWidth(),
alteration = it,
onClick = onAlteration,
)
}
}
TextButton(
modifier = Modifier.align(alignment = Alignment.End),
onClick = onMenuClose,
) {
Text(
modifier = Modifier.padding(horizontal = 8.dp),
text = stringResource(id = R.string.action_close),
) )
} }
} }
@ -154,16 +194,6 @@ private fun RollOverlayContent(
TopAppBar( TopAppBar(
colors = TopAppBarDefaults.topAppBarColors(containerColor = Color.Transparent), colors = TopAppBarDefaults.topAppBarColors(containerColor = Color.Transparent),
title = { }, title = { },
navigationIcon = {
if (enableDrawer.value) {
IconButton(onClick = onMenu) {
Icon(
imageVector = Icons.Outlined.Menu,
contentDescription = null,
)
}
}
},
actions = { actions = {
IconButton(onClick = onClose) { IconButton(onClick = onClose) {
Icon( Icon(
@ -191,8 +221,7 @@ private fun RollOverlayContent(
AnimatedContent( AnimatedContent(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.align(Alignment.BottomCenter) .align(Alignment.BottomCenter),
.padding(all = 16.dp),
targetState = card.value, targetState = card.value,
transitionSpec = { transitionSpec = {
val enter = val enter =
@ -207,11 +236,24 @@ private fun RollOverlayContent(
when (it) { when (it) {
null -> Box( null -> Box(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
) contentAlignment = Alignment.BottomEnd,
) {
if (enableDrawer.value) {
TextButton(
onClick = onMenu,
) {
Text(
modifier = Modifier.padding(horizontal = 8.dp),
text = stringResource(id = R.string.dice_roll_alteraton_action),
)
}
}
}
else -> ThrowsCard( else -> ThrowsCard(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(all = 16.dp)
.clickable(onClick = onCard), .clickable(onClick = onCard),
throws = it, throws = it,
showDetail = showDetail, showDetail = showDetail,
@ -229,56 +271,19 @@ private fun RollOverlayContent(
@Preview(uiMode = UI_MODE_NIGHT_NO) @Preview(uiMode = UI_MODE_NIGHT_NO)
@Preview(uiMode = UI_MODE_NIGHT_YES) @Preview(uiMode = UI_MODE_NIGHT_YES)
private fun RollOverlayPreview( private fun RollOverlayPreview(
@PreviewParameter(RollOverlayPreviewProvider::class) preview: DrawerValue @PreviewParameter(RollOverlayPreviewProvider::class) preview: RollOverlayPreviewUio
) { ) {
LexiconTheme { LexiconTheme {
Surface { Surface {
RollOverlayContent( RollOverlayContent(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
drawer = rememberDrawerState(initialValue = preview), drawer = rememberDrawerState(initialValue = preview.drawer),
dice = remember { dice = preview.dice,
mutableStateOf( card = preview.card,
RollDiceUio(
icon = R.drawable.ic_d20_24,
isCriticalSuccess = true,
result = "20",
)
)
},
card = remember {
mutableStateOf<ThrowsCardUio?>(
ThrowsCardUio(
title = "PERCEPTION CHECK",
highlight = "CHECK",
dice = R.drawable.ic_d20_24,
roll = "$20 + 2 + 2",
result = "20",
isCriticalSuccess = true,
details = listOf(
ThrowsCardUio.Detail(
throws = ThrowsCardUio.Throw(
dice = R.drawable.ic_d20_24,
roll = "1d20",
result = "20"
),
result = "20"
),
ThrowsCardUio.Detail(
title = "Wisdom bonus",
result = "2",
),
ThrowsCardUio.Detail(
title = "Proficiency bonus",
result = "2",
),
),
)
)
},
alterations = remember { alterations = remember {
mutableStateOf( mutableStateOf(
listOf( listOf(
RollAlterationUio(label = "Critique", checked = false), RollAlterationUio(label = "Critique", checked = true),
) )
) )
}, },
@ -286,6 +291,7 @@ private fun RollOverlayPreview(
mutableStateOf(true) mutableStateOf(true)
}, },
onMenu = { }, onMenu = { },
onMenuClose = { },
onClose = { }, onClose = { },
onDice = { }, onDice = { },
onCard = { }, onCard = { },
@ -295,8 +301,75 @@ private fun RollOverlayPreview(
} }
} }
private class RollOverlayPreviewProvider : PreviewParameterProvider<DrawerValue> { @Stable
override val values: Sequence<DrawerValue> = sequenceOf(DrawerValue.Closed, DrawerValue.Open) private data class RollOverlayPreviewUio(
val drawer: DrawerValue,
val dice: State<RollDiceUio>,
val card: State<ThrowsCardUio?>,
)
private class RollOverlayPreviewProvider : PreviewParameterProvider<RollOverlayPreviewUio> {
override val values: Sequence<RollOverlayPreviewUio> = sequenceOf(
RollOverlayPreviewUio(
drawer = DrawerValue.Closed,
dice = mutableStateOf(
RollDiceUio(
icon = R.drawable.ic_d20_24,
result = null,
)
),
card = mutableStateOf(null),
),
RollOverlayPreviewUio(
drawer = DrawerValue.Closed,
dice = mutableStateOf(
RollDiceUio(
icon = R.drawable.ic_d20_24,
isCriticalSuccess = true,
result = "20",
)
),
card = mutableStateOf(
ThrowsCardUio(
title = "PERCEPTION CHECK",
highlight = "CHECK",
dice = R.drawable.ic_d20_24,
roll = "$20 + 2 + 2",
result = "20",
isCriticalSuccess = true,
details = listOf(
ThrowsCardUio.Detail(
throws = ThrowsCardUio.Throw(
dice = R.drawable.ic_d20_24,
roll = "1d20",
result = "20"
),
result = "20"
),
ThrowsCardUio.Detail(
title = "Wisdom bonus",
result = "2",
),
ThrowsCardUio.Detail(
title = "Proficiency bonus",
result = "2",
),
),
)
)
),
RollOverlayPreviewUio(
drawer = DrawerValue.Open,
dice = mutableStateOf(
RollDiceUio(
icon = R.drawable.ic_d20_24,
isCriticalSuccess = true,
result = "20",
)
),
card = mutableStateOf(null),
),
)
} }
@Stable @Stable

View file

@ -1,6 +1,8 @@
<resources> <resources>
<string name="app_name">Rp-Compagnon</string> <string name="app_name">Rp-Compagnon</string>
<string name="action_close">Fermer</string>
<string name="error_generic">Une erreur s\'est produite.</string> <string name="error_generic">Une erreur s\'est produite.</string>
<string name="error_structure">La structure du fichier semble avoir changé et n\'est plus compatible avec cette application.</string> <string name="error_structure">La structure du fichier semble avoir changé et n\'est plus compatible avec cette application.</string>
@ -128,6 +130,7 @@
<string name="dice_roll_spell_hit_title">Jet de sort : \"%1$s"</string> <string name="dice_roll_spell_hit_title">Jet de sort : \"%1$s"</string>
<string name="dice_roll_spell_damage_title">Jet de dommage : \"%1$s\"</string> <string name="dice_roll_spell_damage_title">Jet de dommage : \"%1$s\"</string>
<string name="dice_roll_critical_label">Critique</string> <string name="dice_roll_critical_label">Critique</string>
<string name="dice_roll_alteraton_action">Alterations</string>
<string name="dice_roll_saving_throw_title">JET DE SAUVEGARDE : %1$s</string> <string name="dice_roll_saving_throw_title">JET DE SAUVEGARDE : %1$s</string>
<string name="dice_roll_saving_throw_detail">Sauvegarde de \"%1$s\"</string> <string name="dice_roll_saving_throw_detail">Sauvegarde de \"%1$s\"</string>

View file

@ -1,6 +1,8 @@
<resources> <resources>
<string name="app_name">Rp-Companion</string> <string name="app_name">Rp-Companion</string>
<string name="action_close">Close</string>
<string name="error_generic">An error occur.</string> <string name="error_generic">An error occur.</string>
<string name="error_structure">The file structure appears to have changed and is no longer compatible with this application</string> <string name="error_structure">The file structure appears to have changed and is no longer compatible with this application</string>
@ -128,6 +130,7 @@
<string name="dice_roll_spell_hit_title">%1$s HIT</string> <string name="dice_roll_spell_hit_title">%1$s HIT</string>
<string name="dice_roll_spell_damage_title">%1$s DAMAGE</string> <string name="dice_roll_spell_damage_title">%1$s DAMAGE</string>
<string name="dice_roll_critical_label">Critical</string> <string name="dice_roll_critical_label">Critical</string>
<string name="dice_roll_alteraton_action">Altérations</string>
<string name="dice_roll_saving_throw_title">%1$s SAVING THROW</string> <string name="dice_roll_saving_throw_title">%1$s SAVING THROW</string>
<string name="dice_roll_saving_throw_detail">%1$s save</string> <string name="dice_roll_saving_throw_detail">%1$s save</string>