Skip to content

Commit e74881f

Browse files
committed
Fix removeMedia method and add tests
1 parent a2a7d0e commit e74881f

File tree

5 files changed

+148
-12
lines changed

5 files changed

+148
-12
lines changed

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2161,6 +2161,14 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
21612161
lineBlockFormatter.insertVideo(shouldAddMediaInline, drawable, attributes, onVideoTappedListener, onMediaDeletedListener)
21622162
}
21632163

2164+
fun removeMedia(predicate: (Attributes) -> Boolean) {
2165+
removeMedia(object : AttributePredicate {
2166+
override fun matches(attrs: Attributes): Boolean {
2167+
return predicate(attrs)
2168+
}
2169+
})
2170+
}
2171+
21642172
fun removeMedia(attributePredicate: AttributePredicate) {
21652173
text.getSpans(0, text.length, AztecMediaSpan::class.java)
21662174
.filter {
@@ -2198,8 +2206,8 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
21982206
spans.forEach { temporarySpan ->
21992207
text.setSpan(
22002208
temporarySpan.span,
2201-
temporarySpan.start - 2,
2202-
temporarySpan.end - 2,
2209+
(temporarySpan.start - 2).coerceAtLeast(0),
2210+
(temporarySpan.end - 2).coerceAtMost(text.length),
22032211
temporarySpan.flags
22042212
)
22052213
}

media-placeholders/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ dependencies {
3939
implementation 'androidx.appcompat:appcompat:1.0.0'
4040
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinCoroutinesVersion"
4141
testImplementation "junit:junit:$jUnitVersion"
42+
testImplementation "org.robolectric:robolectric:$robolectricVersion"
4243
}
4344

4445
project.afterEvaluate {

media-placeholders/src/main/java/org/wordpress/aztec/placeholders/ImageWithCaptionAdapter.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ class ImageWithCaptionAdapter(
8282
private const val SRC_ATTRIBUTE = "src"
8383

8484
suspend fun insertImageWithCaption(placeholderManager: PlaceholderManager, src: String, caption: String) {
85-
// placeholderManager.insertItem(ADAPTER_TYPE, SRC_ATTRIBUTE to src, CAPTION_ATTRIBUTE to caption)
8685
placeholderManager.insertOrUpdateItem(ADAPTER_TYPE) { currentAttributes, type ->
8786
if (currentAttributes == null || type != ADAPTER_TYPE) {
8887
mapOf(SRC_ATTRIBUTE to src, CAPTION_ATTRIBUTE to caption)

media-placeholders/src/main/java/org/wordpress/aztec/placeholders/PlaceholderManager.kt

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@ import kotlin.math.min
4141
class PlaceholderManager(
4242
private val aztecText: AztecText,
4343
private val container: FrameLayout,
44-
private val htmlTag: String = DEFAULT_HTML_TAG
44+
private val htmlTag: String = DEFAULT_HTML_TAG,
45+
private val generateUuid: () -> String = {
46+
UUID.randomUUID().toString()
47+
}
4548
) : AztecContentChangeWatcher.AztecTextChangeObserver,
4649
IHtmlTagHandler,
4750
Html.MediaCallback,
@@ -146,12 +149,8 @@ class PlaceholderManager(
146149
* Call this method to remove a placeholder from both the AztecText and the overlaying layer programatically.
147150
* @param predicate determines whether a span should be removed
148151
*/
149-
fun removeItem(predicate: (AztecAttributes) -> Boolean) {
150-
aztecText.editableText.getSpans(0, aztecText.length(), AztecPlaceholderSpan::class.java).filter {
151-
predicate(it.attributes)
152-
}.forEach { placeholderSpan ->
153-
aztecText.removeMediaSpan(placeholderSpan)
154-
}
152+
fun removeItem(predicate: (Attributes) -> Boolean) {
153+
aztecText.removeMedia { predicate(it) }
155154
}
156155

157156
private suspend fun buildPlaceholderDrawable(adapter: PlaceholderAdapter, attrs: AztecAttributes): Drawable {
@@ -251,7 +250,7 @@ class PlaceholderManager(
251250

252251
private fun getAttributesForMedia(type: String, attributes: Array<out Pair<String, String>>): AztecAttributes {
253252
val attrs = AztecAttributes()
254-
attrs.setValue(UUID_ATTRIBUTE, UUID.randomUUID().toString())
253+
attrs.setValue(UUID_ATTRIBUTE, generateUuid())
255254
attrs.setValue(TYPE_ATTRIBUTE, type)
256255
attributes.forEach {
257256
attrs.setValue(it.first, it.second)
@@ -309,7 +308,7 @@ class PlaceholderManager(
309308
val type = attributes.getValue(TYPE_ATTRIBUTE)
310309
val adapter = adapters[type] ?: return false
311310
val aztecAttributes = AztecAttributes(attributes)
312-
aztecAttributes.setValue(UUID_ATTRIBUTE, UUID.randomUUID().toString())
311+
aztecAttributes.setValue(UUID_ATTRIBUTE, generateUuid())
313312
val drawable = runBlocking { buildPlaceholderDrawable(adapter, aztecAttributes) }
314313
val span = AztecPlaceholderSpan(
315314
context = aztecText.context,
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
package org.wordpress.aztec.placeholders
2+
3+
import android.app.Activity
4+
import android.text.BoringLayout
5+
import android.text.Layout
6+
import android.text.TextPaint
7+
import android.view.MenuItem
8+
import android.view.View
9+
import android.view.ViewGroup.LayoutParams.MATCH_PARENT
10+
import android.widget.FrameLayout
11+
import android.widget.PopupMenu
12+
import kotlinx.coroutines.runBlocking
13+
import org.junit.Assert
14+
import org.junit.Before
15+
import org.junit.Test
16+
import org.junit.runner.RunWith
17+
import org.robolectric.Robolectric
18+
import org.robolectric.RobolectricTestRunner
19+
import org.wordpress.aztec.AztecAttributes
20+
import org.wordpress.aztec.AztecText
21+
import org.wordpress.aztec.source.SourceViewEditText
22+
import org.wordpress.aztec.toolbar.AztecToolbar
23+
24+
@RunWith(RobolectricTestRunner::class)
25+
class PlaceholderTest {
26+
lateinit var container: FrameLayout
27+
lateinit var editText: AztecText
28+
lateinit var menuList: PopupMenu
29+
lateinit var menuListOrdered: MenuItem
30+
lateinit var menuListUnordered: MenuItem
31+
lateinit var sourceText: SourceViewEditText
32+
lateinit var toolbar: AztecToolbar
33+
lateinit var placeholderManager: PlaceholderManager
34+
35+
private val uuid: String = "uuid123"
36+
37+
/**
38+
* Initialize variables.
39+
*/
40+
@Before
41+
fun init() {
42+
val activity = Robolectric.buildActivity(Activity::class.java).create().visible().get()
43+
container = FrameLayout(activity)
44+
editText = AztecText(activity)
45+
container.addView(editText, FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT))
46+
placeholderManager = PlaceholderManager(editText, container, generateUuid = {
47+
uuid
48+
})
49+
placeholderManager.registerAdapter(ImageWithCaptionAdapter())
50+
editText.setCalypsoMode(false)
51+
editText.addMediaAfterBlocks()
52+
editText.plugins.add(placeholderManager)
53+
sourceText = SourceViewEditText(activity)
54+
sourceText.setCalypsoMode(false)
55+
toolbar = AztecToolbar(activity)
56+
toolbar.setEditor(editText, sourceText)
57+
menuList = toolbar.getListMenu() as PopupMenu
58+
menuListOrdered = menuList.menu.getItem(1)
59+
menuListUnordered = menuList.menu.getItem(0)
60+
activity.setContentView(container)
61+
}
62+
63+
@Test
64+
@Throws(Exception::class)
65+
fun addAndRemovePlaceholderAtTheBeginning() {
66+
runBlocking {
67+
val initialHtml = "<p>Line 1</p>"
68+
editText.fromHtml(initialHtml)
69+
70+
editText.setSelection(0)
71+
val attributes = AztecAttributes()
72+
attributes.setValue("id", "1234")
73+
ImageWithCaptionAdapter.insertImageWithCaption(placeholderManager, "image.jpg", "Caption 123")
74+
75+
Assert.assertEquals("<placeholder uuid=\"$uuid\" type=\"image_with_caption\" src=\"image.jpg\" caption=\"Caption 123\" /><p>Line 1</p>", editText.toHtml())
76+
77+
placeholderManager.removeItem {
78+
it.getValue("uuid") == uuid
79+
}
80+
81+
Assert.assertEquals(initialHtml, editText.toHtml())
82+
}
83+
}
84+
85+
@Test
86+
@Throws(Exception::class)
87+
fun addAndRemovePlaceholderAtTheEndOfLine() {
88+
runBlocking {
89+
val initialHtml = "<p>Line 123</p><p>Line 2</p>"
90+
editText.fromHtml(initialHtml)
91+
92+
editText.setSelection(editText.editableText.indexOf("1"))
93+
val attributes = AztecAttributes()
94+
attributes.setValue("id", "1234")
95+
ImageWithCaptionAdapter.insertImageWithCaption(placeholderManager, "image.jpg", "Caption 123")
96+
97+
Assert.assertEquals("<p>Line 123<placeholder uuid=\"uuid123\" type=\"image_with_caption\" src=\"image.jpg\" caption=\"Caption 123\" /></p><p>Line 2</p>", editText.toHtml())
98+
99+
placeholderManager.removeItem {
100+
it.getValue("uuid") == uuid
101+
}
102+
103+
Assert.assertEquals(initialHtml, editText.toHtml())
104+
}
105+
}
106+
107+
@Test
108+
@Throws(Exception::class)
109+
fun insertOrUpdateAPlaceholderAtTheBeginning() {
110+
runBlocking {
111+
val initialHtml = "<p>Line 1</p>"
112+
editText.fromHtml(initialHtml)
113+
114+
editText.setSelection(0)
115+
val attributes = AztecAttributes()
116+
attributes.setValue("id", "1234")
117+
ImageWithCaptionAdapter.insertImageWithCaption(placeholderManager, "image.jpg", "Caption 1")
118+
ImageWithCaptionAdapter.insertImageWithCaption(placeholderManager, "image.jpg", "Caption 2")
119+
120+
Assert.assertEquals("<placeholder src=\"image.jpg\" caption=\"Caption 2 - Caption 1\" uuid=\"uuid123\" type=\"image_with_caption\" /><p>Line 1</p>", editText.toHtml())
121+
122+
placeholderManager.removeItem {
123+
it.getValue("uuid") == uuid
124+
}
125+
126+
Assert.assertEquals(initialHtml, editText.toHtml())
127+
}
128+
}
129+
}

0 commit comments

Comments
 (0)