Skip to content

Commit

Permalink
ELO remove Swipe to Dismiss
Browse files Browse the repository at this point in the history
Closes #63
  • Loading branch information
Tiebe committed Aug 3, 2024
1 parent a0c976f commit de8f1d6
Show file tree
Hide file tree
Showing 16 changed files with 149 additions and 197 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@ import com.arkivanov.decompose.ComponentContext
import com.arkivanov.decompose.router.stack.ChildStack
import com.arkivanov.decompose.router.stack.StackNavigation
import com.arkivanov.decompose.router.stack.childStack
import com.arkivanov.decompose.router.stack.pop
import com.arkivanov.decompose.value.MutableValue
import com.arkivanov.decompose.value.Value
import com.arkivanov.essenty.backhandler.BackCallback
import com.arkivanov.essenty.backhandler.BackHandlerOwner
import kotlinx.coroutines.CoroutineScope
import nl.tiebe.otarium.logic.default.componentCoroutineScope
import nl.tiebe.otarium.logic.default.home.children.elo.children.assignments.children.assignment.DefaultAssignmentScreenComponent
import nl.tiebe.otarium.logic.default.home.children.elo.children.assignments.children.list.DefaultAssignmentListComponent
import nl.tiebe.otarium.logic.root.home.children.elo.children.assignments.AssignmentsChildComponent

class DefaultAssignmentsChildComponent(componentContext: ComponentContext) : AssignmentsChildComponent, ComponentContext by componentContext {
class DefaultAssignmentsChildComponent(componentContext: ComponentContext) : AssignmentsChildComponent, ComponentContext by componentContext, BackHandlerOwner {
override val refreshState: MutableValue<Boolean> = MutableValue(false)

override val scope: CoroutineScope = componentCoroutineScope()
Expand Down Expand Up @@ -57,30 +58,7 @@ class DefaultAssignmentsChildComponent(componentContext: ComponentContext) : Ass
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.observe { childStack ->
if (childStack.backStack.isEmpty()) {
unregisterBackHandler()
} else {
registerBackHandler()
}
}
override fun back() {
navigation.pop()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,18 @@ import com.arkivanov.decompose.ComponentContext
import com.arkivanov.decompose.router.stack.ChildStack
import com.arkivanov.decompose.router.stack.StackNavigation
import com.arkivanov.decompose.router.stack.childStack
import com.arkivanov.decompose.router.stack.pop
import com.arkivanov.decompose.value.MutableValue
import com.arkivanov.decompose.value.Value
import com.arkivanov.essenty.backhandler.BackCallback
import com.arkivanov.essenty.backhandler.BackHandlerOwner
import dev.tiebe.magisterapi.response.studyguide.StudyGuide
import kotlinx.coroutines.CoroutineScope
import nl.tiebe.otarium.logic.default.componentCoroutineScope
import nl.tiebe.otarium.logic.default.home.children.elo.children.studyguides.children.folder.DefaultStudyGuideFolderComponent
import nl.tiebe.otarium.logic.default.home.children.elo.children.studyguides.children.list.DefaultStudyGuideListComponent
import nl.tiebe.otarium.logic.root.home.children.elo.children.studyguides.StudyGuidesChildComponent

class DefaultStudyGuidesChildComponent(componentContext: ComponentContext) : StudyGuidesChildComponent, ComponentContext by componentContext {
class DefaultStudyGuidesChildComponent(componentContext: ComponentContext) : StudyGuidesChildComponent, ComponentContext by componentContext, BackHandlerOwner {
override val refreshState: MutableValue<Boolean> = MutableValue(false)

override val scope: CoroutineScope = componentCoroutineScope()
Expand Down Expand Up @@ -55,31 +56,8 @@ class DefaultStudyGuidesChildComponent(componentContext: ComponentContext) : Stu
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.observe { childStack ->
if (childStack.backStack.isEmpty()) {
unregisterBackHandler()
} else {
registerBackHandler()
}
}
override fun back() {
navigation.pop()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,23 @@ package nl.tiebe.otarium.logic.root.home.children.elo.children.assignments
import com.arkivanov.decompose.router.stack.ChildStack
import com.arkivanov.decompose.router.stack.StackNavigation
import com.arkivanov.decompose.router.stack.push
import com.arkivanov.decompose.value.MutableValue
import com.arkivanov.decompose.value.Value
import com.arkivanov.essenty.backhandler.BackHandlerOwner
import kotlinx.coroutines.CoroutineScope
import kotlinx.serialization.Serializable
import nl.tiebe.otarium.logic.root.home.children.elo.ELOComponent
import nl.tiebe.otarium.logic.root.home.children.elo.children.assignments.children.assignment.AssignmentScreenComponent
import nl.tiebe.otarium.logic.root.home.children.elo.children.assignments.children.list.AssignmentListComponent

interface AssignmentsChildComponent : ELOComponent.ELOChildComponent {
interface AssignmentsChildComponent : ELOComponent.ELOChildComponent, BackHandlerOwner {
val navigation: StackNavigation<Config>
val childStack: Value<ChildStack<Config, Child>>

val refreshState: Value<Boolean>
val scope: CoroutineScope

fun back()

fun navigate(child: Config) {
navigation.push(child)
}
Expand All @@ -35,11 +37,5 @@ interface AssignmentsChildComponent : ELOComponent.ELOChildComponent {
data class Assignment(val assignmentLink: String) : Config()
}


val onBack: MutableValue<() -> Unit>

fun registerBackHandler()
fun unregisterBackHandler()

interface AssignmentChildScreen
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,24 @@ package nl.tiebe.otarium.logic.root.home.children.elo.children.studyguides
import com.arkivanov.decompose.router.stack.ChildStack
import com.arkivanov.decompose.router.stack.StackNavigation
import com.arkivanov.decompose.router.stack.push
import com.arkivanov.decompose.value.MutableValue
import com.arkivanov.decompose.value.Value
import com.arkivanov.essenty.backhandler.BackHandlerOwner
import dev.tiebe.magisterapi.response.studyguide.StudyGuide
import kotlinx.coroutines.CoroutineScope
import kotlinx.serialization.Serializable
import nl.tiebe.otarium.logic.root.home.children.elo.ELOComponent
import nl.tiebe.otarium.logic.root.home.children.elo.children.studyguides.children.folder.StudyGuideFolderComponent
import nl.tiebe.otarium.logic.root.home.children.elo.children.studyguides.children.list.StudyGuideListComponent

interface StudyGuidesChildComponent : ELOComponent.ELOChildComponent {
interface StudyGuidesChildComponent : ELOComponent.ELOChildComponent, BackHandlerOwner {
val navigation: StackNavigation<Config>
val childStack: Value<ChildStack<Config, Child>>

val refreshState: Value<Boolean>
val scope: CoroutineScope

fun back()

fun navigate(child: Config) {
navigation.push(child)
}
Expand All @@ -39,12 +41,5 @@ interface StudyGuidesChildComponent : ELOComponent.ELOChildComponent {
data class StudyGuide(val studyGuideLink: String) : Config()
}


val onBack: MutableValue<() -> Unit>

fun registerBackHandler()
fun unregisterBackHandler()


interface StudyGuideChildScreen
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ import kotlinx.coroutines.launch
import nl.tiebe.otarium.MR
import nl.tiebe.otarium.logic.root.home.children.elo.ELOComponent
import nl.tiebe.otarium.ui.home.elo.children.assignments.AssignmentsChildScreen
import nl.tiebe.otarium.ui.home.elo.children.assignments.AssignmentsTopBar
import nl.tiebe.otarium.ui.home.elo.children.learningresources.LearningResourcesChildScreen
import nl.tiebe.otarium.ui.home.elo.children.studyguides.StudyGuidesChildScreen
import nl.tiebe.otarium.ui.home.elo.children.studyguides.StudyGuidesTopBar
import nl.tiebe.otarium.utils.ui.getLocalizedString

@OptIn(ExperimentalFoundationApi::class)
Expand All @@ -37,6 +39,11 @@ internal fun ELOScreen(component: ELOComponent) {
val coroutineScope = rememberCoroutineScope()

Column(modifier = Modifier.fillMaxSize()) {
when (pagerState.currentPage) {
0 -> StudyGuidesTopBar(component.studyGuidesComponent)
1 -> AssignmentsTopBar(component.assignmentsComponent)
}

TabRow(
selectedTabIndex = pagerState.currentPage
) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,72 +1,59 @@
package nl.tiebe.otarium.ui.home.elo.children.assignments

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.WindowInsets
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.ExperimentalMaterial3Api
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
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.ExperimentalDecomposeApi
import com.arkivanov.decompose.extensions.compose.jetbrains.stack.Children
import com.arkivanov.decompose.extensions.compose.jetbrains.stack.animation.fade
import com.arkivanov.decompose.extensions.compose.jetbrains.stack.animation.plus
import com.arkivanov.decompose.extensions.compose.jetbrains.stack.animation.predictiveback.predictiveBackAnimation
import com.arkivanov.decompose.extensions.compose.jetbrains.stack.animation.scale
import com.arkivanov.decompose.extensions.compose.jetbrains.stack.animation.stackAnimation
import com.arkivanov.decompose.extensions.compose.jetbrains.subscribeAsState
import com.arkivanov.decompose.router.stack.pop
import nl.tiebe.otarium.MR
import nl.tiebe.otarium.logic.root.home.children.elo.children.assignments.AssignmentsChildComponent
import nl.tiebe.otarium.ui.home.elo.children.assignments.assignment.AssignmentScreen
import nl.tiebe.otarium.ui.home.elo.children.assignments.assignment.AssignmentScreenTopAppBar
import nl.tiebe.otarium.ui.home.elo.children.assignments.listscreen.AssignmentListScreen
import kotlinx.coroutines.launch
import nl.tiebe.otarium.utils.ui.getLocalizedString

@OptIn(ExperimentalMaterialApi::class)
@OptIn(ExperimentalMaterial3Api::class)
@Composable
internal fun AssignmentsChildScreen(component: AssignmentsChildComponent) {
val screen = component.childStack.subscribeAsState()
val scope = rememberCoroutineScope()

Box(modifier = Modifier.padding(start = 5.dp, end = 5.dp)) {
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)
}
}
fun AssignmentsTopBar(component: AssignmentsChildComponent) {
when (val instance = component.childStack.subscribeAsState().value.active.instance) {
is AssignmentsChildComponent.Child.AssignmentList -> TopAppBar(title = { Text(getLocalizedString(MR.strings.assignments)) }, windowInsets = WindowInsets(0))
is AssignmentsChildComponent.Child.Assignment -> AssignmentScreenTopAppBar(instance.component, component)
}
}

//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)
}
@OptIn(ExperimentalDecomposeApi::class)
@Composable
internal fun AssignmentsChildScreen(component: AssignmentsChildComponent) {
Box(modifier = Modifier.padding(start = 5.dp, end = 5.dp)) {
Children(
component.childStack.subscribeAsState().value,
animation = predictiveBackAnimation(
backHandler = component.backHandler,
animation = stackAnimation(fade() + scale()), // Your usual animation here
onBack = component::back,
)
) { child ->
Surface(Modifier.fillMaxSize()) {
when (val instance = child.instance) {
is AssignmentsChildComponent.Child.Assignment -> AssignmentScreen(instance.component)
is AssignmentsChildComponent.Child.AssignmentList -> AssignmentListScreen(instance.component)
}
}
}
}



Box(modifier = Modifier.padding(start = 5.dp, end = 5.dp)) {

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,39 @@ import androidx.compose.foundation.pager.PageSize
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.pullrefresh.PullRefreshIndicator
import androidx.compose.material.pullrefresh.pullRefresh
import androidx.compose.material.pullrefresh.rememberPullRefreshState
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.text.capitalize
import androidx.compose.ui.text.intl.Locale
import androidx.compose.ui.unit.dp
import com.arkivanov.decompose.extensions.compose.jetbrains.subscribeAsState
import nl.tiebe.otarium.logic.root.home.children.elo.children.assignments.AssignmentsChildComponent
import nl.tiebe.otarium.logic.root.home.children.elo.children.assignments.children.assignment.AssignmentScreenComponent
import kotlin.math.absoluteValue

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun AssignmentScreenTopAppBar(component: AssignmentScreenComponent, parent: AssignmentsChildComponent) {
TopAppBar(
title = { Text(component.assignment.subscribeAsState().value.title.capitalize(Locale.current)) },
navigationIcon = {
IconButton(onClick = { parent.back() }) {
Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Back")
}
},
windowInsets = WindowInsets(0)
)
}

@OptIn(ExperimentalMaterialApi::class, ExperimentalFoundationApi::class)
@Composable
internal fun AssignmentScreen(component: AssignmentScreenComponent) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.pullrefresh.PullRefreshIndicator
import androidx.compose.material.pullrefresh.pullRefresh
import androidx.compose.material.pullrefresh.rememberPullRefreshState
import androidx.compose.material3.Divider
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.ListItem
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
Expand All @@ -36,7 +36,7 @@ internal fun LearningResourcesChildScreen(component: LearningResourcesChildCompo
modifier = Modifier.clickable { component.openLearningResource(it) }
)

Divider()
HorizontalDivider()
}
}

Expand Down
Loading

0 comments on commit de8f1d6

Please sign in to comment.