Skip to content

Commit 17e0510

Browse files
Merge pull request #468 from JoseAlcerreca/owl_multiple_nav_fix
[Owl] Fixes multiple navigation calls with simultaneous taps
2 parents 405b447 + adbf5e5 commit 17e0510

File tree

2 files changed

+54
-14
lines changed

2 files changed

+54
-14
lines changed

Owl/app/src/main/java/com/example/owl/ui/NavGraph.kt

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import androidx.compose.runtime.Composable
2121
import androidx.compose.runtime.mutableStateOf
2222
import androidx.compose.runtime.remember
2323
import androidx.compose.ui.Modifier
24+
import androidx.lifecycle.Lifecycle
25+
import androidx.navigation.NavBackStackEntry
2426
import androidx.navigation.NavHostController
2527
import androidx.navigation.NavType
2628
import androidx.navigation.compose.NavHost
@@ -83,7 +85,7 @@ fun NavGraph(
8385
startDestination = CourseTabs.FEATURED.route
8486
) {
8587
courses(
86-
onCourseSelected = actions.selectCourse,
88+
onCourseSelected = actions.openCourse,
8789
onboardingComplete = onboardingComplete,
8890
navController = navController,
8991
modifier = modifier
@@ -94,12 +96,15 @@ fun NavGraph(
9496
arguments = listOf(
9597
navArgument(COURSE_DETAIL_ID_KEY) { type = NavType.LongType }
9698
)
97-
) { backStackEntry ->
99+
) { backStackEntry: NavBackStackEntry ->
98100
val arguments = requireNotNull(backStackEntry.arguments)
101+
val currentCourseId = arguments.getLong(COURSE_DETAIL_ID_KEY)
99102
CourseDetails(
100-
courseId = arguments.getLong(COURSE_DETAIL_ID_KEY),
101-
selectCourse = actions.selectCourse,
102-
upPress = actions.upPress
103+
courseId = currentCourseId,
104+
selectCourse = { newCourseId ->
105+
actions.relatedCourse(newCourseId, backStackEntry)
106+
},
107+
upPress = { actions.upPress(backStackEntry) }
103108
)
104109
}
105110
}
@@ -112,10 +117,36 @@ class MainActions(navController: NavHostController) {
112117
val onboardingComplete: () -> Unit = {
113118
navController.popBackStack()
114119
}
115-
val selectCourse: (Long) -> Unit = { courseId: Long ->
116-
navController.navigate("${MainDestinations.COURSE_DETAIL_ROUTE}/$courseId")
120+
121+
// Used from COURSES_ROUTE
122+
val openCourse = { newCourseId: Long, from: NavBackStackEntry ->
123+
// In order to discard duplicated navigation events, we check the Lifecycle
124+
if (from.lifecycleIsResumed()) {
125+
navController.navigate("${MainDestinations.COURSE_DETAIL_ROUTE}/$newCourseId")
126+
}
117127
}
118-
val upPress: () -> Unit = {
119-
navController.navigateUp()
128+
129+
// Used from COURSE_DETAIL_ROUTE
130+
val relatedCourse = { newCourseId: Long, from: NavBackStackEntry ->
131+
// In order to discard duplicated navigation events, we check the Lifecycle
132+
if (from.lifecycleIsResumed()) {
133+
navController.navigate("${MainDestinations.COURSE_DETAIL_ROUTE}/$newCourseId")
134+
}
135+
}
136+
137+
// Used from COURSE_DETAIL_ROUTE
138+
val upPress: (rom: NavBackStackEntry) -> Unit = { from ->
139+
// In order to discard duplicated navigation events, we check the Lifecycle
140+
if (from.lifecycleIsResumed()) {
141+
navController.navigateUp()
142+
}
120143
}
121144
}
145+
146+
/**
147+
* If the lifecycle is not resumed it means this NavBackStackEntry already processed a nav event.
148+
*
149+
* This is used to de-duplicate navigation events.
150+
*/
151+
private fun NavBackStackEntry.lifecycleIsResumed() =
152+
this.lifecycle.currentState == Lifecycle.State.RESUMED

Owl/app/src/main/java/com/example/owl/ui/courses/Courses.kt

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import androidx.compose.ui.Modifier
3434
import androidx.compose.ui.res.painterResource
3535
import androidx.compose.ui.res.stringResource
3636
import androidx.compose.ui.unit.dp
37+
import androidx.navigation.NavBackStackEntry
3738
import androidx.navigation.NavGraphBuilder
3839
import androidx.navigation.NavHostController
3940
import androidx.navigation.compose.composable
@@ -44,24 +45,32 @@ import com.example.owl.model.topics
4445
import com.example.owl.ui.MainDestinations
4546

4647
fun NavGraphBuilder.courses(
47-
onCourseSelected: (Long) -> Unit,
48+
onCourseSelected: (Long, NavBackStackEntry) -> Unit,
4849
onboardingComplete: State<Boolean>, // https://issuetracker.google.com/174783110
4950
navController: NavHostController,
5051
modifier: Modifier = Modifier
5152
) {
52-
composable(CourseTabs.FEATURED.route) {
53+
composable(CourseTabs.FEATURED.route) { from ->
5354
// Show onboarding instead if not shown yet.
5455
LaunchedEffect(onboardingComplete) {
5556
if (!onboardingComplete.value) {
5657
navController.navigate(MainDestinations.ONBOARDING_ROUTE)
5758
}
5859
}
5960
if (onboardingComplete.value) { // Avoid glitch when showing onboarding
60-
FeaturedCourses(courses, onCourseSelected, modifier)
61+
FeaturedCourses(
62+
courses = courses,
63+
selectCourse = { id -> onCourseSelected(id, from) },
64+
modifier = modifier
65+
)
6166
}
6267
}
63-
composable(CourseTabs.MY_COURSES.route) {
64-
MyCourses(courses, onCourseSelected, modifier)
68+
composable(CourseTabs.MY_COURSES.route) { from ->
69+
MyCourses(
70+
courses = courses,
71+
{ id -> onCourseSelected(id, from) },
72+
modifier
73+
)
6574
}
6675
composable(CourseTabs.SEARCH.route) {
6776
SearchCourses(topics, modifier)

0 commit comments

Comments
 (0)