@onekeyfe/react-native-native-list 3.0.113 → 3.0.114

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -118,7 +118,6 @@ func nativeListIcon(named name: String) -> UIImage? {
118
118
  case "DragOutline": assetName = "onekey_drag"
119
119
  case "StarOutline": assetName = "onekey_star"
120
120
  case "StarSolid": assetName = "onekey_star_solid"
121
- case "BadgeVerifiedSolid": assetName = "onekey_badge_verified_solid"
122
121
  case "ChevronGrabberVerOutline": assetName = "onekey_chevron_grabber_ver"
123
122
  case "ChevronBottomOutline": assetName = "onekey_chevron_bottom"
124
123
  case "ChevronTopOutline": assetName = "onekey_chevron_top"
@@ -132,10 +131,3 @@ func nativeListIcon(named name: String) -> UIImage? {
132
131
  return UIImage(named: assetName, in: NativeListResources.bundle, compatibleWith: nil)?
133
132
  .withRenderingMode(["GoogleIllus", "BotIllus", "AccountErrorCustom"].contains(name) ? .alwaysOriginal : .alwaysTemplate)
134
133
  }
135
-
136
- func nativeListIcon(named name: String, size: CGSize) -> UIImage? {
137
- guard let image = nativeListIcon(named: name) else { return nil }
138
- return UIGraphicsImageRenderer(size: size).image { _ in
139
- image.draw(in: CGRect(origin: .zero, size: size))
140
- }.withRenderingMode(.alwaysTemplate)
141
- }
@@ -83,10 +83,6 @@ final class NativeListView: UIView {
83
83
  target: self,
84
84
  action: #selector(reorderLongPressChanged(_:))
85
85
  )
86
- private lazy var marketLongPress = UILongPressGestureRecognizer(
87
- target: self,
88
- action: #selector(marketLongPressChanged(_:))
89
- )
90
86
  // OneKey patch: claim only vertical drags so held rows and ancestor pagers stay responsive.
91
87
  private lazy var listBodyGestureGuard = UIPanGestureRecognizer(target: nil, action: nil)
92
88
  private var interactiveReorderSource: (key: String, index: Int)?
@@ -126,10 +122,6 @@ final class NativeListView: UIView {
126
122
  reorderLongPress.allowableMovement = ReorderAnimation.allowableMovement
127
123
  reorderLongPress.delegate = self
128
124
  collectionView.addGestureRecognizer(reorderLongPress)
129
- marketLongPress.minimumPressDuration = 0.8
130
- marketLongPress.allowableMovement = 10
131
- marketLongPress.delegate = self
132
- collectionView.addGestureRecognizer(marketLongPress)
133
125
  interactiveReorderPlaceholder.isHidden = true
134
126
  interactiveReorderPlaceholder.isUserInteractionEnabled = false
135
127
  interactiveReorderPlaceholder.layer.cornerRadius = ReorderAnimation.placeholderRadius
@@ -306,13 +298,8 @@ final class NativeListView: UIView {
306
298
  }
307
299
 
308
300
  var changedKeys: [String] = []
309
- var marketQuoteKeys = Set<String>()
310
301
  var sizeChanged = false
311
- let marketQuoteFields: Set<String> = [
312
- "revision", "price", "priceSegments", "change", "accessibilityLabel",
313
- ]
314
302
  for (index, changes) in pending {
315
- let previous = current.items[index]
316
303
  var merged = current.items[index].data
317
304
  changes.forEach { key, value in
318
305
  if key != "key" && key != "type" { merged[key] = value }
@@ -320,30 +307,14 @@ final class NativeListView: UIView {
320
307
  guard let item = try? NativeListItem(data: merged) else { return }
321
308
  if rowHeight(current.items[index]) != rowHeight(item) { sizeChanged = true }
322
309
  current.items[index] = item
323
- if previous.type == "market", Set(changes.keys).isSubset(of: marketQuoteFields) {
324
- marketQuoteKeys.insert(item.key)
325
- } else {
326
- changedKeys.append(item.key)
327
- }
310
+ changedKeys.append(item.key)
328
311
  if let selected = changes["selected"] as? Bool {
329
312
  if selected { current.selectedKeys.insert(item.key) } else { current.selectedKeys.remove(item.key) }
330
313
  }
331
314
  }
332
- if !changedKeys.isEmpty { invalidateActionAnchor(reason: "snapshot") }
315
+ invalidateActionAnchor(reason: "snapshot")
333
316
  config = current
334
317
  itemsByKey = Dictionary(uniqueKeysWithValues: current.items.map { ($0.key, $0) })
335
- for indexPath in collectionView.indexPathsForVisibleItems {
336
- guard let item = current.items[safe: indexPath.item],
337
- marketQuoteKeys.contains(item.key),
338
- let cell = collectionView.cellForItem(at: indexPath) as? NativeListCell else { continue }
339
- cell.updateMarketQuote(item, theme: current.theme)
340
- }
341
- if changedKeys.isEmpty {
342
- configureFooter(current)
343
- emitVisibleRangeIfNeeded()
344
- checkEndReached()
345
- return
346
- }
347
318
  var snapshot = dataSource.snapshot()
348
319
  snapshot.reconfigureItems(changedKeys.filter { snapshot.indexOfItem($0) != nil })
349
320
  dataSource.apply(snapshot, animatingDifferences: false) { [weak self] in
@@ -1014,9 +985,7 @@ final class NativeListView: UIView {
1014
985
  updateSelection(target: NativeSelectionTarget(scope: "row", key: item.key), sourceKey: item.key)
1015
986
  return
1016
987
  }
1017
- if item.type == "market", !item.data.string("pressActionKey").isEmpty {
1018
- emit(onRowAction, rowActionPayload(item: item, actionKey: item.data.string("pressActionKey"), origin: origin))
1019
- } else if item.type == "action" {
988
+ if item.type == "action" {
1020
989
  emit(onRowAction, rowActionPayload(item: item, actionKey: item.data.string("actionKey"), origin: origin))
1021
990
  } else if item.type == "system", item.data.string("variant") == "retry" {
1022
991
  emit(onRowAction, rowActionPayload(item: item, actionKey: item.data.string("actionKey"), origin: origin))
@@ -1025,19 +994,6 @@ final class NativeListView: UIView {
1025
994
  }
1026
995
  }
1027
996
 
1028
- @objc private func marketLongPressChanged(_ gesture: UILongPressGestureRecognizer) {
1029
- guard gesture.state == .began else { return }
1030
- let point = gesture.location(in: collectionView)
1031
- guard let indexPath = collectionView.indexPathForItem(at: point),
1032
- let item = config?.items[safe: indexPath.item],
1033
- item.type == "market",
1034
- !item.data.bool("disabled") else { return }
1035
- let actionKey = item.data.string("longPressActionKey")
1036
- guard !actionKey.isEmpty else { return }
1037
- let origin = (collectionView.cellForItem(at: indexPath) as? NativeListCell)?.rowActionOrigin()
1038
- handleAction(item: item, actionKey: actionKey, target: nil, origin: origin)
1039
- }
1040
-
1041
997
  private func handleAction(
1042
998
  item: NativeListItem,
1043
999
  actionKey: String,
@@ -1311,18 +1267,10 @@ final class NativeListView: UIView {
1311
1267
  ? 56
1312
1268
  : config?.layout == "linear" ? 30 : 36
1313
1269
  case "system":
1314
- if item.data.string("variant") == "loading" && item.data.string("loadingStyle") == "skeleton" {
1315
- base = 56
1316
- } else if item.data.string("variant") == "loading" && item.data.string("loadingStyle") == "spinner" {
1317
- base = 52
1318
- } else if item.data.string("presentation") == "market" {
1319
- base = item.data.string("variant") == "loading" ? 68 : 44
1320
- } else {
1321
- switch item.data.string("variant") {
1322
- case "noMatch", "end": base = 36
1323
- case "retry": base = 44
1324
- default: base = 56
1325
- }
1270
+ switch item.data.string("variant") {
1271
+ case "noMatch", "end": base = 36
1272
+ case "retry": base = 44
1273
+ default: base = 56
1326
1274
  }
1327
1275
  case "action":
1328
1276
  base = item.data.string("presentation") == "accountSelector"
@@ -1332,14 +1280,6 @@ final class NativeListView: UIView {
1332
1280
  base = item.data.dictionaries("columns").contains {
1333
1281
  !$0.string("secondaryText").isEmpty
1334
1282
  } ? 60 : 56
1335
- case "market":
1336
- let style = item.data.dictionary("style")
1337
- let imageHeight = CGFloat(style?.dictionary("image")?.double(
1338
- "height",
1339
- default: item.data.string("variant") == "stock" ? 40 : 32
1340
- ) ?? (item.data.string("variant") == "stock" ? 40 : 32))
1341
- let verticalPadding = CGFloat(style?.double("verticalPadding", default: 12) ?? 12)
1342
- base = max(item.data.string("variant") == "stock" ? 72 : 68, imageHeight + verticalPadding * 2)
1343
1283
  default:
1344
1284
  if item.type == "identity", !item.data.string("tertiary").isEmpty {
1345
1285
  base = 72
@@ -1550,16 +1490,6 @@ final class NativeListView: UIView {
1550
1490
  }
1551
1491
 
1552
1492
  override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
1553
- if gestureRecognizer === reorderLongPress || gestureRecognizer === marketLongPress {
1554
- let point = gestureRecognizer.location(in: collectionView)
1555
- guard let indexPath = collectionView.indexPathForItem(at: point),
1556
- let item = item(at: indexPath),
1557
- !item.data.bool("disabled") else { return false }
1558
- if gestureRecognizer === reorderLongPress {
1559
- return config?.reorderable == true && item.isReorderable
1560
- }
1561
- return item.type == "market" && !item.data.string("longPressActionKey").isEmpty
1562
- }
1563
1493
  guard gestureRecognizer === listBodyGestureGuard,
1564
1494
  let pan = gestureRecognizer as? UIPanGestureRecognizer else { return true }
1565
1495
  let velocity = pan.velocity(in: collectionView)
@@ -1678,14 +1608,6 @@ extension NativeListView: UICollectionViewDelegateFlowLayout {
1678
1608
  return !item.data.bool("disabled")
1679
1609
  }
1680
1610
 
1681
- func collectionView(_ collectionView: UICollectionView, didHighlightItemAt indexPath: IndexPath) {
1682
- guard let item = config?.items[safe: indexPath.item], item.type == "market" else { return }
1683
- let actionKey = item.data.string("pressInActionKey")
1684
- guard !actionKey.isEmpty else { return }
1685
- let origin = (collectionView.cellForItem(at: indexPath) as? NativeListCell)?.rowActionOrigin()
1686
- handleAction(item: item, actionKey: actionKey, target: nil, origin: origin)
1687
- }
1688
-
1689
1611
  func collectionView(_ collectionView: UICollectionView, shouldSelectItemAt indexPath: IndexPath) -> Bool {
1690
1612
  guard let item = config?.items[safe: indexPath.item] else { return false }
1691
1613
  return !item.data.bool("disabled")
@@ -10,7 +10,6 @@ const MAX_IMAGE_HEADERS = 32;
10
10
  const MAX_HEADER_LENGTH = 4096;
11
11
  const MAX_SPACER_HEIGHT = 512;
12
12
  const MAX_SECTION_INDEX_TITLE_LENGTH = 8;
13
- const MAX_MARKET_BADGES = 3;
14
13
  function fail(path, message) {
15
14
  throw new Error(`NativeList ${path}: ${message}`);
16
15
  }
@@ -63,105 +62,6 @@ function assertTextTone(tone, path) {
63
62
  fail(path, 'must be primary, secondary, positive, or negative');
64
63
  }
65
64
  }
66
- function assertBoundedStyleNumber(value, path, min, max) {
67
- if (value !== undefined && (!Number.isFinite(value) || value < min || value > max)) {
68
- fail(path, `must be within ${min}...${max}`);
69
- }
70
- }
71
- function assertMarketTextStyle(style, path) {
72
- if (!style) return;
73
- assertBoundedStyleNumber(style.fontSize, `${path}.fontSize`, 8, 48);
74
- assertBoundedStyleNumber(style.lineHeight, `${path}.lineHeight`, 8, 64);
75
- if (style.fontWeight !== undefined && !['regular', 'medium', 'semibold', 'bold'].includes(style.fontWeight)) {
76
- fail(`${path}.fontWeight`, 'must be regular, medium, semibold, or bold');
77
- }
78
- if (style.alignment !== undefined && !['start', 'center', 'end'].includes(style.alignment)) {
79
- fail(`${path}.alignment`, 'must be start, center, or end');
80
- }
81
- if (style.lines !== undefined && ![1, 2].includes(style.lines)) {
82
- fail(`${path}.lines`, 'must be 1 or 2');
83
- }
84
- }
85
- function assertMarketStyle(style, path) {
86
- if (!style) return;
87
- for (const field of ['horizontalPadding', 'verticalPadding', 'leadingGap', 'titleBadgeGap', 'trailingGap']) {
88
- assertBoundedStyleNumber(style[field], `${path}.${field}`, 0, 64);
89
- }
90
- assertBoundedStyleNumber(style.lineGap, `${path}.lineGap`, 0, 16);
91
- assertBoundedStyleNumber(style.changeWidth, `${path}.changeWidth`, 1, 160);
92
- assertBoundedStyleNumber(style.changeHeight, `${path}.changeHeight`, 1, 160);
93
- assertBoundedStyleNumber(style.changeCornerRadius, `${path}.changeCornerRadius`, 0, 80);
94
- if (style.image) {
95
- assertBoundedStyleNumber(style.image.width, `${path}.image.width`, 1, 160);
96
- assertBoundedStyleNumber(style.image.height, `${path}.image.height`, 1, 160);
97
- assertBoundedStyleNumber(style.image.cornerRadius, `${path}.image.cornerRadius`, 0, 80);
98
- assertVisualShape(style.image.shape, `${path}.image.shape`);
99
- if (style.image.contentFit !== undefined && !['cover', 'contain', 'fill', 'center'].includes(style.image.contentFit)) {
100
- fail(`${path}.image.contentFit`, 'must be cover, contain, fill, or center');
101
- }
102
- }
103
- assertMarketTextStyle(style.title, `${path}.title`);
104
- assertMarketTextStyle(style.subtitle, `${path}.subtitle`);
105
- assertMarketTextStyle(style.price, `${path}.price`);
106
- assertMarketTextStyle(style.change, `${path}.change`);
107
- }
108
- function assertMarketRow(row, path) {
109
- if (!['token', 'stock', 'perp'].includes(row.variant)) {
110
- fail(`${path}.variant`, 'must be token, stock, or perp');
111
- }
112
- assertText(row.title, `${path}.title`);
113
- assertText(row.subtitle, `${path}.subtitle`);
114
- assertText(row.price, `${path}.price`);
115
- assertText(row.change.text, `${path}.change.text`);
116
- assertLeadingVisual(row.leading, `${path}.leading`);
117
- const assertSegments = (segments, segmentPath) => {
118
- segments?.forEach((segment, index) => {
119
- assertText(segment.text, `${segmentPath}[${index}].text`);
120
- if (segment.style !== undefined && segment.style !== 'subscript') {
121
- fail(`${segmentPath}[${index}].style`, 'must be subscript when provided');
122
- }
123
- });
124
- };
125
- assertSegments(row.subtitleSegments, `${path}.subtitleSegments`);
126
- assertSegments(row.priceSegments, `${path}.priceSegments`);
127
- assertSegments(row.change.textSegments, `${path}.change.textSegments`);
128
- if (!['positive', 'negative', 'neutral'].includes(row.change.tone)) {
129
- fail(`${path}.change.tone`, 'must be positive, negative, or neutral');
130
- }
131
- if ((row.badges?.length ?? 0) > MAX_MARKET_BADGES) {
132
- fail(`${path}.badges`, `supports at most ${MAX_MARKET_BADGES} badges`);
133
- }
134
- const badgeKeys = new Set();
135
- row.badges?.forEach((badge, index) => {
136
- const badgePath = `${path}.badges[${index}]`;
137
- assertKey(badge.key, `${badgePath}.key`);
138
- if (badgeKeys.has(badge.key)) {
139
- fail(`${path}.badges`, `duplicate badge key "${badge.key}"`);
140
- }
141
- badgeKeys.add(badge.key);
142
- assertText(badge.text, `${badgePath}.text`);
143
- if (badge.iconName !== undefined && badge.iconName !== 'verified') {
144
- fail(`${badgePath}.iconName`, 'must be verified when provided');
145
- }
146
- if (badge.iconName !== undefined && badge.icon !== undefined) {
147
- fail(`${badgePath}.icon`, 'cannot be combined with iconName');
148
- }
149
- assertImage(badge.icon, `${badgePath}.icon`);
150
- if (badge.tone !== undefined && !['neutral', 'info', 'success', 'warning', 'danger'].includes(badge.tone)) {
151
- fail(`${badgePath}.tone`, 'must be neutral, info, success, warning, or danger');
152
- }
153
- if (!badge.text && !badge.icon && !badge.iconName) {
154
- fail(badgePath, 'requires text, icon, or iconName');
155
- }
156
- if (badge.actionKey !== undefined) {
157
- assertKey(badge.actionKey, `${badgePath}.actionKey`);
158
- }
159
- });
160
- for (const [key, value] of [['pressActionKey', row.pressActionKey], ['pressInActionKey', row.pressInActionKey], ['longPressActionKey', row.longPressActionKey], ['diagnostics.imageBindActionKey', row.diagnostics?.imageBindActionKey]]) {
161
- if (value !== undefined) assertKey(value, `${path}.${key}`);
162
- }
163
- assertMarketStyle(row.style, `${path}.style`);
164
- }
165
65
  function assertSectionHeaderVariant(variant, path) {
166
66
  if (variant !== undefined && !['summary', 'gallery', 'history'].includes(variant)) {
167
67
  fail(path, 'must be summary, gallery, or history when provided');
@@ -250,7 +150,7 @@ function assertLeadingVisual(visual, path) {
250
150
  }
251
151
  }
252
152
  function assertVisual(row, path) {
253
- const visuals = row.type === 'identity' ? [row.leading] : row.type === 'rail' ? [row.visual] : row.type === 'activity' ? [row.leading, row.secondaryLeading] : row.type === 'message' ? [row.leading] : row.type === 'dataRow' ? [row.leading] : row.type === 'market' ? [row.leading] : row.type === 'metricCard' ? [row.visual] : [];
153
+ const visuals = row.type === 'identity' ? [row.leading] : row.type === 'rail' ? [row.visual] : row.type === 'activity' ? [row.leading, row.secondaryLeading] : row.type === 'message' ? [row.leading] : row.type === 'dataRow' ? [row.leading] : row.type === 'metricCard' ? [row.visual] : [];
254
154
  visuals.forEach((visual, index) => {
255
155
  assertLeadingVisual(visual, `${path}.visual[${index}]`);
256
156
  });
@@ -362,9 +262,6 @@ function assertRow(row, index, path = `rows[${index}]`) {
362
262
  fail(`${path}.badges`, `supports at most ${MAX_BADGES} badges`);
363
263
  }
364
264
  break;
365
- case 'market':
366
- assertMarketRow(row, path);
367
- break;
368
265
  case 'mediaTile':
369
266
  assertImage(row.image, `${path}.image`);
370
267
  if (row.imageState !== undefined && !['empty', 'error'].includes(row.imageState)) {
@@ -430,19 +327,12 @@ function assertRow(row, index, path = `rows[${index}]`) {
430
327
  assertTrailingAccessories(row.trailing, `${path}.trailing`);
431
328
  break;
432
329
  case 'system':
433
- const presentation = 'presentation' in row ? row.presentation : undefined;
434
- if (presentation !== undefined && presentation !== 'market') {
435
- fail(`${path}.presentation`, 'must be market when provided');
436
- }
437
330
  if (
438
331
  // OneKey patch: deprecated-wallet warnings retain the original scrolling semantics.
439
332
  !['loading', 'retry', 'noMatch', 'end', 'spacer', 'warning'].includes(row.variant)) {
440
333
  fail(`${path}.variant`, 'must be loading, retry, noMatch, end, spacer, or warning');
441
334
  }
442
335
  if (row.variant === 'warning') assertText(row.title, `${path}.title`);
443
- if (row.variant === 'loading' && row.loadingStyle !== undefined && row.loadingStyle !== 'skeleton' && row.loadingStyle !== 'spinner') {
444
- fail(`${path}.loadingStyle`, 'must be skeleton or spinner when provided');
445
- }
446
336
  if (row.variant !== 'spacer') {
447
337
  assertText(row.message, `${path}.message`);
448
338
  }
@@ -613,24 +503,6 @@ function assertPatchChanges(patch, index) {
613
503
  fail(`${path}.badges`, `supports at most ${MAX_BADGES} badges`);
614
504
  }
615
505
  break;
616
- case 'market':
617
- assertMarketRow({
618
- type: 'market',
619
- key: patch.key,
620
- variant: 'token',
621
- leading: {
622
- kind: 'icon',
623
- name: 'placeholder'
624
- },
625
- title: '',
626
- price: '',
627
- change: {
628
- text: '',
629
- tone: 'neutral'
630
- },
631
- ...patch.changes
632
- }, path);
633
- break;
634
506
  case 'mediaTile':
635
507
  assertImage(patch.changes.image, `${path}.image`);
636
508
  if (patch.changes.imageState !== undefined && !['empty', 'error'].includes(patch.changes.imageState)) {