Adds haptic feedback to draft deletion swipe
This commit is contained in:
@@ -32,6 +32,7 @@ import androidx.compose.material.icons.Icons
|
|||||||
import androidx.compose.material.icons.filled.Delete
|
import androidx.compose.material.icons.filled.Delete
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.SwipeToDismissBox
|
import androidx.compose.material3.SwipeToDismissBox
|
||||||
import androidx.compose.material3.SwipeToDismissBoxState
|
import androidx.compose.material3.SwipeToDismissBoxState
|
||||||
import androidx.compose.material3.SwipeToDismissBoxValue.EndToStart
|
import androidx.compose.material3.SwipeToDismissBoxValue.EndToStart
|
||||||
@@ -39,10 +40,13 @@ import androidx.compose.material3.SwipeToDismissBoxValue.Settled
|
|||||||
import androidx.compose.material3.SwipeToDismissBoxValue.StartToEnd
|
import androidx.compose.material3.SwipeToDismissBoxValue.StartToEnd
|
||||||
import androidx.compose.material3.rememberSwipeToDismissBoxState
|
import androidx.compose.material3.rememberSwipeToDismissBoxState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
|
||||||
|
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
import com.vitorpamplona.amethyst.ui.stringRes
|
import com.vitorpamplona.amethyst.ui.stringRes
|
||||||
@@ -69,6 +73,7 @@ fun SwipeToDeleteContainer(
|
|||||||
}
|
}
|
||||||
return@rememberSwipeToDismissBoxState true
|
return@rememberSwipeToDismissBoxState true
|
||||||
},
|
},
|
||||||
|
positionalThreshold = { it * .40f },
|
||||||
)
|
)
|
||||||
|
|
||||||
SwipeToDismissBox(
|
SwipeToDismissBox(
|
||||||
@@ -86,11 +91,20 @@ fun DismissBackground(dismissState: SwipeToDismissBoxState) {
|
|||||||
if (dismissState.currentValue > dismissState.targetValue) {
|
if (dismissState.currentValue > dismissState.targetValue) {
|
||||||
Color(0xFFFF1744)
|
Color(0xFFFF1744)
|
||||||
} else {
|
} else {
|
||||||
Color.Transparent
|
MaterialTheme.colorScheme.surfaceVariant
|
||||||
},
|
},
|
||||||
label = "DismissBackground",
|
label = "DismissBackground",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val haptic = LocalHapticFeedback.current
|
||||||
|
LaunchedEffect(key1 = dismissState.currentValue > dismissState.targetValue) {
|
||||||
|
// doesn't run for the first time or when the list is updated.
|
||||||
|
println("AABBCC ${dismissState.progress}")
|
||||||
|
if (dismissState.progress > 0 && dismissState.progress < 1) {
|
||||||
|
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
modifier =
|
modifier =
|
||||||
Modifier
|
Modifier
|
||||||
|
|||||||
+13
-14
@@ -22,7 +22,6 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn
|
|||||||
|
|
||||||
import androidx.compose.animation.animateContentSize
|
import androidx.compose.animation.animateContentSize
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.background
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
@@ -59,6 +58,7 @@ import com.vitorpamplona.amethyst.ui.screen.SaveableFeedState
|
|||||||
import com.vitorpamplona.amethyst.ui.screen.ScrollStateKeys.DRAFTS
|
import com.vitorpamplona.amethyst.ui.screen.ScrollStateKeys.DRAFTS
|
||||||
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
import com.vitorpamplona.amethyst.ui.theme.DividerThickness
|
||||||
import com.vitorpamplona.amethyst.ui.theme.FeedPadding
|
import com.vitorpamplona.amethyst.ui.theme.FeedPadding
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.maxWidthWithBackground
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun DraftListScreen(
|
fun DraftListScreen(
|
||||||
@@ -178,24 +178,23 @@ private fun DraftFeedLoaded(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
itemsIndexed(state.feed.value, key = { _, item -> item.idHex }) { _, item ->
|
itemsIndexed(state.feed.value, key = { _, item -> item.idHex }) { _, item ->
|
||||||
SwipeToDeleteContainer(
|
Row(
|
||||||
modifier =
|
Modifier
|
||||||
Modifier
|
.fillMaxWidth()
|
||||||
.fillMaxWidth()
|
.animateItemPlacement(),
|
||||||
.animateContentSize(),
|
|
||||||
onStartToEnd = { accountViewModel.delete(item) },
|
|
||||||
onEndToStart = { accountViewModel.delete(item) },
|
|
||||||
) {
|
) {
|
||||||
Row(
|
SwipeToDeleteContainer(
|
||||||
Modifier
|
modifier =
|
||||||
.fillMaxWidth()
|
Modifier
|
||||||
.animateItemPlacement()
|
.fillMaxWidth()
|
||||||
.background(MaterialTheme.colorScheme.background),
|
.animateContentSize(),
|
||||||
|
onStartToEnd = { accountViewModel.delete(item) },
|
||||||
|
onEndToStart = { accountViewModel.delete(item) },
|
||||||
) {
|
) {
|
||||||
NoteCompose(
|
NoteCompose(
|
||||||
item,
|
item,
|
||||||
routeForLastRead = routeForLastRead,
|
routeForLastRead = routeForLastRead,
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = MaterialTheme.colorScheme.maxWidthWithBackground,
|
||||||
isBoostedNote = false,
|
isBoostedNote = false,
|
||||||
isHiddenFeed = state.showHidden.value,
|
isHiddenFeed = state.showHidden.value,
|
||||||
quotesLeft = 3,
|
quotesLeft = 3,
|
||||||
|
|||||||
@@ -189,6 +189,16 @@ val LightInnerPostBorderModifier =
|
|||||||
.clip(shape = QuoteBorder)
|
.clip(shape = QuoteBorder)
|
||||||
.border(1.dp, LightSubtleBorder, QuoteBorder)
|
.border(1.dp, LightSubtleBorder, QuoteBorder)
|
||||||
|
|
||||||
|
val DarkMaxWidthWithBackground =
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(DarkColorPalette.background)
|
||||||
|
|
||||||
|
val LightMaxWidthWithBackground =
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(LightColorPalette.background)
|
||||||
|
|
||||||
val DarkSelectedReactionBoxModifier =
|
val DarkSelectedReactionBoxModifier =
|
||||||
Modifier
|
Modifier
|
||||||
.padding(horizontal = 5.dp, vertical = 5.dp)
|
.padding(horizontal = 5.dp, vertical = 5.dp)
|
||||||
@@ -395,6 +405,9 @@ val ColorScheme.replyModifier: Modifier
|
|||||||
val ColorScheme.innerPostModifier: Modifier
|
val ColorScheme.innerPostModifier: Modifier
|
||||||
get() = if (isLight) LightInnerPostBorderModifier else DarkInnerPostBorderModifier
|
get() = if (isLight) LightInnerPostBorderModifier else DarkInnerPostBorderModifier
|
||||||
|
|
||||||
|
val ColorScheme.maxWidthWithBackground: Modifier
|
||||||
|
get() = if (isLight) LightMaxWidthWithBackground else DarkMaxWidthWithBackground
|
||||||
|
|
||||||
val ColorScheme.channelNotePictureModifier: Modifier
|
val ColorScheme.channelNotePictureModifier: Modifier
|
||||||
get() = if (isLight) LightChannelNotePictureModifier else DarkChannelNotePictureModifier
|
get() = if (isLight) LightChannelNotePictureModifier else DarkChannelNotePictureModifier
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user