@onekeyfe/react-native-native-list 3.0.157-alpha.249 → 3.0.157-alpha.251
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 +21 -5
- package/android/src/main/java/com/onekey/nativelist/NativeListAccessoryStack.kt +711 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListActionRenderer.kt +169 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListActivityRenderer.kt +243 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListAdapter.kt +20 -6
- package/android/src/main/java/com/onekey/nativelist/NativeListDataRowRenderer.kt +487 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListIdentityRenderer.kt +820 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListImageSlot.kt +147 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListLeadingVisual.kt +453 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListMarketRenderer.kt +997 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListMediaTileRenderer.kt +234 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListMessageRenderer.kt +232 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListMetricCardRenderer.kt +551 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListModels.kt +24 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListPrimitives.kt +475 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListRailRenderer.kt +143 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListRendererRegistry.kt +42 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListRendererRowView.kt +415 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListResolvedText.kt +163 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListRowHost.kt +70 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListSectionHeaderRenderer.kt +748 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListSystemRenderer.kt +464 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListTextView.kt +25 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListView.kt +174 -104
- package/android/src/main/java/com/onekey/nativelist/NativeListWalletGroupRenderer.kt +407 -0
- package/android/src/test/java/com/margelo/nitro/nativelist/NativeListSelectorBackgroundColorTest.kt +34 -0
- package/docs/DESIGN.md +518 -9
- package/docs/MIGRATION_BASELINE.md +117 -0
- package/docs/ROW_TEMPLATES.md +359 -0
- package/docs/SPEC.md +358 -0
- package/docs/STYLE_SPEC.md +978 -0
- package/docs/images/list-capabilities.svg +39 -0
- package/docs/images/row-action.svg +17 -0
- package/docs/images/row-activity.svg +24 -0
- package/docs/images/row-data.svg +24 -0
- package/docs/images/row-identity.svg +25 -0
- package/docs/images/row-market.svg +23 -0
- package/docs/images/row-media-tile.svg +26 -0
- package/docs/images/row-message.svg +20 -0
- package/docs/images/row-metric-card.svg +33 -0
- package/docs/images/row-rail.svg +18 -0
- package/docs/images/row-section-header.svg +19 -0
- package/docs/images/row-style-regions.svg +30 -0
- package/docs/images/row-system.svg +30 -0
- package/docs/images/row-wallet-group.svg +26 -0
- package/ios/NativeListAccessoryStack.swift +680 -0
- package/ios/NativeListActionRenderer.swift +108 -0
- package/ios/NativeListActivityRenderer.swift +179 -0
- package/ios/NativeListDataRowRenderer.swift +444 -0
- package/ios/NativeListIdentityRenderer.swift +685 -0
- package/ios/NativeListImageSlot.swift +140 -0
- package/ios/NativeListLeadingVisual.swift +372 -0
- package/ios/NativeListMarketRenderer.swift +698 -0
- package/ios/NativeListMediaTileRenderer.swift +184 -0
- package/ios/NativeListMessageRenderer.swift +168 -0
- package/ios/NativeListMetricCardRenderer.swift +420 -0
- package/ios/NativeListModels.swift +32 -0
- package/ios/NativeListRailRenderer.swift +152 -0
- package/ios/NativeListRendererCell.swift +311 -0
- package/ios/NativeListRendererRegistry.swift +50 -0
- package/ios/NativeListResolvedText.swift +122 -0
- package/ios/NativeListRowHost.swift +63 -0
- package/ios/NativeListSectionHeaderRenderer.swift +708 -0
- package/ios/NativeListSystemRenderer.swift +568 -0
- package/ios/NativeListTextLabel.swift +42 -0
- package/ios/NativeListTextStyles.swift +236 -0
- package/ios/NativeListWalletGroupRenderer.swift +255 -0
- package/ios/RNCNativeListView.swift +111 -180
- package/lib/module/models.js +54 -0
- package/lib/module/validation.js +324 -26
- package/lib/module/web/NativeListWebEngine.js +148 -936
- package/lib/module/web/templates/ActionRowRenderer.js +97 -0
- package/lib/module/web/templates/ActivityRowRenderer.js +95 -0
- package/lib/module/web/templates/DataRowRenderer.js +145 -0
- package/lib/module/web/templates/IdentityRowRenderer.js +289 -0
- package/lib/module/web/templates/MarketRowRenderer.js +310 -0
- package/lib/module/web/templates/MediaTileRowRenderer.js +132 -0
- package/lib/module/web/templates/MessageRowRenderer.js +165 -0
- package/lib/module/web/templates/MetricCardRowRenderer.js +172 -0
- package/lib/module/web/templates/RailRowRenderer.js +98 -0
- package/lib/module/web/templates/RowContainerStyle.js +100 -0
- package/lib/module/web/templates/RowElements.js +93 -0
- package/lib/module/web/templates/RowRendererRegistry.js +70 -0
- package/lib/module/web/templates/RowText.js +121 -0
- package/lib/module/web/templates/RowVisual.js +43 -0
- package/lib/module/web/templates/SectionHeaderRowRenderer.js +146 -0
- package/lib/module/web/templates/SystemRowRenderer.js +161 -0
- package/lib/module/web/templates/WalletGroupRowRenderer.js +96 -0
- package/lib/typescript/src/models.d.ts +166 -13
- package/lib/typescript/src/web/NativeListWebEngine.d.ts +18 -16
- package/lib/typescript/src/web/templates/ActionRowRenderer.d.ts +15 -0
- package/lib/typescript/src/web/templates/ActivityRowRenderer.d.ts +15 -0
- package/lib/typescript/src/web/templates/DataRowRenderer.d.ts +15 -0
- package/lib/typescript/src/web/templates/IdentityRowRenderer.d.ts +16 -0
- package/lib/typescript/src/web/templates/MarketRowRenderer.d.ts +30 -0
- package/lib/typescript/src/web/templates/MediaTileRowRenderer.d.ts +15 -0
- package/lib/typescript/src/web/templates/MessageRowRenderer.d.ts +44 -0
- package/lib/typescript/src/web/templates/MetricCardRowRenderer.d.ts +15 -0
- package/lib/typescript/src/web/templates/RailRowRenderer.d.ts +28 -0
- package/lib/typescript/src/web/templates/RowContainerStyle.d.ts +9 -0
- package/lib/typescript/src/web/templates/RowElements.d.ts +38 -0
- package/lib/typescript/src/web/templates/RowRendererRegistry.d.ts +83 -0
- package/lib/typescript/src/web/templates/RowText.d.ts +9 -0
- package/lib/typescript/src/web/templates/RowVisual.d.ts +20 -0
- package/lib/typescript/src/web/templates/SectionHeaderRowRenderer.d.ts +15 -0
- package/lib/typescript/src/web/templates/SystemRowRenderer.d.ts +16 -0
- package/lib/typescript/src/web/templates/WalletGroupRowRenderer.d.ts +20 -0
- package/package.json +3 -3
- package/src/models.ts +281 -19
- package/src/validation.ts +501 -46
- package/src/web/NativeListWebEngine.ts +361 -1932
- package/src/web/templates/ActionRowRenderer.ts +123 -0
- package/src/web/templates/ActivityRowRenderer.ts +159 -0
- package/src/web/templates/DataRowRenderer.ts +212 -0
- package/src/web/templates/IdentityRowRenderer.ts +527 -0
- package/src/web/templates/MarketRowRenderer.ts +467 -0
- package/src/web/templates/MediaTileRowRenderer.ts +182 -0
- package/src/web/templates/MessageRowRenderer.ts +306 -0
- package/src/web/templates/MetricCardRowRenderer.ts +337 -0
- package/src/web/templates/RailRowRenderer.ts +136 -0
- package/src/web/templates/RowContainerStyle.ts +131 -0
- package/src/web/templates/RowElements.ts +160 -0
- package/src/web/templates/RowRendererRegistry.ts +111 -0
- package/src/web/templates/RowText.ts +181 -0
- package/src/web/templates/RowVisual.ts +115 -0
- package/src/web/templates/SectionHeaderRowRenderer.ts +243 -0
- package/src/web/templates/SystemRowRenderer.ts +282 -0
- package/src/web/templates/WalletGroupRowRenderer.ts +131 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListRowView.kt +0 -4538
- package/ios/NativeListCell.swift +0 -4300
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
package com.margelo.nitro.nativelist
|
|
2
|
+
|
|
3
|
+
import android.animation.Animator
|
|
4
|
+
import android.animation.AnimatorListenerAdapter
|
|
5
|
+
import android.animation.TimeInterpolator
|
|
6
|
+
import android.animation.ValueAnimator
|
|
7
|
+
import android.graphics.drawable.GradientDrawable
|
|
8
|
+
import android.view.Gravity
|
|
9
|
+
import android.view.View
|
|
10
|
+
import android.widget.FrameLayout
|
|
11
|
+
import android.widget.LinearLayout
|
|
12
|
+
import android.widget.TextView
|
|
13
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
14
|
+
import org.json.JSONObject
|
|
15
|
+
|
|
16
|
+
/** Composite only; each keyed member owns an independent Identity binding. */
|
|
17
|
+
internal class NativeListWalletGroupRowView(context: ThemedReactContext) :
|
|
18
|
+
NativeListRendererRowView(context) {
|
|
19
|
+
private val membersColumn = LinearLayout(context).apply { orientation = VERTICAL }
|
|
20
|
+
private val memberViews = linkedMapOf<String, NativeListIdentityRowView>()
|
|
21
|
+
private var members = emptyList<NativeListItem>()
|
|
22
|
+
private val compactContainer =
|
|
23
|
+
FrameLayout(context).apply {
|
|
24
|
+
visibility = GONE
|
|
25
|
+
importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
|
|
26
|
+
}
|
|
27
|
+
private var compactParent: NativeListIdentityRowView? = null
|
|
28
|
+
private val dragBadge = TextView(context)
|
|
29
|
+
private var compact = false
|
|
30
|
+
private var expandedHeight = 0
|
|
31
|
+
private var animatedHeight: Int? = null
|
|
32
|
+
private var expandAnimator: ValueAnimator? = null
|
|
33
|
+
private var currentTheme: JSONObject? = null
|
|
34
|
+
private var currentLayout = "linear"
|
|
35
|
+
override val defaultCornerRadius = 12
|
|
36
|
+
override val pressChangesBackground = false
|
|
37
|
+
private var containerStyle = JSONObject()
|
|
38
|
+
private var compactHeight = 0
|
|
39
|
+
override val showsSelection = false
|
|
40
|
+
|
|
41
|
+
override fun usesSourceScale(item: NativeListItem, provided: Boolean) =
|
|
42
|
+
item.usesSelectorSourceScale || provided
|
|
43
|
+
|
|
44
|
+
override fun unselectedBackground(
|
|
45
|
+
item: NativeListItem,
|
|
46
|
+
theme: JSONObject?,
|
|
47
|
+
layout: String,
|
|
48
|
+
itemIndex: Int?,
|
|
49
|
+
) = parseNativeListColor(theme?.optString("subduedBackground", "#F9F9F9") ?: "#F9F9F9")
|
|
50
|
+
|
|
51
|
+
override fun resolvedMeasureHeight(explicit: Int?): Int? =
|
|
52
|
+
if (compact) compactHeight else animatedHeight ?: explicit ?: expandedHeight
|
|
53
|
+
|
|
54
|
+
override fun accessibilityText(item: NativeListItem) =
|
|
55
|
+
item.json.optString(
|
|
56
|
+
"accessibilityLabel",
|
|
57
|
+
item.json.optJSONObject("parent")?.optString("title") ?: "",
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
private fun memberItems(item: NativeListItem): List<NativeListItem> {
|
|
61
|
+
val children = item.json.getJSONArray("children")
|
|
62
|
+
return listOf(NativeListItem.parse(item.json.getJSONObject("parent"))) +
|
|
63
|
+
(0 until children.length()).map { NativeListItem.parse(children.getJSONObject(it)) }
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private fun defaultMemberHeight(item: NativeListItem) =
|
|
67
|
+
item.json.optInt("height", if ((item.json.optJSONArray("badges")?.length() ?: 0) > 0) 92 else 68)
|
|
68
|
+
|
|
69
|
+
private fun memberHeight(item: NativeListItem) =
|
|
70
|
+
item.styledHeight?.let(::stylePx) ?: dp(defaultMemberHeight(item))
|
|
71
|
+
|
|
72
|
+
init {
|
|
73
|
+
orientation = VERTICAL
|
|
74
|
+
addView(membersColumn, LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT))
|
|
75
|
+
addView(compactContainer, LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT))
|
|
76
|
+
dragBadge.gravity = Gravity.CENTER
|
|
77
|
+
dragBadge.typeface = NativeListFonts.semibold(context)
|
|
78
|
+
compactContainer.addView(dragBadge)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
override fun bindContent(
|
|
82
|
+
item: NativeListItem,
|
|
83
|
+
theme: JSONObject?,
|
|
84
|
+
layout: String,
|
|
85
|
+
checkboxState: (NativeListItem, NativeSelectionTarget?, String) -> String,
|
|
86
|
+
) {
|
|
87
|
+
currentTheme = theme
|
|
88
|
+
currentLayout = layout
|
|
89
|
+
members = memberItems(item)
|
|
90
|
+
val keys = members.map { it.key }.toSet()
|
|
91
|
+
memberViews.keys
|
|
92
|
+
.toList()
|
|
93
|
+
.filter { it !in keys }
|
|
94
|
+
.forEach { key ->
|
|
95
|
+
memberViews.remove(key)?.let {
|
|
96
|
+
it.dispose()
|
|
97
|
+
membersColumn.removeView(it)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
val style = item.json.optJSONObject("style")
|
|
101
|
+
containerStyle = style?.optJSONObject("container") ?: JSONObject()
|
|
102
|
+
val inset = if (members.first().json.has("height")) dp(1) else 0
|
|
103
|
+
val horizontal =
|
|
104
|
+
style
|
|
105
|
+
?.takeIf { it.has("horizontalPadding") }
|
|
106
|
+
?.let { stylePx(it.optDouble("horizontalPadding")) } ?: inset
|
|
107
|
+
val styledVertical =
|
|
108
|
+
style?.takeIf { it.has("verticalPadding") }?.let { stylePx(it.optDouble("verticalPadding")) }
|
|
109
|
+
val vertical = styledVertical ?: inset
|
|
110
|
+
membersColumn.setPadding(horizontal, vertical, horizontal, vertical)
|
|
111
|
+
setPadding(0, 0, 0, 0)
|
|
112
|
+
gravity =
|
|
113
|
+
Gravity.FILL_HORIZONTAL or
|
|
114
|
+
when (style?.optJSONObject("container")?.optString("contentVerticalAlignment")) {
|
|
115
|
+
"bottom" -> Gravity.BOTTOM
|
|
116
|
+
"center" -> Gravity.CENTER_VERTICAL
|
|
117
|
+
else -> Gravity.TOP
|
|
118
|
+
}
|
|
119
|
+
expandedHeight =
|
|
120
|
+
item.styledHeight?.let(::stylePx)
|
|
121
|
+
?: modelHeight(item, layout)
|
|
122
|
+
?: if (styledVertical == null && members.none { it.styledHeight != null }) {
|
|
123
|
+
// Legacy default: one rounding pass over the whole unstyled group; the
|
|
124
|
+
// row size modifier can only raise the minimum.
|
|
125
|
+
val base =
|
|
126
|
+
members.sumOf(::defaultMemberHeight) + (members.size - 1) * 12 + if (inset > 0) 2 else 0
|
|
127
|
+
val sizeDelta =
|
|
128
|
+
when (item.json.optString("size")) {
|
|
129
|
+
"small" -> -8
|
|
130
|
+
"large" -> 12
|
|
131
|
+
else -> 0
|
|
132
|
+
}
|
|
133
|
+
maxOf(dp(base), dp((base + sizeDelta).coerceAtLeast(0)))
|
|
134
|
+
} else members.sumOf(::memberHeight) + dp((members.size - 1) * 12) + vertical * 2
|
|
135
|
+
members.forEachIndexed { index, member ->
|
|
136
|
+
val view =
|
|
137
|
+
memberViews.getOrPut(member.key) {
|
|
138
|
+
NativeListIdentityRowView(reactContext).also { view ->
|
|
139
|
+
// Legacy: members own their disabled state; the group never gates them.
|
|
140
|
+
view.onRowPress = { source, origin -> onRowPress?.invoke(source, origin) }
|
|
141
|
+
view.onAction = { source, key, target, origin ->
|
|
142
|
+
onAction?.invoke(source, key, target, origin)
|
|
143
|
+
}
|
|
144
|
+
view.onBindingInvalidated = { source, epoch ->
|
|
145
|
+
onBindingInvalidated?.invoke(source, epoch)
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
view.listStyle = listStyle
|
|
150
|
+
view.bind(
|
|
151
|
+
member,
|
|
152
|
+
theme,
|
|
153
|
+
layout,
|
|
154
|
+
"vertical",
|
|
155
|
+
null,
|
|
156
|
+
member.json.optBoolean("selected"),
|
|
157
|
+
checkboxState,
|
|
158
|
+
sourceScale,
|
|
159
|
+
)
|
|
160
|
+
if (membersColumn.indexOfChild(view) != index) {
|
|
161
|
+
membersColumn.removeView(view)
|
|
162
|
+
membersColumn.addView(view, index)
|
|
163
|
+
}
|
|
164
|
+
view.layoutParams =
|
|
165
|
+
LayoutParams(LayoutParams.MATCH_PARENT, memberHeight(member)).apply {
|
|
166
|
+
if (index > 0) topMargin = dp(12)
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
if (compactParent == null) {
|
|
170
|
+
compactParent =
|
|
171
|
+
NativeListIdentityRowView(reactContext).also {
|
|
172
|
+
compactContainer.addView(
|
|
173
|
+
it,
|
|
174
|
+
0,
|
|
175
|
+
FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT),
|
|
176
|
+
)
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
compactParent!!.listStyle = listStyle
|
|
180
|
+
val parent = members.first()
|
|
181
|
+
compactParent!!.bind(
|
|
182
|
+
parent,
|
|
183
|
+
theme,
|
|
184
|
+
layout,
|
|
185
|
+
"vertical",
|
|
186
|
+
null,
|
|
187
|
+
parent.json.optBoolean("selected"),
|
|
188
|
+
checkboxState,
|
|
189
|
+
sourceScale,
|
|
190
|
+
)
|
|
191
|
+
// Legacy compact drag: the parent keeps its own height (92 with badges) plus
|
|
192
|
+
// the group inset, never less than the 68dp allocation.
|
|
193
|
+
compactHeight = maxOf(dp(68), memberHeight(parent) + vertical * 2)
|
|
194
|
+
compactContainer.setPadding(horizontal, vertical, horizontal, vertical)
|
|
195
|
+
compactContainer.layoutParams.height = compactHeight
|
|
196
|
+
val count = members.drop(1).count { it.json.optBoolean("draggable", true) }
|
|
197
|
+
dragBadge.text = "+$count"
|
|
198
|
+
dragBadge.visibility = if (count == 0) GONE else VISIBLE
|
|
199
|
+
dragBadge.textSize = if (sourceScale) 12f else NativeListScale.font(resources, 12f)
|
|
200
|
+
dragBadge.setPadding(dp(6), 0, dp(6), 0)
|
|
201
|
+
dragBadge.minWidth = dp(24)
|
|
202
|
+
dragBadge.setTextColor(
|
|
203
|
+
parseNativeListColor(theme?.optString("inverseText", "#FCFCFC") ?: "#FCFCFC")
|
|
204
|
+
)
|
|
205
|
+
dragBadge.background =
|
|
206
|
+
GradientDrawable().apply {
|
|
207
|
+
setColor(
|
|
208
|
+
parseNativeListColor(theme?.optString("inverseBackground", "#000000DF") ?: "#000000DF")
|
|
209
|
+
)
|
|
210
|
+
setStroke(
|
|
211
|
+
dp(1),
|
|
212
|
+
parseNativeListColor(theme?.optString("rowBackground", "#FFFFFF") ?: "#FFFFFF"),
|
|
213
|
+
)
|
|
214
|
+
cornerRadius = dp(12).toFloat()
|
|
215
|
+
}
|
|
216
|
+
dragBadge.layoutParams =
|
|
217
|
+
FrameLayout.LayoutParams(LayoutParams.WRAP_CONTENT, dp(24), Gravity.END or Gravity.BOTTOM)
|
|
218
|
+
.apply {
|
|
219
|
+
// Legacy: the badge is inset 4dp from the group's own edges.
|
|
220
|
+
rightMargin = dp(4) - horizontal
|
|
221
|
+
bottomMargin = dp(4) - vertical
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
override fun bindSelectionContent(
|
|
226
|
+
item: NativeListItem,
|
|
227
|
+
checkboxState: (NativeListItem, NativeSelectionTarget?, String) -> String,
|
|
228
|
+
) {
|
|
229
|
+
members = memberItems(item)
|
|
230
|
+
members.forEach { member ->
|
|
231
|
+
memberViews[member.key]?.bindSelection(
|
|
232
|
+
member,
|
|
233
|
+
currentTheme,
|
|
234
|
+
currentLayout,
|
|
235
|
+
null,
|
|
236
|
+
member.json.optBoolean("selected"),
|
|
237
|
+
checkboxState,
|
|
238
|
+
)
|
|
239
|
+
}
|
|
240
|
+
members.firstOrNull()?.let {
|
|
241
|
+
compactParent?.bindSelection(
|
|
242
|
+
it,
|
|
243
|
+
currentTheme,
|
|
244
|
+
currentLayout,
|
|
245
|
+
null,
|
|
246
|
+
it.json.optBoolean("selected"),
|
|
247
|
+
checkboxState,
|
|
248
|
+
)
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
override fun canStartWalletGroupReorder(localY: Float): Boolean {
|
|
253
|
+
val y = localY - membersColumn.top
|
|
254
|
+
members.forEach { member ->
|
|
255
|
+
val view = memberViews[member.key] ?: return@forEach
|
|
256
|
+
if (y >= view.top && y < view.bottom)
|
|
257
|
+
// Legacy: only `draggable: false` excludes a member from starting a group drag.
|
|
258
|
+
return member.json.optBoolean("draggable", true)
|
|
259
|
+
}
|
|
260
|
+
return true
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
private var expansionCompletion: (() -> Unit)? = null
|
|
264
|
+
|
|
265
|
+
// Legacy group chrome: subdued fill with the separator border drawn beneath the
|
|
266
|
+
// members (not as a foreground); row-level backgroundColor does not apply.
|
|
267
|
+
override fun appearance() {
|
|
268
|
+
super.appearance()
|
|
269
|
+
val theme = currentTheme
|
|
270
|
+
fun parse(value: String, fallback: String) =
|
|
271
|
+
runCatching { parseNativeListColor(value) }.getOrElse { parseNativeListColor(fallback) }
|
|
272
|
+
val fill =
|
|
273
|
+
if (containerStyle.has("backgroundColor"))
|
|
274
|
+
parse(containerStyle.optString("backgroundColor"), "#F9F9F9")
|
|
275
|
+
else parse(theme?.optString("subduedBackground", "#F9F9F9") ?: "#F9F9F9", "#F9F9F9")
|
|
276
|
+
val stroke =
|
|
277
|
+
if (containerStyle.has("borderColor")) parse(containerStyle.optString("borderColor"), "#0000001F")
|
|
278
|
+
else parse(theme?.optString("separator", "#0000001F") ?: "#0000001F", "#0000001F")
|
|
279
|
+
background =
|
|
280
|
+
GradientDrawable().apply {
|
|
281
|
+
setColor(fill)
|
|
282
|
+
cornerRadius =
|
|
283
|
+
if (containerStyle.has("cornerRadius")) stylePx(containerStyle.optDouble("cornerRadius")).toFloat()
|
|
284
|
+
else dp(12).toFloat()
|
|
285
|
+
setStroke(
|
|
286
|
+
if (containerStyle.has("borderWidth")) stylePx(containerStyle.optDouble("borderWidth")) else dp(1),
|
|
287
|
+
stroke,
|
|
288
|
+
)
|
|
289
|
+
}
|
|
290
|
+
foreground = null
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
private fun showExpandedMembers(restAlpha: Float) {
|
|
294
|
+
membersColumn.visibility = VISIBLE
|
|
295
|
+
membersColumn.alpha = 1f
|
|
296
|
+
for (index in 0 until membersColumn.childCount) {
|
|
297
|
+
membersColumn.getChildAt(index).apply {
|
|
298
|
+
visibility = VISIBLE
|
|
299
|
+
alpha = if (index == 0) 1f else restAlpha
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
// Cancelling still settles the expanded state and runs the pending completion,
|
|
305
|
+
// so the container's post-drop relayout is never lost.
|
|
306
|
+
private fun cancelExpansion() {
|
|
307
|
+
val completion = expansionCompletion
|
|
308
|
+
expansionCompletion = null
|
|
309
|
+
val animator = expandAnimator
|
|
310
|
+
expandAnimator = null
|
|
311
|
+
animatedHeight = null
|
|
312
|
+
if (animator != null) {
|
|
313
|
+
animator.removeAllListeners()
|
|
314
|
+
animator.cancel()
|
|
315
|
+
showExpandedMembers(1f)
|
|
316
|
+
requestLayout()
|
|
317
|
+
}
|
|
318
|
+
completion?.invoke()
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
override fun setReorderActive(active: Boolean) {
|
|
322
|
+
if (compact == active && expandAnimator == null) return
|
|
323
|
+
cancelExpansion()
|
|
324
|
+
compact = active
|
|
325
|
+
if (active) {
|
|
326
|
+
membersColumn.visibility = GONE
|
|
327
|
+
} else {
|
|
328
|
+
showExpandedMembers(1f)
|
|
329
|
+
}
|
|
330
|
+
compactContainer.visibility = if (active) VISIBLE else GONE
|
|
331
|
+
compactContainer.alpha = 1f
|
|
332
|
+
compactParent?.setReorderActive(active)
|
|
333
|
+
appearance()
|
|
334
|
+
requestLayout()
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
override fun finishWalletGroupReorder(
|
|
338
|
+
durationMs: Long,
|
|
339
|
+
interpolator: TimeInterpolator,
|
|
340
|
+
completion: (() -> Unit)?,
|
|
341
|
+
) {
|
|
342
|
+
cancelExpansion()
|
|
343
|
+
val startHeight = height.coerceAtLeast(dp(68))
|
|
344
|
+
compact = false
|
|
345
|
+
compactParent?.setReorderActive(false)
|
|
346
|
+
compactContainer.visibility = GONE
|
|
347
|
+
compactContainer.alpha = 1f
|
|
348
|
+
// Legacy: the first member stays opaque while the remaining members fade in.
|
|
349
|
+
showExpandedMembers(0f)
|
|
350
|
+
appearance()
|
|
351
|
+
if (expandedHeight <= startHeight) {
|
|
352
|
+
showExpandedMembers(1f)
|
|
353
|
+
requestLayout()
|
|
354
|
+
completion?.invoke()
|
|
355
|
+
return
|
|
356
|
+
}
|
|
357
|
+
animatedHeight = startHeight
|
|
358
|
+
requestLayout()
|
|
359
|
+
expansionCompletion = completion
|
|
360
|
+
expandAnimator =
|
|
361
|
+
ValueAnimator.ofInt(startHeight, expandedHeight).apply {
|
|
362
|
+
duration = durationMs
|
|
363
|
+
this.interpolator = interpolator
|
|
364
|
+
addUpdateListener {
|
|
365
|
+
animatedHeight = it.animatedValue as Int
|
|
366
|
+
val fraction = it.animatedFraction
|
|
367
|
+
for (index in 1 until membersColumn.childCount) membersColumn.getChildAt(index).alpha = fraction
|
|
368
|
+
requestLayout()
|
|
369
|
+
}
|
|
370
|
+
addListener(
|
|
371
|
+
object : AnimatorListenerAdapter() {
|
|
372
|
+
override fun onAnimationEnd(animation: Animator) {
|
|
373
|
+
if (expandAnimator !== animation) return
|
|
374
|
+
expandAnimator = null
|
|
375
|
+
animatedHeight = null
|
|
376
|
+
showExpandedMembers(1f)
|
|
377
|
+
requestLayout()
|
|
378
|
+
val pending = expansionCompletion
|
|
379
|
+
expansionCompletion = null
|
|
380
|
+
pending?.invoke()
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
)
|
|
384
|
+
start()
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
override fun recycleContent() {
|
|
389
|
+
cancelExpansion()
|
|
390
|
+
memberViews.values.forEach { it.dispose() }
|
|
391
|
+
memberViews.clear()
|
|
392
|
+
membersColumn.removeAllViews()
|
|
393
|
+
membersColumn.alpha = 1f
|
|
394
|
+
membersColumn.visibility = VISIBLE
|
|
395
|
+
members = emptyList()
|
|
396
|
+
compactParent?.dispose()
|
|
397
|
+
compactParent?.let(compactContainer::removeView)
|
|
398
|
+
compactParent = null
|
|
399
|
+
compactContainer.visibility = GONE
|
|
400
|
+
compactContainer.alpha = 1f
|
|
401
|
+
compact = false
|
|
402
|
+
expandedHeight = 0
|
|
403
|
+
currentTheme = null
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
override fun disposeContent() {}
|
|
407
|
+
}
|
package/android/src/test/java/com/margelo/nitro/nativelist/NativeListSelectorBackgroundColorTest.kt
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
package com.margelo.nitro.nativelist
|
|
2
|
+
|
|
3
|
+
import org.junit.Assert.assertEquals
|
|
4
|
+
import org.junit.Assert.assertNull
|
|
5
|
+
import org.junit.Test
|
|
6
|
+
|
|
7
|
+
class NativeListSelectorBackgroundColorTest {
|
|
8
|
+
@Test
|
|
9
|
+
fun walletGroupUsesOnlyTheContainerStyleColor() {
|
|
10
|
+
assertNull(
|
|
11
|
+
resolveNativeListSelectorBackgroundColor(
|
|
12
|
+
rowType = "walletGroup",
|
|
13
|
+
styleBackgroundColor = null,
|
|
14
|
+
rowBackgroundColor = "#112233",
|
|
15
|
+
),
|
|
16
|
+
)
|
|
17
|
+
assertEquals(
|
|
18
|
+
"#445566",
|
|
19
|
+
resolveNativeListSelectorBackgroundColor(
|
|
20
|
+
rowType = "walletGroup",
|
|
21
|
+
styleBackgroundColor = "#445566",
|
|
22
|
+
rowBackgroundColor = "#112233",
|
|
23
|
+
),
|
|
24
|
+
)
|
|
25
|
+
assertEquals(
|
|
26
|
+
"#112233",
|
|
27
|
+
resolveNativeListSelectorBackgroundColor(
|
|
28
|
+
rowType = "identity",
|
|
29
|
+
styleBackgroundColor = null,
|
|
30
|
+
rowBackgroundColor = "#112233",
|
|
31
|
+
),
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
}
|