@craft-native/android 0.0.160 → 0.0.161
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
CHANGED
|
@@ -98,7 +98,11 @@ craft android build --native-bundle ../native-screen.js
|
|
|
98
98
|
|
|
99
99
|
Native mode maps STX `View`, `SafeAreaView`, `Text`, `Button`, `Link`, `Icon`,
|
|
100
100
|
`Pressable`, `TouchableOpacity`, `TouchableHighlight`, `Checkbox`, `TextInput`, `Picker`, `DatePicker`, `Modal`, `Switch`, `Slider`, `ActivityIndicator`, `Image`, `Video`, `ScrollView`,
|
|
101
|
-
and `FlatList` to Android views. `
|
|
101
|
+
`SectionList`, and `FlatList` to Android views. `SectionList` uses the same
|
|
102
|
+
native scroll host for ordinary `.stx` slot children; grouped section data
|
|
103
|
+
should use `FlatList` until the section-data protocol is available. The
|
|
104
|
+
generated host routes both list names through `CraftNativeScrollView` for this
|
|
105
|
+
slot-based contract. `Picker` renders `<select>`/`<option>` values
|
|
102
106
|
with `onValueChange` or `onChange`. `DatePicker` uses the platform `DatePicker`
|
|
103
107
|
and `TimePicker` controls for date, time, datetime, and countdown modes and
|
|
104
108
|
emits local `value`, ISO, and millisecond `timestamp` fields. `Modal` is parent-scoped and supports
|
package/package.json
CHANGED
|
@@ -298,6 +298,43 @@ object CraftNative {
|
|
|
298
298
|
margins: FloatArray,
|
|
299
299
|
flags: FloatArray,
|
|
300
300
|
): FloatArray?
|
|
301
|
+
private external fun nativeGridAligned(
|
|
302
|
+
availableWidth: Float,
|
|
303
|
+
availableHeight: Float,
|
|
304
|
+
columns: Int,
|
|
305
|
+
columnGap: Float,
|
|
306
|
+
rowGap: Float,
|
|
307
|
+
alignContent: Int,
|
|
308
|
+
intrinsicWidth: FloatArray,
|
|
309
|
+
intrinsicHeight: FloatArray,
|
|
310
|
+
explicitWidth: FloatArray,
|
|
311
|
+
explicitHeight: FloatArray,
|
|
312
|
+
minWidth: FloatArray,
|
|
313
|
+
maxWidth: FloatArray,
|
|
314
|
+
minHeight: FloatArray,
|
|
315
|
+
maxHeight: FloatArray,
|
|
316
|
+
margins: FloatArray,
|
|
317
|
+
flags: FloatArray,
|
|
318
|
+
): FloatArray?
|
|
319
|
+
private external fun nativeGridAutoRowsAligned(
|
|
320
|
+
availableWidth: Float,
|
|
321
|
+
availableHeight: Float,
|
|
322
|
+
columns: Int,
|
|
323
|
+
columnGap: Float,
|
|
324
|
+
rowGap: Float,
|
|
325
|
+
alignContent: Int,
|
|
326
|
+
autoRowHeight: Float,
|
|
327
|
+
intrinsicWidth: FloatArray,
|
|
328
|
+
intrinsicHeight: FloatArray,
|
|
329
|
+
explicitWidth: FloatArray,
|
|
330
|
+
explicitHeight: FloatArray,
|
|
331
|
+
minWidth: FloatArray,
|
|
332
|
+
maxWidth: FloatArray,
|
|
333
|
+
minHeight: FloatArray,
|
|
334
|
+
maxHeight: FloatArray,
|
|
335
|
+
margins: FloatArray,
|
|
336
|
+
flags: FloatArray,
|
|
337
|
+
): FloatArray?
|
|
301
338
|
private external fun nativeClipboardRead(activity: Activity): String?
|
|
302
339
|
private external fun nativeClipboardWrite(activity: Activity, text: String): Boolean
|
|
303
340
|
private external fun nativeOpenUrl(activity: Activity, url: String): Boolean
|
|
@@ -532,13 +569,14 @@ object CraftNative {
|
|
|
532
569
|
margins: FloatArray,
|
|
533
570
|
flags: FloatArray,
|
|
534
571
|
autoRowHeight: Float? = null,
|
|
572
|
+
alignContent: Int = 0,
|
|
535
573
|
): FloatArray? {
|
|
536
574
|
if (!isAvailable) return null
|
|
537
575
|
return try {
|
|
538
576
|
if (autoRowHeight != null) {
|
|
539
|
-
|
|
577
|
+
nativeGridAutoRowsAligned(availableWidth, availableHeight, columns, columnGap, rowGap, alignContent, autoRowHeight, intrinsicWidth, intrinsicHeight, explicitWidth, explicitHeight, minWidth, maxWidth, minHeight, maxHeight, margins, flags)
|
|
540
578
|
} else {
|
|
541
|
-
|
|
579
|
+
nativeGridAligned(availableWidth, availableHeight, columns, columnGap, rowGap, alignContent, intrinsicWidth, intrinsicHeight, explicitWidth, explicitHeight, minWidth, maxWidth, minHeight, maxHeight, margins, flags)
|
|
542
580
|
}
|
|
543
581
|
?.takeIf { it.size >= intrinsicWidth.size * 4 && it.all { value -> value.isFinite() } }
|
|
544
582
|
} catch (e: UnsatisfiedLinkError) {
|
|
@@ -303,7 +303,8 @@ internal class CraftNativeCapabilities(
|
|
|
303
303
|
return FileResult.Multipart(body.toByteArray(), boundary)
|
|
304
304
|
}
|
|
305
305
|
|
|
306
|
-
private fun files(requestToken: String, method: String, args: JSONArray): CraftNativeCapabilityResult
|
|
306
|
+
private fun files(requestToken: String, method: String, args: JSONArray): CraftNativeCapabilityResult {
|
|
307
|
+
return when (method) {
|
|
307
308
|
"write" -> {
|
|
308
309
|
val name = args.optString(0).trim()
|
|
309
310
|
if (name.isBlank()) return failure("INVALID_ARGUMENT", "files.write needs a file name")
|
|
@@ -322,7 +323,8 @@ internal class CraftNativeCapabilities(
|
|
|
322
323
|
success(file.delete())
|
|
323
324
|
}
|
|
324
325
|
"download" -> download(requestToken, args)
|
|
325
|
-
|
|
326
|
+
else -> failure("UNKNOWN_ACTION", "Unsupported Files method")
|
|
327
|
+
}
|
|
326
328
|
}
|
|
327
329
|
|
|
328
330
|
private fun download(requestToken: String, args: JSONArray): CraftNativeCapabilityResult {
|
|
@@ -115,6 +115,7 @@ private data class CraftNativeLength(
|
|
|
115
115
|
private data class CraftNativeLayoutStyle(
|
|
116
116
|
val width: CraftNativeLength? = null,
|
|
117
117
|
val height: CraftNativeLength? = null,
|
|
118
|
+
val aspectRatio: Double? = null,
|
|
118
119
|
val minWidth: CraftNativeLength? = null,
|
|
119
120
|
val maxWidth: CraftNativeLength? = null,
|
|
120
121
|
val minHeight: CraftNativeLength? = null,
|
|
@@ -143,6 +144,7 @@ private data class CraftNativeLayoutStyle(
|
|
|
143
144
|
val flex = decimal("flex")
|
|
144
145
|
return CraftNativeLayoutStyle(
|
|
145
146
|
width = length("width"), height = length("height"),
|
|
147
|
+
aspectRatio = decimal("aspectRatio")?.takeIf { it.isFinite() && it > 0.0 },
|
|
146
148
|
minWidth = length("minWidth"), maxWidth = length("maxWidth"),
|
|
147
149
|
minHeight = length("minHeight"), maxHeight = length("maxHeight"),
|
|
148
150
|
position = raw.opt("position")
|
|
@@ -583,7 +585,8 @@ private class CraftNativeFlexLayout(context: Context) : LinearLayout(context) {
|
|
|
583
585
|
// The STX style is authoritative. A reused View may still carry a
|
|
584
586
|
// previous fixed LayoutParams width after a reactive width is removed;
|
|
585
587
|
// using that value here prevents intrinsic sizing from being restored.
|
|
586
|
-
val
|
|
588
|
+
val authored = style.width?.resolve(base)
|
|
589
|
+
val explicit = authored ?: style.aspectRatio?.let { ratio -> style.height?.resolve(base)?.times(ratio)?.roundToInt() } ?: flexBasis
|
|
587
590
|
if (explicit != null) {
|
|
588
591
|
child.measure(
|
|
589
592
|
View.MeasureSpec.makeMeasureSpec(explicit, View.MeasureSpec.EXACTLY),
|
|
@@ -613,7 +616,8 @@ private class CraftNativeFlexLayout(context: Context) : LinearLayout(context) {
|
|
|
613
616
|
val flexBasis = if (orientation == VERTICAL) style.flexBasis?.resolve(base) else null
|
|
614
617
|
// Match width measurement: do not let stale native LayoutParams keep
|
|
615
618
|
// a removed reactive height fixed.
|
|
616
|
-
val
|
|
619
|
+
val authored = style.height?.resolve(base)
|
|
620
|
+
val explicit = authored ?: style.aspectRatio?.let { ratio -> style.width?.resolve(base)?.div(ratio)?.roundToInt() } ?: flexBasis
|
|
617
621
|
val target = explicit ?: base
|
|
618
622
|
val spec = if (explicit != null) View.MeasureSpec.makeMeasureSpec(target, View.MeasureSpec.EXACTLY)
|
|
619
623
|
else View.MeasureSpec.makeMeasureSpec(base, View.MeasureSpec.AT_MOST)
|
|
@@ -772,6 +776,7 @@ private class CraftNativeFlexLayout(context: Context) : LinearLayout(context) {
|
|
|
772
776
|
listOf(if (align == "stretch") 1f else 0f, if (align == "center") 1f else if (align == "flex-end") 2f else 0f)
|
|
773
777
|
}.toFloatArray(),
|
|
774
778
|
gridAutoRows?.resolve(contentHeight)?.toFloat(),
|
|
779
|
+
alignContentCode(),
|
|
775
780
|
)
|
|
776
781
|
if (sharedFrames != null) {
|
|
777
782
|
for ((index, entry) in flow.withIndex()) {
|
|
@@ -783,9 +788,26 @@ private class CraftNativeFlexLayout(context: Context) : LinearLayout(context) {
|
|
|
783
788
|
entry.view.layout(x, y, x + childWidth, y + childHeight)
|
|
784
789
|
}
|
|
785
790
|
} else {
|
|
786
|
-
|
|
791
|
+
val totalRows = layout.rowHeights.sum()
|
|
792
|
+
val rowGaps = max(0, layout.rowHeights.size - 1) * rowGap
|
|
793
|
+
val freeRows = max(0, contentHeight - totalRows - rowGaps)
|
|
794
|
+
val rowCount = max(1, layout.rowHeights.size)
|
|
795
|
+
var rowLeading = 0
|
|
796
|
+
var rowBetween = rowGap
|
|
797
|
+
var rowExtra = 0
|
|
798
|
+
when (alignContentCode()) {
|
|
799
|
+
1 -> rowLeading = freeRows / 2
|
|
800
|
+
2 -> rowLeading = freeRows
|
|
801
|
+
3 -> if (rowCount > 1) rowBetween += freeRows / (rowCount - 1)
|
|
802
|
+
4 -> {
|
|
803
|
+
rowLeading = freeRows / (rowCount * 2)
|
|
804
|
+
rowBetween += freeRows / rowCount
|
|
805
|
+
}
|
|
806
|
+
5 -> rowExtra = freeRows / rowCount
|
|
807
|
+
}
|
|
808
|
+
var rowTop = paddingTop + rowLeading
|
|
787
809
|
for ((rowIndex, row) in layout.rows.withIndex()) {
|
|
788
|
-
val rowHeight = layout.rowHeights[rowIndex]
|
|
810
|
+
val rowHeight = layout.rowHeights[rowIndex] + rowExtra
|
|
789
811
|
for ((column, entry) in row.withIndex()) {
|
|
790
812
|
val align = entry.style.alignSelf ?: alignItems
|
|
791
813
|
val lp = entry.view.layoutParams as? MarginLayoutParams
|
|
@@ -809,7 +831,7 @@ private class CraftNativeFlexLayout(context: Context) : LinearLayout(context) {
|
|
|
809
831
|
}
|
|
810
832
|
entry.view.layout(x, y, x + childWidth, y + childHeight)
|
|
811
833
|
}
|
|
812
|
-
rowTop += rowHeight +
|
|
834
|
+
rowTop += rowHeight + rowBetween
|
|
813
835
|
}
|
|
814
836
|
}
|
|
815
837
|
for (entry in layout.absolute) {
|
|
@@ -2803,7 +2825,7 @@ class MainActivity : AppCompatActivity() {
|
|
|
2803
2825
|
"Svg" -> (previous as? CraftNativeSvgView ?: CraftNativeSvgView(this)).apply {
|
|
2804
2826
|
drawing = node
|
|
2805
2827
|
}
|
|
2806
|
-
"ScrollView" -> (previous as? CraftNativeScrollView ?: CraftNativeScrollView(this)).apply {
|
|
2828
|
+
"ScrollView", "SectionList" -> (previous as? CraftNativeScrollView ?: CraftNativeScrollView(this)).apply {
|
|
2807
2829
|
val horizontal = props.optBoolean("horizontal", false) || style.optString("flexDirection") in setOf("row", "row-reverse")
|
|
2808
2830
|
setHorizontal(horizontal)
|
|
2809
2831
|
setNativeNestedScrollingEnabled(true)
|
|
@@ -3064,6 +3086,7 @@ class MainActivity : AppCompatActivity() {
|
|
|
3064
3086
|
"video" -> "Video"
|
|
3065
3087
|
"icon" -> "Icon"
|
|
3066
3088
|
"scrollview" -> "ScrollView"
|
|
3089
|
+
"sectionlist" -> "SectionList"
|
|
3067
3090
|
"flatlist" -> "FlatList"
|
|
3068
3091
|
"svg" -> "Svg"
|
|
3069
3092
|
"touchableopacity" -> "TouchableOpacity"
|
|
@@ -3477,7 +3500,9 @@ class MainActivity : AppCompatActivity() {
|
|
|
3477
3500
|
else -> null
|
|
3478
3501
|
}
|
|
3479
3502
|
view.tooltipText = props.optString("accessibilityHint").takeIf { it.isNotBlank() }
|
|
3480
|
-
val role = props.optString("accessibilityRole").ifBlank {
|
|
3503
|
+
val role = props.optString("accessibilityRole").ifBlank {
|
|
3504
|
+
if (type == "Icon") "image" else type.lowercase()
|
|
3505
|
+
}
|
|
3481
3506
|
val state = props.optJSONObject("accessibilityState")
|
|
3482
3507
|
val disabled = props.optBoolean("disabled", false) || state?.optBoolean("disabled", false) == true
|
|
3483
3508
|
if (type !in setOf("Button", "Link", "Checkbox", "TextInput", "Picker", "DatePicker", "Modal", "Switch", "Slider", "ActivityIndicator")) {
|