Skip to content

Commit b985274

Browse files
fix(android): set piority of applied spans
1 parent a253348 commit b985274

10 files changed

Lines changed: 62 additions & 18 deletions

File tree

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.swmansion.enriched.common
2+
3+
import android.text.Spannable
4+
import com.swmansion.enriched.common.spans.interfaces.EnrichedInlineSpan
5+
import com.swmansion.enriched.common.spans.interfaces.EnrichedSpan
6+
7+
object EnrichedSpanFlags {
8+
private const val PARAGRAPH_SPAN_PRIORITY = 2
9+
private const val INLINE_SPAN_PRIORITY = 1
10+
11+
@JvmField
12+
val paragraphSpanFlags: Int = applyPriority(Spannable.SPAN_EXCLUSIVE_EXCLUSIVE, PARAGRAPH_SPAN_PRIORITY)
13+
14+
@JvmField
15+
val inlineSpanFlags: Int = applyPriority(Spannable.SPAN_EXCLUSIVE_EXCLUSIVE, INLINE_SPAN_PRIORITY)
16+
17+
fun forSpan(
18+
span: EnrichedSpan,
19+
baseFlags: Int,
20+
): Int {
21+
val isInlineSpan = span is EnrichedInlineSpan
22+
val priority = if (isInlineSpan) INLINE_SPAN_PRIORITY else PARAGRAPH_SPAN_PRIORITY
23+
return applyPriority(baseFlags, priority)
24+
}
25+
26+
private fun applyPriority(
27+
flags: Int,
28+
priority: Int,
29+
): Int {
30+
// Cleaning up priority bits
31+
val cleared = flags and Spannable.SPAN_PRIORITY.inv()
32+
// Injecting priority bits
33+
return cleared or ((priority shl Spannable.SPAN_PRIORITY_SHIFT) and Spannable.SPAN_PRIORITY)
34+
}
35+
}

android/src/main/java/com/swmansion/enriched/common/parser/EnrichedParser.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import android.text.style.AlignmentSpan;
1010
import android.text.style.ParagraphStyle;
1111
import com.swmansion.enriched.common.EnrichedConstants;
12+
import com.swmansion.enriched.common.EnrichedSpanFlags;
1213
import com.swmansion.enriched.common.spans.EnrichedBoldSpan;
1314
import com.swmansion.enriched.common.spans.EnrichedCheckboxListSpan;
1415
import com.swmansion.enriched.common.spans.EnrichedCodeBlockSpan;
@@ -435,7 +436,7 @@ public Spanned convert() {
435436
// TODO: verify if Spannable.SPAN_EXCLUSIVE_EXCLUSIVE does not break anything.
436437
// Previously it was SPAN_PARAGRAPH. I've changed that in order to fix ranges for list
437438
// items.
438-
mSpannableStringBuilder.setSpan(obj[i], start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
439+
mSpannableStringBuilder.setSpan(obj[i], start, end, EnrichedSpanFlags.paragraphSpanFlags);
439440
}
440441
}
441442

@@ -455,7 +456,7 @@ public Spanned convert() {
455456

456457
mSpannableStringBuilder.removeSpan(zeroWidthSpaceSpan);
457458
mSpannableStringBuilder.setSpan(
458-
zeroWidthSpaceSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
459+
zeroWidthSpaceSpan, start, end, EnrichedSpanFlags.paragraphSpanFlags);
459460
}
460461

461462
return mSpannableStringBuilder;
@@ -735,7 +736,7 @@ private static void setSpanFromMark(Spannable text, Object mark, Object... spans
735736
int len = text.length();
736737
if (where != len) {
737738
for (Object span : spans) {
738-
text.setSpan(span, where, len, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
739+
text.setSpan(span, where, len, EnrichedSpanFlags.inlineSpanFlags);
739740
}
740741
}
741742
}
@@ -758,7 +759,7 @@ private static void setParagraphSpanFromMark(Editable text, Object mark, Object.
758759

759760
if (where != len) {
760761
for (Object span : spans) {
761-
text.setSpan(span, where, len, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
762+
text.setSpan(span, where, len, EnrichedSpanFlags.paragraphSpanFlags);
762763
}
763764
}
764765
}

android/src/main/java/com/swmansion/enriched/text/EnrichedTextView.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import com.facebook.react.views.text.ReactTypefaceUtils.applyStyles
2424
import com.facebook.react.views.text.ReactTypefaceUtils.parseFontStyle
2525
import com.facebook.react.views.text.ReactTypefaceUtils.parseFontWeight
2626
import com.swmansion.enriched.common.EnrichedConstants
27+
import com.swmansion.enriched.common.EnrichedSpanFlags
2728
import com.swmansion.enriched.common.GumboNormalizer
2829
import com.swmansion.enriched.common.parser.EnrichedParser
2930
import com.swmansion.enriched.text.spans.EnrichedTextImageSpan
@@ -266,7 +267,7 @@ class EnrichedTextView : AppCompatTextView {
266267

267268
spannable.removeSpan(span)
268269
val newSpan = span.rebuildWithStyle(enrichedStyle)
269-
spannable.setSpan(newSpan, start, end, flags)
270+
spannable.setSpan(newSpan, start, end, EnrichedSpanFlags.forSpan(newSpan, flags))
270271
modified = true
271272
}
272273

android/src/main/java/com/swmansion/enriched/textinput/EnrichedTextInputView.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import com.facebook.react.views.text.ReactTypefaceUtils.applyStyles
3939
import com.facebook.react.views.text.ReactTypefaceUtils.parseFontStyle
4040
import com.facebook.react.views.text.ReactTypefaceUtils.parseFontWeight
4141
import com.swmansion.enriched.common.EnrichedConstants
42+
import com.swmansion.enriched.common.EnrichedSpanFlags
4243
import com.swmansion.enriched.common.GumboNormalizer
4344
import com.swmansion.enriched.common.parser.EnrichedParser
4445
import com.swmansion.enriched.textinput.events.MentionHandler
@@ -1068,7 +1069,7 @@ class EnrichedTextInputView :
10681069

10691070
spannable.removeSpan(span)
10701071
val newSpan = span.rebuildWithStyle(htmlStyle)
1071-
spannable.setSpan(newSpan, start, end, flags)
1072+
spannable.setSpan(newSpan, start, end, EnrichedSpanFlags.forSpan(newSpan, flags))
10721073
}
10731074

10741075
if (shouldEmitStateChange) {

android/src/main/java/com/swmansion/enriched/textinput/styles/InlineStyles.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.swmansion.enriched.textinput.styles
22

33
import android.text.Editable
44
import android.text.Spannable
5+
import com.swmansion.enriched.common.EnrichedSpanFlags
56
import com.swmansion.enriched.textinput.EnrichedTextInputView
67
import com.swmansion.enriched.textinput.spans.EnrichedSpans
78
import com.swmansion.enriched.textinput.utils.getSafeSpanBoundaries
@@ -41,7 +42,7 @@ class InlineStyles(
4142

4243
val span = type.getDeclaredConstructor(HtmlStyle::class.java).newInstance(view.htmlStyle)
4344
val (safeStart, safeEnd) = spannable.getSafeSpanBoundaries(minimum, maximum)
44-
spannable.setSpan(span, safeStart, safeEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
45+
spannable.setSpan(span, safeStart, safeEnd, EnrichedSpanFlags.inlineSpanFlags)
4546
}
4647

4748
private fun <T> setAndMergeSpans(

android/src/main/java/com/swmansion/enriched/textinput/styles/ListStyles.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import android.text.Spannable
55
import android.text.SpannableStringBuilder
66
import android.text.Spanned
77
import com.swmansion.enriched.common.EnrichedConstants
8+
import com.swmansion.enriched.common.EnrichedSpanFlags
89
import com.swmansion.enriched.textinput.EnrichedTextInputView
910
import com.swmansion.enriched.textinput.spans.EnrichedInputCheckboxListSpan
1011
import com.swmansion.enriched.textinput.spans.EnrichedInputOrderedListSpan
@@ -65,18 +66,18 @@ class ListStyles(
6566
when (name) {
6667
EnrichedSpans.UNORDERED_LIST -> {
6768
val span = EnrichedInputUnorderedListSpan(view.htmlStyle)
68-
spannable.setSpan(span, safeStart, safeEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
69+
spannable.setSpan(span, safeStart, safeEnd, EnrichedSpanFlags.paragraphSpanFlags)
6970
}
7071

7172
EnrichedSpans.ORDERED_LIST -> {
7273
val index = getOrderedListIndex(spannable, safeStart)
7374
val span = EnrichedInputOrderedListSpan(index, view.htmlStyle)
74-
spannable.setSpan(span, safeStart, safeEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
75+
spannable.setSpan(span, safeStart, safeEnd, EnrichedSpanFlags.paragraphSpanFlags)
7576
}
7677

7778
EnrichedSpans.CHECKBOX_LIST -> {
7879
val span = EnrichedInputCheckboxListSpan(isChecked ?: false, view.htmlStyle)
79-
spannable.setSpan(span, safeStart, safeEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
80+
spannable.setSpan(span, safeStart, safeEnd, EnrichedSpanFlags.paragraphSpanFlags)
8081

8182
// Invalidate layout to update checkbox drawing in case checkbox is bigger than line height
8283
view.layoutManager.invalidateLayout()

android/src/main/java/com/swmansion/enriched/textinput/styles/ParagraphStyles.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import android.text.Spannable
55
import android.text.SpannableStringBuilder
66
import android.util.Log
77
import com.swmansion.enriched.common.EnrichedConstants
8+
import com.swmansion.enriched.common.EnrichedSpanFlags
89
import com.swmansion.enriched.textinput.EnrichedTextInputView
910
import com.swmansion.enriched.textinput.spans.EnrichedSpans
1011
import com.swmansion.enriched.textinput.spans.interfaces.EnrichedInputSpan
@@ -89,7 +90,7 @@ class ParagraphStyles(
8990
}
9091

9192
val (safeStart, safeEnd) = spannable.getSafeSpanBoundaries(newStart, newEnd)
92-
spannable.setSpan(span, safeStart, safeEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
93+
spannable.setSpan(span, safeStart, safeEnd, EnrichedSpanFlags.paragraphSpanFlags)
9394
}
9495

9596
private fun <T> setSpan(
@@ -105,7 +106,7 @@ class ParagraphStyles(
105106

106107
val span = type.getDeclaredConstructor(HtmlStyle::class.java).newInstance(view.htmlStyle)
107108
val (safeStart, safeEnd) = spannable.getSafeSpanBoundaries(start, end)
108-
spannable.setSpan(span, safeStart, safeEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
109+
spannable.setSpan(span, safeStart, safeEnd, EnrichedSpanFlags.paragraphSpanFlags)
109110
}
110111

111112
// Removes spans of the given type in the specified range.
@@ -232,7 +233,7 @@ class ParagraphStyles(
232233
val (safeStart, safeEnd) = s.getSafeSpanBoundaries(newStart, newEnd)
233234
val span = type.getDeclaredConstructor(HtmlStyle::class.java).newInstance(view.htmlStyle)
234235

235-
s.setSpan(span, safeStart, safeEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
236+
s.setSpan(span, safeStart, safeEnd, EnrichedSpanFlags.paragraphSpanFlags)
236237
}
237238

238239
private fun handleConflictsDuringNewlineDeletion(

android/src/main/java/com/swmansion/enriched/textinput/styles/ParametrizedStyles.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import android.text.Spannable
55
import android.text.SpannableStringBuilder
66
import android.text.Spanned
77
import com.swmansion.enriched.common.EnrichedConstants
8+
import com.swmansion.enriched.common.EnrichedSpanFlags
89
import com.swmansion.enriched.textinput.EnrichedTextInputView
910
import com.swmansion.enriched.textinput.spans.EnrichedInputImageSpan
1011
import com.swmansion.enriched.textinput.spans.EnrichedInputLinkSpan
@@ -63,7 +64,7 @@ class ParametrizedStyles(
6364
val spanEnd = start + text.length
6465
val span = EnrichedInputLinkSpan(url, view.htmlStyle, true)
6566
val (safeStart, safeEnd) = spannable.getSafeSpanBoundaries(start, spanEnd)
66-
spannable.setSpan(span, safeStart, safeEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
67+
spannable.setSpan(span, safeStart, safeEnd, EnrichedSpanFlags.inlineSpanFlags)
6768

6869
view.selection?.validateStyles()
6970
isSettingLinkSpan = false
@@ -160,7 +161,7 @@ class ParametrizedStyles(
160161
span,
161162
safeStart,
162163
safeEnd,
163-
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE,
164+
EnrichedSpanFlags.inlineSpanFlags,
164165
)
165166
}
166167
}
@@ -373,7 +374,7 @@ class ParametrizedStyles(
373374
val span = EnrichedInputMentionSpan(text, indicator, attributes, view.htmlStyle)
374375
val spanEnd = start + text.length
375376
val (safeStart, safeEnd) = spannable.getSafeSpanBoundaries(start, spanEnd)
376-
spannable.setSpan(span, safeStart, safeEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
377+
spannable.setSpan(span, safeStart, safeEnd, EnrichedSpanFlags.inlineSpanFlags)
377378

378379
val hasSpaceAtTheEnd = spannable.length > safeEnd && spannable[safeEnd] == ' '
379380
if (!hasSpaceAtTheEnd) {

android/src/main/java/com/swmansion/enriched/textinput/utils/EnrichedSpannable.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.swmansion.enriched.textinput.utils
33
import android.text.Spannable
44
import android.text.SpannableString
55
import android.text.SpannableStringBuilder
6+
import com.swmansion.enriched.common.EnrichedSpanFlags
67
import com.swmansion.enriched.common.spans.interfaces.EnrichedBlockSpan
78
import com.swmansion.enriched.common.spans.interfaces.EnrichedParagraphSpan
89
import com.swmansion.enriched.common.spans.interfaces.EnrichedSpan
@@ -144,7 +145,7 @@ fun Spannable.mergeSpannables(
144145
val (_, newParagraphEnd) = builder.getParagraphBounds(spanStart, pasteEnd)
145146
val flags = builder.getSpanFlags(span)
146147
builder.removeSpan(span)
147-
builder.setSpan(span, spanStart, newParagraphEnd, flags)
148+
builder.setSpan(span, spanStart, newParagraphEnd, EnrichedSpanFlags.forSpan(span, flags))
148149
}
149150
}
150151

android/src/main/java/com/swmansion/enriched/textinput/utils/Utils.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import android.text.Spanned
77
import android.util.Log
88
import android.view.MotionEvent
99
import android.widget.TextView
10+
import com.swmansion.enriched.common.EnrichedSpanFlags
1011
import com.swmansion.enriched.textinput.spans.EnrichedInputCheckboxListSpan
1112
import org.json.JSONObject
1213

@@ -78,7 +79,7 @@ fun TextView.setCheckboxClickListener() {
7879

7980
// Reapply span so changes are visible without need to redraw entire TextView
8081
spannable.removeSpan(span)
81-
spannable.setSpan(span, start, end, flags)
82+
spannable.setSpan(span, start, end, EnrichedSpanFlags.forSpan(span, flags))
8283

8384
// For focused input, ensure cursor is active for affected paragraph
8485
if (tv.isFocused) {

0 commit comments

Comments
 (0)