@onekeyfe/react-native-native-list 6.7.0-alpha.406 → 6.7.0-alpha.409
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/android/src/main/java/com/onekey/nativelist/NativeListActivityDetailsView.kt +22 -1
- package/android/src/main/java/com/onekey/nativelist/NativeListActivityRenderer.kt +6 -10
- package/android/src/main/java/com/onekey/nativelist/NativeListModels.kt +10 -9
- package/android/src/test/java/com/margelo/nitro/nativelist/NativeListActivityHostClipPolicyTest.kt +11 -5
- package/docs/SPEC.md +12 -4
- package/package.json +3 -3
|
@@ -18,6 +18,9 @@ internal class NativeListActivityDetailsView(private val reactContext: ThemedRea
|
|
|
18
18
|
private val main = LinearLayout(context).apply { orientation = HORIZONTAL; gravity = Gravity.CENTER_VERTICAL }
|
|
19
19
|
private val identityColumn = LinearLayout(context).apply { orientation = HORIZONTAL; gravity = Gravity.CENTER_VERTICAL }
|
|
20
20
|
private val visual = NativeListLeadingVisual(reactContext, fonts)
|
|
21
|
+
/** Whether the bound leading visual lays a badge past its frame; see [setClipping]. */
|
|
22
|
+
var leadingOverhangs = false
|
|
23
|
+
private set
|
|
21
24
|
private val identity = LinearLayout(context).apply { orientation = VERTICAL }
|
|
22
25
|
private val titleLine = LinearLayout(context).apply { orientation = HORIZONTAL; gravity = Gravity.CENTER_VERTICAL }
|
|
23
26
|
private val title = NativeListTextView(context)
|
|
@@ -49,6 +52,18 @@ internal class NativeListActivityDetailsView(private val reactContext: ThemedRea
|
|
|
49
52
|
addView(main, LayoutParams(-1, -2))
|
|
50
53
|
addView(actions, LayoutParams(-1, -2))
|
|
51
54
|
}
|
|
55
|
+
/**
|
|
56
|
+
* Android clips a child to its own bounds while its parent clips children, so
|
|
57
|
+
* every view between the leading visual and the row host stops clipping when
|
|
58
|
+
* the visual's network badge overhangs its box (SPEC "Leading badge overhang",
|
|
59
|
+
* OK-66275); the host row applies the same policy to itself.
|
|
60
|
+
*/
|
|
61
|
+
private fun setClipping(clips: Boolean) {
|
|
62
|
+
for (group in listOf(identityColumn, main, this)) {
|
|
63
|
+
group.clipChildren = clips
|
|
64
|
+
group.clipToPadding = clips
|
|
65
|
+
}
|
|
66
|
+
}
|
|
52
67
|
private fun dp(value: Int) = if (sourceScale) (value * resources.displayMetrics.density).roundToInt() else NativeListScale.dp(resources, value)
|
|
53
68
|
private fun px(value: Double) = (value * resources.displayMetrics.density).roundToInt()
|
|
54
69
|
private fun color(tone: String, theme: JSONObject?): Int {
|
|
@@ -79,6 +94,8 @@ internal class NativeListActivityDetailsView(private val reactContext: ThemedRea
|
|
|
79
94
|
visual.visibility = if (hideLeading) GONE else VISIBLE
|
|
80
95
|
if (hideLeading) visual.recycle()
|
|
81
96
|
else visual.bind(data.optJSONObject("leading") ?: JSONObject(), image, item.key, theme, false, sourceScale, data.optJSONObject("secondaryLeading"))
|
|
97
|
+
leadingOverhangs = !hideLeading && visual.requestsUnclippedHost
|
|
98
|
+
setClipping(nativeListActivityHostClips(leadingOverhangs))
|
|
82
99
|
amounts.layoutParams = if (table) LayoutParams(0, -2, 1f).apply { marginStart = gap } else LayoutParams(-2, -2).apply { marginStart = gap }
|
|
83
100
|
text(title, data.optString("title"), style.optJSONObject("title"), 16f, color("primary", theme), 24, "medium")
|
|
84
101
|
text(description, data.optString("description"), style.optJSONObject("description"), 14f, color("secondary", theme), 20, lines = 2)
|
|
@@ -153,7 +170,11 @@ internal class NativeListActivityDetailsView(private val reactContext: ThemedRea
|
|
|
153
170
|
}
|
|
154
171
|
label.text = styled
|
|
155
172
|
}
|
|
156
|
-
fun recycle() {
|
|
173
|
+
fun recycle() {
|
|
174
|
+
visual.recycle(); visual.visibility = VISIBLE; amountViews.forEach { it.recycle() }; description.setOnClickListener(null); actions.removeAllViews()
|
|
175
|
+
leadingOverhangs = false
|
|
176
|
+
setClipping(true)
|
|
177
|
+
}
|
|
157
178
|
fun dispose() { recycle(); visual.dispose(); amountViews.forEach { it.dispose() } }
|
|
158
179
|
|
|
159
180
|
private inner class AmountView : LinearLayout(context) {
|
|
@@ -83,10 +83,11 @@ internal class NativeListActivityRowView(context: ThemedReactContext, fonts: Nat
|
|
|
83
83
|
setPadding(hp, vp, hp, vp)
|
|
84
84
|
visual.recycle()
|
|
85
85
|
details.bind(item, theme, sourceScale)
|
|
86
|
-
//
|
|
87
|
-
//
|
|
88
|
-
//
|
|
89
|
-
|
|
86
|
+
// The rich row's leading visual lives on the details view, where its
|
|
87
|
+
// network badge overhangs the box (OK-66275): this host must stop clipping
|
|
88
|
+
// as well, and a view reused from a badge row clips again when the bound
|
|
89
|
+
// row has no badge.
|
|
90
|
+
setHostClipping(nativeListActivityHostClips(details.leadingOverhangs))
|
|
90
91
|
return
|
|
91
92
|
}
|
|
92
93
|
details.recycle()
|
|
@@ -174,12 +175,7 @@ internal class NativeListActivityRowView(context: ThemedReactContext, fonts: Nat
|
|
|
174
175
|
// Stop clipping the content row and this row's padding exactly when the
|
|
175
176
|
// bound visual reports such a badge (SPEC "Leading badge overhang"), as the
|
|
176
177
|
// Identity renderer does.
|
|
177
|
-
setHostClipping(
|
|
178
|
-
nativeListActivityHostClips(
|
|
179
|
-
rich = false,
|
|
180
|
-
leadingOverhangs = !hideLeading && visual.requestsUnclippedHost,
|
|
181
|
-
)
|
|
182
|
-
)
|
|
178
|
+
setHostClipping(nativeListActivityHostClips(!hideLeading && visual.requestsUnclippedHost))
|
|
183
179
|
bind(
|
|
184
180
|
title,
|
|
185
181
|
data.optString("title"),
|
|
@@ -50,16 +50,17 @@ internal fun nativeListLeadingVisualOverhangsFrame(
|
|
|
50
50
|
): Boolean = kind == "token" && sourceCount > 1 || hasCornerIcon || overlayCount > 0
|
|
51
51
|
|
|
52
52
|
/**
|
|
53
|
-
* Whether an Activity row host
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
53
|
+
* Whether an Activity row host (and, for a rich `amounts` row, the details view
|
|
54
|
+
* with its nested columns) clips its children and padding for this bind. One
|
|
55
|
+
* row view serves both the legacy row and the rich row and is reused across
|
|
56
|
+
* binds, so clipping is derived from the bound item alone and applied on every
|
|
57
|
+
* bind: a row whose bound leading visual lays a badge past its frame
|
|
58
|
+
* ([nativeListLeadingVisualOverhangsFrame]) opts out, whether that visual sits
|
|
59
|
+
* on the host (legacy row, OK-66071) or on the details view (rich row,
|
|
60
|
+
* OK-66275); a row without such a badge clips again even when the view it
|
|
61
|
+
* reuses last showed one.
|
|
60
62
|
*/
|
|
61
|
-
internal fun nativeListActivityHostClips(
|
|
62
|
-
rich || !leadingOverhangs
|
|
63
|
+
internal fun nativeListActivityHostClips(leadingOverhangs: Boolean): Boolean = !leadingOverhangs
|
|
63
64
|
|
|
64
65
|
internal data class NativeListSlotFrame(val x: Int, val y: Int, val width: Int, val height: Int)
|
|
65
66
|
|
package/android/src/test/java/com/margelo/nitro/nativelist/NativeListActivityHostClipPolicyTest.kt
CHANGED
|
@@ -5,10 +5,12 @@ import org.junit.Test
|
|
|
5
5
|
|
|
6
6
|
class NativeListActivityHostClipPolicyTest {
|
|
7
7
|
// One Activity row view serves legacy and rich rows and is reused across
|
|
8
|
-
// binds. A
|
|
9
|
-
// clipping off
|
|
10
|
-
//
|
|
11
|
-
// a
|
|
8
|
+
// binds. A row with an overhanging network badge switches the host's
|
|
9
|
+
// clipping off, whether the badge sits on the host's visual (legacy row,
|
|
10
|
+
// OK-66071) or on the details view's visual (rich row, OK-66275); the next
|
|
11
|
+
// bind must derive clipping afresh, so a row without a badge reusing that
|
|
12
|
+
// view clips again instead of drawing over a neighbouring row (PR #185
|
|
13
|
+
// review).
|
|
12
14
|
@Test
|
|
13
15
|
fun rebindSequenceDerivesClippingFromEachBoundItem() {
|
|
14
16
|
data class Bind(val name: String, val rich: Boolean, val leadingOverhangs: Boolean, val clips: Boolean)
|
|
@@ -17,13 +19,17 @@ class NativeListActivityHostClipPolicyTest {
|
|
|
17
19
|
Bind("legacy row, plain token", rich = false, leadingOverhangs = false, clips = true),
|
|
18
20
|
Bind("legacy row, network badge", rich = false, leadingOverhangs = true, clips = false),
|
|
19
21
|
Bind("rich row reusing the badge row's view", rich = true, leadingOverhangs = false, clips = true),
|
|
22
|
+
// The app's history rows carry `amounts`, so their badge lives on the
|
|
23
|
+
// details view's leading visual: a rich row with such a badge must stop
|
|
24
|
+
// clipping too (OK-66275).
|
|
25
|
+
Bind("rich row, network badge in details", rich = true, leadingOverhangs = true, clips = false),
|
|
20
26
|
Bind("legacy row, badge again", rich = false, leadingOverhangs = true, clips = false),
|
|
21
27
|
Bind("legacy row, hidden leading", rich = false, leadingOverhangs = false, clips = true),
|
|
22
28
|
)
|
|
23
29
|
|
|
24
30
|
assertEquals(
|
|
25
31
|
binds.map(Bind::clips),
|
|
26
|
-
binds.map { nativeListActivityHostClips(
|
|
32
|
+
binds.map { nativeListActivityHostClips(leadingOverhangs = it.leadingOverhangs) },
|
|
27
33
|
)
|
|
28
34
|
}
|
|
29
35
|
}
|
package/docs/SPEC.md
CHANGED
|
@@ -778,7 +778,14 @@ Host clipping is per-bind state. A row view that serves several row shapes
|
|
|
778
778
|
(the Android Activity view serves the legacy row and the rich `amounts` row) is
|
|
779
779
|
reused across binds, so each bind MUST derive clipping from the item it binds
|
|
780
780
|
(`nativeListActivityHostClips`): a view that last showed an overhanging badge
|
|
781
|
-
clips again when it is rebound to a row without one.
|
|
781
|
+
clips again when it is rebound to a row without one. The rule follows the
|
|
782
|
+
visual, not the row shape: the rich row renders its leading visual on the
|
|
783
|
+
details view, so that view and every column between the visual and the host
|
|
784
|
+
stop clipping too, and the host derives its own clipping from the details
|
|
785
|
+
view's visual (`leadingOverhangs`, OK-66275). Before this rule the rich branch
|
|
786
|
+
forced the host's clipping back on and left the details view at Android's
|
|
787
|
+
defaults, so the app's history rows (which always carry `amounts`) still showed
|
|
788
|
+
the badge cut at the bottom-right after the legacy branch had been fixed.
|
|
782
789
|
|
|
783
790
|
The row's own shape still clips on every platform: iOS masks the cell to its
|
|
784
791
|
corner radius (`masksToBounds`), Web keeps the row `overflow: hidden`, and
|
|
@@ -815,9 +822,10 @@ over the badge. The per-source geometry is one pure function on Android
|
|
|
815
822
|
`NativeListLeadingVisual.layoutSubviews` on iOS; both restore the stacking
|
|
816
823
|
order by role on every bind because slots are reused across roles.
|
|
817
824
|
|
|
818
|
-
The Android Activity renderer also applies the badge-overhang rule above
|
|
819
|
-
(`requestsUnclippedHost` stops the content row
|
|
820
|
-
|
|
825
|
+
The Android Activity renderer also applies the badge-overhang rule above on
|
|
826
|
+
both of its branches (`requestsUnclippedHost` stops the legacy content row, the
|
|
827
|
+
rich details view with its columns, and the row padding clipping), so the
|
|
828
|
+
history rows' network badges render whole instead of cut flat.
|
|
821
829
|
|
|
822
830
|
## Failures, fallback and limits
|
|
823
831
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/react-native-native-list",
|
|
3
|
-
"version": "6.7.0-alpha.
|
|
3
|
+
"version": "6.7.0-alpha.409",
|
|
4
4
|
"description": "Template-driven native RecyclerView and UICollectionView for React Native",
|
|
5
5
|
"source": "./src/index.ts",
|
|
6
6
|
"main": "./lib/module/index.js",
|
|
@@ -86,8 +86,8 @@
|
|
|
86
86
|
"typescript": "^5.9.2"
|
|
87
87
|
},
|
|
88
88
|
"peerDependencies": {
|
|
89
|
-
"@onekeyfe/react-native-image": "6.7.0-alpha.
|
|
90
|
-
"@onekeyfe/react-native-native-logger": "6.7.0-alpha.
|
|
89
|
+
"@onekeyfe/react-native-image": "6.7.0-alpha.409",
|
|
90
|
+
"@onekeyfe/react-native-native-logger": "6.7.0-alpha.409",
|
|
91
91
|
"react": "*",
|
|
92
92
|
"react-native": "*",
|
|
93
93
|
"react-native-nitro-modules": "0.37.0"
|