For #17190: notifications are updated when locale is changed (#18179)

* Add intent processor for locale changes

* Recreate notification and notify in the service

* Use locale use cases to update notification

* Use notification id instead of tag

* Add locale use cases and restore locale in application

* Send locale to service instead of string

* Controller tests for locale

* Update Android Components version to 74.0.20210323143308

Co-authored-by: Arturo Mejia <arturomejiamarmol@gmail.com>

(cherry picked from commit 559cf54798)
pull/420/head
Elise Richards 3 years ago committed by mergify[bot]
parent aa6e7c3da8
commit eec72dc9b5

@ -165,6 +165,7 @@ open class FenixApplication : LocaleAwareApplication(), Provider {
initializeWebExtensionSupport() initializeWebExtensionSupport()
restoreBrowserState() restoreBrowserState()
restoreDownloads() restoreDownloads()
restoreLocale()
// Just to make sure it is impossible for any application-services pieces // Just to make sure it is impossible for any application-services pieces
// to invoke parts of itself that require complete megazord initialization // to invoke parts of itself that require complete megazord initialization
@ -213,6 +214,10 @@ open class FenixApplication : LocaleAwareApplication(), Provider {
components.useCases.downloadUseCases.restoreDownloads() components.useCases.downloadUseCases.restoreDownloads()
} }
private fun restoreLocale() {
components.useCases.localeUseCases.restore()
}
private fun initVisualCompletenessQueueAndQueueTasks() { private fun initVisualCompletenessQueueAndQueueTasks() {
val queue = components.performance.visualCompletenessQueue.queue val queue = components.performance.visualCompletenessQueue.queue

@ -22,6 +22,7 @@ import mozilla.components.feature.tabs.CustomTabsUseCases
import mozilla.components.feature.tabs.TabsUseCases import mozilla.components.feature.tabs.TabsUseCases
import mozilla.components.feature.top.sites.TopSitesStorage import mozilla.components.feature.top.sites.TopSitesStorage
import mozilla.components.feature.top.sites.TopSitesUseCases import mozilla.components.feature.top.sites.TopSitesUseCases
import mozilla.components.support.locale.LocaleUseCases
import org.mozilla.fenix.perf.lazyMonitored import org.mozilla.fenix.perf.lazyMonitored
import org.mozilla.fenix.utils.Mockable import org.mozilla.fenix.utils.Mockable
@ -88,4 +89,9 @@ class UseCases(
* Use cases that provide top sites management. * Use cases that provide top sites management.
*/ */
val topSitesUseCase by lazyMonitored { TopSitesUseCases(topSitesStorage) } val topSitesUseCase by lazyMonitored { TopSitesUseCases(topSitesStorage) }
/**
* Use cases that handle locale management.
*/
val localeUseCases by lazyMonitored { LocaleUseCases(store) }
} }

@ -16,6 +16,7 @@ import org.mozilla.fenix.R
import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.metrics import org.mozilla.fenix.ext.metrics
import java.util.Locale
/** /**
* Manages notifications for private tabs. * Manages notifications for private tabs.
@ -33,9 +34,28 @@ class PrivateNotificationService : AbstractPrivateNotificationService() {
override fun NotificationCompat.Builder.buildNotification() { override fun NotificationCompat.Builder.buildNotification() {
setSmallIcon(R.drawable.ic_private_browsing) setSmallIcon(R.drawable.ic_private_browsing)
setContentTitle(applicationContext.getString(R.string.app_name_private_4, getString(R.string.app_name))) setContentTitle(
setContentText(applicationContext.getString(R.string.notification_pbm_delete_text_2)) applicationContext.getString(
color = ContextCompat.getColor(this@PrivateNotificationService, R.color.pbm_notification_color) R.string.app_name_private_4,
getString(R.string.app_name)
)
)
setContentText(
applicationContext.getString(
R.string.notification_pbm_delete_text_2
)
)
color = ContextCompat.getColor(
this@PrivateNotificationService,
R.color.pbm_notification_color
)
}
/**
* Update the existing notification when the [Locale] has been changed.
*/
override fun notifyLocaleChanged() {
super.refreshNotification()
} }
@SuppressLint("MissingSuperCall") @SuppressLint("MissingSuperCall")

@ -7,6 +7,7 @@ package org.mozilla.fenix.settings.advanced
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import mozilla.components.support.locale.LocaleManager import mozilla.components.support.locale.LocaleManager
import mozilla.components.support.locale.LocaleUseCases
import java.util.Locale import java.util.Locale
interface LocaleSettingsController { interface LocaleSettingsController {
@ -17,7 +18,8 @@ interface LocaleSettingsController {
class DefaultLocaleSettingsController( class DefaultLocaleSettingsController(
private val activity: Activity, private val activity: Activity,
private val localeSettingsStore: LocaleSettingsStore private val localeSettingsStore: LocaleSettingsStore,
private val localeUseCase: LocaleUseCases
) : LocaleSettingsController { ) : LocaleSettingsController {
override fun handleLocaleSelected(locale: Locale) { override fun handleLocaleSelected(locale: Locale) {
@ -26,7 +28,7 @@ class DefaultLocaleSettingsController(
return return
} }
localeSettingsStore.dispatch(LocaleSettingsAction.Select(locale)) localeSettingsStore.dispatch(LocaleSettingsAction.Select(locale))
LocaleManager.setNewLocale(activity, locale.toLanguageTag()) LocaleManager.setNewLocale(activity, localeUseCase, locale)
LocaleManager.updateBaseConfiguration(activity, locale) LocaleManager.updateBaseConfiguration(activity, locale)
activity.recreate() activity.recreate()
} }
@ -36,7 +38,7 @@ class DefaultLocaleSettingsController(
return return
} }
localeSettingsStore.dispatch(LocaleSettingsAction.Select(localeSettingsStore.state.localeList[0])) localeSettingsStore.dispatch(LocaleSettingsAction.Select(localeSettingsStore.state.localeList[0]))
LocaleManager.resetToSystemDefault(activity) LocaleManager.resetToSystemDefault(activity, localeUseCase)
LocaleManager.updateBaseConfiguration(activity, localeSettingsStore.state.localeList[0]) LocaleManager.updateBaseConfiguration(activity, localeSettingsStore.state.localeList[0])
activity.recreate() activity.recreate()
} }

@ -17,13 +17,15 @@ import kotlinx.android.synthetic.main.fragment_locale_settings.view.*
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import mozilla.components.lib.state.ext.consumeFrom import mozilla.components.lib.state.ext.consumeFrom
import mozilla.components.support.ktx.android.view.hideKeyboard import mozilla.components.support.ktx.android.view.hideKeyboard
import mozilla.components.support.locale.LocaleUseCases
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.components.StoreProvider import org.mozilla.fenix.components.StoreProvider
import org.mozilla.fenix.ext.components
import org.mozilla.fenix.ext.showToolbar import org.mozilla.fenix.ext.showToolbar
class LocaleSettingsFragment : Fragment() { class LocaleSettingsFragment : Fragment() {
private lateinit var store: LocaleSettingsStore private lateinit var localeSettingsStore: LocaleSettingsStore
private lateinit var interactor: LocaleSettingsInteractor private lateinit var interactor: LocaleSettingsInteractor
private lateinit var localeView: LocaleSettingsView private lateinit var localeView: LocaleSettingsView
@ -39,7 +41,10 @@ class LocaleSettingsFragment : Fragment() {
): View? { ): View? {
val view = inflater.inflate(R.layout.fragment_locale_settings, container, false) val view = inflater.inflate(R.layout.fragment_locale_settings, container, false)
store = StoreProvider.get(this) { val browserStore = requireContext().components.core.store
val localeUseCase = LocaleUseCases(browserStore)
localeSettingsStore = StoreProvider.get(this) {
LocaleSettingsStore( LocaleSettingsStore(
createInitialLocaleSettingsState(requireContext()) createInitialLocaleSettingsState(requireContext())
) )
@ -47,7 +52,8 @@ class LocaleSettingsFragment : Fragment() {
interactor = LocaleSettingsInteractor( interactor = LocaleSettingsInteractor(
controller = DefaultLocaleSettingsController( controller = DefaultLocaleSettingsController(
activity = requireActivity(), activity = requireActivity(),
localeSettingsStore = store localeSettingsStore = localeSettingsStore,
localeUseCase = localeUseCase
) )
) )
localeView = LocaleSettingsView(view.locale_container, interactor) localeView = LocaleSettingsView(view.locale_container, interactor)
@ -87,7 +93,7 @@ class LocaleSettingsFragment : Fragment() {
@ExperimentalCoroutinesApi @ExperimentalCoroutinesApi
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
consumeFrom(store) { consumeFrom(localeSettingsStore) {
localeView.update(it) localeView.update(it)
} }
} }

@ -15,6 +15,7 @@ import io.mockk.spyk
import io.mockk.verify import io.mockk.verify
import io.mockk.verifyAll import io.mockk.verifyAll
import mozilla.components.support.locale.LocaleManager import mozilla.components.support.locale.LocaleManager
import mozilla.components.support.locale.LocaleUseCases
import org.junit.Before import org.junit.Before
import org.junit.Test import org.junit.Test
import java.util.Locale import java.util.Locale
@ -23,13 +24,20 @@ class LocaleSettingsControllerTest {
private val activity = mockk<Activity>(relaxed = true) private val activity = mockk<Activity>(relaxed = true)
private val localeSettingsStore: LocaleSettingsStore = mockk(relaxed = true) private val localeSettingsStore: LocaleSettingsStore = mockk(relaxed = true)
private val localeUseCases: LocaleUseCases = mockk(relaxed = true)
private val mockState = LocaleSettingsState(mockk(), mockk(), mockk()) private val mockState = LocaleSettingsState(mockk(), mockk(), mockk())
private lateinit var controller: DefaultLocaleSettingsController private lateinit var controller: DefaultLocaleSettingsController
@Before @Before
fun setup() { fun setup() {
controller = spyk(DefaultLocaleSettingsController(activity, localeSettingsStore)) controller = spyk(
DefaultLocaleSettingsController(
activity,
localeSettingsStore,
localeUseCases
)
)
mockkObject(LocaleManager) mockkObject(LocaleManager)
mockkStatic("org.mozilla.fenix.settings.advanced.LocaleManagerExtensionKt") mockkStatic("org.mozilla.fenix.settings.advanced.LocaleManagerExtensionKt")
@ -45,11 +53,13 @@ class LocaleSettingsControllerTest {
verifyAll(inverse = true) { verifyAll(inverse = true) {
localeSettingsStore.dispatch(LocaleSettingsAction.Select(selectedLocale)) localeSettingsStore.dispatch(LocaleSettingsAction.Select(selectedLocale))
LocaleManager.setNewLocale(activity, selectedLocale.toLanguageTag()) LocaleManager.setNewLocale(activity, locale = selectedLocale)
activity.recreate() activity.recreate()
} }
with(controller) { with(controller) {
verify(inverse = true) { LocaleManager.updateBaseConfiguration(activity, selectedLocale) } verify(inverse = true) {
LocaleManager.updateBaseConfiguration(activity, selectedLocale)
}
} }
} }
@ -57,8 +67,9 @@ class LocaleSettingsControllerTest {
fun `set a new locale from the list if other locale is chosen`() { fun `set a new locale from the list if other locale is chosen`() {
val selectedLocale = Locale("en", "UK") val selectedLocale = Locale("en", "UK")
val otherLocale: Locale = mockk() val otherLocale: Locale = mockk()
every { localeUseCases.notifyLocaleChanged } returns mockk()
every { localeSettingsStore.state } returns mockState.copy(selectedLocale = otherLocale) every { localeSettingsStore.state } returns mockState.copy(selectedLocale = otherLocale)
every { LocaleManager.setNewLocale(activity, selectedLocale.toLanguageTag()) } returns activity every { LocaleManager.setNewLocale(activity, localeUseCases, selectedLocale) } returns activity
with(controller) { with(controller) {
every { LocaleManager.updateBaseConfiguration(activity, selectedLocale) } just Runs every { LocaleManager.updateBaseConfiguration(activity, selectedLocale) } just Runs
} }
@ -66,7 +77,7 @@ class LocaleSettingsControllerTest {
controller.handleLocaleSelected(selectedLocale) controller.handleLocaleSelected(selectedLocale)
verify { localeSettingsStore.dispatch(LocaleSettingsAction.Select(selectedLocale)) } verify { localeSettingsStore.dispatch(LocaleSettingsAction.Select(selectedLocale)) }
verify { LocaleManager.setNewLocale(activity, selectedLocale.toLanguageTag()) } verify { LocaleManager.setNewLocale(activity, localeUseCases, selectedLocale) }
verify { activity.recreate() } verify { activity.recreate() }
with(controller) { with(controller) {
verify { LocaleManager.updateBaseConfiguration(activity, selectedLocale) } verify { LocaleManager.updateBaseConfiguration(activity, selectedLocale) }
@ -76,9 +87,11 @@ class LocaleSettingsControllerTest {
@Test @Test
fun `set a new locale from the list if default locale is not selected`() { fun `set a new locale from the list if default locale is not selected`() {
val selectedLocale = Locale("en", "UK") val selectedLocale = Locale("en", "UK")
every { localeUseCases.notifyLocaleChanged } returns mockk()
every { localeSettingsStore.state } returns mockState.copy(selectedLocale = selectedLocale) every { localeSettingsStore.state } returns mockState.copy(selectedLocale = selectedLocale)
every { LocaleManager.getCurrentLocale(activity) } returns null every { LocaleManager.getCurrentLocale(activity) } returns null
every { LocaleManager.setNewLocale(activity, selectedLocale.toLanguageTag()) } returns activity every { LocaleManager.setNewLocale(activity, localeUseCases, selectedLocale) } returns activity
with(controller) { with(controller) {
every { LocaleManager.updateBaseConfiguration(activity, selectedLocale) } just Runs every { LocaleManager.updateBaseConfiguration(activity, selectedLocale) } just Runs
} }
@ -86,7 +99,7 @@ class LocaleSettingsControllerTest {
controller.handleLocaleSelected(selectedLocale) controller.handleLocaleSelected(selectedLocale)
verify { localeSettingsStore.dispatch(LocaleSettingsAction.Select(selectedLocale)) } verify { localeSettingsStore.dispatch(LocaleSettingsAction.Select(selectedLocale)) }
verify { LocaleManager.setNewLocale(activity, selectedLocale.toLanguageTag()) } verify { LocaleManager.setNewLocale(activity, localeUseCases, selectedLocale) }
verify { activity.recreate() } verify { activity.recreate() }
with(controller) { with(controller) {
verify { LocaleManager.updateBaseConfiguration(activity, selectedLocale) } verify { LocaleManager.updateBaseConfiguration(activity, selectedLocale) }
@ -103,7 +116,7 @@ class LocaleSettingsControllerTest {
verifyAll(inverse = true) { verifyAll(inverse = true) {
localeSettingsStore.dispatch(LocaleSettingsAction.Select(selectedLocale)) localeSettingsStore.dispatch(LocaleSettingsAction.Select(selectedLocale))
LocaleManager.resetToSystemDefault(activity) LocaleManager.resetToSystemDefault(activity, localeUseCases)
activity.recreate() activity.recreate()
with(controller) { with(controller) {
LocaleManager.updateBaseConfiguration(activity, selectedLocale) LocaleManager.updateBaseConfiguration(activity, selectedLocale)
@ -114,8 +127,9 @@ class LocaleSettingsControllerTest {
@Test @Test
fun `set the default locale as the new locale`() { fun `set the default locale as the new locale`() {
val selectedLocale = Locale("en", "UK") val selectedLocale = Locale("en", "UK")
every { localeUseCases.notifyLocaleChanged } returns mockk()
every { localeSettingsStore.state } returns mockState.copy(localeList = listOf(selectedLocale)) every { localeSettingsStore.state } returns mockState.copy(localeList = listOf(selectedLocale))
every { LocaleManager.resetToSystemDefault(activity) } just Runs every { LocaleManager.resetToSystemDefault(activity, localeUseCases) } just Runs
with(controller) { with(controller) {
every { LocaleManager.updateBaseConfiguration(activity, selectedLocale) } just Runs every { LocaleManager.updateBaseConfiguration(activity, selectedLocale) } just Runs
} }
@ -123,7 +137,7 @@ class LocaleSettingsControllerTest {
controller.handleDefaultLocaleSelected() controller.handleDefaultLocaleSelected()
verify { localeSettingsStore.dispatch(LocaleSettingsAction.Select(selectedLocale)) } verify { localeSettingsStore.dispatch(LocaleSettingsAction.Select(selectedLocale)) }
verify { LocaleManager.resetToSystemDefault(activity) } verify { LocaleManager.resetToSystemDefault(activity, localeUseCases) }
verify { activity.recreate() } verify { activity.recreate() }
with(controller) { with(controller) {
verify { LocaleManager.updateBaseConfiguration(activity, selectedLocale) } verify { LocaleManager.updateBaseConfiguration(activity, selectedLocale) }

Loading…
Cancel
Save