From 5d8a920b5f67912a7959130fcec9c983450ffcc3 Mon Sep 17 00:00:00 2001 From: Jonathan Almeida Date: Mon, 1 Nov 2021 01:32:38 -0400 Subject: [PATCH] [fenix] Close https://github.com/mozilla-mobile/fenix/issues/20704: Add AppStore to Components --- .../org/mozilla/fenix/components/AppStore.kt | 22 +++++++++++++++ .../mozilla/fenix/components/Components.kt | 1 + .../fenix/components/appstate/AppAction.kt | 15 +++++++++++ .../fenix/components/appstate/AppState.kt | 17 ++++++++++++ .../components/appstate/AppStoreReducer.kt | 17 ++++++++++++ .../components/appstate/AppActionTest.kt | 27 +++++++++++++++++++ .../browser/InactiveTabsControllerTest.kt | 10 ++++--- 7 files changed, 106 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/org/mozilla/fenix/components/AppStore.kt create mode 100644 app/src/main/java/org/mozilla/fenix/components/appstate/AppAction.kt create mode 100644 app/src/main/java/org/mozilla/fenix/components/appstate/AppState.kt create mode 100644 app/src/main/java/org/mozilla/fenix/components/appstate/AppStoreReducer.kt create mode 100644 app/src/test/java/org/mozilla/fenix/components/appstate/AppActionTest.kt diff --git a/app/src/main/java/org/mozilla/fenix/components/AppStore.kt b/app/src/main/java/org/mozilla/fenix/components/AppStore.kt new file mode 100644 index 000000000..b82f0ea91 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/components/AppStore.kt @@ -0,0 +1,22 @@ +/* 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.components + +import mozilla.components.lib.state.Middleware +import mozilla.components.lib.state.Store +import org.mozilla.fenix.components.appstate.AppAction +import org.mozilla.fenix.components.appstate.AppState +import org.mozilla.fenix.components.appstate.AppStoreReducer + +/** + * A [Store] that holds the [AppState] for the app and reduces [AppAction]s + * dispatched to the store. + * + * This store is not persisted to disk and is scoped to the life-cycle of the application. + */ +class AppStore( + initialState: AppState = AppState(), + middlewares: List> = emptyList() +) : Store(initialState, AppStoreReducer::reduce, middlewares) diff --git a/app/src/main/java/org/mozilla/fenix/components/Components.kt b/app/src/main/java/org/mozilla/fenix/components/Components.kt index 4a844349c..954f27cfd 100644 --- a/app/src/main/java/org/mozilla/fenix/components/Components.kt +++ b/app/src/main/java/org/mozilla/fenix/components/Components.kt @@ -176,6 +176,7 @@ class Components(private val context: Context) { val appStartReasonProvider by lazyMonitored { AppStartReasonProvider() } val startupActivityLog by lazyMonitored { StartupActivityLog() } val startupStateProvider by lazyMonitored { StartupStateProvider(startupActivityLog, appStartReasonProvider) } + val appStore by lazyMonitored { AppStore() } } /** diff --git a/app/src/main/java/org/mozilla/fenix/components/appstate/AppAction.kt b/app/src/main/java/org/mozilla/fenix/components/appstate/AppAction.kt new file mode 100644 index 000000000..2d30dcbf9 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/components/appstate/AppAction.kt @@ -0,0 +1,15 @@ +/* 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.components.appstate + +import mozilla.components.lib.state.Action +import org.mozilla.fenix.components.AppStore + +/** + * [Action] implementation related to [AppStore]. + */ +sealed class AppAction : Action { + data class UpdateInactiveExpanded(val expanded: Boolean) : AppAction() +} diff --git a/app/src/main/java/org/mozilla/fenix/components/appstate/AppState.kt b/app/src/main/java/org/mozilla/fenix/components/appstate/AppState.kt new file mode 100644 index 000000000..281b13bb7 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/components/appstate/AppState.kt @@ -0,0 +1,17 @@ +/* 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.components.appstate + +import mozilla.components.lib.state.State + +/** + * Value type that represents the state of the tabs tray. + * + * @property inactiveTabsExpanded A flag to know if the Inactive Tabs section of the Tabs Tray + * should be expanded when the tray is opened. + */ +data class AppState( + val inactiveTabsExpanded: Boolean = false +) : State diff --git a/app/src/main/java/org/mozilla/fenix/components/appstate/AppStoreReducer.kt b/app/src/main/java/org/mozilla/fenix/components/appstate/AppStoreReducer.kt new file mode 100644 index 000000000..f61421c28 --- /dev/null +++ b/app/src/main/java/org/mozilla/fenix/components/appstate/AppStoreReducer.kt @@ -0,0 +1,17 @@ +/* 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.components.appstate + +import org.mozilla.fenix.components.AppStore + +/** + * Reducer for [AppStore]. + */ +internal object AppStoreReducer { + fun reduce(state: AppState, action: AppAction): AppState = when (action) { + is AppAction.UpdateInactiveExpanded -> + state.copy(inactiveTabsExpanded = action.expanded) + } +} diff --git a/app/src/test/java/org/mozilla/fenix/components/appstate/AppActionTest.kt b/app/src/test/java/org/mozilla/fenix/components/appstate/AppActionTest.kt new file mode 100644 index 000000000..8bbd4f551 --- /dev/null +++ b/app/src/test/java/org/mozilla/fenix/components/appstate/AppActionTest.kt @@ -0,0 +1,27 @@ +/* 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.components.appstate + +import mozilla.components.support.test.ext.joinBlocking +import mozilla.components.support.test.middleware.CaptureActionsMiddleware +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Test +import org.mozilla.fenix.components.AppStore + +class AppActionTest { + + private val capture = CaptureActionsMiddleware() + private val store = AppStore(middlewares = listOf(capture)) + + @Test + fun `WHEN UpdateInactiveExpanded is dispatched THEN update inactiveTabsExpanded`() { + assertFalse(store.state.inactiveTabsExpanded) + + store.dispatch(AppAction.UpdateInactiveExpanded(true)).joinBlocking() + + assertTrue(store.state.inactiveTabsExpanded) + } +} diff --git a/app/src/test/java/org/mozilla/fenix/tabstray/browser/InactiveTabsControllerTest.kt b/app/src/test/java/org/mozilla/fenix/tabstray/browser/InactiveTabsControllerTest.kt index a781ba9c1..54d6c3916 100644 --- a/app/src/test/java/org/mozilla/fenix/tabstray/browser/InactiveTabsControllerTest.kt +++ b/app/src/test/java/org/mozilla/fenix/tabstray/browser/InactiveTabsControllerTest.kt @@ -14,10 +14,14 @@ import mozilla.components.browser.tabstray.TabsTray import org.junit.Assert.assertEquals import mozilla.components.browser.state.state.createTab as createTabState import org.junit.Test +import org.mozilla.fenix.components.AppStore import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.components.metrics.MetricController class InactiveTabsControllerTest { + + private val appStore = AppStore() + @Test fun `WHEN expanded THEN notify filtered card`() { val filter: (TabSessionState) -> Boolean = { !it.content.private } @@ -32,7 +36,7 @@ class InactiveTabsControllerTest { ) val tray: TabsTray = mockk(relaxed = true) val tabsSlot = slot>() - val controller = InactiveTabsController(store, filter, tray, mockk(relaxed = true)) + val controller = InactiveTabsController(store, appStore, filter, tray, mockk(relaxed = true)) controller.updateCardExpansion(true) @@ -47,7 +51,7 @@ class InactiveTabsControllerTest { val metrics: MetricController = mockk(relaxed = true) val store = BrowserStore(BrowserState()) val controller = InactiveTabsController( - store, mockk(relaxed = true), mockk(relaxed = true), metrics + store, appStore, mockk(relaxed = true), mockk(relaxed = true), metrics ) controller.updateCardExpansion(true) @@ -60,7 +64,7 @@ class InactiveTabsControllerTest { val metrics: MetricController = mockk(relaxed = true) val store = BrowserStore(BrowserState()) val controller = InactiveTabsController( - store, mockk(relaxed = true), mockk(relaxed = true), metrics + store, appStore, mockk(relaxed = true), mockk(relaxed = true), metrics ) controller.updateCardExpansion(false)