@onekeyfe/react-native-native-list 3.0.131 → 3.0.133

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.
@@ -21,6 +21,11 @@ internal data class NativeListItem(
21
21
  val isSelectable: Boolean
22
22
  get() = !json.optBoolean("disabled", false) && type in SELECTABLE_TYPES
23
23
 
24
+ val isRowPressEnabled: Boolean
25
+ get() = !json.optBoolean("disabled", false) &&
26
+ !json.optBoolean("pressDisabled", false) &&
27
+ (type != "system" || json.optString("variant") == "retry")
28
+
24
29
  val isReorderable: Boolean
25
30
  get() {
26
31
  if (json.optBoolean("disabled", false)) return false
@@ -16,6 +16,7 @@ import android.graphics.Shader
16
16
  import android.graphics.Typeface
17
17
  import android.graphics.drawable.Drawable
18
18
  import android.graphics.drawable.GradientDrawable
19
+ import android.graphics.drawable.StateListDrawable
19
20
  import android.os.Handler
20
21
  import android.os.Looper
21
22
  import android.text.Spannable
@@ -622,7 +623,7 @@ internal class NativeListRowView(
622
623
 
623
624
  setOnTouchListener { _, event ->
624
625
  when (event.actionMasked) {
625
- MotionEvent.ACTION_DOWN -> if (isEnabled) {
626
+ MotionEvent.ACTION_DOWN -> if ((tag as? NativeListItem)?.isRowPressEnabled == true) {
626
627
  touchPressed = true
627
628
  marketLongPressFired = false
628
629
  val item = tag as? NativeListItem
@@ -686,7 +687,7 @@ internal class NativeListRowView(
686
687
  return@let
687
688
  }
688
689
  // OneKey patch: allow create-address accessories when whole-row press is gated.
689
- if (!item.json.optBoolean("pressDisabled", false)) onRowPress?.invoke(item, actionOrigin(view, "row"))
690
+ if (item.isRowPressEnabled) onRowPress?.invoke(item, actionOrigin(view, "row"))
690
691
  }
691
692
  }
692
693
  setWillNotDraw(false)
@@ -1334,6 +1335,8 @@ internal class NativeListRowView(
1334
1335
  it.glyphSizeDp = null
1335
1336
  it.alpha = 1f
1336
1337
  it.isEnabled = true
1338
+ it.background = null
1339
+ it.setPadding(0, 0, 0, 0)
1337
1340
  it.setOnClickListener(null)
1338
1341
  }
1339
1342
  checkbox.visibility = GONE
@@ -1407,7 +1410,7 @@ internal class NativeListRowView(
1407
1410
  return@let
1408
1411
  }
1409
1412
  // OneKey patch: allow create-address accessories when whole-row press is gated.
1410
- if (!item.json.optBoolean("pressDisabled", false)) onRowPress?.invoke(item, actionOrigin(view, "row"))
1413
+ if (item.isRowPressEnabled) onRowPress?.invoke(item, actionOrigin(view, "row"))
1411
1414
  }
1412
1415
  }
1413
1416
  }
@@ -3040,7 +3043,7 @@ internal class NativeListRowView(
3040
3043
  }
3041
3044
  }
3042
3045
  setOnClickListener {
3043
- emitAction(item, item.json.optString("actionKey"), null, this, "row")
3046
+ onRowPress?.invoke(item, actionOrigin(this, "row"))
3044
3047
  }
3045
3048
  }
3046
3049
 
@@ -3167,7 +3170,7 @@ internal class NativeListRowView(
3167
3170
  )
3168
3171
  if (variant == "retry") {
3169
3172
  setOnClickListener {
3170
- emitAction(item, item.json.optString("actionKey"), null, this, "row")
3173
+ onRowPress?.invoke(item, actionOrigin(this, "row"))
3171
3174
  }
3172
3175
  showTrailing(0, "Retry", true, item.json.optString("actionKey"))
3173
3176
  trailingViews[0].textSize = sp(14f)
@@ -3524,14 +3527,16 @@ internal class NativeListRowView(
3524
3527
  put("name", "ChevronRightSmallOutline")
3525
3528
  if (optString("actionKey").isEmpty()) put("actionKey", "press")
3526
3529
  },
3530
+ theme,
3527
3531
  )
3528
3532
  "menu" -> showTrailingMenu(textIndex++, accessory.optString("actionKey"))
3529
3533
  "drag" -> showTrailingIcon(
3530
3534
  textIndex++,
3531
3535
  item,
3532
3536
  JSONObject(accessory.toString()).apply { put("name", "DragOutline") },
3537
+ theme,
3533
3538
  )
3534
- "icon" -> showTrailingIcon(textIndex++, item, accessory)
3539
+ "icon" -> showTrailingIcon(textIndex++, item, accessory, theme)
3535
3540
  "spinner" -> spinner.visibility = VISIBLE
3536
3541
  "progress" -> showTrailing(textIndex++, "${(accessory.optDouble("value") * 100).toInt()}%", false)
3537
3542
  }
@@ -3758,7 +3763,7 @@ internal class NativeListRowView(
3758
3763
  else -> color(theme, "primaryText", "#000000DF")
3759
3764
  }
3760
3765
 
3761
- private fun showTrailingIcon(index: Int, item: NativeListItem, data: JSONObject) {
3766
+ private fun showTrailingIcon(index: Int, item: NativeListItem, data: JSONObject, theme: JSONObject?) {
3762
3767
  if (index !in trailingIcons.indices) return
3763
3768
  val icon = trailingIcons[index]
3764
3769
  icon.iconName = data.optString("name")
@@ -3770,17 +3775,20 @@ internal class NativeListRowView(
3770
3775
  if (item.json.optString("presentation") == "accountSelector") {
3771
3776
  icon.glyphSizeDp = 24
3772
3777
  val isSourceMenu = item.json.has("height") && icon.iconName == "DotHorOutline"
3773
- val size = if (isSourceMenu) 24 else if (item.json.has("height") && icon.iconName == "PlusSmallOutline") 36 else 38
3778
+ val size = if (item.json.has("height") && icon.iconName == "PlusSmallOutline") 36 else 38
3774
3779
  icon.layoutParams = LayoutParams(dp(size), dp(size)).apply {
3775
3780
  gravity = Gravity.CENTER_VERTICAL
3776
- if (!isSourceMenu) {
3777
- marginStart = -dp(7)
3778
- marginEnd = -dp(7)
3779
- }
3781
+ marginStart = -dp(7)
3782
+ marginEnd = -dp(7)
3780
3783
  }
3781
- if (isSourceMenu) {
3782
- // OneKey patch: the native ActionList trigger measures 24dp; Yoga rounds its trailing edge cumulatively.
3783
- setPadding(paddingLeft, paddingTop, (12 * resources.displayMetrics.density).toInt(), paddingBottom)
3784
+ if (isSourceMenu && data.optString("actionKey").isNotEmpty()) {
3785
+ icon.background = StateListDrawable().apply {
3786
+ addState(
3787
+ intArrayOf(android.R.attr.state_pressed),
3788
+ roundedFill(color(theme, "rowPressedBackground", "#00000017"), 19f),
3789
+ )
3790
+ addState(intArrayOf(), roundedFill(Color.TRANSPARENT, 19f))
3791
+ }
3784
3792
  }
3785
3793
  } else if (icon.iconName == "ChevronRightSmallOutline") {
3786
3794
  icon.glyphSizeDp = null
@@ -231,6 +231,13 @@ class NativeListView(
231
231
  private var sectionIndexScrubbing = false
232
232
  private var sectionIndexProgrammaticScroll = false
233
233
  private var sectionIndexHapticsEnabled = true
234
+ private val sectionIndexAttachmentHandler = Handler(Looper.getMainLooper())
235
+ private var sectionIndexListAttachmentScheduled = false
236
+ private val sectionIndexListAttachmentRunnable = Runnable {
237
+ sectionIndexListAttachmentScheduled = false
238
+ attachSectionIndexToList()
239
+ if (!disposed && isAttachedToWindow) updateSectionIndexAttachment()
240
+ }
234
241
  private val sectionIndexLocationOnScreen = IntArray(2)
235
242
  private val sectionIndexHostLocationOnScreen = IntArray(2)
236
243
  private var sectionIndexObservedTree: ViewTreeObserver? = null
@@ -385,8 +392,7 @@ class NativeListView(
385
392
  val item = adapter.itemAt(position) ?: return false
386
393
  val clickable = clickableDescendantAt(child, event.rawX.toInt(), event.rawY.toInt())
387
394
  val accessoryHandlesTap = clickable != null && clickable !== child
388
- return accessoryHandlesTap ||
389
- (!item.json.optBoolean("disabled", false) && !item.json.optBoolean("pressDisabled", false))
395
+ return accessoryHandlesTap || item.isRowPressEnabled
390
396
  }
391
397
 
392
398
  private fun clickableDescendantAt(view: View, rawX: Int, rawY: Int): View? {
@@ -444,7 +450,7 @@ class NativeListView(
444
450
 
445
451
  override fun onDetachedFromWindow() {
446
452
  stopSectionIndexAttachmentTracking()
447
- attachSectionIndexToList()
453
+ scheduleSectionIndexAttachmentToList()
448
454
  updateRefreshIndicatorOffset(0)
449
455
  if (disposed) disposeResources()
450
456
  super.onDetachedFromWindow()
@@ -1079,7 +1085,7 @@ class NativeListView(
1079
1085
  if (resourcesDisposed) return
1080
1086
  resourcesDisposed = true
1081
1087
  stopSectionIndexAttachmentTracking()
1082
- attachSectionIndexToList()
1088
+ scheduleSectionIndexAttachmentToList()
1083
1089
  stopReorderRelayoutLoop()
1084
1090
  invalidateActionAnchor("destroy")
1085
1091
  actionAnchor = null
@@ -1255,6 +1261,13 @@ class NativeListView(
1255
1261
  sectionIndexObservedTree = null
1256
1262
  }
1257
1263
 
1264
+ private fun scheduleSectionIndexAttachmentToList() {
1265
+ if (sectionIndexView.parent === contentContainer) return
1266
+ if (sectionIndexListAttachmentScheduled) return
1267
+ sectionIndexListAttachmentScheduled = true
1268
+ sectionIndexAttachmentHandler.post(sectionIndexListAttachmentRunnable)
1269
+ }
1270
+
1258
1271
  private fun attachSectionIndexToList() {
1259
1272
  if (sectionIndexView.parent === contentContainer) return
1260
1273
  (sectionIndexView.parent as? ViewGroup)?.removeView(sectionIndexView)
@@ -1365,6 +1378,7 @@ class NativeListView(
1365
1378
 
1366
1379
  private fun handleRowPress(item: NativeListItem, origin: NativeListActionOrigin) {
1367
1380
  val current = config ?: return
1381
+ if (!item.isRowPressEnabled) return
1368
1382
  if (current.rowPressToggles && item.isSelectable && current.selectionMode != "none") {
1369
1383
  updateSelection(NativeSelectionTarget("row", item.key), item.key)
1370
1384
  } else {
@@ -3819,7 +3819,11 @@ final class NativeListCell: UICollectionViewCell {
3819
3819
  .foregroundColor: label.textColor as Any,
3820
3820
  .paragraphStyle: paragraphStyle,
3821
3821
  ]
3822
- if currentItem?.type == "market" || currentItem?.type == "system" && currentItem?.data.string("presentation") == "market" && currentItem?.data.string("variant") == "noMatch" || (currentItem?.data["height"] != nil && (["accountSelector", "walletSidebar"].contains(currentItem?.data.string("presentation") ?? "") || currentItem?.type == "sectionHeader" && currentItem?.data.string("presentation") == "networkSelector")) || currentItem?.type == "system" && currentItem?.data.string("variant") == "warning" {
3822
+ let isNetworkFallback =
3823
+ label === fallbackLabel &&
3824
+ currentItem?.type == "identity" &&
3825
+ currentItem?.data.string("presentation") == "networkSelector"
3826
+ if currentItem?.type == "market" || currentItem?.type == "system" && currentItem?.data.string("presentation") == "market" && currentItem?.data.string("variant") == "noMatch" || (currentItem?.data["height"] != nil && (["accountSelector", "walletSidebar"].contains(currentItem?.data.string("presentation") ?? "") || currentItem?.type == "sectionHeader" && currentItem?.data.string("presentation") == "networkSelector")) || currentItem?.type == "system" && currentItem?.data.string("variant") == "warning" || isNetworkFallback {
3823
3827
  // OneKey patch: React Native centers font metrics inside explicit line heights.
3824
3828
  let baselineOffset = max(0, (lineHeight - label.font.lineHeight) / 2)
3825
3829
  // OneKey patch: TextKit's 14/20 headings align their baseline to the upper physical pixel.
@@ -14,6 +14,12 @@ struct NativeListItem {
14
14
  return !disabled && Self.selectableTypes.contains(type)
15
15
  }
16
16
 
17
+ var isRowPressEnabled: Bool {
18
+ !data.bool("disabled") &&
19
+ !data.bool("pressDisabled") &&
20
+ (type != "system" || data.string("variant") == "retry")
21
+ }
22
+
17
23
  var isReorderable: Bool {
18
24
  guard !data.bool("disabled") else { return false }
19
25
  if type == "rail", data.bool("draggable") { return true }
@@ -293,13 +293,13 @@ final class NativeListView: UIView {
293
293
  if let touchView = touch.view,
294
294
  touchView === footerCell || touchView.isDescendant(of: footerCell) {
295
295
  guard let footer = config?.fixedFooter else { return false }
296
- return !footer.data.bool("disabled") && !footer.data.bool("pressDisabled")
296
+ return footer.isRowPressEnabled
297
297
  }
298
298
  let point = touch.location(in: collectionView)
299
299
  guard collectionView.bounds.contains(point),
300
300
  let indexPath = collectionView.indexPathForItem(at: point),
301
301
  let item = item(at: indexPath) else { return false }
302
- return !item.data.bool("disabled") && !item.data.bool("pressDisabled")
302
+ return item.isRowPressEnabled
303
303
  }
304
304
 
305
305
  required init?(coder: NSCoder) {
@@ -1310,7 +1310,7 @@ final class NativeListView: UIView {
1310
1310
 
1311
1311
  private func handleRowPress(_ item: NativeListItem, origin: NativeListActionOrigin?) {
1312
1312
  // OneKey patch: missing-address rows keep accessory actions available.
1313
- guard let config, !item.data.bool("disabled"), !item.data.bool("pressDisabled") else { return }
1313
+ guard let config, item.isRowPressEnabled else { return }
1314
1314
  if config.rowPressToggles && item.isSelectable && config.selectionMode != "none" {
1315
1315
  updateSelection(target: NativeSelectionTarget(scope: "row", key: item.key), sourceKey: item.key)
1316
1316
  return
@@ -1332,7 +1332,7 @@ final class NativeListView: UIView {
1332
1332
  guard let indexPath = collectionView.indexPathForItem(at: point),
1333
1333
  let item = config?.items[safe: indexPath.item],
1334
1334
  item.type == "market",
1335
- !item.data.bool("disabled") else { return }
1335
+ item.isRowPressEnabled else { return }
1336
1336
  let actionKey = item.data.string("longPressActionKey")
1337
1337
  guard !actionKey.isEmpty else { return }
1338
1338
  let origin = (collectionView.cellForItem(at: indexPath) as? NativeListCell)?.rowActionOrigin()
@@ -1906,6 +1906,10 @@ final class NativeListView: UIView {
1906
1906
  }
1907
1907
 
1908
1908
  @objc private func footerHighlightChanged(_ recognizer: UILongPressGestureRecognizer) {
1909
+ guard config?.fixedFooter?.isRowPressEnabled == true else {
1910
+ footerCell.setPressed(false)
1911
+ return
1912
+ }
1909
1913
  switch recognizer.state {
1910
1914
  case .began, .changed:
1911
1915
  footerCell.setPressed(footerCell.bounds.contains(recognizer.location(in: footerCell)))
@@ -1964,7 +1968,7 @@ final class NativeListView: UIView {
1964
1968
  if gestureRecognizer === reorderLongPress {
1965
1969
  return config?.reorderable == true && item.isReorderable
1966
1970
  }
1967
- return item.type == "market" && !item.data.string("longPressActionKey").isEmpty
1971
+ return item.type == "market" && item.isRowPressEnabled && !item.data.string("longPressActionKey").isEmpty
1968
1972
  }
1969
1973
  guard gestureRecognizer === listBodyGestureGuard,
1970
1974
  let pan = gestureRecognizer as? UIPanGestureRecognizer else { return true }
@@ -2107,7 +2111,7 @@ extension NativeListView: UICollectionViewDelegateFlowLayout {
2107
2111
 
2108
2112
  func collectionView(_ collectionView: UICollectionView, shouldHighlightItemAt indexPath: IndexPath) -> Bool {
2109
2113
  guard let item = config?.items[safe: indexPath.item] else { return false }
2110
- return !item.data.bool("disabled")
2114
+ return item.isRowPressEnabled
2111
2115
  }
2112
2116
 
2113
2117
  func collectionView(_ collectionView: UICollectionView, didHighlightItemAt indexPath: IndexPath) {
@@ -2120,7 +2124,7 @@ extension NativeListView: UICollectionViewDelegateFlowLayout {
2120
2124
 
2121
2125
  func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
2122
2126
  guard let item = config?.items[safe: indexPath.item] else { return false }
2123
- return !item.data.bool("disabled")
2127
+ return item.isRowPressEnabled
2124
2128
  }
2125
2129
 
2126
2130
  func scrollViewDidScroll(_ scrollView: UIScrollView) {
@@ -3,6 +3,9 @@
3
3
  export function isSelectableRow(row) {
4
4
  return !row.disabled && (row.type === 'identity' || row.type === 'rail' || row.type === 'activity' || row.type === 'message' || row.type === 'dataRow' || row.type === 'mediaTile' || row.type === 'metricCard');
5
5
  }
6
+ export function isRowPressEnabled(row) {
7
+ return !row.disabled && !row.pressDisabled && (row.type !== 'system' || row.variant === 'retry');
8
+ }
6
9
  function deltaBetween(before, after, source, sourceKey) {
7
10
  return {
8
11
  addedKeys: [...after].filter(key => !before.has(key)),
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
 
3
- import { checkboxStateForKeys, checkboxStateForSection, isSelectableRow, reduceSelection, selectionStateFromSnapshot } from "../selection.js";
3
+ import { checkboxStateForKeys, checkboxStateForSection, isRowPressEnabled, isSelectableRow, reduceSelection, selectionStateFromSnapshot } from "../selection.js";
4
4
  import { calculateAlignedScrollOffset, resolveLocationIndex, scrollFailure, validateOffset } from "../scrolling.js";
5
5
  import { applyRowPatches, validateSnapshot } from "../validation.js";
6
6
  import { avatarPrefetchWindow } from "../avatarPrefetch.js";
@@ -455,14 +455,15 @@ export const WEB_LIST_CSS = `
455
455
  .ok-native-list-viewport{position:absolute;inset:0;overflow:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;scrollbar-gutter:stable}
456
456
  .ok-native-list-content{position:relative;min-width:100%;min-height:100%}
457
457
  .ok-native-list-item{position:absolute;box-sizing:border-box;contain:layout paint style;outline:none}
458
- .ok-native-list-row{width:100%;height:100%;box-sizing:border-box;display:flex;align-items:center;gap:12px;overflow:hidden;background:var(--nl-row);color:var(--nl-primary);cursor:pointer;user-select:none;-webkit-user-select:none}
458
+ .ok-native-list-row{width:100%;height:100%;box-sizing:border-box;display:flex;align-items:center;gap:12px;overflow:hidden;background:var(--nl-row);color:var(--nl-primary);cursor:default;user-select:none;-webkit-user-select:none}
459
459
  .ok-native-list-item[data-table-alternate="true"]>.ok-native-list-row{background:var(--nl-bg)}
460
460
  .ok-native-list-item[data-native-list-selected="true"]>.ok-native-list-row{background:var(--nl-selected)}
461
461
  .ok-native-list-item[data-native-list-disabled="true"]>.ok-native-list-row{opacity:.5;cursor:default}
462
- .ok-native-list-item:not([data-native-list-disabled="true"]):hover>.ok-native-list-row{background:var(--nl-pressed)}
463
- .ok-native-list-item:not([data-native-list-disabled="true"]):active>.ok-native-list-row{background:var(--nl-pressed)}
464
- .ok-native-list-item:not([data-native-list-disabled="true"]):not([data-native-list-selected="true"]):hover>.ok-native-list-wallet-row{background:var(--nl-strong)}
465
- .ok-native-list-item:not([data-native-list-disabled="true"]):not([data-native-list-selected="true"]):active>.ok-native-list-wallet-row{background:var(--nl-pressed)}
462
+ .ok-native-list-item[data-native-list-row-press-enabled="true"]>.ok-native-list-row{cursor:pointer}
463
+ .ok-native-list-item[data-native-list-row-press-enabled="true"]:hover>.ok-native-list-row{background:var(--nl-pressed)}
464
+ .ok-native-list-item[data-native-list-row-press-enabled="true"]:active>.ok-native-list-row{background:var(--nl-pressed)}
465
+ .ok-native-list-item[data-native-list-row-press-enabled="true"]:not([data-native-list-selected="true"]):hover>.ok-native-list-wallet-row{background:var(--nl-strong)}
466
+ .ok-native-list-item[data-native-list-row-press-enabled="true"]:not([data-native-list-selected="true"]):active>.ok-native-list-wallet-row{background:var(--nl-pressed)}
466
467
  .ok-native-list-item[data-native-list-selected="true"]:hover>.ok-native-list-wallet-row{background:var(--nl-selected)}
467
468
  .ok-native-list-wallet-group{display:flex;width:100%;height:100%;box-sizing:border-box;flex-direction:column;gap:12px;overflow:hidden;border:1px solid var(--nl-separator);border-radius:12px;background:var(--nl-subdued);user-select:none;-webkit-user-select:none}
468
469
  .ok-native-list-wallet-member{flex:0 0 68px;height:68px;overflow:hidden;border-radius:12px;background:transparent;cursor:pointer}
@@ -470,7 +471,7 @@ export const WEB_LIST_CSS = `
470
471
  .ok-native-list-wallet-member[data-native-list-selected="true"]>.ok-native-list-wallet-row{background:var(--nl-selected)}
471
472
  .ok-native-list-wallet-member:not([data-native-list-selected="true"]):hover>.ok-native-list-wallet-row{background:var(--nl-strong)}
472
473
  .ok-native-list-wallet-member:not([data-native-list-selected="true"]):active>.ok-native-list-wallet-row{background:var(--nl-pressed)}
473
- .ok-native-list-item:focus-visible>.ok-native-list-row{outline:2px solid var(--nl-accent);outline-offset:-2px}
474
+ .ok-native-list-item[data-native-list-row-press-enabled="true"]:focus-visible>.ok-native-list-row{outline:2px solid var(--nl-accent);outline-offset:-2px}
474
475
  .ok-native-list-item[data-native-list-reorderable="true"]>.ok-native-list-row{cursor:grab}
475
476
  .ok-native-list-root[data-native-list-dragging="true"] .ok-native-list-row{cursor:grabbing}
476
477
  .ok-native-list-item[data-native-list-animate-reorder="true"]{transition:transform ${WEB_REORDER_ANIMATION.outOfWayDurationMs}ms ${WEB_REORDER_ANIMATION.outOfWayTimingFunction},height ${WEB_REORDER_ANIMATION.outOfWayDurationMs}ms ${WEB_REORDER_ANIMATION.outOfWayTimingFunction}}
@@ -530,6 +531,8 @@ export const WEB_LIST_CSS = `
530
531
  .ok-native-list-wallet-row[data-native-list-selector="walletSidebar"] .ok-native-list-wallet-badges>.ok-native-list-badge{font-size:11px;line-height:14px;font-weight:400;height:18px;padding:2px 6px;border-radius:4px;background:var(--nl-subdued);color:var(--nl-secondary)}
531
532
  .ok-native-list-wallet-row[data-native-list-selector="walletSidebar"] .ok-native-list-wallet-badges>.ok-native-list-badge[data-tone="warning"]{background:var(--nl-caution-background);color:var(--nl-caution)}
532
533
  .ok-native-list-account-row[data-native-list-selector="accountSelector"] .ok-native-list-accessories>.ok-native-list-icon-button{box-sizing:border-box;flex:0 0 38px;width:38px;height:38px;margin:-7px;padding:7px}
534
+ .ok-native-list-account-row[data-native-list-selector="accountSelector"] .ok-native-list-accessories>.ok-native-list-icon-button[data-native-list-action]:not([data-native-list-account-control="createAddress"]):hover{background:var(--nl-strong);border-radius:50%}
535
+ .ok-native-list-account-row[data-native-list-selector="accountSelector"] .ok-native-list-accessories>.ok-native-list-icon-button[data-native-list-action]:not([data-native-list-account-control="createAddress"]):active{background:var(--nl-pressed);border-radius:50%}
533
536
  /* OneKey patch: AccountSelectorAccountListItem fixes the borderless Plus slot at top18/right20. */
534
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}
535
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}
@@ -2455,6 +2458,7 @@ export class NativeListWebEngine {
2455
2458
  setData(element, 'nativeListBindingEpoch', bindingEpoch);
2456
2459
  setData(element, 'nativeListRowIndex', index);
2457
2460
  setData(element, 'nativeListDisabled', Boolean(row.disabled));
2461
+ setData(element, 'nativeListRowPressEnabled', isRowPressEnabled(row));
2458
2462
  setData(element, 'testid', row.testID);
2459
2463
  // OneKey patch: deprecation dims a row without disabling its actions.
2460
2464
  element.style.opacity = String(row.opacity ?? 1);
@@ -2465,7 +2469,7 @@ export class NativeListWebEngine {
2465
2469
  setData(element, 'tableAlternate', this.snapshot.layout.kind === 'table' && row.type === 'dataRow' && (row.index ?? index) % 2 === 0);
2466
2470
  element.setAttribute('role', 'listitem');
2467
2471
  element.setAttribute('aria-label', row.accessibilityLabel ?? this.rowLabel(row));
2468
- if (!row.disabled && !(row.type === 'system' && row.variant === 'spacer')) {
2472
+ if (isRowPressEnabled(row)) {
2469
2473
  element.tabIndex = 0;
2470
2474
  } else {
2471
2475
  element.removeAttribute('tabindex');
@@ -2926,7 +2930,7 @@ export class NativeListWebEngine {
2926
2930
  handleRowPress(row, rowElement, sourceElement = rowElement) {
2927
2931
  // OneKey patch: missing-address rows keep their create-address accessory interactive.
2928
2932
  // if (row.disabled) return;
2929
- if (row.disabled || row.pressDisabled) return;
2933
+ if (!isRowPressEnabled(row)) return;
2930
2934
  if (this.snapshot.selection?.rowPressToggles && this.snapshot.selection.mode !== 'none' && isSelectableRow(row)) {
2931
2935
  this.activateSelection({
2932
2936
  scope: 'row'
@@ -2958,7 +2962,7 @@ export class NativeListWebEngine {
2958
2962
  if (event.target.closest('[data-native-list-action]')) return;
2959
2963
  const rowElement = event.target.closest('[data-native-list-row-key]');
2960
2964
  const row = this.rowAtElement(rowElement);
2961
- if (row?.type !== 'market' || row.disabled) return;
2965
+ if (row?.type !== 'market' || !isRowPressEnabled(row)) return;
2962
2966
  this.cancelMarketPointer();
2963
2967
  if (row.pressInActionKey) this.emitRowAction(row, row.pressInActionKey, rowElement ?? undefined, rowElement ?? undefined);
2964
2968
  if (!row.longPressActionKey || !rowElement) return;
@@ -20,6 +20,7 @@ export type SelectionResult = Readonly<{
20
20
  delta: SelectionDeltaEvent;
21
21
  }>;
22
22
  export declare function isSelectableRow(row: RowModel): boolean;
23
+ export declare function isRowPressEnabled(row: RowModel): boolean;
23
24
  export declare function reduceSelection(state: SelectionState, action: SelectionAction, rows: readonly RowModel[]): SelectionResult;
24
25
  export declare function checkboxStateForKeys(keys: readonly string[], selectedKeys: ReadonlySet<string>): CheckboxState;
25
26
  export declare function checkboxStateForSection(sectionKey: string, rows: readonly RowModel[], selectedKeys: ReadonlySet<string>): CheckboxState;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onekeyfe/react-native-native-list",
3
- "version": "3.0.131",
3
+ "version": "3.0.133",
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",
@@ -38,7 +38,7 @@
38
38
  "nitrogen": "nitrogen",
39
39
  "typecheck": "tsc -b",
40
40
  "lint": "eslint \"**/*.{js,ts,tsx}\"",
41
- "test": "jest --runInBand && node --test src/__tests__/selector-parity.cjs",
41
+ "test": "jest --runInBand",
42
42
  "release": "yarn prepare && npm whoami && npm publish --access public"
43
43
  },
44
44
  "keywords": [
@@ -83,8 +83,8 @@
83
83
  "typescript": "^5.9.2"
84
84
  },
85
85
  "peerDependencies": {
86
- "@onekeyfe/react-native-image": "3.0.131",
87
- "@onekeyfe/react-native-native-logger": "3.0.131",
86
+ "@onekeyfe/react-native-image": "3.0.133",
87
+ "@onekeyfe/react-native-native-logger": "3.0.133",
88
88
  "react": "*",
89
89
  "react-native": "*",
90
90
  "react-native-nitro-modules": "0.37.0"
package/src/selection.ts CHANGED
@@ -35,6 +35,14 @@ export function isSelectableRow(row: RowModel): boolean {
35
35
  );
36
36
  }
37
37
 
38
+ export function isRowPressEnabled(row: RowModel): boolean {
39
+ return (
40
+ !row.disabled &&
41
+ !row.pressDisabled &&
42
+ (row.type !== 'system' || row.variant === 'retry')
43
+ );
44
+ }
45
+
38
46
  function deltaBetween(
39
47
  before: ReadonlySet<string>,
40
48
  after: ReadonlySet<string>,
@@ -27,6 +27,7 @@ import type {
27
27
  import {
28
28
  checkboxStateForKeys,
29
29
  checkboxStateForSection,
30
+ isRowPressEnabled,
30
31
  isSelectableRow,
31
32
  reduceSelection,
32
33
  selectionStateFromSnapshot,
@@ -882,14 +883,15 @@ export const WEB_LIST_CSS = `
882
883
  .ok-native-list-viewport{position:absolute;inset:0;overflow:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;scrollbar-gutter:stable}
883
884
  .ok-native-list-content{position:relative;min-width:100%;min-height:100%}
884
885
  .ok-native-list-item{position:absolute;box-sizing:border-box;contain:layout paint style;outline:none}
885
- .ok-native-list-row{width:100%;height:100%;box-sizing:border-box;display:flex;align-items:center;gap:12px;overflow:hidden;background:var(--nl-row);color:var(--nl-primary);cursor:pointer;user-select:none;-webkit-user-select:none}
886
+ .ok-native-list-row{width:100%;height:100%;box-sizing:border-box;display:flex;align-items:center;gap:12px;overflow:hidden;background:var(--nl-row);color:var(--nl-primary);cursor:default;user-select:none;-webkit-user-select:none}
886
887
  .ok-native-list-item[data-table-alternate="true"]>.ok-native-list-row{background:var(--nl-bg)}
887
888
  .ok-native-list-item[data-native-list-selected="true"]>.ok-native-list-row{background:var(--nl-selected)}
888
889
  .ok-native-list-item[data-native-list-disabled="true"]>.ok-native-list-row{opacity:.5;cursor:default}
889
- .ok-native-list-item:not([data-native-list-disabled="true"]):hover>.ok-native-list-row{background:var(--nl-pressed)}
890
- .ok-native-list-item:not([data-native-list-disabled="true"]):active>.ok-native-list-row{background:var(--nl-pressed)}
891
- .ok-native-list-item:not([data-native-list-disabled="true"]):not([data-native-list-selected="true"]):hover>.ok-native-list-wallet-row{background:var(--nl-strong)}
892
- .ok-native-list-item:not([data-native-list-disabled="true"]):not([data-native-list-selected="true"]):active>.ok-native-list-wallet-row{background:var(--nl-pressed)}
890
+ .ok-native-list-item[data-native-list-row-press-enabled="true"]>.ok-native-list-row{cursor:pointer}
891
+ .ok-native-list-item[data-native-list-row-press-enabled="true"]:hover>.ok-native-list-row{background:var(--nl-pressed)}
892
+ .ok-native-list-item[data-native-list-row-press-enabled="true"]:active>.ok-native-list-row{background:var(--nl-pressed)}
893
+ .ok-native-list-item[data-native-list-row-press-enabled="true"]:not([data-native-list-selected="true"]):hover>.ok-native-list-wallet-row{background:var(--nl-strong)}
894
+ .ok-native-list-item[data-native-list-row-press-enabled="true"]:not([data-native-list-selected="true"]):active>.ok-native-list-wallet-row{background:var(--nl-pressed)}
893
895
  .ok-native-list-item[data-native-list-selected="true"]:hover>.ok-native-list-wallet-row{background:var(--nl-selected)}
894
896
  .ok-native-list-wallet-group{display:flex;width:100%;height:100%;box-sizing:border-box;flex-direction:column;gap:12px;overflow:hidden;border:1px solid var(--nl-separator);border-radius:12px;background:var(--nl-subdued);user-select:none;-webkit-user-select:none}
895
897
  .ok-native-list-wallet-member{flex:0 0 68px;height:68px;overflow:hidden;border-radius:12px;background:transparent;cursor:pointer}
@@ -897,7 +899,7 @@ export const WEB_LIST_CSS = `
897
899
  .ok-native-list-wallet-member[data-native-list-selected="true"]>.ok-native-list-wallet-row{background:var(--nl-selected)}
898
900
  .ok-native-list-wallet-member:not([data-native-list-selected="true"]):hover>.ok-native-list-wallet-row{background:var(--nl-strong)}
899
901
  .ok-native-list-wallet-member:not([data-native-list-selected="true"]):active>.ok-native-list-wallet-row{background:var(--nl-pressed)}
900
- .ok-native-list-item:focus-visible>.ok-native-list-row{outline:2px solid var(--nl-accent);outline-offset:-2px}
902
+ .ok-native-list-item[data-native-list-row-press-enabled="true"]:focus-visible>.ok-native-list-row{outline:2px solid var(--nl-accent);outline-offset:-2px}
901
903
  .ok-native-list-item[data-native-list-reorderable="true"]>.ok-native-list-row{cursor:grab}
902
904
  .ok-native-list-root[data-native-list-dragging="true"] .ok-native-list-row{cursor:grabbing}
903
905
  .ok-native-list-item[data-native-list-animate-reorder="true"]{transition:transform ${WEB_REORDER_ANIMATION.outOfWayDurationMs}ms ${WEB_REORDER_ANIMATION.outOfWayTimingFunction},height ${WEB_REORDER_ANIMATION.outOfWayDurationMs}ms ${WEB_REORDER_ANIMATION.outOfWayTimingFunction}}
@@ -957,6 +959,8 @@ export const WEB_LIST_CSS = `
957
959
  .ok-native-list-wallet-row[data-native-list-selector="walletSidebar"] .ok-native-list-wallet-badges>.ok-native-list-badge{font-size:11px;line-height:14px;font-weight:400;height:18px;padding:2px 6px;border-radius:4px;background:var(--nl-subdued);color:var(--nl-secondary)}
958
960
  .ok-native-list-wallet-row[data-native-list-selector="walletSidebar"] .ok-native-list-wallet-badges>.ok-native-list-badge[data-tone="warning"]{background:var(--nl-caution-background);color:var(--nl-caution)}
959
961
  .ok-native-list-account-row[data-native-list-selector="accountSelector"] .ok-native-list-accessories>.ok-native-list-icon-button{box-sizing:border-box;flex:0 0 38px;width:38px;height:38px;margin:-7px;padding:7px}
962
+ .ok-native-list-account-row[data-native-list-selector="accountSelector"] .ok-native-list-accessories>.ok-native-list-icon-button[data-native-list-action]:not([data-native-list-account-control="createAddress"]):hover{background:var(--nl-strong);border-radius:50%}
963
+ .ok-native-list-account-row[data-native-list-selector="accountSelector"] .ok-native-list-accessories>.ok-native-list-icon-button[data-native-list-action]:not([data-native-list-account-control="createAddress"]):active{background:var(--nl-pressed);border-radius:50%}
960
964
  /* OneKey patch: AccountSelectorAccountListItem fixes the borderless Plus slot at top18/right20. */
961
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}
962
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}
@@ -4175,6 +4179,7 @@ export class NativeListWebEngine {
4175
4179
  setData(element, 'nativeListBindingEpoch', bindingEpoch);
4176
4180
  setData(element, 'nativeListRowIndex', index);
4177
4181
  setData(element, 'nativeListDisabled', Boolean(row.disabled));
4182
+ setData(element, 'nativeListRowPressEnabled', isRowPressEnabled(row));
4178
4183
  setData(element, 'testid', row.testID);
4179
4184
  // OneKey patch: deprecation dims a row without disabling its actions.
4180
4185
  element.style.opacity = String(row.opacity ?? 1);
@@ -4198,7 +4203,7 @@ export class NativeListWebEngine {
4198
4203
  'aria-label',
4199
4204
  row.accessibilityLabel ?? this.rowLabel(row)
4200
4205
  );
4201
- if (!row.disabled && !(row.type === 'system' && row.variant === 'spacer')) {
4206
+ if (isRowPressEnabled(row)) {
4202
4207
  element.tabIndex = 0;
4203
4208
  } else {
4204
4209
  element.removeAttribute('tabindex');
@@ -4932,7 +4937,7 @@ export class NativeListWebEngine {
4932
4937
  ) {
4933
4938
  // OneKey patch: missing-address rows keep their create-address accessory interactive.
4934
4939
  // if (row.disabled) return;
4935
- if (row.disabled || row.pressDisabled) return;
4940
+ if (!isRowPressEnabled(row)) return;
4936
4941
  if (
4937
4942
  this.snapshot.selection?.rowPressToggles &&
4938
4943
  this.snapshot.selection.mode !== 'none' &&
@@ -4977,7 +4982,7 @@ export class NativeListWebEngine {
4977
4982
  '[data-native-list-row-key]'
4978
4983
  );
4979
4984
  const row = this.rowAtElement(rowElement);
4980
- if (row?.type !== 'market' || row.disabled) return;
4985
+ if (row?.type !== 'market' || !isRowPressEnabled(row)) return;
4981
4986
  this.cancelMarketPointer();
4982
4987
  if (row.pressInActionKey)
4983
4988
  this.emitRowAction(