Bug 1864075 - Create navigation middleware for the debug drawer

fenix/123.0
Noah Bond 5 months ago committed by mergify[bot]
parent 8395c80252
commit 3ceb50b299

@ -0,0 +1,21 @@
/* 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.debugsettings.navigation
import androidx.annotation.StringRes
import androidx.compose.runtime.Composable
/**
* A navigation destination for screens within the Debug Drawer.
*
* @property route The navigation route of the destination.
* @property title The string ID of the destination's title.
* @property content The destination's [Composable].
*/
data class DebugDrawerDestination(
val route: String,
@StringRes val title: Int,
val content: @Composable () -> Unit,
)

@ -0,0 +1,52 @@
/* 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.debugsettings.navigation
import androidx.annotation.StringRes
import org.mozilla.fenix.R
import org.mozilla.fenix.debugsettings.ui.DebugDrawerHome
import org.mozilla.fenix.debugsettings.tabs.TabTools as TabToolsScreen
/**
* The navigation routes for screens within the Debug Drawer.
*
* @property route The navigation route of the destination.
* @property title The string ID of the destination's title.
*/
enum class DebugDrawerRoute(val route: String, @StringRes val title: Int) {
/**
* The navigation route for [DebugDrawerHome].
*/
Home(
route = "home",
title = R.string.debug_drawer_title,
),
/**
* The navigation route for [TabToolsScreen].
*/
TabTools(
route = "tab_tools",
title = R.string.debug_drawer_tab_tools_title,
),
}
/**
* Creates a list of [DebugDrawerDestination]s for the [DebugDrawerRoute]s in Fenix.
*/
fun debugDrawerDestinationsFromRoutes(
// Composable content dependencies will go here (e.g. browser store, the list of menu items, etc.)
): List<DebugDrawerDestination> = DebugDrawerRoute.values().map { debugDrawerRoute ->
DebugDrawerDestination(
route = debugDrawerRoute.route,
title = debugDrawerRoute.title,
content = {
when (debugDrawerRoute) {
DebugDrawerRoute.Home -> {}
DebugDrawerRoute.TabTools -> {}
}
},
)
}

@ -5,6 +5,8 @@
package org.mozilla.fenix.debugsettings.store
import mozilla.components.lib.state.Action
import org.mozilla.fenix.debugsettings.ui.DebugDrawerHome
import org.mozilla.fenix.debugsettings.tabs.TabTools as TabToolsScreen
/**
* [Action] implementation related to [DebugDrawerStore].
@ -20,4 +22,25 @@ sealed class DebugDrawerAction : Action {
* [DebugDrawerAction] fired when the user closes the drawer.
*/
object DrawerClosed : DebugDrawerAction()
/**
* [DebugDrawerAction] fired when a navigation event occurs for a specific destination.
*/
sealed class NavigateTo : DebugDrawerAction() {
/**
* [NavigateTo] action fired when the debug drawer needs to navigate to [DebugDrawerHome].
*/
object Home : NavigateTo()
/**
* [NavigateTo] action fired when the debug drawer needs to navigate to [TabToolsScreen].
*/
object TabTools : NavigateTo()
}
/**
* [DebugDrawerAction] fired when a back navigation event occurs.
*/
object OnBackPressed : DebugDrawerAction()
}

@ -0,0 +1,33 @@
/* 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.debugsettings.store
import androidx.navigation.NavHostController
import mozilla.components.lib.state.Middleware
import mozilla.components.lib.state.MiddlewareContext
import org.mozilla.fenix.debugsettings.navigation.DebugDrawerRoute
/**
* Middleware that handles navigation events for the Debug Drawer feature.
*
* @param navController [NavHostController] used to execute any navigation actions on the UI.
*/
class DebugDrawerNavigationMiddleware(
private val navController: NavHostController,
) : Middleware<DebugDrawerState, DebugDrawerAction> {
override fun invoke(
context: MiddlewareContext<DebugDrawerState, DebugDrawerAction>,
next: (DebugDrawerAction) -> Unit,
action: DebugDrawerAction,
) {
when (action) {
is DebugDrawerAction.NavigateTo.Home -> navController.navigate(route = DebugDrawerRoute.Home.route)
is DebugDrawerAction.NavigateTo.TabTools -> navController.navigate(route = DebugDrawerRoute.TabTools.route)
is DebugDrawerAction.OnBackPressed -> navController.popBackStack()
is DebugDrawerAction.DrawerOpened, DebugDrawerAction.DrawerClosed -> {} // no-op
}
}
}

@ -20,9 +20,8 @@ class DebugDrawerStore(
middlewares,
)
private fun reduce(state: DebugDrawerState, action: DebugDrawerAction): DebugDrawerState {
return when (action) {
is DebugDrawerAction.DrawerOpened -> state.copy(drawerStatus = DrawerStatus.Open)
is DebugDrawerAction.DrawerClosed -> state.copy(drawerStatus = DrawerStatus.Closed)
}
private fun reduce(state: DebugDrawerState, action: DebugDrawerAction): DebugDrawerState = when (action) {
is DebugDrawerAction.DrawerOpened -> state.copy(drawerStatus = DrawerStatus.Open)
is DebugDrawerAction.DrawerClosed -> state.copy(drawerStatus = DrawerStatus.Closed)
is DebugDrawerAction.NavigateTo, DebugDrawerAction.OnBackPressed -> state // handled by [DebugDrawerNavigationMiddleware]
}

@ -2411,8 +2411,10 @@
<string name="download_language_file_dialog_negative_button_text">Cancel</string>
<!-- Debug drawer -->
<!-- The user-facing title of the Debug Drawer feature. -->
<string name="debug_drawer_title">Debug Tools</string>
<!-- The title of the Tab Tools feature in the Debug Drawer. -->
<string name="debug_drawer_tab_tools_title" tools:ignore="UnusedResources">Tab Tools</string>
<string name="debug_drawer_tab_tools_title">Tab Tools</string>
<!-- The title of the tab count section in Tab Tools. -->
<string name="debug_drawer_tab_tools_tab_count_title">Tab count</string>
<!-- The active tab count category in the tab count section in Tab Tools. -->

@ -0,0 +1,63 @@
/* 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.debugsettings
import androidx.navigation.NavHostController
import io.mockk.called
import io.mockk.mockk
import io.mockk.verify
import mozilla.components.support.test.ext.joinBlocking
import org.junit.Before
import org.junit.Test
import org.mozilla.fenix.debugsettings.navigation.DebugDrawerRoute
import org.mozilla.fenix.debugsettings.store.DebugDrawerAction
import org.mozilla.fenix.debugsettings.store.DebugDrawerNavigationMiddleware
import org.mozilla.fenix.debugsettings.store.DebugDrawerStore
class DebugDrawerNavigationMiddlewareTest {
private val navController: NavHostController = mockk(relaxed = true)
private lateinit var store: DebugDrawerStore
@Before
fun setup() {
store = DebugDrawerStore(
middlewares = listOf(
DebugDrawerNavigationMiddleware(
navController = navController,
),
),
)
}
@Test
fun `WHEN home is the next destination THEN home is navigated to`() {
store.dispatch(DebugDrawerAction.NavigateTo.Home).joinBlocking()
verify { navController.navigate(DebugDrawerRoute.Home.route) }
}
@Test
fun `WHEN the tab tools screen is the next destination THEN the tab tools screen is navigated to`() {
store.dispatch(DebugDrawerAction.NavigateTo.TabTools).joinBlocking()
verify { navController.navigate(DebugDrawerRoute.TabTools.route) }
}
@Test
fun `WHEN the back button is pressed THEN the drawer should go back one screen`() {
store.dispatch(DebugDrawerAction.OnBackPressed).joinBlocking()
verify { navController.popBackStack() }
}
@Test
fun `WHEN a non-navigation action is dispatched THEN the drawer should not navigate`() {
store.dispatch(DebugDrawerAction.DrawerOpened).joinBlocking()
store.dispatch(DebugDrawerAction.DrawerClosed).joinBlocking()
verify { navController wasNot called }
}
}

@ -60,6 +60,7 @@ object FenixDependencies {
const val androidx_navigation_ui = "androidx.navigation:navigation-ui:${FenixVersions.androidx_navigation}"
const val androidx_transition = "androidx.transition:transition:${FenixVersions.androidx_transition}"
const val androidx_datastore = "androidx.datastore:datastore:${FenixVersions.androidx_datastore}"
const val androidx_compose_navigation = "androidx.navigation:navigation-compose:${FenixVersions.androidx_navigation}"
const val google_accompanist_drawablepainter = "com.google.accompanist:accompanist-drawablepainter:${FenixVersions.google_accompanist}"

Loading…
Cancel
Save