Skip to content

Commit 501dbce

Browse files
Merge pull request #14859 from woocommerce/issue/WOOMOB-1608-bookings-filters-compose-nav
[CIAB Bookings] Update filter screen navigation to use Compose Navigation
2 parents 022c591 + 6474dc8 commit 501dbce

File tree

2 files changed

+91
-60
lines changed

2 files changed

+91
-60
lines changed

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListScreen.kt

Lines changed: 80 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
package com.woocommerce.android.ui.bookings.filter
22

33
import 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
66
import androidx.compose.animation.core.tween
77
import androidx.compose.animation.fadeIn
88
import androidx.compose.animation.fadeOut
99
import androidx.compose.animation.slideInHorizontally
1010
import androidx.compose.animation.slideOutHorizontally
11-
import androidx.compose.animation.togetherWith
1211
import androidx.compose.foundation.background
1312
import androidx.compose.foundation.layout.Column
1413
import androidx.compose.foundation.layout.fillMaxSize
@@ -19,11 +18,15 @@ import androidx.compose.material3.MaterialTheme
1918
import androidx.compose.material3.Scaffold
2019
import androidx.compose.material3.Text
2120
import androidx.compose.runtime.Composable
21+
import androidx.compose.runtime.LaunchedEffect
2222
import androidx.compose.ui.Modifier
2323
import androidx.compose.ui.graphics.vector.ImageVector
2424
import androidx.compose.ui.res.stringResource
2525
import androidx.compose.ui.res.vectorResource
2626
import androidx.compose.ui.unit.dp
27+
import androidx.navigation.compose.NavHost
28+
import androidx.navigation.compose.composable
29+
import androidx.navigation.compose.rememberNavController
2730
import com.woocommerce.android.R
2831
import com.woocommerce.android.ui.compose.component.Toolbar
2932
import com.woocommerce.android.ui.compose.component.WCColoredButton
@@ -32,10 +35,6 @@ import com.woocommerce.android.ui.compose.theme.WooThemeWithBackground
3235

3336
@Composable
3437
fun 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
127158
private fun BookingFilterListScreenPreview() {

WooCommerce/src/main/kotlin/com/woocommerce/android/ui/bookings/filter/BookingFilterListUiState.kt

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@ import com.woocommerce.android.R
66
import org.wordpress.android.fluxc.network.rest.wpcom.wc.bookings.BookingFilters
77
import org.wordpress.android.fluxc.network.rest.wpcom.wc.bookings.BookingsFilterOption
88

9-
sealed interface BookingFilterPage {
10-
data object List : BookingFilterPage
11-
data object DateTime : BookingFilterPage
12-
data object TeamMember : BookingFilterPage
13-
data object AttendanceStatus : BookingFilterPage
14-
data object PaymentStatus : BookingFilterPage
15-
data object BookingType : BookingFilterPage
16-
data object Customer : BookingFilterPage
17-
data object ServiceEvent : BookingFilterPage
18-
data object Location : BookingFilterPage
9+
enum class BookingFilterPage {
10+
List,
11+
DateTime,
12+
TeamMember,
13+
AttendanceStatus,
14+
PaymentStatus,
15+
BookingType,
16+
Customer,
17+
ServiceEvent,
18+
Location,
1919
}
2020

2121
data class BookingFilterListUiState(
@@ -37,7 +37,7 @@ data class BookingFilterListUiState(
3737

3838
@DrawableRes
3939
val navigationIcon: Int = when (currentPage) {
40-
is BookingFilterPage.List -> R.drawable.ic_gridicons_cross_24dp
40+
BookingFilterPage.List -> R.drawable.ic_gridicons_cross_24dp
4141
else -> R.drawable.ic_back_24dp
4242
}
4343

0 commit comments

Comments
 (0)