diff --git a/newsfragment/3182.feature b/newsfragment/3182.feature new file mode 100644 index 0000000000..83eee3c29c --- /dev/null +++ b/newsfragment/3182.feature @@ -0,0 +1 @@ +Update Message Composer design \ No newline at end of file diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt index ea28a0901b..9ed4feebc4 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt @@ -547,15 +547,15 @@ class RoomDetailFragment @Inject constructor( .fromRootView(views.rootConstraintLayout) .setKeyboardAnimationStyle(R.style.emoji_fade_animation_style) .setOnEmojiPopupShownListener { - views.composerLayout.views.composerEmojiButton.let { - it.setImageResource(R.drawable.ic_keyboard) - it.contentDescription = getString(R.string.a11y_close_emoji_picker) + views.composerLayout.views.composerEmojiButton.apply { + contentDescription = getString(R.string.a11y_close_emoji_picker) + setImageResource(R.drawable.ic_keyboard) } } .setOnEmojiPopupDismissListener { - views.composerLayout.views.composerEmojiButton.let { - it.setImageResource(R.drawable.ic_insert_emoji) - it.contentDescription = getString(R.string.a11y_open_emoji_picker) + views.composerLayout.views.composerEmojiButton.apply { + contentDescription = getString(R.string.a11y_open_emoji_picker) + setImageResource(R.drawable.ic_insert_emoji) } } .build(views.composerLayout.views.composerEditText) @@ -1188,6 +1188,10 @@ class RoomDetailFragment @Inject constructor( override fun onRichContentSelected(contentUri: Uri): Boolean { return sendUri(contentUri) } + + override fun onTextEmptyStateChanged(isEmpty: Boolean) { + // No op + } } } @@ -1201,6 +1205,7 @@ class RoomDetailFragment @Inject constructor( views.composerLayout.collapse(true) lockSendButton = true roomDetailViewModel.handle(RoomDetailAction.SendMessage(text, vectorPreferences.isMarkdownEnabled())) + emojiPopup.dismiss() } } @@ -1250,7 +1255,7 @@ class RoomDetailFragment @Inject constructor( if (state.tombstoneEvent == null) { if (state.canSendMessage) { views.composerLayout.visibility = View.VISIBLE - views.composerLayout.setRoomEncrypted(summary.isEncrypted, summary.roomEncryptionTrustLevel) + views.composerLayout.setRoomEncrypted(summary.isEncrypted) views.notificationAreaView.render(NotificationAreaView.State.Hidden) } else { views.composerLayout.visibility = View.GONE diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/ComposerEditText.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/ComposerEditText.kt index 45c937ca5e..2a2ae56c4c 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/ComposerEditText.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/ComposerEditText.kt @@ -37,9 +37,11 @@ class ComposerEditText @JvmOverloads constructor(context: Context, attrs: Attrib interface Callback { fun onRichContentSelected(contentUri: Uri): Boolean + fun onTextEmptyStateChanged(isEmpty: Boolean) } var callback: Callback? = null + private var isEmptyText = true override fun onCreateInputConnection(editorInfo: EditorInfo): InputConnection? { val ic = super.onCreateInputConnection(editorInfo) ?: return null @@ -93,6 +95,11 @@ class ComposerEditText @JvmOverloads constructor(context: Context, attrs: Attrib } spanToRemove = null } + // Report blank status of EditText to be able to arrange other elements of the composer + if (s.isEmpty() != isEmptyText) { + isEmptyText = !isEmptyText + callback?.onTextEmptyStateChanged(isEmptyText) + } } } ) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/TextComposerView.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/TextComposerView.kt index 6c7721ca02..d5e24dbb6b 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/TextComposerView.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/TextComposerView.kt @@ -24,6 +24,7 @@ import android.view.ViewGroup import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintSet import androidx.core.text.toSpannable +import androidx.core.view.isVisible import androidx.transition.ChangeBounds import androidx.transition.Fade import androidx.transition.Transition @@ -32,8 +33,6 @@ import androidx.transition.TransitionSet import im.vector.app.R import im.vector.app.databinding.ComposerLayoutBinding -import org.matrix.android.sdk.api.crypto.RoomEncryptionTrustLevel - /** * Encapsulate the timeline composer UX. * @@ -70,6 +69,10 @@ class TextComposerView @JvmOverloads constructor( override fun onRichContentSelected(contentUri: Uri): Boolean { return callback?.onRichContentSelected(contentUri) ?: false } + + override fun onTextEmptyStateChanged(isEmpty: Boolean) { + views.sendButton.isVisible = currentConstraintSetId == R.layout.composer_layout_constraint_set_expanded || !isEmpty + } } views.composerRelatedMessageCloseButton.setOnClickListener { collapse() @@ -93,6 +96,7 @@ class TextComposerView @JvmOverloads constructor( } currentConstraintSetId = R.layout.composer_layout_constraint_set_compact applyNewConstraintSet(animate, transitionComplete) + views.sendButton.isVisible = !views.composerEditText.text.isNullOrEmpty() } fun expand(animate: Boolean = true, transitionComplete: (() -> Unit)? = null) { @@ -102,6 +106,7 @@ class TextComposerView @JvmOverloads constructor( } currentConstraintSetId = R.layout.composer_layout_constraint_set_expanded applyNewConstraintSet(animate, transitionComplete) + views.sendButton.isVisible = true } private fun applyNewConstraintSet(animate: Boolean, transitionComplete: (() -> Unit)?) { @@ -110,8 +115,6 @@ class TextComposerView @JvmOverloads constructor( } ConstraintSet().also { it.clone(context, currentConstraintSetId) - // in case shield is hidden, we will have glitch without this - it.getConstraint(R.id.composerShieldImageView).propertySet.visibility = views.composerShieldImageView.visibility it.applyTo(this) } } @@ -139,13 +142,11 @@ class TextComposerView @JvmOverloads constructor( TransitionManager.beginDelayedTransition((parent as? ViewGroup ?: this), transition) } - fun setRoomEncrypted(isEncrypted: Boolean, roomEncryptionTrustLevel: RoomEncryptionTrustLevel?) { + fun setRoomEncrypted(isEncrypted: Boolean) { if (isEncrypted) { views.composerEditText.setHint(R.string.room_message_placeholder) - views.composerShieldImageView.render(roomEncryptionTrustLevel) } else { views.composerEditText.setHint(R.string.room_message_placeholder) - views.composerShieldImageView.render(null) } } } diff --git a/vector/src/main/res/drawable/bg_composer_edit_text.xml b/vector/src/main/res/drawable/bg_composer_edit_text.xml new file mode 100644 index 0000000000..8398fb3dc3 --- /dev/null +++ b/vector/src/main/res/drawable/bg_composer_edit_text.xml @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/vector/src/main/res/drawable/ic_attachment.xml b/vector/src/main/res/drawable/ic_attachment.xml index ea01e94372..8f2deff482 100644 --- a/vector/src/main/res/drawable/ic_attachment.xml +++ b/vector/src/main/res/drawable/ic_attachment.xml @@ -3,19 +3,19 @@ android:height="32dp" android:viewportWidth="32" android:viewportHeight="32"> - - - + + + diff --git a/vector/src/main/res/drawable/ic_insert_emoji.xml b/vector/src/main/res/drawable/ic_insert_emoji.xml index c35000342b..ed1a94c2ff 100644 --- a/vector/src/main/res/drawable/ic_insert_emoji.xml +++ b/vector/src/main/res/drawable/ic_insert_emoji.xml @@ -1,21 +1,15 @@ - - - - + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24"> + + + + diff --git a/vector/src/main/res/drawable/ic_keyboard.xml b/vector/src/main/res/drawable/ic_keyboard.xml index 5e5d431abb..c83c8d9ea7 100644 --- a/vector/src/main/res/drawable/ic_keyboard.xml +++ b/vector/src/main/res/drawable/ic_keyboard.xml @@ -1,4 +1,9 @@ - - + + diff --git a/vector/src/main/res/layout/composer_layout.xml b/vector/src/main/res/layout/composer_layout.xml index 25347d1bf9..3816c206b4 100644 --- a/vector/src/main/res/layout/composer_layout.xml +++ b/vector/src/main/res/layout/composer_layout.xml @@ -25,13 +25,6 @@ android:background="?vctr_list_separator" tools:ignore="MissingConstraints" /> - - - + android:background="@drawable/bg_composer_edit_text" /> + app:tint="?vctr_content_tertiary" + tools:ignore="MissingConstraints,MissingPrefix" /> - - - - + + app:layout_constraintTop_toTopOf="@id/attachmentButton" + app:layout_goneMarginEnd="8dp" + app:tint="?vctr_content_quaternary" + tools:ignore="MissingPrefix" /> + tools:ignore="MissingPrefix" + tools:visibility="visible" /> \ No newline at end of file diff --git a/vector/src/main/res/layout/composer_layout_constraint_set_expanded.xml b/vector/src/main/res/layout/composer_layout_constraint_set_expanded.xml index ff2a67f4f8..4c5034ed96 100644 --- a/vector/src/main/res/layout/composer_layout_constraint_set_expanded.xml +++ b/vector/src/main/res/layout/composer_layout_constraint_set_expanded.xml @@ -26,15 +26,6 @@ app:layout_constraintStart_toStartOf="@+id/related_message_background" app:layout_constraintTop_toTopOf="@id/related_message_background" /> - - - + app:layout_constraintTop_toBottomOf="@id/composer_preview_barrier" + app:layout_goneMarginEnd="12dp" /> + app:layout_goneMarginBottom="52dp" + app:layout_goneMarginEnd="8dp" + app:tint="?vctr_content_quaternary" + tools:ignore="MissingPrefix" /> + tools:ignore="MissingPrefix" + tools:visibility="visible" /> \ No newline at end of file diff --git a/vector/src/main/res/layout/fragment_room_detail.xml b/vector/src/main/res/layout/fragment_room_detail.xml index 1d6c272a11..ae7494894c 100644 --- a/vector/src/main/res/layout/fragment_room_detail.xml +++ b/vector/src/main/res/layout/fragment_room_detail.xml @@ -173,6 +173,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?android:colorBackground" + android:minHeight="56dp" android:transitionName="composer" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" diff --git a/vector/src/main/res/values/styles_riot.xml b/vector/src/main/res/values/styles_riot.xml index 5f285a13c7..56f7f95d87 100644 --- a/vector/src/main/res/values/styles_riot.xml +++ b/vector/src/main/res/values/styles_riot.xml @@ -225,7 +225,7 @@