Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Send Text Formatting message #1857

Merged
merged 16 commits into from
Jun 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,17 @@ fun WireSecondaryIconButton(
state: WireButtonState = WireButtonState.Default,
colors: WireButtonColors = wireSecondaryButtonColors(),
clickBlockParams: ClickBlockParams = ClickBlockParams(),
modifier: Modifier = Modifier
modifier: Modifier = Modifier,
fillMaxWidth: Boolean = false
) {
WireSecondaryButton(
onClick = onButtonClicked,
leadingIcon = {
Icon(
painter = painterResource(id = iconResource),
contentDescription = stringResource(contentDescription),
modifier = Modifier.size(iconSize)
modifier = Modifier
.size(iconSize)
)
},
shape = shape,
Expand All @@ -72,7 +74,7 @@ fun WireSecondaryIconButton(
state = state,
colors = colors,
clickBlockParams = clickBlockParams,
fillMaxWidth = false,
fillMaxWidth = fillMaxWidth,
modifier = modifier
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,12 @@ fun MessageComposeActionsBox(
onPingClicked: () -> Unit,
onSelfDeletionOptionButtonClicked: () -> Unit,
showSelfDeletingOption: Boolean,
modifier: Modifier = Modifier,
onRichTextEditingButtonClicked: () -> Unit,
onCloseRichTextEditingButtonClicked: () -> Unit,
onRichTextEditingHeaderButtonClicked: () -> Unit,
onRichTextEditingBoldButtonClicked: () -> Unit,
onRichTextEditingItalicButtonClicked: () -> Unit,
modifier: Modifier = Modifier
) {
Column(modifier.wrapContentSize()) {
Divider(color = MaterialTheme.wireColorScheme.outline)
Expand All @@ -85,7 +90,13 @@ fun MessageComposeActionsBox(
onAdditionalOptionButtonClicked,
onPingClicked,
onSelfDeletionOptionButtonClicked,
showSelfDeletingOption
showSelfDeletingOption,
state.isRichTextFormattingOptionsDisplayed,
onRichTextEditingButtonClicked,
onCloseRichTextEditingButtonClicked,
onRichTextEditingHeaderButtonClicked,
onRichTextEditingBoldButtonClicked,
onRichTextEditingItalicButtonClicked
)
}
}
Expand All @@ -105,39 +116,56 @@ private fun MessageComposeActions(
onPingClicked: () -> Unit,
onSelfDeletionOptionButtonClicked: () -> Unit,
showSelfDeletingOption: Boolean,
richTextEditingDisplayed: Boolean,
onRichTextEditingButtonClicked: () -> Unit,
onCloseRichTextEditingButtonClicked: () -> Unit,
onRichTextEditingHeaderButtonClicked: () -> Unit,
onRichTextEditingBoldButtonClicked: () -> Unit,
onRichTextEditingItalicButtonClicked: () -> Unit
) {
val localFeatureVisibilityFlags = LocalFeatureVisibilityFlags.current

Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceEvenly,
horizontalArrangement = if (richTextEditingDisplayed) Arrangement.SpaceBetween else Arrangement.SpaceEvenly,
modifier = Modifier
.fillMaxWidth()
.height(dimensions().spacing56x)
) {
with(localFeatureVisibilityFlags) {
if (!isEditMessage) AdditionalOptionButton(
isSelected = attachmentOptionsDisplayed,
isEnabled = isFileSharingEnabled,
onClick = onAdditionalOptionButtonClicked
)
if (RichTextIcon) RichTextEditingAction()
if (!isEditMessage && EmojiIcon) AddEmojiAction()
if (!isEditMessage && GifIcon) AddGifAction()
if (!isEditMessage && showSelfDeletingOption) SelfDeletingMessageAction(
isSelected = selfDeletingOptionSelected,
onButtonClicked = onSelfDeletionOptionButtonClicked
if (richTextEditingDisplayed) {
RichTextOptions(
onRichTextHeaderButtonClicked = onRichTextEditingHeaderButtonClicked,
onRichTextBoldButtonClicked = onRichTextEditingBoldButtonClicked,
onRichTextItalicButtonClicked = onRichTextEditingItalicButtonClicked,
onCloseRichTextEditingButtonClicked = onCloseRichTextEditingButtonClicked
)
if (!isEditMessage && PingIcon) PingAction(onPingClicked = onPingClicked)
AddMentionAction(isMentionsSelected, startMention)
} else {
with(localFeatureVisibilityFlags) {
if (!isEditMessage) AdditionalOptionButton(
isSelected = attachmentOptionsDisplayed,
isEnabled = isFileSharingEnabled,
onClick = onAdditionalOptionButtonClicked
)
if (RichTextIcon) RichTextEditingAction(
onButtonClicked = onRichTextEditingButtonClicked
)
if (!isEditMessage && EmojiIcon) AddEmojiAction()
if (!isEditMessage && GifIcon) AddGifAction()
if (!isEditMessage && showSelfDeletingOption) SelfDeletingMessageAction(
isSelected = selfDeletingOptionSelected,
onButtonClicked = onSelfDeletionOptionButtonClicked
)
if (!isEditMessage && PingIcon) PingAction(onPingClicked = onPingClicked)
AddMentionAction(isMentionsSelected, startMention)
}
}
}
}

@Composable
private fun RichTextEditingAction() {
private fun RichTextEditingAction(onButtonClicked: () -> Unit) {
WireSecondaryIconButton(
onButtonClicked = {},
onButtonClicked = onButtonClicked,
clickBlockParams = ClickBlockParams(blockWhenSyncing = true, blockWhenConnecting = true),
iconResource = R.drawable.ic_rich_text,
contentDescription = R.string.content_description_conversation_enable_rich_text_mode
Expand Down Expand Up @@ -210,10 +238,29 @@ fun PreviewMessageActionsBox() {
.height(dimensions().spacing56x)
) {
AdditionalOptionButton(isSelected = false, isEnabled = true, onClick = {})
RichTextEditingAction()
RichTextEditingAction(onButtonClicked = {})
AddEmojiAction()
AddGifAction()
AddMentionAction(isSelected = false, addMentionAction = {})
PingAction {}
}
}

@Preview
@Composable
fun PreviewRichTextOptions() {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceEvenly,
modifier = Modifier
.fillMaxWidth()
.height(dimensions().spacing56x)
) {
RichTextOptions(
onRichTextHeaderButtonClicked = {},
onRichTextBoldButtonClicked = {},
onRichTextItalicButtonClicked = {},
onCloseRichTextEditingButtonClicked = {}
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.input.getSelectedText
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.wire.android.R
Expand All @@ -65,6 +67,7 @@ import com.wire.android.ui.home.messagecomposer.state.MessageComposeInputType
import com.wire.android.ui.home.messagecomposer.state.MessageComposerState
import com.wire.android.ui.home.newconversation.model.Contact
import com.wire.android.ui.theme.wireColorScheme
import com.wire.android.util.EMPTY
import com.wire.kalium.logic.feature.conversation.InteractionAvailability
import com.wire.kalium.logic.feature.conversation.SecurityClassificationType

Expand Down Expand Up @@ -277,7 +280,33 @@ private fun MessageComposer(
},
onEditSaveButtonClicked = onEditSaveButtonClicked,
onEditCancelButtonClicked = messageComposerState::closeEditToInactive,
onSelfDeletionOptionButtonClicked = onShowSelfDeletionOption
onSelfDeletionOptionButtonClicked = onShowSelfDeletionOption,
onRichTextEditingButtonClicked = {
messageComposerState.toActive()
messageComposerState.showRichTextEditingOptions()
},
onCloseRichTextEditingButtonClicked = {
messageComposerState.hideRichTextEditingOptions()
},
toRichTextEditingHeader = {
addOrRemoveMessageMarkdown(
messageComposerState = messageComposerState,
markdown = RICH_TEXT_MARKDOWN_HEADER,
isHeader = true
)
},
toRichTextEditingBold = {
addOrRemoveMessageMarkdown(
messageComposerState = messageComposerState,
markdown = RICH_TEXT_MARKDOWN_BOLD
)
},
toRichTextEditingItalic = {
addOrRemoveMessageMarkdown(
messageComposerState = messageComposerState,
markdown = RICH_TEXT_MARKDOWN_ITALIC
)
}
)
}
)
Expand Down Expand Up @@ -360,6 +389,61 @@ private fun MembersMentionList(
}
}

private fun addOrRemoveMessageMarkdown(
messageComposerState: MessageComposerState,
markdown: String,
isHeader: Boolean = false
) {
val originalValue = messageComposerState
.messageComposeInputState
.messageText

val range = originalValue.selection
val selectedText = originalValue.getSelectedText()
val stringBuilder = StringBuilder(originalValue.annotatedString)
val markdownLength = markdown.length
val markdownLengthComplete =
if (isHeader) markdownLength else (markdownLength * RICH_TEXT_MARKDOWN_MULTIPLIER)

val rangeEnd = if (selectedText.contains(markdown)) {
// Remove Markdown
stringBuilder.replace(
range.start,
range.end,
selectedText.toString().replace(markdown, String.EMPTY)
)

range.end - markdownLengthComplete
} else {
// Add Markdown
stringBuilder.insert(range.start, markdown)
if (isHeader.not()) stringBuilder.insert(range.end + markdownLength, markdown)

range.end + markdownLengthComplete
}

val (selectionStart, selectionEnd) = if (range.start == range.end) {
if (isHeader) Pair(rangeEnd, rangeEnd)
else {
val middleMarkdownRange = rangeEnd - markdownLength
Pair(middleMarkdownRange, middleMarkdownRange)
}
} else {
Pair(range.start, rangeEnd)
}

// Set new text
messageComposerState.setMessageTextValue(
text = TextFieldValue(
text = stringBuilder.toString(),
selection = TextRange(
start = selectionStart,
end = selectionEnd
)
)
)
}

sealed class KeyboardHeight(open val height: Dp) {
object NotKnown : KeyboardHeight(DEFAULT_KEYBOARD_TOP_SCREEN_OFFSET)
data class Known(override val height: Dp) : KeyboardHeight(height)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,12 @@ private fun EnabledMessageComposerInput(
modifier = Modifier.background(colorsScheme().messageComposerBackgroundColor),
onPingClicked = actions.onPingClicked,
onSelfDeletionOptionButtonClicked = actions.onSelfDeletionOptionButtonClicked,
showSelfDeletingOption = showSelfDeletingOption
showSelfDeletingOption = showSelfDeletingOption,
onRichTextEditingButtonClicked = actions.onRichTextEditingButtonClicked,
onCloseRichTextEditingButtonClicked = actions.onCloseRichTextEditingButtonClicked,
onRichTextEditingHeaderButtonClicked = actions.toRichTextEditingHeader,
onRichTextEditingBoldButtonClicked = actions.toRichTextEditingBold,
onRichTextEditingItalicButtonClicked = actions.toRichTextEditingItalic
)
}
if (membersToMention.isNotEmpty() && messageComposeInputState.isExpanded) {
Expand Down Expand Up @@ -275,7 +280,12 @@ data class MessageComposerInputActions(
val onEditCancelButtonClicked: () -> Unit = {},
val onPingClicked: () -> Unit = {},
val onSelfDeletionOptionButtonClicked: () -> Unit = { },
val onSendSelfDeletingMessageClicked: () -> Unit = {}
val onSendSelfDeletingMessageClicked: () -> Unit = {},
val onRichTextEditingButtonClicked: () -> Unit = {},
val onCloseRichTextEditingButtonClicked: () -> Unit = {},
val toRichTextEditingHeader: () -> Unit = {},
val toRichTextEditingBold: () -> Unit = {},
val toRichTextEditingItalic: () -> Unit = {}
)

@Composable
Expand Down Expand Up @@ -314,5 +324,12 @@ fun PreviewEnabledMessageComposerInputActiveExpanded() {
@Preview
@Composable
fun PreviewEnabledMessageComposerInputActiveEdit() {
generatePreviewWithState(MessageComposeInputState.Active(type = MessageComposeInputType.EditMessage("", "")))
generatePreviewWithState(
MessageComposeInputState.Active(
type = MessageComposeInputType.EditMessage(
"",
""
)
)
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import com.wire.android.ui.home.messagecomposer.state.MessageComposeInputType
import com.wire.android.ui.home.messagecomposer.state.SelfDeletionDuration
import com.wire.android.ui.theme.wireTypography

@Suppress("ComplexMethod")
@OptIn(ExperimentalAnimationApi::class)
@Composable
fun MessageComposerInputRow(
Expand Down
Loading