mirror of
https://github.com/LiveFastEatTrashRaccoon/RaccoonForLemmy.git
synced 2025-02-03 16:47:40 +01:00
fix(common-ui): swipe actions visibility in comment cards
This commit is contained in:
parent
79afe2e40e
commit
01f63bf8b8
@ -47,7 +47,9 @@ fun CommentCard(
|
||||
fontScale = fontScale,
|
||||
),
|
||||
) {
|
||||
Column {
|
||||
Column(
|
||||
modifier = Modifier.background(MaterialTheme.colorScheme.surface)
|
||||
) {
|
||||
var commentHeight by remember { mutableStateOf(0f) }
|
||||
val barWidth = 2.dp
|
||||
val barColor = themeRepository.getCommentBarColor(
|
||||
|
@ -24,6 +24,9 @@ import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.layout.onGloballyPositioned
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.toSize
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
@ -59,23 +62,20 @@ fun SwipeableCard(
|
||||
false
|
||||
},
|
||||
)
|
||||
var willDismissDirection: DismissDirection? by remember {
|
||||
mutableStateOf(null)
|
||||
}
|
||||
val threshold = 0.15f
|
||||
LaunchedEffect(Unit) {
|
||||
snapshotFlow { dismissState.offset.value }.collect {
|
||||
willDismissDirection = when {
|
||||
|
||||
val threshold = 0.25f
|
||||
LaunchedEffect(dismissState) {
|
||||
snapshotFlow { dismissState.offset.value }.map {
|
||||
when {
|
||||
it > width * threshold -> DismissDirection.StartToEnd
|
||||
it < -width * threshold -> DismissDirection.EndToStart
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
LaunchedEffect(willDismissDirection) {
|
||||
if (willDismissDirection != null) {
|
||||
onGestureBegin()
|
||||
}
|
||||
}.onEach { willDismissDirection ->
|
||||
if (willDismissDirection != null) {
|
||||
onGestureBegin()
|
||||
}
|
||||
}.launchIn(this)
|
||||
}
|
||||
SwipeToDismiss(
|
||||
modifier = modifier.onGloballyPositioned {
|
||||
@ -97,7 +97,10 @@ fun SwipeableCard(
|
||||
DismissDirection.EndToStart -> Alignment.CenterEnd
|
||||
}
|
||||
Box(
|
||||
Modifier.fillMaxSize().background(bgColor).padding(horizontal = 20.dp),
|
||||
Modifier
|
||||
.fillMaxSize()
|
||||
.background(bgColor)
|
||||
.padding(horizontal = 20.dp),
|
||||
contentAlignment = alignment,
|
||||
) {
|
||||
swipeContent(direction)
|
||||
|
@ -7,9 +7,9 @@ import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
@ -223,13 +223,13 @@ class PostDetailScreen(
|
||||
model.reduce(PostDetailMviModel.Intent.Refresh)
|
||||
})
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(padding)
|
||||
modifier = Modifier.padding(padding)
|
||||
.nestedScroll(scrollBehavior.nestedScrollConnection)
|
||||
.nestedScroll(fabNestedScrollConnection)
|
||||
.pullRefresh(pullRefreshState),
|
||||
) {
|
||||
LazyColumn(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
verticalArrangement = Arrangement.spacedBy(Spacing.xs),
|
||||
) {
|
||||
item {
|
||||
@ -267,16 +267,14 @@ class PostDetailScreen(
|
||||
)
|
||||
},
|
||||
)
|
||||
PostCardImage(
|
||||
imageUrl = statePost.thumbnailUrl.orEmpty(),
|
||||
PostCardImage(imageUrl = statePost.thumbnailUrl.orEmpty(),
|
||||
onImageClick = {
|
||||
navigator?.push(
|
||||
ZoomableImageScreen(
|
||||
url = statePost.thumbnailUrl.orEmpty()
|
||||
),
|
||||
)
|
||||
}
|
||||
)
|
||||
})
|
||||
PostCardBody(
|
||||
text = statePost.text,
|
||||
)
|
||||
@ -286,8 +284,7 @@ class PostDetailScreen(
|
||||
it?.contains("pictrs/image") == false
|
||||
}.orEmpty(),
|
||||
)
|
||||
PostCardFooter(
|
||||
comments = statePost.comments,
|
||||
PostCardFooter(comments = statePost.comments,
|
||||
score = statePost.score,
|
||||
upVoted = statePost.myVote > 0,
|
||||
downVoted = statePost.myVote < 0,
|
||||
@ -335,121 +332,130 @@ class PostDetailScreen(
|
||||
)
|
||||
bottomSheetNavigator.show(
|
||||
CreatePostScreen(
|
||||
editedPost = post,
|
||||
editedPost = statePost,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
else -> model.reduce(PostDetailMviModel.Intent.SharePost)
|
||||
}
|
||||
}
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
itemsIndexed(uiState.comments) { idx, comment ->
|
||||
Column {
|
||||
SwipeableCard(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
enabled = uiState.swipeActionsEnabled,
|
||||
backgroundColor = {
|
||||
when (it) {
|
||||
DismissValue.DismissedToStart -> MaterialTheme.colorScheme.secondary
|
||||
DismissValue.DismissedToEnd -> MaterialTheme.colorScheme.tertiary
|
||||
DismissValue.Default -> Color.Transparent
|
||||
SwipeableCard(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
enabled = uiState.swipeActionsEnabled,
|
||||
backgroundColor = {
|
||||
when (it) {
|
||||
DismissValue.DismissedToStart -> MaterialTheme.colorScheme.secondary
|
||||
DismissValue.DismissedToEnd -> MaterialTheme.colorScheme.tertiary
|
||||
DismissValue.Default -> Color.Transparent
|
||||
}
|
||||
},
|
||||
onGestureBegin = {
|
||||
model.reduce(PostDetailMviModel.Intent.HapticIndication)
|
||||
},
|
||||
onDismissToStart = {
|
||||
model.reduce(
|
||||
PostDetailMviModel.Intent.UpVoteComment(idx),
|
||||
)
|
||||
},
|
||||
onDismissToEnd = {
|
||||
model.reduce(
|
||||
PostDetailMviModel.Intent.DownVoteComment(idx),
|
||||
)
|
||||
},
|
||||
swipeContent = { direction ->
|
||||
val icon = when (direction) {
|
||||
DismissDirection.StartToEnd -> Icons.Default.ArrowCircleDown
|
||||
DismissDirection.EndToStart -> Icons.Default.ArrowCircleUp
|
||||
}
|
||||
val (iconModifier, iconTint) = when {
|
||||
direction == DismissDirection.StartToEnd && comment.myVote < 0 -> {
|
||||
Modifier.background(
|
||||
color = Color.Transparent,
|
||||
shape = CircleShape,
|
||||
) to MaterialTheme.colorScheme.onTertiary
|
||||
}
|
||||
},
|
||||
onGestureBegin = {
|
||||
model.reduce(PostDetailMviModel.Intent.HapticIndication)
|
||||
},
|
||||
onDismissToStart = {
|
||||
model.reduce(
|
||||
PostDetailMviModel.Intent.UpVoteComment(idx),
|
||||
)
|
||||
},
|
||||
onDismissToEnd = {
|
||||
model.reduce(
|
||||
PostDetailMviModel.Intent.DownVoteComment(idx),
|
||||
)
|
||||
},
|
||||
swipeContent = { direction ->
|
||||
val icon = when (direction) {
|
||||
DismissDirection.StartToEnd -> Icons.Default.ArrowCircleDown
|
||||
DismissDirection.EndToStart -> Icons.Default.ArrowCircleUp
|
||||
|
||||
direction == DismissDirection.StartToEnd -> {
|
||||
Modifier.background(
|
||||
color = MaterialTheme.colorScheme.onTertiary,
|
||||
shape = CircleShape,
|
||||
) to MaterialTheme.colorScheme.tertiary
|
||||
}
|
||||
val (iconModifier, iconTint) = when {
|
||||
direction == DismissDirection.StartToEnd && statePost.myVote < 0 -> {
|
||||
Modifier.background(
|
||||
color = Color.Transparent,
|
||||
shape = CircleShape,
|
||||
) to MaterialTheme.colorScheme.onTertiary
|
||||
}
|
||||
|
||||
direction == DismissDirection.StartToEnd -> {
|
||||
Modifier.background(
|
||||
color = MaterialTheme.colorScheme.onTertiary,
|
||||
shape = CircleShape,
|
||||
) to MaterialTheme.colorScheme.tertiary
|
||||
}
|
||||
direction == DismissDirection.EndToStart && comment.myVote > 0 -> {
|
||||
Modifier.background(
|
||||
color = Color.Transparent,
|
||||
shape = CircleShape,
|
||||
) to MaterialTheme.colorScheme.onSecondary
|
||||
}
|
||||
|
||||
direction == DismissDirection.EndToStart && statePost.myVote > 0 -> {
|
||||
Modifier.background(
|
||||
color = Color.Transparent,
|
||||
shape = CircleShape,
|
||||
) to MaterialTheme.colorScheme.onSecondary
|
||||
}
|
||||
else -> {
|
||||
Modifier.background(
|
||||
color = MaterialTheme.colorScheme.onSecondary,
|
||||
shape = CircleShape,
|
||||
) to MaterialTheme.colorScheme.secondary
|
||||
}
|
||||
}
|
||||
Icon(
|
||||
modifier = iconModifier,
|
||||
imageVector = icon,
|
||||
contentDescription = null,
|
||||
tint = iconTint,
|
||||
)
|
||||
},
|
||||
content = {
|
||||
CommentCard(comment = comment, options = buildList {
|
||||
if (comment.creator?.id == uiState.currentUserId) {
|
||||
add(stringResource(MR.strings.comment_action_delete))
|
||||
}
|
||||
}, onUpVote = {
|
||||
model.reduce(
|
||||
PostDetailMviModel.Intent.UpVoteComment(
|
||||
index = idx,
|
||||
feedback = true,
|
||||
),
|
||||
)
|
||||
}, onDownVote = {
|
||||
model.reduce(
|
||||
PostDetailMviModel.Intent.DownVoteComment(
|
||||
index = idx,
|
||||
feedback = true,
|
||||
),
|
||||
)
|
||||
}, onSave = {
|
||||
model.reduce(
|
||||
PostDetailMviModel.Intent.SaveComment(
|
||||
index = idx,
|
||||
feedback = true,
|
||||
),
|
||||
)
|
||||
}, onReply = {
|
||||
val screen = CreateCommentScreen(
|
||||
originalPost = statePost,
|
||||
originalComment = comment,
|
||||
)
|
||||
notificationCenter.addObserver(
|
||||
{
|
||||
model.reduce(PostDetailMviModel.Intent.Refresh)
|
||||
},
|
||||
key,
|
||||
NotificationCenterContractKeys.CommentCreated
|
||||
)
|
||||
bottomSheetNavigator.show(screen)
|
||||
}, onOptionSelected = { idx ->
|
||||
when (idx) {
|
||||
1 -> model.reduce(
|
||||
PostDetailMviModel.Intent.DeleteComment(
|
||||
comment.id
|
||||
)
|
||||
)
|
||||
|
||||
else -> {
|
||||
Modifier.background(
|
||||
color = MaterialTheme.colorScheme.onSecondary,
|
||||
shape = CircleShape,
|
||||
) to MaterialTheme.colorScheme.secondary
|
||||
}
|
||||
}
|
||||
Icon(
|
||||
modifier = iconModifier,
|
||||
imageVector = icon,
|
||||
contentDescription = null,
|
||||
tint = iconTint,
|
||||
)
|
||||
},
|
||||
content = {
|
||||
CommentCard(
|
||||
comment = comment,
|
||||
options = buildList {
|
||||
if (comment.creator?.id == uiState.currentUserId) {
|
||||
add(stringResource(MR.strings.comment_action_delete))
|
||||
}
|
||||
},
|
||||
onUpVote = {
|
||||
model.reduce(
|
||||
PostDetailMviModel.Intent.UpVoteComment(
|
||||
index = idx,
|
||||
feedback = true,
|
||||
),
|
||||
)
|
||||
},
|
||||
onDownVote = {
|
||||
model.reduce(
|
||||
PostDetailMviModel.Intent.DownVoteComment(
|
||||
index = idx,
|
||||
feedback = true,
|
||||
),
|
||||
)
|
||||
},
|
||||
onSave = {
|
||||
model.reduce(
|
||||
PostDetailMviModel.Intent.SaveComment(
|
||||
index = idx,
|
||||
feedback = true,
|
||||
),
|
||||
)
|
||||
},
|
||||
onReply = {
|
||||
val screen = CreateCommentScreen(
|
||||
originalPost = statePost,
|
||||
originalComment = comment,
|
||||
)
|
||||
notificationCenter.addObserver(
|
||||
{
|
||||
model.reduce(PostDetailMviModel.Intent.Refresh)
|
||||
@ -457,54 +463,34 @@ class PostDetailScreen(
|
||||
key,
|
||||
NotificationCenterContractKeys.CommentCreated
|
||||
)
|
||||
bottomSheetNavigator.show(screen)
|
||||
},
|
||||
onOptionSelected = { idx ->
|
||||
when (idx) {
|
||||
1 -> model.reduce(
|
||||
PostDetailMviModel.Intent.DeleteComment(
|
||||
comment.id
|
||||
)
|
||||
bottomSheetNavigator.show(
|
||||
CreateCommentScreen(
|
||||
editedComment = comment,
|
||||
)
|
||||
|
||||
else -> {
|
||||
notificationCenter.addObserver(
|
||||
{
|
||||
model.reduce(PostDetailMviModel.Intent.Refresh)
|
||||
},
|
||||
key,
|
||||
NotificationCenterContractKeys.CommentCreated
|
||||
)
|
||||
bottomSheetNavigator.show(
|
||||
CreateCommentScreen(
|
||||
editedComment = comment,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
},
|
||||
)
|
||||
if ((comment.comments
|
||||
?: 0) > 0 && comment.depth == CommentRepository.MAX_COMMENT_DEPTH && (idx < uiState.comments.lastIndex && uiState.comments[idx + 1].depth < comment.depth)
|
||||
) {
|
||||
Row {
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
Button(onClick = {
|
||||
model.reduce(
|
||||
PostDetailMviModel.Intent.FetchMoreComments(
|
||||
parentId = comment.id
|
||||
)
|
||||
)
|
||||
}) {
|
||||
Text(
|
||||
text = stringResource(MR.strings.post_detail_load_more_comments),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
)
|
||||
}
|
||||
}
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
})
|
||||
},
|
||||
)
|
||||
if ((comment.comments
|
||||
?: 0) > 0 && comment.depth == CommentRepository.MAX_COMMENT_DEPTH && (idx < uiState.comments.lastIndex && uiState.comments[idx + 1].depth < comment.depth)
|
||||
) {
|
||||
Row {
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
Button(onClick = {
|
||||
model.reduce(
|
||||
PostDetailMviModel.Intent.FetchMoreComments(
|
||||
parentId = comment.id
|
||||
)
|
||||
)
|
||||
}) {
|
||||
Text(
|
||||
text = stringResource(MR.strings.post_detail_load_more_comments),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,9 +41,11 @@ class PostDetailViewModel(
|
||||
override fun onStarted() {
|
||||
mvi.onStarted()
|
||||
val sortType = keyStore[KeyStoreKeys.DefaultCommentSortType, 3].toSortType()
|
||||
val swipeActionsEnabled = keyStore[KeyStoreKeys.EnableSwipeActions, true]
|
||||
mvi.updateState {
|
||||
it.copy(
|
||||
sortType = sortType,
|
||||
swipeActionsEnabled = swipeActionsEnabled,
|
||||
)
|
||||
}
|
||||
mvi.scope?.launch {
|
||||
|
@ -164,6 +164,13 @@ class PostListScreen : Screen {
|
||||
SwipeableCard(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
enabled = uiState.swipeActionsEnabled,
|
||||
backgroundColor = {
|
||||
when (it) {
|
||||
DismissValue.DismissedToStart -> MaterialTheme.colorScheme.secondary
|
||||
DismissValue.DismissedToEnd -> MaterialTheme.colorScheme.tertiary
|
||||
DismissValue.Default -> Color.Transparent
|
||||
}
|
||||
},
|
||||
onGestureBegin = {
|
||||
model.reduce(PostListMviModel.Intent.HapticIndication)
|
||||
},
|
||||
@ -173,13 +180,6 @@ class PostListScreen : Screen {
|
||||
onDismissToEnd = {
|
||||
model.reduce(PostListMviModel.Intent.DownVotePost(idx))
|
||||
},
|
||||
backgroundColor = {
|
||||
when (it) {
|
||||
DismissValue.DismissedToStart -> MaterialTheme.colorScheme.secondary
|
||||
DismissValue.DismissedToEnd -> MaterialTheme.colorScheme.tertiary
|
||||
else -> Color.Transparent
|
||||
}
|
||||
},
|
||||
swipeContent = { direction ->
|
||||
val icon = when (direction) {
|
||||
DismissDirection.StartToEnd -> Icons.Default.ArrowCircleDown
|
||||
|
Loading…
x
Reference in New Issue
Block a user