@onekeyfe/react-native-native-list 6.7.0-alpha.409 → 6.7.0-alpha.412

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.
Files changed (121) hide show
  1. package/android/src/main/java/com/onekey/nativelist/NativeListAccessoryStack.kt +5 -0
  2. package/android/src/main/java/com/onekey/nativelist/NativeListGeneratedIcons.kt +47 -0
  3. package/android/src/main/java/com/onekey/nativelist/NativeListLeadingVisual.kt +5 -0
  4. package/android/src/main/java/com/onekey/nativelist/NativeListPrimitives.kt +117 -338
  5. package/android/src/main/java/com/onekey/nativelist/NativeListRendererRowView.kt +5 -0
  6. package/docs/SPEC.md +114 -7
  7. package/ios/NativeListAccessoryStack.swift +6 -16
  8. package/ios/NativeListDataRowRenderer.swift +15 -6
  9. package/ios/NativeListDesignAssets.swift +13 -84
  10. package/ios/NativeListGeneratedIcons.swift +55 -0
  11. package/ios/NativeListIconBinding.swift +171 -0
  12. package/ios/NativeListIdentityRenderer.swift +12 -10
  13. package/ios/NativeListLeadingVisual.swift +11 -9
  14. package/ios/NativeListMarketRenderer.swift +7 -13
  15. package/ios/NativeListMediaTileRenderer.swift +6 -2
  16. package/ios/NativeListMetricCardRenderer.swift +4 -2
  17. package/ios/NativeListSectionHeaderRenderer.swift +12 -4
  18. package/ios/tests/NativeListAccessoryStackTests.swift +12 -0
  19. package/ios/tests/NativeListSharedIconTests.swift +236 -0
  20. package/lib/module/web/NativeListGeneratedIcons.js +31 -0
  21. package/lib/module/web/NativeListWebEngine.js +21 -323
  22. package/lib/module/web/templates/ActivityRowRenderer.js +4 -24
  23. package/lib/module/web/templates/MarketTableRowRenderer.js +11 -15
  24. package/lib/module/web/templates/MediaTileRowRenderer.js +2 -12
  25. package/lib/typescript/src/web/NativeListGeneratedIcons.d.ts +2 -0
  26. package/lib/typescript/src/web/NativeListWebEngine.d.ts +0 -1
  27. package/package.json +10 -4
  28. package/react-native-native-list.podspec +0 -5
  29. package/scripts/generate-icons.mjs +150 -0
  30. package/scripts/generate-icons.test.mjs +288 -0
  31. package/scripts/native-list-icons.json +260 -0
  32. package/src/web/NativeListGeneratedIcons.ts +28 -0
  33. package/src/web/NativeListWebEngine.ts +25 -405
  34. package/src/web/templates/ActivityRowRenderer.ts +15 -53
  35. package/src/web/templates/MarketTableRowRenderer.ts +17 -29
  36. package/src/web/templates/MediaTileRowRenderer.ts +2 -15
  37. package/ios/Resources/NativeListIcons.xcassets/Contents.json +0 -1
  38. package/ios/Resources/NativeListIcons.xcassets/onekey_arrow_bottom.imageset/Contents.json +0 -1
  39. package/ios/Resources/NativeListIcons.xcassets/onekey_arrow_bottom.imageset/icon.svg +0 -1
  40. package/ios/Resources/NativeListIcons.xcassets/onekey_arrow_top.imageset/Contents.json +0 -1
  41. package/ios/Resources/NativeListIcons.xcassets/onekey_arrow_top.imageset/icon.svg +0 -1
  42. package/ios/Resources/NativeListIcons.xcassets/onekey_badge_verified_solid.imageset/Contents.json +0 -1
  43. package/ios/Resources/NativeListIcons.xcassets/onekey_badge_verified_solid.imageset/icon.svg +0 -1
  44. package/ios/Resources/NativeListIcons.xcassets/onekey_chart_trending_up.imageset/Contents.json +0 -1
  45. package/ios/Resources/NativeListIcons.xcassets/onekey_chart_trending_up.imageset/icon.svg +0 -1
  46. package/ios/Resources/NativeListIcons.xcassets/onekey_checkbox_checked.imageset/Contents.json +0 -1
  47. package/ios/Resources/NativeListIcons.xcassets/onekey_checkbox_checked.imageset/icon.svg +0 -1
  48. package/ios/Resources/NativeListIcons.xcassets/onekey_checkbox_indeterminate.imageset/Contents.json +0 -1
  49. package/ios/Resources/NativeListIcons.xcassets/onekey_checkbox_indeterminate.imageset/icon.svg +0 -1
  50. package/ios/Resources/NativeListIcons.xcassets/onekey_chevron_bottom.imageset/Contents.json +0 -1
  51. package/ios/Resources/NativeListIcons.xcassets/onekey_chevron_bottom.imageset/icon.svg +0 -1
  52. package/ios/Resources/NativeListIcons.xcassets/onekey_chevron_grabber_ver.imageset/Contents.json +0 -1
  53. package/ios/Resources/NativeListIcons.xcassets/onekey_chevron_grabber_ver.imageset/icon.svg +0 -1
  54. package/ios/Resources/NativeListIcons.xcassets/onekey_chevron_right_small.imageset/Contents.json +0 -1
  55. package/ios/Resources/NativeListIcons.xcassets/onekey_chevron_right_small.imageset/icon.svg +0 -1
  56. package/ios/Resources/NativeListIcons.xcassets/onekey_chevron_top.imageset/Contents.json +0 -1
  57. package/ios/Resources/NativeListIcons.xcassets/onekey_chevron_top.imageset/icon.svg +0 -1
  58. package/ios/Resources/NativeListIcons.xcassets/onekey_crypto_coin_outline.imageset/Contents.json +0 -15
  59. package/ios/Resources/NativeListIcons.xcassets/onekey_crypto_coin_outline.imageset/icon.svg +0 -4
  60. package/ios/Resources/NativeListIcons.xcassets/onekey_document2.imageset/Contents.json +0 -1
  61. package/ios/Resources/NativeListIcons.xcassets/onekey_document2.imageset/icon.svg +0 -1
  62. package/ios/Resources/NativeListIcons.xcassets/onekey_dot_hor.imageset/Contents.json +0 -1
  63. package/ios/Resources/NativeListIcons.xcassets/onekey_dot_hor.imageset/icon.svg +0 -1
  64. package/ios/Resources/NativeListIcons.xcassets/onekey_dot_ver_solid.imageset/Contents.json +0 -1
  65. package/ios/Resources/NativeListIcons.xcassets/onekey_dot_ver_solid.imageset/icon.svg +0 -1
  66. package/ios/Resources/NativeListIcons.xcassets/onekey_drag.imageset/Contents.json +0 -1
  67. package/ios/Resources/NativeListIcons.xcassets/onekey_drag.imageset/icon.svg +0 -1
  68. package/ios/Resources/NativeListIcons.xcassets/onekey_error_solid.imageset/Contents.json +0 -1
  69. package/ios/Resources/NativeListIcons.xcassets/onekey_error_solid.imageset/icon.svg +0 -1
  70. package/ios/Resources/NativeListIcons.xcassets/onekey_gas_solid.imageset/Contents.json +0 -15
  71. package/ios/Resources/NativeListIcons.xcassets/onekey_gas_solid.imageset/icon.svg +0 -3
  72. package/ios/Resources/NativeListIcons.xcassets/onekey_image_square_waves.imageset/Contents.json +0 -1
  73. package/ios/Resources/NativeListIcons.xcassets/onekey_image_square_waves.imageset/icon.svg +0 -1
  74. package/ios/Resources/NativeListIcons.xcassets/onekey_info_circle.imageset/Contents.json +0 -1
  75. package/ios/Resources/NativeListIcons.xcassets/onekey_info_circle.imageset/icon.svg +0 -1
  76. package/ios/Resources/NativeListIcons.xcassets/onekey_minus_circle.imageset/Contents.json +0 -1
  77. package/ios/Resources/NativeListIcons.xcassets/onekey_minus_circle.imageset/icon.svg +0 -1
  78. package/ios/Resources/NativeListIcons.xcassets/onekey_minus_circle_solid.imageset/Contents.json +0 -1
  79. package/ios/Resources/NativeListIcons.xcassets/onekey_minus_circle_solid.imageset/icon.svg +0 -1
  80. package/ios/Resources/NativeListIcons.xcassets/onekey_pencil.imageset/Contents.json +0 -1
  81. package/ios/Resources/NativeListIcons.xcassets/onekey_pencil.imageset/icon.svg +0 -1
  82. package/ios/Resources/NativeListIcons.xcassets/onekey_plus_circle.imageset/Contents.json +0 -1
  83. package/ios/Resources/NativeListIcons.xcassets/onekey_plus_circle.imageset/icon.svg +0 -1
  84. package/ios/Resources/NativeListIcons.xcassets/onekey_plus_large.imageset/Contents.json +0 -1
  85. package/ios/Resources/NativeListIcons.xcassets/onekey_plus_large.imageset/icon.svg +0 -1
  86. package/ios/Resources/NativeListIcons.xcassets/onekey_plus_small.imageset/Contents.json +0 -1
  87. package/ios/Resources/NativeListIcons.xcassets/onekey_plus_small.imageset/icon.svg +0 -1
  88. package/ios/Resources/NativeListIcons.xcassets/onekey_questionmark_solid.imageset/Contents.json +0 -1
  89. package/ios/Resources/NativeListIcons.xcassets/onekey_questionmark_solid.imageset/icon.svg +0 -1
  90. package/ios/Resources/NativeListIcons.xcassets/onekey_refresh_ccw_outline.imageset/Contents.json +0 -15
  91. package/ios/Resources/NativeListIcons.xcassets/onekey_refresh_ccw_outline.imageset/icon.svg +0 -3
  92. package/ios/Resources/NativeListIcons.xcassets/onekey_selector_account_error_custom.imageset/Contents.json +0 -15
  93. package/ios/Resources/NativeListIcons.xcassets/onekey_selector_account_error_custom.imageset/icon.svg +0 -14
  94. package/ios/Resources/NativeListIcons.xcassets/onekey_selector_all_networks_solid.imageset/Contents.json +0 -15
  95. package/ios/Resources/NativeListIcons.xcassets/onekey_selector_all_networks_solid.imageset/icon.svg +0 -12
  96. package/ios/Resources/NativeListIcons.xcassets/onekey_selector_apple_brand.imageset/Contents.json +0 -15
  97. package/ios/Resources/NativeListIcons.xcassets/onekey_selector_apple_brand.imageset/icon.svg +0 -6
  98. package/ios/Resources/NativeListIcons.xcassets/onekey_selector_bot_illus.imageset/Contents.json +0 -15
  99. package/ios/Resources/NativeListIcons.xcassets/onekey_selector_bot_illus.imageset/icon.svg +0 -15
  100. package/ios/Resources/NativeListIcons.xcassets/onekey_selector_crossed_small_solid.imageset/Contents.json +0 -15
  101. package/ios/Resources/NativeListIcons.xcassets/onekey_selector_crossed_small_solid.imageset/icon.svg +0 -3
  102. package/ios/Resources/NativeListIcons.xcassets/onekey_selector_globus_outline.imageset/Contents.json +0 -15
  103. package/ios/Resources/NativeListIcons.xcassets/onekey_selector_globus_outline.imageset/icon.svg +0 -7
  104. package/ios/Resources/NativeListIcons.xcassets/onekey_selector_google_illus.imageset/Contents.json +0 -15
  105. package/ios/Resources/NativeListIcons.xcassets/onekey_selector_google_illus.imageset/icon.svg +0 -18
  106. package/ios/Resources/NativeListIcons.xcassets/onekey_selector_lock_solid.imageset/Contents.json +0 -15
  107. package/ios/Resources/NativeListIcons.xcassets/onekey_selector_lock_solid.imageset/icon.svg +0 -7
  108. package/ios/Resources/NativeListIcons.xcassets/onekey_shield_exclamation.imageset/Contents.json +0 -1
  109. package/ios/Resources/NativeListIcons.xcassets/onekey_shield_exclamation.imageset/icon.svg +0 -1
  110. package/ios/Resources/NativeListIcons.xcassets/onekey_speaker_promote.imageset/Contents.json +0 -1
  111. package/ios/Resources/NativeListIcons.xcassets/onekey_speaker_promote.imageset/icon.svg +0 -1
  112. package/ios/Resources/NativeListIcons.xcassets/onekey_star.imageset/Contents.json +0 -1
  113. package/ios/Resources/NativeListIcons.xcassets/onekey_star.imageset/icon.svg +0 -1
  114. package/ios/Resources/NativeListIcons.xcassets/onekey_star_solid.imageset/Contents.json +0 -1
  115. package/ios/Resources/NativeListIcons.xcassets/onekey_star_solid.imageset/icon.svg +0 -1
  116. package/ios/Resources/NativeListIcons.xcassets/onekey_swap_hor.imageset/Contents.json +0 -1
  117. package/ios/Resources/NativeListIcons.xcassets/onekey_swap_hor.imageset/icon.svg +0 -1
  118. package/ios/Resources/NativeListIcons.xcassets/onekey_ticket.imageset/Contents.json +0 -1
  119. package/ios/Resources/NativeListIcons.xcassets/onekey_ticket.imageset/icon.svg +0 -1
  120. package/ios/Resources/NativeListIcons.xcassets/onekey_wallet.imageset/Contents.json +0 -1
  121. package/ios/Resources/NativeListIcons.xcassets/onekey_wallet.imageset/icon.svg +0 -1
@@ -122,6 +122,9 @@ internal class NativeListAccessoryStack(context: android.content.Context, val fo
122
122
  checkboxState: (NativeListItem, NativeSelectionTarget?, String) -> String,
123
123
  horizontal: Boolean = false,
124
124
  ) {
125
+ val iconUpdate = NativeListIconUpdate(this)
126
+ try {
127
+
125
128
  selectorUsesSourceScale = sourceScale
126
129
  reset()
127
130
  tag = item
@@ -179,6 +182,8 @@ internal class NativeListAccessoryStack(context: android.content.Context, val fo
179
182
  }
180
183
  visibility =
181
184
  if ((0 until childCount).any { getChildAt(it).visibility != GONE }) VISIBLE else GONE
185
+
186
+ } finally { iconUpdate.finish() }
182
187
  }
183
188
 
184
189
  fun updateSelection(
@@ -0,0 +1,47 @@
1
+ // Generated by scripts/generate-icons.mjs. Coverage and legacy names only; hosts provide SVG resources.
2
+ package com.margelo.nitro.nativelist
3
+
4
+ internal data class NativeListIconMetadata(val name: String, val width: Float, val height: Float)
5
+ internal val nativeListGeneratedIcons: Map<String, NativeListIconMetadata> = mapOf(
6
+ "AccountErrorCustom" to NativeListIconMetadata("AccountErrorCustom", 18f, 18f),
7
+ "AllNetworksSolid" to NativeListIconMetadata("AllNetworksSolid", 24f, 24f),
8
+ "AppleBrand" to NativeListIconMetadata("AppleBrand", 16f, 20f),
9
+ "ArrowBottomOutline" to NativeListIconMetadata("ArrowBottomOutline", 24f, 24f),
10
+ "ArrowTopOutline" to NativeListIconMetadata("ArrowTopOutline", 24f, 24f),
11
+ "BadgeVerifiedSolid" to NativeListIconMetadata("BadgeRecognizedSolid", 24f, 24f),
12
+ "BotIllus" to NativeListIconMetadata("BotIllus", 24f, 24f),
13
+ "ChartTrendingUpOutline" to NativeListIconMetadata("ChartTrendingUpOutline", 24f, 24f),
14
+ "ChevronBottomOutline" to NativeListIconMetadata("ChevronBottomOutline", 24f, 24f),
15
+ "ChevronGrabberVerOutline" to NativeListIconMetadata("ChevronGrabberVerOutline", 24f, 24f),
16
+ "ChevronRightSmallOutline" to NativeListIconMetadata("ChevronRightSmallOutline", 24f, 24f),
17
+ "ChevronTopOutline" to NativeListIconMetadata("ChevronTopOutline", 24f, 24f),
18
+ "Circle" to NativeListIconMetadata("Circle", 24f, 24f),
19
+ "CrossedSmallSolid" to NativeListIconMetadata("CrossedSmallSolid", 24f, 24f),
20
+ "CryptoCoinOutline" to NativeListIconMetadata("CryptoCoinOutline", 24f, 24f),
21
+ "Document2Outline" to NativeListIconMetadata("Document2Outline", 24f, 24f),
22
+ "DotHorOutline" to NativeListIconMetadata("DotHorOutline", 24f, 24f),
23
+ "DotVerSolid" to NativeListIconMetadata("DotVerSolid", 24f, 24f),
24
+ "DragOutline" to NativeListIconMetadata("DragOutline", 24f, 24f),
25
+ "ErrorSolid" to NativeListIconMetadata("ErrorSolid", 24f, 24f),
26
+ "GasSolid" to NativeListIconMetadata("GasSolid", 24f, 24f),
27
+ "GlobusOutline" to NativeListIconMetadata("GlobusOutline", 24f, 24f),
28
+ "GoogleIllus" to NativeListIconMetadata("GoogleIllus", 24f, 24f),
29
+ "ImageSquareWavesOutline" to NativeListIconMetadata("ImageSquareWavesOutline", 24f, 24f),
30
+ "InfoCircleOutline" to NativeListIconMetadata("InfoCircleOutline", 24f, 24f),
31
+ "LockSolid" to NativeListIconMetadata("LockSolid", 24f, 24f),
32
+ "MinusCircleOutline" to NativeListIconMetadata("MinusCircleOutline", 24f, 24f),
33
+ "MinusCircleSolid" to NativeListIconMetadata("MinusCircleSolid", 24f, 24f),
34
+ "PencilOutline" to NativeListIconMetadata("PencilOutline", 24f, 24f),
35
+ "PlusCircleOutline" to NativeListIconMetadata("PlusCircleOutline", 24f, 24f),
36
+ "PlusLargeOutline" to NativeListIconMetadata("PlusLargeOutline", 24f, 24f),
37
+ "PlusSmallOutline" to NativeListIconMetadata("PlusSmallOutline", 24f, 24f),
38
+ "QuestionmarkSolid" to NativeListIconMetadata("QuestionmarkSolid", 24f, 24f),
39
+ "RefreshCcwOutline" to NativeListIconMetadata("RefreshCcwOutline", 24f, 24f),
40
+ "ShieldExclamationOutline" to NativeListIconMetadata("ShieldExclamationOutline", 24f, 24f),
41
+ "SpeakerPromoteOutline" to NativeListIconMetadata("SpeakerPromoteOutline", 24f, 24f),
42
+ "StarOutline" to NativeListIconMetadata("StarOutline", 24f, 24f),
43
+ "StarSolid" to NativeListIconMetadata("StarSolid", 24f, 24f),
44
+ "SwapHorOutline" to NativeListIconMetadata("SwapHorOutline", 24f, 24f),
45
+ "TicketOutline" to NativeListIconMetadata("TicketOutline", 24f, 24f),
46
+ "WalletOutline" to NativeListIconMetadata("WalletOutline", 24f, 24f),
47
+ )
@@ -112,6 +112,9 @@ internal class NativeListLeadingVisual(private val reactContext: ThemedReactCont
112
112
  sourceScale: Boolean,
113
113
  secondaryVisual: JSONObject? = null,
114
114
  ) {
115
+ val iconUpdate = NativeListIconUpdate(this)
116
+ try {
117
+
115
118
  fallback.typeface = fonts.bold(context)
116
119
  this.visual = visual
117
120
  this.style = style
@@ -394,6 +397,8 @@ internal class NativeListLeadingVisual(private val reactContext: ThemedReactCont
394
397
  overlaySlots.drop(descriptors.size).forEach { it.recycle() }
395
398
  unread.bringToFront()
396
399
  requestLayout()
400
+
401
+ } finally { iconUpdate.finish() }
397
402
  }
398
403
 
399
404
  override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
@@ -3,12 +3,10 @@ package com.margelo.nitro.nativelist
3
3
  import android.graphics.Canvas
4
4
  import android.graphics.Color
5
5
  import android.graphics.Paint
6
- import android.graphics.Path
7
6
  import android.graphics.Typeface
8
7
  import android.view.View
9
8
  import android.widget.LinearLayout
10
9
  import android.widget.TextView
11
- import androidx.core.graphics.PathParser
12
10
  import com.facebook.react.common.assets.ReactFontManager
13
11
  import kotlin.math.roundToInt
14
12
 
@@ -183,357 +181,138 @@ internal class SelectorSubtitleLayout(context: android.content.Context) : Linear
183
181
  }
184
182
  }
185
183
 
186
- internal class OneKeyIconView(context: android.content.Context) : View(context) {
184
+ internal open class OneKeyIconView(context: android.content.Context) : View(context) {
187
185
  var useSourceScale = false
186
+ set(value) { if (field == value) return; field = value; refresh() }
188
187
  var iconName: String = ""
189
- set(value) {
190
- field = value
191
- invalidate()
192
- }
193
-
188
+ set(value) { if (field == value) return; field = value; refresh() }
194
189
  var tintColor: Int = Color.rgb(100, 100, 100)
195
- set(value) {
196
- field = value
197
- invalidate()
198
- }
199
-
190
+ set(value) { if (field == value) return; field = value; refresh() }
200
191
  var glyphSizeDp: Int? = null
201
- set(value) {
202
- field = value
203
- invalidate()
204
- }
192
+ set(value) { if (field == value) return; field = value; refresh() }
193
+ private val owner = Any()
194
+ private var generation = 0L
195
+ private var identity: String? = null
196
+ private var bitmap: android.graphics.Bitmap? = null
197
+ private var displayed: com.margelo.nitro.onekeyimage.OneKeyNamedSVG.RenderResult? = null
198
+ private var displayedGeometry: String? = null
199
+ private val fill = Paint(Paint.ANTI_ALIAS_FLAG or Paint.FILTER_BITMAP_FLAG)
200
+ private var updateDepth = 0
201
+ private var initialized = true
202
+ private var attached = false
205
203
 
206
- private val fill = Paint(Paint.ANTI_ALIAS_FLAG).apply { style = Paint.Style.FILL }
204
+ internal fun beginIconUpdate() { updateDepth++ }
205
+ internal fun endIconUpdate() { updateDepth--; if (updateDepth == 0) refresh() }
207
206
 
208
- override fun onDraw(canvas: Canvas) {
209
- super.onDraw(canvas)
210
- val pathData = iconPaths[iconName] ?: return
211
- val drawSize =
212
- minOf(
213
- minOf(width, height).toFloat(),
214
- glyphSizeDp?.let {
215
- if (useSourceScale) (it * resources.displayMetrics.density).roundToInt().toFloat()
216
- else NativeListScale.dp(resources, it).toFloat()
217
- } ?: Float.MAX_VALUE,
218
- )
219
- // OneKey patch: custom account-error artwork uses an 18-point viewBox.
220
- // val scale = drawSize / 24f
221
- val scale = drawSize / (selectorIconViewBoxes[iconName] ?: 24f)
222
- fill.color = tintColor
223
- canvas.save()
224
- canvas.translate((width - drawSize) / 2f, (height - drawSize) / 2f)
225
- canvas.scale(scale, scale)
226
- val sourceFillTypes = actionIconFillTypes[iconName]
227
- pathData.forEachIndexed { index, data ->
228
- PathParser.createPathFromPathData(data)?.let { path ->
229
- path.fillType = sourceFillTypes?.getOrNull(index) ?: Path.FillType.EVEN_ODD
230
- // OneKey patch: provider illustration colors are part of their source asset.
231
- fill.color = selectorIconColors[iconName]?.getOrNull(index) ?: tintColor
232
- canvas.drawPath(path, fill)
207
+ protected open fun metadata(): NativeListIconMetadata? {
208
+ nativeListGeneratedIcons[iconName]?.let { return it }
209
+ if (iconName.isEmpty()) return null
210
+ val meta = com.margelo.nitro.onekeyimage.OneKeyNamedSVG.iconMetadata(context.applicationContext.assets, iconName) ?: return null
211
+ return NativeListIconMetadata(iconName, meta.width, meta.height)
212
+ }
213
+ protected open fun glyphRect(icon: NativeListIconMetadata): android.graphics.RectF {
214
+ val size = minOf(minOf(width,height).toFloat(), glyphSizeDp?.let {
215
+ if (useSourceScale) (it * resources.displayMetrics.density).roundToInt().toFloat()
216
+ else NativeListScale.dp(resources,it).toFloat()
217
+ } ?: Float.MAX_VALUE)
218
+ val left = (width-size)/2f
219
+ val top = (height-size)/2f
220
+ return android.graphics.RectF(left,top,left+size,top+size*icon.height/icon.width)
221
+ }
222
+
223
+ protected fun refresh(force: Boolean = false) {
224
+ if (updateDepth > 0) return
225
+ val icon = metadata()
226
+ val rect = icon?.let { glyphRect(it) }
227
+ val next = "$iconName|$tintColor|$rect|${resources.displayMetrics.density}|$attached|$isShown"
228
+ if (!force && next == identity) return
229
+ identity = next; generation++
230
+ val revision = generation
231
+ com.margelo.nitro.onekeyimage.OneKeyNamedSVG.cancel(owner)
232
+ fun clear() { bitmap = null; displayed = null; displayedGeometry = null; fill.colorFilter = null; invalidate() }
233
+ if (!attached || !isShown || icon == null || rect == null || rect.isEmpty || icon.name == "Circle") { clear(); return }
234
+ val w = kotlin.math.ceil(rect.width()).toInt()
235
+ val h = kotlin.math.ceil(rect.height()).toInt()
236
+ if (w !in 1..4096 || h !in 1..4096 || w.toLong() * h > 4194304) { clear(); return }
237
+ val color = "rgba(${Color.red(tintColor)},${Color.green(tintColor)},${Color.blue(tintColor)},${Color.alpha(tintColor)/255.0})"
238
+ val geometry = "${icon.name}|$rect|${resources.displayMetrics.density}"
239
+ val ready = displayed
240
+ if (displayedGeometry == geometry && ready != null && bitmap != null) {
241
+ if (ready.canTint(color)) {
242
+ fill.colorFilter = ready.tintColor(color)?.let { android.graphics.PorterDuffColorFilter(it, android.graphics.PorterDuff.Mode.SRC_IN) }
243
+ invalidate(); return
244
+ }
245
+ } else clear()
246
+ val weakView = java.lang.ref.WeakReference(this)
247
+ com.margelo.nitro.onekeyimage.OneKeyNamedSVG.requestRender(owner, context.applicationContext.assets,
248
+ icon.name,color,w,h,resources.displayMetrics.density) { result ->
249
+ val view = weakView.get()
250
+ if (view != null && view.generation == revision && view.attached && view.isShown) {
251
+ view.displayed = result
252
+ view.displayedGeometry = if (result != null) geometry else null
253
+ view.bitmap = result?.bitmap
254
+ view.fill.colorFilter = result?.tintColor(color)?.let { android.graphics.PorterDuffColorFilter(it, android.graphics.PorterDuff.Mode.SRC_IN) }
255
+ view.invalidate()
233
256
  }
234
257
  }
235
- canvas.restore()
236
258
  }
237
259
 
238
- companion object {
239
- // OneKey patch: preserve provider colors and non-24 viewBoxes.
240
- private val selectorIconColors: Map<String, List<Int?>> =
241
- mapOf(
242
- "GlobusOutline" to listOf(null),
243
- "GasSolid" to listOf(null),
244
- "RefreshCcwOutline" to listOf(null),
245
- "CryptoCoinOutline" to listOf(null, null),
246
- "LockSolid" to listOf(null),
247
- "GoogleIllus" to
248
- listOf(
249
- parseNativeListColor("#4285F4"),
250
- parseNativeListColor("#34A853"),
251
- parseNativeListColor("#FBBC05"),
252
- parseNativeListColor("#EA4335"),
253
- ),
254
- "AppleBrand" to listOf(null),
255
- "BotIllus" to
256
- listOf(
257
- parseNativeListColor("#8897A5"),
258
- parseNativeListColor("#3FA9F5"),
259
- parseNativeListColor("#8897A5"),
260
- parseNativeListColor("#8897A5"),
261
- parseNativeListColor("#10243E"),
262
- parseNativeListColor("#10243E"),
263
- parseNativeListColor("#10243E"),
264
- ),
265
- "AllNetworksSolid" to listOf(null, null),
266
- "CrossedSmallSolid" to listOf(null),
267
- "AccountErrorCustom" to listOf(Color.argb(0x72, 0, 0, 0), Color.argb(0x72, 0, 0, 0)),
268
- "Circle" to listOf(null),
269
- )
270
- private val selectorIconViewBoxes =
271
- mapOf(
272
- "GlobusOutline" to 24f,
273
- "GasSolid" to 24f,
274
- "RefreshCcwOutline" to 24f,
275
- "CryptoCoinOutline" to 24f,
276
- "LockSolid" to 24f,
277
- "GoogleIllus" to 24f,
278
- "AppleBrand" to 16f,
279
- "BotIllus" to 24f,
280
- "AllNetworksSolid" to 24f,
281
- "CrossedSmallSolid" to 24f,
282
- "AccountErrorCustom" to 18f,
283
- "Circle" to 24f,
284
- )
285
- // Keep the SVG fill-rule used by each Action-row source path. React Native
286
- // SVG defaults to nonzero (WINDING); only paths declaring fillRule="evenodd"
287
- // use EVEN_ODD. Other existing icons retain their prior rendering behavior.
288
- private val actionIconFillTypes =
289
- mapOf(
290
- // Asset-list icons the app passes by name (OK-66072 audit): absent entries drew nothing.
291
- "DotVerSolid" to listOf(Path.FillType.WINDING),
292
- "Document2Outline" to listOf(Path.FillType.WINDING, Path.FillType.EVEN_ODD),
293
- "WalletOutline" to listOf(Path.FillType.WINDING, Path.FillType.EVEN_ODD),
294
- "PlusLargeOutline" to listOf(Path.FillType.WINDING),
295
- "TicketOutline" to listOf(Path.FillType.WINDING, Path.FillType.EVEN_ODD),
296
- "GlobusOutline" to listOf(Path.FillType.EVEN_ODD),
297
- "GasSolid" to listOf(Path.FillType.EVEN_ODD),
298
- "RefreshCcwOutline" to listOf(Path.FillType.WINDING),
299
- "CryptoCoinOutline" to listOf(Path.FillType.WINDING, Path.FillType.EVEN_ODD),
300
- "LockSolid" to listOf(Path.FillType.EVEN_ODD),
301
- "GoogleIllus" to
302
- listOf(
303
- Path.FillType.WINDING,
304
- Path.FillType.WINDING,
305
- Path.FillType.WINDING,
306
- Path.FillType.WINDING,
307
- ),
308
- "AppleBrand" to listOf(Path.FillType.WINDING),
309
- "BotIllus" to
310
- listOf(
311
- Path.FillType.WINDING,
312
- Path.FillType.WINDING,
313
- Path.FillType.WINDING,
314
- Path.FillType.WINDING,
315
- Path.FillType.WINDING,
316
- Path.FillType.WINDING,
317
- Path.FillType.WINDING,
318
- ),
319
- "AllNetworksSolid" to listOf(Path.FillType.WINDING, Path.FillType.EVEN_ODD),
320
- "CrossedSmallSolid" to listOf(Path.FillType.WINDING),
321
- "AccountErrorCustom" to listOf(Path.FillType.WINDING, Path.FillType.EVEN_ODD),
322
- "Circle" to listOf(Path.FillType.WINDING),
323
- "BadgeVerifiedSolid" to listOf(Path.FillType.EVEN_ODD),
324
- "ChevronRightSmallOutline" to listOf(Path.FillType.WINDING),
325
- "MinusCircleOutline" to listOf(Path.FillType.WINDING, Path.FillType.EVEN_ODD),
326
- "PlusCircleOutline" to listOf(Path.FillType.WINDING, Path.FillType.EVEN_ODD),
327
- "PlusSmallOutline" to listOf(Path.FillType.WINDING),
328
- "DotHorOutline" to listOf(Path.FillType.WINDING),
329
- "MinusCircleSolid" to listOf(Path.FillType.EVEN_ODD),
330
- "PencilOutline" to listOf(Path.FillType.EVEN_ODD),
331
- "DragOutline" to listOf(Path.FillType.WINDING),
332
- "StarSolid" to listOf(Path.FillType.WINDING),
333
- "ChevronGrabberVerOutline" to listOf(Path.FillType.WINDING),
334
- "ChevronBottomOutline" to listOf(Path.FillType.WINDING),
335
- "ChevronTopOutline" to listOf(Path.FillType.WINDING),
336
- "ImageSquareWavesOutline" to listOf(Path.FillType.WINDING, Path.FillType.EVEN_ODD),
337
- )
338
-
339
- // Exact 24x24 paths from app-monorepo packages/components Icon sources.
340
- private val iconPaths =
341
- mapOf(
342
- "DotVerSolid" to
343
- listOf(
344
- "M14 18v4h-4v-4zm0-4h-4v-4h4zm0-8h-4V2h4z"
345
- ),
346
- "Document2Outline" to
347
- listOf(
348
- "M12 16H8v-2h4zm4-4H8v-2h8zm0-4H8V6h8z",
349
- "M20 22H4V2h16zM6 20h12V4H6z"
350
- ),
351
- "WalletOutline" to
352
- listOf(
353
- "M15.5 13.25a1.25 1.25 0 1 1 0 2.5 1.25 1.25 0 0 1 0-2.5",
354
- "M17 8h4v13H7a4 4 0 0 1-4-4V6.5A3.5 3.5 0 0 1 6.5 3H17zM5 17a2 2 0 0 0 2 2h12v-9H6.5c-.537 0-1.045-.12-1.5-.337zM6.5 5a1.5 1.5 0 1 0 0 3H15V5z"
355
- ),
356
- "PlusLargeOutline" to
357
- listOf(
358
- "M13 11h8v2h-8v8h-2v-8H3v-2h8V3h2z"
359
- ),
360
- "TicketOutline" to
361
- listOf(
362
- "M16 17.01h-2V15h2zm0-4h-2V11h2zm0-4h-2V7h2z",
363
- "m22 9.927-.629.252c-1.661.665-1.661 2.977 0 3.642l.629.252V20H2v-5.927l.629-.252c1.661-.665 1.661-2.977 0-3.642L2 9.927V4h20zM4 8.636c2.5 1.52 2.499 5.207 0 6.727V18h16v-2.637c-2.499-1.52-2.5-5.208 0-6.727V6H4z"
364
- ),
365
- "RefreshCcwOutline" to
366
- listOf(
367
- "M5 12a7 7 0 0 0 7 7 7.15 7.15 0 0 0 4.955-2h-2.943v-2h6v6h-2v-2.257A9.148 9.148 0 0 1 12 21a9 9 0 0 1-9-9v-1h2v1Zm1-6.754A9.148 9.148 0 0 1 12 3a9 9 0 0 1 9 9v1h-2v-1a7 7 0 0 0-7-7 7.15 7.15 0 0 0-4.955 2H10v2H4V3h2v2.246Z"
368
- ),
369
- "GasSolid" to
370
- listOf(
371
- "M15 9h4v7h1V8.414L17.586 6 19 4.586l3 3V18h-5v-7h-2v8h1v2H2v-2h1V3h12zM6 9v2h6V9z"
372
- ),
373
- "CryptoCoinOutline" to
374
- listOf(
375
- "M11 16.387a4.5 4.5 0 0 1 0-8.775V6h2v1.613a4.5 4.5 0 0 1 2.856 2.067l-1.712 1.032a2.5 2.5 0 1 0 0 2.576l1.712 1.032A4.5 4.5 0 0 1 13 16.386V18h-2z",
376
- "M22 12c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2s10 4.477 10 10m-2 0a8 8 0 1 0-16 0 8 8 0 0 0 16 0",
377
- ),
378
- // OneKey patch: official selector SVG path geometry.
379
- "GlobusOutline" to
380
- listOf(
381
- "M12 2c5.185 0 9.448 3.947 9.95 9H22v2h-.05c-.502 5.053-4.765 9-9.95 9s-9.448-3.947-9.95-9H2v-2h.05C2.552 5.947 6.815 2 12 2M9.523 13c.09 1.982.438 3.726.934 5.002.29.746.612 1.282.917 1.614.304.331.517.384.626.384s.322-.053.626-.384c.305-.332.627-.868.917-1.614.496-1.276.845-3.02.934-5.002zm-5.459 0a8 8 0 0 0 4.8 6.36 10 10 0 0 1-.271-.633C7.994 17.187 7.61 15.189 7.52 13zm12.416 0c-.09 2.189-.474 4.187-1.073 5.727a10 10 0 0 1-.271.633 8 8 0 0 0 4.8-6.36zM8.863 4.639A8 8 0 0 0 4.064 11h3.457c.09-2.189.473-4.187 1.072-5.727q.127-.327.27-.634M12 4c-.109 0-.322.053-.626.384-.305.332-.627.868-.917 1.614-.496 1.276-.844 3.02-.934 5.002h4.954c-.09-1.982-.438-3.726-.934-5.002-.29-.746-.612-1.282-.917-1.614C12.322 4.053 12.109 4 12 4m3.136.639q.144.307.271.634c.599 1.54.982 3.538 1.073 5.727h3.456a8 8 0 0 0-4.8-6.361"
382
- ),
383
- "LockSolid" to
384
- listOf(
385
- "M12 2a5 5 0 0 1 5 5v2h3v13H4V9h3V7a5 5 0 0 1 5-5m-1 11v5h2v-5zm1-9a3 3 0 0 0-3 3v2h6V7a3 3 0 0 0-3-3"
386
- ),
387
- "GoogleIllus" to
388
- listOf(
389
- "M22.56 12.25c0-.78-.07-1.53-.2-2.25H12v4.26h5.92c-.26 1.37-1.04 2.53-2.21 3.31v2.77h3.57c2.08-1.92 3.28-4.74 3.28-8.09",
390
- "M12 23c2.97 0 5.46-.98 7.28-2.66l-3.57-2.77c-.98.66-2.23 1.06-3.71 1.06-2.86 0-5.29-1.93-6.16-4.53H2.18v2.84C3.99 20.53 7.7 23 12 23",
391
- "M5.84 14.09c-.22-.66-.35-1.36-.35-2.09s.13-1.43.35-2.09V7.07H2.18C1.43 8.55 1 10.22 1 12s.43 3.45 1.18 4.93l2.85-2.22z",
392
- "M12 5.38c1.62 0 3.06.56 4.21 1.64l3.15-3.15C17.45 2.09 14.97 1 12 1 7.7 1 3.99 3.47 2.18 7.07l3.66 2.84c.87-2.6 3.3-4.53 6.16-4.53",
393
- ),
394
- "AppleBrand" to
395
- listOf(
396
- "M11.67.834c.117 1.074-.315 2.153-.955 2.928-.64.773-1.692 1.378-2.718 1.298-.14-1.054.38-2.151.971-2.836C9.63 1.45 10.746.872 11.67.834M14.994 7.093c-.176.108-1.992 1.224-1.972 3.482.025 2.769 2.428 3.693 2.46 3.705l-.004.015a10.1 10.1 0 0 1-1.264 2.593c-.764 1.116-1.556 2.229-2.806 2.254-.598.011-1-.162-1.416-.343-.437-.19-.891-.386-1.609-.386-.751 0-1.226.203-1.683.398-.397.169-.78.333-1.32.354-1.208.047-2.124-1.207-2.895-2.32C.909 14.57-.294 10.414 1.322 7.612c.803-1.395 2.237-2.275 3.794-2.298.671-.014 1.32.244 1.89.47.434.172.821.326 1.135.326.282 0 .659-.149 1.099-.323.692-.273 1.539-.607 2.41-.518.599.026 2.276.24 3.354 1.818z"
397
- ),
398
- "BotIllus" to
399
- listOf(
400
- "M11 2a1 1 0 1 1 2 0v1.8l1.6 1.6a1 1 0 1 1-1.4 1.4L12 5.6l-1.2 1.2a1 1 0 0 1-1.4-1.4L11 3.8z",
401
- "M8.0 6.0h8.0a5.0 5.0 0 0 1 5.0 5.0v4.0a5.0 5.0 0 0 1 -5.0 5.0h-8.0a5.0 5.0 0 0 1 -5.0 -5.0v-4.0a5.0 5.0 0 0 1 5.0 -5.0z",
402
- "M3.0 10.0h0.0a1.5 1.5 0 0 1 1.5 1.5v3.0a1.5 1.5 0 0 1 -1.5 1.5h0.0a1.5 1.5 0 0 1 -1.5 -1.5v-3.0a1.5 1.5 0 0 1 1.5 -1.5z",
403
- "M21.0 10.0h0.0a1.5 1.5 0 0 1 1.5 1.5v3.0a1.5 1.5 0 0 1 -1.5 1.5h0.0a1.5 1.5 0 0 1 -1.5 -1.5v-3.0a1.5 1.5 0 0 1 1.5 -1.5z",
404
- "M7.5 12.0a1.5 1.5 0 1 0 3.0 0a1.5 1.5 0 1 0 -3.0 0",
405
- "M13.5 12.0a1.5 1.5 0 1 0 3.0 0a1.5 1.5 0 1 0 -3.0 0",
406
- "M8.5 15.4c.9.8 2.08 1.2 3.5 1.2s2.6-.4 3.5-1.2c.24-.2.6-.18.8.06.2.23.17.6-.06.8-1.14.98-2.58 1.46-4.24 1.46s-3.1-.48-4.24-1.46a.58.58 0 0 1-.06-.8c.2-.24.56-.26.8-.06",
407
- ),
408
- "AllNetworksSolid" to
409
- listOf(
410
- "M15.333 13.998a1.335 1.335 0 1 1 0 2.67 1.335 1.335 0 0 1 0-2.67",
411
- "M12 0c6.627 0 12 5.373 12 12s-5.373 12-12 12S0 18.627 0 12 5.373 0 12 0M8 12.668A2 2 0 0 0 6 14.666V16c0 1.103.895 1.997 1.998 1.998h1.334A2 2 0 0 0 11.33 16v-1.334a2 2 0 0 0-1.998-1.998zm7.333 0a2.665 2.665 0 1 0 0 5.33 2.665 2.665 0 0 0 0-5.33M7.999 6.001A2 2 0 0 0 6.001 8v1.334c0 1.103.895 1.998 1.998 1.998h1.334a2 2 0 0 0 1.998-1.998V7.999a2 2 0 0 0-1.998-1.998zm6.667 0A2 2 0 0 0 12.668 8v1.334c0 1.103.895 1.998 1.998 1.998H16a2 2 0 0 0 1.998-1.998V7.999A2 2 0 0 0 16 6.001z",
412
- ),
413
- "CrossedSmallSolid" to
414
- listOf(
415
- "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"
416
- ),
417
- "AccountErrorCustom" to
418
- listOf(
419
- "M12.5 12.75a1.25 1.25 0 1 0 0-2.5 1.25 1.25 0 0 0 0 2.5",
420
- "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",
421
- ),
422
- "Circle" to listOf("M0 12a12 12 0 1 0 24 0a12 12 0 1 0 -24 0"),
423
- "BadgeVerifiedSolid" to
424
- listOf(
425
- "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"
426
- ),
427
- "ArrowBottomOutline" to
428
- listOf("m13 17.586 5-5L19.414 14 12 21.414 4.586 14 6 12.586l5 5V3h2z"),
429
- "ArrowTopOutline" to
430
- listOf("M19.414 10 18 11.414l-5-5V21h-2V6.414l-5 5L4.586 10 12 2.586z"),
431
- "ChartTrendingUpOutline" to
432
- listOf("M22 13h-2V9.414l-7 7-4-4-6 6L1.586 17 9 9.586l4 4L18.586 8H15V6h7z"),
433
- "SwapHorOutline" to
434
- listOf(
435
- "M21 16H6.914l2.293 2.293-1.414 1.414L2.086 14H21zm.914-6H3V8h14.086l-2.293-2.293 1.414-1.414z"
436
- ),
437
- "ShieldExclamationOutline" to
438
- listOf(
439
- "M12 12.25a1.25 1.25 0 1 1 0 2.5 1.25 1.25 0 0 1 0-2.5m0-4.75a1 1 0 0 1 1 1v2a1 1 0 0 1-2 0v-2a1 1 0 0 1 1-1",
440
- "M11.352 2.223c.42-.145.876-.145 1.296 0l6.98 2.4a1.995 1.995 0 0 1 1.347 1.886v5.432c0 2.799-1.146 4.817-2.805 6.387-1.61 1.525-3.735 2.652-5.696 3.71a1 1 0 0 1-.947 0c-1.961-1.058-4.086-2.185-5.697-3.71-1.659-1.57-2.805-3.588-2.805-6.386V6.508c0-.852.542-1.61 1.347-1.887l6.98-2.4ZM5.02 6.509v5.432c0 2.16.848 3.676 2.18 4.938 1.272 1.204 2.957 2.149 4.799 3.145 1.842-.996 3.527-1.94 4.799-3.145 1.332-1.262 2.181-2.778 2.181-4.938V6.51L12 4.109z",
441
- ),
442
- "InfoCircleOutline" to
443
- listOf(
444
- "M13 17h-2v-5h-1v-2h3zm0-8h-2V7h2z",
445
- "M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2m0 2a8 8 0 1 0 0 16 8 8 0 0 0 0-16",
446
- ),
447
- "SpeakerPromoteOutline" to
448
- listOf(
449
- "M21.996 11a4 4 0 0 1-3 3.874v5.495l-5.361-1.711A3.998 3.998 0 0 1 5.996 17v-.779l-4-1.276v-7.89l17-5.424v5.495c1.725.444 3 2.01 3 3.874m-2 0c0-.74-.402-1.385-1-1.731v3.46c.597-.345 1-.989 1-1.729M7.998 7.24v7.521l8.998 2.871V4.368l-8.998 2.87ZM3.996 8.516v4.967l2.002.638V7.877zm4 8.484a2 2 0 0 0 3.706 1.041L7.996 16.86z"
450
- ),
451
- "PlusCircleOutline" to
452
- listOf(
453
- "M13 11h4v2h-4v4h-2v-4l-4 .001v-2L11 11V7h2z",
454
- "M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2m0 2a8 8 0 1 0 0 16 8 8 0 0 0 0-16",
455
- ),
456
- "PlusSmallOutline" to listOf("M13 11h5v2h-5v5h-2v-5H6v-2h5V6h2z"),
457
- "DotHorOutline" to listOf("M6 14H2v-4h4zm8 0h-4v-4h4zm8 0h-4v-4h4z"),
458
- "MinusCircleOutline" to
459
- listOf(
460
- "M17 13H7v-2h10z",
461
- "M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2m0 2a8 8 0 1 0 0 16 8 8 0 0 0 0-16",
462
- ),
463
- "MinusCircleSolid" to
464
- listOf(
465
- "M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2M7 13h10v-2H7z"
466
- ),
467
- "ErrorSolid" to listOf("M23.256 20H.742L12 1.041zM11 15v2h2v-2zm0-6v5h2V9z"),
468
- "QuestionmarkSolid" to
469
- listOf(
470
- "M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2m-1 15h2v-2h-2zM9 7v3h2V9h2v1l-2 1.5V14h2v-1.5l2-1.5V7z"
471
- ),
472
- "PencilOutline" to
473
- listOf(
474
- "M22.414 7.5 7.914 22H2v-5.914l14.5-14.5zM4 16.914V20h3.086l9.5-9.5L13.5 7.414zM14.914 6 18 9.086 19.586 7.5 16.5 4.414z"
475
- ),
476
- "ChevronRightSmallOutline" to listOf("M15.414 12 10 17.414 8.586 16l4-4-4-4L10 6.586z"),
477
- "DragOutline" to
478
- listOf("M11 21H7v-4h4zm6 0h-4v-4h4zm-6-7H7v-4h4zm6 0h-4v-4h4zm-6-7H7V3h4zm6 0h-4V3h4z"),
479
- "StarOutline" to
480
- listOf(
481
- "m15.455 7.243 7.729 1.123-5.592 5.45 1.32 7.698L12 17.879l-6.911 3.635 1.32-7.698-5.592-5.45 7.728-1.123L12 .24zM9.872 9.071l-4.759.69 3.444 3.358-.814 4.738L12 15.62l.465.245 3.791 1.993-.813-4.739 3.443-3.357-4.758-.69L12 4.758z"
482
- ),
483
- "StarSolid" to
484
- listOf(
485
- "m15.405 7.313 7.84 1.034-5.735 5.443 1.44 7.774L12 17.793l-6.948 3.771 1.44-7.774L.756 8.347l7.839-1.034L12 .178z"
486
- ),
487
- "ChevronGrabberVerOutline" to
488
- listOf(
489
- "M17.414 15 12 20.414 6.586 15 8 13.586l4 4 4-4zm0-6L16 10.414l-4-4-4 4L6.586 9 12 3.586z"
490
- ),
491
- "ChevronBottomOutline" to
492
- listOf("M20.707 9.707 12 18.414 3.293 9.707l1.414-1.414L12 15.586l7.293-7.293z"),
493
- "ChevronTopOutline" to
494
- listOf("m20.707 14.293-1.414 1.414L12 8.414l-7.293 7.293-1.414-1.414L12 5.586z"),
495
- "ImageSquareWavesOutline" to
496
- listOf(
497
- "M14.25 7a2 2 0 1 1 0 4 2 2 0 0 1 0-4",
498
- "M21 21H3V3h18zM5 16.414V19h12.586L14 15.414l-2 2-4-4zm0-2.828 3-3 4 4 2-2 5 5V5H5z",
499
- ),
500
- )
260
+ override fun onDraw(canvas: Canvas) {
261
+ super.onDraw(canvas)
262
+ val icon = metadata() ?: return
263
+ val rect = glyphRect(icon)
264
+ if (icon.name == "Circle") { fill.colorFilter = null; fill.color = tintColor; canvas.drawOval(rect,fill); return }
265
+ fill.alpha = 255
266
+ bitmap?.let { canvas.drawBitmap(it,null,rect,fill) }
501
267
  }
268
+ override fun onAttachedToWindow() { super.onAttachedToWindow(); attached = true; refresh() }
269
+ override fun onDetachedFromWindow() {
270
+ attached = false
271
+ super.onDetachedFromWindow()
272
+ refresh()
273
+ }
274
+ override fun onVisibilityChanged(changedView: View, visibility: Int) {
275
+ super.onVisibilityChanged(changedView, visibility)
276
+ if (initialized) refresh()
277
+ }
278
+ override fun onSizeChanged(w: Int,h: Int,oldw: Int,oldh: Int) { super.onSizeChanged(w,h,oldw,oldh); refresh() }
279
+ override fun onConfigurationChanged(config: android.content.res.Configuration) { super.onConfigurationChanged(config); refresh(true) }
502
280
  }
503
281
 
504
- internal class OneKeyCheckboxView(context: android.content.Context) : View(context) {
282
+ internal class OneKeyCheckboxView(context: android.content.Context) : OneKeyIconView(context) {
505
283
  var usesSelectorGeometry = false
506
- private val glyphPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply { style = Paint.Style.FILL }
507
- private var state = "unchecked"
508
-
509
- fun setState(value: String, color: Int) {
510
- state = value
511
- glyphPaint.color = color
512
- invalidate()
284
+ set(value) { if (field == value) return; field = value; refresh() }
285
+ fun setState(value: String,color: Int) {
286
+ tintColor = color
287
+ iconName = when(value) {
288
+ "checked" -> "CheckboxCheckedCustom"
289
+ "indeterminate" -> "CheckboxIndeterminateCustom"
290
+ else -> ""
291
+ }
513
292
  }
293
+ override fun metadata(): NativeListIconMetadata? = when(iconName) {
294
+ "CheckboxCheckedCustom", "CheckboxIndeterminateCustom" -> NativeListIconMetadata(iconName,16f,16f)
295
+ else -> null
296
+ }
297
+ override fun glyphRect(icon: NativeListIconMetadata): android.graphics.RectF {
298
+ val size = if (usesSelectorGeometry) (16 * resources.displayMetrics.density).roundToInt().toFloat() else minOf(width,height)*0.8f
299
+ val border = (2 * resources.displayMetrics.density).roundToInt().toFloat()
300
+ val left = if(usesSelectorGeometry) border else (width-size)/2f
301
+ val top = if(usesSelectorGeometry) border else (height-size)/2f
302
+ return android.graphics.RectF(left,top,left+size,top+size)
303
+ }
304
+ }
514
305
 
515
- override fun onDraw(canvas: Canvas) {
516
- super.onDraw(canvas)
517
- val pathData =
518
- when (state) {
519
- "checked" ->
520
- "M12.204 5.043a1 1 0 0 1 0 1.414l-4.5 4.5a1 1 0 0 1-1.414 0l-2-2a1 1 0 1 1 1.414-1.414l1.293 1.293 3.793-3.793a1 1 0 0 1 1.414 0"
521
- "indeterminate" -> "M4 8a1 1 0 0 1 1-1h6a1 1 0 0 1 0 2H5a1 1 0 0 1-1-1"
522
- else -> return
523
- }
524
- // OneKey patch: the source icon is a 16dp child after the 2dp border, not 80% of a rounded
525
- // frame.
526
- val drawSize =
527
- if (usesSelectorGeometry) (16 * resources.displayMetrics.density).roundToInt().toFloat()
528
- else minOf(width, height) * 0.8f
529
- val borderOffset = (2 * resources.displayMetrics.density).roundToInt().toFloat()
530
- canvas.save()
531
- canvas.translate(
532
- if (usesSelectorGeometry) borderOffset else (width - drawSize) / 2f,
533
- if (usesSelectorGeometry) borderOffset else (height - drawSize) / 2f,
534
- )
535
- canvas.scale(drawSize / 16f, drawSize / 16f)
536
- PathParser.createPathFromPathData(pathData)?.let { canvas.drawPath(it, glyphPaint) }
537
- canvas.restore()
306
+ /** Captures existing glyph slots only; nested synchronous binds share their final identity. */
307
+ internal class NativeListIconUpdate(root: View) {
308
+ private val icons = mutableListOf<OneKeyIconView>()
309
+ init {
310
+ fun collect(view: View) {
311
+ if (view is OneKeyIconView) icons.add(view)
312
+ if (view is android.view.ViewGroup) for (index in 0 until view.childCount) collect(view.getChildAt(index))
313
+ }
314
+ collect(root)
315
+ icons.forEach { it.beginIconUpdate() }
538
316
  }
317
+ fun finish() { icons.forEach { it.endIconUpdate() } }
539
318
  }
@@ -186,6 +186,9 @@ internal abstract class NativeListRendererRowView(protected val reactContext: Th
186
186
  checkboxState: (NativeListItem, NativeSelectionTarget?, String) -> String,
187
187
  useSourceScale: Boolean,
188
188
  ) {
189
+ val iconUpdate = NativeListIconUpdate(this)
190
+ try {
191
+
189
192
  val update = update(current, item)
190
193
  val signature =
191
194
  nativeListCanonical(
@@ -246,6 +249,8 @@ internal abstract class NativeListRendererRowView(protected val reactContext: Th
246
249
  bindSelectionContent(item, checkboxState)
247
250
  appearance()
248
251
  requestLayout()
252
+
253
+ } finally { iconUpdate.finish() }
249
254
  }
250
255
 
251
256
  override fun bindSelection(