@@ -5,11 +5,6 @@ import androidx.compose.animation.fadeIn
55import androidx.compose.animation.fadeOut
66import androidx.compose.animation.togetherWith
77import androidx.compose.foundation.background
8- import androidx.compose.foundation.gestures.AnchoredDraggableState
9- import androidx.compose.foundation.gestures.DraggableAnchors
10- import androidx.compose.foundation.gestures.Orientation
11- import androidx.compose.foundation.gestures.anchoredDraggable
12- import androidx.compose.foundation.gestures.snapTo
138import androidx.compose.foundation.layout.Arrangement
149import androidx.compose.foundation.layout.Box
1510import androidx.compose.foundation.layout.BoxScope
@@ -19,15 +14,13 @@ import androidx.compose.foundation.layout.Row
1914import androidx.compose.foundation.layout.fillMaxSize
2015import androidx.compose.foundation.layout.fillMaxWidth
2116import androidx.compose.foundation.layout.height
22- import androidx.compose.foundation.layout.offset
2317import androidx.compose.foundation.layout.padding
2418import androidx.compose.foundation.layout.requiredSize
2519import androidx.compose.foundation.layout.size
2620import androidx.compose.foundation.lazy.LazyColumn
2721import androidx.compose.foundation.lazy.itemsIndexed
2822import androidx.compose.foundation.lazy.rememberLazyListState
2923import androidx.compose.foundation.shape.CircleShape
30- import androidx.compose.foundation.shape.RoundedCornerShape
3124import androidx.compose.material.icons.Icons
3225import androidx.compose.material.icons.filled.GroupAdd
3326import androidx.compose.material3.HorizontalDivider
@@ -36,24 +29,16 @@ import androidx.compose.material3.Text
3629import androidx.compose.runtime.Composable
3730import androidx.compose.runtime.LaunchedEffect
3831import androidx.compose.runtime.getValue
39- import androidx.compose.runtime.mutableFloatStateOf
4032import androidx.compose.runtime.mutableStateOf
4133import androidx.compose.runtime.remember
42- import androidx.compose.runtime.rememberCoroutineScope
43- import androidx.compose.runtime.rememberUpdatedState
4434import androidx.compose.runtime.saveable.rememberSaveable
4535import androidx.compose.runtime.setValue
4636import androidx.compose.ui.Alignment
4737import androidx.compose.ui.Modifier
4838import androidx.compose.ui.draw.clip
49- import androidx.compose.ui.draw.clipToBounds
5039import androidx.compose.ui.graphics.Brush
5140import androidx.compose.ui.graphics.Color
5241import androidx.compose.ui.platform.LocalContext
53- import androidx.compose.ui.platform.LocalDensity
54- import androidx.compose.ui.layout.layout
55- import androidx.compose.ui.layout.onSizeChanged
56- import androidx.compose.ui.unit.IntOffset
5742import androidx.compose.ui.res.painterResource
5843import androidx.compose.ui.res.stringResource
5944import androidx.compose.ui.text.style.TextAlign
@@ -84,14 +69,13 @@ import com.getcode.ui.components.AppBarDefaults
8469import com.getcode.ui.components.AppBarWithTitle
8570import com.getcode.ui.components.CircularIconButton
8671import com.getcode.ui.components.SearchInput
72+ import com.getcode.ui.components.SwipeToRevealItem
8773import com.getcode.ui.core.rememberedClickable
8874import com.getcode.ui.core.verticalScrollStateGradient
8975import com.getcode.ui.theme.CodeCircularProgressIndicator
9076import com.getcode.ui.theme.CodeScaffold
9177import com.getcode.view.LoadingSuccessState
92- import kotlin.math.abs
9378import kotlinx.coroutines.flow.filterIsInstance
94- import kotlinx.coroutines.launch
9579
9680
9781@Composable
@@ -290,101 +274,6 @@ private fun ContactList(
290274 }
291275}
292276
293- private enum class RevealValue { Settled , Revealed , Dismissed }
294-
295- @Composable
296- private fun SwipeToRevealItem (
297- onDelete : () -> Unit ,
298- modifier : Modifier = Modifier ,
299- content : @Composable () -> Unit ,
300- ) {
301- val density = LocalDensity .current
302- val scope = rememberCoroutineScope()
303- val actionWidth = CodeTheme .dimens.staticGrid.x10 + CodeTheme .dimens.inset * 2
304- val actionWidthPx = with (density) { actionWidth.toPx() }
305-
306- val state = remember { AnchoredDraggableState (initialValue = RevealValue .Settled ) }
307- var rowWidthPx by remember { mutableFloatStateOf(0f ) }
308-
309- LaunchedEffect (rowWidthPx, actionWidthPx) {
310- if (rowWidthPx > 0f ) {
311- state.updateAnchors(DraggableAnchors {
312- RevealValue .Settled at 0f
313- RevealValue .Revealed at - actionWidthPx
314- RevealValue .Dismissed at - rowWidthPx
315- })
316- }
317- }
318-
319- val currentOnDelete by rememberUpdatedState(onDelete)
320- LaunchedEffect (state.currentValue) {
321- if (state.currentValue == RevealValue .Dismissed ) {
322- currentOnDelete()
323- }
324- }
325-
326- val actionPadding = CodeTheme .dimens.inset
327- val minActionSize = CodeTheme .dimens.staticGrid.x10
328-
329- Box (
330- modifier = modifier
331- .clipToBounds()
332- .onSizeChanged { rowWidthPx = it.width.toFloat() },
333- ) {
334- // Action area — grows from circle to rounded rect as swipe progresses
335- Box (
336- modifier = Modifier
337- .matchParentSize()
338- .layout { measurable, constraints ->
339- val absOffset = abs(state.offset)
340- val paddingPx = actionPadding.roundToPx()
341- val minPx = minActionSize.roundToPx()
342-
343- val w = (absOffset.toInt() - paddingPx * 2 ).coerceAtLeast(minPx)
344- val h = (constraints.maxHeight - paddingPx * 2 ).coerceAtLeast(minPx)
345-
346- val placeable = measurable.measure(
347- constraints.copy(
348- minWidth = w, maxWidth = w,
349- minHeight = h, maxHeight = h,
350- )
351- )
352- layout(constraints.maxWidth, constraints.maxHeight) {
353- placeable.place(
354- constraints.maxWidth - placeable.width - paddingPx,
355- (constraints.maxHeight - placeable.height) / 2 ,
356- )
357- }
358- }
359- .clip(RoundedCornerShape (50 ))
360- .background(CodeTheme .colors.error)
361- .rememberedClickable {
362- scope.launch {
363- state.snapTo(RevealValue .Settled )
364- }
365- onDelete()
366- },
367- contentAlignment = Alignment .Center ,
368- ) {
369- Icon (
370- painter = painterResource(R .drawable.ic_delete),
371- contentDescription = stringResource(R .string.action_remove),
372- tint = Color .White ,
373- modifier = Modifier .requiredSize(CodeTheme .dimens.staticGrid.x5),
374- )
375- }
376-
377- // Foreground content that slides
378- Box (
379- modifier = Modifier
380- .offset { IntOffset (state.offset.toInt(), 0 ) }
381- .anchoredDraggable(state, Orientation .Horizontal ),
382- ) {
383- content()
384- }
385- }
386- }
387-
388277@Composable
389278private fun ContactGroupHeader (text : String , modifier : Modifier = Modifier ) {
390279 Box (
0 commit comments