Apply design changes to WYSIWYG editor (#7354)

* Apply design changes to WYSIWYG editor

* Add changelog

* Remove unneeded attribute in RichTextComposerLayout

* Fix lint issues

* Fix style naming issue.

* Change rich text editor border radius depending on the number of lines.

* Replace standby voice recorder icon.
This commit is contained in:
Jorge Martin Espinosa 2022-10-14 09:59:43 +02:00 committed by GitHub
parent b679727246
commit 81ef1415dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 188 additions and 58 deletions

1
changelog.d/7354.misc Normal file
View File

@ -0,0 +1 @@
Update WYSIWYG editor designs.

View File

@ -447,7 +447,7 @@
<string name="labs_enable_deferred_dm_summary">Create DM only on first message</string>
<string name="labs_enable_rich_text_editor_title">Enable rich text editor</string>
<string name="labs_enable_rich_text_editor_summary">Use a rich text editor to send formatted messages</string>
<string name="labs_enable_rich_text_editor_summary">Try out the rich text editor (plain text mode coming soon)</string>
<!-- Home fragment -->
<string name="invitations_header">Invites</string>
@ -3362,4 +3362,10 @@
<string name="onboarding_new_app_layout_feedback_message">Tap top right to see the option to feedback.</string>
<string name="onboarding_new_app_layout_button_try">Try it out</string>
<!-- WYSIWYG Composer -->
<string name="rich_text_editor_format_bold">Apply bold format</string>
<string name="rich_text_editor_format_italic">Apply italic format</string>
<string name="rich_text_editor_format_strikethrough">Apply strikethrough format</string>
<string name="rich_text_editor_format_underline">Apply underline format</string>
</resources>

View File

@ -152,4 +152,9 @@
<color name="vctr_badge_color_border_light">@color/palette_white</color>
<color name="vctr_badge_color_border_dark">@color/palette_black_950</color>
<!-- WYSIWYG Colors -->
<attr name="vctr_rich_text_editor_menu_button_background" format="color" />
<color name="vctr_rich_text_editor_menu_button_background_light">#EEF8F4</color>
<color name="vctr_rich_text_editor_menu_button_background_dark">#1D292A</color>
</resources>

View File

@ -47,7 +47,8 @@
<dimen name="composer_min_height">56dp</dimen>
<dimen name="composer_attachment_size">52dp</dimen>
<dimen name="composer_attachment_margin">1dp</dimen>
<dimen name="rich_text_composer_corner_radius_single_line">28dp</dimen>
<dimen name="rich_text_composer_corner_radius_expanded">14dp</dimen>
<dimen name="chat_bubble_margin_start">28dp</dimen>
<dimen name="chat_bubble_margin_end">6dp</dimen>

View File

@ -11,4 +11,14 @@
<item name="android:textColor">?vctr_message_text_color</item>
</style>
<style name="Widget.Vector.EditText.RichTextComposer" parent="Widget.AppCompat.EditText">
<item name="android:background">@android:color/transparent</item>
<item name="android:inputType">textCapSentences|textMultiLine</item>
<item name="android:maxLines">12</item>
<item name="android:minHeight">20dp</item>
<item name="android:padding">0dp</item>
<item name="android:textSize">15sp</item>
<item name="android:textColor">?vctr_message_text_color</item>
</style>
</resources>

View File

@ -152,6 +152,9 @@
<!-- Material 3 -->
<item name="collapsingToolbarLayoutMediumSize">@dimen/collapsing_toolbar_layout_medium_size</item>
<!-- WYSIWYG Editor -->
<item name="vctr_rich_text_editor_menu_button_background">@color/vctr_rich_text_editor_menu_button_background_dark</item>
</style>
<style name="Theme.Vector.Dark" parent="Base.Theme.Vector.Dark" />

View File

@ -153,6 +153,9 @@
<!-- Material 3 -->
<item name="collapsingToolbarLayoutMediumSize">@dimen/collapsing_toolbar_layout_medium_size</item>
<!-- WYSIWYG Editor -->
<item name="vctr_rich_text_editor_menu_button_background">@color/vctr_rich_text_editor_menu_button_background_light</item>
</style>
<style name="Theme.Vector.Light" parent="Base.Theme.Vector.Light" />

View File

@ -76,3 +76,7 @@
-keep class org.bouncycastle.** { *; }
-keepnames class org.bouncycastle.** { *; }
-dontwarn org.bouncycastle.**
# JNA
-keep class com.sun.jna.** { *; }
-keep class * implements com.sun.jna.** { *; }

View File

@ -27,6 +27,7 @@ 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
@ -42,7 +43,10 @@ import im.vector.app.core.animations.SimpleTransitionListener
import im.vector.app.core.extensions.setTextIfDifferent
import im.vector.app.databinding.ComposerRichTextLayoutBinding
import im.vector.app.databinding.ViewRichTextMenuButtonBinding
import io.element.android.wysiwyg.EditorEditText
import io.element.android.wysiwyg.InlineFormat
import uniffi.wysiwyg_composer.ComposerAction
import uniffi.wysiwyg_composer.MenuState
class RichTextComposerLayout @JvmOverloads constructor(
context: Context,
@ -91,10 +95,18 @@ class RichTextComposerLayout @JvmOverloads constructor(
collapse(false)
views.composerEditText.addTextChangedListener(object : 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) {
callback?.onTextChanged(s)
val isExpanded = s.lines().count() > 1
if (previousTextWasExpanded != isExpanded) {
updateTextFieldBorder(isExpanded)
}
previousTextWasExpanded = isExpanded
}
})
@ -116,32 +128,57 @@ class RichTextComposerLayout @JvmOverloads constructor(
}
private fun setupRichTextMenu() {
addRichTextMenuItem(R.drawable.ic_composer_bold, "Bold") {
addRichTextMenuItem(R.drawable.ic_composer_bold, R.string.rich_text_editor_format_bold, ComposerAction.Bold) {
views.composerEditText.toggleInlineFormat(InlineFormat.Bold)
}
addRichTextMenuItem(R.drawable.ic_composer_italic, "Italic") {
addRichTextMenuItem(R.drawable.ic_composer_italic, R.string.rich_text_editor_format_italic, ComposerAction.Italic) {
views.composerEditText.toggleInlineFormat(InlineFormat.Italic)
}
addRichTextMenuItem(R.drawable.ic_composer_underlined, "Underline") {
addRichTextMenuItem(R.drawable.ic_composer_underlined, R.string.rich_text_editor_format_underline, ComposerAction.Underline) {
views.composerEditText.toggleInlineFormat(InlineFormat.Underline)
}
addRichTextMenuItem(R.drawable.ic_composer_strikethrough, "Strikethrough") {
addRichTextMenuItem(R.drawable.ic_composer_strikethrough, R.string.rich_text_editor_format_strikethrough, ComposerAction.StrikeThrough) {
views.composerEditText.toggleInlineFormat(InlineFormat.StrikeThrough)
}
views.composerEditText.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)
}
}
}
private fun addRichTextMenuItem(@DrawableRes iconId: Int, description: String, action: () -> Unit) {
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 = description
contentDescription = resources.getString(description)
setImageResource(iconId)
setOnClickListener {
action()
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(isExpanded: Boolean) {
val borderResource = if (isExpanded) {
R.drawable.bg_composer_rich_edit_text_expanded
} else {
R.drawable.bg_composer_rich_edit_text_single_line
}
views.composerEditTextOuterBorder.setBackgroundResource(borderResource)
}
override fun replaceFormattedContent(text: CharSequence) {
views.composerEditText.setHtml(text.toString())
}

View File

@ -260,7 +260,7 @@ class VoiceMessageViews(
fun resetMicButtonUi() {
views.voiceMessageMicButton.isVisible = true
views.voiceMessageMicButton.setImageResource(R.drawable.ic_voice_mic)
views.voiceMessageMicButton.setImageResource(R.drawable.ic_microphone)
views.voiceMessageMicButton.setAttributeBackground(android.R.attr.selectableItemBackgroundBorderless)
views.voiceMessageMicButton.updateLayoutParams<ViewGroup.MarginLayoutParams> {
if (rtlXMultiplier == -1) {

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_enabled="false" android:color="?attr/vctr_content_quinary" />
<item android:state_pressed="true" android:color="?attr/colorSecondary" />
<item android:state_hovered="true" android:color="?attr/colorSecondary" />
<item android:state_selected="true" android:color="?attr/colorSecondary" />
<item android:color="?attr/vctr_content_tertiary" />
</selector>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@android:color/transparent" />
<stroke
android:width="1dp"
android:color="?vctr_content_quaternary" />
<corners android:radius="@dimen/rich_text_composer_corner_radius_expanded" />
</shape>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@android:color/transparent" />
<stroke
android:width="1dp"
android:color="?vctr_content_quaternary" />
<corners android:radius="@dimen/rich_text_composer_corner_radius_single_line" />
</shape>

View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_hovered="true">
<shape android:shape="rectangle">
<corners android:radius="8dp" />
<solid android:color="?attr/vctr_rich_text_editor_menu_button_background" />
</shape>
</item>
<item android:state_selected="true">
<shape android:shape="rectangle">
<corners android:radius="8dp" />
<solid android:color="?attr/vctr_rich_text_editor_menu_button_background" />
</shape>
</item>
<item>
<ripple android:color="?attr/vctr_rich_text_editor_menu_button_background" />
</item>
</selector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M12,15C13.66,15 14.99,13.66 14.99,12L15,6C15,4.34 13.66,3 12,3C10.34,3 9,4.34 9,6V12C9,13.66 10.34,15 12,15ZM18.08,12C17.66,12 17.31,12.3 17.25,12.71C16.88,15.32 14.53,17.1 12,17.1C9.47,17.1 7.12,15.33 6.75,12.71C6.69,12.3 6.33,12 5.92,12C5.4,12 5,12.46 5.07,12.97C5.53,15.94 8.03,18.27 11,18.72V21C11,21.55 11.45,22 12,22C12.55,22 13,21.55 13,21V18.72C15.96,18.29 18.47,15.94 18.93,12.97C19,12.46 18.6,12 18.08,12Z"
android:fillColor="#8D97A5"/>
</vector>

View File

@ -1,12 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="32"
android:viewportHeight="32">
<path
android:pathData="M10.8,8.2C10.8,5.3281 13.1282,3 16,3C18.8719,3 21.2,5.3281 21.2,8.2V15.9767C21.2,18.8486 18.8719,21.1767 16,21.1767C13.1282,21.1767 10.8,18.8486 10.8,15.9767V8.2Z"
android:fillColor="?vctr_content_tertiary"/>
<path
android:pathData="M6.8998,14.3167C7.8203,14.3167 8.5665,15.0629 8.5665,15.9834C8.5665,20.0737 11.8818,23.3944 15.98,23.4051C15.9867,23.405 15.9934,23.4049 16.0001,23.4049C16.0068,23.4049 16.0134,23.405 16.0201,23.4051C20.1181,23.3941 23.4332,20.0735 23.4332,15.9834C23.4332,15.0629 24.1793,14.3167 25.0998,14.3167C26.0203,14.3167 26.7665,15.0629 26.7665,15.9834C26.7665,21.3586 22.8201,25.8101 17.6667,26.6103V27.6683C17.6667,28.5888 16.9206,29.335 16.0001,29.335C15.0796,29.335 14.3334,28.5888 14.3334,27.6683V26.6104C9.1798,25.8104 5.2332,21.3587 5.2332,15.9834C5.2332,15.0629 5.9794,14.3167 6.8998,14.3167Z"
android:fillColor="?vctr_content_tertiary"/>
</vector>

View File

@ -91,6 +91,7 @@
android:id="@+id/attachmentButton"
android:layout_width="0dp"
android:layout_height="0dp"
android:paddingTop="2dp"
android:background="?android:attr/selectableItemBackground"
android:contentDescription="@string/option_send_files"
android:src="@drawable/ic_attachment"
@ -100,16 +101,17 @@
android:id="@+id/composerEditTextOuterBorder"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@drawable/bg_composer_edit_text" />
android:background="@drawable/bg_composer_rich_edit_text_single_line" />
<io.element.android.wysiwyg.EditorEditText
android:id="@+id/composerEditText"
style="@style/Widget.Vector.EditText.Composer"
style="@style/Widget.Vector.EditText.RichTextComposer"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:nextFocusLeft="@id/composerEditText"
android:nextFocusUp="@id/composerEditText"
tools:hint="@string/room_message_placeholder"
tools:text="@tools:sample/lorem/random"
tools:ignore="MissingConstraints" />
<ImageButton

View File

@ -124,28 +124,30 @@
android:id="@+id/composerEditTextOuterBorder"
android:layout_width="0dp"
android:layout_height="0dp"
android:minHeight="40dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="@id/composerEditText"
app:layout_constraintStart_toStartOf="@id/composerEditText"
app:layout_constraintEnd_toEndOf="@id/composerEditText"
app:layout_constraintTop_toTopOf="@id/composerEditText"
app:layout_goneMarginEnd="12dp" />
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/composerEditText"
style="@style/Widget.Vector.EditText.Composer"
style="@style/Widget.Vector.EditText.RichTextComposer"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="@string/room_message_placeholder"
android:nextFocusLeft="@id/composerEditText"
android:nextFocusUp="@id/composerEditText"
android:layout_marginHorizontal="10dp"
app:layout_constraintVertical_bias="0"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
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" />
<ImageButton
@ -158,7 +160,7 @@
android:scaleType="center"
android:src="@drawable/ic_send"
android:visibility="invisible"
app:layout_constraintTop_toBottomOf="@id/composerEditText"
app:layout_constraintTop_toBottomOf="@id/composerEditTextOuterBorder"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
tools:ignore="MissingPrefix"

View File

@ -130,33 +130,38 @@
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:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
android:minHeight="40dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toTopOf="@id/sendButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
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_goneMarginEnd="12dp" />
app:layout_constraintBottom_toTopOf="@id/sendButton"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<io.element.android.wysiwyg.EditorEditText
android:id="@+id/composerEditText"
style="@style/Widget.Vector.EditText.Composer"
style="@style/Widget.Vector.EditText.RichTextComposer"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="@string/room_message_placeholder"
android:nextFocusLeft="@id/composerEditText"
android:nextFocusUp="@id/composerEditText"
app:layout_constraintBottom_toTopOf="@id/sendButton"
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_toBottomOf="@id/composer_preview_barrier"
app:layout_constraintTop_toTopOf="@id/composerEditTextOuterBorder"
tools:text="@tools:sample/lorem/random" />
<ImageButton
@ -169,10 +174,9 @@
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_constraintTop_toBottomOf="@id/composerEditText"
app:layout_constraintVertical_bias="1"
tools:ignore="MissingPrefix"
tools:visibility="visible" />

View File

@ -1,10 +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="@android:color/transparent"
android:contentDescription="@string/app_name">
<!-- The contentDescription attr is populated programmatically. This is just to fix lint issues. -->
</ImageButton>
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" />

View File

@ -23,11 +23,13 @@
android:id="@+id/voiceMessageMicButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="32dp"
android:minHeight="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"
android:src="@drawable/ic_microphone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />