Bug 1862293 - Translations UI Integration Integrate Download Languages - Global Settings r=android-reviewers,ohall

Differential Revision: https://phabricator.services.mozilla.com/D211357
This commit is contained in:
iorgamgabriel 2024-06-04 10:09:39 +00:00
parent 9eaeb8ac81
commit 0067c27e35
10 changed files with 607 additions and 230 deletions

View file

@ -40,5 +40,6 @@ enum class BrowserDirection(@IdRes val fragmentId: Int) {
FromReviewQualityCheck(R.id.reviewQualityCheckFragment), FromReviewQualityCheck(R.id.reviewQualityCheckFragment),
FromAddonsManagementFragment(R.id.addonsManagementFragment), FromAddonsManagementFragment(R.id.addonsManagementFragment),
FromTranslationsDialogFragment(R.id.translationsDialogFragment), FromTranslationsDialogFragment(R.id.translationsDialogFragment),
FromDownloadLanguagesPreferenceFragment(R.id.downloadLanguagesPreferenceFragment),
FromMenuDialogFragment(R.id.menuDialogFragment), FromMenuDialogFragment(R.id.menuDialogFragment),
} }

View file

@ -55,6 +55,7 @@ import org.mozilla.fenix.shopping.ReviewQualityCheckFragmentDirections
import org.mozilla.fenix.tabstray.TabsTrayFragmentDirections import org.mozilla.fenix.tabstray.TabsTrayFragmentDirections
import org.mozilla.fenix.trackingprotection.TrackingProtectionPanelDialogFragmentDirections import org.mozilla.fenix.trackingprotection.TrackingProtectionPanelDialogFragmentDirections
import org.mozilla.fenix.translations.TranslationsDialogFragmentDirections import org.mozilla.fenix.translations.TranslationsDialogFragmentDirections
import org.mozilla.fenix.translations.preferences.downloadlanguages.DownloadLanguagesPreferenceFragmentDirections
import java.security.InvalidParameterException import java.security.InvalidParameterException
/** /**
@ -326,6 +327,9 @@ private fun getHomeNavDirections(
BrowserDirection.FromTranslationsDialogFragment -> TranslationsDialogFragmentDirections.actionGlobalBrowser() BrowserDirection.FromTranslationsDialogFragment -> TranslationsDialogFragmentDirections.actionGlobalBrowser()
BrowserDirection.FromMenuDialogFragment -> MenuDialogFragmentDirections.actionGlobalBrowser() BrowserDirection.FromMenuDialogFragment -> MenuDialogFragmentDirections.actionGlobalBrowser()
BrowserDirection.FromDownloadLanguagesPreferenceFragment ->
DownloadLanguagesPreferenceFragmentDirections.actionGlobalBrowser()
} }
const val REQUEST_CODE_BROWSER_ROLE = 1 const val REQUEST_CODE_BROWSER_ROLE = 1

View file

@ -30,9 +30,9 @@ import java.util.Locale
*/ */
@Composable @Composable
fun DeleteLanguageFileDialog( fun DeleteLanguageFileDialog(
language: String, language: String? = null,
isAllLanguagesItemType: Boolean, isAllLanguagesItemType: Boolean,
fileSize: Long, fileSize: Long? = null,
onConfirmDelete: () -> Unit, onConfirmDelete: () -> Unit,
onCancel: () -> Unit, onCancel: () -> Unit,
) { ) {
@ -43,24 +43,28 @@ fun DeleteLanguageFileDialog(
shape = RoundedCornerShape(8.dp), shape = RoundedCornerShape(8.dp),
), ),
title = { title = {
val title: String = if (isAllLanguagesItemType) { val title: String? = if (isAllLanguagesItemType) {
stringResource( stringResource(
id = R.string.delete_language_all_languages_file_dialog_title, id = R.string.delete_language_all_languages_file_dialog_title,
fileSize.toMegabyteOrKilobyteString(), fileSize?.toMegabyteOrKilobyteString() ?: 0L,
) )
} else { } else {
stringResource( language?.let {
id = R.string.delete_language_file_dialog_title, stringResource(
language, id = R.string.delete_language_file_dialog_title,
fileSize.toMegabyteOrKilobyteString(), it,
) fileSize?.toMegabyteOrKilobyteString() ?: 0L,
)
}
} }
Text( title?.let {
text = title, Text(
color = FirefoxTheme.colors.textPrimary, text = it,
style = FirefoxTheme.typography.headline7, color = FirefoxTheme.colors.textPrimary,
) style = FirefoxTheme.typography.headline7,
)
}
}, },
text = { text = {
val message: String = if (isAllLanguagesItemType) { val message: String = if (isAllLanguagesItemType) {

View file

@ -50,7 +50,7 @@ import org.mozilla.fenix.theme.FirefoxTheme
@Suppress("LongMethod") @Suppress("LongMethod")
fun DownloadLanguageFileDialog( fun DownloadLanguageFileDialog(
downloadLanguageDialogType: DownloadLanguageFileDialogType, downloadLanguageDialogType: DownloadLanguageFileDialogType,
fileSize: Long, fileSize: Long? = null,
isCheckBoxEnabled: Boolean, isCheckBoxEnabled: Boolean,
isCacheMessage: Boolean = false, isCacheMessage: Boolean = false,
onSavingModeStateChange: (Boolean) -> Unit, onSavingModeStateChange: (Boolean) -> Unit,
@ -70,12 +70,12 @@ fun DownloadLanguageFileDialog(
if (downloadLanguageDialogType is DownloadLanguageFileDialogType.TranslationRequest) { if (downloadLanguageDialogType is DownloadLanguageFileDialogType.TranslationRequest) {
stringResource( stringResource(
R.string.translations_download_language_file_dialog_title, R.string.translations_download_language_file_dialog_title,
fileSize.toMegabyteOrKilobyteString(), fileSize?.toMegabyteOrKilobyteString() ?: 0L,
) )
} else { } else {
stringResource( stringResource(
R.string.download_language_file_dialog_title, R.string.download_language_file_dialog_title,
fileSize.toMegabyteOrKilobyteString(), fileSize?.toMegabyteOrKilobyteString() ?: 0L,
) )
} }
Text( Text(
@ -90,11 +90,15 @@ fun DownloadLanguageFileDialog(
downloadLanguageDialogType is DownloadLanguageFileDialogType.TranslationRequest downloadLanguageDialogType is DownloadLanguageFileDialogType.TranslationRequest
) { ) {
Text( Text(
text = if (isCacheMessage) { stringResource( text = if (isCacheMessage) {
R.string.download_language_file_dialog_message_all_languages, stringResource(
) } else { stringResource( R.string.download_language_file_dialog_message_all_languages,
R.string.download_language_file_dialog_message_all_languages_no_cache, )
) }, } else {
stringResource(
R.string.download_language_file_dialog_message_all_languages_no_cache,
)
},
modifier = Modifier.padding(top = 16.dp, bottom = 16.dp), modifier = Modifier.padding(top = 16.dp, bottom = 16.dp),
style = FirefoxTheme.typography.body2, style = FirefoxTheme.typography.body2,
color = FirefoxTheme.colors.textPrimary, color = FirefoxTheme.colors.textPrimary,

View file

@ -4,32 +4,21 @@
package org.mozilla.fenix.translations.preferences.downloadlanguages package org.mozilla.fenix.translations.preferences.downloadlanguages
import android.os.Parcelable import mozilla.components.concept.engine.translate.LanguageModel
import kotlinx.parcelize.Parcelize
import org.mozilla.geckoview.TranslationsController
/** /**
* DownloadLanguageItemPreference that will appear on [DownloadLanguagesPreferenceFragment] screen. * DownloadLanguageItemPreference that will appear on [DownloadLanguagesPreferenceFragment] screen.
* *
* @property languageModel The object comes from the translation engine. * @property languageModel The object comes from the translation engine.
* @property state State of the [languageModel]. * @property type The type of the language item.
* @property enabled Whether the item is enabled or not.
*
*/ */
data class DownloadLanguageItemPreference( data class DownloadLanguageItemPreference(
val languageModel: TranslationsController.RuntimeTranslation.LanguageModel, val languageModel: LanguageModel,
val state: DownloadLanguageItemStatePreference,
)
/**
* DownloadLanguageItemStatePreference the state of the [DownloadLanguageItemPreference]
*
* @property type The type of the language item.
* @property status State of the language file.
*/
@Parcelize
data class DownloadLanguageItemStatePreference(
val type: DownloadLanguageItemTypePreference, val type: DownloadLanguageItemTypePreference,
val status: DownloadLanguageItemStatusPreference, val enabled: Boolean = true,
) : Parcelable )
/** /**
* DownloadLanguageItemTypePreference the type of the [DownloadLanguageItemPreference] * DownloadLanguageItemTypePreference the type of the [DownloadLanguageItemPreference]
@ -39,13 +28,3 @@ enum class DownloadLanguageItemTypePreference {
AllLanguages, AllLanguages,
GeneralLanguage, GeneralLanguage,
} }
/**
* DownloadLanguageItemStatusPreference the status of the [DownloadLanguageItemPreference]
*/
enum class DownloadLanguageItemStatusPreference {
Downloaded,
NotDownloaded,
DownloadInProgress,
Selected,
}

View file

@ -12,10 +12,12 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.material.Icon import androidx.compose.material.Icon
@ -38,6 +40,9 @@ import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.text.withStyle import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import mozilla.components.concept.engine.translate.Language
import mozilla.components.concept.engine.translate.LanguageModel
import mozilla.components.concept.engine.translate.ModelState
import mozilla.components.feature.downloads.toMegabyteOrKilobyteString import mozilla.components.feature.downloads.toMegabyteOrKilobyteString
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.compose.Divider import org.mozilla.fenix.compose.Divider
@ -46,42 +51,73 @@ import org.mozilla.fenix.compose.LinkTextState
import org.mozilla.fenix.compose.annotation.LightDarkPreview import org.mozilla.fenix.compose.annotation.LightDarkPreview
import org.mozilla.fenix.theme.FirefoxTheme import org.mozilla.fenix.theme.FirefoxTheme
import org.mozilla.fenix.translations.DownloadIconIndicator import org.mozilla.fenix.translations.DownloadIconIndicator
import org.mozilla.geckoview.TranslationsController
import java.util.Locale import java.util.Locale
/** /**
* Firefox Download Languages preference screen. * Firefox Download Languages preference screen.
* *
* @param downloadLanguageItemPreferences List of [DownloadLanguageItemPreference]s that needs to be displayed. * @param downloadLanguageItemPreferences List of [DownloadLanguageItemPreference]s that needs to be displayed.
* @param learnMoreUrl The learn more link for translations website.
* @param onLearnMoreClicked Invoked when the user clicks on the "Learn More" button.
* @param onItemClick Invoked when the user clicks on the language item. * @param onItemClick Invoked when the user clicks on the language item.
*/ */
@Suppress("LongMethod") @Suppress("LongMethod", "CyclomaticComplexMethod")
@Composable @Composable
fun DownloadLanguagesPreference( fun DownloadLanguagesPreference(
downloadLanguageItemPreferences: List<DownloadLanguageItemPreference>, downloadLanguageItemPreferences: List<DownloadLanguageItemPreference>,
learnMoreUrl: String,
onLearnMoreClicked: () -> Unit,
onItemClick: (DownloadLanguageItemPreference) -> Unit, onItemClick: (DownloadLanguageItemPreference) -> Unit,
) { ) {
val downloadedItems = downloadLanguageItemPreferences.filter { val downloadedItems = downloadLanguageItemPreferences.filter {
it.state.status == DownloadLanguageItemStatusPreference.Downloaded && it.languageModel.status == ModelState.DOWNLOADED &&
it.state.type == DownloadLanguageItemTypePreference.GeneralLanguage it.type == DownloadLanguageItemTypePreference.GeneralLanguage
} }
val notDownloadedItems = downloadLanguageItemPreferences.filter { val notDownloadedItems = downloadLanguageItemPreferences.filter {
it.state.status == DownloadLanguageItemStatusPreference.NotDownloaded && it.languageModel.status == ModelState.NOT_DOWNLOADED &&
it.state.type == DownloadLanguageItemTypePreference.GeneralLanguage it.type == DownloadLanguageItemTypePreference.GeneralLanguage
} }
val inProgressItems = downloadLanguageItemPreferences.filter { val downloadInProgressItems = downloadLanguageItemPreferences.filter {
it.state.status == DownloadLanguageItemStatusPreference.DownloadInProgress && it.languageModel.status == ModelState.DOWNLOAD_IN_PROGRESS &&
it.state.type == DownloadLanguageItemTypePreference.GeneralLanguage it.type == DownloadLanguageItemTypePreference.GeneralLanguage
} }
val allLanguagesItem = downloadLanguageItemPreferences.last { val deleteInProgressItems = downloadLanguageItemPreferences.filter {
it.state.type == DownloadLanguageItemTypePreference.AllLanguages it.languageModel.status == ModelState.DELETION_IN_PROGRESS &&
it.type == DownloadLanguageItemTypePreference.GeneralLanguage
} }
val defaultLanguageItem = downloadLanguageItemPreferences.last { var allLanguagesItemDownloaded: DownloadLanguageItemPreference? = null
it.state.type == DownloadLanguageItemTypePreference.PivotLanguage if (downloadLanguageItemPreferences.any {
it.type == DownloadLanguageItemTypePreference.AllLanguages &&
it.languageModel.status == ModelState.DOWNLOADED
}
) {
allLanguagesItemDownloaded = downloadLanguageItemPreferences.last {
it.type == DownloadLanguageItemTypePreference.AllLanguages &&
it.languageModel.status == ModelState.DOWNLOADED
}
}
var allLanguagesItemNotDownloaded: DownloadLanguageItemPreference? = null
if (downloadLanguageItemPreferences.any {
it.type == DownloadLanguageItemTypePreference.AllLanguages &&
it.languageModel.status == ModelState.NOT_DOWNLOADED
}
) {
allLanguagesItemNotDownloaded = downloadLanguageItemPreferences.last {
it.type == DownloadLanguageItemTypePreference.AllLanguages &&
it.languageModel.status == ModelState.NOT_DOWNLOADED
}
}
var pivotLanguage: DownloadLanguageItemPreference? = null
if (downloadLanguageItemPreferences.any { it.type == DownloadLanguageItemTypePreference.PivotLanguage }) {
pivotLanguage = downloadLanguageItemPreferences.last {
it.type == DownloadLanguageItemTypePreference.PivotLanguage
}
} }
Column( Column(
@ -89,22 +125,33 @@ fun DownloadLanguagesPreference(
color = FirefoxTheme.colors.layer1, color = FirefoxTheme.colors.layer1,
), ),
) { ) {
DownloadLanguagesHeaderPreference() DownloadLanguagesHeaderPreference(
learnMoreUrl = learnMoreUrl,
onLearnMoreClicked = onLearnMoreClicked,
)
LazyColumn { LazyColumn {
item { if (
DownloadLanguagesHeader( allLanguagesItemDownloaded != null ||
stringResource( pivotLanguage?.languageModel?.status == ModelState.DOWNLOADED ||
id = R.string.download_languages_available_languages_preference, downloadInProgressItems.isNotEmpty()
), ) {
) item {
DownloadLanguagesHeader(
stringResource(
id = R.string.download_languages_available_languages_preference,
),
)
}
} }
item { allLanguagesItemDownloaded?.let {
LanguageItemPreference( item {
item = defaultLanguageItem, LanguageItemPreference(
onItemClick = onItemClick, item = allLanguagesItemDownloaded,
) onItemClick = onItemClick,
)
}
} }
items(downloadedItems) { item: DownloadLanguageItemPreference -> items(downloadedItems) { item: DownloadLanguageItemPreference ->
@ -114,31 +161,75 @@ fun DownloadLanguagesPreference(
) )
} }
items(inProgressItems) { item: DownloadLanguageItemPreference -> items(downloadInProgressItems) { item: DownloadLanguageItemPreference ->
LanguageItemPreference( LanguageItemPreference(
item = item, item = item,
onItemClick = onItemClick, onItemClick = onItemClick,
) )
} }
item { if (
Divider(Modifier.padding(top = 8.dp, bottom = 8.dp)) pivotLanguage != null &&
pivotLanguage.languageModel.status == ModelState.DOWNLOADED
) {
item {
LanguageItemPreference(
item = pivotLanguage,
onItemClick = onItemClick,
)
}
} }
item { if (pivotLanguage?.languageModel?.status == ModelState.NOT_DOWNLOADED ||
DownloadLanguagesHeader( shouldShowDownloadLanguagesHeader(
stringResource( allLanguagesItemNotDownloaded = allLanguagesItemNotDownloaded,
id = R.string.download_language_header_preference, deleteInProgressItems = deleteInProgressItems,
), notDownloadedItems = notDownloadedItems,
) )
) {
if (pivotLanguage?.languageModel?.status == ModelState.DOWNLOADED ||
downloadInProgressItems.isNotEmpty() ||
allLanguagesItemDownloaded != null
) {
item {
Divider(Modifier.padding(top = 8.dp, bottom = 8.dp))
}
}
item {
DownloadLanguagesHeader(
stringResource(
id = R.string.download_language_header_preference,
),
)
}
} }
item { allLanguagesItemNotDownloaded?.let {
item {
LanguageItemPreference(
item = allLanguagesItemNotDownloaded,
onItemClick = onItemClick,
)
}
}
if (pivotLanguage != null &&
pivotLanguage.languageModel.status == ModelState.NOT_DOWNLOADED
) {
item {
LanguageItemPreference(
item = pivotLanguage,
onItemClick = onItemClick,
)
}
}
items(deleteInProgressItems) { item: DownloadLanguageItemPreference ->
LanguageItemPreference( LanguageItemPreference(
item = allLanguagesItem, item = item,
onItemClick = onItemClick, onItemClick = onItemClick,
) )
Divider(Modifier.padding(top = 8.dp, bottom = 8.dp))
} }
items(notDownloadedItems) { item: DownloadLanguageItemPreference -> items(notDownloadedItems) { item: DownloadLanguageItemPreference ->
@ -153,14 +244,26 @@ fun DownloadLanguagesPreference(
} }
} }
private fun shouldShowDownloadLanguagesHeader(
allLanguagesItemNotDownloaded: DownloadLanguageItemPreference?,
deleteInProgressItems: List<DownloadLanguageItemPreference>,
notDownloadedItems: List<DownloadLanguageItemPreference>,
): Boolean {
return allLanguagesItemNotDownloaded != null ||
deleteInProgressItems.isNotEmpty() ||
notDownloadedItems.isNotEmpty()
}
@Composable @Composable
private fun DownloadLanguagesHeader(title: String) { private fun DownloadLanguagesHeader(title: String) {
Text( Text(
text = title, text = title,
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(start = 72.dp, end = 16.dp, top = 8.dp) .padding(start = 72.dp, end = 16.dp)
.semantics { heading() }, .semantics { heading() }
.defaultMinSize(minHeight = 36.dp)
.wrapContentHeight(),
color = FirefoxTheme.colors.textAccent, color = FirefoxTheme.colors.textAccent,
style = FirefoxTheme.typography.headline8, style = FirefoxTheme.typography.headline8,
) )
@ -172,16 +275,36 @@ private fun LanguageItemPreference(
onItemClick: (DownloadLanguageItemPreference) -> Unit, onItemClick: (DownloadLanguageItemPreference) -> Unit,
) { ) {
val description: String = val description: String =
if (item.state.type == DownloadLanguageItemTypePreference.PivotLanguage) { if (
item.type == DownloadLanguageItemTypePreference.PivotLanguage &&
item.languageModel.status == ModelState.DOWNLOADED &&
!item.enabled
) {
stringResource(id = R.string.download_languages_default_system_language_require_preference) stringResource(id = R.string.download_languages_default_system_language_require_preference)
} else { } else {
item.languageModel.size.toMegabyteOrKilobyteString() var size = 0L
item.languageModel.size?.let { size = it }
size.toMegabyteOrKilobyteString()
} }
val contentDescription = val label = if (item.type == DownloadLanguageItemTypePreference.AllLanguages) {
downloadLanguageItemContentDescriptionPreference(item = item, itemDescription = description) if (item.languageModel.status == ModelState.NOT_DOWNLOADED) {
stringResource(id = R.string.download_language_all_languages_item_preference)
} else {
stringResource(id = R.string.download_language_all_languages_item_preference_to_delete)
}
} else {
item.languageModel.language?.localizedDisplayName
}
item.languageModel.language?.localizedDisplayName?.let { val contentDescription =
downloadLanguageItemContentDescriptionPreference(
item = item,
label = label,
itemDescription = description,
)
label?.let {
TextListItemInlineDescription( TextListItemInlineDescription(
label = it, label = it,
modifier = Modifier modifier = Modifier
@ -190,25 +313,33 @@ private fun LanguageItemPreference(
) )
.clearAndSetSemantics { .clearAndSetSemantics {
role = Role.Button role = Role.Button
this.contentDescription = this.contentDescription = contentDescription
contentDescription }
}, .defaultMinSize(minHeight = 56.dp)
.wrapContentHeight(),
description = description, description = description,
enabled = item.state.status != DownloadLanguageItemStatusPreference.DownloadInProgress, enabled = item.enabled,
onClick = { onItemClick(item) }, onClick = { onItemClick(item) },
icon = { IconDownloadLanguageItemPreference(item = item) }, icon = {
IconDownloadLanguageItemPreference(
item = item,
)
},
) )
} }
} }
@Composable @Composable
private fun DownloadLanguagesHeaderPreference() { private fun DownloadLanguagesHeaderPreference(
learnMoreUrl: String,
onLearnMoreClicked: () -> Unit,
) {
val learnMoreText = val learnMoreText =
stringResource(id = R.string.download_languages_header_learn_more_preference) stringResource(id = R.string.download_languages_header_learn_more_preference)
val learnMoreState = LinkTextState( val learnMoreState = LinkTextState(
text = learnMoreText, text = learnMoreText,
url = "www.mozilla.com", url = learnMoreUrl,
onClick = {}, onClick = { onLearnMoreClicked() },
) )
Box( Box(
modifier = Modifier modifier = Modifier
@ -232,52 +363,53 @@ private fun DownloadLanguagesHeaderPreference() {
linkTextDecoration = TextDecoration.Underline, linkTextDecoration = TextDecoration.Underline,
) )
} }
Spacer(modifier = Modifier.size(8.dp))
} }
@Composable @Composable
private fun downloadLanguageItemContentDescriptionPreference( private fun downloadLanguageItemContentDescriptionPreference(
item: DownloadLanguageItemPreference, item: DownloadLanguageItemPreference,
label: String? = null,
itemDescription: String, itemDescription: String,
): String { ): String {
val contentDescription: String val contentDescription: String
when (item.state.status) { when (item.languageModel.status) {
DownloadLanguageItemStatusPreference.Downloaded -> { ModelState.DOWNLOADED -> {
contentDescription = contentDescription =
item.languageModel.language?.localizedDisplayName + " " + itemDescription + stringResource( "$label $itemDescription" + stringResource(
id = R.string.download_languages_item_content_description_downloaded_state, id = R.string.download_languages_item_content_description_downloaded_state,
) )
} }
DownloadLanguageItemStatusPreference.NotDownloaded -> { ModelState.NOT_DOWNLOADED -> {
contentDescription = contentDescription =
item.languageModel.language?.localizedDisplayName + " " + itemDescription + " " + stringResource( "$label $itemDescription " + stringResource(
id = R.string.download_languages_item_content_description_not_downloaded_state, id = R.string.download_languages_item_content_description_not_downloaded_state,
) )
} }
DownloadLanguageItemStatusPreference.DownloadInProgress -> { ModelState.DOWNLOAD_IN_PROGRESS, ModelState.DELETION_IN_PROGRESS -> {
contentDescription = contentDescription =
item.languageModel.language?.localizedDisplayName + " " + itemDescription + " " + stringResource( "$label $itemDescription " + stringResource(
id = R.string.download_languages_item_content_description_in_progress_state, id = R.string.download_languages_item_content_description_in_progress_state,
) )
} }
DownloadLanguageItemStatusPreference.Selected -> {
contentDescription =
item.languageModel.language?.localizedDisplayName + " " + itemDescription + stringResource(
id = R.string.download_languages_item_content_description_selected_state,
)
}
} }
return contentDescription return contentDescription
} }
@Composable @Composable
private fun IconDownloadLanguageItemPreference(item: DownloadLanguageItemPreference) { private fun IconDownloadLanguageItemPreference(
when (item.state.status) { item: DownloadLanguageItemPreference,
DownloadLanguageItemStatusPreference.Downloaded -> { ) {
if (item.state.type != DownloadLanguageItemTypePreference.PivotLanguage) { when (item.languageModel.status) {
ModelState.DOWNLOADED -> {
if (
item.type != DownloadLanguageItemTypePreference.PivotLanguage ||
item.enabled
) {
Icon( Icon(
painter = painterResource( painter = painterResource(
id = R.drawable.ic_delete, id = R.drawable.ic_delete,
@ -288,27 +420,21 @@ private fun IconDownloadLanguageItemPreference(item: DownloadLanguageItemPrefere
} }
} }
DownloadLanguageItemStatusPreference.NotDownloaded -> { ModelState.NOT_DOWNLOADED -> {
if (item.state.type != DownloadLanguageItemTypePreference.PivotLanguage) { Icon(
Icon( painter = painterResource(
painter = painterResource( id = R.drawable.ic_download,
id = R.drawable.ic_download, ),
), contentDescription = null,
contentDescription = null, tint = FirefoxTheme.colors.iconPrimary,
tint = FirefoxTheme.colors.iconPrimary, )
)
}
} }
DownloadLanguageItemStatusPreference.DownloadInProgress -> { ModelState.DOWNLOAD_IN_PROGRESS, ModelState.DELETION_IN_PROGRESS -> {
if (item.state.type != DownloadLanguageItemTypePreference.PivotLanguage) { DownloadIconIndicator(
DownloadIconIndicator( icon = painterResource(id = R.drawable.mozac_ic_sync_24),
icon = painterResource(id = R.drawable.mozac_ic_sync_24), )
)
}
} }
DownloadLanguageItemStatusPreference.Selected -> {}
} }
} }
@ -368,6 +494,7 @@ private fun TextListItemInlineDescription(
} }
IconButton( IconButton(
onClick = { onClick.invoke() }, onClick = { onClick.invoke() },
enabled = enabled,
modifier = Modifier modifier = Modifier
.padding(end = 16.dp) .padding(end = 16.dp)
.size(24.dp) .size(24.dp)
@ -384,82 +511,51 @@ internal fun getLanguageListPreference(): List<DownloadLanguageItemPreference> {
return mutableListOf<DownloadLanguageItemPreference>().apply { return mutableListOf<DownloadLanguageItemPreference>().apply {
add( add(
DownloadLanguageItemPreference( DownloadLanguageItemPreference(
languageModel = TranslationsController.RuntimeTranslation.LanguageModel( languageModel = LanguageModel(
TranslationsController.Language( language = Language(Locale.FRENCH.toLanguageTag(), Locale.FRENCH.displayName),
Locale.FRENCH.toLanguageTag(), status = ModelState.DOWNLOADED,
Locale.FRENCH.displayLanguage, size = 100L,
),
false,
30000000,
),
state = DownloadLanguageItemStatePreference(
type = DownloadLanguageItemTypePreference.GeneralLanguage,
status = DownloadLanguageItemStatusPreference.Downloaded,
), ),
type = DownloadLanguageItemTypePreference.GeneralLanguage,
), ),
) )
add( add(
DownloadLanguageItemPreference( DownloadLanguageItemPreference(
languageModel = TranslationsController.RuntimeTranslation.LanguageModel( languageModel = LanguageModel(
TranslationsController.Language( language = Language(Locale.GERMAN.toLanguageTag(), Locale.GERMAN.displayName),
Locale.GERMAN.toLanguageTag(), status = ModelState.NOT_DOWNLOADED,
Locale.GERMAN.displayLanguage, size = 100L,
),
false,
30000000,
),
state = DownloadLanguageItemStatePreference(
type = DownloadLanguageItemTypePreference.GeneralLanguage,
status = DownloadLanguageItemStatusPreference.NotDownloaded,
), ),
type = DownloadLanguageItemTypePreference.GeneralLanguage,
), ),
) )
add( add(
DownloadLanguageItemPreference( DownloadLanguageItemPreference(
languageModel = TranslationsController.RuntimeTranslation.LanguageModel( languageModel = LanguageModel(
TranslationsController.Language( language = Language(Locale.ITALIAN.toLanguageTag(), Locale.ITALIAN.displayName),
Locale.ITALIAN.toLanguageTag(), status = ModelState.DOWNLOAD_IN_PROGRESS,
Locale.ITALIAN.displayLanguage, size = 100L,
),
false,
30000000,
),
state = DownloadLanguageItemStatePreference(
type = DownloadLanguageItemTypePreference.GeneralLanguage,
status = DownloadLanguageItemStatusPreference.DownloadInProgress,
), ),
type = DownloadLanguageItemTypePreference.GeneralLanguage,
), ),
) )
add( add(
DownloadLanguageItemPreference( DownloadLanguageItemPreference(
languageModel = TranslationsController.RuntimeTranslation.LanguageModel( languageModel = LanguageModel(
TranslationsController.Language( language = Language(Locale.ENGLISH.toLanguageTag(), Locale.ENGLISH.displayName),
Locale.ENGLISH.toLanguageTag(), status = ModelState.DELETION_IN_PROGRESS,
Locale.ENGLISH.displayLanguage, size = 100L,
),
true,
30000000,
),
state = DownloadLanguageItemStatePreference(
type = DownloadLanguageItemTypePreference.PivotLanguage,
status = DownloadLanguageItemStatusPreference.Selected,
), ),
type = DownloadLanguageItemTypePreference.GeneralLanguage,
), ),
) )
add( add(
DownloadLanguageItemPreference( DownloadLanguageItemPreference(
languageModel = TranslationsController.RuntimeTranslation.LanguageModel( languageModel = LanguageModel(
TranslationsController.Language( status = ModelState.NOT_DOWNLOADED,
stringResource(id = R.string.download_language_all_languages_item_preference), size = 100L,
stringResource(id = R.string.download_language_all_languages_item_preference),
),
true,
90000000,
),
state = DownloadLanguageItemStatePreference(
type = DownloadLanguageItemTypePreference.AllLanguages,
status = DownloadLanguageItemStatusPreference.NotDownloaded,
), ),
type = DownloadLanguageItemTypePreference.AllLanguages,
), ),
) )
} }
@ -471,6 +567,8 @@ private fun DownloadLanguagesPreferencePreview() {
FirefoxTheme { FirefoxTheme {
DownloadLanguagesPreference( DownloadLanguagesPreference(
downloadLanguageItemPreferences = getLanguageListPreference(), downloadLanguageItemPreferences = getLanguageListPreference(),
learnMoreUrl = "https://www.mozilla.org",
onLearnMoreClicked = {},
onItemClick = {}, onItemClick = {},
) )
} }

View file

@ -8,15 +8,30 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.ComposeView
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.navigation.findNavController import androidx.navigation.findNavController
import mozilla.components.browser.state.action.TranslationsAction
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.concept.engine.translate.LanguageModel
import mozilla.components.concept.engine.translate.ModelManagementOptions
import mozilla.components.concept.engine.translate.ModelOperation
import mozilla.components.concept.engine.translate.ModelState
import mozilla.components.concept.engine.translate.OperationLevel
import mozilla.components.lib.state.ext.observeAsComposableState
import mozilla.components.support.base.feature.ViewBoundFeatureWrapper import mozilla.components.support.base.feature.ViewBoundFeatureWrapper
import mozilla.components.support.locale.LocaleManager
import org.mozilla.fenix.BrowserDirection
import org.mozilla.fenix.HomeActivity
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.ext.showToolbar import org.mozilla.fenix.ext.showToolbar
import org.mozilla.fenix.settings.SupportUtils
import org.mozilla.fenix.theme.FirefoxTheme import org.mozilla.fenix.theme.FirefoxTheme
import java.util.Locale
/** /**
* A fragment displaying Download Languages screen. * A fragment displaying Download Languages screen.
@ -25,6 +40,7 @@ class DownloadLanguagesPreferenceFragment : Fragment() {
private val downloadLanguagesFeature = private val downloadLanguagesFeature =
ViewBoundFeatureWrapper<DownloadLanguagesFeature>() ViewBoundFeatureWrapper<DownloadLanguagesFeature>()
private var isDataSaverEnabledAndWifiDisabled = false private var isDataSaverEnabledAndWifiDisabled = false
private val browserStore: BrowserStore by lazy { requireComponents.core.store }
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
@ -38,24 +54,48 @@ class DownloadLanguagesPreferenceFragment : Fragment() {
): View = ComposeView(requireContext()).apply { ): View = ComposeView(requireContext()).apply {
setContent { setContent {
FirefoxTheme { FirefoxTheme {
val learnMoreUrl = SupportUtils.getSumoURLForTopic(
requireContext(),
SupportUtils.SumoTopic.TRANSLATIONS,
)
val downloadLanguageItemsPreference = getDownloadLanguageItemsPreference()
DownloadLanguagesPreference( DownloadLanguagesPreference(
downloadLanguageItemPreferences = getLanguageListPreference(), downloadLanguageItemPreferences = downloadLanguageItemsPreference,
learnMoreUrl = learnMoreUrl,
onLearnMoreClicked = { openBrowserAndLoad(learnMoreUrl) },
onItemClick = { downloadLanguageItemPreference -> onItemClick = { downloadLanguageItemPreference ->
if (downloadLanguageItemPreference.state.status == if (downloadLanguageItemPreference.languageModel.status ==
DownloadLanguageItemStatusPreference.Downloaded || ModelState.DOWNLOADED ||
shouldShowPrefDownloadLanguageFileDialog( shouldShowPrefDownloadLanguageFileDialog(
downloadLanguageItemPreference, downloadLanguageItemPreference,
) )
) { ) {
downloadLanguageItemPreference.languageModel.language?.localizedDisplayName?.let { var size = 0L
findNavController().navigate( downloadLanguageItemPreference.languageModel.size?.let { size = it }
DownloadLanguagesPreferenceFragmentDirections
.actionDownloadLanguagesPreferenceToDownloadLanguagesDialogPreference( findNavController().navigate(
downloadLanguageItemPreference.state, DownloadLanguagesPreferenceFragmentDirections
it, .actionDownloadLanguagesPreferenceToDownloadLanguagesDialogPreference(
downloadLanguageItemPreference.languageModel.size, modelState = downloadLanguageItemPreference.languageModel.status,
), itemType = downloadLanguageItemPreference.type,
languageCode = downloadLanguageItemPreference.languageModel.language?.code,
languageDisplayName =
downloadLanguageItemPreference.languageModel.language?.localizedDisplayName,
modelSize = size,
),
)
} else {
if (
downloadLanguageItemPreference.type ==
DownloadLanguageItemTypePreference.AllLanguages
) {
deleteOrDownloadAllLanguagesModel(
allLanguagesItemPreference = downloadLanguageItemPreference,
allLanguages = downloadLanguageItemsPreference,
) )
} else {
deleteOrDownloadModel(downloadLanguageItemPreference)
} }
} }
}, },
@ -64,15 +104,6 @@ class DownloadLanguagesPreferenceFragment : Fragment() {
} }
} }
private fun shouldShowPrefDownloadLanguageFileDialog(
downloadLanguageItemPreference: DownloadLanguageItemPreference,
) =
(
downloadLanguageItemPreference.state.status == DownloadLanguageItemStatusPreference.NotDownloaded &&
isDataSaverEnabledAndWifiDisabled &&
!requireContext().settings().ignoreTranslationsDataSaverWarning
)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
downloadLanguagesFeature.set( downloadLanguagesFeature.set(
@ -87,4 +118,175 @@ class DownloadLanguagesPreferenceFragment : Fragment() {
view = view, view = view,
) )
} }
private fun deleteOrDownloadModel(downloadLanguageItemPreference: DownloadLanguageItemPreference) {
val options = ModelManagementOptions(
languageToManage = downloadLanguageItemPreference.languageModel.language?.code,
operation = if (
downloadLanguageItemPreference.languageModel.status ==
ModelState.NOT_DOWNLOADED
) {
ModelOperation.DOWNLOAD
} else {
ModelOperation.DELETE
},
operationLevel = OperationLevel.LANGUAGE,
)
browserStore.dispatch(
TranslationsAction.ManageLanguageModelsAction(
options = options,
),
)
}
private fun deleteOrDownloadAllLanguagesModel(
allLanguagesItemPreference: DownloadLanguageItemPreference,
allLanguages: List<DownloadLanguageItemPreference>,
) {
if (allLanguagesItemPreference.languageModel.status == ModelState.DOWNLOADED) {
val downloadedItems = allLanguages.filter {
it.languageModel.status == ModelState.DOWNLOADED &&
it.type == DownloadLanguageItemTypePreference.GeneralLanguage
}
for (downloadedItem in downloadedItems) {
if (!downloadedItem.languageModel.language?.code.equals(Locale.ENGLISH.language)) {
deleteOrDownloadModel(downloadedItem)
}
}
} else {
if (allLanguagesItemPreference.languageModel.status == ModelState.NOT_DOWNLOADED) {
val notDownloadedItems = allLanguages.filter {
it.languageModel.status == ModelState.NOT_DOWNLOADED &&
it.type == DownloadLanguageItemTypePreference.GeneralLanguage
}
for (notDownloadedItem in notDownloadedItems) {
deleteOrDownloadModel(notDownloadedItem)
}
}
}
}
private fun openBrowserAndLoad(learnMoreUrl: String) {
(requireActivity() as HomeActivity).openToBrowserAndLoad(
searchTermOrURL = learnMoreUrl,
newTab = true,
from = BrowserDirection.FromDownloadLanguagesPreferenceFragment,
)
}
@Composable
private fun getDownloadLanguageItemsPreference(): List<DownloadLanguageItemPreference> {
val languageModels = browserStore.observeAsComposableState { state ->
state.translationEngine.languageModels
}.value?.toMutableList()
val languageItemPreferenceList = mutableListOf<DownloadLanguageItemPreference>()
val appLocale = browserStore.state.locale ?: LocaleManager.getSystemDefault()
languageModels?.let {
var allLanguagesSizeNotDownloaded = 0L
var allLanguagesSizeDownloaded = 0L
for (languageModel in languageModels) {
var size = 0L
languageModel.size?.let { size = it }
if (languageModel.status == ModelState.NOT_DOWNLOADED) {
allLanguagesSizeNotDownloaded += size
}
if (
languageModel.status == ModelState.DOWNLOADED &&
!languageModel.language?.code.equals(
Locale.ENGLISH.language,
)
) {
allLanguagesSizeDownloaded += size
}
}
addAllLanguagesNotDownloaded(
allLanguagesSizeNotDownloaded,
languageItemPreferenceList,
)
addAllLanguagesDownloaded(
allLanguagesSizeDownloaded,
languageItemPreferenceList,
)
val iterator = languageModels.iterator()
while (iterator.hasNext()) {
val languageModel = iterator.next()
if (!appLocale.language.equals(Locale.ENGLISH.language) && languageModel.language?.code.equals(
Locale.ENGLISH.language,
)
) {
languageItemPreferenceList.add(
DownloadLanguageItemPreference(
languageModel = languageModel,
type = DownloadLanguageItemTypePreference.PivotLanguage,
enabled = allLanguagesSizeDownloaded == 0L,
),
)
iterator.remove()
}
if (!languageModel.language?.code.equals(Locale.ENGLISH.language)) {
languageItemPreferenceList.add(
DownloadLanguageItemPreference(
languageModel = languageModel,
type = DownloadLanguageItemTypePreference.GeneralLanguage,
enabled = languageModel.status == ModelState.DOWNLOADED ||
languageModel.status == ModelState.NOT_DOWNLOADED,
),
)
}
}
}
return languageItemPreferenceList
}
private fun addAllLanguagesNotDownloaded(
allLanguageSizeNotDownloaded: Long,
languageItemPreferenceList: MutableList<DownloadLanguageItemPreference>,
) {
if (allLanguageSizeNotDownloaded != 0L) {
languageItemPreferenceList.add(
DownloadLanguageItemPreference(
languageModel = LanguageModel(
status = ModelState.NOT_DOWNLOADED,
size = allLanguageSizeNotDownloaded,
),
type = DownloadLanguageItemTypePreference.AllLanguages,
),
)
}
}
private fun addAllLanguagesDownloaded(
allLanguagesSizeDownloaded: Long,
languageItemPreferenceList: MutableList<DownloadLanguageItemPreference>,
) {
if (allLanguagesSizeDownloaded != 0L) {
languageItemPreferenceList.add(
DownloadLanguageItemPreference(
languageModel = LanguageModel(
status = ModelState.DOWNLOADED,
size = allLanguagesSizeDownloaded,
),
type = DownloadLanguageItemTypePreference.AllLanguages,
),
)
}
}
private fun shouldShowPrefDownloadLanguageFileDialog(
downloadLanguageItemPreference: DownloadLanguageItemPreference,
) =
(
downloadLanguageItemPreference.languageModel.status == ModelState.NOT_DOWNLOADED &&
isDataSaverEnabledAndWifiDisabled &&
!requireContext().settings().ignoreTranslationsDataSaverWarning
)
} }

View file

@ -17,14 +17,24 @@ import androidx.compose.ui.platform.ComposeView
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs import androidx.navigation.fragment.navArgs
import mozilla.components.browser.state.action.TranslationsAction
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.concept.engine.translate.ModelManagementOptions
import mozilla.components.concept.engine.translate.ModelOperation
import mozilla.components.concept.engine.translate.ModelState
import mozilla.components.concept.engine.translate.OperationLevel
import mozilla.components.lib.state.ext.observeAsComposableState
import org.mozilla.fenix.ext.requireComponents
import org.mozilla.fenix.ext.settings import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.theme.FirefoxTheme import org.mozilla.fenix.theme.FirefoxTheme
import java.util.Locale
/** /**
* A fragment dialog displays a delete or download language. * A fragment dialog displays a delete or download language.
*/ */
class LanguageDialogPreferenceFragment : DialogFragment() { class LanguageDialogPreferenceFragment : DialogFragment() {
private val args by navArgs<LanguageDialogPreferenceFragmentArgs>() private val args by navArgs<LanguageDialogPreferenceFragmentArgs>()
private val browserStore: BrowserStore by lazy { requireComponents.core.store }
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog = override fun onCreateDialog(savedInstanceState: Bundle?): Dialog =
super.onCreateDialog(savedInstanceState).apply { super.onCreateDialog(savedInstanceState).apply {
@ -39,10 +49,10 @@ class LanguageDialogPreferenceFragment : DialogFragment() {
savedInstanceState: Bundle?, savedInstanceState: Bundle?,
): View { ): View {
val view = ComposeView(requireContext()) val view = ComposeView(requireContext())
if (args.downloadLanguageItemStatePreference.status == DownloadLanguageItemStatusPreference.Downloaded) { if (args.modelState == ModelState.DOWNLOADED) {
setPrefDeleteLanguageFileDialog(view) setPrefDeleteLanguageFileDialog(view)
} else { } else {
if (args.downloadLanguageItemStatePreference.status == DownloadLanguageItemStatusPreference.NotDownloaded) { if (args.modelState == ModelState.NOT_DOWNLOADED) {
setDownloadLanguageFileDialog(view) setDownloadLanguageFileDialog(view)
} }
} }
@ -54,13 +64,43 @@ class LanguageDialogPreferenceFragment : DialogFragment() {
composeView.apply { composeView.apply {
setContent { setContent {
FirefoxTheme { FirefoxTheme {
val languageModels = browserStore.observeAsComposableState { state ->
state.translationEngine.languageModels
}.value?.toMutableList()
DeleteLanguageFileDialog( DeleteLanguageFileDialog(
language = args.languageNamePreference, language = args.languageDisplayName,
isAllLanguagesItemType = isAllLanguagesItemType =
args.downloadLanguageItemStatePreference.type == args.itemType ==
DownloadLanguageItemTypePreference.AllLanguages, DownloadLanguageItemTypePreference.AllLanguages,
fileSize = args.itemFileSizePreference, fileSize = args.modelSize,
onConfirmDelete = { findNavController().popBackStack() }, onConfirmDelete = {
if (args.itemType == DownloadLanguageItemTypePreference.AllLanguages) {
languageModels?.let {
val downloadedItems = it.filter { languageModel ->
languageModel.status == ModelState.DOWNLOADED
}
for (downloadedItem in downloadedItems) {
if (!downloadedItem.language?.code.equals(
Locale.ENGLISH.language,
)
) {
deleteOrDownloadModel(
modelOperation = ModelOperation.DELETE,
languageToManage = downloadedItem.language?.code,
)
}
}
}
} else {
deleteOrDownloadModel(
modelOperation = ModelOperation.DELETE,
languageToManage = args.languageCode,
)
}
findNavController().popBackStack()
},
onCancel = { findNavController().popBackStack() }, onCancel = { findNavController().popBackStack() },
) )
} }
@ -73,20 +113,44 @@ class LanguageDialogPreferenceFragment : DialogFragment() {
setContent { setContent {
FirefoxTheme { FirefoxTheme {
var checkBoxEnabled by remember { mutableStateOf(false) } var checkBoxEnabled by remember { mutableStateOf(false) }
val languageModels = browserStore.observeAsComposableState { state ->
state.translationEngine.languageModels
}.value?.toMutableList()
DownloadLanguageFileDialog( DownloadLanguageFileDialog(
downloadLanguageDialogType = if (args.downloadLanguageItemStatePreference.type == downloadLanguageDialogType = if (args.itemType ==
DownloadLanguageItemTypePreference.AllLanguages DownloadLanguageItemTypePreference.AllLanguages
) { ) {
DownloadLanguageFileDialogType.AllLanguages DownloadLanguageFileDialogType.AllLanguages
} else { } else {
DownloadLanguageFileDialogType.Default DownloadLanguageFileDialogType.Default
}, },
fileSize = args.itemFileSizePreference, fileSize = args.modelSize,
isCheckBoxEnabled = checkBoxEnabled, isCheckBoxEnabled = checkBoxEnabled,
onSavingModeStateChange = { checkBoxEnabled = it }, onSavingModeStateChange = { checkBoxEnabled = it },
onConfirmDownload = { onConfirmDownload = {
requireContext().settings().ignoreTranslationsDataSaverWarning = requireContext().settings().ignoreTranslationsDataSaverWarning =
checkBoxEnabled checkBoxEnabled
if (args.itemType == DownloadLanguageItemTypePreference.AllLanguages) {
languageModels?.let {
val downloadedItems = it.filter { languageModel ->
languageModel.status == ModelState.NOT_DOWNLOADED
}
for (downloadedItem in downloadedItems) {
deleteOrDownloadModel(
modelOperation = ModelOperation.DOWNLOAD,
languageToManage = downloadedItem.language?.code,
)
}
}
} else {
deleteOrDownloadModel(
modelOperation = ModelOperation.DOWNLOAD,
languageToManage = args.languageCode,
)
}
findNavController().popBackStack() findNavController().popBackStack()
}, },
onCancel = { findNavController().popBackStack() }, onCancel = { findNavController().popBackStack() },
@ -95,4 +159,17 @@ class LanguageDialogPreferenceFragment : DialogFragment() {
} }
} }
} }
private fun deleteOrDownloadModel(modelOperation: ModelOperation, languageToManage: String?) {
val options = ModelManagementOptions(
languageToManage = languageToManage,
operation = modelOperation,
operationLevel = OperationLevel.LANGUAGE,
)
browserStore.dispatch(
TranslationsAction.ManageLanguageModelsAction(
options = options,
),
)
}
} }

View file

@ -1519,16 +1519,22 @@
android:id="@+id/downloadLanguagesDialogPreferenceFragment" android:id="@+id/downloadLanguagesDialogPreferenceFragment"
android:name="org.mozilla.fenix.translations.preferences.downloadlanguages.LanguageDialogPreferenceFragment"> android:name="org.mozilla.fenix.translations.preferences.downloadlanguages.LanguageDialogPreferenceFragment">
<argument <argument
android:name="downloadLanguageItemStatePreference" android:name="modelState"
app:argType="org.mozilla.fenix.translations.preferences.downloadlanguages.DownloadLanguageItemStatePreference" /> app:argType="mozilla.components.concept.engine.translate.ModelState" />
<argument <argument
android:name="languageNamePreference" android:name="itemType"
app:argType="string" app:argType="org.mozilla.fenix.translations.preferences.downloadlanguages.DownloadLanguageItemTypePreference" />
app:nullable="false" />
<argument <argument
android:name="itemFileSizePreference" android:name="languageCode"
app:argType="long" app:nullable="true"
app:nullable="false" /> app:argType="string" />
<argument
android:name="languageDisplayName"
app:nullable="true"
app:argType="string" />
<argument
android:name="modelSize"
app:argType="long" />
</dialog> </dialog>
</navigation> </navigation>

View file

@ -2515,8 +2515,10 @@
<string name="download_languages_language_item_preference">%1$s (%2$s)</string> <string name="download_languages_language_item_preference">%1$s (%2$s)</string>
<!-- The subhead of the download language preference screen will appear above the items that were not downloaded. --> <!-- The subhead of the download language preference screen will appear above the items that were not downloaded. -->
<string name="download_language_header_preference">Download Languages</string> <string name="download_language_header_preference">Download Languages</string>
<!-- All languages list item. When the user presses this item, they can download or delete all languages. --> <!-- All languages list item. When the user presses this item, they can download all languages. -->
<string name="download_language_all_languages_item_preference">All languages</string> <string name="download_language_all_languages_item_preference">All languages</string>
<!-- All languages list item. When the user presses this item, they can delete all languages that were downloaded. -->
<string name="download_language_all_languages_item_preference_to_delete">Delete all languages</string>
<!-- Content description (not visible, for screen readers etc.): For a language list item that was downloaded, the user can now delete it. --> <!-- Content description (not visible, for screen readers etc.): For a language list item that was downloaded, the user can now delete it. -->
<string name="download_languages_item_content_description_downloaded_state">Delete</string> <string name="download_languages_item_content_description_downloaded_state">Delete</string>
<!-- Content description (not visible, for screen readers etc.): For a language list item, downloading is in progress. --> <!-- Content description (not visible, for screen readers etc.): For a language list item, downloading is in progress. -->
@ -2524,7 +2526,7 @@
<!-- Content description (not visible, for screen readers etc.): For a language list item that was not downloaded. --> <!-- Content description (not visible, for screen readers etc.): For a language list item that was not downloaded. -->
<string name="download_languages_item_content_description_not_downloaded_state">Download</string> <string name="download_languages_item_content_description_not_downloaded_state">Download</string>
<!-- Content description (not visible, for screen readers etc.): For a language list item that is selected. --> <!-- Content description (not visible, for screen readers etc.): For a language list item that is selected. -->
<string name="download_languages_item_content_description_selected_state">Selected</string> <string name="download_languages_item_content_description_selected_state" moz:removedIn="127" tools:ignore="UnusedResources">Selected</string>
<!-- Title for the dialog used by the translations feature to confirm deleting a language. <!-- Title for the dialog used by the translations feature to confirm deleting a language.
The dialog will be presented when the user requests deletion of a language. The dialog will be presented when the user requests deletion of a language.