Bug 1854631 - Refactor review checker info card

fenix/119.0
rahulsainani 8 months ago committed by mergify[bot]
parent 0cdbfdc829
commit 18ef60af4e

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

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

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

@ -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<String, LinkTextState>? = 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<PreviewModel> {
override val values: Sequence<PreviewModel>
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<ReviewQualityCheckInfoType> {
override val values = enumValues<ReviewQualityCheckInfoType>().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 = {},
),
)
}
}

Loading…
Cancel
Save