Skip to content

Commit

Permalink
added InputFilter that performs a substation of insertion+AztecImageS…
Browse files Browse the repository at this point in the history
…pan when an insertion right before an AztecImageSpan is about to happen, to prevent a crash on Android 8.x
  • Loading branch information
mzorz committed Mar 28, 2019
1 parent 14b9f94 commit 39bf93f
Showing 1 changed file with 40 additions and 3 deletions.
43 changes: 40 additions & 3 deletions aztec/src/main/kotlin/org/wordpress/aztec/AztecText.kt
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,7 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
// triggers ClickableSpan onClick() events
movementMethod = EnhancedMovementMethod

setupBackspaceAndEnterDetection()
setupKeyListenersAndInputFilters()

//disable auto suggestions/correct for older devices
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
Expand All @@ -440,12 +440,44 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
// Setup the keyListener(s) for Backspace and Enter key.
// Backspace: If listener does return false we remove the style here
// Enter: Ask the listener if we need to insert or not the char
private fun setupBackspaceAndEnterDetection() {
private fun setupKeyListenersAndInputFilters() {
//hardware keyboard
setOnKeyListener { _, _, event ->
handleBackspaceAndEnter(event)
}

// This InputFilter created only for the purpose of avoiding crash described here:
// https://android-review.googlesource.com/c/platform/frameworks/base/+/634929
// https://github.com/wordpress-mobile/AztecEditor-Android/issues/729
// the rationale behind this workaround is that the specific crash happens only when adding/deleting text right
// before an AztecImageSpan, so we detect the specific case and re-create the contents only when that happens.
// This is indeed tackling the symptom rather than the actual problem, and should be removed once the real
// problem is fixed at the Android OS level as described in the following url
// https://android-review.googlesource.com/c/platform/frameworks/base/+/634929
val dynamicLayoutCrashPreventer = InputFilter { source, start, end, dest, dstart, dend ->
var temp = source
if (dest.length > dend+1) {
// if there are any images right after the destination position, hack the text
val spans = dest.getSpans(dstart, dend+1, AztecImageSpan::class.java)
if (spans.isNotEmpty()) {
// test: is this an insertion?
if (dstart == dend) {
// take the source (that is, what is being inserted), and append the Image to it. We will delete
// the original Image later so to not have a duplicate.
// use Spannable to copy / keep the current spans
temp = SpannableStringBuilder(source).append(dest.subSequence(dend, dend+1))

// delete the original AztecImageSpan
text.delete(dend, dend+1)
// now insert both the new insertion _and_ the original AztecImageSpan
text.insert(dend, temp)
temp = "" // discard the original source parameter as an ouput from this InputFilter
}
}
}
temp
}

val emptyEditTextBackspaceDetector = InputFilter { source, start, end, dest, dstart, dend ->
if (selectionStart == 0 && selectionEnd == 0
&& end == 0 && start == 0
Expand All @@ -462,7 +494,12 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
source
}

filters = arrayOf(emptyEditTextBackspaceDetector)
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O || Build.VERSION.SDK_INT == Build.VERSION_CODES.O_MR1) {
// dynamicLayoutCrashPreventer needs to be first in array as these are going to be chained when processed
filters = arrayOf(dynamicLayoutCrashPreventer, emptyEditTextBackspaceDetector)
} else {
filters = arrayOf(emptyEditTextBackspaceDetector)
}
}

private fun handleBackspaceAndEnter(event: KeyEvent): Boolean {
Expand Down

0 comments on commit 39bf93f

Please sign in to comment.