@onekeyfe/react-native-native-list 3.0.135 → 3.0.137

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.
@@ -2,6 +2,9 @@ package com.margelo.nitro.nativelist
2
2
 
3
3
  import org.json.JSONArray
4
4
  import org.json.JSONObject
5
+ import java.nio.ByteBuffer
6
+ import java.security.MessageDigest
7
+ import java.util.Locale
5
8
 
6
9
  internal fun isNativeListRowPressEnabled(
7
10
  type: String,
@@ -22,6 +25,28 @@ internal fun isNativeListWholeRowInteractive(
22
25
  pressDisabled = pressDisabled,
23
26
  )
24
27
 
28
+ // The image fallback-state cache is process-wide, so it is keyed by a digest of the request
29
+ // identity instead of the raw headers, which can carry credentials such as Authorization.
30
+ internal fun nativeListSourceFallbackStateKey(uri: String, headers: Map<String, String>): String? {
31
+ val trimmedUri = uri.trim().takeIf(String::isNotEmpty) ?: return null
32
+ val digest = MessageDigest.getInstance("SHA-256")
33
+ updateLengthPrefixed(digest, trimmedUri)
34
+ headers.entries
35
+ .map { it.key.lowercase(Locale.ROOT) to it.value }
36
+ .sortedWith(compareBy<Pair<String, String>>({ it.first }, { it.second }))
37
+ .forEach { (name, value) ->
38
+ updateLengthPrefixed(digest, name)
39
+ updateLengthPrefixed(digest, value)
40
+ }
41
+ return digest.digest().joinToString("") { "%02x".format(Locale.ROOT, it.toInt() and 0xff) }
42
+ }
43
+
44
+ private fun updateLengthPrefixed(digest: MessageDigest, value: String) {
45
+ val bytes = value.toByteArray(Charsets.UTF_8)
46
+ digest.update(ByteBuffer.allocate(Int.SIZE_BYTES).putInt(bytes.size).array())
47
+ digest.update(bytes)
48
+ }
49
+
25
50
  internal data class NativeListItem(
26
51
  val key: String,
27
52
  val type: String,
@@ -395,6 +395,30 @@ private class NativeListTableColumnView(context: android.content.Context) : Line
395
395
  private fun sp(value: Float): Float = NativeListScale.font(resources, value)
396
396
  }
397
397
 
398
+ private object NativeListSourceFallbackState {
399
+ private const val CACHE_LIMIT = 128
400
+ private val sources = LinkedHashMap<String, Unit>(CACHE_LIMIT, 0.75f, true)
401
+
402
+ fun has(key: String): Boolean = synchronized(sources) {
403
+ sources[key] != null
404
+ }
405
+
406
+ fun remember(key: String) {
407
+ synchronized(sources) {
408
+ sources[key] = Unit
409
+ while (sources.size > CACHE_LIMIT) {
410
+ sources.remove(sources.entries.first().key)
411
+ }
412
+ }
413
+ }
414
+
415
+ fun forget(key: String) {
416
+ synchronized(sources) {
417
+ sources.remove(key)
418
+ }
419
+ }
420
+ }
421
+
398
422
  internal class NativeListRowView(
399
423
  private val reactContext: ThemedReactContext,
400
424
  ) : LinearLayout(reactContext) {
@@ -1372,6 +1396,7 @@ internal class NativeListRowView(
1372
1396
  leadingIcon.visibility = GONE
1373
1397
  leadingIcon.iconName = ""
1374
1398
  leadingIcon.layoutParams = FrameLayout.LayoutParams(dp(18), dp(18), Gravity.CENTER)
1399
+ leadingIcon.glyphSizeDp = null
1375
1400
  favoriteIcon.visibility = GONE
1376
1401
  favoriteIcon.iconName = ""
1377
1402
  headerTitleIcon.visibility = GONE
@@ -3214,13 +3239,27 @@ internal class NativeListRowView(
3214
3239
  val cornerIconData = visual.optJSONObject("cornerIcon")
3215
3240
  val fallback = visual.optString("fallbackText").take(2)
3216
3241
  val fallbackIconData = visual.optJSONObject("fallbackIcon")
3242
+ val fallbackIconSizeDp = fallbackIconData?.let {
3243
+ val slotSizeDp = minOf(sizeDp, heightDp)
3244
+ if (it.optString("name") == "GlobusOutline") {
3245
+ (slotSizeDp * 1.2f).roundToInt()
3246
+ } else {
3247
+ slotSizeDp
3248
+ }
3249
+ }
3217
3250
  val sourceLoadingStrategy = sources.firstOrNull()?.first?.optString("loadingStrategy", "none") ?: "none"
3218
3251
  val showsSourcePlaceholder = !isIcon && sources.isNotEmpty() && sourceLoadingStrategy != "none"
3219
3252
  val handlesSourceFallback =
3220
3253
  !isIcon && sources.isNotEmpty() &&
3221
3254
  showsSourcePlaceholder &&
3222
3255
  (visual.has("fallbackText") || fallbackIconData != null)
3223
- leadingFallback.text = if (handlesSourceFallback) "" else fallback
3256
+ val sourceFallbackKey = if (handlesSourceFallback) {
3257
+ sources.firstOrNull()?.first?.let(::sourceFallbackStateKey)
3258
+ } else null
3259
+ val restoresSourceFallback =
3260
+ sourceFallbackKey?.let(NativeListSourceFallbackState::has) == true
3261
+ leadingFallback.text =
3262
+ if (handlesSourceFallback && !restoresSourceFallback) "" else fallback
3224
3263
  leadingFallback.setTextColor(parseNativeListColor("#00000072"))
3225
3264
  val visualBackground = safeColor(
3226
3265
  visual.optString("backgroundColor"),
@@ -3239,6 +3278,23 @@ internal class NativeListRowView(
3239
3278
  )
3240
3279
  leadingFallback.visibility =
3241
3280
  if (!isIcon && (sources.isEmpty() || handlesSourceFallback)) VISIBLE else GONE
3281
+ if (handlesSourceFallback && fallbackIconData != null) {
3282
+ leadingIcon.iconName = fallbackIconData.optString("name")
3283
+ leadingIcon.tintColor = safeColor(
3284
+ fallbackIconData.optString("tintColor"),
3285
+ parseNativeListColor("#0000009B"),
3286
+ )
3287
+ leadingIcon.layoutParams = FrameLayout.LayoutParams(
3288
+ dp(fallbackIconSizeDp ?: sizeDp),
3289
+ dp(fallbackIconSizeDp ?: heightDp),
3290
+ Gravity.CENTER,
3291
+ )
3292
+ leadingIcon.glyphSizeDp = fallbackIconSizeDp
3293
+ // Keep the fallback measured while the source loads so an asynchronous
3294
+ // failure can reveal it without waiting for another RecyclerView layout.
3295
+ leadingFallback.visibility = if (restoresSourceFallback) GONE else VISIBLE
3296
+ leadingIcon.visibility = if (restoresSourceFallback) VISIBLE else INVISIBLE
3297
+ }
3242
3298
  if (isIcon) {
3243
3299
  leadingFrame.background = GradientDrawable().apply {
3244
3300
  setColor(visualBackground)
@@ -3258,6 +3314,12 @@ internal class NativeListRowView(
3258
3314
  fallbackIconData.optString("tintColor"),
3259
3315
  parseNativeListColor("#0000009B"),
3260
3316
  )
3317
+ leadingIcon.layoutParams = FrameLayout.LayoutParams(
3318
+ dp(fallbackIconSizeDp ?: sizeDp),
3319
+ dp(fallbackIconSizeDp ?: heightDp),
3320
+ Gravity.CENTER,
3321
+ )
3322
+ leadingIcon.glyphSizeDp = fallbackIconSizeDp
3261
3323
  leadingIcon.visibility = VISIBLE
3262
3324
  }
3263
3325
  val visibleSources = sources.take(leadingImages.size)
@@ -3356,6 +3418,7 @@ internal class NativeListRowView(
3356
3418
  bindImage(source, image, boundKey ?: "", index, variant,
3357
3419
  onLoad = if (!ownsSourceFallback) null else ({
3358
3420
  if (bindingEpoch == expectedEpoch) {
3421
+ sourceFallbackKey?.let(NativeListSourceFallbackState::forget)
3359
3422
  image.visibility = VISIBLE
3360
3423
  leadingFallback.visibility = GONE
3361
3424
  leadingIcon.visibility = GONE
@@ -3363,6 +3426,7 @@ internal class NativeListRowView(
3363
3426
  }),
3364
3427
  onError = if (!ownsSourceFallback) null else ({
3365
3428
  if (bindingEpoch == expectedEpoch) {
3429
+ sourceFallbackKey?.let(NativeListSourceFallbackState::remember)
3366
3430
  image.visibility = GONE
3367
3431
  if (fallbackIcon != null) {
3368
3432
  leadingFallback.visibility = GONE
@@ -3473,6 +3537,14 @@ internal class NativeListRowView(
3473
3537
  }
3474
3538
  }
3475
3539
 
3540
+ private fun sourceFallbackStateKey(source: JSONObject): String? =
3541
+ nativeListSourceFallbackStateKey(
3542
+ uri = source.optString("uri"),
3543
+ headers = source.optJSONObject("headers")?.let { headers ->
3544
+ headers.keys().asSequence().associateWith { headers.optString(it) }
3545
+ }.orEmpty(),
3546
+ )
3547
+
3476
3548
  private fun leadingImageLayout(
3477
3549
  index: Int,
3478
3550
  count: Int,
@@ -4159,8 +4231,10 @@ internal class NativeListRowView(
4159
4231
  val uri = source.optString("uri").trim().takeIf(String::isNotEmpty)
4160
4232
  val sourceHeadersJson = source.optJSONObject("headers")?.toString()
4161
4233
  val recyclingKey = if (retryAttempt == 0) "$token:$slot" else "$token:$slot:retry:$retryAttempt"
4162
- if (hideUntilLoaded && !imageView.isDisplaying(uri, sourceHeadersJson, recyclingKey)) {
4163
- imageView.visibility = INVISIBLE
4234
+ if (hideUntilLoaded) {
4235
+ imageView.visibility = if (
4236
+ imageView.isDisplaying(uri, sourceHeadersJson, recyclingKey)
4237
+ ) VISIBLE else INVISIBLE
4164
4238
  }
4165
4239
  val handleLoad: (() -> Unit)? = if (hideUntilLoaded) ({
4166
4240
  if (bindingEpoch == expectedEpoch) {
@@ -4194,8 +4268,8 @@ internal class NativeListRowView(
4194
4268
  }),
4195
4269
  onError = if (retryLimit == 0) handleError else ({
4196
4270
  if (bindingEpoch == expectedEpoch) {
4197
- if (retryAttempt >= retryLimit) handleError?.invoke()
4198
- else if (!selectorImageRetries.containsKey(imageView)) {
4271
+ handleError?.invoke()
4272
+ if (retryAttempt < retryLimit && !selectorImageRetries.containsKey(imageView)) {
4199
4273
  val retry = Runnable {
4200
4274
  if (bindingEpoch == expectedEpoch) {
4201
4275
  selectorImageRetries.remove(imageView)
@@ -53,6 +53,24 @@ import kotlin.math.roundToInt
53
53
  import kotlin.math.sin
54
54
  import kotlin.math.sqrt
55
55
 
56
+ private class NativeListGridLayoutManager(
57
+ context: Context,
58
+ spanCount: Int,
59
+ ) : GridLayoutManager(context, spanCount) {
60
+ override fun removeAndRecycleViewAt(index: Int, recycler: RecyclerView.Recycler) {
61
+ val child = getChildAt(index) ?: return
62
+ removeViewAt(index)
63
+ // An index-based removal can leave the selected child attached during rapid
64
+ // nested scrolling. Detach that exact view before giving it to RecyclerView.
65
+ if (child.parent != null) removeView(child)
66
+ if (child.parent == null) {
67
+ recycler.recycleView(child)
68
+ } else {
69
+ requestLayout()
70
+ }
71
+ }
72
+ }
73
+
56
74
  class NativeListView(
57
75
  private val reactContext: ThemedReactContext,
58
76
  ) : LinearLayout(reactContext) {
@@ -110,7 +128,7 @@ class NativeListView(
110
128
  private var refreshIndicatorOffsetPx = 0
111
129
  private val contentContainer = FrameLayout(context)
112
130
  private val adapter = NativeListAdapter(reactContext)
113
- private val layoutManager = GridLayoutManager(context, 1)
131
+ private val layoutManager = NativeListGridLayoutManager(context, 1)
114
132
  // OneKey patch: vertical lists retain vertical drags and leave horizontal drags to a parent pager.
115
133
  private val pagerGestureTouchSlop = ViewConfiguration.get(context).scaledTouchSlop
116
134
  private var pagerGestureIsVertical = false
@@ -0,0 +1,43 @@
1
+ package com.margelo.nitro.nativelist
2
+
3
+ import org.junit.Assert.assertEquals
4
+ import org.junit.Assert.assertFalse
5
+ import org.junit.Assert.assertNull
6
+ import org.junit.Assert.assertTrue
7
+ import org.junit.Test
8
+
9
+ class NativeListSourceFallbackStateKeyTest {
10
+ private val uri = "https://example.com/token.png"
11
+
12
+ @Test
13
+ fun keyIsADigestThatDoesNotRetainHeaderValues() {
14
+ val key = nativeListSourceFallbackStateKey(uri, mapOf("Authorization" to "Bearer secret-token"))
15
+
16
+ assertTrue(key.orEmpty().matches(Regex("[0-9a-f]{64}")))
17
+ assertFalse(key.orEmpty().contains("secret-token"))
18
+ }
19
+
20
+ @Test
21
+ fun keyIgnoresHeaderOrderAndNameCase() {
22
+ assertEquals(
23
+ nativeListSourceFallbackStateKey(uri, linkedMapOf("Authorization" to "Bearer a", "X-Trace" to "1")),
24
+ nativeListSourceFallbackStateKey(uri, linkedMapOf("x-trace" to "1", "authorization" to "Bearer a")),
25
+ )
26
+ }
27
+
28
+ @Test
29
+ fun keyDistinguishesSourcesThatDifferOnlyByHeaders() {
30
+ val keys = listOf(
31
+ nativeListSourceFallbackStateKey(uri, emptyMap()),
32
+ nativeListSourceFallbackStateKey(uri, mapOf("Authorization" to "Bearer a")),
33
+ nativeListSourceFallbackStateKey(uri, mapOf("Authorization" to "Bearer b")),
34
+ )
35
+
36
+ assertEquals(keys.size, keys.toSet().size)
37
+ }
38
+
39
+ @Test
40
+ fun blankUriHasNoKey() {
41
+ assertNull(nativeListSourceFallbackStateKey(" ", mapOf("Authorization" to "Bearer a")))
42
+ }
43
+ }
@@ -1,9 +1,30 @@
1
1
  import Foundation
2
2
  // OneKey patch: preserve native font faces while enabling tabular number features.
3
3
  import CoreText
4
+ import CryptoKit
4
5
  import OneKeyImage
5
6
  import UIKit
6
7
 
8
+ private enum NativeListSourceFallbackState {
9
+ private static let sources: NSCache<NSString, NSNumber> = {
10
+ let cache = NSCache<NSString, NSNumber>()
11
+ cache.countLimit = 128
12
+ return cache
13
+ }()
14
+
15
+ static func has(_ key: String) -> Bool {
16
+ sources.object(forKey: key as NSString) != nil
17
+ }
18
+
19
+ static func remember(_ key: String) {
20
+ sources.setObject(NSNumber(value: true), forKey: key as NSString)
21
+ }
22
+
23
+ static func forget(_ key: String) {
24
+ sources.removeObject(forKey: key as NSString)
25
+ }
26
+ }
27
+
7
28
  // Market/TokenListSkeleton: source geometry and the native Skeleton's 3s shimmer.
8
29
  private final class NativeListMarketSkeleton: UIView {
9
30
  private let marks = (0..<5).map { _ in UIView() }
@@ -3408,12 +3429,20 @@ final class NativeListCell: UICollectionViewCell {
3408
3429
  let cornerIcon = visual.dictionary("cornerIcon")
3409
3430
  let fallbackText = String(visual.string("fallbackText").prefix(2))
3410
3431
  let fallbackIconData = visual.dictionary("fallbackIcon")
3432
+ let fallbackIconSize = fallbackIconData.map {
3433
+ let slotSize = min(leadingWidth.constant, leadingHeight.constant)
3434
+ return $0.string("name") == "GlobusOutline" ? slotSize * 1.2 : slotSize
3435
+ }
3411
3436
  let sourceLoadingStrategy = sources.first?.data.string("loadingStrategy", default: "none") ?? "none"
3412
3437
  let showsSourcePlaceholder = !isIcon && !sources.isEmpty && sourceLoadingStrategy != "none"
3413
3438
  let handlesSourceFallback = !isIcon && !sources.isEmpty &&
3414
3439
  showsSourcePlaceholder &&
3415
3440
  (visual["fallbackText"] != nil || fallbackIconData != nil)
3416
- fallbackLabel.text = handlesSourceFallback ? nil : fallbackText
3441
+ let sourceFallbackKey = handlesSourceFallback
3442
+ ? sources.first.flatMap { sourceFallbackStateKey($0.data) }
3443
+ : nil
3444
+ let restoresSourceFallback = sourceFallbackKey.map(NativeListSourceFallbackState.has) ?? false
3445
+ fallbackLabel.text = handlesSourceFallback && !restoresSourceFallback ? nil : fallbackText
3417
3446
  let sourceFallbackBackground = currentTheme?["strongBackground"] as? String ?? "#0000000F"
3418
3447
  // OneKey patch: source-backed visuals default to no placeholder/background.
3419
3448
  // A non-none image loadingStrategy opts back into the themed placeholder.
@@ -3451,6 +3480,20 @@ final class NativeListCell: UICollectionViewCell {
3451
3480
  leadingIconImageView.image = nativeListIcon(named: fallbackIconData.string("name"))
3452
3481
  leadingIconImageView.contentMode = .scaleAspectFit
3453
3482
  }
3483
+ if handlesSourceFallback, let fallbackIconData {
3484
+ fallbackLabel.isHidden = true
3485
+ leadingIconImageView.image = nativeListIcon(named: fallbackIconData.string("name"))
3486
+ leadingIconImageView.tintColor = UIColor(
3487
+ nativeListHex: fallbackIconData.string("tintColor", default: "#646464"),
3488
+ fallback: .darkGray
3489
+ )
3490
+ leadingIconImageView.contentMode = .scaleAspectFit
3491
+ leadingIconWidth.constant = fallbackIconSize ?? leadingWidth.constant
3492
+ leadingIconHeight.constant = fallbackIconSize ?? leadingHeight.constant
3493
+ leadingIconImageView.isHidden = !restoresSourceFallback
3494
+ } else if handlesSourceFallback {
3495
+ fallbackLabel.isHidden = !restoresSourceFallback
3496
+ }
3454
3497
  let visibleSources = Array(sources.prefix(leadingImages.count))
3455
3498
  let tokenPair = kind == "token" && visibleSources.count > 1
3456
3499
  leadingContainer.clipsToBounds = !tokenPair && cornerIcon == nil
@@ -3506,6 +3549,9 @@ final class NativeListCell: UICollectionViewCell {
3506
3549
  bindImage(source.data, into: imageView, token: key, slot: index, variant: source.variant,
3507
3550
  onLoad: !ownsSourceFallback ? nil : { [weak self, weak imageView] in
3508
3551
  guard let self, self.bindingEpoch == expectedEpoch else { return }
3552
+ if let sourceFallbackKey {
3553
+ NativeListSourceFallbackState.forget(sourceFallbackKey)
3554
+ }
3509
3555
  imageView?.isHidden = false
3510
3556
  self.fallbackLabel.isHidden = true
3511
3557
  self.leadingIconImageView.isHidden = true
@@ -3513,6 +3559,9 @@ final class NativeListCell: UICollectionViewCell {
3513
3559
  },
3514
3560
  onError: !ownsSourceFallback ? nil : { [weak self, weak imageView] in
3515
3561
  guard let self, self.bindingEpoch == expectedEpoch else { return }
3562
+ if let sourceFallbackKey {
3563
+ NativeListSourceFallbackState.remember(sourceFallbackKey)
3564
+ }
3516
3565
  imageView?.isHidden = true
3517
3566
  if let fallbackIcon {
3518
3567
  self.fallbackLabel.isHidden = true
@@ -3643,6 +3692,26 @@ final class NativeListCell: UICollectionViewCell {
3643
3692
  return sources
3644
3693
  }
3645
3694
 
3695
+ private func sourceFallbackStateKey(_ source: [String: Any]) -> String? {
3696
+ let uri = source.string("uri").trimmingCharacters(in: .whitespacesAndNewlines)
3697
+ guard !uri.isEmpty else { return nil }
3698
+ // The fallback-state cache is process-wide, so key it by a digest of the request identity
3699
+ // instead of retaining raw header values, which can carry credentials such as Authorization.
3700
+ let headers = source.dictionary("headers") ?? [:]
3701
+ let fields: [(name: String, value: String)] = headers.map { key, value in
3702
+ (name: key.lowercased(), value: String(describing: value))
3703
+ }
3704
+ let sortedFields = fields.sorted { lhs, rhs in
3705
+ lhs.name == rhs.name ? lhs.value < rhs.value : lhs.name < rhs.name
3706
+ }
3707
+ var canonicalValue = "\(uri.utf8.count):\(uri)"
3708
+ for field in sortedFields {
3709
+ canonicalValue += "\(field.name.utf8.count):\(field.name)\(field.value.utf8.count):\(field.value)"
3710
+ }
3711
+ let digest = SHA256.hash(data: Data(canonicalValue.utf8))
3712
+ return digest.map { String(format: "%02x", $0) }.joined()
3713
+ }
3714
+
3646
3715
  private func leadingConstraints(
3647
3716
  _ imageView: UIView,
3648
3717
  index: Int,
@@ -4085,8 +4154,10 @@ final class NativeListCell: UICollectionViewCell {
4085
4154
  },
4086
4155
  onError: retryLimit == 0 ? handleError : { [weak self, weak imageView] in
4087
4156
  guard let self, self.bindingEpoch == expectedEpoch, let imageView else { return }
4088
- guard retryAttempt < retryLimit else { handleError?(); return }
4089
- guard self.selectorImageRetries[imageID] == nil else { return }
4157
+ // Report every failed attempt: a rebind during the retry delay cancels the pending retry,
4158
+ // so deferring to the last attempt would never record the source fallback state.
4159
+ handleError?()
4160
+ guard retryAttempt < retryLimit, self.selectorImageRetries[imageID] == nil else { return }
4090
4161
  let retry = DispatchWorkItem { [weak self, weak imageView] in
4091
4162
  guard let self, self.bindingEpoch == expectedEpoch, let imageView else { return }
4092
4163
  self.selectorImageRetries.removeValue(forKey: imageID)
@@ -537,6 +537,12 @@ export const WEB_LIST_CSS = `
537
537
  .ok-native-list-account-row[data-native-list-selector="accountSelector"]>.ok-native-list-accessories[data-native-list-account-control="createAddress"]{position:absolute;top:18px;right:12px}
538
538
  .ok-native-list-account-row[data-native-list-selector="accountSelector"] .ok-native-list-accessories>[data-native-list-account-control="createAddress"]{flex-basis:36px;width:36px;height:36px;padding:6px;border-radius:8px}
539
539
  .ok-native-list-account-action-row{padding-left:12px;padding-right:12px}.ok-native-list-account-action-row .ok-native-list-action-title{font-size:16px;line-height:24px;font-weight:400}.ok-native-list-account-action-row .ok-native-list-action-title[data-tone="primary"]{color:var(--nl-primary)}
540
+ /* OneKey patch: account selector wallets and accounts keep the default cursor instead of pointer or grab affordances.
541
+ Only the row surface is matched: cursor inherits, so plain children follow the row, while icon buttons,
542
+ checkboxes, and action buttons keep advertising themselves with their own pointer cursor. */
543
+ .ok-native-list-root .ok-native-list-item>.ok-native-list-wallet-row,.ok-native-list-root .ok-native-list-wallet-member>.ok-native-list-wallet-row,.ok-native-list-root .ok-native-list-item>.ok-native-list-account-row,.ok-native-list-root .ok-native-list-item>.ok-native-list-account-action-row,.ok-native-list-wallet-member{cursor:default}
544
+ /* OneKey patch: Add account hover and pressed backgrounds keep the account row corner radius. */
545
+ .ok-native-list-account-action-row{border-radius:12px}
540
546
  `;
541
547
  function createElement(document, tag, className, text) {
542
548
  const element = document.createElement(tag);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/react-native-native-list",
3
- "version": "3.0.135",
3
+ "version": "3.0.137",
4
4
  "description": "Template-driven native RecyclerView and UICollectionView for React Native",
5
5
  "source": "./src/index.ts",
6
6
  "main": "./lib/module/index.js",
@@ -83,8 +83,8 @@
83
83
  "typescript": "^5.9.2"
84
84
  },
85
85
  "peerDependencies": {
86
- "@onekeyfe/react-native-image": "3.0.135",
87
- "@onekeyfe/react-native-native-logger": "3.0.135",
86
+ "@onekeyfe/react-native-image": "3.0.137",
87
+ "@onekeyfe/react-native-native-logger": "3.0.137",
88
88
  "react": "*",
89
89
  "react-native": "*",
90
90
  "react-native-nitro-modules": "0.37.0"
@@ -965,6 +965,12 @@ export const WEB_LIST_CSS = `
965
965
  .ok-native-list-account-row[data-native-list-selector="accountSelector"]>.ok-native-list-accessories[data-native-list-account-control="createAddress"]{position:absolute;top:18px;right:12px}
966
966
  .ok-native-list-account-row[data-native-list-selector="accountSelector"] .ok-native-list-accessories>[data-native-list-account-control="createAddress"]{flex-basis:36px;width:36px;height:36px;padding:6px;border-radius:8px}
967
967
  .ok-native-list-account-action-row{padding-left:12px;padding-right:12px}.ok-native-list-account-action-row .ok-native-list-action-title{font-size:16px;line-height:24px;font-weight:400}.ok-native-list-account-action-row .ok-native-list-action-title[data-tone="primary"]{color:var(--nl-primary)}
968
+ /* OneKey patch: account selector wallets and accounts keep the default cursor instead of pointer or grab affordances.
969
+ Only the row surface is matched: cursor inherits, so plain children follow the row, while icon buttons,
970
+ checkboxes, and action buttons keep advertising themselves with their own pointer cursor. */
971
+ .ok-native-list-root .ok-native-list-item>.ok-native-list-wallet-row,.ok-native-list-root .ok-native-list-wallet-member>.ok-native-list-wallet-row,.ok-native-list-root .ok-native-list-item>.ok-native-list-account-row,.ok-native-list-root .ok-native-list-item>.ok-native-list-account-action-row,.ok-native-list-wallet-member{cursor:default}
972
+ /* OneKey patch: Add account hover and pressed backgrounds keep the account row corner radius. */
973
+ .ok-native-list-account-action-row{border-radius:12px}
968
974
  `;
969
975
 
970
976
  function createElement(