From f8250b31d2b16fc9491f4acac9a8dd281f8eb230 Mon Sep 17 00:00:00 2001 From: Diego Beraldin Date: Sun, 29 Oct 2023 22:03:04 +0100 Subject: [PATCH] enhancement: text formatting and comment layout (#87) * enhancement: better selection and cursor handling in text formatting * enhancement: comment card spacing --- .../components/CollapsedCommentCard.kt | 2 +- .../core/commonui/components/CommentCard.kt | 10 +- .../commonui/components/TextFormattingBar.kt | 193 ++++++++++-------- .../commonui/postdetail/PostDetailScreen.kt | 1 - 4 files changed, 105 insertions(+), 101 deletions(-) diff --git a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/components/CollapsedCommentCard.kt b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/components/CollapsedCommentCard.kt index 476c7a27a..245e7020b 100644 --- a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/components/CollapsedCommentCard.kt +++ b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/components/CollapsedCommentCard.kt @@ -97,7 +97,7 @@ fun CollapsedCommentCard( } Box( modifier = Modifier - .padding(top = Spacing.xs) + .padding(top = Spacing.xxs) .width(barWidth) .height(commentHeight.toLocalDp()) .background(color = barColor) diff --git a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/components/CommentCard.kt b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/components/CommentCard.kt index 7fd3b112b..441f64061 100644 --- a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/components/CommentCard.kt +++ b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/components/CommentCard.kt @@ -15,7 +15,6 @@ 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.dp import androidx.compose.ui.unit.toSize import com.github.diegoberaldin.raccoonforlemmy.core.appearance.di.getThemeRepository @@ -78,7 +77,6 @@ fun CommentCard( } ) { CommunityAndCreatorInfo( - modifier = Modifier.padding(top = Spacing.xs), iconSize = 20.dp, creator = comment.creator.takeIf { !hideAuthor }, community = comment.community.takeIf { !hideCommunity }, @@ -117,18 +115,12 @@ fun CommentCard( if (!hideIndent) { Box( modifier = Modifier - .padding(top = Spacing.xs) + .padding(top = Spacing.xxs) .width(barWidth) .height(commentHeight.toLocalDp()) .background(color = barColor) ) } } - Box( - modifier = Modifier - .height(Dp.Hairline) - .fillMaxWidth() - .background(MaterialTheme.colorScheme.background) - ) } } diff --git a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/components/TextFormattingBar.kt b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/components/TextFormattingBar.kt index 7da7330b8..e3324da20 100644 --- a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/components/TextFormattingBar.kt +++ b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/components/TextFormattingBar.kt @@ -32,37 +32,32 @@ fun TextFormattingBar( Icon( modifier = Modifier.onClick { val selection = textFieldValue.selection - if (selection.length == 0) { - val newValue = textFieldValue.let { - it.copy( - text = it.text + "****", - selection = TextRange(it.text.length + 2), + val newValue = textFieldValue.let { + val newText = buildString { + append(it.text.substring(0, selection.start)) + append("**") + append( + it.text.substring( + selection.start, + selection.end + ) + ) + append("**") + append( + it.text.substring( + selection.end, + it.text.length + ) ) } - onTextFieldValueChanged(newValue) - } else { - val newValue = textFieldValue.let { - val newText = buildString { - append(it.text.substring(0, selection.start)) - append("**") - append( - it.text.substring( - selection.start, - selection.end - ) - ) - append("**") - append( - it.text.substring( - selection.end, - it.text.length - ) - ) - } - it.copy(text = newText) + val newSelection = if (selection.length == 0) { + TextRange(index = selection.start + 2) + } else { + TextRange(start = it.selection.start + 2, end = it.selection.end + 2) } - onTextFieldValueChanged(newValue) + it.copy(text = newText, selection = newSelection) } + onTextFieldValueChanged(newValue) }, imageVector = Icons.Default.FormatBold, contentDescription = null, @@ -70,37 +65,32 @@ fun TextFormattingBar( Icon( modifier = Modifier.onClick { val selection = textFieldValue.selection - if (selection.length == 0) { - val newValue = textFieldValue.let { - it.copy( - text = it.text + "**", - selection = TextRange(it.text.length + 1), + val newValue = textFieldValue.let { + val newText = buildString { + append(it.text.substring(0, selection.start)) + append("*") + append( + it.text.substring( + selection.start, + selection.end + ) + ) + append("*") + append( + it.text.substring( + selection.end, + it.text.length + ) ) } - onTextFieldValueChanged(newValue) - } else { - val newValue = textFieldValue.let { - val newText = buildString { - append(it.text.substring(0, selection.start)) - append("*") - append( - it.text.substring( - selection.start, - selection.end - ) - ) - append("*") - append( - it.text.substring( - selection.end, - it.text.length - ) - ) - } - it.copy(text = newText) + val newSelection = if (selection.length == 0) { + TextRange(index = selection.start + 1) + } else { + TextRange(start = it.selection.start + 1, end = it.selection.end + 1) } - onTextFieldValueChanged(newValue) + it.copy(text = newText, selection = newSelection) } + onTextFieldValueChanged(newValue) }, imageVector = Icons.Default.FormatItalic, contentDescription = null, @@ -108,37 +98,32 @@ fun TextFormattingBar( Icon( modifier = Modifier.onClick { val selection = textFieldValue.selection - if (selection.length == 0) { - val newValue = textFieldValue.let { - it.copy( - text = it.text + "~~~~", - selection = TextRange(it.text.length + 2), + val newValue = textFieldValue.let { + val newText = buildString { + append(it.text.substring(0, selection.start)) + append("~~") + append( + it.text.substring( + selection.start, + selection.end + ) + ) + append("~~") + append( + it.text.substring( + selection.end, + it.text.length + ) ) } - onTextFieldValueChanged(newValue) - } else { - val newValue = textFieldValue.let { - val newText = buildString { - append(it.text.substring(0, selection.start)) - append("~~") - append( - it.text.substring( - selection.start, - selection.end - ) - ) - append("~~") - append( - it.text.substring( - selection.end, - it.text.length - ) - ) - } - it.copy(text = newText) + val newSelection = if (selection.length == 0) { + TextRange(index = selection.start + 2) + } else { + TextRange(start = it.selection.start + 2, end = it.selection.end + 2) } - onTextFieldValueChanged(newValue) + it.copy(text = newText, selection = newSelection) } + onTextFieldValueChanged(newValue) }, imageVector = Icons.Default.FormatStrikethrough, contentDescription = null, @@ -153,10 +138,18 @@ fun TextFormattingBar( Icon( modifier = Modifier.onClick { val newValue = textFieldValue.let { - it.copy( - text = it.text + "[](url)", - selection = TextRange(it.text.length + 1), - ) + val selection = it.selection + val newText = buildString { + append(it.text.substring(0, selection.start)) + append(" [](url)") + append( + it.text.substring( + selection.end, + it.text.length + ) + ) + } + it.copy(text = newText, selection = TextRange(index = selection.start + 2)) } onTextFieldValueChanged(newValue) }, @@ -166,10 +159,30 @@ fun TextFormattingBar( Icon( modifier = Modifier.onClick { val newValue = textFieldValue.let { - it.copy( - text = it.text + "``", - selection = TextRange(it.text.length + 1), - ) + val selection = it.selection + val newText = buildString { + append(it.text.substring(0, selection.start)) + append("`") + append( + it.text.substring( + selection.start, + selection.end + ) + ) + append("`") + append( + it.text.substring( + selection.end, + it.text.length + ) + ) + } + val newSelection = if (selection.length == 0) { + TextRange(index = selection.start + 1) + } else { + TextRange(start = it.selection.start + 1, end = it.selection.end + 1) + } + it.copy(text = newText, selection = newSelection) } onTextFieldValueChanged(newValue) }, @@ -181,7 +194,7 @@ fun TextFormattingBar( val newValue = textFieldValue.let { it.copy( text = it.text + "\n> ", - selection = TextRange(it.text.length + 3), + selection = TextRange(index = it.text.length + 3), ) } onTextFieldValueChanged(newValue) diff --git a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/postdetail/PostDetailScreen.kt b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/postdetail/PostDetailScreen.kt index acc5e5dff..c48f3062e 100644 --- a/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/postdetail/PostDetailScreen.kt +++ b/core-commonui/src/commonMain/kotlin/com/github/diegoberaldin/raccoonforlemmy/core/commonui/postdetail/PostDetailScreen.kt @@ -666,7 +666,6 @@ class PostDetailScreen( } else { CollapsedCommentCard( comment = comment, - modifier = Modifier.padding(vertical = Spacing.xs), onToggleExpanded = { model.reduce( PostDetailMviModel.Intent.ToggleExpandComment(