Bug 1864073 - Stand up debug drawer Store and State

fenix/123.0
Noah Bond 5 months ago committed by mergify[bot]
parent 56309b2673
commit 23ddff7ebb

@ -102,6 +102,7 @@ import org.mozilla.fenix.components.metrics.GrowthDataWorker
import org.mozilla.fenix.components.metrics.fonts.FontEnumerationWorker
import org.mozilla.fenix.databinding.ActivityHomeBinding
import org.mozilla.fenix.debugsettings.data.DefaultDebugSettingsRepository
import org.mozilla.fenix.debugsettings.store.DebugDrawerStore
import org.mozilla.fenix.debugsettings.ui.DebugOverlay
import org.mozilla.fenix.exceptions.trackingprotection.TrackingProtectionExceptionsFragmentDirections
import org.mozilla.fenix.experiments.ResearchSurfaceDialogFragment
@ -301,7 +302,9 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity {
setContent {
FirefoxTheme(theme = Theme.getTheme(allowPrivateTheme = false)) {
DebugOverlay()
DebugOverlay(
debugDrawerStore = DebugDrawerStore(),
)
}
}
} else {

@ -0,0 +1,23 @@
/* 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 mozilla.components.lib.state.Action
/**
* [Action] implementation related to [DebugDrawerStore].
*/
sealed class DebugDrawerAction : Action {
/**
* [DebugDrawerAction] fired when the user opens the drawer.
*/
object DrawerOpened : DebugDrawerAction()
/**
* [DebugDrawerAction] fired when the user closes the drawer.
*/
object DrawerClosed : DebugDrawerAction()
}

@ -0,0 +1,32 @@
/* 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 mozilla.components.lib.state.State
/**
* UI state of the debug drawer feature.
*
* @property drawerStatus The [DrawerStatus] indicating the physical state of the drawer.
*/
data class DebugDrawerState(
val drawerStatus: DrawerStatus = DrawerStatus.Closed,
) : State {
/**
* Possible values of [DebugDrawerState.drawerStatus].
*/
enum class DrawerStatus {
/**
* The state of the drawer when it is closed.
*/
Closed,
/**
* The state of the drawer when it is open.
*/
Open,
}
}

@ -0,0 +1,28 @@
/* 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 mozilla.components.lib.state.Middleware
import mozilla.components.lib.state.Store
/**
* A [Store] that holds the [DebugDrawerState] for the Debug Drawer and reduces [DebugDrawerAction]s
* dispatched to the store.
*/
class DebugDrawerStore(
initialState: DebugDrawerState = DebugDrawerState(),
middlewares: List<Middleware<DebugDrawerState, DebugDrawerAction>> = emptyList(),
) : Store<DebugDrawerState, DebugDrawerAction>(
initialState,
::reduce,
middlewares,
)
private fun reduce(state: DebugDrawerState, action: DebugDrawerAction): DebugDrawerState {
return when (action) {
is DebugDrawerAction.DrawerOpened -> state.copy(drawerStatus = DebugDrawerState.DrawerStatus.Open)
is DebugDrawerAction.DrawerClosed -> state.copy(drawerStatus = DebugDrawerState.DrawerStatus.Closed)
}
}

@ -17,9 +17,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@ -29,24 +27,34 @@ import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
import mozilla.components.lib.state.ext.observeAsState
import org.mozilla.fenix.R
import org.mozilla.fenix.compose.annotation.LightDarkPreview
import org.mozilla.fenix.compose.button.FloatingActionButton
import org.mozilla.fenix.debugsettings.store.DebugDrawerAction
import org.mozilla.fenix.debugsettings.store.DebugDrawerState
import org.mozilla.fenix.debugsettings.store.DebugDrawerState.DrawerStatus
import org.mozilla.fenix.debugsettings.store.DebugDrawerStore
import org.mozilla.fenix.theme.FirefoxTheme
/**
* Overlay for presenting Fenix-wide debugging content.
*
* @param debugDrawerStore [DebugDrawerStore] used to listen for changes to [DebugDrawerState] and
* dispatch any [DebugDrawerAction]s.
*/
@Composable
fun DebugOverlay() {
fun DebugOverlay(
debugDrawerStore: DebugDrawerStore,
) {
val drawerStatus by debugDrawerStore.observeAsState(initialValue = DrawerStatus.Closed) { state ->
state.drawerStatus
}
val snackbarState = remember { SnackbarHostState() }
// The separate boolean in conjunction with `drawerState` is to allow the drawer animations
// to still occur even with the show/hide logic documented below.
val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
var drawerEnabled by remember { mutableStateOf(false) }
LaunchedEffect(drawerEnabled) {
if (drawerEnabled) {
LaunchedEffect(drawerStatus) {
if (drawerStatus == DrawerStatus.Open) {
drawerState.open()
}
}
@ -56,7 +64,7 @@ fun DebugOverlay() {
.distinctUntilChanged()
.filter { it == DrawerValue.Closed }
.collect {
drawerEnabled = false
debugDrawerStore.dispatch(DebugDrawerAction.DrawerClosed)
}
}
@ -69,14 +77,14 @@ fun DebugOverlay() {
.align(Alignment.CenterStart)
.padding(start = 16.dp),
onClick = {
drawerEnabled = true
debugDrawerStore.dispatch(DebugDrawerAction.DrawerOpened)
},
)
// ModalDrawer utilizes a Surface, which blocks ALL clicks behind it, preventing the app
// from being interactable. This cannot be overridden in the Surface API, so we must hide
// the entire drawer when it is closed.
if (drawerEnabled) {
if (drawerStatus == DrawerStatus.Open) {
val currentLayoutDirection = LocalLayoutDirection.current
val sheetLayoutDirection = when (currentLayoutDirection) {
LayoutDirection.Rtl -> LayoutDirection.Ltr
@ -116,8 +124,8 @@ fun DebugOverlay() {
@LightDarkPreview
private fun DebugOverlayPreview() {
FirefoxTheme {
Box(modifier = Modifier.fillMaxSize()) {
DebugOverlay()
}
DebugOverlay(
debugDrawerStore = DebugDrawerStore(),
)
}
}

@ -0,0 +1,41 @@
package org.mozilla.fenix.debugsettings
import mozilla.components.support.test.ext.joinBlocking
import org.junit.Assert.assertEquals
import org.junit.Test
import org.mozilla.fenix.debugsettings.store.DebugDrawerAction
import org.mozilla.fenix.debugsettings.store.DebugDrawerState
import org.mozilla.fenix.debugsettings.store.DebugDrawerStore
class DebugDrawerStoreTest {
@Test
fun `GIVEN the drawer is closed WHEN the drawer is opened THEN the state should be set to open`() {
val expected = DebugDrawerState.DrawerStatus.Open
val store = createStore()
store.dispatch(DebugDrawerAction.DrawerOpened).joinBlocking()
assertEquals(expected, store.state.drawerStatus)
}
@Test
fun `GIVEN the drawer is opened WHEN the drawer is closed THEN the state should be set to closed`() {
val expected = DebugDrawerState.DrawerStatus.Closed
val store = createStore(
drawerStatus = DebugDrawerState.DrawerStatus.Open,
)
store.dispatch(DebugDrawerAction.DrawerClosed).joinBlocking()
assertEquals(expected, store.state.drawerStatus)
}
private fun createStore(
drawerStatus: DebugDrawerState.DrawerStatus = DebugDrawerState.DrawerStatus.Closed,
) = DebugDrawerStore(
initialState = DebugDrawerState(
drawerStatus = drawerStatus,
),
)
}
Loading…
Cancel
Save