From fa5a3b49cabdf296c905d88a2da096c6c2d954d7 Mon Sep 17 00:00:00 2001 From: Messias Junior Date: Thu, 22 Oct 2026 13:16:40 +0100 Subject: [PATCH 1/3] disable swipe when task is completed --- .../core/ui/component/task/FoliaryTaskCard.kt | 81 ++++++++++++++----- 1 file changed, 59 insertions(+), 22 deletions(-) diff --git a/foliary/src/commonMain/kotlin/dev/appoutlet/foliary/core/ui/component/task/FoliaryTaskCard.kt b/foliary/src/commonMain/kotlin/dev/appoutlet/foliary/core/ui/component/task/FoliaryTaskCard.kt index d01e363..0dc3c8b 100644 --- a/foliary/src/commonMain/kotlin/dev/appoutlet/foliary/core/ui/component/task/FoliaryTaskCard.kt +++ b/foliary/src/commonMain/kotlin/dev/appoutlet/foliary/core/ui/component/task/FoliaryTaskCard.kt @@ -8,9 +8,14 @@ import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.SwipeToDismissBox +import androidx.compose.material3.SwipeToDismissBoxValue import androidx.compose.material3.Text +import androidx.compose.material3.rememberSwipeToDismissBoxState import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.testTag @@ -39,31 +44,63 @@ fun FoliaryTaskCard( }, ) - FoliaryCard( - modifier = modifier.fillMaxWidth(), - colors = FoliaryCardDefaults.colors(containerColor = cardContainerColor.value), - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .clickable(enabled = onClick != null) { onClick?.invoke() } - .padding(16.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(12.dp), - ) { - FoliaryCheckbox( - checked = task.isCompleted, - onCheckedChange = onCompletedChange, - modifier = Modifier.testTag("FoliaryTaskCard:Checkbox"), - ) + val swipeToDismissBoxState = rememberSwipeToDismissBoxState() - FoliaryTaskCardContent( - task = task, - onPillClick = onPillClick, - modifier = Modifier.weight(1f), - ) + LaunchedEffect(swipeToDismissBoxState.currentValue) { + when (swipeToDismissBoxState.currentValue) { + SwipeToDismissBoxValue.EndToStart -> { + onCompletedChange(true) + swipeToDismissBoxState.reset() + } + + else -> swipeToDismissBoxState.reset() } } + + SwipeToDismissBox( + modifier = Modifier.fillMaxWidth(), + state = swipeToDismissBoxState, + backgroundContent = { + FoliaryCard( + colors = FoliaryCardDefaults.colors(contentColor = MaterialTheme.colorScheme.errorContainer) + ) { + FoliaryTaskCardContent( + task = task, + onPillClick = onPillClick, + modifier = Modifier.weight(1f), + ) + } + }, + enableDismissFromStartToEnd = false, + enableDismissFromEndToStart = task.isCompleted.not(), + content = { + FoliaryCard( + modifier = modifier.fillMaxWidth(), + colors = FoliaryCardDefaults.colors(containerColor = cardContainerColor.value), + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .clickable(enabled = onClick != null) { onClick?.invoke() } + .padding(16.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(12.dp), + ) { + FoliaryCheckbox( + checked = task.isCompleted, + onCheckedChange = onCompletedChange, + modifier = Modifier.testTag("FoliaryTaskCard:Checkbox"), + ) + + FoliaryTaskCardContent( + task = task, + onPillClick = onPillClick, + modifier = Modifier.weight(1f), + ) + } + } + }, + ) } @Composable From aba5b5e25409dd769fcfaffacfc5d4468d00da07 Mon Sep 17 00:00:00 2001 From: Messias Junior Date: Thu, 22 Oct 2026 13:30:13 +0100 Subject: [PATCH 2/3] simplify swap --- .../core/ui/component/task/FoliaryTaskCard.kt | 91 +++++++++---------- 1 file changed, 44 insertions(+), 47 deletions(-) diff --git a/foliary/src/commonMain/kotlin/dev/appoutlet/foliary/core/ui/component/task/FoliaryTaskCard.kt b/foliary/src/commonMain/kotlin/dev/appoutlet/foliary/core/ui/component/task/FoliaryTaskCard.kt index 076f16d..007ee75 100644 --- a/foliary/src/commonMain/kotlin/dev/appoutlet/foliary/core/ui/component/task/FoliaryTaskCard.kt +++ b/foliary/src/commonMain/kotlin/dev/appoutlet/foliary/core/ui/component/task/FoliaryTaskCard.kt @@ -6,15 +6,14 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.material3.MaterialTheme import androidx.compose.material3.SwipeToDismissBox -import androidx.compose.material3.SwipeToDismissBoxValue import androidx.compose.material3.Text import androidx.compose.material3.rememberSwipeToDismissBoxState import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.testTag @@ -43,62 +42,60 @@ fun FoliaryTaskCard( }, ) - val swipeToDismissBoxState = rememberSwipeToDismissBoxState() + FoliarySwipeToDismiss( + modifier = modifier, + isTaskComplete = task.isCompleted, + onCompletedChange = onCompletedChange + ) { + FoliaryCard( + modifier = Modifier.fillMaxWidth(), + colors = FoliaryCardDefaults.colors(containerColor = cardContainerColor.value), + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .clickable(enabled = onClick != null) { onClick?.invoke() } + .padding(16.dp), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(12.dp), + ) { + FoliaryCheckbox( + checked = task.isCompleted, + onCheckedChange = onCompletedChange, + modifier = Modifier.testTag("FoliaryTaskCard:Checkbox"), + ) - LaunchedEffect(swipeToDismissBoxState.currentValue) { - when (swipeToDismissBoxState.currentValue) { - SwipeToDismissBoxValue.EndToStart -> { - onCompletedChange(true) - swipeToDismissBoxState.reset() + FoliaryTaskCardContent( + task = task, + onPillClick = onPillClick, + modifier = Modifier.weight(1f), + ) } - - else -> swipeToDismissBoxState.reset() } } +} + +@Composable +private fun FoliarySwipeToDismiss( + isTaskComplete: Boolean, + onCompletedChange: (Boolean) -> Unit, + modifier: Modifier = Modifier, + content: @Composable RowScope.() -> Unit +) { + val swipeToDismissBoxState = rememberSwipeToDismissBoxState() SwipeToDismissBox( - modifier = Modifier.fillMaxWidth(), + modifier = modifier.fillMaxWidth(), state = swipeToDismissBoxState, backgroundContent = { - FoliaryCard( - colors = FoliaryCardDefaults.colors(contentColor = MaterialTheme.colorScheme.errorContainer) - ) { - FoliaryTaskCardContent( - task = task, - onPillClick = onPillClick, - modifier = Modifier.weight(1f), - ) - } + }, enableDismissFromStartToEnd = false, - enableDismissFromEndToStart = task.isCompleted.not(), - content = { - FoliaryCard( - modifier = modifier.fillMaxWidth(), - colors = FoliaryCardDefaults.colors(containerColor = cardContainerColor.value), - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .clickable(enabled = onClick != null) { onClick?.invoke() } - .padding(16.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.spacedBy(12.dp), - ) { - FoliaryCheckbox( - checked = task.isCompleted, - onCheckedChange = onCompletedChange, - modifier = Modifier.testTag("FoliaryTaskCard:Checkbox"), - ) - - FoliaryTaskCardContent( - task = task, - onPillClick = onPillClick, - modifier = Modifier.weight(1f), - ) - } - } + enableDismissFromEndToStart = isTaskComplete.not(), + onDismiss = { + onCompletedChange(true) }, + content = content, ) } From 7da5b27e0b63c9a3fe40b00ba5c6aec3fd784fb8 Mon Sep 17 00:00:00 2001 From: Messias Junior Date: Thu, 22 Oct 2026 13:44:12 +0100 Subject: [PATCH 3/3] swipe bacground --- .../core/ui/component/card/FoliaryCard.kt | 21 ++++++++++---- .../core/ui/component/task/FoliaryTaskCard.kt | 28 ++++++++++++++++++- .../appoutlet/foliary/core/ui/theme/Color.kt | 4 +-- 3 files changed, 45 insertions(+), 8 deletions(-) diff --git a/foliary/src/commonMain/kotlin/dev/appoutlet/foliary/core/ui/component/card/FoliaryCard.kt b/foliary/src/commonMain/kotlin/dev/appoutlet/foliary/core/ui/component/card/FoliaryCard.kt index 2c70ebe..466aca0 100644 --- a/foliary/src/commonMain/kotlin/dev/appoutlet/foliary/core/ui/component/card/FoliaryCard.kt +++ b/foliary/src/commonMain/kotlin/dev/appoutlet/foliary/core/ui/component/card/FoliaryCard.kt @@ -3,25 +3,28 @@ package dev.appoutlet.foliary.core.ui.component.card import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.layout.ColumnScope import androidx.compose.material3.Card -import androidx.compose.material3.CardColors import androidx.compose.material3.CardDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp +import dev.appoutlet.foliary.core.ui.component.modifier.FoliaryShadowColorDefault import dev.appoutlet.foliary.core.ui.component.modifier.foliaryShadow @Composable fun FoliaryCard( modifier: Modifier = Modifier, - colors: CardColors = FoliaryCardDefaults.colors(), + colors: FoliaryCardColors = FoliaryCardDefaults.colors(), content: @Composable ColumnScope.() -> Unit ) { Card( - modifier = modifier.foliaryShadow(), + modifier = modifier.foliaryShadow(color = colors.shadowColor), shape = MaterialTheme.shapes.extraLarge, - colors = colors, + colors = CardDefaults.cardColors( + containerColor = colors.containerColor, + contentColor = colors.contentColor, + ), border = BorderStroke(1.dp, MaterialTheme.colorScheme.outline), elevation = CardDefaults.cardElevation(defaultElevation = 0.dp), content = content @@ -34,8 +37,16 @@ object FoliaryCardDefaults { fun colors( containerColor: Color = MaterialTheme.colorScheme.surface, contentColor: Color = MaterialTheme.colorScheme.onSurface, - ): CardColors = CardDefaults.cardColors( + shadowColor: Color = FoliaryShadowColorDefault + ) = FoliaryCardColors( containerColor = containerColor, contentColor = contentColor, + shadowColor = shadowColor, ) } + +data class FoliaryCardColors( + val containerColor: Color, + val contentColor: Color, + val shadowColor: Color, +) diff --git a/foliary/src/commonMain/kotlin/dev/appoutlet/foliary/core/ui/component/task/FoliaryTaskCard.kt b/foliary/src/commonMain/kotlin/dev/appoutlet/foliary/core/ui/component/task/FoliaryTaskCard.kt index 007ee75..d7a06af 100644 --- a/foliary/src/commonMain/kotlin/dev/appoutlet/foliary/core/ui/component/task/FoliaryTaskCard.kt +++ b/foliary/src/commonMain/kotlin/dev/appoutlet/foliary/core/ui/component/task/FoliaryTaskCard.kt @@ -3,12 +3,15 @@ package dev.appoutlet.foliary.core.ui.component.task import androidx.compose.animation.animateColorAsState import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.RowScope +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.SwipeToDismissBox import androidx.compose.material3.Text @@ -16,10 +19,13 @@ import androidx.compose.material3.rememberSwipeToDismissBoxState import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.testTag import androidx.compose.ui.text.style.TextDecoration import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp +import com.composables.icons.lucide.CircleCheckBig +import com.composables.icons.lucide.Lucide import dev.appoutlet.foliary.core.ui.component.card.FoliaryCard import dev.appoutlet.foliary.core.ui.component.card.FoliaryCardDefaults import dev.appoutlet.foliary.core.ui.component.checkbox.FoliaryCheckbox @@ -88,7 +94,7 @@ private fun FoliarySwipeToDismiss( modifier = modifier.fillMaxWidth(), state = swipeToDismissBoxState, backgroundContent = { - + BackgroundContent() }, enableDismissFromStartToEnd = false, enableDismissFromEndToStart = isTaskComplete.not(), @@ -99,6 +105,26 @@ private fun FoliarySwipeToDismiss( ) } +@Composable +private fun BackgroundContent() { + FoliaryCard( + modifier = Modifier.fillMaxSize(), + colors = FoliaryCardDefaults.colors( + containerColor = MaterialTheme.colorScheme.primaryContainer, + contentColor = MaterialTheme.colorScheme.onPrimaryContainer, + shadowColor = Color.Transparent + ), + ) { + Box(modifier = Modifier.fillMaxSize().padding(16.dp)) { + Icon( + modifier = Modifier.align(Alignment.CenterEnd), + imageVector = Lucide.CircleCheckBig, + contentDescription = null + ) + } + } +} + @Composable private fun FoliaryTaskCardContent( task: FoliaryTaskCardViewData, diff --git a/foliary/src/commonMain/kotlin/dev/appoutlet/foliary/core/ui/theme/Color.kt b/foliary/src/commonMain/kotlin/dev/appoutlet/foliary/core/ui/theme/Color.kt index 243438d..6573a42 100644 --- a/foliary/src/commonMain/kotlin/dev/appoutlet/foliary/core/ui/theme/Color.kt +++ b/foliary/src/commonMain/kotlin/dev/appoutlet/foliary/core/ui/theme/Color.kt @@ -5,7 +5,7 @@ import androidx.compose.ui.graphics.Color val primaryLight = Color(0xFF1A4D3E) val onPrimaryLight = Color(0xFFFFFFFF) val primaryContainerLight = Color(0xFF1B4D3E) -val onPrimaryContainerLight = Color(0xFF8ABDA9) +val onPrimaryContainerLight = Color(0xFFBBE3D4) val secondaryLight = Color(0xFFe9f3ee) val onSecondaryLight = Color(0xFFFFFFFF) val secondaryContainerLight = Color(0xFFE9F3EE) @@ -41,7 +41,7 @@ val surfaceContainerHighestLight = Color(0xFFE5E2E1) val primaryDark = Color(0xFF00E796) val onPrimaryDark = Color(0xFF00382A) val primaryContainerDark = Color(0xFF1D5643) -val onPrimaryContainerDark = Color(0xFFB9E6D3) +val onPrimaryContainerDark = Color(0xFFD0EADD) val secondaryDark = Color(0xFF16504f) val onSecondaryDark = Color(0xFFF4FFFB) val secondaryContainerDark = Color(0xFF35473C)