From ebacdff2ba23348fdccfa091ba582d5382e3d691 Mon Sep 17 00:00:00 2001 From: vojtasmrcek Date: Wed, 18 Dec 2019 10:55:46 +0100 Subject: [PATCH 1/5] Add content change watcher for AztecText --- .../aztec/AztecContentChangeWatcher.kt | 33 +++++++++++++++++++ .../kotlin/org/wordpress/aztec/AztecText.kt | 12 +++++++ 2 files changed, 45 insertions(+) create mode 100644 aztec/src/main/kotlin/org/wordpress/aztec/AztecContentChangeWatcher.kt diff --git a/aztec/src/main/kotlin/org/wordpress/aztec/AztecContentChangeWatcher.kt b/aztec/src/main/kotlin/org/wordpress/aztec/AztecContentChangeWatcher.kt new file mode 100644 index 000000000..07a9864ff --- /dev/null +++ b/aztec/src/main/kotlin/org/wordpress/aztec/AztecContentChangeWatcher.kt @@ -0,0 +1,33 @@ +package org.wordpress.aztec + +import java.lang.ref.WeakReference + +class AztecContentChangeWatcher { + private val observers = mutableListOf>() + fun registerObserver(observer: AztecTextChangeObserver) { + if (observers.none { it.get() == observer }) { + observers.add(WeakReference(observer)) + } + } + + fun unregisterObserver(observer: AztecTextChangeObserver) { + observers.removeAll { it.get() == observer } + } + + internal fun notifyContentChanged() { + val iterator = observers.iterator() + while (iterator.hasNext()) { + val item = iterator.next() + val foundObserver = item.get() + if (foundObserver == null) { + iterator.remove() + } else { + foundObserver.onContentChanged() + } + } + } + + interface AztecTextChangeObserver { + fun onContentChanged() + } +} diff --git a/aztec/src/main/kotlin/org/wordpress/aztec/AztecText.kt b/aztec/src/main/kotlin/org/wordpress/aztec/AztecText.kt index 8671b1aab..99f7e9e0e 100644 --- a/aztec/src/main/kotlin/org/wordpress/aztec/AztecText.kt +++ b/aztec/src/main/kotlin/org/wordpress/aztec/AztecText.kt @@ -293,6 +293,8 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown private var focusOnVisible = true + val contentChangeWatcher = AztecContentChangeWatcher() + interface OnSelectionChangedListener { fun onSelectionChanged(selStart: Int, selEnd: Int) } @@ -497,6 +499,8 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown // use HTML from the new text to set the state of the editText directly fromHtml(toFormattedHtml(newText), false) + contentChangeWatcher.notifyContentChanged() + // re-enable MediaDeleted listener enableMediaDeletedListener() // re-enable this very filter @@ -565,6 +569,7 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown setText("") enableTextChangedListener() } + contentChangeWatcher.notifyContentChanged() } return wasStyleRemoved } @@ -627,6 +632,7 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown } override fun afterTextChanged(text: Editable) { + contentChangeWatcher.notifyContentChanged() if (isTextChangedListenerDisabled()) { return } @@ -1024,6 +1030,8 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown .forEach { it.toggle() } } } + + contentChangeWatcher.notifyContentChanged() } fun contains(format: ITextFormat, selStart: Int = selectionStart, selEnd: Int = selectionEnd): Boolean { @@ -1128,10 +1136,12 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown fun redo() { history.redo(this) + contentChangeWatcher.notifyContentChanged() } fun undo() { history.undo(this) + contentChangeWatcher.notifyContentChanged() } // Helper ====================================================================================== @@ -1618,6 +1628,7 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown fromHtml(newHtml, false) inlineFormatter.joinStyleSpans(0, length()) } + contentChangeWatcher.notifyContentChanged() } } @@ -1643,6 +1654,7 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown } else { linkFormatter.addLink(url, anchor, openInNewWindow, selectionStart, selectionEnd) } + contentChangeWatcher.notifyContentChanged() } fun removeLink() { From 7e66fc997f59f798878573b4fb6747fe866e3c80 Mon Sep 17 00:00:00 2001 From: vojtasmrcek Date: Wed, 18 Dec 2019 12:57:06 +0100 Subject: [PATCH 2/5] Add useless log --- aztec/src/main/kotlin/org/wordpress/aztec/AztecText.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/aztec/src/main/kotlin/org/wordpress/aztec/AztecText.kt b/aztec/src/main/kotlin/org/wordpress/aztec/AztecText.kt index 99f7e9e0e..b7dccdde3 100644 --- a/aztec/src/main/kotlin/org/wordpress/aztec/AztecText.kt +++ b/aztec/src/main/kotlin/org/wordpress/aztec/AztecText.kt @@ -43,6 +43,7 @@ import android.text.TextWatcher import android.text.style.SuggestionSpan import android.util.AttributeSet import android.util.DisplayMetrics +import android.util.Log import android.view.KeyEvent import android.view.LayoutInflater import android.view.MotionEvent @@ -345,6 +346,7 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown } fun setCalypsoMode(isCompatibleWithCalypso: Boolean) { + Log.d("testing", "for the sake of testing") isInCalypsoMode = isCompatibleWithCalypso } From fa992d9e68ae14ee7e8bdc7663dafce1495d6036 Mon Sep 17 00:00:00 2001 From: vojtasmrcek Date: Thu, 19 Dec 2019 09:51:05 +0100 Subject: [PATCH 3/5] Add unit tests --- .../kotlin/org/wordpress/aztec/AztecText.kt | 2 - .../aztec/AztecContentChangeWatcherTest.kt | 73 +++++++++++++++++++ 2 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 aztec/src/test/kotlin/org/wordpress/aztec/AztecContentChangeWatcherTest.kt diff --git a/aztec/src/main/kotlin/org/wordpress/aztec/AztecText.kt b/aztec/src/main/kotlin/org/wordpress/aztec/AztecText.kt index b7dccdde3..99f7e9e0e 100644 --- a/aztec/src/main/kotlin/org/wordpress/aztec/AztecText.kt +++ b/aztec/src/main/kotlin/org/wordpress/aztec/AztecText.kt @@ -43,7 +43,6 @@ import android.text.TextWatcher import android.text.style.SuggestionSpan import android.util.AttributeSet import android.util.DisplayMetrics -import android.util.Log import android.view.KeyEvent import android.view.LayoutInflater import android.view.MotionEvent @@ -346,7 +345,6 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown } fun setCalypsoMode(isCompatibleWithCalypso: Boolean) { - Log.d("testing", "for the sake of testing") isInCalypsoMode = isCompatibleWithCalypso } diff --git a/aztec/src/test/kotlin/org/wordpress/aztec/AztecContentChangeWatcherTest.kt b/aztec/src/test/kotlin/org/wordpress/aztec/AztecContentChangeWatcherTest.kt new file mode 100644 index 000000000..88d510a4b --- /dev/null +++ b/aztec/src/test/kotlin/org/wordpress/aztec/AztecContentChangeWatcherTest.kt @@ -0,0 +1,73 @@ +package org.wordpress.aztec + +import org.junit.Assert.* +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +@RunWith(JUnit4::class) +class AztecContentChangeWatcherTest { + private lateinit var aztecContentChangeWatcher: AztecContentChangeWatcher + @Before + fun setUp() { + aztecContentChangeWatcher = AztecContentChangeWatcher() + } + + @Test + fun `notifies registered observer`() { + // Given + var contentChanged = false + setupRegisteredObserver { + contentChanged = true + } + + // When + aztecContentChangeWatcher.notifyContentChanged() + + // Then + assertTrue(contentChanged) + } + + @Test + fun `does not notify unregistered observer`() { + // Given + var contentChanged = false + val observer = setupRegisteredObserver { + contentChanged = true + } + + // When + aztecContentChangeWatcher.unregisterObserver(observer) + aztecContentChangeWatcher.notifyContentChanged() + + // Then + assertFalse(contentChanged) + } + + @Test + fun `observer is garbage collected and reference is lost`() { + // Given + var contentChanged = false + setupRegisteredObserver { + contentChanged = true + } + System.gc() + + // When + aztecContentChangeWatcher.notifyContentChanged() + + // Then + assertFalse(contentChanged) + } + + private fun setupRegisteredObserver(onContentChanged: () -> Unit): AztecContentChangeWatcher.AztecTextChangeObserver { + val observer = object : AztecContentChangeWatcher.AztecTextChangeObserver { + override fun onContentChanged() { + onContentChanged() + } + } + aztecContentChangeWatcher.registerObserver(observer) + return observer + } +} \ No newline at end of file From 4018ef96dfde51be6e652076e3c151e909a95d6a Mon Sep 17 00:00:00 2001 From: vojtasmrcek Date: Thu, 19 Dec 2019 09:54:21 +0100 Subject: [PATCH 4/5] Add missing newline --- .../kotlin/org/wordpress/aztec/AztecContentChangeWatcherTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aztec/src/test/kotlin/org/wordpress/aztec/AztecContentChangeWatcherTest.kt b/aztec/src/test/kotlin/org/wordpress/aztec/AztecContentChangeWatcherTest.kt index 88d510a4b..512dcfc79 100644 --- a/aztec/src/test/kotlin/org/wordpress/aztec/AztecContentChangeWatcherTest.kt +++ b/aztec/src/test/kotlin/org/wordpress/aztec/AztecContentChangeWatcherTest.kt @@ -70,4 +70,4 @@ class AztecContentChangeWatcherTest { aztecContentChangeWatcher.registerObserver(observer) return observer } -} \ No newline at end of file +} From 807062ab67edb46a777883aedc107fc80bb13659 Mon Sep 17 00:00:00 2001 From: vojtasmrcek Date: Fri, 20 Dec 2019 13:42:17 +0100 Subject: [PATCH 5/5] Fix lint issue --- .../org/wordpress/aztec/AztecContentChangeWatcherTest.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/aztec/src/test/kotlin/org/wordpress/aztec/AztecContentChangeWatcherTest.kt b/aztec/src/test/kotlin/org/wordpress/aztec/AztecContentChangeWatcherTest.kt index 512dcfc79..3313879c9 100644 --- a/aztec/src/test/kotlin/org/wordpress/aztec/AztecContentChangeWatcherTest.kt +++ b/aztec/src/test/kotlin/org/wordpress/aztec/AztecContentChangeWatcherTest.kt @@ -1,6 +1,7 @@ package org.wordpress.aztec -import org.junit.Assert.* +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test import org.junit.runner.RunWith