tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit ffaea1fbd2fcc92188618e7cb36c271d9ce7e520
parent 87d62c53683e401d61fbadf14ac211df55803b76
Author: Mugurell <Mugurell@users.noreply.github.com>
Date:   Thu, 20 Nov 2025 09:12:32 +0000

Bug 1996643 - part 5 - Migrate from the environment idiom within SettingsSearchStore r=android-reviewers,matt-tighe

Differential Revision: https://phabricator.services.mozilla.com/D272158

Diffstat:
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/settingssearch/SettingsSearchAction.kt | 7-------
Dmobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/settingssearch/SettingsSearchEnvironment.kt | 24------------------------
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/settingssearch/SettingsSearchFragment.kt | 26+++++---------------------
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/settingssearch/SettingsSearchMiddleware.kt | 48++++++++++++++++++------------------------------
Mmobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/settingssearch/SettingsSearchStore.kt | 1-
Mmobile/android/fenix/app/src/test/java/org/mozilla/fenix/settings/settingssearch/SettingsSearchMiddlewareTest.kt | 76++++++++++++++++------------------------------------------------------------
6 files changed, 39 insertions(+), 143 deletions(-)

diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/settingssearch/SettingsSearchAction.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/settingssearch/SettingsSearchAction.kt @@ -17,13 +17,6 @@ sealed interface SettingsSearchAction : Action { data object Init : SettingsSearchAction /** - * Signals a new valid [SettingsSearchEnvironment] has been set. - * - * @property environment New [SettingsSearchEnvironment]. - */ - data class EnvironmentRehydrated(val environment: SettingsSearchEnvironment) : SettingsSearchAction - - /** * Signals that the current [SettingsSearchEnvironment] has been cleared. */ data object EnvironmentCleared : SettingsSearchAction diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/settingssearch/SettingsSearchEnvironment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/settingssearch/SettingsSearchEnvironment.kt @@ -1,24 +0,0 @@ -/* 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.settings.settingssearch - -import android.content.Context -import androidx.fragment.app.Fragment -import androidx.navigation.NavController - -/** - * Environment for the [SettingsSearchStore]. - * - * @property navController [NavController] used for navigation. - * @property fragment [Fragment] used for lifecycle owner and context for UI operations. - * @property context [Context] used for various system interactions - * @property recentSettingsSearchesRepository [RecentSettingsSearchesRepository] used for storing recent searches. - */ -data class SettingsSearchEnvironment( - val navController: NavController, - val fragment: Fragment, - val context: Context, - val recentSettingsSearchesRepository: RecentSettingsSearchesRepository, -) diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/settingssearch/SettingsSearchFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/settingssearch/SettingsSearchFragment.kt @@ -11,9 +11,9 @@ import android.view.ViewGroup import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.Fragment import androidx.fragment.compose.content -import androidx.lifecycle.DefaultLifecycleObserver +import androidx.lifecycle.coroutineScope import androidx.navigation.fragment.findNavController -import org.mozilla.fenix.components.StoreProvider +import mozilla.components.lib.state.helpers.StoreProvider.Companion.storeProvider import org.mozilla.fenix.ext.components import org.mozilla.fenix.theme.FirefoxTheme @@ -49,34 +49,18 @@ class SettingsSearchFragment : Fragment() { private fun buildSettingsSearchStore(): SettingsSearchStore { val recentSettingsSearchesRepository = FenixRecentSettingsSearchesRepository(requireContext()) - return StoreProvider.get(this) { + return storeProvider.get { restoredState -> SettingsSearchStore( - initialState = SettingsSearchState.Default(emptyList()), + initialState = restoredState ?: SettingsSearchState.Default(emptyList()), middleware = listOf( SettingsSearchMiddleware( fenixSettingsIndexer = requireContext().components.settingsIndexer, - ), - ), - ) - }.also { - it.dispatch( - SettingsSearchAction.EnvironmentRehydrated( - environment = SettingsSearchEnvironment( - fragment = this, navController = findNavController(), - context = requireContext(), recentSettingsSearchesRepository = recentSettingsSearchesRepository, + scope = viewLifecycleOwner.lifecycle.coroutineScope, ), ), ) - - viewLifecycleOwner.lifecycle.addObserver( - object : DefaultLifecycleObserver { - override fun onDestroy(owner: androidx.lifecycle.LifecycleOwner) { - it.dispatch(SettingsSearchAction.EnvironmentCleared) - } - }, - ) } } } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/settingssearch/SettingsSearchMiddleware.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/settingssearch/SettingsSearchMiddleware.kt @@ -5,9 +5,7 @@ package org.mozilla.fenix.settings.settingssearch import androidx.core.os.bundleOf -import androidx.lifecycle.Lifecycle.State.RESUMED -import androidx.lifecycle.lifecycleScope -import androidx.lifecycle.repeatOnLifecycle +import androidx.navigation.NavController import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -18,15 +16,19 @@ import mozilla.components.lib.state.MiddlewareContext /** * [Middleware] for the settings search screen. * - * @property fenixSettingsIndexer [SettingsIndexer] to use for indexing and querying settings. - * @property dispatcher [CoroutineDispatcher] to use for performing background tasks. + * @param fenixSettingsIndexer [SettingsIndexer] to use for indexing and querying settings. + * @param navController [NavController] used for navigation. + * @param recentSettingsSearchesRepository [RecentSettingsSearchesRepository] used for storing recent searches. + * @param scope [CoroutineScope] used for running long running operations in background. + * @param dispatcher [CoroutineDispatcher] to use for performing background tasks. */ class SettingsSearchMiddleware( - val fenixSettingsIndexer: SettingsIndexer, - val dispatcher: CoroutineDispatcher = Dispatchers.IO, + private val fenixSettingsIndexer: SettingsIndexer, + private val navController: NavController, + private val recentSettingsSearchesRepository: RecentSettingsSearchesRepository, + private val scope: CoroutineScope, + private val dispatcher: CoroutineDispatcher = Dispatchers.IO, ) : Middleware<SettingsSearchState, SettingsSearchAction> { - internal var environment: SettingsSearchEnvironment? = null - override fun invoke( context: MiddlewareContext<SettingsSearchState, SettingsSearchAction>, next: (SettingsSearchAction) -> Unit, @@ -37,17 +39,7 @@ class SettingsSearchMiddleware( is SettingsSearchAction.Init -> { next(action) fenixSettingsIndexer.indexAllSettings() - } - is SettingsSearchAction.EnvironmentRehydrated -> { - next(action) - environment = action.environment - environment?.fragment?.viewLifecycleOwner?.lifecycleScope?.launch { - observeRecentSearches(store) - } - } - is SettingsSearchAction.EnvironmentCleared -> { - next(action) - environment = null + scope.launch { observeRecentSearches(store) } } is SettingsSearchAction.SearchQueryUpdated -> { next(action) @@ -73,17 +65,17 @@ class SettingsSearchMiddleware( ) val fragmentId = searchItem.preferenceFileInformation.fragmentId CoroutineScope(dispatcher).launch { - environment?.recentSettingsSearchesRepository?.addRecentSearchItem(searchItem) + recentSettingsSearchesRepository.addRecentSearchItem(searchItem) } CoroutineScope(Dispatchers.Main).launch { - environment?.navController?.navigate(fragmentId, bundle) + navController.navigate(fragmentId, bundle) } next(action) } is SettingsSearchAction.ClearRecentSearchesClicked -> { next(action) CoroutineScope(Dispatchers.IO).launch { - environment?.recentSettingsSearchesRepository?.clearRecentSearches() + recentSettingsSearchesRepository.clearRecentSearches() } } else -> { @@ -99,13 +91,9 @@ class SettingsSearchMiddleware( * @param store The [SettingsSearchStore] to dispatch the updates to. */ private fun observeRecentSearches(store: SettingsSearchStore) { - environment?.fragment?.viewLifecycleOwner?.run { - lifecycleScope.launch { - repeatOnLifecycle(RESUMED) { - environment?.recentSettingsSearchesRepository?.recentSearches?.collect { recents -> - store.dispatch(SettingsSearchAction.RecentSearchesUpdated(recents)) - } - } + scope.launch { + recentSettingsSearchesRepository.recentSearches.collect { recents -> + store.dispatch(SettingsSearchAction.RecentSearchesUpdated(recents)) } } } diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/settingssearch/SettingsSearchStore.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/settings/settingssearch/SettingsSearchStore.kt @@ -71,7 +71,6 @@ private fun reduce(state: SettingsSearchState, action: SettingsSearchAction): Se is SettingsSearchAction.Init, is SettingsSearchAction.ResultItemClicked, is SettingsSearchAction.EnvironmentCleared, - is SettingsSearchAction.EnvironmentRehydrated, -> state } } diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/settings/settingssearch/SettingsSearchMiddlewareTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/settings/settingssearch/SettingsSearchMiddlewareTest.kt @@ -15,6 +15,8 @@ import io.mockk.every import io.mockk.mockk import io.mockk.spyk import io.mockk.verify +import kotlinx.coroutines.CoroutineDispatcher +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.test.runTest import mozilla.components.support.test.robolectric.testContext @@ -47,31 +49,25 @@ class SettingsSearchMiddlewareTest { every { fragment.viewLifecycleOwner } returns lifecycleOwner } - private fun buildMiddleware(): SettingsSearchMiddleware { - return SettingsSearchMiddleware( - fenixSettingsIndexer = TestSettingsIndexer(), - dispatcher = coroutineRule.testDispatcher, - ) - } + private fun buildMiddleware( + fenixSettingsIndexer: SettingsIndexer = TestSettingsIndexer(), + navController: NavController = this.navController, + recentSettingsSearchesRepository: RecentSettingsSearchesRepository = this.recentSearchesRepository, + scope: CoroutineScope = coroutineRule.scope, + dispatcher: CoroutineDispatcher = coroutineRule.testDispatcher, + ) = SettingsSearchMiddleware( + fenixSettingsIndexer = fenixSettingsIndexer, + navController = navController, + recentSettingsSearchesRepository = recentSettingsSearchesRepository, + scope = scope, + dispatcher = dispatcher, + ) @Test fun `WHEN the settings search query is updated and results are not found THEN the state is updated`() { - val middleware = SettingsSearchMiddleware( - fenixSettingsIndexer = EmptyTestSettingsIndexer(), - dispatcher = coroutineRule.testDispatcher, - ) + val middleware = buildMiddleware(EmptyTestSettingsIndexer()) val query = "longSample" val store = SettingsSearchStore(middleware = listOf(middleware)) - store.dispatch( - SettingsSearchAction.EnvironmentRehydrated( - environment = SettingsSearchEnvironment( - fragment = fragment, - navController = navController, - context = testContext, - recentSettingsSearchesRepository = recentSearchesRepository, - ), - ), - ) store.dispatch(SettingsSearchAction.SearchQueryUpdated(query)) assert(store.state is SettingsSearchState.NoSearchResults) assert(store.state.searchQuery == query) @@ -84,16 +80,6 @@ class SettingsSearchMiddlewareTest { val query = "a" val store = SettingsSearchStore(middleware = listOf(middleware)) store.dispatch(SettingsSearchAction.Init) - store.dispatch( - SettingsSearchAction.EnvironmentRehydrated( - environment = SettingsSearchEnvironment( - fragment = fragment, - navController = navController, - context = testContext, - recentSettingsSearchesRepository = recentSearchesRepository, - ), - ), - ) store.dispatch(SettingsSearchAction.SearchQueryUpdated(query)) assert(store.state is SettingsSearchState.SearchInProgress) assert(store.state.searchQuery == query) @@ -106,16 +92,6 @@ class SettingsSearchMiddlewareTest { val testItem = testList.first() store.dispatch(SettingsSearchAction.Init) - store.dispatch( - SettingsSearchAction.EnvironmentRehydrated( - environment = SettingsSearchEnvironment( - fragment = fragment, - navController = navController, - context = testContext, - recentSettingsSearchesRepository = recentSearchesRepository, - ), - ), - ) store.dispatch(SettingsSearchAction.ResultItemClicked(testItem)) @@ -128,16 +104,6 @@ class SettingsSearchMiddlewareTest { val middleware = buildMiddleware() val store = SettingsSearchStore(middleware = listOf(middleware)) val updatedRecents = listOf(testList.first()) - store.dispatch( - SettingsSearchAction.EnvironmentRehydrated( - environment = SettingsSearchEnvironment( - fragment = fragment, - navController = navController, - context = testContext, - recentSettingsSearchesRepository = recentSearchesRepository, - ), - ), - ) store.dispatch(SettingsSearchAction.RecentSearchesUpdated(updatedRecents)) @@ -148,16 +114,6 @@ class SettingsSearchMiddlewareTest { fun `WHEN ClearRecentSearchesClicked is dispatched THEN store state is updated correctly`() { val middleware = buildMiddleware() val store = SettingsSearchStore(middleware = listOf(middleware)) - store.dispatch( - SettingsSearchAction.EnvironmentRehydrated( - environment = SettingsSearchEnvironment( - fragment = fragment, - navController = navController, - context = testContext, - recentSettingsSearchesRepository = recentSearchesRepository, - ), - ), - ) store.dispatch(SettingsSearchAction.ClearRecentSearchesClicked)