Skip to content

Commit 8fef696

Browse files
authored
Merge branch 'main' into @ksienkiewicz/fix-list-styling
2 parents 1582dce + 9b76677 commit 8fef696

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
@@ -31,6 +31,7 @@ import com.swmansion.enriched.common.updateOrderedListColumnMargins
3131
import com.swmansion.enriched.text.spans.EnrichedTextImageSpan
3232
import com.swmansion.enriched.text.spans.interfaces.EnrichedTextClickableSpan
3333
import com.swmansion.enriched.text.spans.interfaces.EnrichedTextSpan
34+
import com.swmansion.enriched.textinput.spans.EnrichedLineHeightSpan
3435
import kotlin.math.ceil
3536

3637
class EnrichedTextView : AppCompatTextView {
@@ -42,13 +43,15 @@ class EnrichedTextView : AppCompatTextView {
4243
private var fontWeight: Int = ReactConstants.UNSET
4344
private var fontSize: Float = EnrichedConstants.TEXT_DEFAULT_FONT_SIZE
4445
private var fontSizeRaw: Float? = null
46+
private var lineHeight: Float? = null
4547
private var htmlStyleMap: ReadableMap? = null
4648
var allowFontScaling: Boolean = EnrichedConstants.ALLOW_FONT_SCALING_DEFAULT
4749
set(value) {
4850
if (field == value) return
4951
field = value
5052
fontSizeRaw?.let { setFontSize(it) }
5153
htmlStyleMap?.let { setHtmlStyle(it) }
54+
applyLineSpacing()
5255
}
5356

5457
private var enrichedStyle: EnrichedTextStyle? = null
@@ -187,6 +190,7 @@ class EnrichedTextView : AppCompatTextView {
187190
parsedText = null
188191
this.text = text
189192
}
193+
applyLineSpacing()
190194
}
191195

192196
private fun parseText(
@@ -308,6 +312,33 @@ class EnrichedTextView : AppCompatTextView {
308312
setTextSize(TypedValue.COMPLEX_UNIT_PX, sizeInt)
309313
}
310314

315+
fun setLineHeight(height: Float) {
316+
lineHeight = if (height <= 0f) null else height
317+
applyLineSpacing()
318+
}
319+
320+
private fun applyLineSpacing() {
321+
val currentText = text ?: return
322+
val spannable =
323+
currentText as? Spannable ?: SpannableString(currentText)
324+
spannable
325+
.getSpans(0, spannable.length, EnrichedLineHeightSpan::class.java)
326+
.forEach { spannable.removeSpan(it) }
327+
328+
lineHeight?.let {
329+
spannable.setSpan(
330+
EnrichedLineHeightSpan(it, allowFontScaling),
331+
0,
332+
spannable.length,
333+
Spannable.SPAN_INCLUSIVE_INCLUSIVE,
334+
)
335+
}
336+
337+
if (spannable !== currentText) {
338+
setText(spannable, BufferType.SPANNABLE)
339+
}
340+
}
341+
311342
fun setFontFamily(family: String?) {
312343
if (family != fontFamily) {
313344
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
@@ -572,7 +572,7 @@ class EnrichedTextInputView :
572572
}
573573

574574
fun setLineHeight(height: Float) {
575-
lineHeight = if (height == 0f) null else height
575+
lineHeight = if (height <= 0f) null else height
576576
applyLineSpacing()
577577
layoutManager.invalidateLayout()
578578
forceScrollToSelection()

0 commit comments

Comments
 (0)