diff --git a/shared/src/commonMain/kotlin/nl/tiebe/otarium/ui/home/elo/children/assignments/AssignmentsChildComponent.kt b/shared/src/commonMain/kotlin/nl/tiebe/otarium/ui/home/elo/children/assignments/AssignmentsChildComponent.kt index 5e8cdb52..4d52fa60 100644 --- a/shared/src/commonMain/kotlin/nl/tiebe/otarium/ui/home/elo/children/assignments/AssignmentsChildComponent.kt +++ b/shared/src/commonMain/kotlin/nl/tiebe/otarium/ui/home/elo/children/assignments/AssignmentsChildComponent.kt @@ -7,6 +7,7 @@ import com.arkivanov.decompose.router.stack.childStack import com.arkivanov.decompose.router.stack.push import com.arkivanov.decompose.value.MutableValue import com.arkivanov.decompose.value.Value +import com.arkivanov.essenty.backhandler.BackCallback import com.arkivanov.essenty.parcelable.Parcelable import com.arkivanov.essenty.parcelable.Parcelize import kotlinx.coroutines.CoroutineScope @@ -40,6 +41,12 @@ interface AssignmentsChildComponent : ELOChildComponent { @Parcelize data class Assignment(val assignmentLink: String) : Config() } + + + val onBack: MutableValue<() -> Unit> + + fun registerBackHandler() + fun unregisterBackHandler() } class DefaultAssignmentsChildComponent(componentContext: ComponentContext) : AssignmentsChildComponent, ComponentContext by componentContext { @@ -76,6 +83,33 @@ class DefaultAssignmentsChildComponent(componentContext: ComponentContext) : Ass componentContext = componentContext, assignmentLink = assignmentLink, ) + + private val registered = MutableValue(false) + private val backCallback = BackCallback { onBack.value() } + override val onBack: MutableValue<() -> Unit> = MutableValue {} + + override fun registerBackHandler() { + if (registered.value) return + backHandler.register(backCallback) + registered.value = true + } + + override fun unregisterBackHandler() { + if (!registered.value) return + backHandler.unregister(backCallback) + registered.value = false + } + + + init { + childStack.subscribe { childStack -> + if (childStack.backStack.isEmpty()) { + unregisterBackHandler() + } else { + registerBackHandler() + } + } + } } interface AssignmentChildScreen \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/nl/tiebe/otarium/ui/home/elo/children/assignments/AssignmentsChildScreen.kt b/shared/src/commonMain/kotlin/nl/tiebe/otarium/ui/home/elo/children/assignments/AssignmentsChildScreen.kt index c01c33a3..9d199727 100644 --- a/shared/src/commonMain/kotlin/nl/tiebe/otarium/ui/home/elo/children/assignments/AssignmentsChildScreen.kt +++ b/shared/src/commonMain/kotlin/nl/tiebe/otarium/ui/home/elo/children/assignments/AssignmentsChildScreen.kt @@ -1,23 +1,71 @@ package nl.tiebe.otarium.ui.home.elo.children.assignments import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding +import androidx.compose.material.DismissDirection +import androidx.compose.material.DismissValue +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.SwipeToDismiss +import androidx.compose.material.rememberDismissState +import androidx.compose.material3.Surface import androidx.compose.runtime.Composable +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.arkivanov.decompose.extensions.compose.jetbrains.subscribeAsState +import com.arkivanov.decompose.router.stack.pop +import kotlinx.coroutines.launch import nl.tiebe.otarium.ui.home.elo.children.assignments.assignment.AssignmentScreen import nl.tiebe.otarium.ui.home.elo.children.assignments.listscreen.AssignmentListScreen +@OptIn(ExperimentalMaterialApi::class) @Composable internal fun AssignmentsChildScreen(component: AssignmentsChildComponent) { - val child = component.childStack.subscribeAsState().value + val screen = component.childStack.subscribeAsState() + val scope = rememberCoroutineScope() Box(modifier = Modifier.padding(start = 5.dp, end = 5.dp)) { - when (val screen = child.active.instance) { - is AssignmentsChildComponent.Child.Assignment -> AssignmentScreen(screen.component) - is AssignmentsChildComponent.Child.AssignmentList -> AssignmentListScreen(screen.component) + when (val child = screen.value.items[0].instance) { + is AssignmentsChildComponent.Child.Assignment -> AssignmentScreen(child.component) + is AssignmentsChildComponent.Child.AssignmentList -> AssignmentListScreen(child.component) } + + + for (item in screen.value.items.subList(1, screen.value.items.size)) { + val state = rememberDismissState() + + component.onBack.value = { + scope.launch { + state.animateTo(DismissValue.DismissedToEnd) + } + } + + //pop on finish + if (state.isDismissed(DismissDirection.StartToEnd)) { + component.navigation.pop() + } + + SwipeToDismiss( + state = state, + background = { + }, + directions = setOf(DismissDirection.StartToEnd) + ) { + Surface(Modifier.fillMaxSize()) { + when (val child = item.instance) { + is AssignmentsChildComponent.Child.Assignment -> AssignmentScreen(child.component) + is AssignmentsChildComponent.Child.AssignmentList -> AssignmentListScreen(child.component) + } + } + } + } + } + + + + Box(modifier = Modifier.padding(start = 5.dp, end = 5.dp)) { + } } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/nl/tiebe/otarium/ui/home/elo/children/studyguides/StudyGuidesChildComponent.kt b/shared/src/commonMain/kotlin/nl/tiebe/otarium/ui/home/elo/children/studyguides/StudyGuidesChildComponent.kt index 25f8b850..66ef6685 100644 --- a/shared/src/commonMain/kotlin/nl/tiebe/otarium/ui/home/elo/children/studyguides/StudyGuidesChildComponent.kt +++ b/shared/src/commonMain/kotlin/nl/tiebe/otarium/ui/home/elo/children/studyguides/StudyGuidesChildComponent.kt @@ -7,6 +7,7 @@ import com.arkivanov.decompose.router.stack.childStack import com.arkivanov.decompose.router.stack.push import com.arkivanov.decompose.value.MutableValue import com.arkivanov.decompose.value.Value +import com.arkivanov.essenty.backhandler.BackCallback import com.arkivanov.essenty.parcelable.Parcelable import com.arkivanov.essenty.parcelable.Parcelize import dev.tiebe.magisterapi.response.studyguide.StudyGuide @@ -44,6 +45,12 @@ interface StudyGuidesChildComponent : ELOChildComponent { data class StudyGuide(val studyGuideLink: String) : Config() } + + val onBack: MutableValue<() -> Unit> + + fun registerBackHandler() + fun unregisterBackHandler() + } class DefaultStudyGuidesChildComponent(componentContext: ComponentContext) : StudyGuidesChildComponent, ComponentContext by componentContext { @@ -81,6 +88,33 @@ class DefaultStudyGuidesChildComponent(componentContext: ComponentContext) : Stu componentContext = componentContext, studyGuideLink = studyGuideLink, ) + + private val registered = MutableValue(false) + private val backCallback = BackCallback { onBack.value() } + override val onBack: MutableValue<() -> Unit> = MutableValue {} + + override fun registerBackHandler() { + if (registered.value) return + backHandler.register(backCallback) + registered.value = true + } + + override fun unregisterBackHandler() { + if (!registered.value) return + backHandler.unregister(backCallback) + registered.value = false + } + + + init { + childStack.subscribe { childStack -> + if (childStack.backStack.isEmpty()) { + unregisterBackHandler() + } else { + registerBackHandler() + } + } + } } interface StudyGuideChildScreen \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/nl/tiebe/otarium/ui/home/elo/children/studyguides/StudyGuidesChildScreen.kt b/shared/src/commonMain/kotlin/nl/tiebe/otarium/ui/home/elo/children/studyguides/StudyGuidesChildScreen.kt index 1256b763..4345625e 100644 --- a/shared/src/commonMain/kotlin/nl/tiebe/otarium/ui/home/elo/children/studyguides/StudyGuidesChildScreen.kt +++ b/shared/src/commonMain/kotlin/nl/tiebe/otarium/ui/home/elo/children/studyguides/StudyGuidesChildScreen.kt @@ -2,22 +2,58 @@ package nl.tiebe.otarium.ui.home.elo.children.studyguides import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.padding +import androidx.compose.material.DismissDirection +import androidx.compose.material.DismissValue import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.SwipeToDismiss +import androidx.compose.material.rememberDismissState import androidx.compose.runtime.Composable +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.arkivanov.decompose.extensions.compose.jetbrains.subscribeAsState +import com.arkivanov.decompose.router.stack.pop +import kotlinx.coroutines.launch import nl.tiebe.otarium.ui.home.elo.children.studyguides.folder.StudyGuideFolderScreen import nl.tiebe.otarium.ui.home.elo.children.studyguides.listscreen.StudyGuideListScreen +@OptIn(ExperimentalMaterialApi::class) @Composable internal fun StudyGuidesChildScreen(component: StudyGuidesChildComponent) { - val child = component.childStack.subscribeAsState().value + val screen = component.childStack.subscribeAsState() + val scope = rememberCoroutineScope() Box(modifier = Modifier.padding(start = 5.dp, end = 5.dp)) { - when (val screen = child.active.instance) { - is StudyGuidesChildComponent.Child.StudyGuideListChild -> StudyGuideListScreen(screen.component) - is StudyGuidesChildComponent.Child.FolderChild -> StudyGuideFolderScreen(screen.component) + when (val child = screen.value.items[0].instance) { + is StudyGuidesChildComponent.Child.StudyGuideListChild -> StudyGuideListScreen(child.component) + is StudyGuidesChildComponent.Child.FolderChild -> StudyGuideFolderScreen(child.component) + } + + for (item in screen.value.items.subList(1, screen.value.items.size)) { + val state = rememberDismissState() + + component.onBack.value = { + scope.launch { + state.animateTo(DismissValue.DismissedToEnd) + } + } + + //pop on finish + if (state.isDismissed(DismissDirection.StartToEnd)) { + component.navigation.pop() + } + + SwipeToDismiss( + state = state, + background = { + }, + directions = setOf(DismissDirection.StartToEnd) + ) { + when (val child = item.instance) { + is StudyGuidesChildComponent.Child.StudyGuideListChild -> StudyGuideListScreen(child.component) + is StudyGuidesChildComponent.Child.FolderChild -> StudyGuideFolderScreen(child.component) + } + } } } } \ No newline at end of file diff --git a/shared/src/commonMain/kotlin/nl/tiebe/otarium/ui/home/settings/SettingsComponent.kt b/shared/src/commonMain/kotlin/nl/tiebe/otarium/ui/home/settings/SettingsComponent.kt index 6f40baef..27c4cc90 100644 --- a/shared/src/commonMain/kotlin/nl/tiebe/otarium/ui/home/settings/SettingsComponent.kt +++ b/shared/src/commonMain/kotlin/nl/tiebe/otarium/ui/home/settings/SettingsComponent.kt @@ -34,7 +34,6 @@ interface SettingsComponent: MenuItemComponent { val navigateRootComponent: (RootComponent.ChildScreen) -> Unit - val onBack: MutableValue<() -> Unit> fun navigate(child: Config) { navigation.push(child) @@ -73,6 +72,8 @@ interface SettingsComponent: MenuItemComponent { object Colors : Config(getLocalizedString(MR.strings.color_settings)) } + val onBack: MutableValue<() -> Unit> + fun registerBackHandler() fun unregisterBackHandler() }