diff --git a/app/src/main/java/org/mozilla/fenix/shopping/ui/ProductAnalysis.kt b/app/src/main/java/org/mozilla/fenix/shopping/ui/ProductAnalysis.kt index d03fe38b0..e8989b404 100644 --- a/app/src/main/java/org/mozilla/fenix/shopping/ui/ProductAnalysis.kt +++ b/app/src/main/java/org/mozilla/fenix/shopping/ui/ProductAnalysis.kt @@ -18,7 +18,6 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.material.Icon import androidx.compose.material.Text @@ -95,13 +94,6 @@ fun ProductAnalysis( description = stringResource(id = R.string.review_quality_check_no_reviews_warning_body), type = ReviewQualityCheckInfoType.Info, modifier = Modifier.fillMaxWidth(), - icon = { - Icon( - painter = painterResource(id = R.drawable.mozac_ic_information_fill_24), - contentDescription = null, - tint = FirefoxTheme.colors.iconPrimary, - ) - }, ) } @@ -154,16 +146,10 @@ private fun ReanalyzeCard( title = stringResource(R.string.review_quality_check_outdated_analysis_warning_title), type = ReviewQualityCheckInfoType.AnalysisUpdate, modifier = Modifier.fillMaxWidth(), - buttonText = stringResource(R.string.review_quality_check_outdated_analysis_warning_action), - onButtonClick = onReanalyzeClick, - icon = { - Icon( - painter = painterResource(id = R.drawable.mozac_ic_information_fill_24), - contentDescription = null, - modifier = Modifier.size(24.dp), - tint = FirefoxTheme.colors.iconPrimary, - ) - }, + buttonText = InfoCardButtonText( + text = stringResource(R.string.review_quality_check_outdated_analysis_warning_action), + onClick = onReanalyzeClick, + ), ) } @@ -171,13 +157,8 @@ private fun ReanalyzeCard( private fun ReanalysisInProgressCard() { ReviewQualityCheckInfoCard( title = stringResource(R.string.review_quality_check_reanalysis_in_progress_warning_title), - type = ReviewQualityCheckInfoType.AnalysisUpdate, + type = ReviewQualityCheckInfoType.Loading, modifier = Modifier.fillMaxWidth(), - icon = { - IndeterminateProgressIndicator( - modifier = Modifier.size(24.dp), - ) - }, ) } diff --git a/app/src/main/java/org/mozilla/fenix/shopping/ui/ProductAnalysisError.kt b/app/src/main/java/org/mozilla/fenix/shopping/ui/ProductAnalysisError.kt index decc44583..aa89d0585 100644 --- a/app/src/main/java/org/mozilla/fenix/shopping/ui/ProductAnalysisError.kt +++ b/app/src/main/java/org/mozilla/fenix/shopping/ui/ProductAnalysisError.kt @@ -4,16 +4,15 @@ package org.mozilla.fenix.shopping.ui +import androidx.annotation.StringRes import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.material.Icon import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import org.mozilla.fenix.R @@ -48,53 +47,43 @@ fun ProductAnalysisError( modifier = modifier, verticalArrangement = Arrangement.spacedBy(16.dp), ) { - when (error) { - ProductReviewState.Error.GenericError -> - ReviewQualityCheckInfoCard( - title = stringResource(id = R.string.review_quality_check_generic_error_title), - description = stringResource(id = R.string.review_quality_check_generic_error_body), - type = ReviewQualityCheckInfoType.Warning, - modifier = Modifier.fillMaxWidth(), - icon = { - Icon( - painter = painterResource(id = R.drawable.mozac_ic_warning_fill_24), - contentDescription = null, - tint = FirefoxTheme.colors.iconPrimary, - ) - }, + val ( + @StringRes titleResourceId: Int, + @StringRes descriptionResourceId: Int, + type: ReviewQualityCheckInfoType, + ) = when (error) { + ProductReviewState.Error.GenericError -> { + Triple( + R.string.review_quality_check_generic_error_title, + R.string.review_quality_check_generic_error_body, + ReviewQualityCheckInfoType.Info, ) + } - ProductReviewState.Error.NetworkError -> - ReviewQualityCheckInfoCard( - title = stringResource(id = R.string.review_quality_check_no_connection_title), - description = stringResource(id = R.string.review_quality_check_no_connection_body), - type = ReviewQualityCheckInfoType.Warning, - modifier = Modifier.fillMaxWidth(), - icon = { - Icon( - painter = painterResource(id = R.drawable.mozac_ic_warning_fill_24), - contentDescription = null, - tint = FirefoxTheme.colors.iconPrimary, - ) - }, + ProductReviewState.Error.NetworkError -> { + Triple( + R.string.review_quality_check_no_connection_title, + R.string.review_quality_check_no_connection_body, + ReviewQualityCheckInfoType.Warning, ) + } - ProductReviewState.Error.UnsupportedProductTypeError -> - ReviewQualityCheckInfoCard( - title = stringResource(id = R.string.review_quality_check_not_analyzable_info_title), - description = stringResource(id = R.string.review_quality_check_not_analyzable_info_body), - type = ReviewQualityCheckInfoType.Info, - modifier = Modifier.fillMaxWidth(), - icon = { - Icon( - painter = painterResource(id = R.drawable.mozac_ic_information_fill_24), - contentDescription = null, - tint = FirefoxTheme.colors.iconPrimary, - ) - }, + ProductReviewState.Error.UnsupportedProductTypeError -> { + Triple( + R.string.review_quality_check_not_analyzable_info_title, + R.string.review_quality_check_not_analyzable_info_body, + ReviewQualityCheckInfoType.Info, ) + } } + ReviewQualityCheckInfoCard( + title = stringResource(id = titleResourceId), + description = stringResource(id = descriptionResourceId), + type = type, + modifier = Modifier.fillMaxWidth(), + ) + ReviewQualityInfoCard( onLearnMoreClick = onReviewGradeLearnMoreClick, ) diff --git a/app/src/main/java/org/mozilla/fenix/shopping/ui/ReviewQualityCheckCards.kt b/app/src/main/java/org/mozilla/fenix/shopping/ui/ReviewQualityCheckCards.kt index 9f8e109c4..af739141d 100644 --- a/app/src/main/java/org/mozilla/fenix/shopping/ui/ReviewQualityCheckCards.kt +++ b/app/src/main/java/org/mozilla/fenix/shopping/ui/ReviewQualityCheckCards.kt @@ -10,6 +10,7 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth @@ -53,7 +54,7 @@ fun ReviewQualityCheckExpandableCard( ) { ReviewQualityCheckCard( modifier = modifier, - contentPadding = 0.dp, + contentPadding = PaddingValues(0.dp), ) { var isExpanded by remember { mutableStateOf(false) } @@ -113,7 +114,7 @@ fun ReviewQualityCheckCard( modifier: Modifier, backgroundColor: Color = FirefoxTheme.colors.layer2, elevation: Dp = defaultCardElevation, - contentPadding: Dp = defaultCardContentPadding, + contentPadding: PaddingValues = PaddingValues(defaultCardContentPadding), content: @Composable ColumnScope.() -> Unit, ) { Card( diff --git a/app/src/main/java/org/mozilla/fenix/shopping/ui/ReviewQualityCheckInfoCard.kt b/app/src/main/java/org/mozilla/fenix/shopping/ui/ReviewQualityCheckInfoCard.kt index 2cae0d088..5ef298d8f 100644 --- a/app/src/main/java/org/mozilla/fenix/shopping/ui/ReviewQualityCheckInfoCard.kt +++ b/app/src/main/java/org/mozilla/fenix/shopping/ui/ReviewQualityCheckInfoCard.kt @@ -8,6 +8,7 @@ import androidx.compose.foundation.background import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth @@ -15,8 +16,6 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.Card import androidx.compose.material.Icon import androidx.compose.material.Text import androidx.compose.runtime.Composable @@ -34,22 +33,15 @@ import org.mozilla.fenix.compose.annotation.LightDarkPreview import org.mozilla.fenix.compose.button.PrimaryButton import org.mozilla.fenix.theme.FirefoxTheme -private val cardShape = RoundedCornerShape(8.dp) - /** - * Review Quality Check info UI. + * Review Quality Check Info Card UI. * * @param title The primary text of the info message. * @param type The [ReviewQualityCheckInfoType] of message to display. * @param modifier Modifier to be applied to the card. * @param description The optional secondary piece of text. - * @param linkText An optional piece of text with a clickable substring. - * @param hyperlinkText The text within [linkText] that is clickable. - * @param linkURL The optional URL to return when the link is clicked. + * @param footer An optional piece of text with a clickable link. * @param buttonText The text to show in the optional button. - * @param onLinkClick Invoked when the link is clicked. When not-null, the link will be visible. - * @param onButtonClick Invoked when the button is clicked. When not-null, the button will be visible. - * @param icon The UI to display before the text, typically an image or loading spinner. */ @Composable fun ReviewQualityCheckInfoCard( @@ -57,77 +49,104 @@ fun ReviewQualityCheckInfoCard( type: ReviewQualityCheckInfoType, modifier: Modifier = Modifier, description: String? = null, - linkText: String = "", - hyperlinkText: String = "", - linkURL: String = "", - buttonText: String = "", - onLinkClick: (() -> Unit)? = null, - onButtonClick: (() -> Unit)? = null, - icon: @Composable () -> Unit, + footer: Pair? = null, + buttonText: InfoCardButtonText? = null, ) { - Card( + ReviewQualityCheckCard( modifier = modifier, - shape = cardShape, backgroundColor = type.cardBackgroundColor, + contentPadding = PaddingValues( + horizontal = 12.dp, + vertical = 8.dp, + ), elevation = 0.dp, ) { - Column(modifier = Modifier.padding(horizontal = 12.dp, vertical = 8.dp)) { - Row { - icon() + Row { + when (type) { + ReviewQualityCheckInfoType.Warning -> { + InfoCardIcon(iconId = R.drawable.mozac_ic_warning_fill_24) + } + + ReviewQualityCheckInfoType.Confirmation -> { + InfoCardIcon(iconId = R.drawable.mozac_ic_checkmark_24) + } + + ReviewQualityCheckInfoType.Error, + ReviewQualityCheckInfoType.Info, + ReviewQualityCheckInfoType.AnalysisUpdate, + -> { + InfoCardIcon( + iconId = R.drawable.mozac_ic_information_fill_24, + modifier = Modifier.size(24.dp), + ) + } - Spacer(modifier = Modifier.width(12.dp)) + ReviewQualityCheckInfoType.Loading -> { + IndeterminateProgressIndicator(modifier = Modifier.size(24.dp)) + } + } + + Spacer(modifier = Modifier.width(12.dp)) + + Column { + Text( + text = title, + color = FirefoxTheme.colors.textPrimary, + style = FirefoxTheme.typography.headline8, + ) + + description?.let { + Spacer(modifier = Modifier.height(4.dp)) - Column { Text( - text = title, + text = description, color = FirefoxTheme.colors.textPrimary, - style = FirefoxTheme.typography.headline8, + style = FirefoxTheme.typography.body2, ) + } - description?.let { - Spacer(modifier = Modifier.height(4.dp)) + footer?.let { + Spacer(modifier = Modifier.height(4.dp)) - Text( - text = description, + LinkText( + text = it.first, + linkTextState = it.second, + style = FirefoxTheme.typography.body2.copy( color = FirefoxTheme.colors.textPrimary, - style = FirefoxTheme.typography.body2, - ) - } - - onLinkClick?.let { - Spacer(modifier = Modifier.height(4.dp)) - - LinkText( - text = linkText, - linkTextState = LinkTextState( - text = hyperlinkText, - url = linkURL, - onClick = { onLinkClick() }, - ), - style = FirefoxTheme.typography.body2.copy( - color = FirefoxTheme.colors.textPrimary, - ), - linkTextColor = FirefoxTheme.colors.textPrimary, - linkTextDecoration = TextDecoration.Underline, - ) - } + ), + linkTextColor = FirefoxTheme.colors.textPrimary, + linkTextDecoration = TextDecoration.Underline, + ) } } + } - onButtonClick?.let { - Spacer(modifier = Modifier.height(8.dp)) + buttonText?.let { + Spacer(modifier = Modifier.height(8.dp)) - PrimaryButton( - text = buttonText, - textColor = type.buttonTextColor, - backgroundColor = type.buttonBackgroundColor, - onClick = onButtonClick, - ) - } + PrimaryButton( + text = it.text, + textColor = type.buttonTextColor, + backgroundColor = type.buttonBackgroundColor, + onClick = it.onClick, + ) } } } +@Composable +private fun InfoCardIcon( + iconId: Int, + modifier: Modifier = Modifier, +) { + Icon( + painter = painterResource(id = iconId), + contentDescription = null, + tint = FirefoxTheme.colors.iconPrimary, + modifier = modifier, + ) +} + /** * The possible types of a [ReviewQualityCheckInfoCard]. */ @@ -138,6 +157,7 @@ enum class ReviewQualityCheckInfoType { Error, Info, AnalysisUpdate, + Loading, ; val cardBackgroundColor: Color @@ -148,6 +168,7 @@ enum class ReviewQualityCheckInfoType { Error -> FirefoxTheme.colors.layerError Info -> FirefoxTheme.colors.layerInfo AnalysisUpdate -> Color.Transparent + Loading -> Color.Transparent } val buttonBackgroundColor: Color @@ -158,37 +179,38 @@ enum class ReviewQualityCheckInfoType { Error -> FirefoxTheme.colors.actionError Info -> FirefoxTheme.colors.actionInfo AnalysisUpdate -> FirefoxTheme.colors.actionSecondary + Loading -> FirefoxTheme.colors.actionSecondary } val buttonTextColor: Color @Composable get() = when { this == Info && !isSystemInDarkTheme() -> FirefoxTheme.colors.textOnColorPrimary - this == AnalysisUpdate -> FirefoxTheme.colors.textActionSecondary + this == AnalysisUpdate || this == Loading -> FirefoxTheme.colors.textActionSecondary else -> FirefoxTheme.colors.textPrimary } } -private class PreviewModel( - val messageType: ReviewQualityCheckInfoType, - val iconId: Int, +/** + * Model for the optional button in a [ReviewQualityCheckInfoCard]. + * + * @param text The text to show in the button. + * @param onClick The callback to invoke when the button is clicked. + */ +data class InfoCardButtonText( + val text: String, + val onClick: () -> Unit, ) -private class PreviewModelParameterProvider : PreviewParameterProvider { - override val values: Sequence - get() = sequenceOf( - PreviewModel(ReviewQualityCheckInfoType.Warning, R.drawable.mozac_ic_warning_fill_24), - PreviewModel(ReviewQualityCheckInfoType.Confirmation, R.drawable.mozac_ic_checkmark_24), - PreviewModel(ReviewQualityCheckInfoType.Error, R.drawable.mozac_ic_information_fill_24), - PreviewModel(ReviewQualityCheckInfoType.Info, R.drawable.mozac_ic_information_fill_24), - PreviewModel(ReviewQualityCheckInfoType.AnalysisUpdate, R.drawable.mozac_ic_information_fill_24), - ) +private class PreviewModelParameterProvider : PreviewParameterProvider { + + override val values = enumValues().asSequence() } @LightDarkPreview @Composable private fun InfoCardPreview( - @PreviewParameter(PreviewModelParameterProvider::class) model: PreviewModel, + @PreviewParameter(PreviewModelParameterProvider::class) type: ReviewQualityCheckInfoType, ) { FirefoxTheme { Box( @@ -198,22 +220,18 @@ private fun InfoCardPreview( ) { ReviewQualityCheckInfoCard( title = "Title text", - type = model.messageType, + type = type, modifier = Modifier.fillMaxWidth(), description = "Description text", - linkText = "Primary link text with an underlined hyperlink.", - hyperlinkText = "underlined hyperlink", - buttonText = "Button text", - onLinkClick = {}, - onButtonClick = {}, - icon = { - Icon( - painter = painterResource(id = model.iconId), - contentDescription = null, - modifier = Modifier.size(24.dp), - tint = FirefoxTheme.colors.iconPrimary, - ) - }, + footer = "Primary link text with an underlined hyperlink." to LinkTextState( + text = "underlined hyperlink", + url = "https://www.mozilla.org", + onClick = {}, + ), + buttonText = InfoCardButtonText( + text = "Button text", + onClick = {}, + ), ) } }