Skip to content

Commit 0ff5b39

Browse files
committed
Merge branch 'develop' of github.com:wordpress-mobile/WordPress-Aztec-Android into issue/396-improving-image-click-detection
2 parents e831237 + bc4fe2d commit 0ff5b39

File tree

14 files changed

+356
-99
lines changed

14 files changed

+356
-99
lines changed

app/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ dependencies {
3737
compile project(':wordpress-comments')
3838

3939
//noinspection GradleCompatible
40-
compile "com.android.support:appcompat-v7:25.4.0"
40+
compile "com.android.support:appcompat-v7:25.3.1"
4141
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
4242
compile "org.wordpress:utils:1.16.0"
4343
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2', {
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package org.wordpress.aztec.demo
2+
3+
import android.support.test.espresso.action.ViewActions
4+
import android.support.test.espresso.action.ViewActions.closeSoftKeyboard
5+
import android.support.test.espresso.action.ViewActions.typeText
6+
import android.support.test.espresso.assertion.ViewAssertions.matches
7+
import android.support.test.espresso.matcher.ViewMatchers.*
8+
import android.support.test.rule.ActivityTestRule
9+
import android.support.test.runner.AndroidJUnit4
10+
import android.view.KeyEvent
11+
import org.junit.Rule
12+
import org.junit.Test
13+
import org.junit.runner.RunWith
14+
import org.wordpress.aztec.demo.TestUtils.*
15+
16+
@RunWith(AndroidJUnit4::class)
17+
class ToolbarHighlightingTest {
18+
19+
@Rule @JvmField
20+
var mActivityTestRule = ActivityTestRule(MainActivity::class.java)
21+
22+
//test behavior of highlighted style at 0 index of editor with 1 line of text (EOB marker at the 1 line)
23+
@Test
24+
fun testLeadingStyleHighlightInEmptyEditor() {
25+
boldButton.perform(betterScrollTo(), betterClick())
26+
aztecText.perform(typeText(formattedText))
27+
28+
italicButton.perform(betterScrollTo(), betterClick())
29+
30+
boldButton.check(matches(isChecked()))
31+
italicButton.check(matches(isChecked()))
32+
33+
formattedText.forEach {
34+
aztecText.perform(ViewActions.pressKey(KeyEvent.KEYCODE_DEL))
35+
}
36+
37+
boldButton.check(matches(isChecked()))
38+
italicButton.check(matches(isNotChecked()))
39+
40+
aztecText.perform(ViewActions.pressKey(KeyEvent.KEYCODE_DEL))
41+
42+
boldButton.check(matches(isNotChecked()))
43+
italicButton.check(matches(isNotChecked()))
44+
45+
}
46+
47+
//test behavior of highlighted style at 0 index of editor with > 1 lines of text (no EOB marker at the 1 line)
48+
@Test
49+
fun testLeadingStyleHighlightInNotEmptyEditor() {
50+
boldButton.perform(betterScrollTo(), betterClick())
51+
aztecText.perform(typeText(formattedText))
52+
italicButton.perform(betterScrollTo(), betterClick())
53+
54+
aztecText.perform(ViewActions.pressKey(KeyEvent.KEYCODE_ENTER))
55+
56+
boldButton.check(matches(isNotChecked()))
57+
italicButton.check(matches(isNotChecked()))
58+
59+
aztecText.perform(typeText(formattedText))
60+
61+
62+
formattedText.forEach {
63+
aztecText.perform(ViewActions.pressKey(KeyEvent.KEYCODE_DEL))
64+
}
65+
66+
formattedText.forEach {
67+
aztecText.perform(ViewActions.pressKey(KeyEvent.KEYCODE_DEL))
68+
}
69+
70+
aztecText.perform(ViewActions.pressKey(KeyEvent.KEYCODE_DEL))
71+
72+
boldButton.check(matches(isChecked()))
73+
italicButton.check(matches(isNotChecked()))
74+
75+
aztecText.perform(ViewActions.pressKey(KeyEvent.KEYCODE_DEL))
76+
77+
boldButton.check(matches(isNotChecked()))
78+
italicButton.check(matches(isNotChecked()))
79+
}
80+
81+
//make sure that inline style is not sticking to end of buffer marker
82+
@Test
83+
fun testInlineIsDeselectedNearEndOfBufferMarker() {
84+
boldButton.perform(betterScrollTo(), betterClick())
85+
aztecText.perform(typeText(formattedText))
86+
87+
boldButton.check(matches(isChecked()))
88+
boldButton.perform(betterScrollTo(), betterClick())
89+
boldButton.check(matches(isNotChecked()))
90+
91+
aztecText.perform(typeText(unformattedText))
92+
93+
boldButton.check(matches(isNotChecked()))
94+
95+
// Check that HTML formatting tags were correctly added
96+
toggleHTMLView()
97+
sourceText.check(matches(withText("<b>$formattedText</b>$unformattedText")))
98+
}
99+
100+
101+
//make sure that selected toolbar style in empty editor remains when soft keyboard is displayed
102+
@Test
103+
fun testStyleHighlightPersistenceInEmptyEditorOnWindowFocusChange() {
104+
aztecText.perform(closeSoftKeyboard()) //make sure keyboard is closed
105+
boldButton.perform(betterScrollTo(), betterClick())
106+
aztecText.perform(betterClick()) //click in editor so the soft keyboard is up
107+
108+
boldButton.check(matches(isChecked()))
109+
110+
aztecText.perform(closeSoftKeyboard())
111+
112+
boldButton.check(matches(isChecked()))
113+
114+
aztecText.perform(typeText(formattedText))
115+
toggleHTMLView()
116+
sourceText.check(matches(withText("<b>$formattedText</b>")))
117+
}
118+
119+
}

aztec/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,15 @@ android {
2525
}
2626

2727
dependencies {
28-
compile "com.android.support:support-v4:25.4.0"
28+
compile "com.android.support:support-v4:25.3.1"
2929
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
3030
compile 'org.ccil.cowan.tagsoup:tagsoup:1.2.1'
3131
compile 'org.jsoup:jsoup:1.10.2'
3232

3333
testCompile 'junit:junit:4.12'
3434
testCompile 'org.robolectric:robolectric:3.3.2'
3535

36-
compile 'com.android.support:design:25.4.0'
36+
compile 'com.android.support:design:25.3.1'
3737
//https://github.com/robolectric/robolectric/issues/1932
3838
testCompile 'org.khronos:opengl-api:gl1.1-android-2.1_r1'
3939
}

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

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,14 @@ import java.util.*
1313
open class Aztec private constructor(val visualEditor: AztecText, val sourceEditor: SourceViewEditText,
1414
val toolbar: AztecToolbar, val toolbarClickListener: IAztecToolbarClickListener) {
1515

16-
var imageGetter: Html.ImageGetter? = null
17-
var videoThumbnailGetter: Html.VideoThumbnailGetter? = null
18-
var imeBackListener: AztecText.OnImeBackListener? = null
19-
var onTouchListener: View.OnTouchListener? = null
20-
var historyListener: IHistoryListener? = null
21-
var onImageTappedListener: AztecText.OnImageTappedListener? = null
22-
var onVideoTappedListener: AztecText.OnVideoTappedListener? = null
23-
24-
var plugins: ArrayList<IAztecPlugin> = visualEditor.plugins
16+
private var imageGetter: Html.ImageGetter? = null
17+
private var videoThumbnailGetter: Html.VideoThumbnailGetter? = null
18+
private var imeBackListener: AztecText.OnImeBackListener? = null
19+
private var onTouchListener: View.OnTouchListener? = null
20+
private var historyListener: IHistoryListener? = null
21+
private var onImageTappedListener: AztecText.OnImageTappedListener? = null
22+
private var onVideoTappedListener: AztecText.OnVideoTappedListener? = null
23+
private var plugins: ArrayList<IAztecPlugin> = visualEditor.plugins
2524

2625
init {
2726
initHistory()

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

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,15 @@ class AztecText : AppCompatAutoCompleteTextView, TextWatcher, UnknownHtmlSpan.On
8686
private var addLinkDialog: AlertDialog? = null
8787
private var blockEditorDialog: AlertDialog? = null
8888
private var consumeEditEvent: Boolean = false
89+
private var consumeSelectionChangedEvent: Boolean = false
8990

9091
private var onSelectionChangedListener: OnSelectionChangedListener? = null
9192
private var onImeBackListener: OnImeBackListener? = null
9293
private var onImageTappedListener: OnImageTappedListener? = null
9394
private var onVideoTappedListener: OnVideoTappedListener? = null
9495

9596
private var isViewInitialized = false
97+
private var isLeadingStyleRemoved = false
9698
private var previousCursorPosition = 0
9799

98100
var isInCalypsoMode = true
@@ -235,9 +237,13 @@ class AztecText : AppCompatAutoCompleteTextView, TextWatcher, UnknownHtmlSpan.On
235237
// detect the press of backspace from hardware keyboard when no characters are deleted (eg. at 0 index of EditText)
236238
setOnKeyListener { v, keyCode, event ->
237239
var consumeKeyEvent = false
238-
history.beforeTextChanged(toFormattedHtml())
239240
if (keyCode == KeyEvent.KEYCODE_DEL && event.action == KeyEvent.ACTION_DOWN) {
240-
inlineFormatter.tryRemoveLeadingInlineStyle()
241+
history.beforeTextChanged(toFormattedHtml())
242+
if (selectionStart == 0 || selectionEnd == 0) {
243+
inlineFormatter.tryRemoveLeadingInlineStyle()
244+
isLeadingStyleRemoved = true
245+
onSelectionChanged(0, 0)
246+
}
241247
consumeKeyEvent = blockFormatter.tryRemoveBlockStyleFromFirstLine()
242248
}
243249

@@ -282,6 +288,7 @@ class AztecText : AppCompatAutoCompleteTextView, TextWatcher, UnknownHtmlSpan.On
282288
FullWidthImageElementWatcher.install(this)
283289

284290
EndOfBufferMarkerAdder.install(this)
291+
ZeroIndexContentWatcher.install(this)
285292
}
286293

287294
override fun onWindowFocusChanged(hasWindowFocus: Boolean) {
@@ -477,6 +484,11 @@ class AztecText : AppCompatAutoCompleteTextView, TextWatcher, UnknownHtmlSpan.On
477484
super.onSelectionChanged(selStart, selEnd)
478485
if (!isViewInitialized) return
479486

487+
if (isOnSelectionListenerDisabled()) {
488+
enableOnSelectionListener()
489+
return
490+
}
491+
480492
if (length() != 0) {
481493
// if the text end has the marker, let's make sure the cursor never includes it or surpasses it
482494
if ((selStart == length() || selEnd == length()) && text[length() - 1] == Constants.END_OF_BUFFER_MARKER) {
@@ -498,16 +510,23 @@ class AztecText : AppCompatAutoCompleteTextView, TextWatcher, UnknownHtmlSpan.On
498510

499511
previousCursorPosition = selEnd
500512

501-
onSelectionChangedListener?.onSelectionChanged(selStart, selEnd)
502513

514+
//do not update toolbar or selected styles when we removed the last character in editor
515+
if (!isLeadingStyleRemoved && length() == 1 && text[0] == Constants.END_OF_BUFFER_MARKER) {
516+
return
517+
}
518+
519+
onSelectionChangedListener?.onSelectionChanged(selStart, selEnd)
503520
setSelectedStyles(getAppliedStyles(selStart, selEnd))
521+
522+
isLeadingStyleRemoved = false
504523
}
505524

525+
506526
override fun getSelectionStart(): Int {
507527
return Math.min(super.getSelectionStart(), super.getSelectionEnd())
508528
}
509529

510-
511530
override fun getSelectionEnd(): Int {
512531
return Math.max(super.getSelectionStart(), super.getSelectionEnd())
513532
}
@@ -843,6 +862,19 @@ class AztecText : AppCompatAutoCompleteTextView, TextWatcher, UnknownHtmlSpan.On
843862
return consumeEditEvent
844863
}
845864

865+
fun disableOnSelectionListener() {
866+
consumeSelectionChangedEvent = true
867+
}
868+
869+
fun enableOnSelectionListener() {
870+
consumeSelectionChangedEvent = false
871+
}
872+
873+
fun isOnSelectionListenerDisabled(): Boolean {
874+
return consumeSelectionChangedEvent
875+
}
876+
877+
846878
fun refreshText() {
847879
disableTextChangedListener()
848880
val selStart = selectionStart
@@ -893,6 +925,13 @@ class AztecText : AppCompatAutoCompleteTextView, TextWatcher, UnknownHtmlSpan.On
893925
android.R.id.cut -> {
894926
copy(text, min, max)
895927
text.delete(min, max) //this will hide text action menu
928+
929+
//if we are cutting text from the beginning of editor, remove leading inline style
930+
if (min == 0) {
931+
inlineFormatter.tryRemoveLeadingInlineStyle()
932+
isLeadingStyleRemoved = true
933+
onSelectionChanged(0, 0)
934+
}
896935
}
897936
else -> return super.onTextContextMenuItem(id)
898937
}
@@ -1067,10 +1106,16 @@ class AztecText : AppCompatAutoCompleteTextView, TextWatcher, UnknownHtmlSpan.On
10671106

10681107
override fun sendKeyEvent(event: KeyEvent): Boolean {
10691108
if (event.action == KeyEvent.ACTION_DOWN && event.keyCode == KeyEvent.KEYCODE_DEL) {
1109+
val isStyleRemoved = blockFormatter.tryRemoveBlockStyleFromFirstLine()
1110+
10701111
history.beforeTextChanged(toFormattedHtml())
1112+
if (selectionStart == 0 || selectionEnd == 0) {
1113+
inlineFormatter.tryRemoveLeadingInlineStyle()
1114+
isLeadingStyleRemoved = true
1115+
onSelectionChanged(0, 0)
1116+
return false
1117+
}
10711118

1072-
inlineFormatter.tryRemoveLeadingInlineStyle()
1073-
val isStyleRemoved = blockFormatter.tryRemoveBlockStyleFromFirstLine()
10741119
if (isStyleRemoved) {
10751120
history.handleHistory(this@AztecText)
10761121
return false
@@ -1080,6 +1125,10 @@ class AztecText : AppCompatAutoCompleteTextView, TextWatcher, UnknownHtmlSpan.On
10801125
}
10811126

10821127
override fun deleteSurroundingText(beforeLength: Int, afterLength: Int): Boolean {
1128+
//detect pressing of backspace with soft keyboard on 0 index, when no text is deleted
1129+
if (beforeLength == 1 && afterLength == 0 && selectionStart == 0 && selectionEnd == 0) {
1130+
sendKeyEvent(KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL))
1131+
}
10831132
return super.deleteSurroundingText(beforeLength, afterLength)
10841133
}
10851134
}

0 commit comments

Comments
 (0)