Bug 1871408 - Translations UI Add Messages Under On Toggles

fenix/123.0
iorgamgabriel 4 months ago committed by mergify[bot]
parent acf5eec1a0
commit cc476767f7

@ -35,6 +35,7 @@ private const val DISABLED_ALPHA = 0.5f
* UI for a switch with label that can be on or off.
*
* @param label Text to be displayed next to the switch.
* @param description An optional description text below the label.
* @param checked Whether or not the switch is checked.
* @param onCheckedChange Invoked when Switch is being clicked, therefore the change of checked
* state is requested.
@ -44,6 +45,7 @@ private const val DISABLED_ALPHA = 0.5f
@Composable
fun SwitchWithLabel(
label: String,
description: String? = null,
checked: Boolean,
onCheckedChange: ((Boolean) -> Unit),
modifier: Modifier = Modifier,
@ -60,16 +62,28 @@ fun SwitchWithLabel(
horizontalArrangement = Arrangement.spacedBy(16.dp),
verticalAlignment = Alignment.CenterVertically,
) {
Text(
text = label,
color = if (enabled) {
FirefoxTheme.colors.textPrimary
} else {
FirefoxTheme.colors.textDisabled
},
style = FirefoxTheme.typography.subtitle1,
modifier = Modifier.weight(1f),
)
Column(
modifier = Modifier
.weight(1f),
) {
Text(
text = label,
color = if (enabled) {
FirefoxTheme.colors.textPrimary
} else {
FirefoxTheme.colors.textDisabled
},
style = FirefoxTheme.typography.subtitle1,
)
description?.let {
Text(
text = description,
color = FirefoxTheme.colors.textSecondary,
style = FirefoxTheme.typography.body2,
)
}
}
Switch(
modifier = Modifier.clearAndSetSemantics {},
@ -139,6 +153,7 @@ private fun SwitchWithLabelPreview() {
var enabledSwitchState by remember { mutableStateOf(false) }
SwitchWithLabel(
label = if (enabledSwitchState) "On" else "Off",
description = "Description text",
checked = enabledSwitchState,
onCheckedChange = { enabledSwitchState = it },
)

@ -17,6 +17,9 @@ import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.compose.runtime.toMutableStateList
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
@ -49,9 +52,42 @@ fun TranslationOptionsDialog(
) {
TranslationOptionsDialogHeader(onBackClicked)
val translationOptionsListState = remember {
translationOptionsList.toMutableStateList()
}
EnabledTranslationOptionsItems(
translationOptionsListState,
)
LazyColumn {
items(translationOptionsList) { item: TranslationSwitchItem ->
TranslationOptions(translationSwitchItem = item)
items(translationOptionsListState) { item: TranslationSwitchItem ->
val translationSwitchItem = TranslationSwitchItem(
textLabel = item.textLabel,
description = if (item.isChecked) item.description else null,
importance = item.importance,
isChecked = item.isChecked,
isEnabled = item.isEnabled,
hasDivider = item.hasDivider,
onStateChange = { checked ->
// If the item has the same importance, only one switch should be enabled.
val iterator = translationOptionsListState.iterator()
iterator.forEach {
if (it != item && it.importance == item.importance && it.isChecked) {
it.isChecked = false
}
}
val index = translationOptionsListState.indexOf(item)
translationOptionsListState[index] = translationOptionsListState[index].copy(
isChecked = checked,
)
},
)
TranslationOptions(
translationSwitchItem = translationSwitchItem,
)
}
item {
@ -79,14 +115,43 @@ fun TranslationOptionsDialog(
}
}
/**
* If the item with the highest importance is checked, all other items should be disabled.
* If all items are unchecked, all of them are enabled.
* If the item with the highest importance is unchecked and a item with importance 1 is checked ,
* the item with importance 0 is disabled.
* If the item with importance 0 is checked all the items are enabled.
*/
@Composable
private fun TranslationOptions(translationSwitchItem: TranslationSwitchItem) {
private fun EnabledTranslationOptionsItems(
translationOptionsListState: SnapshotStateList<TranslationSwitchItem>,
) {
val itemCheckedWithHighestImportance =
translationOptionsListState.sortedByDescending { listItem -> listItem.importance }
.firstOrNull { it.isChecked }
if (itemCheckedWithHighestImportance == null || itemCheckedWithHighestImportance.importance == 0) {
translationOptionsListState.forEach {
it.isEnabled = true
}
} else {
translationOptionsListState.forEach {
it.isEnabled = it.importance >= itemCheckedWithHighestImportance.importance
}
}
}
@Composable
private fun TranslationOptions(
translationSwitchItem: TranslationSwitchItem,
) {
SwitchWithLabel(
label = translationSwitchItem.textLabel,
description = translationSwitchItem.description,
enabled = translationSwitchItem.isEnabled,
checked = translationSwitchItem.isChecked,
onCheckedChange = translationSwitchItem.onStateChange,
label = translationSwitchItem.textLabel,
modifier = Modifier
.padding(start = 72.dp, end = 16.dp),
modifier = Modifier.padding(start = 72.dp, end = 16.dp),
)
if (translationSwitchItem.hasDivider) {
@ -106,8 +171,7 @@ private fun TranslationOptionsDialogHeader(
) {
IconButton(
onClick = { onBackClicked() },
modifier = Modifier
.size(24.dp),
modifier = Modifier.size(24.dp),
) {
Icon(
painter = painterResource(id = R.drawable.mozac_ic_back_24),
@ -140,7 +204,8 @@ fun getTranslationOptionsList(): List<TranslationSwitchItem> {
textLabel = stringResource(R.string.translation_option_bottom_sheet_always_translate),
isChecked = false,
hasDivider = true,
onStateChange = {},
isEnabled = true,
onStateChange = { },
),
)
add(
@ -149,7 +214,10 @@ fun getTranslationOptionsList(): List<TranslationSwitchItem> {
id = R.string.translation_option_bottom_sheet_always_translate_in_language,
formatArgs = arrayOf(Locale("es").displayName),
),
description = stringResource(id = R.string.translation_option_bottom_sheet_switch_description),
importance = 1,
isChecked = false,
isEnabled = true,
hasDivider = false,
onStateChange = {},
),
@ -160,7 +228,10 @@ fun getTranslationOptionsList(): List<TranslationSwitchItem> {
id = R.string.translation_option_bottom_sheet_never_translate_in_language,
formatArgs = arrayOf(Locale("es").displayName),
),
description = stringResource(id = R.string.translation_option_bottom_sheet_switch_description),
importance = 1,
isChecked = true,
isEnabled = true,
hasDivider = true,
onStateChange = {},
),
@ -168,7 +239,12 @@ fun getTranslationOptionsList(): List<TranslationSwitchItem> {
add(
TranslationSwitchItem(
textLabel = stringResource(R.string.translation_option_bottom_sheet_never_translate_site),
description = stringResource(
id = R.string.translation_option_bottom_sheet_switch_never_translate_site_description,
),
importance = 2,
isChecked = true,
isEnabled = true,
hasDivider = true,
onStateChange = {},
),

@ -122,6 +122,7 @@ internal fun getTranslationSettingsSwitchList(): List<TranslationSwitchItem> {
textLabel = stringResource(R.string.translation_settings_offer_to_translate),
isChecked = true,
hasDivider = false,
isEnabled = true,
onStateChange = {},
),
)
@ -130,6 +131,7 @@ internal fun getTranslationSettingsSwitchList(): List<TranslationSwitchItem> {
textLabel = stringResource(R.string.translation_settings_always_download),
isChecked = false,
hasDivider = true,
isEnabled = true,
onStateChange = {},
),
)

@ -8,14 +8,20 @@ package org.mozilla.fenix.translations
* TranslationSwitchItem that will appear on Translation screens.
*
* @property textLabel The text that will appear on the switch item.
* @property description An optional description text below the label.
* @property importance Based on this, the translation switch item is enabled or disabled.
* @property isChecked Whether the switch is checked or not.
* @property isEnabled Whether the switch is enabled or not.
* @property hasDivider Whether a divider should appear under the switch item.
* @property onStateChange Invoked when the switch item is clicked,
* the new checked state is passed into the callback.
*/
data class TranslationSwitchItem(
val textLabel: String,
val isChecked: Boolean,
var description: String? = null,
val importance: Int = 0,
var isChecked: Boolean,
var isEnabled: Boolean = true,
val hasDivider: Boolean,
val onStateChange: (Boolean) -> Unit,
)

@ -2391,6 +2391,10 @@
<string name="translation_option_bottom_sheet_never_translate_in_language">Never translate %1$s</string>
<!-- Toggle switch label that allows a user to set the setting if they would like the browser to never translate the site the user is currently visiting. -->
<string name="translation_option_bottom_sheet_never_translate_site">Never translate this site</string>
<!-- Toggle switch description that will appear under the "Never translate these sites" settings toggle switch to provide more information on how this setting interacts with other settings. -->
<string name="translation_option_bottom_sheet_switch_never_translate_site_description">Overrides all other settings</string>
<!-- Toggle switch description that will appear under the "Never translate" and "Always translate" toggle switch settings to provide more information on how these settings interacts with other settings. -->
<string name="translation_option_bottom_sheet_switch_description">Overrides offers to translate</string>
<!-- Button text for the button that will take the user to the translation settings dialog. -->
<string name="translation_option_bottom_sheet_translation_settings">Translation settings</string>
<!-- Button text for the button that will take the user to a website to learn more about how translations works in the given app. The first parameter is the name of the application, for example, "Fenix". -->

Loading…
Cancel
Save