11package com.woocommerce.android.ui.bookings.filter
22
33import androidx.activity.compose.BackHandler
4- import androidx.compose.animation.AnimatedContent
5- import androidx.compose.animation.ContentTransform
4+ import androidx.compose.animation.EnterTransition
5+ import androidx.compose.animation.ExitTransition
66import androidx.compose.animation.core.tween
77import androidx.compose.animation.fadeIn
88import androidx.compose.animation.fadeOut
99import androidx.compose.animation.slideInHorizontally
1010import androidx.compose.animation.slideOutHorizontally
11- import androidx.compose.animation.togetherWith
1211import androidx.compose.foundation.background
1312import androidx.compose.foundation.layout.Column
1413import androidx.compose.foundation.layout.fillMaxSize
@@ -19,11 +18,15 @@ import androidx.compose.material3.MaterialTheme
1918import androidx.compose.material3.Scaffold
2019import androidx.compose.material3.Text
2120import androidx.compose.runtime.Composable
21+ import androidx.compose.runtime.LaunchedEffect
2222import androidx.compose.ui.Modifier
2323import androidx.compose.ui.graphics.vector.ImageVector
2424import androidx.compose.ui.res.stringResource
2525import androidx.compose.ui.res.vectorResource
2626import androidx.compose.ui.unit.dp
27+ import androidx.navigation.compose.NavHost
28+ import androidx.navigation.compose.composable
29+ import androidx.navigation.compose.rememberNavController
2730import com.woocommerce.android.R
2831import com.woocommerce.android.ui.compose.component.Toolbar
2932import com.woocommerce.android.ui.compose.component.WCColoredButton
@@ -32,10 +35,6 @@ import com.woocommerce.android.ui.compose.theme.WooThemeWithBackground
3235
3336@Composable
3437fun BookingFilterListScreen (state : BookingFilterListUiState ) {
35- BackHandler {
36- state.onClose()
37- }
38-
3938 Scaffold (
4039 topBar = {
4140 Column {
@@ -66,62 +65,94 @@ fun BookingFilterListScreen(state: BookingFilterListUiState) {
6665 },
6766 containerColor = MaterialTheme .colorScheme.surface,
6867 ) { innerPadding ->
69- AnimatedContent (
70- targetState = state.currentPage,
71- transitionSpec = {
72- if (targetState is BookingFilterPage .List ) {
73- slideOut()
74- } else {
75- slideIn()
76- }
77- },
78- label = " BookingFiltersAnimatedContent" ,
68+ FiltersNavHost (
69+ state = state,
7970 modifier = Modifier
8071 .fillMaxSize()
8172 .padding(innerPadding)
82- ) { page ->
83- when (page) {
84- is BookingFilterPage .List -> {
85- BookingFilterRootPage (state.items)
86- }
73+ )
8774
88- BookingFilterPage .AttendanceStatus ,
89- BookingFilterPage .BookingType ,
90- BookingFilterPage .Customer ,
91- BookingFilterPage .Location ,
92- BookingFilterPage .PaymentStatus ,
93- BookingFilterPage .ServiceEvent ,
94- BookingFilterPage .TeamMember ,
95- is BookingFilterPage .DateTime -> {
96- DateTimeFilterPicker ()
97- }
75+ // The navigation is driven by the state, so we handle back navigation by calling onClose
76+ // We need to ensure that this called after NavHost to make sure we receive back events
77+ BackHandler {
78+ state.onClose()
79+ }
80+ }
81+ }
82+
83+ @Composable
84+ private fun FiltersNavHost (
85+ state : BookingFilterListUiState ,
86+ modifier : Modifier
87+ ) {
88+ val navController = rememberNavController()
89+
90+ LaunchedEffect (state.currentPage) {
91+ if (state.currentPage != BookingFilterPage .List ) {
92+ navController.navigate(state.currentPage.route) {
93+ popUpTo(BookingFilterPage .List .route)
9894 }
95+ } else {
96+ navController.popBackStack(BookingFilterPage .List .route, false )
97+ }
98+ }
99+
100+ NavHost (
101+ navController = navController,
102+ startDestination = BookingFilterPage .List .route,
103+ enterTransition = { slideIn(popNavigation = true ) },
104+ exitTransition = { slideOut(popNavigation = true ) },
105+ popEnterTransition = { slideIn(popNavigation = false ) },
106+ popExitTransition = { slideOut(popNavigation = false ) },
107+ modifier = modifier
108+ ) {
109+ composable(BookingFilterPage .List .route) {
110+ BookingFilterRootPage (state.items)
111+ }
112+ composable(BookingFilterPage .DateTime .route) {
113+ DateTimeFilterPicker ()
114+ }
115+ composable(BookingFilterPage .TeamMember .route) {
116+ TODO ()
117+ }
118+ composable(BookingFilterPage .AttendanceStatus .route) {
119+ TODO ()
120+ }
121+ composable(BookingFilterPage .PaymentStatus .route) {
122+ TODO ()
123+ }
124+ composable(BookingFilterPage .BookingType .route) {
125+ TODO ()
126+ }
127+ composable(BookingFilterPage .Customer .route) {
128+ TODO ()
129+ }
130+ composable(BookingFilterPage .ServiceEvent .route) {
131+ TODO ()
132+ }
133+ composable(BookingFilterPage .Location .route) {
134+ TODO ()
99135 }
100136 }
101137}
102138
103- private const val TRANSITION_DURATION = 250
139+ private val BookingFilterPage .route: String
140+ get() = name
104141
105- private fun slideIn (duration : Int = TRANSITION_DURATION ): ContentTransform {
106- return (
107- slideInHorizontally(animationSpec = tween(durationMillis = duration)) { fullWidth -> fullWidth } +
108- fadeIn(animationSpec = tween(durationMillis = duration))
109- ) togetherWith (
110- slideOutHorizontally(animationSpec = tween(durationMillis = duration)) { fullWidth -> - fullWidth } +
111- fadeOut(animationSpec = tween(durationMillis = duration))
112- )
142+ private fun slideIn (popNavigation : Boolean ): EnterTransition {
143+ return slideInHorizontally(animationSpec = tween(durationMillis = TRANSITION_DURATION )) { fullWidth ->
144+ if (popNavigation) fullWidth else - fullWidth
145+ } + fadeIn(animationSpec = tween(durationMillis = TRANSITION_DURATION ))
113146}
114147
115- private fun slideOut (duration : Int = TRANSITION_DURATION ): ContentTransform {
116- return (
117- slideInHorizontally(animationSpec = tween(durationMillis = duration)) { fullWidth -> - fullWidth } +
118- fadeIn(animationSpec = tween(durationMillis = duration))
119- ) togetherWith (
120- slideOutHorizontally(animationSpec = tween(durationMillis = duration)) { fullWidth -> fullWidth } +
121- fadeOut(animationSpec = tween(durationMillis = duration))
122- )
148+ private fun slideOut (popNavigation : Boolean ): ExitTransition {
149+ return slideOutHorizontally(animationSpec = tween(durationMillis = TRANSITION_DURATION )) { fullWidth ->
150+ if (popNavigation) - fullWidth else fullWidth
151+ } + fadeOut(animationSpec = tween(durationMillis = TRANSITION_DURATION ))
123152}
124153
154+ private const val TRANSITION_DURATION = 250
155+
125156@LightDarkThemePreviews
126157@Composable
127158private fun BookingFilterListScreenPreview () {
0 commit comments