Composer compiling and running
This commit is contained in:
parent
848f665509
commit
04d2e206ee
69 changed files with 6463 additions and 17 deletions
4
libraries/textcomposer/src/main/AndroidManifest.xml
Normal file
4
libraries/textcomposer/src/main/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
</manifest>
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 2022 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.x.textcomposer
|
||||
|
||||
import android.net.Uri
|
||||
import android.text.Editable
|
||||
import android.widget.EditText
|
||||
import android.widget.ImageButton
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
|
||||
// Imported from Element Android
|
||||
interface MessageComposerView {
|
||||
|
||||
val text: Editable?
|
||||
val formattedText: String?
|
||||
val editText: EditText
|
||||
val emojiButton: ImageButton?
|
||||
val sendButton: ImageButton
|
||||
val attachmentButton: ImageButton
|
||||
val fullScreenButton: ImageButton?
|
||||
val composerRelatedMessageTitle: TextView
|
||||
val composerRelatedMessageContent: TextView
|
||||
val composerRelatedMessageImage: ImageView
|
||||
val composerRelatedMessageActionIcon: ImageView
|
||||
val composerRelatedMessageAvatar: ImageView
|
||||
|
||||
var callback: Callback?
|
||||
|
||||
var isVisible: Boolean
|
||||
|
||||
fun collapse(animate: Boolean = true, transitionComplete: (() -> Unit)? = null)
|
||||
fun expand(animate: Boolean = true, transitionComplete: (() -> Unit)? = null)
|
||||
fun setTextIfDifferent(text: CharSequence?): Boolean
|
||||
fun replaceFormattedContent(text: CharSequence)
|
||||
fun toggleFullScreen(newValue: Boolean)
|
||||
|
||||
fun setInvisible(isInvisible: Boolean)
|
||||
}
|
||||
|
||||
interface Callback {
|
||||
// From ComposerEditText.Callback
|
||||
fun onRichContentSelected(contentUri: Uri): Boolean
|
||||
|
||||
// From ComposerEditText.Callback
|
||||
fun onTextChanged(text: CharSequence)
|
||||
|
||||
fun onCloseRelatedMessage()
|
||||
fun onSendMessage(text: CharSequence)
|
||||
fun onAddAttachment()
|
||||
fun onExpandOrCompactChange()
|
||||
fun onFullScreenModeChanged()
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,324 @@
|
|||
/*
|
||||
* Copyright (c) 2022 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package io.element.android.x.textcomposer
|
||||
|
||||
import android.content.Context
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.util.AttributeSet
|
||||
import android.view.LayoutInflater
|
||||
import android.widget.EditText
|
||||
import android.widget.ImageButton
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.constraintlayout.widget.ConstraintLayout
|
||||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
import androidx.core.text.toSpannable
|
||||
import androidx.core.view.isInvisible
|
||||
import androidx.core.view.isVisible
|
||||
import io.element.android.wysiwyg.EditorEditText
|
||||
import io.element.android.wysiwyg.inputhandlers.models.InlineFormat
|
||||
import io.element.android.x.element.resources.R as ElementR
|
||||
import io.element.android.x.textcomposer.databinding.ComposerRichTextLayoutBinding
|
||||
import io.element.android.x.textcomposer.databinding.ViewRichTextMenuButtonBinding
|
||||
import io.element.android.x.textcomposer.tools.animateLayoutChange
|
||||
import io.element.android.x.textcomposer.tools.setTextIfDifferent
|
||||
import uniffi.wysiwyg_composer.ComposerAction
|
||||
import uniffi.wysiwyg_composer.MenuState
|
||||
|
||||
// Imported from Element Android
|
||||
class RichTextComposerLayout @JvmOverloads constructor(
|
||||
context: Context,
|
||||
attrs: AttributeSet? = null,
|
||||
defStyleAttr: Int = 0
|
||||
) : ConstraintLayout(context, attrs, defStyleAttr), MessageComposerView {
|
||||
|
||||
private val views: ComposerRichTextLayoutBinding
|
||||
|
||||
override var callback: Callback? = null
|
||||
|
||||
private var currentConstraintSetId: Int = -1
|
||||
private val animationDuration = 100L
|
||||
private val maxEditTextLinesWhenCollapsed = 12
|
||||
|
||||
private val isFullScreen: Boolean get() = currentConstraintSetId == R.layout.composer_rich_text_layout_constraint_set_fullscreen
|
||||
|
||||
var isTextFormattingEnabled = true
|
||||
set(value) {
|
||||
if (field == value) return
|
||||
syncEditTexts()
|
||||
field = value
|
||||
updateEditTextVisibility()
|
||||
}
|
||||
|
||||
override val text: Editable?
|
||||
get() = editText.text
|
||||
override val formattedText: String?
|
||||
get() = (editText as? EditorEditText)?.getHtmlOutput()
|
||||
override val editText: EditText
|
||||
get() = if (isTextFormattingEnabled) {
|
||||
views.richTextComposerEditText
|
||||
} else {
|
||||
views.plainTextComposerEditText
|
||||
}
|
||||
override val emojiButton: ImageButton?
|
||||
get() = null
|
||||
override val sendButton: ImageButton
|
||||
get() = views.sendButton
|
||||
override val attachmentButton: ImageButton
|
||||
get() = views.attachmentButton
|
||||
override val fullScreenButton: ImageButton?
|
||||
get() = views.composerFullScreenButton
|
||||
override val composerRelatedMessageActionIcon: ImageView
|
||||
get() = views.composerRelatedMessageActionIcon
|
||||
override val composerRelatedMessageAvatar: ImageView
|
||||
get() = views.composerRelatedMessageAvatar
|
||||
override val composerRelatedMessageContent: TextView
|
||||
get() = views.composerRelatedMessageContent
|
||||
override val composerRelatedMessageImage: ImageView
|
||||
get() = views.composerRelatedMessageImage
|
||||
override val composerRelatedMessageTitle: TextView
|
||||
get() = views.composerRelatedMessageTitle
|
||||
override var isVisible: Boolean
|
||||
get() = views.root.isVisible
|
||||
set(value) {
|
||||
views.root.isVisible = value
|
||||
}
|
||||
|
||||
init {
|
||||
inflate(context, R.layout.composer_rich_text_layout, this)
|
||||
views = ComposerRichTextLayoutBinding.bind(this)
|
||||
|
||||
collapse(false)
|
||||
|
||||
views.richTextComposerEditText.addTextChangedListener(
|
||||
TextChangeListener({ callback?.onTextChanged(it) }, { updateTextFieldBorder() })
|
||||
)
|
||||
views.plainTextComposerEditText.addTextChangedListener(
|
||||
TextChangeListener({ callback?.onTextChanged(it) }, { updateTextFieldBorder() })
|
||||
)
|
||||
|
||||
views.composerRelatedMessageCloseButton.setOnClickListener {
|
||||
collapse()
|
||||
callback?.onCloseRelatedMessage()
|
||||
}
|
||||
|
||||
views.sendButton.setOnClickListener {
|
||||
val textMessage = text?.toSpannable() ?: ""
|
||||
callback?.onSendMessage(textMessage)
|
||||
}
|
||||
|
||||
views.attachmentButton.setOnClickListener {
|
||||
callback?.onAddAttachment()
|
||||
}
|
||||
|
||||
views.composerFullScreenButton.setOnClickListener {
|
||||
callback?.onFullScreenModeChanged()
|
||||
}
|
||||
|
||||
setupRichTextMenu()
|
||||
}
|
||||
|
||||
private fun setupRichTextMenu() {
|
||||
addRichTextMenuItem(
|
||||
ElementR.drawable.ic_composer_bold,
|
||||
ElementR.string.rich_text_editor_format_bold,
|
||||
ComposerAction.Bold
|
||||
) {
|
||||
views.richTextComposerEditText.toggleInlineFormat(InlineFormat.Bold)
|
||||
}
|
||||
addRichTextMenuItem(
|
||||
ElementR.drawable.ic_composer_italic,
|
||||
ElementR.string.rich_text_editor_format_italic,
|
||||
ComposerAction.Italic
|
||||
) {
|
||||
views.richTextComposerEditText.toggleInlineFormat(InlineFormat.Italic)
|
||||
}
|
||||
addRichTextMenuItem(
|
||||
ElementR.drawable.ic_composer_underlined,
|
||||
ElementR.string.rich_text_editor_format_underline,
|
||||
ComposerAction.Underline
|
||||
) {
|
||||
views.richTextComposerEditText.toggleInlineFormat(InlineFormat.Underline)
|
||||
}
|
||||
addRichTextMenuItem(
|
||||
ElementR.drawable.ic_composer_strikethrough,
|
||||
ElementR.string.rich_text_editor_format_strikethrough,
|
||||
ComposerAction.StrikeThrough
|
||||
) {
|
||||
views.richTextComposerEditText.toggleInlineFormat(InlineFormat.StrikeThrough)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAttachedToWindow() {
|
||||
super.onAttachedToWindow()
|
||||
|
||||
views.richTextComposerEditText.menuStateChangedListener =
|
||||
EditorEditText.OnMenuStateChangedListener { state ->
|
||||
if (state is MenuState.Update) {
|
||||
updateMenuStateFor(ComposerAction.Bold, state)
|
||||
updateMenuStateFor(ComposerAction.Italic, state)
|
||||
updateMenuStateFor(ComposerAction.Underline, state)
|
||||
updateMenuStateFor(ComposerAction.StrikeThrough, state)
|
||||
}
|
||||
}
|
||||
|
||||
updateEditTextVisibility()
|
||||
}
|
||||
|
||||
private fun updateEditTextVisibility() {
|
||||
views.richTextComposerEditText.isVisible = isTextFormattingEnabled
|
||||
views.richTextMenu.isVisible = isTextFormattingEnabled
|
||||
views.plainTextComposerEditText.isVisible = !isTextFormattingEnabled
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the non-active input with the contents of the active input.
|
||||
*/
|
||||
private fun syncEditTexts() =
|
||||
if (isTextFormattingEnabled) {
|
||||
views.plainTextComposerEditText.setText(views.richTextComposerEditText.getPlainText())
|
||||
} else {
|
||||
views.richTextComposerEditText.setText(views.plainTextComposerEditText.text.toString())
|
||||
}
|
||||
|
||||
private fun addRichTextMenuItem(
|
||||
@DrawableRes iconId: Int,
|
||||
@StringRes description: Int,
|
||||
action: ComposerAction,
|
||||
onClick: () -> Unit
|
||||
) {
|
||||
val inflater = LayoutInflater.from(context)
|
||||
val button = ViewRichTextMenuButtonBinding.inflate(inflater, views.richTextMenu, true)
|
||||
button.root.tag = action
|
||||
with(button.root) {
|
||||
contentDescription = resources.getString(description)
|
||||
setImageResource(iconId)
|
||||
setOnClickListener {
|
||||
onClick()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateMenuStateFor(action: ComposerAction, menuState: MenuState.Update) {
|
||||
val button = findViewWithTag<ImageButton>(action) ?: return
|
||||
button.isEnabled = !menuState.disabledActions.contains(action)
|
||||
button.isSelected = menuState.reversedActions.contains(action)
|
||||
}
|
||||
|
||||
private fun updateTextFieldBorder() {
|
||||
val isExpanded = editText.editableText.lines().count() > 1
|
||||
val borderResource = if (isExpanded || isFullScreen) {
|
||||
ElementR.drawable.bg_composer_rich_edit_text_expanded
|
||||
} else {
|
||||
ElementR.drawable.bg_composer_rich_edit_text_single_line
|
||||
}
|
||||
views.composerEditTextOuterBorder.setBackgroundResource(borderResource)
|
||||
}
|
||||
|
||||
override fun replaceFormattedContent(text: CharSequence) {
|
||||
views.richTextComposerEditText.setHtml(text.toString())
|
||||
}
|
||||
|
||||
override fun collapse(animate: Boolean, transitionComplete: (() -> Unit)?) {
|
||||
if (currentConstraintSetId == R.layout.composer_rich_text_layout_constraint_set_compact) {
|
||||
// ignore we good
|
||||
return
|
||||
}
|
||||
currentConstraintSetId = R.layout.composer_rich_text_layout_constraint_set_compact
|
||||
applyNewConstraintSet(animate, transitionComplete)
|
||||
updateEditTextVisibility()
|
||||
}
|
||||
|
||||
override fun expand(animate: Boolean, transitionComplete: (() -> Unit)?) {
|
||||
if (currentConstraintSetId == R.layout.composer_rich_text_layout_constraint_set_expanded) {
|
||||
// ignore we good
|
||||
return
|
||||
}
|
||||
currentConstraintSetId = R.layout.composer_rich_text_layout_constraint_set_expanded
|
||||
applyNewConstraintSet(animate, transitionComplete)
|
||||
updateEditTextVisibility()
|
||||
}
|
||||
|
||||
override fun setTextIfDifferent(text: CharSequence?): Boolean {
|
||||
return editText.setTextIfDifferent(text)
|
||||
}
|
||||
|
||||
override fun toggleFullScreen(newValue: Boolean) {
|
||||
val constraintSetId =
|
||||
if (newValue) R.layout.composer_rich_text_layout_constraint_set_fullscreen else currentConstraintSetId
|
||||
ConstraintSet().also {
|
||||
it.clone(context, constraintSetId)
|
||||
it.applyTo(this)
|
||||
}
|
||||
|
||||
updateTextFieldBorder()
|
||||
updateEditTextVisibility()
|
||||
|
||||
updateEditTextFullScreenState(views.richTextComposerEditText, newValue)
|
||||
updateEditTextFullScreenState(views.plainTextComposerEditText, newValue)
|
||||
}
|
||||
|
||||
private fun updateEditTextFullScreenState(editText: EditText, isFullScreen: Boolean) {
|
||||
if (isFullScreen) {
|
||||
editText.maxLines = Int.MAX_VALUE
|
||||
// This is a workaround to fix incorrect scroll position when maximised
|
||||
post { editText.requestLayout() }
|
||||
} else {
|
||||
editText.maxLines = maxEditTextLinesWhenCollapsed
|
||||
}
|
||||
}
|
||||
|
||||
private fun applyNewConstraintSet(animate: Boolean, transitionComplete: (() -> Unit)?) {
|
||||
// val wasSendButtonInvisible = views.sendButton.isInvisible
|
||||
if (animate) {
|
||||
animateLayoutChange(animationDuration, transitionComplete)
|
||||
}
|
||||
ConstraintSet().also {
|
||||
it.clone(context, currentConstraintSetId)
|
||||
it.applyTo(this)
|
||||
}
|
||||
|
||||
// Might be updated by view state just after, but avoid blinks
|
||||
// views.sendButton.isInvisible = wasSendButtonInvisible
|
||||
}
|
||||
|
||||
override fun setInvisible(isInvisible: Boolean) {
|
||||
this.isInvisible = isInvisible
|
||||
}
|
||||
|
||||
private class TextChangeListener(
|
||||
private val onTextChanged: (s: Editable) -> Unit,
|
||||
private val onExpandedChanged: (isExpanded: Boolean) -> Unit,
|
||||
) : TextWatcher {
|
||||
private var previousTextWasExpanded = false
|
||||
|
||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
|
||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}
|
||||
override fun afterTextChanged(s: Editable) {
|
||||
onTextChanged.invoke(s)
|
||||
|
||||
val isExpanded = s.lines().count() > 1
|
||||
if (previousTextWasExpanded != isExpanded) {
|
||||
onExpandedChanged(isExpanded)
|
||||
}
|
||||
previousTextWasExpanded = isExpanded
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
package io.element.android.x.textcomposer
|
||||
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.viewinterop.AndroidView
|
||||
import androidx.core.view.isVisible
|
||||
import io.element.android.x.element.resources.R as ElementR
|
||||
|
||||
@Composable
|
||||
fun TextComposer(
|
||||
callback: Callback,
|
||||
height: Dp,
|
||||
){
|
||||
AndroidView(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(height),
|
||||
factory = { context ->
|
||||
RichTextComposerLayout(context).apply {
|
||||
// Sets up listeners for View -> Compose communication
|
||||
this.callback = callback
|
||||
val messageComposerView = (this as MessageComposerView)
|
||||
setupComposer(messageComposerView)
|
||||
}
|
||||
},
|
||||
update = { view ->
|
||||
// View's been inflated or state read in this block has been updated
|
||||
// Add logic here if necessary
|
||||
|
||||
// As selectedItem is read here, AndroidView will recompose
|
||||
// whenever the state changes
|
||||
// Example of Compose -> View communication
|
||||
val messageComposerView = (view as MessageComposerView)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun setupComposer(messageComposerView: MessageComposerView) {
|
||||
messageComposerView.editText.setHint(ElementR.string.room_message_placeholder)
|
||||
messageComposerView.emojiButton?.isVisible = true
|
||||
messageComposerView.sendButton.isVisible = true
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
package io.element.android.x.textcomposer.tools
|
||||
|
||||
import android.text.Spanned
|
||||
import android.widget.EditText
|
||||
|
||||
fun EditText.setTextIfDifferent(newText: CharSequence?): Boolean {
|
||||
if (!isTextDifferent(newText, text)) {
|
||||
// Previous text is the same. No op
|
||||
return false
|
||||
}
|
||||
setText(newText)
|
||||
// Since the text changed we move the cursor to the end of the new text.
|
||||
// This allows us to fill in text programmatically with a different value,
|
||||
// but if the user is typing and the view is rebound we won't lose their cursor position.
|
||||
setSelection(newText?.length ?: 0)
|
||||
return true
|
||||
}
|
||||
|
||||
private fun isTextDifferent(str1: CharSequence?, str2: CharSequence?): Boolean {
|
||||
if (str1 === str2) {
|
||||
return false
|
||||
}
|
||||
if (str1 == null || str2 == null) {
|
||||
return true
|
||||
}
|
||||
val length = str1.length
|
||||
if (length != str2.length) {
|
||||
return true
|
||||
}
|
||||
if (str1 is Spanned) {
|
||||
return str1 != str2
|
||||
}
|
||||
for (i in 0 until length) {
|
||||
if (str1[i] != str2[i]) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package io.element.android.x.textcomposer.tools
|
||||
|
||||
import androidx.transition.Transition
|
||||
|
||||
open class SimpleTransitionListener : Transition.TransitionListener {
|
||||
override fun onTransitionEnd(transition: Transition) {
|
||||
// No op
|
||||
}
|
||||
|
||||
override fun onTransitionResume(transition: Transition) {
|
||||
// No op
|
||||
}
|
||||
|
||||
override fun onTransitionPause(transition: Transition) {
|
||||
// No op
|
||||
}
|
||||
|
||||
override fun onTransitionCancel(transition: Transition) {
|
||||
// No op
|
||||
}
|
||||
|
||||
override fun onTransitionStart(transition: Transition) {
|
||||
// No op
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
package io.element.android.x.textcomposer.tools
|
||||
|
||||
import android.view.ViewGroup
|
||||
import androidx.transition.*
|
||||
|
||||
fun ViewGroup.animateLayoutChange(animationDuration: Long, transitionComplete: (() -> Unit)? = null) {
|
||||
val transition = TransitionSet().apply {
|
||||
ordering = TransitionSet.ORDERING_SEQUENTIAL
|
||||
addTransition(ChangeBounds())
|
||||
addTransition(Fade(Fade.IN))
|
||||
duration = animationDuration
|
||||
addListener(object : SimpleTransitionListener() {
|
||||
override fun onTransitionEnd(transition: Transition) {
|
||||
transitionComplete?.invoke()
|
||||
}
|
||||
})
|
||||
}
|
||||
TransitionManager.beginDelayedTransition((parent as? ViewGroup ?: this), transition)
|
||||
}
|
||||
|
|
@ -0,0 +1,184 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:constraintSet="@layout/composer_rich_text_layout_constraint_set_compact"
|
||||
tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">
|
||||
|
||||
<!-- ========================
|
||||
/!\ Constraints for this layout are defined in external layout files that are used as constraint set for animation.
|
||||
/!\ These 3 files must be modified to stay coherent!
|
||||
======================== -->
|
||||
<View
|
||||
android:id="@+id/related_message_background"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="?colorSurface"
|
||||
tools:ignore="MissingConstraints" />
|
||||
|
||||
<View
|
||||
android:id="@+id/related_message_background_top_separator"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="?vctr_list_separator"
|
||||
tools:ignore="MissingConstraints" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/composerRelatedMessageAvatar"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:importantForAccessibility="no"
|
||||
tools:ignore="MissingConstraints" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/composerRelatedMessageTitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:textStyle="bold"
|
||||
tools:ignore="MissingConstraints"
|
||||
tools:text="@tools:sample/first_names"
|
||||
tools:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/composerRelatedMessageContent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="3"
|
||||
android:textColor="?vctr_message_text_color"
|
||||
tools:ignore="MissingConstraints"
|
||||
tools:text="@tools:sample/lorem"
|
||||
tools:visibility="gone" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/composerRelatedMessageActionIcon"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:importantForAccessibility="no"
|
||||
app:tint="?vctr_content_primary"
|
||||
tools:ignore="MissingConstraints,MissingPrefix" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/composerRelatedMessageImage"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:importantForAccessibility="no"
|
||||
tools:ignore="MissingPrefix" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/composerRelatedMessageCloseButton"
|
||||
android:layout_width="22dp"
|
||||
android:layout_height="22dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:contentDescription="@string/action_cancel"
|
||||
android:src="@drawable/ic_close_round"
|
||||
app:tint="?colorError"
|
||||
tools:ignore="MissingConstraints,MissingPrefix" />
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/composer_preview_barrier"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:barrierDirection="bottom"
|
||||
app:barrierMargin="8dp"
|
||||
app:constraint_referenced_ids="composerRelatedMessageContent,composerRelatedMessageActionIcon"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/attachmentButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:contentDescription="@string/option_send_files"
|
||||
android:paddingTop="2dp"
|
||||
android:src="@drawable/ic_attachment"
|
||||
tools:ignore="MissingConstraints" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/composerEditTextOuterBorder"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="@drawable/bg_composer_rich_edit_text_single_line" />
|
||||
|
||||
<io.element.android.wysiwyg.EditorEditText
|
||||
android:id="@+id/richTextComposerEditText"
|
||||
style="@style/Widget.Vector.EditText.RichTextComposer"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="top"
|
||||
android:nextFocusLeft="@id/richTextComposerEditText"
|
||||
android:nextFocusUp="@id/richTextComposerEditText"
|
||||
tools:hint="@string/room_message_placeholder"
|
||||
tools:ignore="MissingConstraints"
|
||||
tools:text="@tools:sample/lorem/random" />
|
||||
|
||||
<!-- Use a separate EditText for plain text editing while the rich text editor doesn't support this mode -->
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/plainTextComposerEditText"
|
||||
style="@style/Widget.Vector.EditText.RichTextComposer"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="top"
|
||||
android:nextFocusLeft="@id/plainTextComposerEditText"
|
||||
android:nextFocusUp="@id/plainTextComposerEditText"
|
||||
tools:hint="@string/room_message_placeholder"
|
||||
tools:ignore="MissingConstraints"
|
||||
tools:text="@tools:sample/lorem/random" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/composerFullScreenButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:contentDescription="@string/rich_text_editor_full_screen_toggle"
|
||||
android:src="@drawable/ic_composer_full_screen"
|
||||
app:layout_constraintBottom_toBottomOf="@id/composerEditTextOuterBorder"
|
||||
app:layout_constraintEnd_toEndOf="@id/composerEditTextOuterBorder"
|
||||
app:layout_constraintTop_toTopOf="@id/composerEditTextOuterBorder" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/sendButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="@drawable/bg_send"
|
||||
android:contentDescription="@string/action_send"
|
||||
android:src="@drawable/ic_send"
|
||||
tools:ignore="MissingConstraints" />
|
||||
|
||||
<HorizontalScrollView
|
||||
android:id="@+id/richTextMenuScrollView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:fillViewport="true"
|
||||
android:scrollbars="none"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/sendButton"
|
||||
app:layout_constraintStart_toEndOf="@id/attachmentButton"
|
||||
app:layout_constraintTop_toTopOf="@id/sendButton">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/richTextMenu"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</HorizontalScrollView>
|
||||
|
||||
<!--
|
||||
<ImageButton
|
||||
android:id="@+id/voiceMessageMicButton"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:contentDescription="@string/a11y_start_voice_message"
|
||||
android:src="@drawable/ic_voice_mic" />
|
||||
-->
|
||||
|
||||
</merge>
|
||||
|
|
@ -0,0 +1,233 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/composerLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
|
||||
<View
|
||||
android:id="@+id/related_message_background"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="?colorSurface"
|
||||
app:layout_constraintBottom_toTopOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:layout_height="40dp" />
|
||||
|
||||
<View
|
||||
android:id="@+id/related_message_background_top_separator"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="?vctr_list_separator"
|
||||
app:layout_constraintBottom_toTopOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/composerRelatedMessageAvatar"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:importantForAccessibility="no"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toTopOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/composerRelatedMessageTitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:textStyle="bold"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toTopOf="@id/composerRelatedMessageContent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:text="@tools:sample/first_names" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/composerRelatedMessageContent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toTopOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:text="@tools:sample/lorem/random" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/composerRelatedMessageActionIcon"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="38dp"
|
||||
android:alpha="0"
|
||||
android:importantForAccessibility="no"
|
||||
app:layout_constraintEnd_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="parent"
|
||||
app:tint="?vctr_content_primary"
|
||||
tools:ignore="MissingConstraints,MissingPrefix"
|
||||
tools:src="@drawable/ic_edit" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/composerRelatedMessageImage"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:importantForAccessibility="no"
|
||||
app:layout_constraintBottom_toTopOf="parent"
|
||||
app:layout_constraintStart_toEndOf="parent"
|
||||
tools:ignore="MissingPrefix"
|
||||
tools:src="@tools:sample/backgrounds/scenic" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/composerRelatedMessageCloseButton"
|
||||
android:layout_width="22dp"
|
||||
android:layout_height="22dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:contentDescription="@string/action_cancel"
|
||||
android:src="@drawable/ic_close_round"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toTopOf="parent"
|
||||
app:layout_constraintStart_toEndOf="parent"
|
||||
app:tint="?colorError"
|
||||
tools:ignore="MissingPrefix"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/composer_preview_barrier"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:barrierDirection="bottom"
|
||||
app:barrierMargin="8dp"
|
||||
app:constraint_referenced_ids="composerRelatedMessageContent,composerRelatedMessageActionIcon"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/attachmentButton"
|
||||
android:layout_width="@dimen/composer_attachment_size"
|
||||
android:layout_height="@dimen/composer_attachment_size"
|
||||
android:layout_margin="@dimen/composer_attachment_margin"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:contentDescription="@string/option_send_files"
|
||||
android:src="@drawable/ic_attachment"
|
||||
app:layout_constraintVertical_bias="1"
|
||||
app:layout_constraintBottom_toBottomOf="@id/sendButton"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/sendButton"
|
||||
app:layout_goneMarginBottom="57dp"
|
||||
tools:ignore="MissingPrefix" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/composerEditTextOuterBorder"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:minHeight="40dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginHorizontal="12dp"
|
||||
android:background="@drawable/bg_composer_rich_edit_text_single_line"
|
||||
app:layout_constraintVertical_bias="0"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/sendButton"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<io.element.android.wysiwyg.EditorEditText
|
||||
android:id="@+id/richTextComposerEditText"
|
||||
style="@style/Widget.Vector.EditText.RichTextComposer"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/room_message_placeholder"
|
||||
android:nextFocusLeft="@id/richTextComposerEditText"
|
||||
android:nextFocusUp="@id/richTextComposerEditText"
|
||||
android:layout_marginHorizontal="12dp"
|
||||
android:layout_marginVertical="10dp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/composerEditTextOuterBorder"
|
||||
app:layout_constraintEnd_toEndOf="@id/composerEditTextOuterBorder"
|
||||
app:layout_constraintStart_toStartOf="@id/composerEditTextOuterBorder"
|
||||
app:layout_constraintTop_toTopOf="@id/composerEditTextOuterBorder"
|
||||
tools:text="@tools:sample/lorem/random" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/plainTextComposerEditText"
|
||||
style="@style/Widget.Vector.EditText.RichTextComposer"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/room_message_placeholder"
|
||||
android:nextFocusLeft="@id/plainTextComposerEditText"
|
||||
android:nextFocusUp="@id/plainTextComposerEditText"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginVertical="10dp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/composerEditTextOuterBorder"
|
||||
app:layout_constraintEnd_toStartOf="@id/composerFullScreenButton"
|
||||
app:layout_constraintStart_toStartOf="@id/composerEditTextOuterBorder"
|
||||
app:layout_constraintTop_toTopOf="@id/composerEditTextOuterBorder"
|
||||
tools:text="@tools:sample/lorem/random" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/composerFullScreenButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="@id/composerEditTextOuterBorder"
|
||||
app:layout_constraintEnd_toEndOf="@id/composerEditTextOuterBorder"
|
||||
app:layout_constraintBottom_toBottomOf="@id/composerEditTextOuterBorder"
|
||||
app:layout_constraintVertical_bias="0"
|
||||
android:src="@drawable/ic_composer_full_screen"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:contentDescription="@string/rich_text_editor_full_screen_toggle" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/sendButton"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="@dimen/composer_min_height"
|
||||
android:layout_marginEnd="2dp"
|
||||
android:background="@drawable/bg_send"
|
||||
android:contentDescription="@string/action_send"
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/ic_send"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintTop_toBottomOf="@id/composerEditTextOuterBorder"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintVertical_bias="1"
|
||||
tools:ignore="MissingPrefix"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<HorizontalScrollView android:id="@+id/richTextMenuScrollView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="@id/sendButton"
|
||||
app:layout_constraintStart_toEndOf="@id/attachmentButton"
|
||||
app:layout_constraintEnd_toStartOf="@id/sendButton"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintVertical_bias="1"
|
||||
android:fillViewport="true">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/richTextMenu"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</HorizontalScrollView>
|
||||
|
||||
<!--
|
||||
<ImageButton
|
||||
android:id="@+id/voiceMessageMicButton"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:contentDescription="@string/a11y_start_voice_message"
|
||||
android:src="@drawable/ic_voice_mic"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
-->
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
@ -0,0 +1,230 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/composerLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
|
||||
<View
|
||||
android:id="@+id/related_message_background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:background="?colorSurface"
|
||||
app:layout_constraintBottom_toBottomOf="@id/composer_preview_barrier"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<View
|
||||
android:id="@+id/related_message_background_top_separator"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="1dp"
|
||||
android:background="?vctr_list_separator"
|
||||
app:layout_constraintEnd_toEndOf="@id/related_message_background"
|
||||
app:layout_constraintStart_toStartOf="@id/related_message_background"
|
||||
app:layout_constraintTop_toTopOf="@id/related_message_background" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/composerRelatedMessageAvatar"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:importantForAccessibility="no"
|
||||
app:layout_constraintBottom_toTopOf="@id/composerRelatedMessageActionIcon"
|
||||
app:layout_constraintEnd_toStartOf="@id/composerRelatedMessageTitle"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/composerRelatedMessageTitle"
|
||||
tools:src="@sample/user_round_avatars" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/composerRelatedMessageTitle"
|
||||
style="@style/Widget.Vector.TextView.Body"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintEnd_toStartOf="@id/composerRelatedMessageCloseButton"
|
||||
app:layout_constraintStart_toEndOf="@id/composerRelatedMessageAvatar"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="@tools:sample/first_names" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/composerRelatedMessageImage"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="66dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:importantForAccessibility="no"
|
||||
android:scaleType="centerCrop"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintStart_toStartOf="@id/composerRelatedMessageTitle"
|
||||
app:layout_constraintTop_toBottomOf="@id/composerRelatedMessageTitle"
|
||||
tools:ignore="MissingPrefix"
|
||||
tools:src="@tools:sample/backgrounds/scenic"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/composerRelatedMessageContent"
|
||||
style="@style/Widget.Vector.TextView.Body"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:textColor="?vctr_message_text_color"
|
||||
app:layout_constrainedHeight="true"
|
||||
app:layout_constraintEnd_toEndOf="@id/composerRelatedMessageTitle"
|
||||
app:layout_constraintStart_toStartOf="@id/composerRelatedMessageTitle"
|
||||
app:layout_constraintTop_toBottomOf="@id/composerRelatedMessageImage"
|
||||
tools:text="@tools:sample/lorem/random" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/composerRelatedMessageActionIcon"
|
||||
android:layout_width="10dp"
|
||||
android:layout_height="10dp"
|
||||
android:layout_marginTop="6dp"
|
||||
android:layout_marginBottom="38dp"
|
||||
android:alpha="1"
|
||||
android:importantForAccessibility="no"
|
||||
android:visibility="visible"
|
||||
app:layout_constraintEnd_toEndOf="@id/composerRelatedMessageAvatar"
|
||||
app:layout_constraintStart_toStartOf="@id/composerRelatedMessageAvatar"
|
||||
app:layout_constraintTop_toBottomOf="@id/composerRelatedMessageAvatar"
|
||||
app:tint="?vctr_content_primary"
|
||||
tools:ignore="MissingPrefix"
|
||||
tools:src="@drawable/ic_edit" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/composerRelatedMessageCloseButton"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:contentDescription="@string/action_cancel"
|
||||
android:src="@drawable/ic_close_round"
|
||||
app:layout_constraintBottom_toBottomOf="@id/composer_preview_barrier"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:tint="?colorError"
|
||||
tools:ignore="MissingPrefix" />
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/composer_preview_barrier"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:barrierDirection="bottom"
|
||||
app:barrierMargin="8dp"
|
||||
app:constraint_referenced_ids="composerRelatedMessageContent,composerRelatedMessageActionIcon"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/attachmentButton"
|
||||
android:layout_width="@dimen/composer_attachment_size"
|
||||
android:layout_height="@dimen/composer_attachment_size"
|
||||
android:layout_margin="@dimen/composer_attachment_margin"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:contentDescription="@string/option_send_files"
|
||||
android:src="@drawable/ic_attachment"
|
||||
app:layout_constraintBottom_toBottomOf="@id/sendButton"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/sendButton"
|
||||
app:layout_goneMarginBottom="57dp"
|
||||
tools:ignore="MissingPrefix" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/composerEditTextOuterBorder"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:minHeight="40dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="0dp"
|
||||
android:layout_marginHorizontal="12dp"
|
||||
android:background="@drawable/bg_composer_rich_edit_text_single_line"
|
||||
app:layout_constraintVertical_bias="0"
|
||||
app:layout_constraintTop_toBottomOf="@id/composer_preview_barrier"
|
||||
app:layout_constraintBottom_toTopOf="@id/sendButton"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<io.element.android.wysiwyg.EditorEditText
|
||||
android:id="@+id/richTextComposerEditText"
|
||||
style="@style/Widget.Vector.EditText.RichTextComposer"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/room_message_placeholder"
|
||||
android:nextFocusLeft="@id/richTextComposerEditText"
|
||||
android:nextFocusUp="@id/richTextComposerEditText"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginVertical="10dp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/composerEditTextOuterBorder"
|
||||
app:layout_constraintEnd_toStartOf="@id/composerFullScreenButton"
|
||||
app:layout_constraintStart_toStartOf="@id/composerEditTextOuterBorder"
|
||||
app:layout_constraintTop_toTopOf="@id/composerEditTextOuterBorder"
|
||||
tools:text="@tools:sample/lorem/random" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/plainTextComposerEditText"
|
||||
style="@style/Widget.Vector.EditText.RichTextComposer"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/room_message_placeholder"
|
||||
android:nextFocusLeft="@id/plainTextComposerEditText"
|
||||
android:nextFocusUp="@id/plainTextComposerEditText"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginVertical="10dp"
|
||||
app:layout_constraintBottom_toBottomOf="@id/composerEditTextOuterBorder"
|
||||
app:layout_constraintEnd_toStartOf="@id/composerFullScreenButton"
|
||||
app:layout_constraintStart_toStartOf="@id/composerEditTextOuterBorder"
|
||||
app:layout_constraintTop_toTopOf="@id/composerEditTextOuterBorder"
|
||||
tools:text="@tools:sample/lorem/random" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/composerFullScreenButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="@id/composerEditTextOuterBorder"
|
||||
app:layout_constraintEnd_toEndOf="@id/composerEditTextOuterBorder"
|
||||
app:layout_constraintBottom_toBottomOf="@id/composerEditTextOuterBorder"
|
||||
app:layout_constraintVertical_bias="0"
|
||||
android:src="@drawable/ic_composer_full_screen"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:contentDescription="@string/rich_text_editor_full_screen_toggle" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/sendButton"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="@dimen/composer_min_height"
|
||||
android:layout_marginEnd="2dp"
|
||||
android:background="@drawable/bg_send"
|
||||
android:contentDescription="@string/action_send"
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/ic_send"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintTop_toBottomOf="@id/composerEditTextOuterBorder"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
tools:ignore="MissingPrefix"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<HorizontalScrollView android:id="@+id/richTextMenuScrollView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="@id/sendButton"
|
||||
app:layout_constraintStart_toEndOf="@id/attachmentButton"
|
||||
app:layout_constraintEnd_toStartOf="@id/sendButton"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:fillViewport="true">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/richTextMenu"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</HorizontalScrollView>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
@ -0,0 +1,234 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/composerLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
|
||||
<View
|
||||
android:id="@+id/related_message_background"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="?colorSurface"
|
||||
app:layout_constraintBottom_toTopOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:layout_height="40dp" />
|
||||
|
||||
<View
|
||||
android:id="@+id/related_message_background_top_separator"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="?vctr_list_separator"
|
||||
app:layout_constraintBottom_toTopOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/composerRelatedMessageAvatar"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:importantForAccessibility="no"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toTopOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/composerRelatedMessageTitle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:textStyle="bold"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toTopOf="@id/composerRelatedMessageContent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:text="@tools:sample/first_names" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/composerRelatedMessageContent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toTopOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:text="@tools:sample/lorem/random" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/composerRelatedMessageActionIcon"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="38dp"
|
||||
android:alpha="0"
|
||||
android:importantForAccessibility="no"
|
||||
app:layout_constraintEnd_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="parent"
|
||||
app:tint="?vctr_content_primary"
|
||||
tools:ignore="MissingConstraints,MissingPrefix"
|
||||
tools:src="@drawable/ic_edit" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/composerRelatedMessageImage"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:importantForAccessibility="no"
|
||||
app:layout_constraintBottom_toTopOf="parent"
|
||||
app:layout_constraintStart_toEndOf="parent"
|
||||
tools:ignore="MissingPrefix"
|
||||
tools:src="@tools:sample/backgrounds/scenic" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/composerRelatedMessageCloseButton"
|
||||
android:layout_width="22dp"
|
||||
android:layout_height="22dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:contentDescription="@string/action_cancel"
|
||||
android:src="@drawable/ic_close_round"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toTopOf="parent"
|
||||
app:layout_constraintStart_toEndOf="parent"
|
||||
app:tint="?colorError"
|
||||
tools:ignore="MissingPrefix"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/composer_preview_barrier"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:barrierDirection="bottom"
|
||||
app:barrierMargin="8dp"
|
||||
app:constraint_referenced_ids="composerRelatedMessageContent,composerRelatedMessageActionIcon"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/attachmentButton"
|
||||
android:layout_width="@dimen/composer_attachment_size"
|
||||
android:layout_height="@dimen/composer_attachment_size"
|
||||
android:layout_margin="@dimen/composer_attachment_margin"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:contentDescription="@string/option_send_files"
|
||||
android:src="@drawable/ic_attachment"
|
||||
app:layout_constraintBottom_toBottomOf="@id/sendButton"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/sendButton"
|
||||
app:layout_goneMarginBottom="57dp"
|
||||
app:layout_constraintVertical_bias="1"
|
||||
tools:ignore="MissingPrefix" />
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/composerEditTextOuterBorder"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:minHeight="40dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginHorizontal="12dp"
|
||||
android:background="@drawable/bg_composer_rich_edit_text_expanded"
|
||||
app:layout_constraintVertical_bias="0"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/sendButton"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
<io.element.android.wysiwyg.EditorEditText
|
||||
android:id="@+id/richTextComposerEditText"
|
||||
style="@style/Widget.Vector.EditText.RichTextComposer"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:hint="@string/room_message_placeholder"
|
||||
android:nextFocusLeft="@id/richTextComposerEditText"
|
||||
android:nextFocusUp="@id/richTextComposerEditText"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginVertical="10dp"
|
||||
android:gravity="top"
|
||||
app:layout_constraintBottom_toBottomOf="@id/composerEditTextOuterBorder"
|
||||
app:layout_constraintEnd_toStartOf="@id/composerFullScreenButton"
|
||||
app:layout_constraintStart_toStartOf="@id/composerEditTextOuterBorder"
|
||||
app:layout_constraintTop_toTopOf="@id/composerEditTextOuterBorder"
|
||||
tools:text="@tools:sample/lorem/random" />
|
||||
|
||||
<com.google.android.material.textfield.TextInputEditText
|
||||
android:id="@+id/plainTextComposerEditText"
|
||||
style="@style/Widget.Vector.EditText.RichTextComposer"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:hint="@string/room_message_placeholder"
|
||||
android:nextFocusLeft="@id/plainTextComposerEditText"
|
||||
android:nextFocusUp="@id/plainTextComposerEditText"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginVertical="10dp"
|
||||
android:gravity="top"
|
||||
app:layout_constraintBottom_toBottomOf="@id/composerEditTextOuterBorder"
|
||||
app:layout_constraintEnd_toStartOf="@id/composerFullScreenButton"
|
||||
app:layout_constraintStart_toStartOf="@id/composerEditTextOuterBorder"
|
||||
app:layout_constraintTop_toTopOf="@id/composerEditTextOuterBorder"
|
||||
tools:text="@tools:sample/lorem/random" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/composerFullScreenButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="@id/composerEditTextOuterBorder"
|
||||
app:layout_constraintEnd_toEndOf="@id/composerEditTextOuterBorder"
|
||||
app:layout_constraintBottom_toBottomOf="@id/composerEditTextOuterBorder"
|
||||
app:layout_constraintVertical_bias="0"
|
||||
android:src="@drawable/ic_composer_full_screen"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:contentDescription="@string/rich_text_editor_full_screen_toggle" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/sendButton"
|
||||
android:layout_width="56dp"
|
||||
android:layout_height="@dimen/composer_min_height"
|
||||
android:layout_marginEnd="2dp"
|
||||
android:background="@drawable/bg_send"
|
||||
android:contentDescription="@string/action_send"
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/ic_send"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintVertical_bias="1"
|
||||
tools:ignore="MissingPrefix"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<HorizontalScrollView android:id="@+id/richTextMenuScrollView"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="@id/sendButton"
|
||||
app:layout_constraintStart_toEndOf="@id/attachmentButton"
|
||||
app:layout_constraintEnd_toStartOf="@id/sendButton"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintVertical_bias="1"
|
||||
android:fillViewport="true">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/richTextMenu"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</HorizontalScrollView>
|
||||
|
||||
<!--
|
||||
<ImageButton
|
||||
android:id="@+id/voiceMessageMicButton"
|
||||
android:layout_width="32dp"
|
||||
android:layout_height="32dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:contentDescription="@string/a11y_start_voice_message"
|
||||
android:src="@drawable/ic_voice_mic"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
-->
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ImageButton xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginHorizontal="2dp"
|
||||
android:background="@drawable/bg_rich_text_menu_button"
|
||||
app:tint="@color/selector_rich_text_menu_icon"
|
||||
tools:src="@drawable/ic_composer_bold"
|
||||
tools:ignore="ContentDescription" />
|
||||
Loading…
Add table
Add a link
Reference in a new issue