react-native-enriched 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -17
- package/android/build.gradle +77 -72
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerDelegate.java +21 -0
- package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerInterface.java +7 -0
- package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/EventEmitters.cpp +156 -0
- package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/EventEmitters.h +147 -0
- package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/Props.cpp +10 -0
- package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/Props.h +194 -0
- package/android/lint.gradle +70 -0
- package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputConnectionWrapper.kt +140 -0
- package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputView.kt +304 -83
- package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewLayoutManager.kt +3 -1
- package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewManager.kt +166 -51
- package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewPackage.kt +1 -3
- package/android/src/main/java/com/swmansion/enriched/MeasurementStore.kt +70 -21
- package/android/src/main/java/com/swmansion/enriched/events/MentionHandler.kt +21 -11
- package/android/src/main/java/com/swmansion/enriched/events/OnChangeHtmlEvent.kt +8 -9
- package/android/src/main/java/com/swmansion/enriched/events/OnChangeSelectionEvent.kt +10 -9
- package/android/src/main/java/com/swmansion/enriched/events/OnChangeStateDeprecatedEvent.kt +21 -0
- package/android/src/main/java/com/swmansion/enriched/events/OnChangeStateEvent.kt +9 -12
- package/android/src/main/java/com/swmansion/enriched/events/OnChangeTextEvent.kt +10 -10
- package/android/src/main/java/com/swmansion/enriched/events/OnInputBlurEvent.kt +7 -9
- package/android/src/main/java/com/swmansion/enriched/events/OnInputFocusEvent.kt +7 -9
- package/android/src/main/java/com/swmansion/enriched/events/OnInputKeyPressEvent.kt +27 -0
- package/android/src/main/java/com/swmansion/enriched/events/OnLinkDetectedEvent.kt +13 -11
- package/android/src/main/java/com/swmansion/enriched/events/OnMentionDetectedEvent.kt +10 -9
- package/android/src/main/java/com/swmansion/enriched/events/OnMentionEvent.kt +9 -8
- package/android/src/main/java/com/swmansion/enriched/events/OnRequestHtmlResultEvent.kt +32 -0
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedBlockQuoteSpan.kt +24 -5
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedBoldSpan.kt +8 -1
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedCodeBlockSpan.kt +10 -2
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH1Span.kt +8 -1
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH2Span.kt +8 -1
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH3Span.kt +8 -1
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH4Span.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH5Span.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH6Span.kt +24 -0
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedImageSpan.kt +34 -17
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedInlineCodeSpan.kt +8 -1
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedItalicSpan.kt +7 -1
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedLinkSpan.kt +10 -4
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedMentionSpan.kt +14 -11
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedOrderedListSpan.kt +18 -11
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedSpans.kt +174 -72
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedStrikeThroughSpan.kt +7 -1
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedUnderlineSpan.kt +7 -1
- package/android/src/main/java/com/swmansion/enriched/spans/EnrichedUnorderedListSpan.kt +11 -5
- package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedBlockSpan.kt +3 -2
- package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedHeadingSpan.kt +1 -2
- package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedInlineSpan.kt +1 -2
- package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedParagraphSpan.kt +3 -2
- package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedSpan.kt +5 -0
- package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedZeroWidthSpaceSpan.kt +1 -2
- package/android/src/main/java/com/swmansion/enriched/spans/utils/ForceRedrawSpan.kt +2 -1
- package/android/src/main/java/com/swmansion/enriched/styles/HtmlStyle.kt +155 -20
- package/android/src/main/java/com/swmansion/enriched/styles/InlineStyles.kt +25 -8
- package/android/src/main/java/com/swmansion/enriched/styles/ListStyles.kt +60 -20
- package/android/src/main/java/com/swmansion/enriched/styles/ParagraphStyles.kt +161 -25
- package/android/src/main/java/com/swmansion/enriched/styles/ParametrizedStyles.kt +128 -52
- package/android/src/main/java/com/swmansion/enriched/utils/AsyncDrawable.kt +10 -7
- package/android/src/main/java/com/swmansion/enriched/utils/EnrichedConstants.kt +11 -0
- package/android/src/main/java/com/swmansion/enriched/utils/EnrichedEditableFactory.kt +17 -0
- package/android/src/main/java/com/swmansion/enriched/utils/EnrichedParser.java +136 -87
- package/android/src/main/java/com/swmansion/enriched/utils/EnrichedSelection.kt +71 -42
- package/android/src/main/java/com/swmansion/enriched/utils/EnrichedSpanState.kt +183 -48
- package/android/src/main/java/com/swmansion/enriched/utils/EnrichedSpannable.kt +82 -0
- package/android/src/main/java/com/swmansion/enriched/utils/EnrichedSpannableStringBuilder.kt +15 -0
- package/android/src/main/java/com/swmansion/enriched/utils/Utils.kt +0 -70
- package/android/src/main/java/com/swmansion/enriched/watchers/EnrichedSpanWatcher.kt +46 -14
- package/android/src/main/java/com/swmansion/enriched/watchers/EnrichedTextWatcher.kt +34 -11
- package/android/src/main/new_arch/CMakeLists.txt +6 -0
- package/android/src/main/new_arch/RNEnrichedTextInputViewSpec.cpp +6 -6
- package/android/src/main/new_arch/RNEnrichedTextInputViewSpec.h +6 -6
- package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputComponentDescriptor.h +19 -19
- package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputMeasurementManager.cpp +40 -51
- package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputMeasurementManager.h +13 -15
- package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputShadowNode.cpp +23 -21
- package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputShadowNode.h +35 -36
- package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputState.cpp +4 -4
- package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputState.h +13 -14
- package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/conversions.h +33 -14
- package/ios/EnrichedTextInputView.h +26 -14
- package/ios/EnrichedTextInputView.mm +1209 -586
- package/ios/config/InputConfig.h +24 -6
- package/ios/config/InputConfig.mm +154 -38
- package/ios/{utils → extensions}/ColorExtension.mm +7 -5
- package/ios/extensions/FontExtension.mm +106 -0
- package/ios/{utils → extensions}/LayoutManagerExtension.h +1 -1
- package/ios/extensions/LayoutManagerExtension.mm +396 -0
- package/ios/{utils → extensions}/StringExtension.mm +19 -16
- package/ios/generated/RNEnrichedTextInputViewSpec/EventEmitters.cpp +156 -0
- package/ios/generated/RNEnrichedTextInputViewSpec/EventEmitters.h +147 -0
- package/ios/generated/RNEnrichedTextInputViewSpec/Props.cpp +10 -0
- package/ios/generated/RNEnrichedTextInputViewSpec/Props.h +194 -0
- package/ios/generated/RNEnrichedTextInputViewSpec/RCTComponentViewHelpers.h +95 -0
- package/ios/inputParser/InputParser.h +5 -5
- package/ios/inputParser/InputParser.mm +864 -380
- package/ios/inputTextView/InputTextView.h +1 -1
- package/ios/inputTextView/InputTextView.mm +100 -59
- package/ios/{utils → interfaces}/BaseStyleProtocol.h +2 -2
- package/ios/interfaces/ImageAttachment.h +10 -0
- package/ios/interfaces/ImageAttachment.mm +36 -0
- package/ios/interfaces/LinkRegexConfig.h +19 -0
- package/ios/interfaces/LinkRegexConfig.mm +37 -0
- package/ios/interfaces/MediaAttachment.h +23 -0
- package/ios/interfaces/MediaAttachment.mm +31 -0
- package/ios/{utils → interfaces}/MentionParams.h +0 -1
- package/ios/{utils → interfaces}/MentionStyleProps.mm +27 -20
- package/ios/{utils → interfaces}/StyleHeaders.h +37 -15
- package/ios/{utils → interfaces}/StyleTypeEnum.h +3 -0
- package/ios/internals/EnrichedTextInputViewComponentDescriptor.h +11 -9
- package/ios/internals/EnrichedTextInputViewShadowNode.h +28 -25
- package/ios/internals/EnrichedTextInputViewShadowNode.mm +45 -40
- package/ios/internals/EnrichedTextInputViewState.h +3 -1
- package/ios/styles/BlockQuoteStyle.mm +189 -118
- package/ios/styles/BoldStyle.mm +110 -63
- package/ios/styles/CodeBlockStyle.mm +204 -128
- package/ios/styles/H1Style.mm +10 -4
- package/ios/styles/H2Style.mm +10 -4
- package/ios/styles/H3Style.mm +10 -4
- package/ios/styles/H4Style.mm +17 -0
- package/ios/styles/H5Style.mm +17 -0
- package/ios/styles/H6Style.mm +17 -0
- package/ios/styles/HeadingStyleBase.mm +148 -86
- package/ios/styles/ImageStyle.mm +75 -73
- package/ios/styles/InlineCodeStyle.mm +162 -88
- package/ios/styles/ItalicStyle.mm +76 -52
- package/ios/styles/LinkStyle.mm +411 -232
- package/ios/styles/MentionStyle.mm +363 -246
- package/ios/styles/OrderedListStyle.mm +171 -106
- package/ios/styles/StrikethroughStyle.mm +52 -35
- package/ios/styles/UnderlineStyle.mm +68 -46
- package/ios/styles/UnorderedListStyle.mm +169 -106
- package/ios/utils/OccurenceUtils.h +42 -42
- package/ios/utils/OccurenceUtils.mm +142 -119
- package/ios/utils/ParagraphAttributesUtils.h +10 -2
- package/ios/utils/ParagraphAttributesUtils.mm +182 -71
- package/ios/utils/ParagraphsUtils.h +2 -1
- package/ios/utils/ParagraphsUtils.mm +41 -27
- package/ios/utils/TextInsertionUtils.h +13 -2
- package/ios/utils/TextInsertionUtils.mm +38 -20
- package/ios/utils/WordsUtils.h +2 -1
- package/ios/utils/WordsUtils.mm +32 -22
- package/ios/utils/ZeroWidthSpaceUtils.h +3 -1
- package/ios/utils/ZeroWidthSpaceUtils.mm +145 -79
- package/lib/module/EnrichedTextInput.js +61 -2
- package/lib/module/EnrichedTextInput.js.map +1 -1
- package/lib/module/EnrichedTextInputNativeComponent.ts +149 -12
- package/lib/module/{normalizeHtmlStyle.js → utils/normalizeHtmlStyle.js} +12 -0
- package/lib/module/utils/normalizeHtmlStyle.js.map +1 -0
- package/lib/module/utils/regexParser.js +46 -0
- package/lib/module/utils/regexParser.js.map +1 -0
- package/lib/typescript/src/EnrichedTextInput.d.ts +24 -14
- package/lib/typescript/src/EnrichedTextInput.d.ts.map +1 -1
- package/lib/typescript/src/EnrichedTextInputNativeComponent.d.ts +129 -12
- package/lib/typescript/src/EnrichedTextInputNativeComponent.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +1 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/utils/normalizeHtmlStyle.d.ts +4 -0
- package/lib/typescript/src/utils/normalizeHtmlStyle.d.ts.map +1 -0
- package/lib/typescript/src/utils/regexParser.d.ts +3 -0
- package/lib/typescript/src/utils/regexParser.d.ts.map +1 -0
- package/package.json +17 -6
- package/src/EnrichedTextInput.tsx +96 -13
- package/src/EnrichedTextInputNativeComponent.ts +149 -12
- package/src/index.tsx +2 -0
- package/src/{normalizeHtmlStyle.ts → utils/normalizeHtmlStyle.ts} +14 -2
- package/src/utils/regexParser.ts +56 -0
- package/ios/utils/FontExtension.mm +0 -91
- package/ios/utils/LayoutManagerExtension.mm +0 -286
- package/lib/module/normalizeHtmlStyle.js.map +0 -1
- package/lib/typescript/src/normalizeHtmlStyle.d.ts +0 -4
- package/lib/typescript/src/normalizeHtmlStyle.d.ts.map +0 -1
- package/ios/{utils → extensions}/ColorExtension.h +0 -0
- package/ios/{utils → extensions}/FontExtension.h +0 -0
- package/ios/{utils → extensions}/StringExtension.h +1 -1
- package/ios/{utils → interfaces}/ImageData.h +0 -0
- package/ios/{utils → interfaces}/ImageData.mm +0 -0
- package/ios/{utils → interfaces}/LinkData.h +0 -0
- package/ios/{utils → interfaces}/LinkData.mm +0 -0
- package/ios/{utils → interfaces}/MentionParams.mm +0 -0
- package/ios/{utils → interfaces}/MentionStyleProps.h +1 -1
- /package/ios/{utils → interfaces}/StylePair.h +0 -0
- /package/ios/{utils → interfaces}/StylePair.mm +0 -0
- /package/ios/{utils → interfaces}/TextDecorationLineEnum.h +0 -0
- /package/ios/{utils → interfaces}/TextDecorationLineEnum.mm +0 -0
|
@@ -5,14 +5,21 @@ import android.text.Spannable
|
|
|
5
5
|
import android.text.SpannableStringBuilder
|
|
6
6
|
import android.util.Log
|
|
7
7
|
import com.swmansion.enriched.EnrichedTextInputView
|
|
8
|
-
import com.swmansion.enriched.spans.EnrichedBlockQuoteSpan
|
|
9
|
-
import com.swmansion.enriched.spans.EnrichedCodeBlockSpan
|
|
10
8
|
import com.swmansion.enriched.spans.EnrichedSpans
|
|
9
|
+
import com.swmansion.enriched.spans.interfaces.EnrichedSpan
|
|
10
|
+
import com.swmansion.enriched.utils.EnrichedConstants
|
|
11
11
|
import com.swmansion.enriched.utils.getParagraphBounds
|
|
12
12
|
import com.swmansion.enriched.utils.getSafeSpanBoundaries
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
import com.swmansion.enriched.utils.removeZWS
|
|
14
|
+
|
|
15
|
+
class ParagraphStyles(
|
|
16
|
+
private val view: EnrichedTextInputView,
|
|
17
|
+
) {
|
|
18
|
+
private fun <T> getPreviousParagraphSpan(
|
|
19
|
+
spannable: Spannable,
|
|
20
|
+
paragraphStart: Int,
|
|
21
|
+
type: Class<T>,
|
|
22
|
+
): T? {
|
|
16
23
|
if (paragraphStart <= 0) return null
|
|
17
24
|
|
|
18
25
|
val (previousParagraphStart, previousParagraphEnd) = spannable.getParagraphBounds(paragraphStart - 1)
|
|
@@ -31,7 +38,11 @@ class ParagraphStyles(private val view: EnrichedTextInputView) {
|
|
|
31
38
|
return null
|
|
32
39
|
}
|
|
33
40
|
|
|
34
|
-
private fun <T>getNextParagraphSpan(
|
|
41
|
+
private fun <T> getNextParagraphSpan(
|
|
42
|
+
spannable: Spannable,
|
|
43
|
+
paragraphEnd: Int,
|
|
44
|
+
type: Class<T>,
|
|
45
|
+
): T? {
|
|
35
46
|
if (paragraphEnd >= spannable.length - 1) return null
|
|
36
47
|
|
|
37
48
|
val (nextParagraphStart, nextParagraphEnd) = spannable.getParagraphBounds(paragraphEnd + 1)
|
|
@@ -55,7 +66,12 @@ class ParagraphStyles(private val view: EnrichedTextInputView) {
|
|
|
55
66
|
* Applies a continuous span to the specified range.
|
|
56
67
|
* If the new range touches existing continuous spans, they are coalesced into a single span
|
|
57
68
|
*/
|
|
58
|
-
private fun <T>setContinuousSpan(
|
|
69
|
+
private fun <T> setContinuousSpan(
|
|
70
|
+
spannable: Spannable,
|
|
71
|
+
start: Int,
|
|
72
|
+
end: Int,
|
|
73
|
+
type: Class<T>,
|
|
74
|
+
) {
|
|
59
75
|
val span = type.getDeclaredConstructor(HtmlStyle::class.java).newInstance(view.htmlStyle)
|
|
60
76
|
val previousSpan = getPreviousParagraphSpan(spannable, start, type)
|
|
61
77
|
val nextSpan = getNextParagraphSpan(spannable, end, type)
|
|
@@ -76,8 +92,12 @@ class ParagraphStyles(private val view: EnrichedTextInputView) {
|
|
|
76
92
|
spannable.setSpan(span, safeStart, safeEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
77
93
|
}
|
|
78
94
|
|
|
79
|
-
|
|
80
|
-
|
|
95
|
+
private fun <T> setSpan(
|
|
96
|
+
spannable: Spannable,
|
|
97
|
+
type: Class<T>,
|
|
98
|
+
start: Int,
|
|
99
|
+
end: Int,
|
|
100
|
+
) {
|
|
81
101
|
if (EnrichedSpans.isTypeContinuous(type)) {
|
|
82
102
|
setContinuousSpan(spannable, start, end, type)
|
|
83
103
|
return
|
|
@@ -88,7 +108,12 @@ class ParagraphStyles(private val view: EnrichedTextInputView) {
|
|
|
88
108
|
spannable.setSpan(span, safeStart, safeEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
89
109
|
}
|
|
90
110
|
|
|
91
|
-
private fun <T>removeSpansForRange(
|
|
111
|
+
private fun <T> removeSpansForRange(
|
|
112
|
+
spannable: Spannable,
|
|
113
|
+
start: Int,
|
|
114
|
+
end: Int,
|
|
115
|
+
clazz: Class<T>,
|
|
116
|
+
): Boolean {
|
|
92
117
|
val ssb = spannable as SpannableStringBuilder
|
|
93
118
|
var finalStart = start
|
|
94
119
|
var finalEnd = end
|
|
@@ -103,11 +128,17 @@ class ParagraphStyles(private val view: EnrichedTextInputView) {
|
|
|
103
128
|
ssb.removeSpan(span)
|
|
104
129
|
}
|
|
105
130
|
|
|
106
|
-
ssb.
|
|
131
|
+
ssb.removeZWS(finalStart, finalEnd)
|
|
132
|
+
|
|
107
133
|
return true
|
|
108
134
|
}
|
|
109
135
|
|
|
110
|
-
private fun <T>setAndMergeSpans(
|
|
136
|
+
private fun <T> setAndMergeSpans(
|
|
137
|
+
spannable: Spannable,
|
|
138
|
+
type: Class<T>,
|
|
139
|
+
start: Int,
|
|
140
|
+
end: Int,
|
|
141
|
+
) {
|
|
111
142
|
val spans = spannable.getSpans(start, end, type)
|
|
112
143
|
|
|
113
144
|
// No spans setup for current selection, means we just need to assign new span
|
|
@@ -158,7 +189,11 @@ class ParagraphStyles(private val view: EnrichedTextInputView) {
|
|
|
158
189
|
}
|
|
159
190
|
}
|
|
160
191
|
|
|
161
|
-
private fun <T>isSpanEnabledInNextLine(
|
|
192
|
+
private fun <T> isSpanEnabledInNextLine(
|
|
193
|
+
spannable: Spannable,
|
|
194
|
+
index: Int,
|
|
195
|
+
type: Class<T>,
|
|
196
|
+
): Boolean {
|
|
162
197
|
val selection = view.selection ?: return false
|
|
163
198
|
if (index + 1 >= spannable.length) return false
|
|
164
199
|
val (start, end) = selection.getParagraphSelection()
|
|
@@ -167,7 +202,11 @@ class ParagraphStyles(private val view: EnrichedTextInputView) {
|
|
|
167
202
|
return spans.isNotEmpty()
|
|
168
203
|
}
|
|
169
204
|
|
|
170
|
-
private fun <T>mergeAdjacentStyleSpans(
|
|
205
|
+
private fun <T> mergeAdjacentStyleSpans(
|
|
206
|
+
s: Editable,
|
|
207
|
+
endCursorPosition: Int,
|
|
208
|
+
type: Class<T>,
|
|
209
|
+
) {
|
|
171
210
|
val (start, end) = s.getParagraphBounds(endCursorPosition)
|
|
172
211
|
val currParagraphSpans = s.getSpans(start, end, type)
|
|
173
212
|
|
|
@@ -194,16 +233,102 @@ class ParagraphStyles(private val view: EnrichedTextInputView) {
|
|
|
194
233
|
s.setSpan(span, safeStart, safeEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
195
234
|
}
|
|
196
235
|
|
|
197
|
-
fun
|
|
236
|
+
private fun handleConflictsDuringNewlineDeletion(
|
|
237
|
+
s: Editable,
|
|
238
|
+
style: String,
|
|
239
|
+
paragraphStart: Int,
|
|
240
|
+
paragraphEnd: Int,
|
|
241
|
+
): Boolean {
|
|
242
|
+
val spanState = view.spanState ?: return false
|
|
243
|
+
val mergingConfig = EnrichedSpans.getMergingConfigForStyle(style, view.htmlStyle) ?: return false
|
|
244
|
+
var isConflicting = false
|
|
245
|
+
val stylesToCheck = mergingConfig.blockingStyles + mergingConfig.conflictingStyles
|
|
246
|
+
|
|
247
|
+
for (styleToCheck in stylesToCheck) {
|
|
248
|
+
val conflictingType = EnrichedSpans.allSpans[styleToCheck]?.clazz ?: continue
|
|
249
|
+
|
|
250
|
+
val spans = s.getSpans(paragraphStart, paragraphEnd, conflictingType)
|
|
251
|
+
if (spans.isEmpty()) {
|
|
252
|
+
continue
|
|
253
|
+
}
|
|
254
|
+
isConflicting = true
|
|
255
|
+
|
|
256
|
+
val isParagraphStyle = EnrichedSpans.paragraphSpans[styleToCheck] != null
|
|
257
|
+
if (!isParagraphStyle) {
|
|
258
|
+
continue
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
for (span in spans) {
|
|
262
|
+
extendStyleOnWholeParagraph(s, span as EnrichedSpan, conflictingType, paragraphEnd)
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if (isConflicting) {
|
|
267
|
+
val styleStart = spanState.getStart(style) ?: return false
|
|
268
|
+
spanState.setStart(style, null)
|
|
269
|
+
removeStyle(style, styleStart, paragraphEnd)
|
|
270
|
+
return true
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return false
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
private fun deleteConflictingAndBlockingStyles(
|
|
277
|
+
s: Editable,
|
|
278
|
+
style: String,
|
|
279
|
+
paragraphStart: Int,
|
|
280
|
+
paragraphEnd: Int,
|
|
281
|
+
) {
|
|
282
|
+
val mergingConfig = EnrichedSpans.getMergingConfigForStyle(style, view.htmlStyle) ?: return
|
|
283
|
+
val stylesToCheck = mergingConfig.blockingStyles + mergingConfig.conflictingStyles
|
|
284
|
+
|
|
285
|
+
for (styleToCheck in stylesToCheck) {
|
|
286
|
+
val conflictingType = EnrichedSpans.allSpans[styleToCheck]?.clazz ?: continue
|
|
287
|
+
|
|
288
|
+
val spans = s.getSpans(paragraphStart, paragraphEnd, conflictingType)
|
|
289
|
+
for (span in spans) {
|
|
290
|
+
s.removeSpan(span)
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
private fun <T> extendStyleOnWholeParagraph(
|
|
296
|
+
s: Editable,
|
|
297
|
+
span: EnrichedSpan,
|
|
298
|
+
type: Class<T>,
|
|
299
|
+
paragraphEnd: Int,
|
|
300
|
+
) {
|
|
301
|
+
val currStyleStart = s.getSpanStart(span)
|
|
302
|
+
s.removeSpan(span)
|
|
303
|
+
val (safeStart, safeEnd) = s.getSafeSpanBoundaries(currStyleStart, paragraphEnd)
|
|
304
|
+
setSpan(s, type, safeStart, safeEnd)
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
fun afterTextChanged(
|
|
308
|
+
s: Editable,
|
|
309
|
+
endPosition: Int,
|
|
310
|
+
previousTextLength: Int,
|
|
311
|
+
) {
|
|
198
312
|
var endCursorPosition = endPosition
|
|
199
313
|
val isBackspace = s.length < previousTextLength
|
|
200
|
-
val isNewLine = endCursorPosition == 0 || endCursorPosition > 0 && s[endCursorPosition - 1] == '\n'
|
|
314
|
+
val isNewLine = endCursorPosition == 0 || (endCursorPosition > 0 && s[endCursorPosition - 1] == '\n')
|
|
315
|
+
val spanState = view.spanState ?: return
|
|
201
316
|
|
|
202
317
|
for ((style, config) in EnrichedSpans.paragraphSpans) {
|
|
203
|
-
val spanState = view.spanState ?: continue
|
|
204
318
|
val styleStart = spanState.getStart(style)
|
|
205
319
|
|
|
206
320
|
if (styleStart == null) {
|
|
321
|
+
if (isBackspace) {
|
|
322
|
+
val (start, end) = s.getParagraphBounds(endCursorPosition)
|
|
323
|
+
val spans = s.getSpans(start, end, config.clazz)
|
|
324
|
+
|
|
325
|
+
for (span in spans) {
|
|
326
|
+
// handle conflicts when entering paragraph with some paragraph style applied
|
|
327
|
+
deleteConflictingAndBlockingStyles(s, style, start, end)
|
|
328
|
+
extendStyleOnWholeParagraph(s, span as EnrichedSpan, config.clazz, end)
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
207
332
|
if (config.isContinuous) {
|
|
208
333
|
mergeAdjacentStyleSpans(s, endCursorPosition, config.clazz)
|
|
209
334
|
}
|
|
@@ -218,14 +343,23 @@ class ParagraphStyles(private val view: EnrichedTextInputView) {
|
|
|
218
343
|
|
|
219
344
|
if (isBackspace) {
|
|
220
345
|
endCursorPosition -= 1
|
|
221
|
-
|
|
346
|
+
spanState.setStart(style, null)
|
|
222
347
|
} else {
|
|
223
|
-
s.insert(endCursorPosition,
|
|
348
|
+
s.insert(endCursorPosition, EnrichedConstants.ZWS_STRING)
|
|
224
349
|
endCursorPosition += 1
|
|
225
350
|
}
|
|
226
351
|
}
|
|
227
352
|
|
|
228
353
|
var (start, end) = s.getParagraphBounds(styleStart, endCursorPosition)
|
|
354
|
+
|
|
355
|
+
// handle conflicts when deleting newline from paragraph style (going back to previous line)
|
|
356
|
+
if (isBackspace && styleStart != start) {
|
|
357
|
+
val isConflicting = handleConflictsDuringNewlineDeletion(s, style, start, end)
|
|
358
|
+
if (isConflicting) {
|
|
359
|
+
continue
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
229
363
|
val isNotEndLineSpan = isSpanEnabledInNextLine(s, end, config.clazz)
|
|
230
364
|
val spans = s.getSpans(start, end, config.clazz)
|
|
231
365
|
|
|
@@ -260,7 +394,7 @@ class ParagraphStyles(private val view: EnrichedTextInputView) {
|
|
|
260
394
|
}
|
|
261
395
|
|
|
262
396
|
if (start == end) {
|
|
263
|
-
spannable.insert(start,
|
|
397
|
+
spannable.insert(start, EnrichedConstants.ZWS_STRING)
|
|
264
398
|
setAndMergeSpans(spannable, type, start, end + 1)
|
|
265
399
|
view.selection.validateStyles()
|
|
266
400
|
|
|
@@ -272,7 +406,7 @@ class ParagraphStyles(private val view: EnrichedTextInputView) {
|
|
|
272
406
|
val paragraphs = spannable.substring(start, end).split("\n")
|
|
273
407
|
|
|
274
408
|
for (paragraph in paragraphs) {
|
|
275
|
-
spannable.insert(currentStart,
|
|
409
|
+
spannable.insert(currentStart, EnrichedConstants.ZWS_STRING)
|
|
276
410
|
currentEnd = currentStart + paragraph.length + 1
|
|
277
411
|
currentStart = currentEnd + 1
|
|
278
412
|
}
|
|
@@ -281,11 +415,13 @@ class ParagraphStyles(private val view: EnrichedTextInputView) {
|
|
|
281
415
|
view.selection.validateStyles()
|
|
282
416
|
}
|
|
283
417
|
|
|
284
|
-
fun getStyleRange(): Pair<Int, Int>
|
|
285
|
-
return view.selection?.getParagraphSelection() ?: Pair(0, 0)
|
|
286
|
-
}
|
|
418
|
+
fun getStyleRange(): Pair<Int, Int> = view.selection?.getParagraphSelection() ?: Pair(0, 0)
|
|
287
419
|
|
|
288
|
-
fun removeStyle(
|
|
420
|
+
fun removeStyle(
|
|
421
|
+
name: String,
|
|
422
|
+
start: Int,
|
|
423
|
+
end: Int,
|
|
424
|
+
): Boolean {
|
|
289
425
|
val config = EnrichedSpans.paragraphSpans[name] ?: return false
|
|
290
426
|
val spannable = view.text as Spannable
|
|
291
427
|
return removeSpansForRange(spannable, start, end, config.clazz)
|
|
@@ -9,20 +9,29 @@ import com.swmansion.enriched.spans.EnrichedImageSpan
|
|
|
9
9
|
import com.swmansion.enriched.spans.EnrichedLinkSpan
|
|
10
10
|
import com.swmansion.enriched.spans.EnrichedMentionSpan
|
|
11
11
|
import com.swmansion.enriched.spans.EnrichedSpans
|
|
12
|
+
import com.swmansion.enriched.utils.EnrichedConstants
|
|
12
13
|
import com.swmansion.enriched.utils.getSafeSpanBoundaries
|
|
14
|
+
import com.swmansion.enriched.utils.removeZWS
|
|
13
15
|
|
|
14
|
-
class ParametrizedStyles(
|
|
16
|
+
class ParametrizedStyles(
|
|
17
|
+
private val view: EnrichedTextInputView,
|
|
18
|
+
) {
|
|
15
19
|
private var mentionStart: Int? = null
|
|
16
20
|
private var isSettingLinkSpan = false
|
|
17
21
|
|
|
18
22
|
var mentionIndicators: Array<String> = emptyArray<String>()
|
|
19
23
|
|
|
20
|
-
fun <T>removeSpansForRange(
|
|
24
|
+
fun <T> removeSpansForRange(
|
|
25
|
+
spannable: Spannable,
|
|
26
|
+
start: Int,
|
|
27
|
+
end: Int,
|
|
28
|
+
clazz: Class<T>,
|
|
29
|
+
): Boolean {
|
|
21
30
|
val ssb = spannable as SpannableStringBuilder
|
|
22
31
|
val spans = ssb.getSpans(start, end, clazz)
|
|
23
32
|
if (spans.isEmpty()) return false
|
|
24
33
|
|
|
25
|
-
ssb.
|
|
34
|
+
ssb.removeZWS(start, end)
|
|
26
35
|
|
|
27
36
|
for (span in spans) {
|
|
28
37
|
ssb.removeSpan(span)
|
|
@@ -31,7 +40,12 @@ class ParametrizedStyles(private val view: EnrichedTextInputView) {
|
|
|
31
40
|
return true
|
|
32
41
|
}
|
|
33
42
|
|
|
34
|
-
fun setLinkSpan(
|
|
43
|
+
fun setLinkSpan(
|
|
44
|
+
start: Int,
|
|
45
|
+
end: Int,
|
|
46
|
+
text: String,
|
|
47
|
+
url: String,
|
|
48
|
+
) {
|
|
35
49
|
isSettingLinkSpan = true
|
|
36
50
|
|
|
37
51
|
val spannable = view.text as SpannableStringBuilder
|
|
@@ -55,36 +69,66 @@ class ParametrizedStyles(private val view: EnrichedTextInputView) {
|
|
|
55
69
|
isSettingLinkSpan = false
|
|
56
70
|
}
|
|
57
71
|
|
|
58
|
-
fun afterTextChanged(
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
72
|
+
fun afterTextChanged(
|
|
73
|
+
s: Editable,
|
|
74
|
+
startCursorPosition: Int,
|
|
75
|
+
endCursorPosition: Int,
|
|
76
|
+
) {
|
|
77
|
+
afterTextChangedLinks(startCursorPosition, endCursorPosition)
|
|
78
|
+
afterTextChangedMentions(s, startCursorPosition)
|
|
63
79
|
}
|
|
64
80
|
|
|
65
|
-
fun
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
81
|
+
fun detectLinksInRange(
|
|
82
|
+
spannable: Spannable,
|
|
83
|
+
start: Int,
|
|
84
|
+
end: Int,
|
|
85
|
+
) {
|
|
86
|
+
val regex = view.linkRegex ?: return
|
|
87
|
+
val contextText = spannable.subSequence(start, end).toString()
|
|
70
88
|
|
|
71
|
-
val spans = spannable.getSpans(
|
|
89
|
+
val spans = spannable.getSpans(start, end, EnrichedLinkSpan::class.java)
|
|
72
90
|
for (span in spans) {
|
|
73
91
|
spannable.removeSpan(span)
|
|
74
92
|
}
|
|
75
93
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
94
|
+
val wordsRegex = Regex("\\S+")
|
|
95
|
+
for (wordMatch in wordsRegex.findAll(contextText)) {
|
|
96
|
+
var word = wordMatch.value
|
|
97
|
+
var wordStart = wordMatch.range.first
|
|
98
|
+
|
|
99
|
+
// Do not include zero-width space in link detection
|
|
100
|
+
if (word.startsWith("\u200B")) {
|
|
101
|
+
word = word.substring(1)
|
|
102
|
+
wordStart += 1
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Loop over words and detect links
|
|
106
|
+
val matcher = regex.matcher(word)
|
|
107
|
+
while (matcher.find()) {
|
|
108
|
+
val linkStart = matcher.start()
|
|
109
|
+
val linkEnd = matcher.end()
|
|
110
|
+
|
|
111
|
+
val spanStart = start + wordStart + linkStart
|
|
112
|
+
val spanEnd = start + wordStart + linkEnd
|
|
113
|
+
|
|
114
|
+
val span = EnrichedLinkSpan(matcher.group(), view.htmlStyle)
|
|
115
|
+
val (safeStart, safeEnd) = spannable.getSafeSpanBoundaries(spanStart, spanEnd)
|
|
116
|
+
|
|
117
|
+
spannable.setSpan(
|
|
118
|
+
span,
|
|
119
|
+
safeStart,
|
|
120
|
+
safeEnd,
|
|
121
|
+
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE,
|
|
122
|
+
)
|
|
123
|
+
}
|
|
83
124
|
}
|
|
84
125
|
}
|
|
85
126
|
|
|
86
|
-
private fun getWordAtIndex(
|
|
87
|
-
|
|
127
|
+
private fun getWordAtIndex(
|
|
128
|
+
s: CharSequence,
|
|
129
|
+
index: Int,
|
|
130
|
+
): TextRange? {
|
|
131
|
+
if (index < 0) return null
|
|
88
132
|
|
|
89
133
|
var start = index
|
|
90
134
|
var end = index
|
|
@@ -102,8 +146,31 @@ class ParametrizedStyles(private val view: EnrichedTextInputView) {
|
|
|
102
146
|
return TextRange(result, start, end)
|
|
103
147
|
}
|
|
104
148
|
|
|
149
|
+
// After editing text we want to automatically detect links in the affected range
|
|
150
|
+
// Affected range is range + previous word + next word
|
|
151
|
+
private fun getLinksAffectedRange(
|
|
152
|
+
s: CharSequence,
|
|
153
|
+
start: Int,
|
|
154
|
+
end: Int,
|
|
155
|
+
): IntRange {
|
|
156
|
+
var actualStart = start
|
|
157
|
+
var actualEnd = end
|
|
158
|
+
|
|
159
|
+
// Expand backward to find the start of the first affected word
|
|
160
|
+
while (actualStart > 0 && !Character.isWhitespace(s[actualStart - 1])) {
|
|
161
|
+
actualStart--
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Expand forward to find the end of the last affected word
|
|
165
|
+
while (actualEnd < s.length && !Character.isWhitespace(s[actualEnd])) {
|
|
166
|
+
actualEnd++
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return actualStart..actualEnd
|
|
170
|
+
}
|
|
171
|
+
|
|
105
172
|
private fun canLinkBeApplied(): Boolean {
|
|
106
|
-
val mergingConfig = EnrichedSpans.getMergingConfigForStyle(EnrichedSpans.LINK, view.htmlStyle)?: return true
|
|
173
|
+
val mergingConfig = EnrichedSpans.getMergingConfigForStyle(EnrichedSpans.LINK, view.htmlStyle) ?: return true
|
|
107
174
|
val conflictingStyles = mergingConfig.conflictingStyles
|
|
108
175
|
val blockingStyles = mergingConfig.blockingStyles
|
|
109
176
|
|
|
@@ -118,34 +185,29 @@ class ParametrizedStyles(private val view: EnrichedTextInputView) {
|
|
|
118
185
|
return true
|
|
119
186
|
}
|
|
120
187
|
|
|
121
|
-
private fun afterTextChangedLinks(
|
|
188
|
+
private fun afterTextChangedLinks(
|
|
189
|
+
editStart: Int,
|
|
190
|
+
editEnd: Int,
|
|
191
|
+
) {
|
|
122
192
|
// Do not detect link if it's applied manually
|
|
123
193
|
if (isSettingLinkSpan || !canLinkBeApplied()) return
|
|
124
194
|
|
|
125
|
-
val spannable = view.text as Spannable
|
|
126
|
-
val (
|
|
127
|
-
|
|
128
|
-
// TODO: Consider using more reliable regex, this one matches almost anything
|
|
129
|
-
val urlPattern = android.util.Patterns.WEB_URL.matcher(word)
|
|
130
|
-
val spans = spannable.getSpans(start, end, EnrichedLinkSpan::class.java)
|
|
131
|
-
for (span in spans) {
|
|
132
|
-
spannable.removeSpan(span)
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
if (urlPattern.matches()) {
|
|
136
|
-
val span = EnrichedLinkSpan(word, view.htmlStyle)
|
|
137
|
-
val (safeStart, safeEnd) = spannable.getSafeSpanBoundaries(start, end)
|
|
138
|
-
spannable.setSpan(span, safeStart, safeEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
139
|
-
}
|
|
195
|
+
val spannable = view.text as? Spannable ?: return
|
|
196
|
+
val affectedRange = getLinksAffectedRange(spannable, editStart, editEnd)
|
|
197
|
+
detectLinksInRange(spannable, affectedRange.first, affectedRange.last)
|
|
140
198
|
}
|
|
141
199
|
|
|
142
|
-
private fun afterTextChangedMentions(
|
|
200
|
+
private fun afterTextChangedMentions(
|
|
201
|
+
s: CharSequence,
|
|
202
|
+
endCursorPosition: Int,
|
|
203
|
+
) {
|
|
143
204
|
val mentionHandler = view.mentionHandler ?: return
|
|
205
|
+
val currentWord = getWordAtIndex(s, endCursorPosition) ?: return
|
|
144
206
|
val spannable = view.text as Spannable
|
|
145
207
|
|
|
146
208
|
val indicatorsPattern = mentionIndicators.joinToString("|") { Regex.escape(it) }
|
|
147
209
|
val mentionIndicatorRegex = Regex("^($indicatorsPattern)")
|
|
148
|
-
val mentionRegex= Regex("^($indicatorsPattern)\\w*")
|
|
210
|
+
val mentionRegex = Regex("^($indicatorsPattern)\\w*")
|
|
149
211
|
|
|
150
212
|
val spans = spannable.getSpans(currentWord.start, currentWord.end, EnrichedMentionSpan::class.java)
|
|
151
213
|
for (span in spans) {
|
|
@@ -192,20 +254,24 @@ class ParametrizedStyles(private val view: EnrichedTextInputView) {
|
|
|
192
254
|
mentionHandler.onMention(indicator, text)
|
|
193
255
|
}
|
|
194
256
|
|
|
195
|
-
fun setImageSpan(
|
|
257
|
+
fun setImageSpan(
|
|
258
|
+
src: String,
|
|
259
|
+
width: Float,
|
|
260
|
+
height: Float,
|
|
261
|
+
) {
|
|
196
262
|
if (view.selection == null) return
|
|
197
263
|
val spannable = view.text as SpannableStringBuilder
|
|
198
264
|
val (start, originalEnd) = view.selection.getInlineSelection()
|
|
199
265
|
|
|
200
266
|
if (start == originalEnd) {
|
|
201
|
-
spannable.insert(start,
|
|
267
|
+
spannable.insert(start, EnrichedConstants.ORC_STRING)
|
|
202
268
|
} else {
|
|
203
269
|
val spans = spannable.getSpans(start, originalEnd, EnrichedImageSpan::class.java)
|
|
204
270
|
for (s in spans) {
|
|
205
271
|
spannable.removeSpan(s)
|
|
206
272
|
}
|
|
207
273
|
|
|
208
|
-
spannable.replace(start, originalEnd,
|
|
274
|
+
spannable.replace(start, originalEnd, EnrichedConstants.ORC_STRING)
|
|
209
275
|
}
|
|
210
276
|
|
|
211
277
|
val (imageStart, imageEnd) = spannable.getSafeSpanBoundaries(start, start + 1)
|
|
@@ -228,7 +294,11 @@ class ParametrizedStyles(private val view: EnrichedTextInputView) {
|
|
|
228
294
|
}
|
|
229
295
|
}
|
|
230
296
|
|
|
231
|
-
fun setMentionSpan(
|
|
297
|
+
fun setMentionSpan(
|
|
298
|
+
indicator: String,
|
|
299
|
+
text: String,
|
|
300
|
+
attributes: Map<String, String>,
|
|
301
|
+
) {
|
|
232
302
|
val selection = view.selection ?: return
|
|
233
303
|
|
|
234
304
|
val spannable = view.text as SpannableStringBuilder
|
|
@@ -259,17 +329,23 @@ class ParametrizedStyles(private val view: EnrichedTextInputView) {
|
|
|
259
329
|
view.selection.validateStyles()
|
|
260
330
|
}
|
|
261
331
|
|
|
262
|
-
fun getStyleRange(): Pair<Int, Int>
|
|
263
|
-
return view.selection?.getInlineSelection() ?: Pair(0, 0)
|
|
264
|
-
}
|
|
332
|
+
fun getStyleRange(): Pair<Int, Int> = view.selection?.getInlineSelection() ?: Pair(0, 0)
|
|
265
333
|
|
|
266
|
-
fun removeStyle(
|
|
334
|
+
fun removeStyle(
|
|
335
|
+
name: String,
|
|
336
|
+
start: Int,
|
|
337
|
+
end: Int,
|
|
338
|
+
): Boolean {
|
|
267
339
|
val config = EnrichedSpans.parametrizedStyles[name] ?: return false
|
|
268
340
|
val spannable = view.text as Spannable
|
|
269
341
|
return removeSpansForRange(spannable, start, end, config.clazz)
|
|
270
342
|
}
|
|
271
343
|
|
|
272
344
|
companion object {
|
|
273
|
-
data class TextRange(
|
|
345
|
+
data class TextRange(
|
|
346
|
+
val text: String,
|
|
347
|
+
val start: Int,
|
|
348
|
+
val end: Int,
|
|
349
|
+
)
|
|
274
350
|
}
|
|
275
351
|
}
|
|
@@ -13,12 +13,12 @@ import android.os.Looper
|
|
|
13
13
|
import android.util.Log
|
|
14
14
|
import androidx.core.content.res.ResourcesCompat
|
|
15
15
|
import androidx.core.graphics.drawable.DrawableCompat
|
|
16
|
-
import java.net.URL
|
|
17
|
-
import java.util.concurrent.Executors
|
|
18
16
|
import androidx.core.graphics.drawable.toDrawable
|
|
19
17
|
import com.swmansion.enriched.R
|
|
18
|
+
import java.net.URL
|
|
19
|
+
import java.util.concurrent.Executors
|
|
20
20
|
|
|
21
|
-
class AsyncDrawable
|
|
21
|
+
class AsyncDrawable(
|
|
22
22
|
private val url: String,
|
|
23
23
|
) : Drawable() {
|
|
24
24
|
private var internalDrawable: Drawable = Color.TRANSPARENT.toDrawable()
|
|
@@ -78,11 +78,14 @@ class AsyncDrawable (
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
@Deprecated("Deprecated in Java")
|
|
81
|
-
override fun getOpacity(): Int
|
|
82
|
-
return PixelFormat.TRANSLUCENT
|
|
83
|
-
}
|
|
81
|
+
override fun getOpacity(): Int = PixelFormat.TRANSLUCENT
|
|
84
82
|
|
|
85
|
-
override fun setBounds(
|
|
83
|
+
override fun setBounds(
|
|
84
|
+
left: Int,
|
|
85
|
+
top: Int,
|
|
86
|
+
right: Int,
|
|
87
|
+
bottom: Int,
|
|
88
|
+
) {
|
|
86
89
|
super.setBounds(left, top, right, bottom)
|
|
87
90
|
internalDrawable.setBounds(left, top, right, bottom)
|
|
88
91
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
package com.swmansion.enriched.utils
|
|
2
|
+
|
|
3
|
+
import android.text.Editable
|
|
4
|
+
import android.text.Spannable
|
|
5
|
+
import android.text.SpannableStringBuilder
|
|
6
|
+
import com.swmansion.enriched.watchers.EnrichedSpanWatcher
|
|
7
|
+
|
|
8
|
+
class EnrichedEditableFactory(
|
|
9
|
+
private val watcher: EnrichedSpanWatcher,
|
|
10
|
+
) : Editable.Factory() {
|
|
11
|
+
override fun newEditable(source: CharSequence): Editable {
|
|
12
|
+
val s = source as? SpannableStringBuilder ?: SpannableStringBuilder(source)
|
|
13
|
+
s.removeSpan(watcher)
|
|
14
|
+
s.setSpan(watcher, 0, s.length, Spannable.SPAN_INCLUSIVE_INCLUSIVE)
|
|
15
|
+
return s
|
|
16
|
+
}
|
|
17
|
+
}
|