@onekeyfe/react-native-native-list 3.0.113 → 3.0.114
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 +3 -57
- package/android/src/main/java/com/onekey/nativelist/NativeListAdapter.kt +1 -17
- package/android/src/main/java/com/onekey/nativelist/NativeListRowView.kt +34 -545
- package/android/src/main/java/com/onekey/nativelist/NativeListView.kt +2 -26
- package/ios/NativeListCell.swift +20 -504
- package/ios/NativeListDesignAssets.swift +0 -8
- package/ios/RNCNativeListView.swift +7 -85
- package/lib/module/validation.js +1 -129
- package/lib/module/web/NativeListWebEngine.js +5 -357
- package/lib/typescript/src/models.d.ts +2 -82
- package/lib/typescript/src/web/NativeListWebEngine.d.ts +1 -26
- package/package.json +2 -2
- package/src/models.ts +3 -121
- package/src/validation.ts +0 -206
- package/src/web/NativeListWebEngine.ts +4 -578
- package/ios/Resources/NativeListIcons.xcassets/onekey_badge_verified_solid.imageset/Contents.json +0 -1
- package/ios/Resources/NativeListIcons.xcassets/onekey_badge_verified_solid.imageset/icon.svg +0 -1
|
@@ -6,18 +6,12 @@ import android.animation.TimeInterpolator
|
|
|
6
6
|
import android.animation.ValueAnimator
|
|
7
7
|
import android.graphics.Color
|
|
8
8
|
import android.graphics.Canvas
|
|
9
|
-
import android.graphics.LinearGradient
|
|
10
|
-
import android.graphics.Matrix
|
|
11
9
|
import android.graphics.Outline
|
|
12
10
|
import android.graphics.Paint
|
|
13
11
|
import android.graphics.Path
|
|
14
|
-
import android.graphics.RectF
|
|
15
|
-
import android.graphics.Shader
|
|
16
12
|
import android.graphics.Typeface
|
|
17
13
|
import android.graphics.drawable.Drawable
|
|
18
14
|
import android.graphics.drawable.GradientDrawable
|
|
19
|
-
import android.os.Handler
|
|
20
|
-
import android.os.Looper
|
|
21
15
|
import android.text.Spannable
|
|
22
16
|
import android.text.SpannableStringBuilder
|
|
23
17
|
import android.text.TextUtils
|
|
@@ -30,7 +24,6 @@ import android.view.MotionEvent
|
|
|
30
24
|
import android.view.View
|
|
31
25
|
import android.view.ViewGroup
|
|
32
26
|
import android.view.ViewOutlineProvider
|
|
33
|
-
import android.view.animation.LinearInterpolator
|
|
34
27
|
import android.widget.FrameLayout
|
|
35
28
|
import android.widget.LinearLayout
|
|
36
29
|
import android.widget.ProgressBar
|
|
@@ -49,69 +42,6 @@ import org.json.JSONArray
|
|
|
49
42
|
import org.json.JSONObject
|
|
50
43
|
import kotlin.math.roundToInt
|
|
51
44
|
|
|
52
|
-
// Market/TokenListSkeleton: source geometry and the native Skeleton's 3s shimmer.
|
|
53
|
-
private class NativeListMarketSkeleton(context: android.content.Context, backgroundColor: Int) : View(context) {
|
|
54
|
-
private val marks = Array(5) { RectF() }
|
|
55
|
-
private val paint = Paint(Paint.ANTI_ALIAS_FLAG)
|
|
56
|
-
private val matrix = Matrix()
|
|
57
|
-
private val shaders = arrayOfNulls<LinearGradient>(5)
|
|
58
|
-
private val dark = Color.red(backgroundColor) * 0.299 + Color.green(backgroundColor) * 0.587 + Color.blue(backgroundColor) * 0.114 < 128
|
|
59
|
-
private val colors = intArrayOf(
|
|
60
|
-
Color.parseColor(if (dark) "#111111" else "#FAFAFA"),
|
|
61
|
-
Color.parseColor(if (dark) "#333333" else "#CDCDCD"),
|
|
62
|
-
Color.parseColor(if (dark) "#111111" else "#FAFAFA"),
|
|
63
|
-
)
|
|
64
|
-
private var phase = 0f
|
|
65
|
-
private val animator = ValueAnimator.ofFloat(0f, 1f).apply {
|
|
66
|
-
duration = 3000
|
|
67
|
-
repeatCount = ValueAnimator.INFINITE
|
|
68
|
-
interpolator = LinearInterpolator()
|
|
69
|
-
addUpdateListener { phase = it.animatedValue as Float; invalidate() }
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
private fun dp(value: Float) = NativeListScale.dp(resources, value)
|
|
73
|
-
|
|
74
|
-
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
|
|
75
|
-
super.onSizeChanged(w, h, oldw, oldh)
|
|
76
|
-
marks[0].set(0f, 0f, dp(32f), dp(32f))
|
|
77
|
-
marks[1].set(dp(44f), 0f, dp(124f), dp(16f))
|
|
78
|
-
marks[2].set(dp(44f), dp(20f), dp(104f), dp(32f))
|
|
79
|
-
marks[3].set(w - dp(168f), dp(7f), w - dp(88f), dp(25f))
|
|
80
|
-
marks[4].set(w - dp(80f), dp(7f), w.toFloat(), dp(25f))
|
|
81
|
-
marks.forEachIndexed { index, mark ->
|
|
82
|
-
shaders[index] = LinearGradient(0f, 0f, mark.width(), 0f, colors, floatArrayOf(0f, 0.5f, 1f), Shader.TileMode.CLAMP)
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
override fun onDraw(canvas: Canvas) {
|
|
87
|
-
super.onDraw(canvas)
|
|
88
|
-
marks.forEachIndexed { index, mark ->
|
|
89
|
-
matrix.setTranslate(mark.left - mark.width() + phase * mark.width() * 3f, 0f)
|
|
90
|
-
shaders[index]?.setLocalMatrix(matrix)
|
|
91
|
-
paint.shader = shaders[index]
|
|
92
|
-
val radius = dp(if (index == 0) 16f else 8f)
|
|
93
|
-
canvas.drawRoundRect(mark, radius, radius, paint)
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
override fun onAttachedToWindow() {
|
|
98
|
-
super.onAttachedToWindow()
|
|
99
|
-
if (windowVisibility == VISIBLE) animator.start()
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
override fun onDetachedFromWindow() {
|
|
103
|
-
animator.cancel()
|
|
104
|
-
super.onDetachedFromWindow()
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
override fun onWindowVisibilityChanged(visibility: Int) {
|
|
108
|
-
super.onWindowVisibilityChanged(visibility)
|
|
109
|
-
if (visibility == VISIBLE && isAttachedToWindow) {
|
|
110
|
-
if (!animator.isStarted) animator.start()
|
|
111
|
-
} else animator.cancel()
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
45
|
internal data class NativeListActionOrigin(
|
|
116
46
|
val sourceView: View,
|
|
117
47
|
val ownerRowView: NativeListRowView,
|
|
@@ -217,25 +147,26 @@ private class PackedTitleLineLayout(context: android.content.Context) : LinearLa
|
|
|
217
147
|
}
|
|
218
148
|
|
|
219
149
|
val title = getChildAt(0)
|
|
150
|
+
val badge = getChildAt(1)
|
|
220
151
|
val widthMode = MeasureSpec.getMode(widthMeasureSpec)
|
|
221
152
|
val widthSize = MeasureSpec.getSize(widthMeasureSpec)
|
|
222
|
-
|
|
223
|
-
for (index in 1 until childCount) {
|
|
224
|
-
val child = getChildAt(index)
|
|
225
|
-
if (child.visibility == GONE) continue
|
|
153
|
+
if (badge.visibility != GONE) {
|
|
226
154
|
measureChildWithMargins(
|
|
227
|
-
|
|
155
|
+
badge,
|
|
228
156
|
widthMeasureSpec,
|
|
229
|
-
paddingLeft + paddingRight
|
|
157
|
+
paddingLeft + paddingRight,
|
|
230
158
|
heightMeasureSpec,
|
|
231
159
|
paddingTop + paddingBottom,
|
|
232
160
|
)
|
|
233
|
-
|
|
234
|
-
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
val badgeMargins = badge.layoutParams as MarginLayoutParams
|
|
164
|
+
val badgeWidth = if (badge.visibility == GONE) 0 else {
|
|
165
|
+
badge.measuredWidth + badgeMargins.leftMargin + badgeMargins.rightMargin
|
|
235
166
|
}
|
|
236
167
|
val titleMargins = title.layoutParams as MarginLayoutParams
|
|
237
168
|
if (widthMode != MeasureSpec.UNSPECIFIED) {
|
|
238
|
-
(title as TextView).maxWidth = (widthSize - paddingLeft - paddingRight -
|
|
169
|
+
(title as TextView).maxWidth = (widthSize - paddingLeft - paddingRight - badgeWidth -
|
|
239
170
|
titleMargins.leftMargin - titleMargins.rightMargin).coerceAtLeast(0)
|
|
240
171
|
}
|
|
241
172
|
(title.layoutParams as LayoutParams).apply {
|
|
@@ -431,10 +362,6 @@ internal class NativeListRowView(
|
|
|
431
362
|
private val status = TextView(context)
|
|
432
363
|
private val metricSubtitle = TextView(context)
|
|
433
364
|
private val badgeLine = TextView(context)
|
|
434
|
-
private val marketBadgeViews = List(3) { LinearLayout(context) }
|
|
435
|
-
private val marketBadgeLabels = List(3) { TextView(context) }
|
|
436
|
-
private val marketBadgeImages = List(3) { OneKeyImageReusableView(reactContext) }
|
|
437
|
-
private val marketBadgeGlyphs = List(3) { OneKeyIconView(context) }
|
|
438
365
|
private val activityContentRow = LinearLayout(context)
|
|
439
366
|
private val actionLine = LinearLayout(context)
|
|
440
367
|
private val actionViews = List(3) { TextView(context) }
|
|
@@ -475,11 +402,6 @@ internal class NativeListRowView(
|
|
|
475
402
|
private var pressedRowBackground: Drawable? = null
|
|
476
403
|
// OneKey patch: preserve a held row independently from RecyclerView snapshot rebinding.
|
|
477
404
|
private var touchPressed = false
|
|
478
|
-
private val marketLongPressHandler = Handler(Looper.getMainLooper())
|
|
479
|
-
private var marketLongPressRunnable: Runnable? = null
|
|
480
|
-
private var marketTouchStartX = 0f
|
|
481
|
-
private var marketTouchStartY = 0f
|
|
482
|
-
private var marketLongPressFired = false
|
|
483
405
|
private var reorderActive = false
|
|
484
406
|
private var checkboxCheckedColor = Color.rgb(32, 32, 32)
|
|
485
407
|
private var checkboxUncheckedColor = Color.rgb(252, 252, 252)
|
|
@@ -544,23 +466,6 @@ internal class NativeListRowView(
|
|
|
544
466
|
titleLine.gravity = Gravity.CENTER_VERTICAL
|
|
545
467
|
titleLine.addView(title, LayoutParams(0, LayoutParams.WRAP_CONTENT, 1f))
|
|
546
468
|
titleLine.addView(badgeLine, wrap())
|
|
547
|
-
marketBadgeViews.forEachIndexed { index, badge ->
|
|
548
|
-
badge.orientation = HORIZONTAL
|
|
549
|
-
badge.gravity = Gravity.CENTER_VERTICAL
|
|
550
|
-
badge.isClickable = true
|
|
551
|
-
marketBadgeGlyphs[index].visibility = GONE
|
|
552
|
-
marketBadgeImages[index].visibility = GONE
|
|
553
|
-
marketBadgeLabels[index].apply {
|
|
554
|
-
includeFontPadding = false
|
|
555
|
-
maxLines = 1
|
|
556
|
-
ellipsize = TextUtils.TruncateAt.END
|
|
557
|
-
textSize = sp(11f)
|
|
558
|
-
typeface = NativeListFonts.medium(context)
|
|
559
|
-
}
|
|
560
|
-
badge.addView(marketBadgeGlyphs[index], LayoutParams(dp(16), dp(16)))
|
|
561
|
-
badge.addView(marketBadgeImages[index], LayoutParams(dp(14), dp(14)))
|
|
562
|
-
badge.addView(marketBadgeLabels[index], wrap())
|
|
563
|
-
}
|
|
564
469
|
mainColumn.addView(titleLine)
|
|
565
470
|
mainColumn.addView(subtitle)
|
|
566
471
|
mainColumn.addView(tertiary)
|
|
@@ -605,47 +510,19 @@ internal class NativeListRowView(
|
|
|
605
510
|
when (event.actionMasked) {
|
|
606
511
|
MotionEvent.ACTION_DOWN -> if (isEnabled) {
|
|
607
512
|
touchPressed = true
|
|
608
|
-
marketLongPressFired = false
|
|
609
|
-
val item = tag as? NativeListItem
|
|
610
|
-
if (item?.type == "market") {
|
|
611
|
-
marketTouchStartX = event.x
|
|
612
|
-
marketTouchStartY = event.y
|
|
613
|
-
item.json.optString("pressInActionKey").takeIf(String::isNotEmpty)?.let { actionKey ->
|
|
614
|
-
emitAction(item, actionKey, null, this, "row")
|
|
615
|
-
}
|
|
616
|
-
item.json.optString("longPressActionKey").takeIf(String::isNotEmpty)?.let { actionKey ->
|
|
617
|
-
val expectedKey = item.key
|
|
618
|
-
val runnable = Runnable {
|
|
619
|
-
val current = tag as? NativeListItem
|
|
620
|
-
if (touchPressed && current?.key == expectedKey && current.type == "market") {
|
|
621
|
-
marketLongPressRunnable = null
|
|
622
|
-
marketLongPressFired = true
|
|
623
|
-
emitAction(current, actionKey, null, this, "row")
|
|
624
|
-
}
|
|
625
|
-
}
|
|
626
|
-
marketLongPressRunnable = runnable
|
|
627
|
-
marketLongPressHandler.postDelayed(runnable, 800L)
|
|
628
|
-
}
|
|
629
|
-
}
|
|
630
513
|
if ((tag as? NativeListItem)?.type == "mediaTile") {
|
|
631
514
|
leadingFrame.alpha = 0.8f
|
|
632
515
|
} else {
|
|
633
516
|
background = pressedRowBackground
|
|
634
517
|
}
|
|
635
518
|
}
|
|
636
|
-
MotionEvent.ACTION_MOVE ->
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
if (outside || movedMarket) {
|
|
642
|
-
cancelMarketLongPress()
|
|
643
|
-
touchPressed = false
|
|
644
|
-
restoreRestingBackground()
|
|
645
|
-
}
|
|
519
|
+
MotionEvent.ACTION_MOVE -> if (
|
|
520
|
+
event.x < 0 || event.y < 0 || event.x >= width || event.y >= height
|
|
521
|
+
) {
|
|
522
|
+
touchPressed = false
|
|
523
|
+
restoreRestingBackground()
|
|
646
524
|
}
|
|
647
525
|
MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
|
|
648
|
-
cancelMarketLongPress()
|
|
649
526
|
touchPressed = false
|
|
650
527
|
restoreRestingBackground()
|
|
651
528
|
}
|
|
@@ -654,10 +531,6 @@ internal class NativeListRowView(
|
|
|
654
531
|
}
|
|
655
532
|
setOnClickListener { view ->
|
|
656
533
|
(view.tag as? NativeListItem)?.let { item ->
|
|
657
|
-
if (item.type == "market" && marketLongPressFired) {
|
|
658
|
-
marketLongPressFired = false
|
|
659
|
-
return@let
|
|
660
|
-
}
|
|
661
534
|
// OneKey patch: allow create-address accessories when whole-row press is gated.
|
|
662
535
|
if (!item.json.optBoolean("pressDisabled", false)) onRowPress?.invoke(item, actionOrigin(view, "row"))
|
|
663
536
|
}
|
|
@@ -777,15 +650,13 @@ internal class NativeListRowView(
|
|
|
777
650
|
useSourceScale: Boolean = false,
|
|
778
651
|
) {
|
|
779
652
|
val shouldRestorePressed = touchPressed && boundKey == item.key
|
|
780
|
-
cancelMarketLongPress()
|
|
781
|
-
marketLongPressFired = false
|
|
782
653
|
invalidateCurrentBinding()
|
|
783
654
|
bindingEpoch += 1
|
|
784
655
|
boundKey = item.key
|
|
785
656
|
touchPressed = shouldRestorePressed
|
|
786
657
|
currentLayout = layout
|
|
787
658
|
tag = item
|
|
788
|
-
selectorUsesSourceScale = item.
|
|
659
|
+
selectorUsesSourceScale = item.usesSelectorSourceScale || useSourceScale
|
|
789
660
|
reorderActive = false
|
|
790
661
|
leadingImages.forEach(OneKeyImageReusableView::prepareForReuse)
|
|
791
662
|
secondaryImage.prepareForReuse()
|
|
@@ -871,7 +742,6 @@ internal class NativeListRowView(
|
|
|
871
742
|
"activity" -> bindActivity(item, theme)
|
|
872
743
|
"message" -> bindMessage(item, theme)
|
|
873
744
|
"dataRow" -> bindDataRow(item, theme, checkboxState)
|
|
874
|
-
"market" -> bindMarket(item, theme)
|
|
875
745
|
"mediaTile" -> bindMediaTile(item, theme)
|
|
876
746
|
"metricCard" -> bindMetricCard(item, theme)
|
|
877
747
|
"sectionHeader" -> bindSectionHeader(item, theme, checkboxState)
|
|
@@ -906,8 +776,6 @@ internal class NativeListRowView(
|
|
|
906
776
|
}
|
|
907
777
|
|
|
908
778
|
fun recycle() {
|
|
909
|
-
cancelMarketLongPress()
|
|
910
|
-
marketLongPressFired = false
|
|
911
779
|
touchPressed = false
|
|
912
780
|
restoreRestingBackground()
|
|
913
781
|
invalidateCurrentBinding()
|
|
@@ -998,7 +866,6 @@ internal class NativeListRowView(
|
|
|
998
866
|
}
|
|
999
867
|
|
|
1000
868
|
fun dispose() {
|
|
1001
|
-
cancelMarketLongPress()
|
|
1002
869
|
invalidateCurrentBinding()
|
|
1003
870
|
restoreRestingBackground()
|
|
1004
871
|
selectorImages.forEach(OneKeyImageReusableView::dispose)
|
|
@@ -1007,7 +874,6 @@ internal class NativeListRowView(
|
|
|
1007
874
|
secondaryImage.dispose()
|
|
1008
875
|
mediaNetworkImage.dispose()
|
|
1009
876
|
metricVisualImages.forEach(OneKeyImageReusableView::dispose)
|
|
1010
|
-
marketBadgeImages.forEach(OneKeyImageReusableView::dispose)
|
|
1011
877
|
walletGroupRows.forEach(NativeListRowView::dispose)
|
|
1012
878
|
}
|
|
1013
879
|
|
|
@@ -1087,25 +953,6 @@ internal class NativeListRowView(
|
|
|
1087
953
|
selectorImages.forEach(OneKeyImageReusableView::dispose)
|
|
1088
954
|
selectorImages.clear()
|
|
1089
955
|
selectorHeight = null
|
|
1090
|
-
marketBadgeViews.forEachIndexed { index, badge ->
|
|
1091
|
-
(badge.parent as? ViewGroup)?.removeView(badge)
|
|
1092
|
-
badge.visibility = GONE
|
|
1093
|
-
badge.background = null
|
|
1094
|
-
badge.setPadding(0, 0, 0, 0)
|
|
1095
|
-
badge.setOnClickListener(null)
|
|
1096
|
-
badge.contentDescription = null
|
|
1097
|
-
marketBadgeLabels[index].apply {
|
|
1098
|
-
text = ""
|
|
1099
|
-
setTextColor(color(null, "secondaryText", "#0000009B"))
|
|
1100
|
-
}
|
|
1101
|
-
marketBadgeImages[index].prepareForReuse()
|
|
1102
|
-
marketBadgeImages[index].visibility = GONE
|
|
1103
|
-
marketBadgeGlyphs[index].apply {
|
|
1104
|
-
visibility = GONE
|
|
1105
|
-
iconName = ""
|
|
1106
|
-
tintColor = color(null, "secondaryText", "#0000009B")
|
|
1107
|
-
}
|
|
1108
|
-
}
|
|
1109
956
|
title.setOnClickListener(null)
|
|
1110
957
|
title.isClickable = false
|
|
1111
958
|
walletGroupRows.forEach { it.invalidateCurrentBinding() }
|
|
@@ -1274,21 +1121,12 @@ internal class NativeListRowView(
|
|
|
1274
1121
|
mainColumn.removeView(skeletonSecondary)
|
|
1275
1122
|
setOnClickListener { view ->
|
|
1276
1123
|
(view.tag as? NativeListItem)?.let { item ->
|
|
1277
|
-
if (item.type == "market" && marketLongPressFired) {
|
|
1278
|
-
marketLongPressFired = false
|
|
1279
|
-
return@let
|
|
1280
|
-
}
|
|
1281
1124
|
// OneKey patch: allow create-address accessories when whole-row press is gated.
|
|
1282
1125
|
if (!item.json.optBoolean("pressDisabled", false)) onRowPress?.invoke(item, actionOrigin(view, "row"))
|
|
1283
1126
|
}
|
|
1284
1127
|
}
|
|
1285
1128
|
}
|
|
1286
1129
|
|
|
1287
|
-
private fun cancelMarketLongPress() {
|
|
1288
|
-
marketLongPressRunnable?.let(marketLongPressHandler::removeCallbacks)
|
|
1289
|
-
marketLongPressRunnable = null
|
|
1290
|
-
}
|
|
1291
|
-
|
|
1292
1130
|
private fun restoreRestingBackground() {
|
|
1293
1131
|
background = if (reorderActive) pressedRowBackground else restingRowBackground
|
|
1294
1132
|
leadingFrame.alpha = 1f
|
|
@@ -1895,272 +1733,6 @@ internal class NativeListRowView(
|
|
|
1895
1733
|
addView(dataContainer, weighted())
|
|
1896
1734
|
}
|
|
1897
1735
|
|
|
1898
|
-
private fun marketTypeface(weight: String, fallback: String): Typeface = when (
|
|
1899
|
-
weight.ifEmpty { fallback }
|
|
1900
|
-
) {
|
|
1901
|
-
"regular" -> NativeListFonts.regular(context)
|
|
1902
|
-
"semibold" -> NativeListFonts.semibold(context)
|
|
1903
|
-
"bold" -> NativeListFonts.bold(context)
|
|
1904
|
-
else -> NativeListFonts.medium(context)
|
|
1905
|
-
}
|
|
1906
|
-
|
|
1907
|
-
private fun applyMarketTextStyle(
|
|
1908
|
-
view: TextView,
|
|
1909
|
-
style: JSONObject?,
|
|
1910
|
-
defaultSize: Float,
|
|
1911
|
-
defaultLineHeight: Int,
|
|
1912
|
-
defaultWeight: String,
|
|
1913
|
-
defaultColor: Int,
|
|
1914
|
-
defaultAlignment: String,
|
|
1915
|
-
) {
|
|
1916
|
-
view.includeFontPadding = false
|
|
1917
|
-
view.fontFeatureSettings = "tnum"
|
|
1918
|
-
view.textSize = sp(style?.optDouble("fontSize", defaultSize.toDouble())?.toFloat() ?: defaultSize)
|
|
1919
|
-
view.typeface = marketTypeface(style?.optString("fontWeight").orEmpty(), defaultWeight)
|
|
1920
|
-
view.setTextColor(safeColor(style?.optString("color"), defaultColor))
|
|
1921
|
-
val alignment = style?.optString("alignment", defaultAlignment) ?: defaultAlignment
|
|
1922
|
-
view.gravity = Gravity.CENTER_VERTICAL or when (alignment) {
|
|
1923
|
-
"center" -> Gravity.CENTER_HORIZONTAL
|
|
1924
|
-
"end" -> Gravity.END
|
|
1925
|
-
else -> Gravity.START
|
|
1926
|
-
}
|
|
1927
|
-
view.maxLines = style?.optInt("lines", 1)?.coerceIn(1, 2) ?: 1
|
|
1928
|
-
view.ellipsize = TextUtils.TruncateAt.END
|
|
1929
|
-
TextViewCompat.setLineHeight(
|
|
1930
|
-
view,
|
|
1931
|
-
dp(style?.optDouble("lineHeight", defaultLineHeight.toDouble())?.roundToInt() ?: defaultLineHeight),
|
|
1932
|
-
)
|
|
1933
|
-
}
|
|
1934
|
-
|
|
1935
|
-
private fun marketText(value: String, segments: JSONArray?, fontSize: Float): CharSequence {
|
|
1936
|
-
if (segments == null || segments.length() == 0) return value
|
|
1937
|
-
val result = SpannableStringBuilder()
|
|
1938
|
-
for (index in 0 until segments.length()) {
|
|
1939
|
-
val segment = segments.getJSONObject(index)
|
|
1940
|
-
val start = result.length
|
|
1941
|
-
result.append(segment.optString("text"))
|
|
1942
|
-
if (segment.optString("style") == "subscript") {
|
|
1943
|
-
result.setSpan(
|
|
1944
|
-
AbsoluteSizeSpan(sp(kotlin.math.ceil(fontSize * 0.6f)).roundToInt(), true),
|
|
1945
|
-
start,
|
|
1946
|
-
result.length,
|
|
1947
|
-
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE,
|
|
1948
|
-
)
|
|
1949
|
-
}
|
|
1950
|
-
}
|
|
1951
|
-
return result
|
|
1952
|
-
}
|
|
1953
|
-
|
|
1954
|
-
private fun bindMarket(item: NativeListItem, theme: JSONObject?) {
|
|
1955
|
-
// Network badges extend beyond the leading image's frame.
|
|
1956
|
-
clipChildren = false
|
|
1957
|
-
val variant = item.json.optString("variant")
|
|
1958
|
-
val style = item.json.optJSONObject("style")
|
|
1959
|
-
val imageStyle = style?.optJSONObject("image")
|
|
1960
|
-
val imageWidth = imageStyle?.optDouble("width", if (variant == "stock") 40.0 else 32.0)?.roundToInt()
|
|
1961
|
-
?: if (variant == "stock") 40 else 32
|
|
1962
|
-
val imageHeight = imageStyle?.optDouble("height", if (variant == "stock") 40.0 else 32.0)?.roundToInt()
|
|
1963
|
-
?: if (variant == "stock") 40 else 32
|
|
1964
|
-
val horizontalPadding = style?.optDouble("horizontalPadding", if (variant == "perp") 16.0 else 20.0)?.roundToInt()
|
|
1965
|
-
?: if (variant == "perp") 16 else 20
|
|
1966
|
-
val verticalPadding = style?.optDouble("verticalPadding", 12.0)?.roundToInt() ?: 12
|
|
1967
|
-
val leadingGap = style?.optDouble("leadingGap", if (variant == "perp") 8.0 else 14.0)?.roundToInt()
|
|
1968
|
-
?: if (variant == "perp") 8 else 14
|
|
1969
|
-
setPadding(dp(horizontalPadding), dp(verticalPadding), dp(horizontalPadding), dp(verticalPadding))
|
|
1970
|
-
|
|
1971
|
-
val leading = JSONObject(item.json.getJSONObject("leading").toString())
|
|
1972
|
-
imageStyle?.optString("shape")?.takeIf(String::isNotEmpty)?.let { leading.put("shape", it) }
|
|
1973
|
-
imageStyle?.optString("contentFit")?.takeIf(String::isNotEmpty)?.let { contentFit ->
|
|
1974
|
-
leading.optJSONObject("image")?.put("contentFit", contentFit)
|
|
1975
|
-
}
|
|
1976
|
-
val shape = imageStyle?.optString("shape", leading.optString("shape", "circle"))
|
|
1977
|
-
?: leading.optString("shape", "circle")
|
|
1978
|
-
val cornerRadius = imageStyle?.takeIf { it.has("cornerRadius") }?.optDouble("cornerRadius")?.toFloat()
|
|
1979
|
-
?: when (shape) {
|
|
1980
|
-
"square" -> 0f
|
|
1981
|
-
"rounded" -> 8f
|
|
1982
|
-
else -> minOf(imageWidth, imageHeight) / 2f
|
|
1983
|
-
}
|
|
1984
|
-
addLeading(
|
|
1985
|
-
leading,
|
|
1986
|
-
sizeDp = imageWidth,
|
|
1987
|
-
spacingDp = leadingGap,
|
|
1988
|
-
heightDp = imageHeight,
|
|
1989
|
-
cornerRadiusDp = cornerRadius,
|
|
1990
|
-
)
|
|
1991
|
-
|
|
1992
|
-
addView(mainColumn, weighted())
|
|
1993
|
-
titleLine.packsChildrenAtStart = true
|
|
1994
|
-
showText(title, item.json.optString("title"), style?.optJSONObject("title")?.optInt("lines", 1) ?: 1)
|
|
1995
|
-
applyMarketTextStyle(
|
|
1996
|
-
title,
|
|
1997
|
-
style?.optJSONObject("title"),
|
|
1998
|
-
16f,
|
|
1999
|
-
24,
|
|
2000
|
-
"medium",
|
|
2001
|
-
color(theme, "primaryText", "#202020"),
|
|
2002
|
-
"start",
|
|
2003
|
-
)
|
|
2004
|
-
val badges = item.json.optJSONArray("badges")
|
|
2005
|
-
val titleBadgeGap = style?.optDouble("titleBadgeGap", 4.0)?.roundToInt() ?: 4
|
|
2006
|
-
if (badges != null) {
|
|
2007
|
-
for (index in 0 until minOf(marketBadgeViews.size, badges.length())) {
|
|
2008
|
-
val badge = badges.getJSONObject(index)
|
|
2009
|
-
val badgeView = marketBadgeViews[index]
|
|
2010
|
-
val badgeLabel = marketBadgeLabels[index]
|
|
2011
|
-
val hasGlyph = badge.optString("iconName") == "verified"
|
|
2012
|
-
val remoteIcon = badge.optJSONObject("icon")
|
|
2013
|
-
val hasIcon = hasGlyph || remoteIcon != null
|
|
2014
|
-
val text = badge.optString("text")
|
|
2015
|
-
val toneColor = when (badge.optString("tone")) {
|
|
2016
|
-
"success" -> color(theme, "positive", "#218358")
|
|
2017
|
-
"danger" -> color(theme, "negative", "#CE2C31")
|
|
2018
|
-
"info" -> color(theme, "info", "#0D74CE")
|
|
2019
|
-
"warning" -> color(theme, "primaryText", "#202020")
|
|
2020
|
-
else -> color(theme, "secondaryText", "#646464")
|
|
2021
|
-
}
|
|
2022
|
-
val foreground = safeColor(badge.optString("textColor"), toneColor)
|
|
2023
|
-
badgeView.visibility = VISIBLE
|
|
2024
|
-
val iconOnly = hasIcon && text.isEmpty()
|
|
2025
|
-
badgeView.setPadding(dp(if (iconOnly) 0 else if (hasIcon) 2 else 5), 0, dp(if (iconOnly) 0 else 5), 0)
|
|
2026
|
-
badgeView.background = roundedFill(
|
|
2027
|
-
safeColor(
|
|
2028
|
-
badge.optString("backgroundColor"),
|
|
2029
|
-
if (hasIcon && text.isEmpty()) Color.TRANSPARENT else color(theme, "strongBackground", "#0000000F"),
|
|
2030
|
-
),
|
|
2031
|
-
4f,
|
|
2032
|
-
)
|
|
2033
|
-
badgeLabel.text = text
|
|
2034
|
-
badgeLabel.setTextColor(foreground)
|
|
2035
|
-
badgeLabel.visibility = if (text.isEmpty()) GONE else VISIBLE
|
|
2036
|
-
if (hasGlyph) {
|
|
2037
|
-
marketBadgeGlyphs[index].apply {
|
|
2038
|
-
iconName = "BadgeVerifiedSolid"
|
|
2039
|
-
tintColor = foreground
|
|
2040
|
-
visibility = VISIBLE
|
|
2041
|
-
}
|
|
2042
|
-
}
|
|
2043
|
-
remoteIcon?.let { icon ->
|
|
2044
|
-
marketBadgeImages[index].visibility = VISIBLE
|
|
2045
|
-
marketBadgeImages[index].outlineProvider = circleOutlineProvider
|
|
2046
|
-
marketBadgeImages[index].clipToOutline = true
|
|
2047
|
-
bindImage(icon, marketBadgeImages[index], item.key, 20 + index, "generic")
|
|
2048
|
-
}
|
|
2049
|
-
val actionKey = badge.optString("actionKey")
|
|
2050
|
-
badgeView.isClickable = actionKey.isNotEmpty()
|
|
2051
|
-
if (actionKey.isNotEmpty()) {
|
|
2052
|
-
badgeView.setOnClickListener {
|
|
2053
|
-
emitAction(item, actionKey, null, badgeView, "marketBadge", index)
|
|
2054
|
-
}
|
|
2055
|
-
}
|
|
2056
|
-
badgeView.contentDescription = badge.optString("accessibilityLabel", text)
|
|
2057
|
-
titleLine.addView(
|
|
2058
|
-
badgeView,
|
|
2059
|
-
LayoutParams(LayoutParams.WRAP_CONTENT, dp(18)).apply { marginStart = dp(titleBadgeGap) },
|
|
2060
|
-
)
|
|
2061
|
-
}
|
|
2062
|
-
}
|
|
2063
|
-
subtitle.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT).apply {
|
|
2064
|
-
topMargin = dp(style?.optDouble("lineGap", 0.0)?.roundToInt() ?: 0)
|
|
2065
|
-
}
|
|
2066
|
-
val subtitleText = item.json.optString("subtitle")
|
|
2067
|
-
val subtitleSegments = item.json.optJSONArray("subtitleSegments")
|
|
2068
|
-
if (subtitleText.isNotEmpty() || (subtitleSegments?.length() ?: 0) > 0) {
|
|
2069
|
-
subtitle.visibility = VISIBLE
|
|
2070
|
-
applyMarketTextStyle(
|
|
2071
|
-
subtitle,
|
|
2072
|
-
style?.optJSONObject("subtitle"),
|
|
2073
|
-
14f,
|
|
2074
|
-
20,
|
|
2075
|
-
"regular",
|
|
2076
|
-
color(theme, "secondaryText", "#646464"),
|
|
2077
|
-
"start",
|
|
2078
|
-
)
|
|
2079
|
-
subtitle.text = marketText(
|
|
2080
|
-
subtitleText,
|
|
2081
|
-
subtitleSegments,
|
|
2082
|
-
style?.optJSONObject("subtitle")?.optDouble("fontSize", 14.0)?.toFloat() ?: 14f,
|
|
2083
|
-
)
|
|
2084
|
-
}
|
|
2085
|
-
trailingColumn.orientation = HORIZONTAL
|
|
2086
|
-
trailingColumn.gravity = Gravity.END or Gravity.CENTER_VERTICAL
|
|
2087
|
-
addView(trailingColumn, wrap())
|
|
2088
|
-
bindMarketQuote(item, theme)
|
|
2089
|
-
item.json.optJSONObject("diagnostics")?.optString("imageBindActionKey")
|
|
2090
|
-
?.takeIf(String::isNotEmpty)
|
|
2091
|
-
?.takeIf { leading.optJSONObject("image") != null || leading.optJSONObject("networkImage") != null }
|
|
2092
|
-
?.let { actionKey -> onAction?.invoke(item, actionKey, null, null) }
|
|
2093
|
-
}
|
|
2094
|
-
|
|
2095
|
-
fun bindMarketQuote(item: NativeListItem, theme: JSONObject?) {
|
|
2096
|
-
if (boundKey != item.key || item.type != "market") return
|
|
2097
|
-
tag = item
|
|
2098
|
-
val style = item.json.optJSONObject("style")
|
|
2099
|
-
val priceStyle = style?.optJSONObject("price")
|
|
2100
|
-
val price = trailingViews[0]
|
|
2101
|
-
price.isClickable = false
|
|
2102
|
-
price.isLongClickable = false
|
|
2103
|
-
price.visibility = VISIBLE
|
|
2104
|
-
price.maxWidth = dp(112)
|
|
2105
|
-
applyMarketTextStyle(
|
|
2106
|
-
price,
|
|
2107
|
-
priceStyle,
|
|
2108
|
-
16f,
|
|
2109
|
-
24,
|
|
2110
|
-
"medium",
|
|
2111
|
-
color(theme, "primaryText", "#202020"),
|
|
2112
|
-
"end",
|
|
2113
|
-
)
|
|
2114
|
-
price.text = marketText(
|
|
2115
|
-
item.json.optString("price"),
|
|
2116
|
-
item.json.optJSONArray("priceSegments"),
|
|
2117
|
-
priceStyle?.optDouble("fontSize", 16.0)?.toFloat() ?: 16f,
|
|
2118
|
-
)
|
|
2119
|
-
val trailingGap = style?.optDouble("trailingGap", 8.0)?.roundToInt() ?: 8
|
|
2120
|
-
price.layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT).apply {
|
|
2121
|
-
marginEnd = dp(trailingGap)
|
|
2122
|
-
}
|
|
2123
|
-
|
|
2124
|
-
val changeData = item.json.getJSONObject("change")
|
|
2125
|
-
val changeStyle = style?.optJSONObject("change")
|
|
2126
|
-
val change = trailingViews[1]
|
|
2127
|
-
change.isClickable = false
|
|
2128
|
-
change.isLongClickable = false
|
|
2129
|
-
val toneColor = when (changeData.optString("tone")) {
|
|
2130
|
-
"positive" -> color(theme, "positive", "#218358")
|
|
2131
|
-
"negative" -> color(theme, "negative", "#CE2C31")
|
|
2132
|
-
else -> color(theme, "secondaryText", "#8D8D8D")
|
|
2133
|
-
}
|
|
2134
|
-
val textColor = safeColor(
|
|
2135
|
-
changeData.optString("textColor"),
|
|
2136
|
-
color(theme, "inverseText", "#FFFFFF"),
|
|
2137
|
-
)
|
|
2138
|
-
change.visibility = VISIBLE
|
|
2139
|
-
applyMarketTextStyle(change, changeStyle, 14f, 20, "medium", textColor, "center")
|
|
2140
|
-
change.text = marketText(
|
|
2141
|
-
changeData.optString("text"),
|
|
2142
|
-
changeData.optJSONArray("textSegments"),
|
|
2143
|
-
changeStyle?.optDouble("fontSize", 14.0)?.toFloat() ?: 14f,
|
|
2144
|
-
)
|
|
2145
|
-
change.background = roundedFill(
|
|
2146
|
-
safeColor(changeData.optString("backgroundColor"), toneColor),
|
|
2147
|
-
style?.optDouble("changeCornerRadius", 8.0)?.toFloat() ?: 8f,
|
|
2148
|
-
)
|
|
2149
|
-
change.layoutParams = LayoutParams(
|
|
2150
|
-
dp(style?.optDouble("changeWidth", 80.0)?.roundToInt() ?: 80),
|
|
2151
|
-
dp(style?.optDouble("changeHeight", 32.0)?.roundToInt() ?: 32),
|
|
2152
|
-
)
|
|
2153
|
-
contentDescription = item.json.optString(
|
|
2154
|
-
"accessibilityLabel",
|
|
2155
|
-
listOf(
|
|
2156
|
-
item.json.optString("title"),
|
|
2157
|
-
item.json.optString("subtitle"),
|
|
2158
|
-
item.json.optString("price"),
|
|
2159
|
-
changeData.optString("text"),
|
|
2160
|
-
).filter(String::isNotEmpty).joinToString(", "),
|
|
2161
|
-
)
|
|
2162
|
-
}
|
|
2163
|
-
|
|
2164
1736
|
private fun styledDataText(
|
|
2165
1737
|
column: JSONObject,
|
|
2166
1738
|
badges: JSONArray?,
|
|
@@ -2795,40 +2367,6 @@ internal class NativeListRowView(
|
|
|
2795
2367
|
|
|
2796
2368
|
private fun bindSystem(item: NativeListItem, theme: JSONObject?) {
|
|
2797
2369
|
val variant = item.json.optString("variant")
|
|
2798
|
-
val isMarket = item.json.optString("presentation") == "market"
|
|
2799
|
-
if (isMarket) setPadding(dp(20), dp(12), dp(20), dp(12))
|
|
2800
|
-
if (variant == "loading" && item.json.optString("loadingStyle") == "skeleton") {
|
|
2801
|
-
setPadding(dp(20), dp(12), dp(20), dp(12))
|
|
2802
|
-
addView(
|
|
2803
|
-
NativeListMarketSkeleton(context, color(theme, "background", "#FFFFFF")),
|
|
2804
|
-
LayoutParams(LayoutParams.MATCH_PARENT, dp(32)),
|
|
2805
|
-
)
|
|
2806
|
-
return
|
|
2807
|
-
}
|
|
2808
|
-
if (variant == "loading" && item.json.optString("loadingStyle") == "spinner") {
|
|
2809
|
-
gravity = Gravity.CENTER
|
|
2810
|
-
setPadding(0, dp(16), 0, dp(16))
|
|
2811
|
-
addView(
|
|
2812
|
-
ProgressBar(context, null, android.R.attr.progressBarStyleSmall).apply {
|
|
2813
|
-
isIndeterminate = true
|
|
2814
|
-
indeterminateTintList = android.content.res.ColorStateList.valueOf(color(theme, "icon", "#0000009B"))
|
|
2815
|
-
},
|
|
2816
|
-
LayoutParams(dp(20), dp(20)),
|
|
2817
|
-
)
|
|
2818
|
-
return
|
|
2819
|
-
}
|
|
2820
|
-
if (isMarket && variant == "noMatch") {
|
|
2821
|
-
gravity = Gravity.CENTER
|
|
2822
|
-
setPadding(dp(32), dp(32), dp(32), dp(32))
|
|
2823
|
-
title.textSize = sp(16f)
|
|
2824
|
-
title.typeface = NativeListFonts.regular(context)
|
|
2825
|
-
title.gravity = Gravity.CENTER
|
|
2826
|
-
title.setTextColor(color(theme, "secondaryText", "#0000009B"))
|
|
2827
|
-
TextViewCompat.setLineHeight(title, dp(24))
|
|
2828
|
-
showText(title, item.json.optString("message"), 1)
|
|
2829
|
-
addView(mainColumn, weighted())
|
|
2830
|
-
return
|
|
2831
|
-
}
|
|
2832
2370
|
// OneKey patch: warning title/description wrap inside the actual scroll content.
|
|
2833
2371
|
if (variant == "warning") {
|
|
2834
2372
|
setPadding(dp(12), dp(14), dp(12), dp(14))
|
|
@@ -2862,11 +2400,11 @@ internal class NativeListRowView(
|
|
|
2862
2400
|
}
|
|
2863
2401
|
gravity = Gravity.CENTER
|
|
2864
2402
|
if (variant == "loading") {
|
|
2865
|
-
addLeading(JSONObject().put("kind", "skeleton"),
|
|
2403
|
+
addLeading(JSONObject().put("kind", "skeleton"), 40)
|
|
2866
2404
|
leadingFallback.text = ""
|
|
2867
2405
|
leadingFallback.background = roundedFill(
|
|
2868
2406
|
color(theme, "strongBackground", "#0000000F"),
|
|
2869
|
-
|
|
2407
|
+
20f,
|
|
2870
2408
|
)
|
|
2871
2409
|
addSkeleton(skeletonPrimary, 120, 12, theme, bottomMarginDp = 8)
|
|
2872
2410
|
addSkeleton(skeletonSecondary, 80, 12, theme)
|
|
@@ -2907,17 +2445,15 @@ internal class NativeListRowView(
|
|
|
2907
2445
|
sizeDp: Int = 40,
|
|
2908
2446
|
secondaryVisual: JSONObject? = null,
|
|
2909
2447
|
spacingDp: Int = 12,
|
|
2910
|
-
heightDp: Int = sizeDp,
|
|
2911
|
-
cornerRadiusDp: Float? = null,
|
|
2912
2448
|
) {
|
|
2913
2449
|
leadingFrame.visibility = VISIBLE
|
|
2914
|
-
leadingFrame.layoutParams = LayoutParams(dp(sizeDp), dp(
|
|
2450
|
+
leadingFrame.layoutParams = LayoutParams(dp(sizeDp), dp(sizeDp)).apply {
|
|
2915
2451
|
val item = tag as? NativeListItem
|
|
2916
2452
|
// OneKey patch: Yoga rounds cumulative selector edges, not each 12dp gap separately.
|
|
2917
2453
|
marginEnd = if (item?.json?.has("height") == true && item.json.optString("presentation") in setOf("accountSelector", "networkSelector")) dp(12 + sizeDp + spacingDp) - dp(12) - dp(sizeDp) else dp(spacingDp)
|
|
2918
2454
|
}
|
|
2919
2455
|
addView(leadingFrame)
|
|
2920
|
-
leadingFallback.layoutParams = FrameLayout.LayoutParams(dp(sizeDp), dp(
|
|
2456
|
+
leadingFallback.layoutParams = FrameLayout.LayoutParams(dp(sizeDp), dp(sizeDp))
|
|
2921
2457
|
if (visual == null) return
|
|
2922
2458
|
val kind = visual.optString("kind")
|
|
2923
2459
|
val shape = visual.optString(
|
|
@@ -2938,19 +2474,16 @@ internal class NativeListRowView(
|
|
|
2938
2474
|
if (!isIcon && visual.optString("backgroundColor").isNotEmpty()) {
|
|
2939
2475
|
leadingFrame.background = roundedFill(
|
|
2940
2476
|
visualBackground,
|
|
2941
|
-
|
|
2477
|
+
leadingCornerRadius(shape, sizeDp),
|
|
2942
2478
|
)
|
|
2943
2479
|
}
|
|
2944
|
-
leadingFallback.background = roundedFill(
|
|
2945
|
-
visualBackground,
|
|
2946
|
-
cornerRadiusDp ?: leadingCornerRadius(shape, minOf(sizeDp, heightDp)),
|
|
2947
|
-
)
|
|
2480
|
+
leadingFallback.background = roundedFill(visualBackground, leadingCornerRadius(shape, sizeDp))
|
|
2948
2481
|
leadingFallback.visibility = if (!isIcon && sources.isEmpty()) VISIBLE else GONE
|
|
2949
2482
|
if (isIcon) {
|
|
2950
2483
|
leadingFrame.background = GradientDrawable().apply {
|
|
2951
2484
|
setColor(visualBackground)
|
|
2952
2485
|
setStroke(1, parseNativeListColor("#0000001F"))
|
|
2953
|
-
cornerRadius = scaledDp(
|
|
2486
|
+
cornerRadius = scaledDp(leadingCornerRadius(shape, sizeDp))
|
|
2954
2487
|
}
|
|
2955
2488
|
leadingIcon.iconName = visual.optString("name")
|
|
2956
2489
|
leadingIcon.tintColor = safeColor(
|
|
@@ -2961,9 +2494,15 @@ internal class NativeListRowView(
|
|
|
2961
2494
|
}
|
|
2962
2495
|
val visibleSources = sources.take(leadingImages.size)
|
|
2963
2496
|
val tokenPair = kind == "token" && visibleSources.size > 1
|
|
2964
|
-
|
|
2965
|
-
|
|
2497
|
+
val hasAccountSelectorBadge =
|
|
2498
|
+
kind == "account" &&
|
|
2499
|
+
(tag as? NativeListItem)?.json?.optString("presentation") == "accountSelector" &&
|
|
2500
|
+
(visual.optJSONArray("overlays")?.length() ?: 0) > 0
|
|
2501
|
+
if (tokenPair || hasAccountSelectorBadge) {
|
|
2502
|
+
// Network badges intentionally extend past the avatar frame.
|
|
2966
2503
|
clipChildren = false
|
|
2504
|
+
}
|
|
2505
|
+
if (tokenPair) {
|
|
2967
2506
|
leadingOverlayBackground.visibility = VISIBLE
|
|
2968
2507
|
leadingOverlayBackground.background = roundedFill(visualBackdropColor, 10f)
|
|
2969
2508
|
leadingOverlayBackground.layoutParams = FrameLayout.LayoutParams(
|
|
@@ -3002,33 +2541,13 @@ internal class NativeListRowView(
|
|
|
3002
2541
|
index = index,
|
|
3003
2542
|
count = visibleSources.size,
|
|
3004
2543
|
sizeDp = sizeDp,
|
|
3005
|
-
heightDp = heightDp,
|
|
3006
2544
|
tokenPair = tokenPair,
|
|
3007
2545
|
)
|
|
3008
2546
|
image.outlineProvider = when {
|
|
3009
2547
|
tokenPair && index == 1 -> circleOutlineProvider
|
|
3010
|
-
cornerRadiusDp != null -> roundedOutlineProvider(cornerRadiusDp)
|
|
3011
2548
|
else -> leadingOutlineProvider(shape)
|
|
3012
2549
|
}
|
|
3013
2550
|
image.clipToOutline = true
|
|
3014
|
-
if ((tag as? NativeListItem)?.type == "market" && index == 0 && visual.optString("borderColor").isNotEmpty()) {
|
|
3015
|
-
val inset = dp(1)
|
|
3016
|
-
val radius = scaledDp(cornerRadiusDp ?: leadingCornerRadius(shape, minOf(sizeDp, heightDp)))
|
|
3017
|
-
leadingFrame.background = GradientDrawable().apply {
|
|
3018
|
-
setColor(visualBackground)
|
|
3019
|
-
setStroke(inset, safeColor(visual.optString("borderColor"), Color.TRANSPARENT))
|
|
3020
|
-
this.cornerRadius = radius
|
|
3021
|
-
}
|
|
3022
|
-
image.layoutParams = FrameLayout.LayoutParams(dp(sizeDp) - inset * 2, dp(heightDp) - inset * 2).apply {
|
|
3023
|
-
leftMargin = inset
|
|
3024
|
-
topMargin = inset
|
|
3025
|
-
}
|
|
3026
|
-
image.outlineProvider = object : ViewOutlineProvider() {
|
|
3027
|
-
override fun getOutline(view: View, outline: Outline) {
|
|
3028
|
-
outline.setRoundRect(-inset, -inset, view.width + inset, view.height + inset, radius)
|
|
3029
|
-
}
|
|
3030
|
-
}
|
|
3031
|
-
}
|
|
3032
2551
|
val fallbackIcon = if (index == 0) visual.optJSONObject("fallbackIcon") else null
|
|
3033
2552
|
val expectedEpoch = bindingEpoch
|
|
3034
2553
|
bindImage(source, image, boundKey ?: "", index, variant,
|
|
@@ -3145,11 +2664,10 @@ internal class NativeListRowView(
|
|
|
3145
2664
|
index: Int,
|
|
3146
2665
|
count: Int,
|
|
3147
2666
|
sizeDp: Int,
|
|
3148
|
-
heightDp: Int,
|
|
3149
2667
|
tokenPair: Boolean,
|
|
3150
2668
|
): FrameLayout.LayoutParams {
|
|
3151
2669
|
if (count == 1 || tokenPair && index == 0) {
|
|
3152
|
-
return FrameLayout.LayoutParams(dp(sizeDp), dp(
|
|
2670
|
+
return FrameLayout.LayoutParams(dp(sizeDp), dp(sizeDp))
|
|
3153
2671
|
}
|
|
3154
2672
|
if (tokenPair && index == 1) {
|
|
3155
2673
|
return FrameLayout.LayoutParams(dp(16), dp(16), Gravity.END or Gravity.BOTTOM).apply {
|
|
@@ -3491,22 +3009,6 @@ internal class NativeListRowView(
|
|
|
3491
3009
|
}
|
|
3492
3010
|
|
|
3493
3011
|
private fun applySize(item: NativeListItem) {
|
|
3494
|
-
if (item.type == "market") {
|
|
3495
|
-
val style = item.json.optJSONObject("style")
|
|
3496
|
-
val imageHeight = style?.optJSONObject("image")?.optDouble(
|
|
3497
|
-
"height",
|
|
3498
|
-
if (item.json.optString("variant") == "stock") 40.0 else 32.0,
|
|
3499
|
-
) ?: if (item.json.optString("variant") == "stock") 40.0 else 32.0
|
|
3500
|
-
val verticalPadding = style?.optDouble("verticalPadding", 12.0) ?: 12.0
|
|
3501
|
-
val defaultHeight = if (item.json.optString("variant") == "stock") 72.0 else 68.0
|
|
3502
|
-
minimumHeight = dp(
|
|
3503
|
-
item.json.optDouble(
|
|
3504
|
-
"height",
|
|
3505
|
-
maxOf(defaultHeight, imageHeight + verticalPadding * 2),
|
|
3506
|
-
).roundToInt(),
|
|
3507
|
-
)
|
|
3508
|
-
return
|
|
3509
|
-
}
|
|
3510
3012
|
val isWalletSidebar =
|
|
3511
3013
|
item.type == "identity" && item.json.optString("presentation") == "walletSidebar"
|
|
3512
3014
|
val isAccountSelectorIdentity =
|
|
@@ -3659,14 +3161,9 @@ internal class NativeListRowView(
|
|
|
3659
3161
|
else -> 36
|
|
3660
3162
|
}
|
|
3661
3163
|
"system" -> when (item.json.optString("variant")) {
|
|
3662
|
-
"loading" -> when (item.json.optString("loadingStyle")) {
|
|
3663
|
-
"skeleton" -> 56
|
|
3664
|
-
"spinner" -> 52
|
|
3665
|
-
else -> if (item.json.optString("presentation") == "market") 68 else 56
|
|
3666
|
-
}
|
|
3667
|
-
"noMatch", "retry" -> if (item.json.optString("presentation") == "market") 44 else if (item.json.optString("variant") == "noMatch") 36 else 44
|
|
3668
3164
|
"warning" -> 0
|
|
3669
|
-
"
|
|
3165
|
+
"noMatch", "end" -> 36
|
|
3166
|
+
"retry" -> 44
|
|
3670
3167
|
else -> 56
|
|
3671
3168
|
}
|
|
3672
3169
|
"action" -> when {
|
|
@@ -3772,12 +3269,6 @@ internal class NativeListRowView(
|
|
|
3772
3269
|
}
|
|
3773
3270
|
}
|
|
3774
3271
|
|
|
3775
|
-
private fun roundedOutlineProvider(radiusDp: Float) = object : ViewOutlineProvider() {
|
|
3776
|
-
override fun getOutline(view: View, outline: Outline) {
|
|
3777
|
-
outline.setRoundRect(0, 0, view.width, view.height, scaledDp(radiusDp))
|
|
3778
|
-
}
|
|
3779
|
-
}
|
|
3780
|
-
|
|
3781
3272
|
private fun JSONArray?.hasAccessory(kind: String): Boolean {
|
|
3782
3273
|
if (this == null) return false
|
|
3783
3274
|
return (0 until length()).any { optJSONObject(it)?.optString("kind") == kind }
|
|
@@ -3974,7 +3465,6 @@ private class OneKeyIconView(context: android.content.Context) : View(context) {
|
|
|
3974
3465
|
"CrossedSmallSolid" to listOf(Path.FillType.WINDING),
|
|
3975
3466
|
"AccountErrorCustom" to listOf(Path.FillType.WINDING, Path.FillType.EVEN_ODD),
|
|
3976
3467
|
"Circle" to listOf(Path.FillType.WINDING),
|
|
3977
|
-
"BadgeVerifiedSolid" to listOf(Path.FillType.EVEN_ODD),
|
|
3978
3468
|
"ChevronRightSmallOutline" to listOf(Path.FillType.WINDING),
|
|
3979
3469
|
"MinusCircleOutline" to listOf(Path.FillType.WINDING, Path.FillType.EVEN_ODD),
|
|
3980
3470
|
"PlusCircleOutline" to listOf(Path.FillType.WINDING, Path.FillType.EVEN_ODD),
|
|
@@ -4002,7 +3492,6 @@ private class OneKeyIconView(context: android.content.Context) : View(context) {
|
|
|
4002
3492
|
"CrossedSmallSolid" to listOf("M17.87 8.25 14.12 12l3.75 3.75-2.12 2.121-3.75-3.75-3.75 3.75-2.121-2.121L9.879 12l-3.75-3.75 2.12-2.121L12 9.879l3.75-3.75 2.122 2.121Z"),
|
|
4003
3493
|
"AccountErrorCustom" to listOf("M12.5 12.75a1.25 1.25 0 1 0 0-2.5 1.25 1.25 0 0 0 0 2.5", "M0 3.5A3.5 3.5 0 0 1 3.5 0h8.088A2.41 2.41 0 0 1 14 2.412V5h1a3 3 0 0 1 3 3v7a3 3 0 0 1-3 3H4a4 4 0 0 1-4-4zm2 3.163V14a2 2 0 0 0 2 2h11a1 1 0 0 0 1-1V8a1 1 0 0 0-1-1H3.5c-.537 0-1.045-.12-1.5-.337M2 3.5A1.5 1.5 0 0 0 3.5 5H12V2.412A.41.41 0 0 0 11.588 2H3.5A1.5 1.5 0 0 0 2 3.5"),
|
|
4004
3494
|
"Circle" to listOf("M0 12a12 12 0 1 0 24 0a12 12 0 1 0 -24 0"),
|
|
4005
|
-
"BadgeVerifiedSolid" to listOf("M9.483 11.458v3.5h-1v-3.5z M10.467 2.698a2.03 2.03 0 0 1 3.065 0l1.358 1.564a.03.03 0 0 0 .028.01l2.046-.325a2.03 2.03 0 0 1 2.347 1.971l.037 2.07q0 .016.014.026l1.776 1.066a2.03 2.03 0 0 1 .532 3.019l-1.304 1.609a.03.03 0 0 0-.005.03l.675 1.956a2.03 2.03 0 0 1-1.533 2.656l-2.033.394a.03.03 0 0 0-.023.019l-.741 1.933a2.03 2.03 0 0 1-2.88 1.05l-1.811-1.006a.03.03 0 0 0-.03 0l-1.811 1.005a2.03 2.03 0 0 1-2.88-1.049l-.742-1.933a.03.03 0 0 0-.023-.019l-2.033-.394a2.03 2.03 0 0 1-1.532-2.656l.675-1.957a.03.03 0 0 0-.005-.029l-1.304-1.61a2.03 2.03 0 0 1 .532-3.018l1.776-1.066a.03.03 0 0 0 .014-.026l.035-2.07a2.03 2.03 0 0 1 2.349-1.97l2.045.324a.03.03 0 0 0 .028-.01zm1.516 3.76a.5.5 0 0 0-.447.276l-1.861 3.724H8.483a1 1 0 0 0-1 1v3.5a1 1 0 0 0 1 1h6.692a2 2 0 0 0 1.981-1.73l.341-2.5a2 2 0 0 0-1.982-2.27h-1.939l.197-1.269a1.5 1.5 0 0 0-1.481-1.731z"),
|
|
4006
3495
|
"ArrowBottomOutline" to listOf("m13 17.586 5-5L19.414 14 12 21.414 4.586 14 6 12.586l5 5V3h2z"),
|
|
4007
3496
|
"ArrowTopOutline" to listOf("M19.414 10 18 11.414l-5-5V21h-2V6.414l-5 5L4.586 10 12 2.586z"),
|
|
4008
3497
|
"ChartTrendingUpOutline" to listOf("M22 13h-2V9.414l-7 7-4-4-6 6L1.586 17 9 9.586l4 4L18.586 8H15V6h7z"),
|