From d413a13043c045e07c24f9e7d64dce638f783698 Mon Sep 17 00:00:00 2001 From: Gibran Chevalley Date: Thu, 17 Oct 2024 10:54:46 +0200 Subject: [PATCH] Add the possibility to make button load --- .../swisstransfer/ui/components/Buttons.kt | 108 ++++++++++++++++-- 1 file changed, 101 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/Buttons.kt b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/Buttons.kt index 68da741e6..f835a4ea1 100644 --- a/app/src/main/java/com/infomaniak/swisstransfer/ui/components/Buttons.kt +++ b/app/src/main/java/com/infomaniak/swisstransfer/ui/components/Buttons.kt @@ -22,7 +22,12 @@ import androidx.annotation.StringRes import androidx.compose.foundation.layout.* import androidx.compose.material3.* import androidx.compose.runtime.Composable +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.alpha import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource @@ -37,28 +42,60 @@ import com.infomaniak.swisstransfer.ui.theme.Dimens import com.infomaniak.swisstransfer.ui.theme.Margin import com.infomaniak.swisstransfer.ui.theme.SwissTransferTheme + +/** + * Specifying a progress has the priority over specifying showIndeterminateProgress + */ @Composable fun LargeButton( @StringRes titleRes: Int, modifier: Modifier = Modifier, style: ButtonType = ButtonType.PRIMARY, enabled: () -> Boolean = { true }, + showIndeterminateProgress: () -> Boolean = { false }, + determinateProgress: (() -> Float)? = null, onClick: () -> Unit, imageVector: ImageVector? = null, ) { - CoreButton(titleRes, modifier, ButtonSize.LARGE, style, enabled, onClick, imageVector) + CoreButton( + titleRes, + modifier, + ButtonSize.LARGE, + style, + enabled, + showIndeterminateProgress, + determinateProgress, + onClick, + imageVector, + ) } + +/** + * Specifying a progress has the priority over specifying showIndeterminateProgress + */ @Composable fun SmallButton( @StringRes titleRes: Int, modifier: Modifier = Modifier, style: ButtonType = ButtonType.PRIMARY, enabled: () -> Boolean = { true }, + showIndeterminateProgress: () -> Boolean = { false }, + determinateProgress: (() -> Float)? = null, onClick: () -> Unit, imageVector: ImageVector? = null, ) { - CoreButton(titleRes, modifier, ButtonSize.SMALL, style, enabled, onClick, imageVector) + CoreButton( + titleRes, + modifier, + ButtonSize.SMALL, + style, + enabled, + showIndeterminateProgress, + determinateProgress, + onClick, + imageVector, + ) } @Composable @@ -68,16 +105,46 @@ private fun CoreButton( buttonSize: ButtonSize, style: ButtonType, enabled: () -> Boolean, + showIndeterminateProgress: () -> Boolean, + progress: (() -> Float)?, onClick: () -> Unit, imageVector: ImageVector?, ) { + val isEnabled by remember { derivedStateOf { enabled() || showIndeterminateProgress() } } + val buttonColors = style.buttonColors() + Button( modifier = modifier.height(buttonSize.height), - colors = style.buttonColors(), + colors = buttonColors, shape = CustomShapes.medium, - enabled = enabled(), + enabled = isEnabled, onClick = onClick, ) { + when { + progress != null -> { + val (progressColor, progressModifier) = getProgressSpecs(buttonColors) + Box(contentAlignment = Alignment.Center) { + ButtonTextContent(imageVector, titleRes, Modifier.alpha(0f)) + CircularProgressIndicator(modifier = progressModifier, color = progressColor, progress = progress) + } + } + showIndeterminateProgress() -> { + val (progressColor, progressModifier) = getProgressSpecs(buttonColors) + Box(contentAlignment = Alignment.Center) { + ButtonTextContent(imageVector, titleRes, Modifier.alpha(0f)) + CircularProgressIndicator(modifier = progressModifier, color = progressColor) + } + } + else -> { + ButtonTextContent(imageVector, titleRes) + } + } + } +} + +@Composable +private fun ButtonTextContent(imageVector: ImageVector?, titleRes: Int, modifier: Modifier = Modifier) { + Row(modifier = modifier) { imageVector?.let { Icon(modifier = Modifier.size(Margin.Medium), imageVector = it, contentDescription = null) Spacer(modifier = Modifier.width(Margin.Small)) @@ -86,6 +153,15 @@ private fun CoreButton( } } +@Composable +private fun getProgressSpecs(buttonColors: ButtonColors): Pair { + val progressColor = buttonColors.contentColor + val progressModifier = Modifier + .fillMaxHeight(0.8f) + .aspectRatio(1f) + return Pair(progressColor, progressModifier) +} + enum class ButtonType(val buttonColors: @Composable () -> ButtonColors) { PRIMARY({ ButtonDefaults.buttonColors( @@ -118,8 +194,8 @@ private enum class ButtonSize(val height: Dp) { SMALL(40.dp), } -@Preview(name = "Light") -@Preview(name = "Dark", uiMode = Configuration.UI_MODE_NIGHT_YES or Configuration.UI_MODE_TYPE_NORMAL) +@Preview(name = "Light", widthDp = 800) +@Preview(name = "Dark", widthDp = 800, uiMode = Configuration.UI_MODE_NIGHT_YES or Configuration.UI_MODE_TYPE_NORMAL) @Composable private fun LargeButtonPreview() { SwissTransferTheme { @@ -127,9 +203,27 @@ private fun LargeButtonPreview() { Column { ButtonType.entries.forEach { Row { - LargeButton(titleRes = R.string.appName, style = it, imageVector = AppIcons.Add, onClick = {}) + LargeButton(titleRes = R.string.appName, style = it, onClick = {}, imageVector = AppIcons.Add) + Spacer(modifier = Modifier.width(Margin.Small)) + LargeButton( + titleRes = R.string.appName, + style = it, + determinateProgress = { 0.3f }, + onClick = {}, + imageVector = AppIcons.Add + ) + Spacer(modifier = Modifier.width(Margin.Small)) + SmallButton(titleRes = R.string.appName, style = it, imageVector = AppIcons.Add, onClick = {}) + Spacer(modifier = Modifier.width(Margin.Small)) + SmallButton( + titleRes = R.string.appName, + style = it, + determinateProgress = { 0.3f }, + imageVector = AppIcons.Add, + onClick = {} + ) } Spacer(modifier = Modifier.height(Margin.Medium)) }