Skip to content

Commit fb2d9fd

Browse files
committed
Added fix for predictive text on Samsung.
1 parent 2e7ceb6 commit fb2d9fd

File tree

2 files changed

+42
-7
lines changed

2 files changed

+42
-7
lines changed

app/src/main/kotlin/org/wordpress/aztec/demo/MainActivity.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,7 @@ open class MainActivity : AppCompatActivity(),
466466
aztec.sourceEditor?.displayStyledAndFormattedHtml(EXAMPLE)
467467

468468
aztec.addPlugin(CssUnderlinePlugin())
469+
aztec.visualEditor.enableSamsungPredictiveBehaviorOverride()
469470
}
470471

471472
if (savedInstanceState == null) {

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

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
236236
private var bypassObservationQueue: Boolean = false
237237
private var bypassMediaDeletedListener: Boolean = false
238238
private var bypassCrashPreventerInputFilter: Boolean = false
239+
private var overrideSamsungPredictiveBehavior: Boolean = false
239240

240241
var initialEditorContentParsedSHA256: ByteArray = ByteArray(0)
241242

@@ -663,6 +664,29 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
663664
handleBackspaceAndEnter(event)
664665
}
665666

667+
// This InputFilter is creating for fixing the issue with predictive text on Samsung devices with API 33
668+
// (at least this time) https://github.com/wordpress-mobile/AztecEditor-Android/issues/1023
669+
// We are detecting when content of the editor is replaced with identical content, by comparing string values
670+
// and ranges of incoming and exiting content. When this happens, instead of using incoming source content
671+
// we use original content, with SuggestionSpan from incoming content added to it.
672+
val samsungContentReplacementPreventer = InputFilter { source, start, end, dest, dstart, dend ->
673+
var temp: CharSequence? = null
674+
if (overrideSamsungPredictiveBehavior) {
675+
val equalStringValues = source.toString() == dest.toString()
676+
val equalRange = start == 0 && dstart == 0 && end == source.length && dend == source.length
677+
678+
679+
if (equalStringValues && equalRange) {
680+
temp = SpannableStringBuilder(dest)
681+
TextUtils.copySpansFrom(dest, 0, dest.length, Any::class.java, temp, 0)
682+
if (source is Spanned) {
683+
TextUtils.copySpansFrom(source, 0, dest.length, SuggestionSpan::class.java, temp, 0)
684+
}
685+
}
686+
}
687+
temp
688+
}
689+
666690
// This InputFilter created only for the purpose of avoiding crash described here:
667691
// https://android-review.googlesource.com/c/platform/frameworks/base/+/634929
668692
// https://github.com/wordpress-mobile/AztecEditor-Android/issues/729
@@ -723,11 +747,13 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
723747
source
724748
}
725749

726-
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O || Build.VERSION.SDK_INT == Build.VERSION_CODES.O_MR1) {
750+
filters = if (Build.MANUFACTURER == "samsung" && Build.VERSION.SDK_INT == 33) {
751+
arrayOf(samsungContentReplacementPreventer, emptyEditTextBackspaceDetector)
752+
} else if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O || Build.VERSION.SDK_INT == Build.VERSION_CODES.O_MR1) {
727753
// dynamicLayoutCrashPreventer needs to be first in array as these are going to be chained when processed
728-
filters = arrayOf(dynamicLayoutCrashPreventer, emptyEditTextBackspaceDetector)
754+
arrayOf(dynamicLayoutCrashPreventer, emptyEditTextBackspaceDetector)
729755
} else {
730-
filters = arrayOf(emptyEditTextBackspaceDetector)
756+
arrayOf(emptyEditTextBackspaceDetector)
731757
}
732758
}
733759

@@ -1713,6 +1739,14 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
17131739
bypassMediaDeletedListener = false
17141740
}
17151741

1742+
fun enableSamsungPredictiveBehaviorOverride() {
1743+
overrideSamsungPredictiveBehavior = true
1744+
}
1745+
1746+
fun disableSamsungPredictiveBehaviorOverride() {
1747+
overrideSamsungPredictiveBehavior = false
1748+
}
1749+
17161750
fun isMediaDeletedListenerDisabled(): Boolean {
17171751
return bypassMediaDeletedListener
17181752
}
@@ -1865,7 +1899,7 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
18651899
val html = Format.removeSourceEditorFormatting(parser.toHtml(output), isInCalypsoMode, isInGutenbergMode)
18661900

18671901
val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as android.content.ClipboardManager
1868-
clipboard.primaryClip = ClipData.newHtmlText("aztec", output.toString(), html)
1902+
clipboard.setPrimaryClip(ClipData.newHtmlText("aztec", output.toString(), html))
18691903
}
18701904

18711905
// copied from TextView with some changes
@@ -1926,14 +1960,14 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
19261960
}
19271961
if (itemToPaste != null) {
19281962
val oldHtml = toPlainHtml().replace("<aztec_cursor>", "")
1929-
val pastedHtmlText: String = plugins.filterIsInstance<IClipboardPastePlugin<*>>()
1963+
val pastedHtmlText: String = (plugins.filterIsInstance<IClipboardPastePlugin<*>>()
19301964
.fold(null as? String?) { acc, plugin ->
19311965
plugin.itemToHtml(itemToPaste, acc ?: selectedText?.takeIf { it.isNotBlank() }) ?: acc
19321966
} ?: when (itemToPaste) {
19331967
is IClipboardPastePlugin.PastedItem.HtmlText -> itemToPaste.text
19341968
is IClipboardPastePlugin.PastedItem.Url -> itemToPaste.uri.path
19351969
is IClipboardPastePlugin.PastedItem.PastedIntent -> itemToPaste.intent.toString()
1936-
}
1970+
})!!
19371971

19381972
val newHtml = oldHtml.replace(
19391973
Constants.REPLACEMENT_MARKER_STRING,
@@ -2083,7 +2117,7 @@ open class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknown
20832117

20842118
unknownBlockSpanStart = text.getSpanStart(unknownHtmlSpan)
20852119
blockEditorDialog = builder.create()
2086-
blockEditorDialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
2120+
// blockEditorDialog?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
20872121
blockEditorDialog?.show()
20882122
}
20892123

0 commit comments

Comments
 (0)