diff --git a/changelog.d/8045.feature b/changelog.d/8045.feature
new file mode 100644
index 0000000000..89b9111def
--- /dev/null
+++ b/changelog.d/8045.feature
@@ -0,0 +1 @@
+[Rich text editor] Add code block, quote and indentation actions
\ No newline at end of file
diff --git a/dependencies.gradle b/dependencies.gradle
index a876db4fc5..a87fd3f868 100644
--- a/dependencies.gradle
+++ b/dependencies.gradle
@@ -103,7 +103,7 @@ ext.libs = [
],
element : [
'opusencoder' : "io.element.android:opusencoder:1.1.0",
- 'wysiwyg' : "io.element.android:wysiwyg:0.23.0"
+ 'wysiwyg' : "io.element.android:wysiwyg:1.0.0"
],
squareup : [
'moshi' : "com.squareup.moshi:moshi:$moshi",
diff --git a/library/ui-strings/src/main/res/values/strings.xml b/library/ui-strings/src/main/res/values/strings.xml
index de3fa20916..17fbadd776 100644
--- a/library/ui-strings/src/main/res/values/strings.xml
+++ b/library/ui-strings/src/main/res/values/strings.xml
@@ -3503,7 +3503,11 @@
Set link
Toggle numbered list
Toggle bullet list
+ Indent
+ Unindent
+ Toggle quote
Apply inline code format
+ Toggle code block
Toggle full screen mode
Text
diff --git a/vector/src/androidTest/java/im/vector/app/features/html/EventHtmlRendererTest.kt b/vector/src/androidTest/java/im/vector/app/features/html/EventHtmlRendererTest.kt
index 7f3293e7d1..c095b33b44 100644
--- a/vector/src/androidTest/java/im/vector/app/features/html/EventHtmlRendererTest.kt
+++ b/vector/src/androidTest/java/im/vector/app/features/html/EventHtmlRendererTest.kt
@@ -21,6 +21,7 @@ import androidx.core.text.toSpanned
import androidx.test.platform.app.InstrumentationRegistry
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.resources.ColorProvider
+import im.vector.app.core.utils.DimensionConverter
import im.vector.app.core.utils.toTestSpan
import im.vector.app.features.settings.VectorPreferences
import io.mockk.every
@@ -40,9 +41,10 @@ class EventHtmlRendererTest {
every { it.isRichTextEditorEnabled() } returns false
}
private val fakeSessionHolder = mockk()
+ private val fakeDimensionConverter = mockk()
private val renderer = EventHtmlRenderer(
- MatrixHtmlPluginConfigure(ColorProvider(context), context.resources, fakeVectorPreferences),
+ MatrixHtmlPluginConfigure(ColorProvider(context), context.resources, fakeVectorPreferences, fakeDimensionConverter),
context,
fakeVectorPreferences,
fakeSessionHolder,
diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt
index 2e0ef1f70a..a13ef25d62 100644
--- a/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt
+++ b/vector/src/main/java/im/vector/app/features/home/room/detail/composer/RichTextComposerLayout.kt
@@ -232,6 +232,27 @@ internal class RichTextComposerLayout @JvmOverloads constructor(
addRichTextMenuItem(R.drawable.ic_composer_strikethrough, R.string.rich_text_editor_format_strikethrough, ComposerAction.STRIKE_THROUGH) {
views.richTextComposerEditText.toggleInlineFormat(InlineFormat.StrikeThrough)
}
+ addRichTextMenuItem(R.drawable.ic_composer_bullet_list, R.string.rich_text_editor_bullet_list, ComposerAction.UNORDERED_LIST) {
+ views.richTextComposerEditText.toggleList(ordered = false)
+ }
+ addRichTextMenuItem(R.drawable.ic_composer_numbered_list, R.string.rich_text_editor_numbered_list, ComposerAction.ORDERED_LIST) {
+ views.richTextComposerEditText.toggleList(ordered = true)
+ }
+ addRichTextMenuItem(R.drawable.ic_composer_indent, R.string.rich_text_editor_indent, ComposerAction.INDENT) {
+ views.richTextComposerEditText.indent()
+ }
+ addRichTextMenuItem(R.drawable.ic_composer_unindent, R.string.rich_text_editor_unindent, ComposerAction.UNINDENT) {
+ views.richTextComposerEditText.unindent()
+ }
+ addRichTextMenuItem(R.drawable.ic_composer_quote, R.string.rich_text_editor_quote, ComposerAction.QUOTE) {
+ views.richTextComposerEditText.toggleQuote()
+ }
+ addRichTextMenuItem(R.drawable.ic_composer_inline_code, R.string.rich_text_editor_inline_code, ComposerAction.INLINE_CODE) {
+ views.richTextComposerEditText.toggleInlineFormat(InlineFormat.InlineCode)
+ }
+ addRichTextMenuItem(R.drawable.ic_composer_code_block, R.string.rich_text_editor_code_block, ComposerAction.CODE_BLOCK) {
+ views.richTextComposerEditText.toggleCodeBlock()
+ }
addRichTextMenuItem(R.drawable.ic_composer_link, R.string.rich_text_editor_link, ComposerAction.LINK) {
views.richTextComposerEditText.getLinkAction()?.let {
when (it) {
@@ -240,15 +261,6 @@ internal class RichTextComposerLayout @JvmOverloads constructor(
}
}
}
- addRichTextMenuItem(R.drawable.ic_composer_bullet_list, R.string.rich_text_editor_bullet_list, ComposerAction.UNORDERED_LIST) {
- views.richTextComposerEditText.toggleList(ordered = false)
- }
- addRichTextMenuItem(R.drawable.ic_composer_numbered_list, R.string.rich_text_editor_numbered_list, ComposerAction.ORDERED_LIST) {
- views.richTextComposerEditText.toggleList(ordered = true)
- }
- addRichTextMenuItem(R.drawable.ic_composer_inline_code, R.string.rich_text_editor_inline_code, ComposerAction.INLINE_CODE) {
- views.richTextComposerEditText.toggleInlineFormat(InlineFormat.InlineCode)
- }
}
fun setLink(link: String?) =
@@ -331,11 +343,11 @@ internal class RichTextComposerLayout @JvmOverloads constructor(
* Updates the non-active input with the contents of the active input.
*/
private fun syncEditTexts() =
- if (isTextFormattingEnabled) {
- views.plainTextComposerEditText.setText(views.richTextComposerEditText.getMarkdown())
- } else {
- views.richTextComposerEditText.setMarkdown(views.plainTextComposerEditText.text.toString())
- }
+ if (isTextFormattingEnabled) {
+ views.plainTextComposerEditText.setText(views.richTextComposerEditText.getMarkdown())
+ } else {
+ views.richTextComposerEditText.setMarkdown(views.plainTextComposerEditText.text.toString())
+ }
private fun addRichTextMenuItem(@DrawableRes iconId: Int, @StringRes description: Int, action: ComposerAction, onClick: () -> Unit) {
val inflater = LayoutInflater.from(context)
@@ -355,6 +367,13 @@ internal class RichTextComposerLayout @JvmOverloads constructor(
val stateForAction = menuState[action]
button.isEnabled = stateForAction != ActionState.DISABLED
button.isSelected = stateForAction == ActionState.REVERSED
+
+ if (action == ComposerAction.INDENT || action == ComposerAction.UNINDENT) {
+ val indentationButtonIsVisible =
+ menuState[ComposerAction.ORDERED_LIST] == ActionState.REVERSED ||
+ menuState[ComposerAction.UNORDERED_LIST] == ActionState.REVERSED
+ button.isVisible = indentationButtonIsVisible
+ }
}
fun estimateCollapsedHeight(): Int {
diff --git a/vector/src/main/java/im/vector/app/features/html/EventHtmlRenderer.kt b/vector/src/main/java/im/vector/app/features/html/EventHtmlRenderer.kt
index bc9ba0b85a..e75d12f1d8 100644
--- a/vector/src/main/java/im/vector/app/features/html/EventHtmlRenderer.kt
+++ b/vector/src/main/java/im/vector/app/features/html/EventHtmlRenderer.kt
@@ -240,6 +240,7 @@ class MatrixHtmlPluginConfigure @Inject constructor(
private val colorProvider: ColorProvider,
private val resources: Resources,
private val vectorPreferences: VectorPreferences,
+ private val dimensionConverter: DimensionConverter,
) : HtmlPlugin.HtmlConfigure {
override fun configureHtml(plugin: HtmlPlugin) {
@@ -248,7 +249,7 @@ class MatrixHtmlPluginConfigure @Inject constructor(
.addHandler(FontTagHandler())
.addHandler(ParagraphHandler(DimensionConverter(resources)))
.addHandler(MxReplyTagHandler())
- .addHandler(CodePostProcessorTagHandler(vectorPreferences))
+ .addHandler(CodePostProcessorTagHandler(vectorPreferences, dimensionConverter))
.addHandler(CodePreTagHandler())
.addHandler(CodeTagHandler())
.addHandler(SpanHandler(colorProvider))
diff --git a/vector/src/main/java/im/vector/app/features/html/HtmlCodeHandlers.kt b/vector/src/main/java/im/vector/app/features/html/HtmlCodeHandlers.kt
index 295b74c7a9..3175996ba1 100644
--- a/vector/src/main/java/im/vector/app/features/html/HtmlCodeHandlers.kt
+++ b/vector/src/main/java/im/vector/app/features/html/HtmlCodeHandlers.kt
@@ -16,7 +16,9 @@
package im.vector.app.features.html
+import im.vector.app.core.utils.DimensionConverter
import im.vector.app.features.settings.VectorPreferences
+import io.element.android.wysiwyg.spans.CodeBlockSpan
import io.element.android.wysiwyg.spans.InlineCodeSpan
import io.noties.markwon.MarkwonVisitor
import io.noties.markwon.SpannableBuilder
@@ -68,6 +70,7 @@ internal class CodePreTagHandler : TagHandler() {
internal class CodePostProcessorTagHandler(
private val vectorPreferences: VectorPreferences,
+ private val dimensionConverter: DimensionConverter,
) : TagHandler() {
override fun supportedTags() = listOf(HtmlRootTagPlugin.ROOT_TAG_NAME)
@@ -90,6 +93,7 @@ internal class CodePostProcessorTagHandler(
val intermediateCodeSpan = code.what as IntermediateCodeSpan
val theme = visitor.configuration().theme()
val span = intermediateCodeSpan.toFinalCodeSpan(theme)
+
SpannableBuilder.setSpans(
visitor.builder(), span, code.start, code.end
)
@@ -98,9 +102,15 @@ internal class CodePostProcessorTagHandler(
private fun IntermediateCodeSpan.toFinalCodeSpan(
markwonTheme: MarkwonTheme
- ): Any = if (vectorPreferences.isRichTextEditorEnabled() && !isBlock) {
- InlineCodeSpan()
+ ): Any = if (vectorPreferences.isRichTextEditorEnabled()) {
+ toRichTextEditorSpan()
} else {
HtmlCodeSpan(markwonTheme, isBlock)
}
+
+ private fun IntermediateCodeSpan.toRichTextEditorSpan() = if (isBlock) {
+ CodeBlockSpan(dimensionConverter.dpToPx(10), dimensionConverter.dpToPx(4))
+ } else {
+ InlineCodeSpan()
+ }
}
diff --git a/vector/src/main/res/drawable/ic_composer_bold.xml b/vector/src/main/res/drawable/ic_composer_bold.xml
index 3d9a10d16b..2624bbddd6 100644
--- a/vector/src/main/res/drawable/ic_composer_bold.xml
+++ b/vector/src/main/res/drawable/ic_composer_bold.xml
@@ -3,8 +3,8 @@
android:height="44dp"
android:viewportWidth="44"
android:viewportHeight="44">
-
+
diff --git a/vector/src/main/res/drawable/ic_composer_bullet_list.xml b/vector/src/main/res/drawable/ic_composer_bullet_list.xml
index f6febc88f0..81e57753b0 100644
--- a/vector/src/main/res/drawable/ic_composer_bullet_list.xml
+++ b/vector/src/main/res/drawable/ic_composer_bullet_list.xml
@@ -3,11 +3,10 @@
android:height="44dp"
android:viewportWidth="44"
android:viewportHeight="44">
-
-
-
-
+
+
+
+
diff --git a/vector/src/main/res/drawable/ic_composer_code_block.xml b/vector/src/main/res/drawable/ic_composer_code_block.xml
new file mode 100644
index 0000000000..ca4ab42a46
--- /dev/null
+++ b/vector/src/main/res/drawable/ic_composer_code_block.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/vector/src/main/res/drawable/ic_composer_collapse.xml b/vector/src/main/res/drawable/ic_composer_collapse.xml
index 724a833761..d123caac5f 100644
--- a/vector/src/main/res/drawable/ic_composer_collapse.xml
+++ b/vector/src/main/res/drawable/ic_composer_collapse.xml
@@ -4,6 +4,6 @@
android:viewportWidth="20"
android:viewportHeight="20">
+ android:fillColor="?vctr_content_quaternary"
+ android:pathData="M10.708,10Q10.438,10 10.219,9.781Q10,9.562 10,9.292V4.542Q10,4.354 10.146,4.219Q10.292,4.083 10.458,4.083Q10.646,4.083 10.781,4.219Q10.917,4.354 10.917,4.542V8.438L16.375,3Q16.5,2.854 16.688,2.854Q16.875,2.854 17,3Q17.146,3.125 17.146,3.312Q17.146,3.5 17,3.625L11.562,9.083H15.458Q15.646,9.083 15.781,9.229Q15.917,9.375 15.917,9.542Q15.917,9.729 15.781,9.865Q15.646,10 15.458,10ZM3,17Q2.854,16.875 2.854,16.688Q2.854,16.5 3,16.375L8.438,10.917H4.542Q4.354,10.917 4.219,10.771Q4.083,10.625 4.083,10.458Q4.083,10.271 4.219,10.135Q4.354,10 4.542,10H9.292Q9.562,10 9.781,10.219Q10,10.438 10,10.708V15.458Q10,15.646 9.854,15.781Q9.708,15.917 9.542,15.917Q9.354,15.917 9.219,15.781Q9.083,15.646 9.083,15.458V11.562L3.625,17Q3.5,17.146 3.312,17.146Q3.125,17.146 3,17Z" />
diff --git a/vector/src/main/res/drawable/ic_composer_full_screen.xml b/vector/src/main/res/drawable/ic_composer_full_screen.xml
index de1862c09b..6c7d7d6731 100644
--- a/vector/src/main/res/drawable/ic_composer_full_screen.xml
+++ b/vector/src/main/res/drawable/ic_composer_full_screen.xml
@@ -4,6 +4,6 @@
android:viewportWidth="20"
android:viewportHeight="20">
+ android:fillColor="?vctr_content_quaternary"
+ android:pathData="M3.625,17.083Q3.354,17.083 3.135,16.865Q2.917,16.646 2.917,16.375V11.625Q2.917,11.438 3.062,11.302Q3.208,11.167 3.375,11.167Q3.562,11.167 3.698,11.302Q3.833,11.438 3.833,11.625V15.5L15.5,3.833H11.625Q11.438,3.833 11.302,3.688Q11.167,3.542 11.167,3.375Q11.167,3.188 11.302,3.052Q11.438,2.917 11.625,2.917H16.375Q16.646,2.917 16.865,3.135Q17.083,3.354 17.083,3.625V8.375Q17.083,8.562 16.938,8.698Q16.792,8.833 16.625,8.833Q16.438,8.833 16.302,8.698Q16.167,8.562 16.167,8.375V4.5L4.5,16.167H8.375Q8.562,16.167 8.698,16.312Q8.833,16.458 8.833,16.625Q8.833,16.812 8.698,16.948Q8.562,17.083 8.375,17.083Z" />
diff --git a/vector/src/main/res/drawable/ic_composer_indent.xml b/vector/src/main/res/drawable/ic_composer_indent.xml
new file mode 100644
index 0000000000..5aa8cd73da
--- /dev/null
+++ b/vector/src/main/res/drawable/ic_composer_indent.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
diff --git a/vector/src/main/res/drawable/ic_composer_inline_code.xml b/vector/src/main/res/drawable/ic_composer_inline_code.xml
index 1743b757af..e041523d1c 100644
--- a/vector/src/main/res/drawable/ic_composer_inline_code.xml
+++ b/vector/src/main/res/drawable/ic_composer_inline_code.xml
@@ -3,13 +3,13 @@
android:height="44dp"
android:viewportWidth="44"
android:viewportHeight="44">
-
-
-
+
+
+
diff --git a/vector/src/main/res/drawable/ic_composer_italic.xml b/vector/src/main/res/drawable/ic_composer_italic.xml
index faa4f89cd4..7e293577ea 100644
--- a/vector/src/main/res/drawable/ic_composer_italic.xml
+++ b/vector/src/main/res/drawable/ic_composer_italic.xml
@@ -3,8 +3,8 @@
android:height="44dp"
android:viewportWidth="44"
android:viewportHeight="44">
-
+
diff --git a/vector/src/main/res/drawable/ic_composer_link.xml b/vector/src/main/res/drawable/ic_composer_link.xml
index 6d0f731ed9..5a38a6d2c3 100644
--- a/vector/src/main/res/drawable/ic_composer_link.xml
+++ b/vector/src/main/res/drawable/ic_composer_link.xml
@@ -3,10 +3,10 @@
android:height="44dp"
android:viewportWidth="44"
android:viewportHeight="44">
-
+
diff --git a/vector/src/main/res/drawable/ic_composer_numbered_list.xml b/vector/src/main/res/drawable/ic_composer_numbered_list.xml
index d6a860c4c8..47522233a4 100644
--- a/vector/src/main/res/drawable/ic_composer_numbered_list.xml
+++ b/vector/src/main/res/drawable/ic_composer_numbered_list.xml
@@ -3,22 +3,22 @@
android:height="44dp"
android:viewportWidth="44"
android:viewportHeight="44">
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/vector/src/main/res/drawable/ic_composer_quote.xml b/vector/src/main/res/drawable/ic_composer_quote.xml
new file mode 100644
index 0000000000..42336fbecd
--- /dev/null
+++ b/vector/src/main/res/drawable/ic_composer_quote.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
diff --git a/vector/src/main/res/drawable/ic_composer_rich_text_editor_close.xml b/vector/src/main/res/drawable/ic_composer_rich_text_editor_close.xml
index c461470de5..c432cc3cfb 100644
--- a/vector/src/main/res/drawable/ic_composer_rich_text_editor_close.xml
+++ b/vector/src/main/res/drawable/ic_composer_rich_text_editor_close.xml
@@ -3,7 +3,7 @@
android:height="12dp"
android:viewportWidth="12"
android:viewportHeight="12">
-
+
diff --git a/vector/src/main/res/drawable/ic_composer_rich_text_editor_edit.xml b/vector/src/main/res/drawable/ic_composer_rich_text_editor_edit.xml
index 4556974221..155f3be031 100644
--- a/vector/src/main/res/drawable/ic_composer_rich_text_editor_edit.xml
+++ b/vector/src/main/res/drawable/ic_composer_rich_text_editor_edit.xml
@@ -3,10 +3,10 @@
android:height="12dp"
android:viewportWidth="12"
android:viewportHeight="12">
-
-
+
+
diff --git a/vector/src/main/res/drawable/ic_composer_strikethrough.xml b/vector/src/main/res/drawable/ic_composer_strikethrough.xml
index 3970c95381..7ad78919ac 100644
--- a/vector/src/main/res/drawable/ic_composer_strikethrough.xml
+++ b/vector/src/main/res/drawable/ic_composer_strikethrough.xml
@@ -3,10 +3,10 @@
android:height="44dp"
android:viewportWidth="44"
android:viewportHeight="44">
-
-
+
+
diff --git a/vector/src/main/res/drawable/ic_composer_underlined.xml b/vector/src/main/res/drawable/ic_composer_underlined.xml
index fe18d60185..170edd6641 100644
--- a/vector/src/main/res/drawable/ic_composer_underlined.xml
+++ b/vector/src/main/res/drawable/ic_composer_underlined.xml
@@ -3,11 +3,10 @@
android:height="44dp"
android:viewportWidth="44"
android:viewportHeight="44">
-
-
-
-
+
+
+
+
diff --git a/vector/src/main/res/drawable/ic_composer_unindent.xml b/vector/src/main/res/drawable/ic_composer_unindent.xml
new file mode 100644
index 0000000000..0585f21b03
--- /dev/null
+++ b/vector/src/main/res/drawable/ic_composer_unindent.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
diff --git a/vector/src/main/res/drawable/ic_microphone.xml b/vector/src/main/res/drawable/ic_microphone.xml
index 270fe456fa..d1366aeca9 100644
--- a/vector/src/main/res/drawable/ic_microphone.xml
+++ b/vector/src/main/res/drawable/ic_microphone.xml
@@ -5,5 +5,5 @@
android:viewportHeight="24">
+ android:fillColor="?vctr_content_tertiary"/>
diff --git a/vector/src/main/res/drawable/ic_rich_composer_add.xml b/vector/src/main/res/drawable/ic_rich_composer_add.xml
index 3a90a40902..8d082ed3b3 100644
--- a/vector/src/main/res/drawable/ic_rich_composer_add.xml
+++ b/vector/src/main/res/drawable/ic_rich_composer_add.xml
@@ -5,11 +5,11 @@
android:viewportHeight="36">
+ android:fillColor="?vctr_system"/>