mirror of
https://github.com/LiveFastEatTrashRaccoon/RaccoonForLemmy.git
synced 2025-02-03 11:17:32 +01:00
feat: comment collapsing (#83)
* feat: new comment expanding policy * fix: typo in Italian l10n * fix: text fields in create post screen
This commit is contained in:
parent
dfff1ed9fb
commit
596d4a5cd7
@ -0,0 +1,107 @@
|
||||
package com.github.diegoberaldin.raccoonforlemmy.core.commonui.components
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.layout.onGloballyPositioned
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.toSize
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.di.getThemeRepository
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.utils.toLocalDp
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommentModel
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.UserModel
|
||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.CommentRepository
|
||||
|
||||
@Composable
|
||||
fun CollapsedCommentCard(
|
||||
comment: CommentModel,
|
||||
modifier: Modifier = Modifier,
|
||||
separateUpAndDownVotes: Boolean = false,
|
||||
autoLoadImages: Boolean = true,
|
||||
options: List<String> = emptyList(),
|
||||
onOpenCreator: ((UserModel) -> Unit)? = null,
|
||||
onUpVote: (() -> Unit)? = null,
|
||||
onDownVote: (() -> Unit)? = null,
|
||||
onSave: (() -> Unit)? = null,
|
||||
onReply: (() -> Unit)? = null,
|
||||
onOptionSelected: ((Int) -> Unit)? = null,
|
||||
onToggleExpanded: (() -> Unit)? = null,
|
||||
) {
|
||||
val themeRepository = remember { getThemeRepository() }
|
||||
var commentHeight by remember { mutableStateOf(0f) }
|
||||
val barWidth = 2.dp
|
||||
val barColor = themeRepository.getCommentBarColor(
|
||||
depth = comment.depth,
|
||||
maxDepth = CommentRepository.MAX_COMMENT_DEPTH,
|
||||
startColor = MaterialTheme.colorScheme.primary,
|
||||
endColor = MaterialTheme.colorScheme.background,
|
||||
)
|
||||
Column(
|
||||
modifier = modifier
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier.padding(
|
||||
start = (10 * comment.depth).dp
|
||||
),
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(start = barWidth)
|
||||
.fillMaxWidth()
|
||||
.padding(
|
||||
vertical = Spacing.xxs,
|
||||
horizontal = Spacing.s,
|
||||
).onGloballyPositioned {
|
||||
commentHeight = it.size.toSize().height
|
||||
}
|
||||
) {
|
||||
CommunityAndCreatorInfo(
|
||||
iconSize = 20.dp,
|
||||
creator = comment.creator,
|
||||
indicatorExpanded = comment.expanded,
|
||||
autoLoadImages = autoLoadImages,
|
||||
onToggleExpanded = {
|
||||
onToggleExpanded?.invoke()
|
||||
},
|
||||
onOpenCreator = onOpenCreator,
|
||||
)
|
||||
PostCardFooter(
|
||||
score = comment.score,
|
||||
separateUpAndDownVotes = separateUpAndDownVotes,
|
||||
upvotes = comment.upvotes,
|
||||
downvotes = comment.downvotes,
|
||||
saved = comment.saved,
|
||||
upVoted = comment.myVote > 0,
|
||||
downVoted = comment.myVote < 0,
|
||||
comments = comment.comments,
|
||||
onUpVote = onUpVote,
|
||||
onDownVote = onDownVote,
|
||||
onSave = onSave,
|
||||
onReply = onReply,
|
||||
date = comment.publishDate,
|
||||
options = options,
|
||||
onOptionSelected = onOptionSelected,
|
||||
)
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(top = Spacing.xs)
|
||||
.width(barWidth)
|
||||
.height(commentHeight.toLocalDp())
|
||||
.background(color = barColor)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -45,6 +45,7 @@ fun CommentCard(
|
||||
onOpenCommunity: ((CommunityModel) -> Unit)? = null,
|
||||
onOpenCreator: ((UserModel) -> Unit)? = null,
|
||||
onOptionSelected: ((Int) -> Unit)? = null,
|
||||
onToggleExpanded: (() -> Unit)? = null,
|
||||
) {
|
||||
val themeRepository = remember { getThemeRepository() }
|
||||
Column(
|
||||
@ -85,6 +86,7 @@ fun CommentCard(
|
||||
autoLoadImages = autoLoadImages,
|
||||
onOpenCreator = onOpenCreator,
|
||||
onOpenCommunity = onOpenCommunity,
|
||||
onToggleExpanded = onToggleExpanded,
|
||||
)
|
||||
ScaledContent {
|
||||
PostCardBody(
|
||||
|
@ -36,6 +36,7 @@ fun CommunityAndCreatorInfo(
|
||||
creator: UserModel? = null,
|
||||
onOpenCommunity: ((CommunityModel) -> Unit)? = null,
|
||||
onOpenCreator: ((UserModel) -> Unit)? = null,
|
||||
onToggleExpanded: (() -> Unit)? = null,
|
||||
) {
|
||||
val communityName = community?.name.orEmpty()
|
||||
val communityIcon = community?.icon.orEmpty()
|
||||
@ -144,16 +145,18 @@ fun CommunityAndCreatorInfo(
|
||||
}
|
||||
if (indicatorExpanded != null) {
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
val modifier = Modifier.padding(end = Spacing.xs)
|
||||
val expandedModifier = Modifier
|
||||
.padding(end = Spacing.xs)
|
||||
.onClick { onToggleExpanded?.invoke() }
|
||||
if (indicatorExpanded) {
|
||||
Icon(
|
||||
modifier = modifier,
|
||||
modifier = expandedModifier,
|
||||
imageVector = Icons.Default.ExpandLess,
|
||||
contentDescription = null,
|
||||
)
|
||||
} else {
|
||||
Icon(
|
||||
modifier = modifier,
|
||||
modifier = expandedModifier,
|
||||
imageVector = Icons.Default.ExpandMore,
|
||||
contentDescription = null,
|
||||
)
|
||||
|
@ -44,6 +44,7 @@ import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
||||
import androidx.compose.ui.input.nestedscroll.NestedScrollSource
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.input.ImeAction
|
||||
import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
@ -174,6 +175,7 @@ class CreatePostScreen(
|
||||
},
|
||||
textStyle = MaterialTheme.typography.titleMedium,
|
||||
value = uiState.title,
|
||||
singleLine = true,
|
||||
keyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Ascii,
|
||||
autoCorrect = false,
|
||||
@ -218,7 +220,6 @@ class CreatePostScreen(
|
||||
unfocusedContainerColor = Color.Transparent,
|
||||
disabledContainerColor = Color.Transparent,
|
||||
),
|
||||
maxLines = 1,
|
||||
label = {
|
||||
Text(text = stringResource(MR.strings.create_post_url))
|
||||
},
|
||||
@ -231,8 +232,11 @@ class CreatePostScreen(
|
||||
contentDescription = null,
|
||||
)
|
||||
},
|
||||
textStyle = MaterialTheme.typography.bodyMedium,
|
||||
textStyle = MaterialTheme.typography.bodyMedium.copy(
|
||||
fontFamily = FontFamily.Monospace,
|
||||
),
|
||||
value = uiState.url,
|
||||
singleLine = true,
|
||||
keyboardOptions = KeyboardOptions(
|
||||
keyboardType = KeyboardType.Ascii,
|
||||
autoCorrect = false,
|
||||
|
@ -1,10 +1,13 @@
|
||||
package com.github.diegoberaldin.raccoonforlemmy.core.commonui.postdetail
|
||||
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.slideInVertically
|
||||
import androidx.compose.animation.slideOutVertically
|
||||
import androidx.compose.animation.togetherWith
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
@ -76,6 +79,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.appearance.di.getThemeRepos
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.architecture.bindToLifecycle
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.CommunityDetailScreen
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.CollapsedCommentCard
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.CommentCard
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.CommentCardPlaceholder
|
||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.FloatingActionButtonMenu
|
||||
@ -455,161 +459,114 @@ class PostDetailScreen(
|
||||
}
|
||||
itemsIndexed(uiState.comments, key = { _, c -> c.id }) { idx, comment ->
|
||||
val commentId = comment.id
|
||||
AnimatedVisibility(
|
||||
visible = comment.visible,
|
||||
exit = fadeOut(),
|
||||
enter = fadeIn(),
|
||||
AnimatedContent(
|
||||
targetState = comment.expanded,
|
||||
transitionSpec = {
|
||||
fadeIn(animationSpec = tween(220, delayMillis = 90))
|
||||
.togetherWith(fadeOut(animationSpec = tween(90)))
|
||||
},
|
||||
) {
|
||||
if (comment.expanded) {
|
||||
SwipeableCard(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
enabled = uiState.swipeActionsEnabled && !isOnOtherInstance,
|
||||
backgroundColor = {
|
||||
when (it) {
|
||||
DismissValue.DismissedToStart -> upvoteColor
|
||||
?: defaultUpvoteColor
|
||||
|
||||
) {
|
||||
SwipeableCard(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
enabled = uiState.swipeActionsEnabled && !isOnOtherInstance,
|
||||
backgroundColor = {
|
||||
when (it) {
|
||||
DismissValue.DismissedToStart -> upvoteColor
|
||||
?: defaultUpvoteColor
|
||||
DismissValue.DismissedToEnd -> downvoteColor
|
||||
?: defaultDownVoteColor
|
||||
|
||||
DismissValue.DismissedToEnd -> downvoteColor
|
||||
?: defaultDownVoteColor
|
||||
|
||||
DismissValue.Default -> Color.Transparent
|
||||
}
|
||||
},
|
||||
onGestureBegin = {
|
||||
model.reduce(PostDetailMviModel.Intent.HapticIndication)
|
||||
},
|
||||
onDismissToStart = {
|
||||
model.reduce(
|
||||
PostDetailMviModel.Intent.UpVoteComment(commentId),
|
||||
)
|
||||
},
|
||||
onDismissToEnd = {
|
||||
model.reduce(
|
||||
PostDetailMviModel.Intent.DownVoteComment(commentId),
|
||||
)
|
||||
},
|
||||
swipeContent = { direction ->
|
||||
val icon = when (direction) {
|
||||
DismissDirection.StartToEnd -> Icons.Default.ArrowCircleDown
|
||||
DismissDirection.EndToStart -> Icons.Default.ArrowCircleUp
|
||||
}
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
contentDescription = null,
|
||||
tint = Color.White,
|
||||
)
|
||||
},
|
||||
content = {
|
||||
CommentCard(
|
||||
modifier = Modifier.background(MaterialTheme.colorScheme.background)
|
||||
.let {
|
||||
if (comment.id == highlightCommentId) {
|
||||
it.background(
|
||||
MaterialTheme.colorScheme.surfaceColorAtElevation(
|
||||
5.dp
|
||||
).copy(
|
||||
alpha = 0.75f
|
||||
DismissValue.Default -> Color.Transparent
|
||||
}
|
||||
},
|
||||
onGestureBegin = {
|
||||
model.reduce(PostDetailMviModel.Intent.HapticIndication)
|
||||
},
|
||||
onDismissToStart = {
|
||||
model.reduce(
|
||||
PostDetailMviModel.Intent.UpVoteComment(commentId),
|
||||
)
|
||||
},
|
||||
onDismissToEnd = {
|
||||
model.reduce(
|
||||
PostDetailMviModel.Intent.DownVoteComment(commentId),
|
||||
)
|
||||
},
|
||||
swipeContent = { direction ->
|
||||
val icon = when (direction) {
|
||||
DismissDirection.StartToEnd -> Icons.Default.ArrowCircleDown
|
||||
DismissDirection.EndToStart -> Icons.Default.ArrowCircleUp
|
||||
}
|
||||
Icon(
|
||||
imageVector = icon,
|
||||
contentDescription = null,
|
||||
tint = Color.White,
|
||||
)
|
||||
},
|
||||
content = {
|
||||
CommentCard(
|
||||
modifier = Modifier.background(MaterialTheme.colorScheme.background)
|
||||
.let {
|
||||
if (comment.id == highlightCommentId) {
|
||||
it.background(
|
||||
MaterialTheme.colorScheme.surfaceColorAtElevation(
|
||||
5.dp
|
||||
).copy(
|
||||
alpha = 0.75f
|
||||
)
|
||||
)
|
||||
)
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}.onClick {
|
||||
} else {
|
||||
it
|
||||
}
|
||||
},
|
||||
comment = comment,
|
||||
separateUpAndDownVotes = uiState.separateUpAndDownVotes,
|
||||
autoLoadImages = uiState.autoLoadImages,
|
||||
onToggleExpanded = {
|
||||
model.reduce(
|
||||
PostDetailMviModel.Intent.ToggleExpandComment(
|
||||
commentId,
|
||||
)
|
||||
)
|
||||
},
|
||||
comment = comment,
|
||||
separateUpAndDownVotes = uiState.separateUpAndDownVotes,
|
||||
autoLoadImages = uiState.autoLoadImages,
|
||||
onUpVote = {
|
||||
if (!isOnOtherInstance) {
|
||||
model.reduce(
|
||||
PostDetailMviModel.Intent.UpVoteComment(
|
||||
commentId = commentId,
|
||||
feedback = true,
|
||||
),
|
||||
)
|
||||
}
|
||||
},
|
||||
onDownVote = {
|
||||
if (!isOnOtherInstance) {
|
||||
model.reduce(
|
||||
PostDetailMviModel.Intent.DownVoteComment(
|
||||
commentId = commentId,
|
||||
feedback = true,
|
||||
),
|
||||
)
|
||||
}
|
||||
},
|
||||
onSave = {
|
||||
if (!isOnOtherInstance) {
|
||||
model.reduce(
|
||||
PostDetailMviModel.Intent.SaveComment(
|
||||
commentId = commentId,
|
||||
feedback = true,
|
||||
),
|
||||
)
|
||||
}
|
||||
},
|
||||
onReply = {
|
||||
if (!isOnOtherInstance) {
|
||||
val screen = CreateCommentScreen(
|
||||
originalPost = statePost,
|
||||
originalComment = comment,
|
||||
)
|
||||
notificationCenter.addObserver(
|
||||
{
|
||||
model.reduce(PostDetailMviModel.Intent.Refresh)
|
||||
model.reduce(PostDetailMviModel.Intent.RefreshPost)
|
||||
},
|
||||
key,
|
||||
NotificationCenterContractKeys.CommentCreated
|
||||
)
|
||||
bottomSheetNavigator.show(screen)
|
||||
}
|
||||
},
|
||||
onOpenCreator = {
|
||||
val user = comment.creator
|
||||
if (user != null) {
|
||||
navigator?.push(
|
||||
UserDetailScreen(
|
||||
user = user,
|
||||
otherInstance = otherInstance,
|
||||
),
|
||||
)
|
||||
}
|
||||
},
|
||||
onOpenCommunity = {
|
||||
val community = comment.community
|
||||
if (community != null) {
|
||||
navigator?.push(
|
||||
CommunityDetailScreen(
|
||||
community = community,
|
||||
otherInstance = otherInstance,
|
||||
),
|
||||
)
|
||||
}
|
||||
},
|
||||
options = buildList {
|
||||
add(stringResource(MR.strings.post_action_see_raw))
|
||||
add(stringResource(MR.strings.post_action_report))
|
||||
if (comment.creator?.id == uiState.currentUserId) {
|
||||
add(stringResource(MR.strings.post_action_edit))
|
||||
add(stringResource(MR.strings.comment_action_delete))
|
||||
}
|
||||
},
|
||||
onOptionSelected = { optionId ->
|
||||
when (optionId) {
|
||||
3 -> model.reduce(
|
||||
PostDetailMviModel.Intent.DeleteComment(
|
||||
comment.id
|
||||
)
|
||||
)
|
||||
|
||||
2 -> {
|
||||
},
|
||||
onUpVote = {
|
||||
if (!isOnOtherInstance) {
|
||||
model.reduce(
|
||||
PostDetailMviModel.Intent.UpVoteComment(
|
||||
commentId = commentId,
|
||||
feedback = true,
|
||||
),
|
||||
)
|
||||
}
|
||||
},
|
||||
onDownVote = {
|
||||
if (!isOnOtherInstance) {
|
||||
model.reduce(
|
||||
PostDetailMviModel.Intent.DownVoteComment(
|
||||
commentId = commentId,
|
||||
feedback = true,
|
||||
),
|
||||
)
|
||||
}
|
||||
},
|
||||
onSave = {
|
||||
if (!isOnOtherInstance) {
|
||||
model.reduce(
|
||||
PostDetailMviModel.Intent.SaveComment(
|
||||
commentId = commentId,
|
||||
feedback = true,
|
||||
),
|
||||
)
|
||||
}
|
||||
},
|
||||
onReply = {
|
||||
if (!isOnOtherInstance) {
|
||||
val screen = CreateCommentScreen(
|
||||
originalPost = statePost,
|
||||
originalComment = comment,
|
||||
)
|
||||
notificationCenter.addObserver(
|
||||
{
|
||||
model.reduce(PostDetailMviModel.Intent.Refresh)
|
||||
@ -618,29 +575,195 @@ class PostDetailScreen(
|
||||
key,
|
||||
NotificationCenterContractKeys.CommentCreated
|
||||
)
|
||||
bottomSheetNavigator.show(
|
||||
CreateCommentScreen(
|
||||
editedComment = comment,
|
||||
)
|
||||
bottomSheetNavigator.show(screen)
|
||||
}
|
||||
},
|
||||
onOpenCreator = {
|
||||
val user = comment.creator
|
||||
if (user != null) {
|
||||
navigator?.push(
|
||||
UserDetailScreen(
|
||||
user = user,
|
||||
otherInstance = otherInstance,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
1 -> {
|
||||
bottomSheetNavigator.show(
|
||||
CreateReportScreen(
|
||||
commentId = comment.id
|
||||
)
|
||||
},
|
||||
onOpenCommunity = {
|
||||
val community = comment.community
|
||||
if (community != null) {
|
||||
navigator?.push(
|
||||
CommunityDetailScreen(
|
||||
community = community,
|
||||
otherInstance = otherInstance,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
else -> {
|
||||
rawContent = comment
|
||||
},
|
||||
options = buildList {
|
||||
add(stringResource(MR.strings.post_action_see_raw))
|
||||
add(stringResource(MR.strings.post_action_report))
|
||||
if (comment.creator?.id == uiState.currentUserId) {
|
||||
add(stringResource(MR.strings.post_action_edit))
|
||||
add(stringResource(MR.strings.comment_action_delete))
|
||||
}
|
||||
},
|
||||
onOptionSelected = { optionId ->
|
||||
when (optionId) {
|
||||
3 -> model.reduce(
|
||||
PostDetailMviModel.Intent.DeleteComment(
|
||||
comment.id
|
||||
)
|
||||
)
|
||||
|
||||
2 -> {
|
||||
notificationCenter.addObserver(
|
||||
{
|
||||
model.reduce(PostDetailMviModel.Intent.Refresh)
|
||||
model.reduce(PostDetailMviModel.Intent.RefreshPost)
|
||||
},
|
||||
key,
|
||||
NotificationCenterContractKeys.CommentCreated
|
||||
)
|
||||
bottomSheetNavigator.show(
|
||||
CreateCommentScreen(
|
||||
editedComment = comment,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
1 -> {
|
||||
bottomSheetNavigator.show(
|
||||
CreateReportScreen(
|
||||
commentId = comment.id
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
else -> {
|
||||
rawContent = comment
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
} else {
|
||||
CollapsedCommentCard(
|
||||
comment = comment,
|
||||
modifier = Modifier.padding(vertical = Spacing.xs),
|
||||
onToggleExpanded = {
|
||||
model.reduce(
|
||||
PostDetailMviModel.Intent.ToggleExpandComment(
|
||||
comment.id
|
||||
)
|
||||
)
|
||||
},
|
||||
onUpVote = {
|
||||
if (!isOnOtherInstance) {
|
||||
model.reduce(
|
||||
PostDetailMviModel.Intent.UpVoteComment(
|
||||
commentId = commentId,
|
||||
feedback = true,
|
||||
),
|
||||
)
|
||||
}
|
||||
},
|
||||
onDownVote = {
|
||||
if (!isOnOtherInstance) {
|
||||
model.reduce(
|
||||
PostDetailMviModel.Intent.DownVoteComment(
|
||||
commentId = commentId,
|
||||
feedback = true,
|
||||
),
|
||||
)
|
||||
}
|
||||
},
|
||||
onSave = {
|
||||
if (!isOnOtherInstance) {
|
||||
model.reduce(
|
||||
PostDetailMviModel.Intent.SaveComment(
|
||||
commentId = commentId,
|
||||
feedback = true,
|
||||
),
|
||||
)
|
||||
}
|
||||
},
|
||||
onReply = {
|
||||
if (!isOnOtherInstance) {
|
||||
val screen = CreateCommentScreen(
|
||||
originalPost = statePost,
|
||||
originalComment = comment,
|
||||
)
|
||||
notificationCenter.addObserver(
|
||||
{
|
||||
model.reduce(PostDetailMviModel.Intent.Refresh)
|
||||
model.reduce(PostDetailMviModel.Intent.RefreshPost)
|
||||
},
|
||||
key,
|
||||
NotificationCenterContractKeys.CommentCreated
|
||||
)
|
||||
bottomSheetNavigator.show(screen)
|
||||
}
|
||||
},
|
||||
onOpenCreator = {
|
||||
val user = comment.creator
|
||||
if (user != null) {
|
||||
navigator?.push(
|
||||
UserDetailScreen(
|
||||
user = user,
|
||||
otherInstance = otherInstance,
|
||||
),
|
||||
)
|
||||
}
|
||||
},
|
||||
options = buildList {
|
||||
add(stringResource(MR.strings.post_action_see_raw))
|
||||
add(stringResource(MR.strings.post_action_report))
|
||||
if (comment.creator?.id == uiState.currentUserId) {
|
||||
add(stringResource(MR.strings.post_action_edit))
|
||||
add(stringResource(MR.strings.comment_action_delete))
|
||||
}
|
||||
},
|
||||
onOptionSelected = { optionId ->
|
||||
when (optionId) {
|
||||
3 -> model.reduce(
|
||||
PostDetailMviModel.Intent.DeleteComment(
|
||||
comment.id
|
||||
)
|
||||
)
|
||||
|
||||
2 -> {
|
||||
notificationCenter.addObserver(
|
||||
{
|
||||
model.reduce(PostDetailMviModel.Intent.Refresh)
|
||||
model.reduce(PostDetailMviModel.Intent.RefreshPost)
|
||||
},
|
||||
key,
|
||||
NotificationCenterContractKeys.CommentCreated
|
||||
)
|
||||
bottomSheetNavigator.show(
|
||||
CreateCommentScreen(
|
||||
editedComment = comment,
|
||||
)
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
1 -> {
|
||||
bottomSheetNavigator.show(
|
||||
CreateReportScreen(
|
||||
commentId = comment.id
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
else -> {
|
||||
rawContent = comment
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
Divider(
|
||||
modifier = Modifier.padding(vertical = Spacing.xxxs),
|
||||
thickness = 0.25.dp
|
||||
|
@ -43,7 +43,6 @@ class PostDetailViewModel(
|
||||
private var currentPage: Int = 1
|
||||
private var highlightCommentPath: String? = null
|
||||
private var commentWasHighlighted = false
|
||||
private var expandedTopLevelComments = mutableListOf<Int>()
|
||||
|
||||
init {
|
||||
notificationCenter.addObserver({
|
||||
@ -250,24 +249,18 @@ class PostDetailViewModel(
|
||||
sort = sort,
|
||||
)?.processCommentsToGetNestedOrder(
|
||||
ancestorId = null,
|
||||
)?.populateLoadMoreComments().let {
|
||||
)?.populateLoadMoreComments()?.let { list ->
|
||||
if (refreshing) {
|
||||
it
|
||||
list
|
||||
} else {
|
||||
it?.filter { c1 ->
|
||||
list.filter { c1 ->
|
||||
// prevents accidental duplication
|
||||
currentState.comments.none { c2 -> c1.id == c2.id }
|
||||
}
|
||||
}
|
||||
}?.let {
|
||||
if (autoExpandComments) {
|
||||
expandedTopLevelComments =
|
||||
it.filter { c -> c.depth == 0 }.map { c -> c.id }.toMutableList()
|
||||
}
|
||||
it
|
||||
}?.applyExpansionFilter(
|
||||
expandedTopLevelCommentIds = expandedTopLevelComments,
|
||||
)
|
||||
}?.map {
|
||||
it.copy(expanded = autoExpandComments)
|
||||
}
|
||||
|
||||
if (!itemList.isNullOrEmpty()) {
|
||||
currentPage++
|
||||
@ -322,13 +315,10 @@ class PostDetailViewModel(
|
||||
ancestorId = parentId.toString(),
|
||||
)?.filter {
|
||||
currentState.comments.none { c -> c.id == it.id }
|
||||
}?.let {
|
||||
if (autoExpandComments) {
|
||||
expandedTopLevelComments =
|
||||
it.filter { c -> c.depth == 0 }.map { c -> c.id }.toMutableList()
|
||||
}
|
||||
it
|
||||
}?.map {
|
||||
it.copy(expanded = autoExpandComments)
|
||||
}
|
||||
|
||||
val commentsToInsert = fetchResult.orEmpty()
|
||||
if (commentsToInsert.isEmpty()) {
|
||||
// abort and disable load more button
|
||||
@ -622,25 +612,20 @@ class PostDetailViewModel(
|
||||
}
|
||||
|
||||
private fun toggleExpanded(comment: CommentModel) {
|
||||
if (comment.depth > 0) {
|
||||
return
|
||||
}
|
||||
val id = comment.id
|
||||
if (expandedTopLevelComments.contains(id)) {
|
||||
expandedTopLevelComments -= id
|
||||
} else {
|
||||
expandedTopLevelComments += id
|
||||
}
|
||||
val commentId = comment.id
|
||||
mvi.updateState {
|
||||
val newComments = it.comments.applyExpansionFilter(
|
||||
expandedTopLevelCommentIds = expandedTopLevelComments,
|
||||
)
|
||||
val newComments = it.comments.map { comment ->
|
||||
if (comment.id == commentId) {
|
||||
comment.copy(expanded = !comment.expanded)
|
||||
} else {
|
||||
comment
|
||||
}
|
||||
}
|
||||
it.copy(comments = newComments)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private data class Node(
|
||||
val comment: CommentModel?,
|
||||
val children: MutableList<Node> = mutableListOf(),
|
||||
@ -705,17 +690,3 @@ private fun List<CommentModel>.processCommentsToGetNestedOrder(
|
||||
|
||||
return result.reversed().toList()
|
||||
}
|
||||
|
||||
private fun List<CommentModel>.applyExpansionFilter(
|
||||
expandedTopLevelCommentIds: List<Int>,
|
||||
): List<CommentModel> = map { comment ->
|
||||
val visible = comment.depth == 0 || expandedTopLevelCommentIds.any { e ->
|
||||
e == comment.path.split(".")[1].toInt()
|
||||
}
|
||||
val indicatorExpanded = when {
|
||||
comment.depth > 0 -> null
|
||||
(comment.comments ?: 0) == 0 -> null
|
||||
else -> expandedTopLevelCommentIds.contains(comment.id)
|
||||
}
|
||||
comment.copy(visible = visible, expanded = indicatorExpanded)
|
||||
}
|
@ -18,9 +18,7 @@ data class CommentModel(
|
||||
val comments: Int? = null,
|
||||
val path: String = "",
|
||||
@Transient
|
||||
val visible: Boolean = true,
|
||||
@Transient
|
||||
val expanded: Boolean? = null,
|
||||
val expanded: Boolean = true,
|
||||
@Transient
|
||||
val loadMoreButtonVisible: Boolean = false,
|
||||
) : JavaSerializable {
|
||||
|
@ -197,5 +197,5 @@
|
||||
<string name="settings_ui_font_family">Font UI</string>
|
||||
<string name="settings_ui_font_scale">Dimensione testo UI</string>
|
||||
<string name="settings_ui_theme">Tema interfaccia</string>
|
||||
<string name="settings_upvote_color">Colore voti positivo</string>
|
||||
<string name="settings_upvote_color">Colore voti positivi</string>
|
||||
</resources>
|
Loading…
x
Reference in New Issue
Block a user