diff --git a/app/src/main/java/de/jeanlucmakiola/calendula/ui/common/EventDrag.kt b/app/src/main/java/de/jeanlucmakiola/calendula/ui/common/EventDrag.kt index c1746b4..5b786f9 100644 --- a/app/src/main/java/de/jeanlucmakiola/calendula/ui/common/EventDrag.kt +++ b/app/src/main/java/de/jeanlucmakiola/calendula/ui/common/EventDrag.kt @@ -212,11 +212,21 @@ private fun rememberPickUpSurface( } } -/** A lift on pickup, then a tick every time the drop target snaps to a new slot. */ +/** + * A lift on pickup, a tick every time the drop target snaps to a new slot, and a + * confirm each time [drops] counts a real drop. + */ @Composable -fun DragSnapHaptics(slot: Any?) { +fun DragSnapHaptics(slot: Any?, drops: Int) { val haptics = LocalHapticFeedback.current val previous = remember { arrayOfNulls(1) } + val dropsSeen = remember { intArrayOf(drops) } + LaunchedEffect(drops) { + if (drops != dropsSeen[0]) { + dropsSeen[0] = drops + haptics.performHapticFeedback(HapticFeedbackType.Confirm) + } + } LaunchedEffect(slot) { val had = previous[0] previous[0] = slot diff --git a/app/src/main/java/de/jeanlucmakiola/calendula/ui/common/TimelineDrag.kt b/app/src/main/java/de/jeanlucmakiola/calendula/ui/common/TimelineDrag.kt index e4377bd..045d14f 100644 --- a/app/src/main/java/de/jeanlucmakiola/calendula/ui/common/TimelineDrag.kt +++ b/app/src/main/java/de/jeanlucmakiola/calendula/ui/common/TimelineDrag.kt @@ -21,6 +21,7 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateListOf +import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue @@ -467,6 +468,10 @@ class TimelineDragController { var settling: TimelineDrag? by mutableStateOf(null) private set + /** How many real drops this controller has handed back. */ + var drops by mutableIntStateOf(0) + private set + /** * Which block is lifted, and whether anything is. Separate snapshot state * from [drag], which changes every frame, so blocks that only need "am I the @@ -770,6 +775,7 @@ class TimelineDragController { liftedInstanceId = landed.event.instanceId settledOrigin = landed.event.eventId to landed.event.start settledAbandonedMark = abandonedTicks?.value ?: 0 + drops++ return TimelineDrop(landed.event, landed.date, landed.startMin, clipOffset) } @@ -826,6 +832,7 @@ class TimelineDragController { settledOrigin = landed.event.eventId to landed.event.start settledAbandonedMark = abandonedTicks?.value ?: 0 settledEnd = drop.end + drops++ return drop } @@ -1160,7 +1167,7 @@ fun TimelineDragOverlay(controller: TimelineDragController, modifier: Modifier = // Both live here rather than beside the controller: they read [drag], which // changes every frame, and this composable is the one that is meant to. - DragSnapHaptics(controller.drag?.slot) + DragSnapHaptics(controller.drag?.slot, controller.drops) // Only once the finger has moved: a long press held near an edge must not // scroll the drop target out from under a finger that only means to select. LaunchedEffect(controller.isDragging && controller.pointerMoved) { diff --git a/app/src/main/java/de/jeanlucmakiola/calendula/ui/month/MonthDrag.kt b/app/src/main/java/de/jeanlucmakiola/calendula/ui/month/MonthDrag.kt index 746dad4..9e7df88 100644 --- a/app/src/main/java/de/jeanlucmakiola/calendula/ui/month/MonthDrag.kt +++ b/app/src/main/java/de/jeanlucmakiola/calendula/ui/month/MonthDrag.kt @@ -4,6 +4,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.Stable import androidx.compose.runtime.compositionLocalOf import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue @@ -133,6 +134,10 @@ class MonthDragController { var settling: MonthChipDrag? by mutableStateOf(null) private set + /** How many real drops this controller has handed back. */ + var drops by mutableIntStateOf(0) + private set + /** * Which chip is lifted, and whether anything is. Separate snapshot state from * [drag], which changes every frame, so the chips and rows that only need @@ -291,6 +296,7 @@ class MonthDragController { settledGhost = true undoable = settling settledAbandonedMark = abandonedTicks?.value ?: 0 + drops++ return MonthChipDrop(landed.event, landed.grabDate, target) } diff --git a/app/src/main/java/de/jeanlucmakiola/calendula/ui/month/MonthScreen.kt b/app/src/main/java/de/jeanlucmakiola/calendula/ui/month/MonthScreen.kt index 2e778c2..27ec981 100644 --- a/app/src/main/java/de/jeanlucmakiola/calendula/ui/month/MonthScreen.kt +++ b/app/src/main/java/de/jeanlucmakiola/calendula/ui/month/MonthScreen.kt @@ -596,7 +596,7 @@ private fun MonthDragOverlay(controller: MonthDragController) { val moveInFlight = moveInFlight() // Here rather than beside the controller: this reads [drag], which changes // every frame, and this composable is the one that is meant to. - DragSnapHaptics(controller.drag?.targetDate) + DragSnapHaptics(controller.drag?.targetDate, controller.drops) // Hold the landed chip until the write is done — including the time a // recurring drop's scope dialog is up — and then, unlike the timeline, carry // it to its seat: it was dropped at whatever height the finger was at, while @@ -1463,8 +1463,14 @@ private fun SplitMonthContent( showWeekNumbers = showWeekNumbers, expandDrag = expandDrag, onSelectDay = onSelectDay, - onPaneSwipeNext = onPaneSwipeNext, - onPaneSwipePrev = onPaneSwipePrev, + onPaneSwipeNext = { + onPaneSwipeNext() + haptics.performHapticFeedback(HapticFeedbackType.SegmentTick) + }, + onPaneSwipePrev = { + onPaneSwipePrev() + haptics.performHapticFeedback(HapticFeedbackType.SegmentTick) + }, onClearSelection = onClearSelection, onOpenDay = onOpenDay, onEventClick = onEventClick, diff --git a/app/src/main/java/de/jeanlucmakiola/calendula/ui/week/WeekScreen.kt b/app/src/main/java/de/jeanlucmakiola/calendula/ui/week/WeekScreen.kt index 85d3799..03873c1 100644 --- a/app/src/main/java/de/jeanlucmakiola/calendula/ui/week/WeekScreen.kt +++ b/app/src/main/java/de/jeanlucmakiola/calendula/ui/week/WeekScreen.kt @@ -587,7 +587,8 @@ private fun WeekContent( dragController.select(resized) return@resize } - dragController.select(resized, moved = true) + // Still lifted under its copy, so it takes over without the ghost's fade-in dip. + dragController.select(resized, moved = true, fromLift = true) move?.move( MoveRequest( eventId = drop.event.eventId,