Skip to content

Commit 64397bb

Browse files
committed
Merge branch 'trunk' into fix/simplify-contains-preformat-method
2 parents e9815a9 + 96fb186 commit 64397bb

File tree

15 files changed

+133
-89
lines changed

15 files changed

+133
-89
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ repositories {
104104
```
105105
```gradle
106106
dependencies {
107-
api "org.wordpress:aztec:v1.6.0"
107+
api "org.wordpress:aztec:v1.6.2"
108108
}
109109
```
110110

app/build.gradle

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ dependencies {
4141
implementation project(':wordpress-shortcodes')
4242
implementation project(':media-placeholders')
4343

44-
implementation "org.jetbrains.kotlin:kotlin-stdlib:$gradle.ext.kotlinVersion"
4544
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinCoroutinesVersion"
4645
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinCoroutinesVersion"
4746

aztec/build.gradle

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,6 @@ android {
4848
}
4949

5050
dependencies {
51-
implementation "org.jetbrains.kotlin:kotlin-stdlib:$gradle.ext.kotlinVersion"
52-
5351
implementation "org.ccil.cowan.tagsoup:tagsoup:$tagSoupVersion"
5452
implementation "org.jsoup:jsoup:$jSoupVersion"
5553

aztec/src/main/kotlin/org/wordpress/aztec/AztecText.kt

Lines changed: 48 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ import org.wordpress.aztec.handlers.ListItemHandler
7474
import org.wordpress.aztec.handlers.PreformatHandler
7575
import org.wordpress.aztec.handlers.QuoteHandler
7676
import org.wordpress.aztec.plugins.IAztecPlugin
77+
import org.wordpress.aztec.plugins.IClipboardPastePlugin
7778
import org.wordpress.aztec.plugins.IOnDrawPlugin
78-
import org.wordpress.aztec.plugins.ITextPastePlugin
7979
import org.wordpress.aztec.plugins.IToolbarButton
8080
import org.wordpress.aztec.source.Format
8181
import org.wordpress.aztec.source.SourceViewEditText
@@ -259,6 +259,7 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
259259
var isInCalypsoMode = true
260260
var isInGutenbergMode: Boolean = false
261261
val alignmentRendering: AlignmentRendering
262+
262263
// If this field is true, the media and horizontal line are added inline. If it's false, they are added after the
263264
// current block.
264265
var shouldAddMediaInline: Boolean = true
@@ -353,8 +354,8 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
353354
}
354355

355356
interface OnAztecKeyListener {
356-
fun onEnterKey(text: Spannable, firedAfterTextChanged: Boolean, selStart: Int, selEnd: Int) : Boolean
357-
fun onBackspaceKey() : Boolean
357+
fun onEnterKey(text: Spannable, firedAfterTextChanged: Boolean, selStart: Int, selEnd: Int): Boolean
358+
fun onBackspaceKey(): Boolean
358359
}
359360

360361
interface OnLinkTappedListener {
@@ -435,11 +436,11 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
435436
commentsVisible = styles.getBoolean(R.styleable.AztecText_commentsVisible, commentsVisible)
436437

437438
verticalParagraphPadding = styles.getDimensionPixelSize(R.styleable.AztecText_blockVerticalPadding,
438-
resources.getDimensionPixelSize(R.dimen.block_vertical_padding))
439+
resources.getDimensionPixelSize(R.dimen.block_vertical_padding))
439440
verticalParagraphMargin = styles.getDimensionPixelSize(R.styleable.AztecText_paragraphVerticalMargin,
440-
resources.getDimensionPixelSize(R.dimen.block_vertical_margin))
441+
resources.getDimensionPixelSize(R.dimen.block_vertical_margin))
441442
verticalHeadingMargin = styles.getDimensionPixelSize(R.styleable.AztecText_headingVerticalPadding,
442-
resources.getDimensionPixelSize(R.dimen.heading_vertical_padding))
443+
resources.getDimensionPixelSize(R.dimen.heading_vertical_padding))
443444

444445
inlineFormatter = InlineFormatter(this,
445446
InlineFormatter.CodeStyle(
@@ -597,7 +598,7 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
597598
isViewInitialized = true
598599
}
599600

600-
private fun <T>selectionHasExactlyOneMarker(start: Int, end: Int, type: Class<T>): Boolean {
601+
private fun <T> selectionHasExactlyOneMarker(start: Int, end: Int, type: Class<T>): Boolean {
601602
val spanFound: Array<T> = editableText.getSpans(
602603
start,
603604
end,
@@ -670,11 +671,11 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
670671
// problem is fixed at the Android OS level as described in the following url
671672
// https://android-review.googlesource.com/c/platform/frameworks/base/+/634929
672673
val dynamicLayoutCrashPreventer = InputFilter { source, start, end, dest, dstart, dend ->
673-
var temp : CharSequence? = null
674+
var temp: CharSequence? = null
674675
if (!bypassCrashPreventerInputFilter && dend < dest.length && source != Constants.NEWLINE_STRING) {
675676

676677
// if there are any images right after the destination position, hack the text
677-
val spans = dest.getSpans(dend, dend+1, AztecImageSpan::class.java)
678+
val spans = dest.getSpans(dend, dend + 1, AztecImageSpan::class.java)
678679
if (spans.isNotEmpty()) {
679680

680681
// prevent this filter from running recursively
@@ -730,7 +731,7 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
730731
}
731732

732733
private fun isCleanStringEmpty(text: CharSequence): Boolean {
733-
if ( isInGutenbergMode ) {
734+
if (isInGutenbergMode) {
734735
return (text.count() == 1 && text[0] == Constants.END_OF_BUFFER_MARKER)
735736
} else {
736737
return text.count() == 0
@@ -1045,7 +1046,7 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
10451046
this.onSelectionChangedListener = onSelectionChangedListener
10461047
}
10471048

1048-
fun getAztecKeyListener() : OnAztecKeyListener? {
1049+
fun getAztecKeyListener(): OnAztecKeyListener? {
10491050
return this.onAztecKeyListener
10501051
}
10511052

@@ -1823,7 +1824,8 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
18231824
} else {
18241825
return super.onTextContextMenuItem(id)
18251826
}
1826-
} else -> return super.onTextContextMenuItem(id)
1827+
}
1828+
else -> return super.onTextContextMenuItem(id)
18271829
}
18281830

18291831
return true
@@ -1900,21 +1902,42 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
19001902
enableTextChangedListener()
19011903

19021904
if (clip.itemCount > 0) {
1903-
val textToPaste = if (asPlainText) clip.getItemAt(0).coerceToText(context).toString()
1904-
else clip.getItemAt(0).coerceToHtmlText(AztecParser(alignmentRendering, plugins))
1905-
1906-
val oldHtml = toPlainHtml().replace("<aztec_cursor>", "")
1907-
val pastedHtmlText = plugins.filterIsInstance<ITextPastePlugin>().fold(textToPaste) { acc, plugin ->
1908-
if (selectedText.isNullOrEmpty()) {
1909-
plugin.toHtml(acc)
1910-
} else {
1911-
plugin.toHtml(selectedText, acc)
1905+
val firstItem = clip.getItemAt(0)
1906+
val itemToPaste = when {
1907+
!firstItem.text.isNullOrEmpty() -> {
1908+
val textToPaste = if (asPlainText) clip.getItemAt(0).coerceToText(context).toString()
1909+
else clip.getItemAt(0).coerceToHtmlText(AztecParser(alignmentRendering, plugins))
1910+
IClipboardPastePlugin.PastedItem.HtmlText(textToPaste)
1911+
}
1912+
firstItem.uri != null -> {
1913+
IClipboardPastePlugin.PastedItem.Url(firstItem.uri)
1914+
}
1915+
firstItem.intent != null -> {
1916+
IClipboardPastePlugin.PastedItem.PastedIntent(firstItem.intent)
1917+
}
1918+
else -> {
1919+
null
19121920
}
19131921
}
1914-
val newHtml = oldHtml.replace(Constants.REPLACEMENT_MARKER_STRING, pastedHtmlText + "<" + AztecCursorSpan.AZTEC_CURSOR_TAG + ">")
1922+
if (itemToPaste != null) {
1923+
val oldHtml = toPlainHtml().replace("<aztec_cursor>", "")
1924+
val pastedHtmlText: String = plugins.filterIsInstance<IClipboardPastePlugin<*>>()
1925+
.fold(null as? String?) { acc, plugin ->
1926+
plugin.itemToHtml(itemToPaste, acc ?: selectedText?.takeIf { it.isNotBlank() }) ?: acc
1927+
} ?: when (itemToPaste) {
1928+
is IClipboardPastePlugin.PastedItem.HtmlText -> itemToPaste.text
1929+
is IClipboardPastePlugin.PastedItem.Url -> itemToPaste.uri.path
1930+
is IClipboardPastePlugin.PastedItem.PastedIntent -> itemToPaste.intent.toString()
1931+
}
19151932

1916-
fromHtml(newHtml, false)
1917-
inlineFormatter.joinStyleSpans(0, length())
1933+
val newHtml = oldHtml.replace(
1934+
Constants.REPLACEMENT_MARKER_STRING,
1935+
pastedHtmlText + "<" + AztecCursorSpan.AZTEC_CURSOR_TAG + ">"
1936+
)
1937+
1938+
fromHtml(newHtml, false)
1939+
inlineFormatter.joinStyleSpans(0, length())
1940+
}
19181941
}
19191942
contentChangeWatcher.notifyContentChanged()
19201943
}
@@ -1964,7 +1987,7 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
19641987
}
19651988

19661989
@SuppressLint("InflateParams")
1967-
fun showLinkDialog(presetUrl: String = "", presetAnchor: String = "", presetOpenInNewWindow: String = "" ) {
1990+
fun showLinkDialog(presetUrl: String = "", presetAnchor: String = "", presetOpenInNewWindow: String = "") {
19681991
val urlAndAnchor = linkFormatter.getSelectedUrlWithAnchor()
19691992

19701993
val url = if (TextUtils.isEmpty(presetUrl)) urlAndAnchor.first else presetUrl
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package org.wordpress.aztec.plugins
2+
3+
import android.content.Intent
4+
import android.net.Uri
5+
6+
/**
7+
* Use this plugin in order to override the default item paste behaviour. An example is overriding the paste so that
8+
* you can handle pasted image URLs as images over the selected text.
9+
*/
10+
interface IClipboardPastePlugin<T : IClipboardPastePlugin.PastedItem> : IAztecPlugin {
11+
fun toHtml(pastedItem: T, selectedText: String? = null): String
12+
13+
/**
14+
* This method is called when text is pasted into the editor. If text is selected, the default behaviour
15+
* is to replace the selected text with the pasted item but it can be changed by overriding this method.
16+
* If text is not selected, this returned object of this method is inserted into the text.
17+
* This method should return HTML (plain text is OK if you don't apply any changes to the pasted text).
18+
* @param pastedItem clipboard item pasted over selected text
19+
* @param selectedText currently selected text
20+
* @return html of the result
21+
*/
22+
fun itemToHtml(pastedItem: PastedItem, selectedText: String? = null): String? {
23+
return when {
24+
pastedItem is PastedItem.HtmlText && this is ITextPastePlugin -> this.toHtml(pastedItem, selectedText)
25+
pastedItem is PastedItem.Url && this is IUriPastePlugin -> this.toHtml(pastedItem, selectedText)
26+
pastedItem is PastedItem.PastedIntent && this is IIntentPastePlugin -> this.toHtml(pastedItem, selectedText)
27+
else -> null
28+
}
29+
}
30+
31+
interface ITextPastePlugin : IClipboardPastePlugin<PastedItem.HtmlText> {
32+
/**
33+
* Override this method if you only need to handle the pasted text and not other types. If returned value is
34+
* null, it will be ignored and the default behaviour will take over.
35+
* @param pastedItem pasted text
36+
* @return value of the pasted HTML
37+
*/
38+
override fun toHtml(pastedItem: PastedItem.HtmlText, selectedText: String?): String
39+
}
40+
41+
interface IUriPastePlugin : IClipboardPastePlugin<PastedItem.Url> {
42+
/**
43+
* Override this method to handle pasted URIs. If returned value is null, it will be ignored and the default
44+
* behaviour will take over.
45+
* @param pastedItem pasted URI
46+
* @return HTML representation of an URI
47+
*/
48+
override fun toHtml(pastedItem: PastedItem.Url, selectedText: String?): String
49+
}
50+
51+
interface IIntentPastePlugin : IClipboardPastePlugin<PastedItem.PastedIntent> {
52+
/**
53+
* Override this method to handle pasted intents. If returned value is null, it will be ignored and the default
54+
* behaviour will take over.
55+
* @param pastedItem Pasted intent
56+
* @return HTML representation of an intent
57+
*/
58+
override fun toHtml(pastedItem: PastedItem.PastedIntent, selectedText: String?): String
59+
}
60+
61+
/**
62+
* Pasted items supported by Clipboard
63+
*/
64+
sealed class PastedItem {
65+
data class HtmlText(val text: String) : PastedItem()
66+
data class Url(val uri: Uri) : PastedItem()
67+
data class PastedIntent(val intent: Intent) : PastedItem()
68+
}
69+
}
70+

aztec/src/main/kotlin/org/wordpress/aztec/plugins/ITextPastePlugin.kt

Lines changed: 0 additions & 31 deletions
This file was deleted.

aztec/src/main/kotlin/org/wordpress/aztec/plugins/UrlPastePlugin.kt

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,19 @@ import android.util.Patterns
66
* This plugin overrides the paste logic of URLs in the AztecText. The purpose is to make sure inserted links are
77
* treated as HTML links.
88
*/
9-
class UrlPastePlugin : ITextPastePlugin {
9+
class UrlPastePlugin : IClipboardPastePlugin.ITextPastePlugin {
1010
/**
1111
* If the pasted text is a link, make sure it's wrapped with the `a` tag so that it's rendered as a link.
1212
*/
13-
override fun toHtml(pastedText: String): String {
14-
return if (Patterns.WEB_URL.matcher(pastedText).matches()) {
15-
"<a href=\"$pastedText\">$pastedText</a>"
13+
override fun toHtml(pastedItem: IClipboardPastePlugin.PastedItem.HtmlText, selectedText: String?): String {
14+
return if (Patterns.WEB_URL.matcher(pastedItem.text).matches()) {
15+
if (selectedText != null) {
16+
"<a href=\"${pastedItem.text}\">$selectedText</a>"
17+
} else {
18+
"<a href=\"${pastedItem.text}\">${pastedItem.text}</a>"
19+
}
1620
} else {
17-
pastedText
18-
}
19-
}
20-
21-
/**
22-
* If the pasted text is a link, make sure the selected text is wrapped with `a` tag and not removed.
23-
*/
24-
override fun toHtml(selectedText: String, pastedText: String): String {
25-
return if (Patterns.WEB_URL.matcher(pastedText).matches()) {
26-
"<a href=\"$pastedText\">$selectedText</a>"
27-
} else {
28-
pastedText
21+
pastedItem.text
2922
}
3023
}
3124
}

aztec/src/main/kotlin/org/wordpress/aztec/spans/IAztecNestable.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ interface IAztecNestable {
1212
fun getNestingLevelAt(spanned: Spanned, index: Int, nextIndex: Int = index): Int {
1313
return spanned.getSpans(index, nextIndex, IAztecNestable::class.java)
1414
.filter { spanned.getSpanEnd(it) != index || index == 0 || spanned[index - 1] != Constants.NEWLINE }
15-
.maxBy { it.nestingLevel }?.nestingLevel ?: 0
15+
.maxByOrNull { it.nestingLevel }?.nestingLevel ?: 0
1616
}
1717

1818
fun getMinNestingLevelAt(spanned: Spanned, index: Int, nextIndex: Int = index): Int {
@@ -21,7 +21,7 @@ interface IAztecNestable {
2121
.filter { spanned.getSpanStart(it) <= index && spanned.getSpanEnd(it) >= nextIndex &&
2222
(spanned.getSpanStart(it) != index || spanned.getSpanEnd(it) != nextIndex) }
2323
.filter { index != nextIndex || spanned.getSpanStart(it) != index && spanned.getSpanEnd(it) != index }
24-
.minBy { it.nestingLevel }?.nestingLevel ?: 0
24+
.minByOrNull { it.nestingLevel }?.nestingLevel ?: 0
2525
}
2626

2727
fun pushDeeper(spannable: Spannable, start: Int, end: Int, fromLevel: Int = 0, pushBy: Int = 1): List<SpanWrapper<IAztecNestable>> {

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ ext {
6161
tagSoupVersion = '1.2.1'
6262
glideVersion = '4.10.0'
6363
picassoVersion = '2.5.2'
64-
robolectricVersion = '4.4'
64+
robolectricVersion = '4.9'
6565
jUnitVersion = '4.12'
6666
jSoupVersion = '1.11.3'
6767
wordpressUtilsVersion = 'trunk-1ed207c03d2242b6fc3d74f9e388e9163cbc82a6'

glide-loader/build.gradle

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ android {
2424
}
2525

2626
dependencies {
27-
implementation "org.jetbrains.kotlin:kotlin-stdlib:$gradle.ext.kotlinVersion"
28-
2927
implementation aztecProjectDependency
3028
implementation "com.github.bumptech.glide:glide:$glideVersion"
3129
}

0 commit comments

Comments
 (0)