From c9bd899c1f5ca4b30f6d9bdf07c2babe4429b52b Mon Sep 17 00:00:00 2001 From: Diego Beraldin Date: Sat, 23 Dec 2023 12:26:38 +0100 Subject: [PATCH] enhancement: back to home; closes #345 (#358) --- androidApp/build.gradle.kts | 2 ++ .../raccoonforlemmy/android/MainActivity.kt | 15 +++++++++-- .../DefaultNavigationCoordinator.kt | 25 ++++++++++++++----- .../core/navigation/NavigationCoordinator.kt | 5 ++++ .../raccoonforlemmy/MainScreen.kt | 8 +++++- 5 files changed, 46 insertions(+), 9 deletions(-) diff --git a/androidApp/build.gradle.kts b/androidApp/build.gradle.kts index cab032a89..edccad3ab 100644 --- a/androidApp/build.gradle.kts +++ b/androidApp/build.gradle.kts @@ -68,6 +68,8 @@ dependencies { implementation(libs.koin.android) implementation(libs.coil) implementation(libs.coil.gif) + implementation(libs.voyager.navigator) + implementation(libs.voyager.tab) implementation(projects.shared) implementation(projects.core.utils) diff --git a/androidApp/src/main/java/com/github/diegoberaldin/raccoonforlemmy/android/MainActivity.kt b/androidApp/src/main/java/com/github/diegoberaldin/raccoonforlemmy/android/MainActivity.kt index deb697a19..d278bd71a 100644 --- a/androidApp/src/main/java/com/github/diegoberaldin/raccoonforlemmy/android/MainActivity.kt +++ b/androidApp/src/main/java/com/github/diegoberaldin/raccoonforlemmy/android/MainActivity.kt @@ -8,7 +8,9 @@ import androidx.activity.compose.setContent import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen import androidx.lifecycle.lifecycleScope import com.github.diegoberaldin.raccoonforlemmy.MainView +import com.github.diegoberaldin.raccoonforlemmy.core.navigation.TabNavigationSection import com.github.diegoberaldin.raccoonforlemmy.core.navigation.di.getNavigationCoordinator +import com.github.diegoberaldin.raccoonforlemmy.feature.home.ui.HomeTab import kotlinx.coroutines.delay import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -27,8 +29,17 @@ class MainActivity : ComponentActivity() { val navigationCoordinator = getNavigationCoordinator() val backPressedCallback = object : OnBackPressedCallback(true) { override fun handleOnBackPressed() { - if (!navigationCoordinator.exitMessageVisible.value) { - navigationCoordinator.setExitMessageVisible(true) + if (navigationCoordinator.currentSection.value == TabNavigationSection.Home) { + // asks for confirmation + if (!navigationCoordinator.exitMessageVisible.value) { + navigationCoordinator.setExitMessageVisible(true) + } + } else { + // goes back to home + with(navigationCoordinator) { + changeTab(HomeTab) + setCurrentSection(TabNavigationSection.Home) + } } } } diff --git a/core/navigation/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/navigation/DefaultNavigationCoordinator.kt b/core/navigation/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/navigation/DefaultNavigationCoordinator.kt index d1b99b2f0..f5383b234 100644 --- a/core/navigation/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/navigation/DefaultNavigationCoordinator.kt +++ b/core/navigation/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/navigation/DefaultNavigationCoordinator.kt @@ -4,6 +4,8 @@ import androidx.compose.ui.input.nestedscroll.NestedScrollConnection import cafe.adriel.voyager.core.screen.Screen import cafe.adriel.voyager.navigator.Navigator import cafe.adriel.voyager.navigator.bottomSheet.BottomSheetNavigator +import cafe.adriel.voyager.navigator.tab.Tab +import cafe.adriel.voyager.navigator.tab.TabNavigator import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.SupervisorJob @@ -13,6 +15,7 @@ import kotlinx.coroutines.ensureActive import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.debounce +import kotlinx.coroutines.flow.getAndUpdate import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.receiveAsFlow @@ -28,6 +31,7 @@ private sealed interface NavigationEvent { @OptIn(FlowPreview::class) internal class DefaultNavigationCoordinator : NavigationCoordinator { + override val currentSection = MutableStateFlow(null) override val onDoubleTabSelection = MutableSharedFlow() override val deepLinkUrl = MutableSharedFlow() override val inboxUnread = MutableStateFlow(0) @@ -38,7 +42,7 @@ internal class DefaultNavigationCoordinator : NavigationCoordinator { private var connection: NestedScrollConnection? = null private var navigator: Navigator? = null private var bottomNavigator: BottomSheetNavigator? = null - private var currentTab: TabNavigationSection? = null + private var tabNavigator: TabNavigator? = null private val scope = CoroutineScope(SupervisorJob()) private var canGoBackCallback: (() -> Boolean)? = null private val bottomSheetChannel = Channel() @@ -93,12 +97,13 @@ internal class DefaultNavigationCoordinator : NavigationCoordinator { override fun getBottomBarScrollConnection() = connection override fun setCurrentSection(section: TabNavigationSection) { - val oldTab = currentTab - currentTab = section - if (section == oldTab) { - scope.launch { - onDoubleTabSelection.emit(section) + currentSection.getAndUpdate { oldValue -> + if (section == oldValue) { + scope.launch { + onDoubleTabSelection.emit(section) + } } + section } } @@ -157,4 +162,12 @@ internal class DefaultNavigationCoordinator : NavigationCoordinator { override fun setBottomSheetGesturesEnabled(value: Boolean) { bottomSheetGesturesEnabled.value = value } + + override fun setTabNavigator(value: TabNavigator) { + tabNavigator = value + } + + override fun changeTab(value: Tab) { + tabNavigator?.current = value + } } \ No newline at end of file diff --git a/core/navigation/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/navigation/NavigationCoordinator.kt b/core/navigation/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/navigation/NavigationCoordinator.kt index 71c4d4bec..61403faef 100644 --- a/core/navigation/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/navigation/NavigationCoordinator.kt +++ b/core/navigation/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/navigation/NavigationCoordinator.kt @@ -5,6 +5,8 @@ import androidx.compose.ui.input.nestedscroll.NestedScrollConnection import cafe.adriel.voyager.core.screen.Screen import cafe.adriel.voyager.navigator.Navigator import cafe.adriel.voyager.navigator.bottomSheet.BottomSheetNavigator +import cafe.adriel.voyager.navigator.tab.Tab +import cafe.adriel.voyager.navigator.tab.TabNavigator import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.StateFlow @@ -19,6 +21,7 @@ sealed interface TabNavigationSection { @Stable interface NavigationCoordinator { + val currentSection: StateFlow val onDoubleTabSelection: Flow val inboxUnread: StateFlow val deepLinkUrl: Flow @@ -41,4 +44,6 @@ interface NavigationCoordinator { fun popScreen() fun setExitMessageVisible(value: Boolean) fun setBottomSheetGesturesEnabled(value: Boolean) + fun setTabNavigator(value: TabNavigator) + fun changeTab(value: Tab) } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/MainScreen.kt b/shared/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/MainScreen.kt index 8298ed09b..fa409a9da 100644 --- a/shared/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/MainScreen.kt +++ b/shared/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/MainScreen.kt @@ -110,10 +110,13 @@ internal object MainScreen : Screen { } TabNavigator(HomeTab) { tabNavigator -> + navigationCoordinator.setTabNavigator(tabNavigator) + LaunchedEffect(tabNavigator.current) { // when the current tab chanes, reset the bottom bar offset to the default value model.reduce(MainScreenMviModel.Intent.SetBottomBarOffsetHeightPx(0f)) } + LaunchedEffect(drawerCoordinator) { drawerCoordinator.events.onEach { evt -> when (evt) { @@ -121,7 +124,10 @@ internal object MainScreen : Screen { if (tabNavigator.current == HomeTab) { notificationCenter.send(NotificationCenterEvent.ChangeFeedType(evt.value)) } else { - tabNavigator.current = HomeTab + with(navigationCoordinator) { + changeTab(HomeTab) + setCurrentSection(TabNavigationSection.Home) + } launch { // wait for transition to finish delay(750)