Bug 1856955 - Translations UI Download Model Settings Screen Popups.

fenix/123.0
iorgamgabriel 6 months ago committed by mergify[bot]
parent 06e71e5244
commit 62d7b1ce5e

@ -25,7 +25,7 @@ import org.mozilla.fenix.compose.list.TextListItem
import org.mozilla.fenix.theme.FirefoxTheme
/**
* Firefox Translation settings fragment compose view.
* Translation Settings Fragment.
*
* @param translationSwitchList list of [TranslationSwitchItem]s to display.
* @param onAutomaticTranslationClicked Invoked when the user clicks on the "Automatic Translation" button.

@ -15,7 +15,7 @@ import org.mozilla.fenix.ext.showToolbar
import org.mozilla.fenix.theme.FirefoxTheme
/**
* A fragment displaying the Firefox Preference Automatic Translation Options screen.
* A fragment displaying Automatic Translation Options screen.
*/
class AutomaticTranslationOptionsPreferenceFragment : Fragment() {
private val args by navArgs<AutomaticTranslationOptionsPreferenceFragmentArgs>()

@ -23,7 +23,7 @@ import org.mozilla.fenix.theme.FirefoxTheme
import java.util.Locale
/**
* Firefox Preferences Automatic Translate preference screen.
* Automatic Translate preference screen.
*
* @param automaticTranslationListPreferences List of [AutomaticTranslationItemPreference]s to display.
* @param onItemClick Invoked when the user clicks on the a item from the list.

@ -0,0 +1,126 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.translations.preferences.downloadlanguages
import androidx.compose.foundation.background
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.AlertDialog
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import mozilla.components.feature.downloads.toMegabyteOrKilobyteString
import org.mozilla.fenix.R
import org.mozilla.fenix.compose.annotation.LightDarkPreview
import org.mozilla.fenix.compose.button.TextButton
import org.mozilla.fenix.theme.FirefoxTheme
import java.util.Locale
/**
* Download Languages Delete Dialog.
*
* @param language Language name that should be displayed in the dialogue title.
* @param isAllLanguagesItemType Whether the download language file item is of type all languages.
* @param fileSize Language file size in bytes that should be displayed in the dialogue title.
* @param onConfirmDelete Invoked when the user clicks on the "Delete" dialog button.
* @param onCancel Invoked when the user clicks on the "Cancel" dialog button.
*/
@Composable
fun DeleteLanguageFileDialog(
language: String,
isAllLanguagesItemType: Boolean,
fileSize: Long,
onConfirmDelete: () -> Unit,
onCancel: () -> Unit,
) {
AlertDialog(
onDismissRequest = {},
modifier = Modifier.background(
color = FirefoxTheme.colors.layer2,
shape = RoundedCornerShape(8.dp),
),
title = {
val title: String = if (isAllLanguagesItemType) {
stringResource(
id = R.string.delete_language_all_languages_file_dialog_title,
fileSize.toMegabyteOrKilobyteString(),
)
} else {
stringResource(
id = R.string.delete_language_file_dialog_title,
language,
fileSize.toMegabyteOrKilobyteString(),
)
}
Text(
text = title,
color = FirefoxTheme.colors.textPrimary,
style = FirefoxTheme.typography.headline7,
)
},
text = {
val message: String = if (isAllLanguagesItemType) {
stringResource(
id = R.string.delete_language_all_languages_file_dialog_message,
stringResource(id = R.string.firefox),
)
} else {
stringResource(
id = R.string.delete_language_file_dialog_message,
stringResource(id = R.string.firefox),
)
}
Text(
text = message,
color = FirefoxTheme.colors.textPrimary,
style = FirefoxTheme.typography.body2,
)
},
confirmButton = {
TextButton(
text = stringResource(id = R.string.delete_language_file_dialog_positive_button_text),
onClick = { onConfirmDelete() },
)
},
dismissButton = {
TextButton(
text = stringResource(id = R.string.delete_language_file_dialog_negative_button_text),
onClick = { onCancel() },
)
},
backgroundColor = FirefoxTheme.colors.layer2,
)
}
@Composable
@LightDarkPreview
private fun DeleteLanguageFileDialogPreview() {
FirefoxTheme {
DeleteLanguageFileDialog(
language = Locale.CHINA.displayLanguage,
isAllLanguagesItemType = false,
fileSize = 4000L,
onConfirmDelete = {},
onCancel = {},
)
}
}
@Composable
@LightDarkPreview
private fun DeleteAllLanguagesFileDialogPreview() {
FirefoxTheme {
DeleteLanguageFileDialog(
language = Locale.CHINA.displayLanguage,
isAllLanguagesItemType = true,
fileSize = 4000L,
onConfirmDelete = {},
onCancel = {},
)
}
}

@ -0,0 +1,192 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.translations.preferences.downloadlanguages
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.defaultMinSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.selection.toggleable
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Checkbox
import androidx.compose.material.CheckboxDefaults
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.Role
import androidx.compose.ui.semantics.clearAndSetSemantics
import androidx.compose.ui.semantics.heading
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import mozilla.components.feature.downloads.toMegabyteOrKilobyteString
import org.mozilla.fenix.R
import org.mozilla.fenix.compose.annotation.LightDarkPreview
import org.mozilla.fenix.compose.button.PrimaryButton
import org.mozilla.fenix.compose.button.TextButton
import org.mozilla.fenix.theme.FirefoxTheme
/**
* Download Languages File Dialog.
*
* @param fileSize Language file size in bytes that should be displayed in the dialogue title.
* @param isCheckBoxEnabled Whether saving mode checkbox is checked or unchecked.
* @param isAllLanguagesItemType Whether the download language file item is of type all languages.
* @param onSavingModeStateChange Invoked when the user clicks on the checkbox of the saving mode state.
* @param onConfirmDownload Invoked when the user click on the "Download" dialog button.
* @param onCancel Invoked when the user clicks on the "Cancel" dialog button.
*/
@Suppress("LongParameterList")
@Composable
fun DownloadLanguageFileDialog(
fileSize: Long,
isCheckBoxEnabled: Boolean,
isAllLanguagesItemType: Boolean,
onSavingModeStateChange: (Boolean) -> Unit,
onConfirmDownload: () -> Unit,
onCancel: () -> Unit,
) {
Dialog(onDismissRequest = {}) {
Column(
modifier = Modifier
.background(
color = FirefoxTheme.colors.layer2,
shape = RoundedCornerShape(8.dp),
)
.padding(16.dp),
) {
Text(
text = stringResource(
R.string.download_language_file_dialog_title,
fileSize.toMegabyteOrKilobyteString(),
),
modifier = Modifier
.semantics { heading() },
color = FirefoxTheme.colors.textPrimary,
style = FirefoxTheme.typography.headline7,
fontWeight = FontWeight.Bold,
)
if (isAllLanguagesItemType) {
Text(
text = stringResource(
R.string.download_language_file_dialog_message_all_languages,
),
modifier = Modifier.padding(top = 16.dp, bottom = 16.dp),
style = FirefoxTheme.typography.body2,
color = FirefoxTheme.colors.textPrimary,
)
}
DownloadLanguageFileDialogCheckbox(
isCheckBoxEnabled = isCheckBoxEnabled,
onSavingModeStateChange = onSavingModeStateChange,
)
val primaryButtonText: String = if (isAllLanguagesItemType) {
stringResource(id = R.string.download_language_file_dialog_positive_button_text_all_languages)
} else {
stringResource(id = R.string.download_language_file_dialog_positive_button_text)
}
PrimaryButton(
text = primaryButtonText,
modifier = Modifier
.padding(top = 16.dp)
.fillMaxWidth(),
onClick = {
onConfirmDownload()
},
)
TextButton(
text = stringResource(id = R.string.download_language_file_dialog_negative_button_text),
modifier = Modifier
.fillMaxWidth(),
onClick = {
onCancel()
},
)
}
}
}
@Composable
private fun DownloadLanguageFileDialogCheckbox(
isCheckBoxEnabled: Boolean,
onSavingModeStateChange: (Boolean) -> Unit,
) {
val checkBoxText = stringResource(
R.string.download_language_file_dialog_checkbox_text,
)
Row(
modifier = Modifier
.toggleable(
value = isCheckBoxEnabled,
role = Role.Checkbox,
onValueChange = onSavingModeStateChange,
)
.defaultMinSize(minHeight = 56.dp),
) {
Checkbox(
modifier = Modifier
.align(Alignment.CenterVertically)
.clearAndSetSemantics { },
checked = isCheckBoxEnabled,
onCheckedChange = onSavingModeStateChange,
colors = CheckboxDefaults.colors(
checkedColor = FirefoxTheme.colors.formSelected,
uncheckedColor = FirefoxTheme.colors.formDefault,
),
)
Spacer(modifier = Modifier.width(20.dp))
Text(
modifier = Modifier
.align(Alignment.CenterVertically),
text = checkBoxText,
style = FirefoxTheme.typography.body2,
color = FirefoxTheme.colors.textPrimary,
)
}
}
@Composable
@LightDarkPreview
private fun PrefDownloadLanguageFileDialogPreviewAllLanguages() {
FirefoxTheme {
DownloadLanguageFileDialog(
fileSize = 4000L,
isCheckBoxEnabled = true,
isAllLanguagesItemType = true,
onSavingModeStateChange = {},
onConfirmDownload = {},
onCancel = {},
)
}
}
@Composable
@LightDarkPreview
private fun PrefDownloadLanguageFileDialogPreview() {
FirefoxTheme {
DownloadLanguageFileDialog(
fileSize = 4000L,
isCheckBoxEnabled = false,
isAllLanguagesItemType = false,
onSavingModeStateChange = {},
onConfirmDownload = {},
onCancel = {},
)
}
}

@ -0,0 +1,76 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.translations.preferences.downloadlanguages
import android.app.Application
import android.content.Context
import android.net.ConnectivityManager
import android.os.Build
import androidx.annotation.VisibleForTesting
import androidx.core.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_ENABLED
import androidx.core.net.ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_WHITELISTED
import mozilla.components.support.base.feature.LifecycleAwareFeature
import org.mozilla.fenix.wifi.WifiConnectionMonitor
/**
* Helper for observing WiFi connection and data saving mode.
*
* @param context Android context.
* @param wifiConnectionMonitor Attaches itself to the [Application]
* and listens for WIFI available/not available events.
* @param onDataSaverAndWifiChanged A callback that will return true if the data saver is on and WiFi is off.
*/
class DownloadLanguagesFeature(
private val context: Context,
private val wifiConnectionMonitor: WifiConnectionMonitor,
private val onDataSaverAndWifiChanged: (Boolean) -> Unit,
) : LifecycleAwareFeature {
@VisibleForTesting
internal var connectivityManager: ConnectivityManager? = null
@VisibleForTesting
internal val wifiConnectedListener: ((Boolean) -> Unit) by lazy {
{ connected: Boolean ->
var isDataSaverEnabled = false
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val restrictBackgroundStatus = connectivityManager?.restrictBackgroundStatus
if (restrictBackgroundStatus == RESTRICT_BACKGROUND_STATUS_ENABLED ||
restrictBackgroundStatus == RESTRICT_BACKGROUND_STATUS_WHITELISTED
) {
isDataSaverEnabled = true
}
}
if (isDataSaverEnabled && !connected) {
onDataSaverAndWifiChanged.invoke(true)
} else {
onDataSaverAndWifiChanged.invoke(false)
}
}
}
private fun addWifiConnectedListener() {
wifiConnectionMonitor.addOnWifiConnectedChangedListener(wifiConnectedListener)
}
private fun removeWifiConnectedListener() {
wifiConnectionMonitor.removeOnWifiConnectedChangedListener(wifiConnectedListener)
}
override fun start() {
connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as
ConnectivityManager
wifiConnectionMonitor.start()
addWifiConnectedListener()
}
override fun stop() {
connectivityManager = null
wifiConnectionMonitor.stop()
removeWifiConnectedListener()
}
}

@ -10,14 +10,22 @@ import android.view.View
import android.view.ViewGroup
import androidx.compose.ui.platform.ComposeView
import androidx.fragment.app.Fragment
import androidx.navigation.findNavController
import mozilla.components.support.base.feature.ViewBoundFeatureWrapper
import org.mozilla.fenix.R
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.ext.showToolbar
import org.mozilla.fenix.theme.FirefoxTheme
/**
* A fragment displaying the Firefox Preferences Download Languages screen.
* A fragment displaying Download Languages screen.
*/
class DownloadLanguagesPreferenceFragment : Fragment() {
private val downloadLanguagesFeature =
ViewBoundFeatureWrapper<DownloadLanguagesFeature>()
private var isDataSaverEnabledAndWifiDisabled = false
override fun onResume() {
super.onResume()
showToolbar(getString(R.string.download_languages_toolbar_title_preference))
@ -32,9 +40,51 @@ class DownloadLanguagesPreferenceFragment : Fragment() {
FirefoxTheme {
DownloadLanguagesPreference(
downloadLanguageItemPreferences = getLanguageListPreference(),
onItemClick = {},
onItemClick = { downloadLanguageItemPreference ->
if (downloadLanguageItemPreference.state.status ==
DownloadLanguageItemStatusPreference.Downloaded ||
shouldShowPrefDownloadLanguageFileDialog(
downloadLanguageItemPreference,
)
) {
downloadLanguageItemPreference.languageModel.language?.localizedDisplayName?.let {
findNavController().navigate(
DownloadLanguagesPreferenceFragmentDirections
.actionDownloadLanguagesPreferenceToDownloadLanguagesDialogPreference(
downloadLanguageItemPreference.state,
it,
downloadLanguageItemPreference.languageModel.size,
),
)
}
}
},
)
}
}
}
private fun shouldShowPrefDownloadLanguageFileDialog(
downloadLanguageItemPreference: DownloadLanguageItemPreference,
) =
(
downloadLanguageItemPreference.state.status == DownloadLanguageItemStatusPreference.NotDownloaded &&
isDataSaverEnabledAndWifiDisabled &&
!requireContext().settings().ignoreTranslationsDataSaverWarning
)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
downloadLanguagesFeature.set(
feature = DownloadLanguagesFeature(
context = requireContext(),
wifiConnectionMonitor = requireContext().components.wifiConnectionMonitor,
onDataSaverAndWifiChanged = {
isDataSaverEnabledAndWifiDisabled = it
},
),
owner = this,
view = view,
)
}
}

@ -0,0 +1,93 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.translations.preferences.downloadlanguages
import android.app.Dialog
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.ComposeView
import androidx.fragment.app.DialogFragment
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
import org.mozilla.fenix.ext.settings
import org.mozilla.fenix.theme.FirefoxTheme
/**
* A fragment dialog displays a delete or download language.
*/
class LanguageDialogPreferenceFragment : DialogFragment() {
private val args by navArgs<LanguageDialogPreferenceFragmentArgs>()
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog =
super.onCreateDialog(savedInstanceState).apply {
setOnShowListener {
setCanceledOnTouchOutside(false)
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?,
): View {
val view = ComposeView(requireContext())
if (args.downloadLanguageItemStatePreference.status == DownloadLanguageItemStatusPreference.Downloaded) {
setPrefDeleteLanguageFileDialog(view)
} else {
if (args.downloadLanguageItemStatePreference.status == DownloadLanguageItemStatusPreference.NotDownloaded) {
setDownloadLanguageFileDialog(view)
}
}
return view
}
private fun setPrefDeleteLanguageFileDialog(composeView: ComposeView) {
composeView.apply {
setContent {
FirefoxTheme {
DeleteLanguageFileDialog(
language = args.languageNamePreference,
isAllLanguagesItemType =
args.downloadLanguageItemStatePreference.type ==
DownloadLanguageItemTypePreference.AllLanguages,
fileSize = args.itemFileSizePreference,
onConfirmDelete = { findNavController().popBackStack() },
onCancel = { findNavController().popBackStack() },
)
}
}
}
}
private fun setDownloadLanguageFileDialog(composeView: ComposeView) {
composeView.apply {
setContent {
FirefoxTheme {
var checkBoxEnabled by remember { mutableStateOf(false) }
DownloadLanguageFileDialog(
fileSize = args.itemFileSizePreference,
isCheckBoxEnabled = checkBoxEnabled,
isAllLanguagesItemType = args.downloadLanguageItemStatePreference.type ==
DownloadLanguageItemTypePreference.AllLanguages,
onSavingModeStateChange = { checkBoxEnabled = it },
onConfirmDownload = {
requireContext().settings().ignoreTranslationsDataSaverWarning =
checkBoxEnabled
findNavController().popBackStack()
},
onCancel = { findNavController().popBackStack() },
)
}
}
}
}
}

@ -18,7 +18,7 @@ import org.mozilla.fenix.compose.button.TextButton
import org.mozilla.fenix.theme.FirefoxTheme
/**
* Firefox Preference: Never Translate Dialog compose view.
* Never Translate Dialog
*
* @param websiteUrl Title of the dialog that should be display.
* @param onConfirmDelete Invoked when the user clicks on the "Delete" dialog button.

@ -16,7 +16,7 @@ import androidx.navigation.fragment.navArgs
import org.mozilla.fenix.theme.FirefoxTheme
/**
* A dialog fragment displaying the Firefox Preference: never translate site item.
* A dialog fragment displaying never translate site item.
*/
class NeverTranslateSiteDialogPreferenceFragment : DialogFragment() {

@ -26,7 +26,7 @@ import org.mozilla.fenix.compose.list.TextListItem
import org.mozilla.fenix.theme.FirefoxTheme
/**
* Firefox Preference: Never Translate Site preference screen.
* Never Translate Site preference screen.
*
* @param neverTranslateSiteListPreferences List of [NeverTranslateSiteListItemPreference]s to display.
* @param onItemClick Invoked when the user clicks on the a item from the list.

@ -16,7 +16,7 @@ import org.mozilla.fenix.ext.showToolbar
import org.mozilla.fenix.theme.FirefoxTheme
/**
* A fragment displaying the Firefox Preference never translate site items list.
* A fragment displaying never translate site items list.
*/
class NeverTranslateSitePreferenceFragment : Fragment() {
override fun onResume() {

@ -1948,6 +1948,15 @@ class Settings(private val appContext: Context) : PreferencesHolder {
featureFlag = FeatureFlags.fxSuggest,
)
/**
* Indicates that the user does not want warned of a translations
* model download while in data saver mode and using mobile data.
*/
var ignoreTranslationsDataSaverWarning by booleanPreference(
appContext.getPreferenceKey(R.string.pref_key_ignore_translations_data_saver_warning),
default = false,
)
/**
* Indicates if the user is shown new redesigned Toolbar UI.
*/

@ -1453,10 +1453,6 @@
android:id="@+id/action_translationSettingsFragment_to_neverTranslateSitePreferenceFragment"
app:destination="@id/neverTranslateSitePreferenceFragment" />
</fragment>
<fragment
android:id="@+id/downloadLanguagesPreferenceFragment"
android:name="org.mozilla.fenix.translations.preferences.downloadlanguages.DownloadLanguagesPreferenceFragment">
</fragment>
<fragment
android:id="@+id/automaticTranslationPreferenceFragment"
android:name="org.mozilla.fenix.translations.preferences.automatic.AutomaticTranslationPreferenceFragment">
@ -1485,5 +1481,27 @@
android:name="websiteUrl"
app:argType="string" />
</dialog>
<fragment
android:id="@+id/downloadLanguagesPreferenceFragment"
android:name="org.mozilla.fenix.translations.preferences.downloadlanguages.DownloadLanguagesPreferenceFragment">
<action
android:id="@+id/action_downloadLanguagesPreference_to_downloadLanguagesDialogPreference"
app:destination="@id/downloadLanguagesDialogPreferenceFragment" />
</fragment>
<dialog
android:id="@+id/downloadLanguagesDialogPreferenceFragment"
android:name="org.mozilla.fenix.translations.preferences.downloadlanguages.LanguageDialogPreferenceFragment">
<argument
android:name="downloadLanguageItemStatePreference"
app:argType="org.mozilla.fenix.translations.preferences.downloadlanguages.DownloadLanguageItemStatePreference" />
<argument
android:name="languageNamePreference"
app:argType="string"
app:nullable="false" />
<argument
android:name="itemFileSizePreference"
app:argType="long"
app:nullable="false" />
</dialog>
</navigation>
</navigation>

@ -119,7 +119,7 @@
<string name="pref_key_show_sponsored_suggestions" translatable="false">pref_key_show_sponsored_suggestions</string>
<string name="pref_key_show_nonsponsored_suggestions" translatable="false">pref_key_show_nonsponsored_suggestions</string>
<string name="pref_key_learn_about_fx_suggest" translatable="false">pref_key_learn_about_fx_suggest</string>
<!-- Site Permissions Settings -->
<string name="pref_key_site_permissions_description" translatable="false">pref_key_site_permissions_description</string>
<string name="pref_key_show_site_exceptions" translatable="false">pref_key_show_site_exceptions</string>
@ -386,4 +386,7 @@
<string name="pref_key_should_show_review_quality_opt_in_time">pref_key_should_show_review_quality_opt_in_time</string>
<string name="pref_key_should_show_review_quality_cfr_displayed_time">pref_key_should_show_review_quality_cfr_displayed_time</string>
<string name="pref_key_review_quality_cfr_shown_counter">pref_key_review_quality_cfr_shown_counter</string>
<!--Translations -->
<string name="pref_key_ignore_translations_data_saver_warning" translatable="false">pref_key_ignore_translations_data_saver_warning</string>
</resources>

@ -2305,6 +2305,39 @@
<!-- 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>
<!-- 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 first parameter is the name of the language, for example, "Spanish" and the second parameter is the size in kilobytes or megabytes of the language file. -->
<string name="delete_language_file_dialog_title">Delete %1$s (%2$s)?</string>
<!-- Additional information for the dialog used by the translations feature to confirm deleting a language. The first parameter is the name of the application, for example, "Fenix". -->
<string name="delete_language_file_dialog_message">If you delete this language, %1$s will download partial languages to your cache as you translate.</string>
<!-- Title for the dialog used by the translations feature to confirm deleting all languages file.
The dialog will be presented when the user requests deletion of all languages file.
The first parameter is the size in kilobytes or megabytes of the language file. -->
<string name="delete_language_all_languages_file_dialog_title">Delete all languages (%1$s)?</string>
<!-- Additional information for the dialog used by the translations feature to confirm deleting all languages file. The first parameter is the name of the application, for example, "Fenix". -->
<string name="delete_language_all_languages_file_dialog_message">If you delete all languages, %1$s will download partial languages to your cache as you translate.</string>
<!-- Button text on the dialog used by the translations feature to confirm deleting a language. -->
<string name="delete_language_file_dialog_positive_button_text">Delete</string>
<!-- Button text on the dialog used by the translations feature to cancel deleting a language. -->
<string name="delete_language_file_dialog_negative_button_text">Cancel</string>
<!-- Title for the data saving mode warning dialog used by the translations feature.
This dialog will be presented when the user attempts to download a language or perform
a translation without the necessary language files downloaded first when Android's data saver mode is enabled and the user is not using WiFi.
The first parameter is the size in kilobytes or megabytes of the language file.-->
<string name="download_language_file_dialog_title">Download while in data saving mode (%1$s)?</string>
<!-- Additional information for the data saving mode warning dialog used by the translations feature. This text explains the reason a download is required for a translation. -->
<string name="download_language_file_dialog_message_all_languages">We download partial languages to your cache to keep translations private.</string>
<!-- Checkbox label text on the data saving mode warning dialog used by the translations feature. This checkbox allows users to ignore the data usage warnings. -->
<string name="download_language_file_dialog_checkbox_text">Always download in data saving mode</string>
<!-- Button text on the data saving mode warning dialog used by the translations feature to allow users to confirm they wish to continue and download the language file. -->
<string name="download_language_file_dialog_positive_button_text">Download</string>
<!-- Button text on the data saving mode warning dialog used by the translations feature to allow users to confirm they wish to continue and download the language file and perform a translation. -->
<string name="download_language_file_dialog_positive_button_text_all_languages">Download and translate</string>
<!-- Button text on the data saving mode warning dialog used by the translations feature to allow users to cancel the action and not perform a download of the language file. -->
<string name="download_language_file_dialog_negative_button_text">Cancel</string>
<!-- Debug drawer -->
<!-- The title of the Tab Tools feature in the Debug Drawer. -->
<string name="debug_drawer_tab_tools_title" tools:ignore="UnusedResources">Tab Tools</string>

@ -0,0 +1,126 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.translations.preferences.downloadlanguages
import android.net.ConnectivityManager
import android.os.Build
import androidx.core.net.ConnectivityManagerCompat
import androidx.test.ext.junit.runners.AndroidJUnit4
import io.mockk.every
import io.mockk.mockk
import io.mockk.verify
import mozilla.components.support.test.mock
import mozilla.components.support.test.robolectric.testContext
import org.junit.Assert
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito
import org.mozilla.fenix.wifi.WifiConnectionMonitor
import org.robolectric.annotation.Config
@RunWith(AndroidJUnit4::class)
class DownloadLanguagesFeatureTest {
private lateinit var downloadLanguagesFeature: DownloadLanguagesFeature
private lateinit var wifiConnectionMonitor: WifiConnectionMonitor
private lateinit var dataSaverAndWifiChanged: ((Boolean) -> Unit)
private lateinit var connectivityManager: ConnectivityManager
@Before
fun setUp() {
wifiConnectionMonitor = mockk(relaxed = true)
dataSaverAndWifiChanged = mock()
connectivityManager = mockk()
downloadLanguagesFeature =
DownloadLanguagesFeature(
context = testContext,
wifiConnectionMonitor = wifiConnectionMonitor,
onDataSaverAndWifiChanged = dataSaverAndWifiChanged,
)
downloadLanguagesFeature.connectivityManager = mockk()
}
@Test
fun `GIVEN fragment is added WHEN the feature starts THEN listen for wifi changes`() {
downloadLanguagesFeature.start()
verify(exactly = 1) {
wifiConnectionMonitor.start()
}
verify(exactly = 1) {
wifiConnectionMonitor.addOnWifiConnectedChangedListener(
downloadLanguagesFeature.wifiConnectedListener,
)
}
Assert.assertNotNull(downloadLanguagesFeature.connectivityManager)
}
@Test
fun `WHEN stopping the feature THEN all listeners will be removed`() {
downloadLanguagesFeature.stop()
verify(exactly = 1) {
wifiConnectionMonitor.stop()
}
verify(exactly = 1) {
wifiConnectionMonitor.removeOnWifiConnectedChangedListener(
downloadLanguagesFeature.wifiConnectedListener,
)
}
Assert.assertNull(downloadLanguagesFeature.connectivityManager)
}
@Test
@Config(sdk = [Build.VERSION_CODES.N])
fun `GIVEN wifi is connected WHEN wifi changes to not connected and restrictBackgroundStatus is RESTRICT_BACKGROUND_STATUS_ENABLED THEN onDataSaverAndWifiChanged callback should return true`() {
every { connectivityManager.restrictBackgroundStatus } returns
ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_ENABLED
downloadLanguagesFeature.start()
downloadLanguagesFeature.connectivityManager = connectivityManager
downloadLanguagesFeature.wifiConnectedListener(false)
Mockito.verify(dataSaverAndWifiChanged).invoke(true)
}
@Test
@Config(sdk = [Build.VERSION_CODES.N])
fun `GIVEN wifi is connected WHEN wifi changes to not connected and restrictBackgroundStatus is RESTRICT_BACKGROUND_STATUS_WHITELISTED THEN onDataSaverAndWifiChanged callback should return true`() {
every { connectivityManager.restrictBackgroundStatus } returns
ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_WHITELISTED
downloadLanguagesFeature.start()
downloadLanguagesFeature.connectivityManager = connectivityManager
downloadLanguagesFeature.wifiConnectedListener(false)
Mockito.verify(dataSaverAndWifiChanged).invoke(true)
}
@Test
@Config(sdk = [Build.VERSION_CODES.N])
fun `GIVEN wifi is connected WHEN wifi changes to connected and restrictBackgroundStatus is RESTRICT_BACKGROUND_STATUS_WHITELISTED THEN onDataSaverAndWifiChanged callback should return false`() {
every { connectivityManager.restrictBackgroundStatus } returns
ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_WHITELISTED
downloadLanguagesFeature.start()
downloadLanguagesFeature.connectivityManager = connectivityManager
downloadLanguagesFeature.wifiConnectedListener(true)
Mockito.verify(dataSaverAndWifiChanged).invoke(false)
}
@Test
@Config(sdk = [Build.VERSION_CODES.N])
fun `GIVEN wifi is connected WHEN wifi changes to connected and restrictBackgroundStatus is RESTRICT_BACKGROUND_STATUS_DISABLED THEN onDataSaverAndWifiChanged callback should return false`() {
every { connectivityManager.restrictBackgroundStatus } returns
ConnectivityManagerCompat.RESTRICT_BACKGROUND_STATUS_DISABLED
downloadLanguagesFeature.start()
downloadLanguagesFeature.connectivityManager = connectivityManager
downloadLanguagesFeature.wifiConnectedListener(true)
Mockito.verify(dataSaverAndWifiChanged).invoke(false)
}
}
Loading…
Cancel
Save