Skip to content

Commit e16bf94

Browse files
authored
Merge pull request #466 from wordpress-mobile/issue/464-missing-suggestions
Issue/464 missing suggestions
2 parents 462503f + fe554bb commit e16bf94

File tree

9 files changed

+289
-84
lines changed

9 files changed

+289
-84
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
## [1.0-beta.7](https://github.com/wordpress-mobile/AztecEditor-Android/releases/tag/v1.0-beta.7) - 2017-08-15
2323
### Changed
2424
- Toolbar button highlighted state to use a color with more contrast
25+
- Fixed conflicts of autocorrect/suggestions with editor styling
2526

2627
### Fixed
2728
- Image/video loading placeholder drawable usage
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package org.wordpress.aztec.demo.tests
2+
3+
import android.support.test.rule.ActivityTestRule
4+
import org.junit.Rule
5+
import org.junit.Test
6+
import org.wordpress.aztec.demo.BaseTest
7+
import org.wordpress.aztec.demo.NonCalypsoActivity
8+
import org.wordpress.aztec.demo.pages.EditorPage
9+
10+
class NonCalypsoFormattingTests : BaseTest() {
11+
12+
@Rule
13+
@JvmField
14+
var mActivityTestRule = ActivityTestRule(NonCalypsoActivity::class.java)
15+
16+
@Test
17+
fun testRetainParagraphFormatting() {
18+
val text = "some text"
19+
val html = "<p>$text</p>"
20+
21+
EditorPage()
22+
.toggleHtml()
23+
.insertHTML(html)
24+
.toggleHtml()
25+
.toggleHtml()
26+
.verifyHTML(html)
27+
}
28+
}

app/src/main/AndroidManifest.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@
2626

2727
</activity>
2828

29+
<activity
30+
android:name=".NonCalypsoActivity"
31+
android:windowSoftInputMode="adjustResize|stateHidden"
32+
android:theme="@style/MainActivityTheme" >
33+
</activity>
34+
2935
<!-- Provider for exposing file URIs on Android 7+ -->
3036
<provider
3137
android:name="android.support.v4.content.FileProvider"

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ import org.xml.sax.Attributes
5959
import java.io.File
6060
import java.util.Random
6161

62-
class MainActivity : AppCompatActivity(),
62+
open class MainActivity : AppCompatActivity(),
6363
AztecText.OnImeBackListener,
6464
AztecText.OnImageTappedListener,
6565
AztecText.OnVideoTappedListener,
@@ -168,7 +168,7 @@ class MainActivity : AppCompatActivity(),
168168
private val REQUEST_MEDIA_PHOTO: Int = 2003
169169
private val REQUEST_MEDIA_VIDEO: Int = 2004
170170

171-
private lateinit var aztec: Aztec
171+
protected lateinit var aztec: Aztec
172172
private lateinit var mediaFile: String
173173
private lateinit var mediaPath: String
174174

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package org.wordpress.aztec.demo
2+
3+
import android.os.Bundle
4+
5+
class NonCalypsoActivity : MainActivity() {
6+
7+
override fun onCreate(savedInstanceState: Bundle?) {
8+
super.onCreate(savedInstanceState)
9+
10+
aztec.visualEditor.setCalypsoMode(false)
11+
aztec.sourceEditor?.setCalypsoMode(false)
12+
}
13+
}

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

Lines changed: 65 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,16 @@ import android.content.ClipData
2222
import android.content.ClipboardManager
2323
import android.content.Context
2424
import android.graphics.drawable.Drawable
25+
import android.os.Build
2526
import android.os.Bundle
2627
import android.os.Parcel
2728
import android.os.Parcelable
2829
import android.support.v4.content.ContextCompat
2930
import android.support.v7.app.AlertDialog
30-
import android.support.v7.widget.AppCompatAutoCompleteTextView
31+
import android.support.v7.widget.AppCompatEditText
3132
import android.text.Editable
33+
import android.text.InputFilter
34+
import android.text.InputType
3235
import android.text.Spannable
3336
import android.text.SpannableStringBuilder
3437
import android.text.Spanned
@@ -41,9 +44,6 @@ import android.view.LayoutInflater
4144
import android.view.View
4245
import android.view.WindowManager
4346
import android.view.inputmethod.BaseInputConnection
44-
import android.view.inputmethod.EditorInfo
45-
import android.view.inputmethod.InputConnection
46-
import android.view.inputmethod.InputConnectionWrapper
4747
import android.widget.EditText
4848
import org.wordpress.aztec.formatting.BlockFormatter
4949
import org.wordpress.aztec.formatting.InlineFormatter
@@ -84,6 +84,7 @@ import org.wordpress.aztec.watchers.InlineTextWatcher
8484
import org.wordpress.aztec.watchers.ParagraphBleedAdjuster
8585
import org.wordpress.aztec.watchers.ParagraphCollapseAdjuster
8686
import org.wordpress.aztec.watchers.ParagraphCollapseRemover
87+
import org.wordpress.aztec.watchers.SuggestionWatcher
8788
import org.wordpress.aztec.watchers.TextDeleter
8889
import org.wordpress.aztec.watchers.ZeroIndexContentWatcher
8990
import org.xml.sax.Attributes
@@ -92,7 +93,7 @@ import java.util.Arrays
9293
import java.util.LinkedList
9394

9495
@Suppress("UNUSED_PARAMETER")
95-
class AztecText : AppCompatAutoCompleteTextView, TextWatcher, UnknownHtmlSpan.OnUnknownHtmlTappedListener {
96+
class AztecText : AppCompatEditText, TextWatcher, UnknownHtmlSpan.OnUnknownHtmlTappedListener {
9697
companion object {
9798
val BLOCK_EDITOR_HTML_KEY = "RETAINED_BLOCK_HTML_KEY"
9899
val BLOCK_EDITOR_START_INDEX_KEY = "BLOCK_EDITOR_START_INDEX_KEY"
@@ -123,6 +124,7 @@ class AztecText : AppCompatAutoCompleteTextView, TextWatcher, UnknownHtmlSpan.On
123124
private var blockEditorDialog: AlertDialog? = null
124125
private var consumeEditEvent: Boolean = false
125126
private var consumeSelectionChangedEvent: Boolean = false
127+
private var isInlineTextHandlerEnabled: Boolean = true
126128

127129
private var onSelectionChangedListener: OnSelectionChangedListener? = null
128130
private var onImeBackListener: OnImeBackListener? = null
@@ -135,6 +137,8 @@ class AztecText : AppCompatAutoCompleteTextView, TextWatcher, UnknownHtmlSpan.On
135137
private var isLeadingStyleRemoved = false
136138
private var previousCursorPosition = 0
137139

140+
private var isHandlingBackspaceEvent = false
141+
138142
var isInCalypsoMode = true
139143

140144
private var unknownBlockSpanStart = -1
@@ -287,9 +291,11 @@ class AztecText : AppCompatAutoCompleteTextView, TextWatcher, UnknownHtmlSpan.On
287291
// triggers ClickableSpan onClick() events
288292
movementMethod = EnhancedMovementMethod
289293

290-
// detect the press of backspace from hardware keyboard when no characters are deleted (eg. at 0 index of EditText)
291-
setOnKeyListener { _, _, event ->
292-
handleBackspace(event)
294+
setupZeroIndexBackspaceDetection()
295+
296+
//disable auto suggestions/correct for older devices
297+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
298+
inputType = InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS
293299
}
294300

295301
install()
@@ -302,6 +308,29 @@ class AztecText : AppCompatAutoCompleteTextView, TextWatcher, UnknownHtmlSpan.On
302308
isViewInitialized = true
303309
}
304310

311+
// detect the press of backspace when no characters are deleted (eg. at 0 index of EditText)
312+
private fun setupZeroIndexBackspaceDetection() {
313+
//hardware keyboard
314+
setOnKeyListener { _, _, event ->
315+
handleBackspace(event)
316+
}
317+
318+
//software keyboard
319+
val emptyEditTextBackspaceDetector = InputFilter { source, start, end, dest, dstart, dend ->
320+
if (selectionStart == 0 && selectionEnd == 0
321+
&& end == 0 && start == 0
322+
&& dstart == 0 && dend == 0
323+
&& !isHandlingBackspaceEvent) {
324+
isHandlingBackspaceEvent = true
325+
handleBackspace(KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL))
326+
isHandlingBackspaceEvent = false
327+
}
328+
source
329+
}
330+
331+
filters = arrayOf(emptyEditTextBackspaceDetector)
332+
}
333+
305334
private fun handleBackspace(event: KeyEvent): Boolean {
306335
var wasStyleRemoved = false
307336
if (event.action == KeyEvent.ACTION_DOWN && event.keyCode == KeyEvent.KEYCODE_DEL) {
@@ -331,6 +360,10 @@ class AztecText : AppCompatAutoCompleteTextView, TextWatcher, UnknownHtmlSpan.On
331360

332361
EndOfParagraphMarkerAdder.install(this, verticalParagraphMargin)
333362

363+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
364+
SuggestionWatcher.install(this)
365+
}
366+
334367
InlineTextWatcher.install(inlineFormatter, this)
335368

336369
// NB: text change handler should not alter text before "afterTextChanged" is called otherwise not all watchers
@@ -484,7 +517,8 @@ class AztecText : AppCompatAutoCompleteTextView, TextWatcher, UnknownHtmlSpan.On
484517
}
485518

486519
companion object {
487-
@JvmField val CREATOR: Parcelable.Creator<SavedState> = object : Parcelable.Creator<SavedState> {
520+
@JvmField
521+
val CREATOR: Parcelable.Creator<SavedState> = object : Parcelable.Creator<SavedState> {
488522
override fun createFromParcel(source: Parcel): SavedState {
489523
return SavedState(source)
490524
}
@@ -944,6 +978,18 @@ class AztecText : AppCompatAutoCompleteTextView, TextWatcher, UnknownHtmlSpan.On
944978
consumeSelectionChangedEvent = false
945979
}
946980

981+
fun disableInlineTextHandling() {
982+
isInlineTextHandlerEnabled = false
983+
}
984+
985+
fun enableInlineTextHandling() {
986+
isInlineTextHandlerEnabled = true
987+
}
988+
989+
fun isInlineTextHandlerEnabled(): Boolean {
990+
return isInlineTextHandlerEnabled
991+
}
992+
947993
fun isOnSelectionListenerDisabled(): Boolean {
948994
return consumeSelectionChangedEvent
949995
}
@@ -1023,18 +1069,18 @@ class AztecText : AppCompatAutoCompleteTextView, TextWatcher, UnknownHtmlSpan.On
10231069
// do not copy unnecessary block hierarchy, just the minimum required
10241070
var deleteNext = false
10251071
output.getSpans(0, output.length, IAztecBlockSpan::class.java)
1026-
.sortedBy { it.nestingLevel }
1027-
.reversed()
1028-
.forEach {
1029-
if (deleteNext) {
1030-
output.removeSpan(it)
1031-
} else {
1032-
deleteNext = output.getSpanStart(it) == 0 && output.getSpanEnd(it) == output.length
1033-
if (deleteNext && it is AztecListItemSpan) {
1034-
deleteNext = false
1072+
.sortedBy { it.nestingLevel }
1073+
.reversed()
1074+
.forEach {
1075+
if (deleteNext) {
1076+
output.removeSpan(it)
1077+
} else {
1078+
deleteNext = output.getSpanStart(it) == 0 && output.getSpanEnd(it) == output.length
1079+
if (deleteNext && it is AztecListItemSpan) {
1080+
deleteNext = false
1081+
}
10351082
}
10361083
}
1037-
}
10381084

10391085
val html = Format.removeSourceEditorFormatting(parser.toHtml(output), isInCalypsoMode)
10401086

@@ -1202,28 +1248,6 @@ class AztecText : AppCompatAutoCompleteTextView, TextWatcher, UnknownHtmlSpan.On
12021248
blockEditorDialog!!.show()
12031249
}
12041250

1205-
// Custom input connection is used to detect the press of backspace when no characters are deleted
1206-
// (eg. at 0 index of EditText)
1207-
override fun onCreateInputConnection(outAttrs: EditorInfo): InputConnection {
1208-
return AztecInputConnection(super.onCreateInputConnection(outAttrs), true)
1209-
}
1210-
1211-
private inner class AztecInputConnection(target: InputConnection, mutable: Boolean) : InputConnectionWrapper(target, mutable) {
1212-
1213-
override fun sendKeyEvent(event: KeyEvent): Boolean {
1214-
handleBackspace(event)
1215-
return super.sendKeyEvent(event)
1216-
}
1217-
1218-
override fun deleteSurroundingText(beforeLength: Int, afterLength: Int): Boolean {
1219-
// detect pressing of backspace with soft keyboard on 0 index, when no text is deleted
1220-
if (beforeLength == 1 && afterLength == 0 && selectionStart == 0 && selectionEnd == 0) {
1221-
sendKeyEvent(KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL))
1222-
}
1223-
return super.deleteSurroundingText(beforeLength, afterLength)
1224-
}
1225-
}
1226-
12271251
private fun deleteInlineStyleFromTheBeginning() {
12281252
inlineFormatter.tryRemoveLeadingInlineStyle()
12291253
isLeadingStyleRemoved = true

0 commit comments

Comments
 (0)