-
Notifications
You must be signed in to change notification settings - Fork 67
Expand file tree
/
Copy pathEnrichedTextStyle.kt
More file actions
194 lines (183 loc) · 7.65 KB
/
Copy pathEnrichedTextStyle.kt
File metadata and controls
194 lines (183 loc) · 7.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
package com.swmansion.enriched.text
import android.graphics.Color
import com.facebook.react.bridge.ColorPropConverter
import com.facebook.react.bridge.ReactContext
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.views.text.ReactTypefaceUtils.parseFontWeight
import com.swmansion.enriched.common.EnrichedStyle
import com.swmansion.enriched.common.MentionStyle
import com.swmansion.enriched.common.pixelFromSpOrDp
import kotlin.math.ceil
data class EnrichedTextStyle(
// Headings
override val h1FontSize: Int,
override val h1Bold: Boolean,
override val h2FontSize: Int,
override val h2Bold: Boolean,
override val h3FontSize: Int,
override val h3Bold: Boolean,
override val h4FontSize: Int,
override val h4Bold: Boolean,
override val h5FontSize: Int,
override val h5Bold: Boolean,
override val h6FontSize: Int,
override val h6Bold: Boolean,
// Blockquote
override val blockquoteColor: Int?,
override val blockquoteBorderColor: Int,
override val blockquoteStripeWidth: Int,
override val blockquoteGapWidth: Int,
// Ordered List
override val olGapWidth: Int,
override val olMarginLeft: Int,
override val olMarkerFontWeight: Int?,
override val olMarkerColor: Int?,
// Unordered List
override val ulGapWidth: Int,
override val ulMarginLeft: Int,
override val ulBulletSize: Int,
override val ulBulletColor: Int,
// Checkbox List
override val ulCheckboxBoxColor: Int,
override val ulCheckboxBoxSize: Int,
override val ulCheckboxGapWidth: Int,
override val ulCheckboxMarginLeft: Int,
// Links
override val aColor: Int,
override val aUnderline: Boolean,
val aPressColor: Int,
// Code Blocks
override val codeBlockColor: Int,
override val codeBlockBackgroundColor: Int,
override val codeBlockRadius: Float,
// Inline Code
override val inlineCodeColor: Int,
override val inlineCodeBackgroundColor: Int,
// Mentions
override val mentionsStyle: Map<String, MentionStyle>,
) : EnrichedStyle {
companion object {
fun fromReadableMap(
context: ReactContext,
fontSize: Int,
map: ReadableMap,
allowFontScaling: Boolean,
): EnrichedTextStyle {
val h1 = map.getMap("h1")
val h2 = map.getMap("h2")
val h3 = map.getMap("h3")
val h4 = map.getMap("h4")
val h5 = map.getMap("h5")
val h6 = map.getMap("h6")
val blockquote = map.getMap("blockquote")
val orderedList = map.getMap("ol")
val unorderedList = map.getMap("ul")
val checkboxList = map.getMap("ulCheckbox")
val link = map.getMap("a")
val codeblock = map.getMap("codeblock")
val inlineCode = map.getMap("code")
val mentions = map.getMap("mention")
return EnrichedTextStyle(
h1FontSize = parseFloat(h1, "fontSize", allowFontScaling).toInt(),
h1Bold = h1?.getBoolean("bold") ?: false,
h2FontSize = parseFloat(h2, "fontSize", allowFontScaling).toInt(),
h2Bold = h2?.getBoolean("bold") ?: false,
h3FontSize = parseFloat(h3, "fontSize", allowFontScaling).toInt(),
h3Bold = h3?.getBoolean("bold") ?: false,
h4FontSize = parseFloat(h4, "fontSize", allowFontScaling).toInt(),
h4Bold = h4?.getBoolean("bold") ?: false,
h5FontSize = parseFloat(h5, "fontSize", allowFontScaling).toInt(),
h5Bold = h5?.getBoolean("bold") ?: false,
h6FontSize = parseFloat(h6, "fontSize", allowFontScaling).toInt(),
h6Bold = h6?.getBoolean("bold") ?: false,
blockquoteColor = parseOptionalColor(context, blockquote, "color"),
blockquoteBorderColor = parseColor(context, blockquote, "borderColor"),
blockquoteStripeWidth = parseFloat(blockquote, "borderWidth", allowFontScaling).toInt(),
blockquoteGapWidth = parseFloat(blockquote, "gapWidth", allowFontScaling).toInt(),
olGapWidth = parseFloat(orderedList, "gapWidth", allowFontScaling).toInt(),
olMarginLeft = parseFloat(orderedList, "marginLeft", allowFontScaling).toInt(),
olMarkerFontWeight = parseOptionalFontWeight(orderedList, "markerFontWeight"),
olMarkerColor = parseOptionalColor(context, orderedList, "markerColor"),
ulGapWidth = parseFloat(unorderedList, "gapWidth", allowFontScaling).toInt(),
ulMarginLeft = parseFloat(unorderedList, "marginLeft", allowFontScaling).toInt(),
ulBulletSize = parseFloat(unorderedList, "bulletSize", allowFontScaling).toInt(),
ulBulletColor = parseColor(context, unorderedList, "bulletColor"),
ulCheckboxBoxColor = parseColor(context, checkboxList, "boxColor"),
ulCheckboxBoxSize = parseFloat(checkboxList, "boxSize", allowFontScaling).toInt(),
ulCheckboxGapWidth = parseFloat(checkboxList, "gapWidth", allowFontScaling).toInt(),
ulCheckboxMarginLeft = parseFloat(checkboxList, "marginLeft", allowFontScaling).toInt(),
aColor = parseColor(context, link, "color"),
aUnderline = parseIsUnderline(link),
aPressColor = parseColor(context, link, "pressColor"),
codeBlockColor = parseColor(context, codeblock, "color"),
codeBlockBackgroundColor = parseColorWithOpacity(context, codeblock, "backgroundColor", 80),
codeBlockRadius = parseFloat(codeblock, "borderRadius", allowFontScaling),
inlineCodeColor = parseColor(context, inlineCode, "color"),
inlineCodeBackgroundColor = parseColorWithOpacity(context, inlineCode, "backgroundColor", 80),
mentionsStyle = parseMentionsStyle(context, mentions),
)
}
private fun parseFloat(
map: ReadableMap?,
key: String,
allowFontScaling: Boolean,
): Float {
if (map == null || !map.hasKey(key) || map.isNull(key)) return 0f
return ceil(pixelFromSpOrDp(map.getDouble(key), allowFontScaling))
}
private fun parseColor(
context: ReactContext,
map: ReadableMap?,
key: String,
): Int {
val colorDouble = map?.getDouble(key) ?: throw Error("Key $key is missing or null")
return ColorPropConverter.getColor(colorDouble, context) ?: Color.BLACK
}
private fun parseOptionalColor(
context: ReactContext,
map: ReadableMap?,
key: String,
): Int? {
if (map == null || !map.hasKey(key) || map.isNull(key)) return null
return ColorPropConverter.getColor(map.getDouble(key), context)
}
private fun parseColorWithOpacity(
context: ReactContext,
map: ReadableMap?,
key: String,
opacity: Int,
): Int {
val color = parseColor(context, map, key)
if (Color.alpha(color) != 255) return color
return (color and 0x00FFFFFF) or (opacity.coerceIn(0, 255) shl 24)
}
private fun parseIsUnderline(map: ReadableMap?): Boolean = map?.getString("textDecorationLine") == "underline"
private fun parseOptionalFontWeight(
map: ReadableMap?,
key: String,
): Int? {
val weight = map?.getString(key) ?: return null
return parseFontWeight(weight)
}
private fun parseMentionsStyle(
context: ReactContext,
map: ReadableMap?,
): Map<String, MentionStyle> {
val result = mutableMapOf<String, MentionStyle>()
val iterator = map?.keySetIterator() ?: return result
while (iterator.hasNextKey()) {
val key = iterator.nextKey()
val value = map.getMap(key) ?: continue
result[key] =
MentionStyle(
color = parseColor(context, value, "color"),
backgroundColor = parseColorWithOpacity(context, value, "backgroundColor", 80),
underline = parseIsUnderline(value),
pressColor = parseColor(context, value, "pressColor"),
pressBackgroundColor = parseColorWithOpacity(context, value, "pressBackgroundColor", 80),
)
}
return result
}
}
}