Skip to content

Commit 493fa45

Browse files
authored
Merge branch 'main' into @ksienkiewicz/fix-web-destroyed-editor-check
2 parents 1e97f54 + 9b76677 commit 493fa45

32 files changed

Lines changed: 604 additions & 56 deletions

.github/workflows/docs-build.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,17 @@ jobs:
3939

4040
- name: Build docs
4141
run: yarn build
42+
43+
- name: Check docs llms.txt
44+
run: |
45+
file=build/llms.txt
46+
if [ ! -s "$file" ]; then
47+
echo "::error::$file is missing or empty"
48+
exit 1
49+
fi
50+
count=$(grep -cE '^- \[[^]]+\]\(https://docs\.swmansion\.com/react-native-enriched-html/[^)]+\)' "$file" || true)
51+
if [ "$count" -eq 0 ]; then
52+
echo "::error::$file lists no pages"
53+
exit 1
54+
fi
55+
echo "llms.txt lists $count pages"
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
appId: swmansion.enriched.example
2+
---
3+
# Verifies that typing attributes are properly preserved on selection changes
4+
- launchApp
5+
6+
- tapOn:
7+
id: 'toggle-screen-button'
8+
9+
- tapOn:
10+
id: "editor-input"
11+
12+
- tapOn:
13+
id: "toolbar-bold"
14+
15+
- inputText: 'bold text'
16+
- pressKey: Enter
17+
- pressKey: Enter
18+
- pressKey: Enter
19+
- inputText: 'another line'
20+
21+
- doubleTapOn:
22+
id: 'editor-input'
23+
point: '20%, 75%'
24+
25+
- tapOn:
26+
id: 'editor-input'
27+
point: '50%, 15%'
28+
29+
- inputText: 'new'
30+
31+
- runFlow:
32+
file: '../subflows/capture_or_assert_screenshot.yaml'
33+
env:
34+
SCREENSHOT_NAME: 'preserve_typing_attributes_on_selection_changes'
9.81 KB
Loading
8 Bytes
Loading
21 Bytes
Loading
11.6 KB
Loading

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import com.swmansion.enriched.common.pixelFromSpOrDp
3030
import com.swmansion.enriched.text.spans.EnrichedTextImageSpan
3131
import com.swmansion.enriched.text.spans.interfaces.EnrichedTextClickableSpan
3232
import com.swmansion.enriched.text.spans.interfaces.EnrichedTextSpan
33+
import com.swmansion.enriched.textinput.spans.EnrichedLineHeightSpan
3334
import kotlin.math.ceil
3435

3536
class EnrichedTextView : AppCompatTextView {
@@ -41,13 +42,15 @@ class EnrichedTextView : AppCompatTextView {
4142
private var fontWeight: Int = ReactConstants.UNSET
4243
private var fontSize: Float = EnrichedConstants.TEXT_DEFAULT_FONT_SIZE
4344
private var fontSizeRaw: Float? = null
45+
private var lineHeight: Float? = null
4446
private var htmlStyleMap: ReadableMap? = null
4547
var allowFontScaling: Boolean = EnrichedConstants.ALLOW_FONT_SCALING_DEFAULT
4648
set(value) {
4749
if (field == value) return
4850
field = value
4951
fontSizeRaw?.let { setFontSize(it) }
5052
htmlStyleMap?.let { setHtmlStyle(it) }
53+
applyLineSpacing()
5154
}
5255

5356
private var enrichedStyle: EnrichedTextStyle? = null
@@ -185,6 +188,7 @@ class EnrichedTextView : AppCompatTextView {
185188
parsedText = null
186189
this.text = text
187190
}
191+
applyLineSpacing()
188192
}
189193

190194
private fun parseText(
@@ -305,6 +309,33 @@ class EnrichedTextView : AppCompatTextView {
305309
setTextSize(TypedValue.COMPLEX_UNIT_PX, sizeInt)
306310
}
307311

312+
fun setLineHeight(height: Float) {
313+
lineHeight = if (height <= 0f) null else height
314+
applyLineSpacing()
315+
}
316+
317+
private fun applyLineSpacing() {
318+
val currentText = text ?: return
319+
val spannable =
320+
currentText as? Spannable ?: SpannableString(currentText)
321+
spannable
322+
.getSpans(0, spannable.length, EnrichedLineHeightSpan::class.java)
323+
.forEach { spannable.removeSpan(it) }
324+
325+
lineHeight?.let {
326+
spannable.setSpan(
327+
EnrichedLineHeightSpan(it, allowFontScaling),
328+
0,
329+
spannable.length,
330+
Spannable.SPAN_INCLUSIVE_INCLUSIVE,
331+
)
332+
}
333+
334+
if (spannable !== currentText) {
335+
setText(spannable, BufferType.SPANNABLE)
336+
}
337+
}
338+
308339
fun setFontFamily(family: String?) {
309340
if (family != fontFamily) {
310341
fontFamily = family

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ class EnrichedTextViewManager :
5353
view?.setFontSize(value)
5454
}
5555

56+
override fun setLineHeight(
57+
view: EnrichedTextView?,
58+
value: Float,
59+
) {
60+
view?.setLineHeight(value)
61+
}
62+
5663
override fun setFontFamily(
5764
view: EnrichedTextView?,
5865
value: String?,

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

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import android.content.Context
44
import android.graphics.Typeface
55
import android.graphics.text.LineBreaker
66
import android.os.Build
7+
import android.text.Spannable
8+
import android.text.SpannableString
79
import android.text.StaticLayout
810
import android.text.TextPaint
911
import android.text.TextUtils
@@ -21,6 +23,7 @@ import com.swmansion.enriched.common.GumboNormalizer
2123
import com.swmansion.enriched.common.allowFontScalingFromProps
2224
import com.swmansion.enriched.common.parser.EnrichedParser
2325
import com.swmansion.enriched.common.pixelFromSpOrDp
26+
import com.swmansion.enriched.textinput.spans.EnrichedLineHeightSpan
2427
import kotlin.math.ceil
2528

2629
object MeasurementStore {
@@ -134,6 +137,13 @@ object MeasurementStore {
134137
return props.getBoolean("useHtmlNormalizer")
135138
}
136139

140+
private fun lineHeightFromProps(props: ReadableMap?): Float {
141+
if (props == null || !props.hasKey("lineHeight") || props.isNull("lineHeight")) {
142+
return 0f
143+
}
144+
return props.getDouble("lineHeight").toFloat()
145+
}
146+
137147
private fun getInitialFontSize(props: ReadableMap?): Float {
138148
val propsFontSize = props?.getDouble("fontSize")?.toFloat() ?: EnrichedConstants.TEXT_DEFAULT_FONT_SIZE
139149
val fontSize =
@@ -151,15 +161,31 @@ object MeasurementStore {
151161
props: ReadableMap?,
152162
): Long {
153163
val fontSize = getInitialFontSize(props)
154-
val text = getInitialText(context, fontSize.toInt(), props)
164+
val rawText = getInitialText(context, fontSize.toInt(), props)
165+
val lineHeight = lineHeightFromProps(props)
166+
val allowFontScaling = allowFontScalingFromProps(props)
167+
168+
val measuredText: CharSequence =
169+
if (lineHeight > 0f) {
170+
val spannable = SpannableString(rawText)
171+
spannable.setSpan(
172+
EnrichedLineHeightSpan(lineHeight, allowFontScaling),
173+
0,
174+
spannable.length,
175+
Spannable.SPAN_INCLUSIVE_INCLUSIVE,
176+
)
177+
spannable
178+
} else {
179+
rawText
180+
}
155181

156182
val fontFamily = props?.getString("fontFamily")
157183
val numberOfLines = props?.getInt("numberOfLines") ?: 0
158184
val ellipsizeMode = props?.getString("ellipsizeMode")
159185
val fontStyle = parseFontStyle(props?.getString("fontStyle"))
160186
val fontWeight = parseFontWeight(props?.getString("fontWeight"))
161187
val typeface = applyStyles(null, fontStyle, fontWeight, fontFamily, context.assets)
162-
val size = measure(width, text, typeface, fontSize, numberOfLines, ellipsizeMode)
188+
val size = measure(width, measuredText, typeface, fontSize, numberOfLines, ellipsizeMode)
163189

164190
return size
165191
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -568,7 +568,7 @@ class EnrichedTextInputView :
568568
}
569569

570570
fun setLineHeight(height: Float) {
571-
lineHeight = if (height == 0f) null else height
571+
lineHeight = if (height <= 0f) null else height
572572
applyLineSpacing()
573573
layoutManager.invalidateLayout()
574574
forceScrollToSelection()

0 commit comments

Comments
 (0)