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.
Files changed (186) hide show
  1. package/README.md +16 -17
  2. package/android/build.gradle +77 -72
  3. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerDelegate.java +21 -0
  4. package/android/generated/java/com/facebook/react/viewmanagers/EnrichedTextInputViewManagerInterface.java +7 -0
  5. package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/EventEmitters.cpp +156 -0
  6. package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/EventEmitters.h +147 -0
  7. package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/Props.cpp +10 -0
  8. package/android/generated/jni/react/renderer/components/RNEnrichedTextInputViewSpec/Props.h +194 -0
  9. package/android/lint.gradle +70 -0
  10. package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputConnectionWrapper.kt +140 -0
  11. package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputView.kt +304 -83
  12. package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewLayoutManager.kt +3 -1
  13. package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewManager.kt +166 -51
  14. package/android/src/main/java/com/swmansion/enriched/EnrichedTextInputViewPackage.kt +1 -3
  15. package/android/src/main/java/com/swmansion/enriched/MeasurementStore.kt +70 -21
  16. package/android/src/main/java/com/swmansion/enriched/events/MentionHandler.kt +21 -11
  17. package/android/src/main/java/com/swmansion/enriched/events/OnChangeHtmlEvent.kt +8 -9
  18. package/android/src/main/java/com/swmansion/enriched/events/OnChangeSelectionEvent.kt +10 -9
  19. package/android/src/main/java/com/swmansion/enriched/events/OnChangeStateDeprecatedEvent.kt +21 -0
  20. package/android/src/main/java/com/swmansion/enriched/events/OnChangeStateEvent.kt +9 -12
  21. package/android/src/main/java/com/swmansion/enriched/events/OnChangeTextEvent.kt +10 -10
  22. package/android/src/main/java/com/swmansion/enriched/events/OnInputBlurEvent.kt +7 -9
  23. package/android/src/main/java/com/swmansion/enriched/events/OnInputFocusEvent.kt +7 -9
  24. package/android/src/main/java/com/swmansion/enriched/events/OnInputKeyPressEvent.kt +27 -0
  25. package/android/src/main/java/com/swmansion/enriched/events/OnLinkDetectedEvent.kt +13 -11
  26. package/android/src/main/java/com/swmansion/enriched/events/OnMentionDetectedEvent.kt +10 -9
  27. package/android/src/main/java/com/swmansion/enriched/events/OnMentionEvent.kt +9 -8
  28. package/android/src/main/java/com/swmansion/enriched/events/OnRequestHtmlResultEvent.kt +32 -0
  29. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedBlockQuoteSpan.kt +24 -5
  30. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedBoldSpan.kt +8 -1
  31. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedCodeBlockSpan.kt +10 -2
  32. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH1Span.kt +8 -1
  33. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH2Span.kt +8 -1
  34. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH3Span.kt +8 -1
  35. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH4Span.kt +24 -0
  36. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH5Span.kt +24 -0
  37. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedH6Span.kt +24 -0
  38. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedImageSpan.kt +34 -17
  39. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedInlineCodeSpan.kt +8 -1
  40. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedItalicSpan.kt +7 -1
  41. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedLinkSpan.kt +10 -4
  42. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedMentionSpan.kt +14 -11
  43. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedOrderedListSpan.kt +18 -11
  44. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedSpans.kt +174 -72
  45. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedStrikeThroughSpan.kt +7 -1
  46. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedUnderlineSpan.kt +7 -1
  47. package/android/src/main/java/com/swmansion/enriched/spans/EnrichedUnorderedListSpan.kt +11 -5
  48. package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedBlockSpan.kt +3 -2
  49. package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedHeadingSpan.kt +1 -2
  50. package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedInlineSpan.kt +1 -2
  51. package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedParagraphSpan.kt +3 -2
  52. package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedSpan.kt +5 -0
  53. package/android/src/main/java/com/swmansion/enriched/spans/interfaces/EnrichedZeroWidthSpaceSpan.kt +1 -2
  54. package/android/src/main/java/com/swmansion/enriched/spans/utils/ForceRedrawSpan.kt +2 -1
  55. package/android/src/main/java/com/swmansion/enriched/styles/HtmlStyle.kt +155 -20
  56. package/android/src/main/java/com/swmansion/enriched/styles/InlineStyles.kt +25 -8
  57. package/android/src/main/java/com/swmansion/enriched/styles/ListStyles.kt +60 -20
  58. package/android/src/main/java/com/swmansion/enriched/styles/ParagraphStyles.kt +161 -25
  59. package/android/src/main/java/com/swmansion/enriched/styles/ParametrizedStyles.kt +128 -52
  60. package/android/src/main/java/com/swmansion/enriched/utils/AsyncDrawable.kt +10 -7
  61. package/android/src/main/java/com/swmansion/enriched/utils/EnrichedConstants.kt +11 -0
  62. package/android/src/main/java/com/swmansion/enriched/utils/EnrichedEditableFactory.kt +17 -0
  63. package/android/src/main/java/com/swmansion/enriched/utils/EnrichedParser.java +136 -87
  64. package/android/src/main/java/com/swmansion/enriched/utils/EnrichedSelection.kt +71 -42
  65. package/android/src/main/java/com/swmansion/enriched/utils/EnrichedSpanState.kt +183 -48
  66. package/android/src/main/java/com/swmansion/enriched/utils/EnrichedSpannable.kt +82 -0
  67. package/android/src/main/java/com/swmansion/enriched/utils/EnrichedSpannableStringBuilder.kt +15 -0
  68. package/android/src/main/java/com/swmansion/enriched/utils/Utils.kt +0 -70
  69. package/android/src/main/java/com/swmansion/enriched/watchers/EnrichedSpanWatcher.kt +46 -14
  70. package/android/src/main/java/com/swmansion/enriched/watchers/EnrichedTextWatcher.kt +34 -11
  71. package/android/src/main/new_arch/CMakeLists.txt +6 -0
  72. package/android/src/main/new_arch/RNEnrichedTextInputViewSpec.cpp +6 -6
  73. package/android/src/main/new_arch/RNEnrichedTextInputViewSpec.h +6 -6
  74. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputComponentDescriptor.h +19 -19
  75. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputMeasurementManager.cpp +40 -51
  76. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputMeasurementManager.h +13 -15
  77. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputShadowNode.cpp +23 -21
  78. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputShadowNode.h +35 -36
  79. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputState.cpp +4 -4
  80. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/EnrichedTextInputState.h +13 -14
  81. package/android/src/main/new_arch/react/renderer/components/RNEnrichedTextInputViewSpec/conversions.h +33 -14
  82. package/ios/EnrichedTextInputView.h +26 -14
  83. package/ios/EnrichedTextInputView.mm +1209 -586
  84. package/ios/config/InputConfig.h +24 -6
  85. package/ios/config/InputConfig.mm +154 -38
  86. package/ios/{utils → extensions}/ColorExtension.mm +7 -5
  87. package/ios/extensions/FontExtension.mm +106 -0
  88. package/ios/{utils → extensions}/LayoutManagerExtension.h +1 -1
  89. package/ios/extensions/LayoutManagerExtension.mm +396 -0
  90. package/ios/{utils → extensions}/StringExtension.mm +19 -16
  91. package/ios/generated/RNEnrichedTextInputViewSpec/EventEmitters.cpp +156 -0
  92. package/ios/generated/RNEnrichedTextInputViewSpec/EventEmitters.h +147 -0
  93. package/ios/generated/RNEnrichedTextInputViewSpec/Props.cpp +10 -0
  94. package/ios/generated/RNEnrichedTextInputViewSpec/Props.h +194 -0
  95. package/ios/generated/RNEnrichedTextInputViewSpec/RCTComponentViewHelpers.h +95 -0
  96. package/ios/inputParser/InputParser.h +5 -5
  97. package/ios/inputParser/InputParser.mm +864 -380
  98. package/ios/inputTextView/InputTextView.h +1 -1
  99. package/ios/inputTextView/InputTextView.mm +100 -59
  100. package/ios/{utils → interfaces}/BaseStyleProtocol.h +2 -2
  101. package/ios/interfaces/ImageAttachment.h +10 -0
  102. package/ios/interfaces/ImageAttachment.mm +36 -0
  103. package/ios/interfaces/LinkRegexConfig.h +19 -0
  104. package/ios/interfaces/LinkRegexConfig.mm +37 -0
  105. package/ios/interfaces/MediaAttachment.h +23 -0
  106. package/ios/interfaces/MediaAttachment.mm +31 -0
  107. package/ios/{utils → interfaces}/MentionParams.h +0 -1
  108. package/ios/{utils → interfaces}/MentionStyleProps.mm +27 -20
  109. package/ios/{utils → interfaces}/StyleHeaders.h +37 -15
  110. package/ios/{utils → interfaces}/StyleTypeEnum.h +3 -0
  111. package/ios/internals/EnrichedTextInputViewComponentDescriptor.h +11 -9
  112. package/ios/internals/EnrichedTextInputViewShadowNode.h +28 -25
  113. package/ios/internals/EnrichedTextInputViewShadowNode.mm +45 -40
  114. package/ios/internals/EnrichedTextInputViewState.h +3 -1
  115. package/ios/styles/BlockQuoteStyle.mm +189 -118
  116. package/ios/styles/BoldStyle.mm +110 -63
  117. package/ios/styles/CodeBlockStyle.mm +204 -128
  118. package/ios/styles/H1Style.mm +10 -4
  119. package/ios/styles/H2Style.mm +10 -4
  120. package/ios/styles/H3Style.mm +10 -4
  121. package/ios/styles/H4Style.mm +17 -0
  122. package/ios/styles/H5Style.mm +17 -0
  123. package/ios/styles/H6Style.mm +17 -0
  124. package/ios/styles/HeadingStyleBase.mm +148 -86
  125. package/ios/styles/ImageStyle.mm +75 -73
  126. package/ios/styles/InlineCodeStyle.mm +162 -88
  127. package/ios/styles/ItalicStyle.mm +76 -52
  128. package/ios/styles/LinkStyle.mm +411 -232
  129. package/ios/styles/MentionStyle.mm +363 -246
  130. package/ios/styles/OrderedListStyle.mm +171 -106
  131. package/ios/styles/StrikethroughStyle.mm +52 -35
  132. package/ios/styles/UnderlineStyle.mm +68 -46
  133. package/ios/styles/UnorderedListStyle.mm +169 -106
  134. package/ios/utils/OccurenceUtils.h +42 -42
  135. package/ios/utils/OccurenceUtils.mm +142 -119
  136. package/ios/utils/ParagraphAttributesUtils.h +10 -2
  137. package/ios/utils/ParagraphAttributesUtils.mm +182 -71
  138. package/ios/utils/ParagraphsUtils.h +2 -1
  139. package/ios/utils/ParagraphsUtils.mm +41 -27
  140. package/ios/utils/TextInsertionUtils.h +13 -2
  141. package/ios/utils/TextInsertionUtils.mm +38 -20
  142. package/ios/utils/WordsUtils.h +2 -1
  143. package/ios/utils/WordsUtils.mm +32 -22
  144. package/ios/utils/ZeroWidthSpaceUtils.h +3 -1
  145. package/ios/utils/ZeroWidthSpaceUtils.mm +145 -79
  146. package/lib/module/EnrichedTextInput.js +61 -2
  147. package/lib/module/EnrichedTextInput.js.map +1 -1
  148. package/lib/module/EnrichedTextInputNativeComponent.ts +149 -12
  149. package/lib/module/{normalizeHtmlStyle.js → utils/normalizeHtmlStyle.js} +12 -0
  150. package/lib/module/utils/normalizeHtmlStyle.js.map +1 -0
  151. package/lib/module/utils/regexParser.js +46 -0
  152. package/lib/module/utils/regexParser.js.map +1 -0
  153. package/lib/typescript/src/EnrichedTextInput.d.ts +24 -14
  154. package/lib/typescript/src/EnrichedTextInput.d.ts.map +1 -1
  155. package/lib/typescript/src/EnrichedTextInputNativeComponent.d.ts +129 -12
  156. package/lib/typescript/src/EnrichedTextInputNativeComponent.d.ts.map +1 -1
  157. package/lib/typescript/src/index.d.ts +1 -1
  158. package/lib/typescript/src/index.d.ts.map +1 -1
  159. package/lib/typescript/src/utils/normalizeHtmlStyle.d.ts +4 -0
  160. package/lib/typescript/src/utils/normalizeHtmlStyle.d.ts.map +1 -0
  161. package/lib/typescript/src/utils/regexParser.d.ts +3 -0
  162. package/lib/typescript/src/utils/regexParser.d.ts.map +1 -0
  163. package/package.json +17 -6
  164. package/src/EnrichedTextInput.tsx +96 -13
  165. package/src/EnrichedTextInputNativeComponent.ts +149 -12
  166. package/src/index.tsx +2 -0
  167. package/src/{normalizeHtmlStyle.ts → utils/normalizeHtmlStyle.ts} +14 -2
  168. package/src/utils/regexParser.ts +56 -0
  169. package/ios/utils/FontExtension.mm +0 -91
  170. package/ios/utils/LayoutManagerExtension.mm +0 -286
  171. package/lib/module/normalizeHtmlStyle.js.map +0 -1
  172. package/lib/typescript/src/normalizeHtmlStyle.d.ts +0 -4
  173. package/lib/typescript/src/normalizeHtmlStyle.d.ts.map +0 -1
  174. package/ios/{utils → extensions}/ColorExtension.h +0 -0
  175. package/ios/{utils → extensions}/FontExtension.h +0 -0
  176. package/ios/{utils → extensions}/StringExtension.h +1 -1
  177. package/ios/{utils → interfaces}/ImageData.h +0 -0
  178. package/ios/{utils → interfaces}/ImageData.mm +0 -0
  179. package/ios/{utils → interfaces}/LinkData.h +0 -0
  180. package/ios/{utils → interfaces}/LinkData.mm +0 -0
  181. package/ios/{utils → interfaces}/MentionParams.mm +0 -0
  182. package/ios/{utils → interfaces}/MentionStyleProps.h +1 -1
  183. /package/ios/{utils → interfaces}/StylePair.h +0 -0
  184. /package/ios/{utils → interfaces}/StylePair.mm +0 -0
  185. /package/ios/{utils → interfaces}/TextDecorationLineEnum.h +0 -0
  186. /package/ios/{utils → interfaces}/TextDecorationLineEnum.mm +0 -0
@@ -28,6 +28,15 @@ class HtmlStyle {
28
28
  var h3FontSize: Int = 56
29
29
  var h3Bold: Boolean = false
30
30
 
31
+ var h4FontSize: Int = 48
32
+ var h4Bold: Boolean = false
33
+
34
+ var h5FontSize: Int = 40
35
+ var h5Bold: Boolean = false
36
+
37
+ var h6FontSize: Int = 32
38
+ var h6Bold: Boolean = false
39
+
31
40
  var blockquoteColor: Int? = null
32
41
  var blockquoteBorderColor: Int = Color.BLACK
33
42
  var blockquoteStripeWidth: Int = 2
@@ -77,6 +86,18 @@ class HtmlStyle {
77
86
  h3FontSize = parseFloat(h3Style, "fontSize").toInt()
78
87
  h3Bold = h3Style?.getBoolean("bold") == true
79
88
 
89
+ val h4Style = style.getMap("h4")
90
+ h4FontSize = parseFloat(h4Style, "fontSize").toInt()
91
+ h4Bold = h4Style?.getBoolean("bold") == true
92
+
93
+ val h5Style = style.getMap("h5")
94
+ h5FontSize = parseFloat(h5Style, "fontSize").toInt()
95
+ h5Bold = h5Style?.getBoolean("bold") == true
96
+
97
+ val h6Style = style.getMap("h6")
98
+ h6FontSize = parseFloat(h6Style, "fontSize").toInt()
99
+ h6Bold = h6Style?.getBoolean("bold") == true
100
+
80
101
  val blockquoteStyle = style.getMap("blockquote")
81
102
  blockquoteColor = parseOptionalColor(blockquoteStyle, "color")
82
103
  blockquoteBorderColor = parseColor(blockquoteStyle, "borderColor")
@@ -114,19 +135,29 @@ class HtmlStyle {
114
135
  mentionsStyle = parseMentionsStyle(mentionStyle)
115
136
  }
116
137
 
117
- private fun parseFloat(map: ReadableMap?, key: String): Float {
138
+ private fun parseFloat(
139
+ map: ReadableMap?,
140
+ key: String,
141
+ ): Float {
118
142
  val safeMap = ensureValueIsSet(map, key)
119
143
 
120
144
  val value = safeMap.getDouble(key)
121
145
  return ceil(PixelUtil.toPixelFromSP(value))
122
146
  }
123
147
 
124
- private fun parseColorWithOpacity(map: ReadableMap?, key: String, opacity: Int): Int {
148
+ private fun parseColorWithOpacity(
149
+ map: ReadableMap?,
150
+ key: String,
151
+ opacity: Int,
152
+ ): Int {
125
153
  val color = parseColor(map, key)
126
154
  return withOpacity(color, opacity)
127
155
  }
128
156
 
129
- private fun parseOptionalColor(map: ReadableMap?, key: String): Int? {
157
+ private fun parseOptionalColor(
158
+ map: ReadableMap?,
159
+ key: String,
160
+ ): Int? {
130
161
  if (map == null) return null
131
162
  if (!map.hasKey(key)) return null
132
163
  if (map.isNull(key)) return null
@@ -134,7 +165,10 @@ class HtmlStyle {
134
165
  return parseColor(map, key)
135
166
  }
136
167
 
137
- private fun parseColor(map: ReadableMap?, key: String): Int {
168
+ private fun parseColor(
169
+ map: ReadableMap?,
170
+ key: String,
171
+ ): Int {
138
172
  val safeMap = ensureValueIsSet(map, key)
139
173
 
140
174
  val color = safeMap.getDouble(key)
@@ -146,7 +180,10 @@ class HtmlStyle {
146
180
  return parsedColor
147
181
  }
148
182
 
149
- private fun withOpacity(color: Int, alpha: Int): Int {
183
+ private fun withOpacity(
184
+ color: Int,
185
+ alpha: Int,
186
+ ): Int {
150
187
  // Do not apply opacity to transparent color
151
188
  if (Color.alpha(color) == 0) return color
152
189
  val a = alpha.coerceIn(0, 255)
@@ -164,14 +201,20 @@ class HtmlStyle {
164
201
  throw Error("Specified textDecorationLine value is not supported: $underline. Supported values are 'underline' and 'none'.")
165
202
  }
166
203
 
167
- private fun calculateOlMarginLeft(view: EnrichedTextInputView?, userMargin: Int): Int {
204
+ private fun calculateOlMarginLeft(
205
+ view: EnrichedTextInputView?,
206
+ userMargin: Int,
207
+ ): Int {
168
208
  val fontSize = view?.fontSize?.toInt() ?: 0
169
209
  val leadMargin = fontSize / 2
170
210
 
171
211
  return leadMargin + userMargin
172
212
  }
173
213
 
174
- private fun ensureValueIsSet(map: ReadableMap?, key: String): ReadableMap {
214
+ private fun ensureValueIsSet(
215
+ map: ReadableMap?,
216
+ key: String,
217
+ ): ReadableMap {
175
218
  if (map == null) throw Error("Style map cannot be null")
176
219
 
177
220
  if (!map.hasKey(key)) throw Error("Style map must contain key: $key")
@@ -186,24 +229,27 @@ class HtmlStyle {
186
229
 
187
230
  val parsedMentionsStyle: MutableMap<String, MentionStyle> = mutableMapOf()
188
231
 
189
- val iterator = mentionsStyle.keySetIterator()
190
- while (iterator.hasNextKey()) {
191
- val key = iterator.nextKey()
192
- val value = mentionsStyle.getMap(key)
232
+ val iterator = mentionsStyle.keySetIterator()
233
+ while (iterator.hasNextKey()) {
234
+ val key = iterator.nextKey()
235
+ val value = mentionsStyle.getMap(key)
193
236
 
194
- if (value == null) throw Error("Mention style for key '$key' cannot be null")
237
+ if (value == null) throw Error("Mention style for key '$key' cannot be null")
195
238
 
196
- val color = parseColor(value, "color")
197
- val backgroundColor = parseColorWithOpacity(value, "backgroundColor", 80)
198
- val isUnderline = parseIsUnderline(value)
199
- val parsedStyle = MentionStyle(color, backgroundColor, isUnderline)
200
- parsedMentionsStyle.put(key, parsedStyle)
201
- }
239
+ val color = parseColor(value, "color")
240
+ val backgroundColor = parseColorWithOpacity(value, "backgroundColor", 80)
241
+ val isUnderline = parseIsUnderline(value)
242
+ val parsedStyle = MentionStyle(color, backgroundColor, isUnderline)
243
+ parsedMentionsStyle.put(key, parsedStyle)
244
+ }
202
245
 
203
246
  return parsedMentionsStyle
204
247
  }
205
248
 
206
- private fun parseOptionalFontWeight(map: ReadableMap?, key: String): Int? {
249
+ private fun parseOptionalFontWeight(
250
+ map: ReadableMap?,
251
+ key: String,
252
+ ): Int? {
207
253
  if (map == null) return null
208
254
  if (!map.hasKey(key)) return null
209
255
  if (map.isNull(key)) return null
@@ -212,11 +258,100 @@ class HtmlStyle {
212
258
  return parseFontWeight(fontWeight)
213
259
  }
214
260
 
261
+ override fun equals(other: Any?): Boolean {
262
+ if (this === other) return true
263
+ if (other !is HtmlStyle) return false
264
+
265
+ return h1FontSize == other.h1FontSize &&
266
+ h1Bold == other.h1Bold &&
267
+ h2FontSize == other.h2FontSize &&
268
+ h2Bold == other.h2Bold &&
269
+ h3FontSize == other.h3FontSize &&
270
+ h3Bold == other.h3Bold &&
271
+ h4FontSize == other.h4FontSize &&
272
+ h4Bold == other.h4Bold &&
273
+ h5FontSize == other.h5FontSize &&
274
+ h5Bold == other.h5Bold &&
275
+ h6FontSize == other.h6FontSize &&
276
+ h6Bold == other.h6Bold &&
277
+
278
+ blockquoteColor == other.blockquoteColor &&
279
+ blockquoteBorderColor == other.blockquoteBorderColor &&
280
+ blockquoteStripeWidth == other.blockquoteStripeWidth &&
281
+ blockquoteGapWidth == other.blockquoteGapWidth &&
282
+
283
+ olGapWidth == other.olGapWidth &&
284
+ olMarginLeft == other.olMarginLeft &&
285
+ olMarkerFontWeight == other.olMarkerFontWeight &&
286
+ olMarkerColor == other.olMarkerColor &&
287
+
288
+ ulGapWidth == other.ulGapWidth &&
289
+ ulMarginLeft == other.ulMarginLeft &&
290
+ ulBulletSize == other.ulBulletSize &&
291
+ ulBulletColor == other.ulBulletColor &&
292
+
293
+ aColor == other.aColor &&
294
+ aUnderline == other.aUnderline &&
295
+
296
+ codeBlockColor == other.codeBlockColor &&
297
+ codeBlockBackgroundColor == other.codeBlockBackgroundColor &&
298
+ codeBlockRadius == other.codeBlockRadius &&
299
+
300
+ inlineCodeColor == other.inlineCodeColor &&
301
+ inlineCodeBackgroundColor == other.inlineCodeBackgroundColor &&
302
+
303
+ mentionsStyle == other.mentionsStyle
304
+ }
305
+
306
+ override fun hashCode(): Int {
307
+ var result = h1FontSize.hashCode()
308
+ result = 31 * result + h1Bold.hashCode()
309
+ result = 31 * result + h2FontSize.hashCode()
310
+ result = 31 * result + h2Bold.hashCode()
311
+ result = 31 * result + h3FontSize.hashCode()
312
+ result = 31 * result + h3Bold.hashCode()
313
+ result = 31 * result + h4FontSize.hashCode()
314
+ result = 31 * result + h4Bold.hashCode()
315
+ result = 31 * result + h5FontSize.hashCode()
316
+ result = 31 * result + h5Bold.hashCode()
317
+ result = 31 * result + h6FontSize.hashCode()
318
+ result = 31 * result + h6Bold.hashCode()
319
+
320
+ result = 31 * result + (blockquoteColor ?: 0)
321
+ result = 31 * result + blockquoteBorderColor.hashCode()
322
+ result = 31 * result + blockquoteStripeWidth.hashCode()
323
+ result = 31 * result + blockquoteGapWidth.hashCode()
324
+
325
+ result = 31 * result + olGapWidth.hashCode()
326
+ result = 31 * result + olMarginLeft.hashCode()
327
+ result = 31 * result + (olMarkerFontWeight?.hashCode() ?: 0)
328
+ result = 31 * result + (olMarkerColor ?: 0)
329
+
330
+ result = 31 * result + ulGapWidth.hashCode()
331
+ result = 31 * result + ulMarginLeft.hashCode()
332
+ result = 31 * result + ulBulletSize.hashCode()
333
+ result = 31 * result + ulBulletColor.hashCode()
334
+
335
+ result = 31 * result + aColor.hashCode()
336
+ result = 31 * result + aUnderline.hashCode()
337
+
338
+ result = 31 * result + codeBlockColor.hashCode()
339
+ result = 31 * result + codeBlockBackgroundColor.hashCode()
340
+ result = 31 * result + codeBlockRadius.hashCode()
341
+
342
+ result = 31 * result + inlineCodeColor.hashCode()
343
+ result = 31 * result + inlineCodeBackgroundColor.hashCode()
344
+
345
+ result = 31 * result + mentionsStyle.hashCode()
346
+
347
+ return result
348
+ }
349
+
215
350
  companion object {
216
351
  data class MentionStyle(
217
352
  val color: Int,
218
353
  val backgroundColor: Int,
219
- val underline: Boolean
354
+ val underline: Boolean,
220
355
  )
221
356
  }
222
357
  }
@@ -6,8 +6,15 @@ import com.swmansion.enriched.EnrichedTextInputView
6
6
  import com.swmansion.enriched.spans.EnrichedSpans
7
7
  import com.swmansion.enriched.utils.getSafeSpanBoundaries
8
8
 
9
- class InlineStyles(private val view: EnrichedTextInputView) {
10
- private fun <T>setSpan(spannable: Spannable, type: Class<T>, start: Int, end: Int) {
9
+ class InlineStyles(
10
+ private val view: EnrichedTextInputView,
11
+ ) {
12
+ private fun <T> setSpan(
13
+ spannable: Spannable,
14
+ type: Class<T>,
15
+ start: Int,
16
+ end: Int,
17
+ ) {
11
18
  val previousSpanStart = (start - 1).coerceAtLeast(0)
12
19
  val previousSpanEnd = previousSpanStart + 1
13
20
  val nextSpanStart = (end + 1).coerceAtMost(spannable.length)
@@ -37,7 +44,12 @@ class InlineStyles(private val view: EnrichedTextInputView) {
37
44
  spannable.setSpan(span, safeStart, safeEnd, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
38
45
  }
39
46
 
40
- private fun <T>setAndMergeSpans(spannable: Spannable, type: Class<T>, start: Int, end: Int) {
47
+ private fun <T> setAndMergeSpans(
48
+ spannable: Spannable,
49
+ type: Class<T>,
50
+ start: Int,
51
+ end: Int,
52
+ ) {
41
53
  val spans = spannable.getSpans(start, end, type)
42
54
 
43
55
  // No spans setup for current selection, means we just need to assign new span
@@ -89,7 +101,10 @@ class InlineStyles(private val view: EnrichedTextInputView) {
89
101
  }
90
102
  }
91
103
 
92
- fun afterTextChanged(s: Editable, endCursorPosition: Int) {
104
+ fun afterTextChanged(
105
+ s: Editable,
106
+ endCursorPosition: Int,
107
+ ) {
93
108
  for ((style, config) in EnrichedSpans.inlineSpans) {
94
109
  val start = view.spanState?.getStart(style) ?: continue
95
110
  var end = endCursorPosition
@@ -128,7 +143,11 @@ class InlineStyles(private val view: EnrichedTextInputView) {
128
143
  view.selection.validateStyles()
129
144
  }
130
145
 
131
- fun removeStyle(name: String, start: Int, end: Int): Boolean {
146
+ fun removeStyle(
147
+ name: String,
148
+ start: Int,
149
+ end: Int,
150
+ ): Boolean {
132
151
  val config = EnrichedSpans.inlineSpans[name] ?: return false
133
152
  val spannable = view.text as Spannable
134
153
  val spans = spannable.getSpans(start, end, config.clazz)
@@ -141,7 +160,5 @@ class InlineStyles(private val view: EnrichedTextInputView) {
141
160
  return true
142
161
  }
143
162
 
144
- fun getStyleRange(): Pair<Int, Int> {
145
- return view.selection?.getInlineSelection() ?: Pair(0, 0)
146
- }
163
+ fun getStyleRange(): Pair<Int, Int> = view.selection?.getInlineSelection() ?: Pair(0, 0)
147
164
  }
@@ -8,11 +8,19 @@ import com.swmansion.enriched.EnrichedTextInputView
8
8
  import com.swmansion.enriched.spans.EnrichedOrderedListSpan
9
9
  import com.swmansion.enriched.spans.EnrichedSpans
10
10
  import com.swmansion.enriched.spans.EnrichedUnorderedListSpan
11
+ import com.swmansion.enriched.utils.EnrichedConstants
11
12
  import com.swmansion.enriched.utils.getParagraphBounds
12
13
  import com.swmansion.enriched.utils.getSafeSpanBoundaries
13
-
14
- class ListStyles(private val view: EnrichedTextInputView) {
15
- private fun <T>getPreviousParagraphSpan(spannable: Spannable, s: Int, type: Class<T>): T? {
14
+ import com.swmansion.enriched.utils.removeZWS
15
+
16
+ class ListStyles(
17
+ private val view: EnrichedTextInputView,
18
+ ) {
19
+ private fun <T> getPreviousParagraphSpan(
20
+ spannable: Spannable,
21
+ s: Int,
22
+ type: Class<T>,
23
+ ): T? {
16
24
  if (s <= 0) return null
17
25
 
18
26
  val (previousParagraphStart, previousParagraphEnd) = spannable.getParagraphBounds(s - 1)
@@ -25,19 +33,31 @@ class ListStyles(private val view: EnrichedTextInputView) {
25
33
  return null
26
34
  }
27
35
 
28
- private fun <T>isPreviousParagraphList(spannable: Spannable, s: Int, type: Class<T>): Boolean {
36
+ private fun <T> isPreviousParagraphList(
37
+ spannable: Spannable,
38
+ s: Int,
39
+ type: Class<T>,
40
+ ): Boolean {
29
41
  val previousSpan = getPreviousParagraphSpan(spannable, s, type)
30
42
 
31
43
  return previousSpan != null
32
44
  }
33
45
 
34
- private fun getOrderedListIndex(spannable: Spannable, s: Int): Int {
46
+ private fun getOrderedListIndex(
47
+ spannable: Spannable,
48
+ s: Int,
49
+ ): Int {
35
50
  val span = getPreviousParagraphSpan(spannable, s, EnrichedOrderedListSpan::class.java)
36
51
  val index = span?.getIndex() ?: 0
37
52
  return index + 1
38
53
  }
39
54
 
40
- private fun setSpan(spannable: Spannable, name: String, start: Int, end: Int) {
55
+ private fun setSpan(
56
+ spannable: Spannable,
57
+ name: String,
58
+ start: Int,
59
+ end: Int,
60
+ ) {
41
61
  val (safeStart, safeEnd) = spannable.getSafeSpanBoundaries(start, end)
42
62
 
43
63
  if (name == EnrichedSpans.UNORDERED_LIST) {
@@ -53,7 +73,12 @@ class ListStyles(private val view: EnrichedTextInputView) {
53
73
  }
54
74
  }
55
75
 
56
- private fun <T>removeSpansForRange(spannable: Spannable, start: Int, end: Int, clazz: Class<T>): Boolean {
76
+ private fun <T> removeSpansForRange(
77
+ spannable: Spannable,
78
+ start: Int,
79
+ end: Int,
80
+ clazz: Class<T>,
81
+ ): Boolean {
57
82
  val ssb = spannable as SpannableStringBuilder
58
83
  val spans = ssb.getSpans(start, end, clazz)
59
84
  if (spans.isEmpty()) return false
@@ -62,13 +87,17 @@ class ListStyles(private val view: EnrichedTextInputView) {
62
87
  ssb.removeSpan(span)
63
88
  }
64
89
 
65
- ssb.replace(start, end, ssb.substring(start, end).replace("\u200B", ""))
90
+ ssb.removeZWS(start, end)
66
91
  return true
67
92
  }
68
93
 
69
- fun updateOrderedListIndexes(text: Spannable, position: Int) {
94
+ fun updateOrderedListIndexes(
95
+ text: Spannable,
96
+ position: Int,
97
+ ) {
70
98
  val spans = text.getSpans(position + 1, text.length, EnrichedOrderedListSpan::class.java)
71
- for (span in spans) {
99
+ val sortedSpans = spans.sortedBy { text.getSpanStart(it) }
100
+ for (span in sortedSpans) {
72
101
  val spanStart = text.getSpanStart(span)
73
102
  val index = getOrderedListIndex(text, spanStart)
74
103
  span.setIndex(index)
@@ -91,7 +120,7 @@ class ListStyles(private val view: EnrichedTextInputView) {
91
120
  }
92
121
 
93
122
  if (start == end) {
94
- spannable.insert(start, "\u200B")
123
+ spannable.insert(start, EnrichedConstants.ZWS_STRING)
95
124
  view.spanState?.setStart(name, start + 1)
96
125
  removeSpansForRange(spannable, start, end, config.clazz)
97
126
  setSpan(spannable, name, start, end + 1)
@@ -104,7 +133,7 @@ class ListStyles(private val view: EnrichedTextInputView) {
104
133
  removeSpansForRange(spannable, start, end, config.clazz)
105
134
 
106
135
  for (paragraph in paragraphs) {
107
- spannable.insert(currentStart, "\u200B")
136
+ spannable.insert(currentStart, EnrichedConstants.ZWS_STRING)
108
137
  val currentEnd = currentStart + paragraph.length + 1
109
138
  setSpan(spannable, name, currentStart, currentEnd)
110
139
 
@@ -114,7 +143,12 @@ class ListStyles(private val view: EnrichedTextInputView) {
114
143
  view.spanState?.setStart(name, currentStart)
115
144
  }
116
145
 
117
- private fun handleAfterTextChanged(s: Editable, name: String, endCursorPosition: Int, previousTextLength: Int) {
146
+ private fun handleAfterTextChanged(
147
+ s: Editable,
148
+ name: String,
149
+ endCursorPosition: Int,
150
+ previousTextLength: Int,
151
+ ) {
118
152
  val config = EnrichedSpans.listSpans[name] ?: return
119
153
  val cursorPosition = endCursorPosition.coerceAtMost(s.length)
120
154
  val (start, end) = s.getParagraphBounds(cursorPosition)
@@ -131,7 +165,7 @@ class ListStyles(private val view: EnrichedTextInputView) {
131
165
  }
132
166
 
133
167
  if (!isBackspace && isShortcut) {
134
- s.replace(start, cursorPosition, "\u200B")
168
+ s.replace(start, cursorPosition, EnrichedConstants.ZWS_STRING)
135
169
  setSpan(s, name, start, start + 1)
136
170
  // Inform that new span has been added
137
171
  view.selection?.validateStyles()
@@ -139,7 +173,7 @@ class ListStyles(private val view: EnrichedTextInputView) {
139
173
  }
140
174
 
141
175
  if (!isBackspace && isNewLine && isPreviousParagraphList(s, start, config.clazz)) {
142
- s.insert(cursorPosition, "\u200B")
176
+ s.insert(cursorPosition, EnrichedConstants.ZWS_STRING)
143
177
  setSpan(s, name, start, end + 1)
144
178
  // Inform that new span has been added
145
179
  view.selection?.validateStyles()
@@ -155,16 +189,22 @@ class ListStyles(private val view: EnrichedTextInputView) {
155
189
  }
156
190
  }
157
191
 
158
- fun afterTextChanged(s: Editable, endCursorPosition: Int, previousTextLength: Int) {
192
+ fun afterTextChanged(
193
+ s: Editable,
194
+ endCursorPosition: Int,
195
+ previousTextLength: Int,
196
+ ) {
159
197
  handleAfterTextChanged(s, EnrichedSpans.ORDERED_LIST, endCursorPosition, previousTextLength)
160
198
  handleAfterTextChanged(s, EnrichedSpans.UNORDERED_LIST, endCursorPosition, previousTextLength)
161
199
  }
162
200
 
163
- fun getStyleRange(): Pair<Int, Int> {
164
- return view.selection?.getParagraphSelection() ?: Pair(0, 0)
165
- }
201
+ fun getStyleRange(): Pair<Int, Int> = view.selection?.getParagraphSelection() ?: Pair(0, 0)
166
202
 
167
- fun removeStyle(name: String, start: Int, end: Int): Boolean {
203
+ fun removeStyle(
204
+ name: String,
205
+ start: Int,
206
+ end: Int,
207
+ ): Boolean {
168
208
  val config = EnrichedSpans.listSpans[name] ?: return false
169
209
  val spannable = view.text as Spannable
170
210
  return removeSpansForRange(spannable, start, end, config.clazz)