mirror of
https://github.com/fork-maintainers/iceraven-browser
synced 2024-11-03 23:15:31 +00:00
Bug 1850407 - Add nimbus flag for review checker product recommendations
This commit is contained in:
parent
0e0596121e
commit
8eb81afee5
@ -199,6 +199,9 @@ shopping-experience:
|
|||||||
enabled:
|
enabled:
|
||||||
type: boolean
|
type: boolean
|
||||||
description: "if true, the shopping experience feature is shown to the user."
|
description: "if true, the shopping experience feature is shown to the user."
|
||||||
|
product-recommendations:
|
||||||
|
type: boolean
|
||||||
|
description: "if true, recommended products feature is enabled to be shown to the user based on their preference."
|
||||||
splash-screen:
|
splash-screen:
|
||||||
description: "A feature that extends splash screen duration, allowing additional data fetching time for the app's initial run."
|
description: "A feature that extends splash screen duration, allowing additional data fetching time for the app's initial run."
|
||||||
hasExposure: true
|
hasExposure: true
|
||||||
|
@ -346,6 +346,10 @@ features:
|
|||||||
description: if true, the shopping experience feature is shown to the user.
|
description: if true, the shopping experience feature is shown to the user.
|
||||||
type: Boolean
|
type: Boolean
|
||||||
default: false
|
default: false
|
||||||
|
product-recommendations:
|
||||||
|
description: if true, recommended products feature is enabled to be shown to the user based on their preference.
|
||||||
|
type: Boolean
|
||||||
|
default: false
|
||||||
defaults:
|
defaults:
|
||||||
- channel: developer
|
- channel: developer
|
||||||
value:
|
value:
|
||||||
|
@ -6,6 +6,7 @@ package org.mozilla.fenix.shopping.middleware
|
|||||||
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
import org.mozilla.fenix.nimbus.FxNimbus
|
||||||
import org.mozilla.fenix.utils.Settings
|
import org.mozilla.fenix.utils.Settings
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -18,9 +19,10 @@ interface ReviewQualityCheckPreferences {
|
|||||||
suspend fun enabled(): Boolean
|
suspend fun enabled(): Boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the user has enabled product recommendations.
|
* Returns true if the user has turned on product recommendations, false if turned off by the
|
||||||
|
* user, null if the product recommendations feature is disabled.
|
||||||
*/
|
*/
|
||||||
suspend fun productRecommendationsEnabled(): Boolean
|
suspend fun productRecommendationsEnabled(): Boolean?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets whether the user has opted in to the review quality check feature.
|
* Sets whether the user has opted in to the review quality check feature.
|
||||||
@ -28,7 +30,7 @@ interface ReviewQualityCheckPreferences {
|
|||||||
suspend fun setEnabled(isEnabled: Boolean)
|
suspend fun setEnabled(isEnabled: Boolean)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets whether the user has enabled product recommendations.
|
* Sets user preference to turn on/off product recommendations.
|
||||||
*/
|
*/
|
||||||
suspend fun setProductRecommendationsEnabled(isEnabled: Boolean)
|
suspend fun setProductRecommendationsEnabled(isEnabled: Boolean)
|
||||||
|
|
||||||
@ -52,8 +54,12 @@ class ReviewQualityCheckPreferencesImpl(
|
|||||||
settings.isReviewQualityCheckEnabled
|
settings.isReviewQualityCheckEnabled
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun productRecommendationsEnabled(): Boolean = withContext(Dispatchers.IO) {
|
override suspend fun productRecommendationsEnabled(): Boolean? = withContext(Dispatchers.IO) {
|
||||||
settings.isReviewQualityCheckProductRecommendationsEnabled
|
if (FxNimbus.features.shoppingExperience.value().productRecommendations) {
|
||||||
|
settings.isReviewQualityCheckProductRecommendationsEnabled
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun setEnabled(isEnabled: Boolean) {
|
override suspend fun setEnabled(isEnabled: Boolean) {
|
||||||
|
@ -86,9 +86,13 @@ class ReviewQualityCheckPreferencesMiddleware(
|
|||||||
|
|
||||||
ReviewQualityCheckAction.ToggleProductRecommendation -> {
|
ReviewQualityCheckAction.ToggleProductRecommendation -> {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
reviewQualityCheckPreferences.setProductRecommendationsEnabled(
|
val productRecommendationsEnabled =
|
||||||
!reviewQualityCheckPreferences.productRecommendationsEnabled(),
|
reviewQualityCheckPreferences.productRecommendationsEnabled()
|
||||||
)
|
if (productRecommendationsEnabled != null) {
|
||||||
|
reviewQualityCheckPreferences.setProductRecommendationsEnabled(
|
||||||
|
!productRecommendationsEnabled,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,10 +54,14 @@ sealed interface ReviewQualityCheckAction : Action {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Triggered as a result of a [PreferencesMiddlewareAction] to update the state.
|
* Triggered as a result of a [PreferencesMiddlewareAction] to update the state.
|
||||||
|
*
|
||||||
|
* @property hasUserOptedIn True when user has opted in for shopping experience.
|
||||||
|
* @property isProductRecommendationsEnabled Reflects the user preference update to display
|
||||||
|
* recommended product. Null when product recommendations feature is disabled.
|
||||||
*/
|
*/
|
||||||
data class UpdateUserPreferences(
|
data class UpdateUserPreferences(
|
||||||
val hasUserOptedIn: Boolean,
|
val hasUserOptedIn: Boolean,
|
||||||
val isProductRecommendationsEnabled: Boolean,
|
val isProductRecommendationsEnabled: Boolean?,
|
||||||
) : UpdateAction
|
) : UpdateAction
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,11 +29,12 @@ sealed interface ReviewQualityCheckState : State {
|
|||||||
*
|
*
|
||||||
* @property productReviewState The state of the product the user is browsing.
|
* @property productReviewState The state of the product the user is browsing.
|
||||||
* @property productRecommendationsPreference User preference whether to show product
|
* @property productRecommendationsPreference User preference whether to show product
|
||||||
* recommendations. True if product recommendations should be shown.
|
* recommendations. True if product recommendations should be shown. Null indicates that product
|
||||||
|
* recommendations are disabled.
|
||||||
*/
|
*/
|
||||||
data class OptedIn(
|
data class OptedIn(
|
||||||
val productReviewState: ProductReviewState = ProductReviewState.Loading,
|
val productReviewState: ProductReviewState = ProductReviewState.Loading,
|
||||||
val productRecommendationsPreference: Boolean,
|
val productRecommendationsPreference: Boolean?,
|
||||||
) : ReviewQualityCheckState {
|
) : ReviewQualityCheckState {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -58,7 +58,7 @@ private fun mapStateForUpdateAction(
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReviewQualityCheckAction.ToggleProductRecommendation -> {
|
ReviewQualityCheckAction.ToggleProductRecommendation -> {
|
||||||
if (state is ReviewQualityCheckState.OptedIn) {
|
if (state is ReviewQualityCheckState.OptedIn && state.productRecommendationsPreference != null) {
|
||||||
state.copy(productRecommendationsPreference = !state.productRecommendationsPreference)
|
state.copy(productRecommendationsPreference = !state.productRecommendationsPreference)
|
||||||
} else {
|
} else {
|
||||||
state
|
state
|
||||||
|
@ -58,7 +58,7 @@ import org.mozilla.fenix.theme.FirefoxTheme
|
|||||||
@Composable
|
@Composable
|
||||||
@Suppress("LongParameterList")
|
@Suppress("LongParameterList")
|
||||||
fun ProductAnalysis(
|
fun ProductAnalysis(
|
||||||
productRecommendationsEnabled: Boolean,
|
productRecommendationsEnabled: Boolean?,
|
||||||
productAnalysis: AnalysisPresent,
|
productAnalysis: AnalysisPresent,
|
||||||
onOptOutClick: () -> Unit,
|
onOptOutClick: () -> Unit,
|
||||||
onReanalyzeClick: () -> Unit,
|
onReanalyzeClick: () -> Unit,
|
||||||
|
@ -29,7 +29,7 @@ import org.mozilla.fenix.theme.FirefoxTheme
|
|||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun ProductAnalysisError(
|
fun ProductAnalysisError(
|
||||||
productRecommendationsEnabled: Boolean,
|
productRecommendationsEnabled: Boolean?,
|
||||||
onReviewGradeLearnMoreClick: (String) -> Unit,
|
onReviewGradeLearnMoreClick: (String) -> Unit,
|
||||||
onOptOutClick: () -> Unit,
|
onOptOutClick: () -> Unit,
|
||||||
onProductRecommendationsEnabledStateChange: (Boolean) -> Unit,
|
onProductRecommendationsEnabledStateChange: (Boolean) -> Unit,
|
||||||
|
@ -33,7 +33,7 @@ import org.mozilla.fenix.theme.FirefoxTheme
|
|||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
fun ReviewQualityCheckSettingsCard(
|
fun ReviewQualityCheckSettingsCard(
|
||||||
productRecommendationsEnabled: Boolean,
|
productRecommendationsEnabled: Boolean?,
|
||||||
onProductRecommendationsEnabledStateChange: (Boolean) -> Unit,
|
onProductRecommendationsEnabledStateChange: (Boolean) -> Unit,
|
||||||
onTurnOffReviewQualityCheckClick: () -> Unit,
|
onTurnOffReviewQualityCheckClick: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
@ -53,7 +53,7 @@ fun ReviewQualityCheckSettingsCard(
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun SettingsContent(
|
private fun SettingsContent(
|
||||||
productRecommendationsEnabled: Boolean,
|
productRecommendationsEnabled: Boolean?,
|
||||||
onProductRecommendationsEnabledStateChange: (Boolean) -> Unit,
|
onProductRecommendationsEnabledStateChange: (Boolean) -> Unit,
|
||||||
onTurnOffReviewQualityCheckClick: () -> Unit,
|
onTurnOffReviewQualityCheckClick: () -> Unit,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
@ -61,13 +61,15 @@ private fun SettingsContent(
|
|||||||
Column(modifier = modifier) {
|
Column(modifier = modifier) {
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
Spacer(modifier = Modifier.height(8.dp))
|
||||||
|
|
||||||
SwitchWithLabel(
|
if (productRecommendationsEnabled != null) {
|
||||||
checked = productRecommendationsEnabled,
|
SwitchWithLabel(
|
||||||
onCheckedChange = onProductRecommendationsEnabledStateChange,
|
checked = productRecommendationsEnabled,
|
||||||
label = stringResource(R.string.review_quality_check_settings_recommended_products),
|
onCheckedChange = onProductRecommendationsEnabledStateChange,
|
||||||
)
|
label = stringResource(R.string.review_quality_check_settings_recommended_products),
|
||||||
|
)
|
||||||
|
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
}
|
||||||
|
|
||||||
SecondaryButton(
|
SecondaryButton(
|
||||||
text = stringResource(R.string.review_quality_check_settings_turn_off),
|
text = stringResource(R.string.review_quality_check_settings_turn_off),
|
||||||
|
@ -90,6 +90,30 @@ class ReviewQualityCheckStoreTest {
|
|||||||
assertEquals(expected, tested.state)
|
assertEquals(expected, tested.state)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `GIVEN the user has opted in the feature and product recommendations feature is disabled THEN state should reflect that`() =
|
||||||
|
runTest {
|
||||||
|
val tested = ReviewQualityCheckStore(
|
||||||
|
middleware = provideReviewQualityCheckMiddleware(
|
||||||
|
reviewQualityCheckPreferences = FakeReviewQualityCheckPreferences(
|
||||||
|
isEnabled = true,
|
||||||
|
isProductRecommendationsEnabled = null,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
tested.waitUntilIdle()
|
||||||
|
dispatcher.scheduler.advanceUntilIdle()
|
||||||
|
tested.waitUntilIdle()
|
||||||
|
|
||||||
|
val expected = ReviewQualityCheckState.OptedIn(productRecommendationsPreference = null)
|
||||||
|
assertEquals(expected, tested.state)
|
||||||
|
|
||||||
|
// Even if toggle action is dispatched, state is not changed
|
||||||
|
tested.dispatch(ReviewQualityCheckAction.ToggleProductRecommendation).joinBlocking()
|
||||||
|
tested.waitUntilIdle()
|
||||||
|
assertEquals(expected, tested.state)
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `GIVEN the user has opted in the feature and product recommendations are off WHEN the user turns on product recommendations THEN state should reflect that`() =
|
fun `GIVEN the user has opted in the feature and product recommendations are off WHEN the user turns on product recommendations THEN state should reflect that`() =
|
||||||
runTest {
|
runTest {
|
||||||
@ -213,12 +237,12 @@ class ReviewQualityCheckStoreTest {
|
|||||||
|
|
||||||
private class FakeReviewQualityCheckPreferences(
|
private class FakeReviewQualityCheckPreferences(
|
||||||
private val isEnabled: Boolean = false,
|
private val isEnabled: Boolean = false,
|
||||||
private val isProductRecommendationsEnabled: Boolean = false,
|
private val isProductRecommendationsEnabled: Boolean? = false,
|
||||||
private val updateCFRCallback: () -> Unit = { },
|
private val updateCFRCallback: () -> Unit = { },
|
||||||
) : ReviewQualityCheckPreferences {
|
) : ReviewQualityCheckPreferences {
|
||||||
override suspend fun enabled(): Boolean = isEnabled
|
override suspend fun enabled(): Boolean = isEnabled
|
||||||
|
|
||||||
override suspend fun productRecommendationsEnabled(): Boolean = isProductRecommendationsEnabled
|
override suspend fun productRecommendationsEnabled(): Boolean? = isProductRecommendationsEnabled
|
||||||
|
|
||||||
override suspend fun setEnabled(isEnabled: Boolean) {
|
override suspend fun setEnabled(isEnabled: Boolean) {
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user