@onekeyfe/react-native-native-list 3.0.105 → 3.0.106
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/src/main/java/com/onekey/nativelist/NativeListAdapter.kt +16 -3
- package/android/src/main/java/com/onekey/nativelist/NativeListModels.kt +6 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListRowView.kt +671 -52
- package/android/src/main/java/com/onekey/nativelist/NativeListView.kt +282 -54
- package/ios/HybridNativeList.swift +8 -2
- package/ios/NativeListCell.swift +630 -31
- package/ios/NativeListDesignAssets.swift +24 -1
- package/ios/RNCNativeListView.swift +216 -42
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_account_error_custom.imageset/Contents.json +15 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_account_error_custom.imageset/icon.svg +14 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_all_networks_solid.imageset/Contents.json +15 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_all_networks_solid.imageset/icon.svg +12 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_apple_brand.imageset/Contents.json +15 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_apple_brand.imageset/icon.svg +6 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_bot_illus.imageset/Contents.json +15 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_bot_illus.imageset/icon.svg +15 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_crossed_small_solid.imageset/Contents.json +15 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_crossed_small_solid.imageset/icon.svg +3 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_globus_outline.imageset/Contents.json +15 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_globus_outline.imageset/icon.svg +7 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_google_illus.imageset/Contents.json +15 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_google_illus.imageset/icon.svg +18 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_lock_solid.imageset/Contents.json +15 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_selector_lock_solid.imageset/icon.svg +7 -0
- package/lib/module/NativeList.js +102 -8
- package/lib/module/NativeList.web.js +20 -2
- package/lib/module/avatarPrefetch.js +174 -0
- package/lib/module/validation.js +45 -2
- package/lib/module/web/NativeListAvatarWorker.js +542 -0
- package/lib/module/web/NativeListWebAvatarCache.js +267 -0
- package/lib/module/web/NativeListWebEngine.js +958 -47
- package/lib/typescript/src/NativeList.web.d.ts +2 -2
- package/lib/typescript/src/avatarPrefetch.d.ts +28 -0
- package/lib/typescript/src/models.d.ts +72 -4
- package/lib/typescript/src/web/NativeListWebAvatarCache.d.ts +6 -0
- package/lib/typescript/src/web/NativeListWebEngine.d.ts +10 -1
- package/package.json +2 -2
- package/src/NativeList.tsx +149 -13
- package/src/NativeList.web.tsx +30 -3
- package/src/avatarPrefetch.ts +236 -0
- package/src/models.ts +98 -7
- package/src/validation.ts +131 -2
- package/src/web/NativeListAvatarWorker.js +567 -0
- package/src/web/NativeListWebAvatarCache.ts +314 -0
- package/src/web/NativeListWebEngine.ts +1409 -60
|
@@ -3,7 +3,13 @@
|
|
|
3
3
|
import { checkboxStateForKeys, checkboxStateForSection, 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";
|
|
7
|
+
import { acquireNativeListAvatar, canonicalNativeListAvatarUri } from "./NativeListWebAvatarCache.js";
|
|
8
|
+
const SECTION_INDEX_CONTENT_INSET = 16;
|
|
9
|
+
const SECTION_INDEX_RAIL_WIDTH = 32;
|
|
10
|
+
const SECTION_INDEX_EDGE_PADDING = 8;
|
|
11
|
+
const SECTION_INDEX_MIN_LABEL_SPACING = 14;
|
|
12
|
+
const SECTION_INDEX_MIN_HEIGHT = 120;
|
|
7
13
|
const DEFAULT_VIEWPORT_WIDTH = 320;
|
|
8
14
|
const DEFAULT_VIEWPORT_HEIGHT = 640;
|
|
9
15
|
const OVERSCAN_VIEWPORTS = 1;
|
|
@@ -147,9 +153,22 @@ function approximateMessageHeight(row, availableWidth) {
|
|
|
147
153
|
return 32 + titleLines * 20 + bodyLines * 20 + 22;
|
|
148
154
|
}
|
|
149
155
|
export function estimateWebRowHeight(row, snapshot, availableWidth) {
|
|
150
|
-
|
|
151
|
-
if (row.type === '
|
|
152
|
-
if (row.
|
|
156
|
+
// OneKey patch: explicit selector height takes precedence over presets.
|
|
157
|
+
// if (row.type === 'system' && row.variant === 'spacer') return row.height;
|
|
158
|
+
if (row.height !== undefined) return row.height;
|
|
159
|
+
if (row.type === 'system' && row.variant === 'warning') {
|
|
160
|
+
const width = Math.max(1, availableWidth - 24);
|
|
161
|
+
const lines = text => Math.max(1, Math.ceil(Array.from(text).reduce((length, char) => length + (char.charCodeAt(0) > 255 ? 14 : 7), 0) / width));
|
|
162
|
+
return 32 + 20 * (lines(row.title) + lines(row.message));
|
|
163
|
+
}
|
|
164
|
+
if (row.type === 'walletGroup')
|
|
165
|
+
// OneKey patch: wallet badges participate in the outer group height.
|
|
166
|
+
// return (row.children.length + 1) * 68 + row.children.length * 12;
|
|
167
|
+
return [row.parent, ...row.children].reduce((height, member) => height + estimateWebRowHeight(member, snapshot, availableWidth), 0) + row.children.length * 12 + (row.parent.height !== undefined ? 2 : 0);
|
|
168
|
+
// OneKey patch: reserve the source badge line below wallet names.
|
|
169
|
+
// if (row.type === 'identity' && row.presentation === 'walletSidebar')
|
|
170
|
+
// return 68;
|
|
171
|
+
if (row.type === 'identity' && row.presentation === 'walletSidebar') return 68 + (row.badges?.length ? 24 : 0);
|
|
153
172
|
if (row.type === 'identity' && row.presentation === 'networkSelector') return 47;
|
|
154
173
|
if (row.type === 'identity' && row.presentation === 'accountSelector') return 58;
|
|
155
174
|
let base;
|
|
@@ -208,9 +227,10 @@ export function computeWebListLayout(snapshot, viewportWidth, viewportHeight, co
|
|
|
208
227
|
const horizontal = snapshot.layout.orientation === 'horizontal';
|
|
209
228
|
const spacing = snapshot.layout.itemSpacing ?? 0;
|
|
210
229
|
const padding = paddingValues(snapshot);
|
|
211
|
-
const indexGutter = sectionIndexEnabled(snapshot) ? SECTION_INDEX_GUTTER : 0;
|
|
212
230
|
const width = Math.max(1, viewportWidth || DEFAULT_VIEWPORT_WIDTH);
|
|
213
231
|
const height = Math.max(1, viewportHeight || DEFAULT_VIEWPORT_HEIGHT);
|
|
232
|
+
// OneKey patch: the index overlays the content and only keeps a small accessory-safe inset.
|
|
233
|
+
const indexGutter = sectionIndexEnabled(snapshot) && height >= SECTION_INDEX_MIN_HEIGHT ? SECTION_INDEX_CONTENT_INSET : 0;
|
|
214
234
|
const availableWidth = Math.max(1, width - padding.horizontal * 2 - indexGutter);
|
|
215
235
|
const availableHeight = Math.max(1, height - padding.top - padding.bottom);
|
|
216
236
|
const items = [];
|
|
@@ -371,7 +391,10 @@ function rowWithoutSelectionState(row) {
|
|
|
371
391
|
export function webRowRenderSignature(row) {
|
|
372
392
|
return JSON.stringify(rowWithoutSelectionState(row));
|
|
373
393
|
}
|
|
394
|
+
|
|
395
|
+
// OneKey patch: selector names must shrink before the sidebar clips their contents.
|
|
374
396
|
export const WEB_LIST_CSS = `
|
|
397
|
+
[data-native-list-selector="walletSidebar"] .ok-native-list-title{max-width:100%;min-width:0}
|
|
375
398
|
.ok-native-list-root{--nl-bg:#f7f7f7;--nl-row:#fff;--nl-selected:#eaf2ff;--nl-pressed:#e8e8e8;--nl-subdued:#f9f9f9;--nl-strong:#0000000f;--nl-primary:#111;--nl-secondary:#6b7280;--nl-disabled:#8d8d8d;--nl-icon:#111;--nl-icon-subdued:#8d8d8d;--nl-separator:#e5e7eb;--nl-accent:#2f6bff;--nl-positive:#15803d;--nl-negative:#dc2626;--nl-critical:#feecec;--nl-inverse:#202020;--nl-inverse-text:#fcfcfc;--nl-info:#0d74ce;position:absolute;inset:0;display:flex;min-width:0;min-height:0;overflow:hidden;background:var(--nl-bg);color:var(--nl-primary);font-family:Roobert,-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;font-synthesis:none}
|
|
376
399
|
.ok-native-list-viewport-frame{position:relative;flex:1;min-width:0;min-height:0;overflow:hidden}
|
|
377
400
|
.ok-native-list-viewport{position:absolute;inset:0;overflow:auto;overscroll-behavior:contain;-webkit-overflow-scrolling:touch;scrollbar-gutter:stable}
|
|
@@ -382,6 +405,7 @@ export const WEB_LIST_CSS = `
|
|
|
382
405
|
.ok-native-list-item[data-native-list-selected="true"]>.ok-native-list-row{background:var(--nl-selected)}
|
|
383
406
|
.ok-native-list-item[data-native-list-disabled="true"]>.ok-native-list-row{opacity:.5;cursor:default}
|
|
384
407
|
.ok-native-list-item:not([data-native-list-disabled="true"]):hover>.ok-native-list-row{background:var(--nl-pressed)}
|
|
408
|
+
.ok-native-list-item:not([data-native-list-disabled="true"]):active>.ok-native-list-row{background:var(--nl-pressed)}
|
|
385
409
|
.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)}
|
|
386
410
|
.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)}
|
|
387
411
|
.ok-native-list-item[data-native-list-selected="true"]:hover>.ok-native-list-wallet-row{background:var(--nl-selected)}
|
|
@@ -424,9 +448,29 @@ export const WEB_LIST_CSS = `
|
|
|
424
448
|
.ok-native-list-media{display:block;padding:0 5px;background:transparent;border-radius:16px}.ok-native-list-media-image{display:block;width:100%;aspect-ratio:1;border-radius:10px;background:var(--nl-strong);object-fit:cover}.ok-native-list-media-image[data-state="empty"]{background:transparent}.ok-native-list-media-image[data-state="error"]{display:flex;align-items:center;justify-content:center;color:var(--nl-icon-subdued);font-size:24px}.ok-native-list-media-meta{padding-top:7px}.ok-native-list-media-subtitle-row{display:flex;align-items:center;gap:6px}.ok-native-list-media-subtitle{flex:1;min-width:0;font-size:12px;color:var(--nl-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ok-native-list-media-network{width:14px;height:14px;border-radius:50%}.ok-native-list-media-title{font-size:16px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ok-native-list-media-close{position:absolute;right:9px;top:4px;border:0;background:color-mix(in srgb,var(--nl-inverse) 72%,transparent);color:var(--nl-inverse-text);width:24px;height:24px;border-radius:50%;font:18px/20px inherit;cursor:pointer}
|
|
425
449
|
.ok-native-list-metric{display:flex;flex-direction:column;align-items:flex-start;padding:12px;border-radius:12px;gap:5px;background:var(--nl-row)}.ok-native-list-metric-value{font-size:22px;line-height:28px;font-weight:700}.ok-native-list-composite{display:flex;flex-direction:column;align-items:stretch;padding:14px;border-radius:12px;gap:12px;background:var(--nl-subdued)}.ok-native-list-composite-heading{font-size:14px;letter-spacing:1px;color:var(--nl-secondary)}.ok-native-list-composite-row{display:flex;gap:12px}.ok-native-list-composite-cell{flex:1;min-width:0}.ok-native-list-composite-cell[data-shaded="true"]{padding:10px;border-radius:10px;background:color-mix(in srgb,var(--nl-primary) 5%,transparent)}.ok-native-list-composite-value{font-size:18px;font-weight:600}.ok-native-list-divider{height:1px;background:var(--nl-separator)}.ok-native-list-progress{height:4px;border-radius:2px;overflow:hidden;background:var(--nl-negative)}.ok-native-list-progress>span{display:block;height:100%;border-radius:2px;background:var(--nl-positive)}
|
|
426
450
|
.ok-native-list-data{padding:6px 12px}.ok-native-list-index{flex:0 0 28px;color:var(--nl-secondary);font-size:13px}.ok-native-list-favorite{flex:0 0 24px;color:var(--nl-icon-subdued);font-size:22px}.ok-native-list-favorite[data-active="true"]{color:var(--nl-accent)}.ok-native-list-data-cell{display:flex;flex-direction:column;min-width:0}.ok-native-list-data-cell[data-align="center"]{align-items:center}.ok-native-list-data-cell[data-align="end"]{align-items:flex-end}.ok-native-list-data-primary{display:flex;align-items:center;gap:5px;max-width:100%;font-size:16px;font-weight:500;white-space:nowrap}.ok-native-list-unread{width:7px;height:7px;flex:0 0 7px;border-radius:50%;background:var(--nl-accent)}.ok-native-list-thumbnail{width:64px;height:64px;border-radius:10px;object-fit:cover}
|
|
427
|
-
.ok-native-list-footer{flex:0 0 auto;min-height:0}.ok-native-list-sticky{position:absolute;z-index:4;left:0;right:0;top:0;pointer-events:auto;box-shadow:0 1px 0 var(--nl-separator)}.ok-native-list-index-rail{position:absolute;z-index:6;top:0;right:0;bottom:0;width
|
|
451
|
+
.ok-native-list-footer{flex:0 0 auto;min-height:0}.ok-native-list-sticky{position:absolute;z-index:4;left:0;right:0;top:0;pointer-events:auto;box-shadow:0 1px 0 var(--nl-separator)}.ok-native-list-index-rail{position:absolute;z-index:6;top:0;right:0;bottom:0;width:${SECTION_INDEX_RAIL_WIDTH}px;touch-action:none;cursor:pointer}.ok-native-list-index-rail[hidden]{display:none}.ok-native-list-index-button{appearance:none;position:absolute;left:6px;display:flex;width:20px;height:16px;align-items:center;justify-content:center;padding:0;transform:translateY(-50%);border:0;border-radius:8px;background:transparent;color:var(--nl-secondary);font:600 10px/1 inherit;cursor:pointer}.ok-native-list-index-button[data-active="true"]{background:var(--nl-accent);color:var(--nl-inverse-text)}.ok-native-list-index-button:focus-visible{outline:2px solid var(--nl-accent);outline-offset:1px}.ok-native-list-index-preview{position:absolute;z-index:8;right:40px;top:50%;display:flex;width:48px;height:48px;align-items:center;justify-content:center;transform:translateY(-50%) scale(.92);border-radius:14px;background:var(--nl-inverse);color:var(--nl-inverse-text);font-size:22px;font-weight:600;opacity:0;pointer-events:none;transition:opacity .15s ease,transform .15s ease}.ok-native-list-index-preview[data-visible="true"]{opacity:1;transform:translateY(-50%) scale(1)}
|
|
428
452
|
.ok-native-list-refresh{position:absolute;z-index:7;left:50%;top:8px;display:flex;align-items:center;gap:6px;padding:6px 10px;border-radius:999px;background:var(--nl-inverse);color:var(--nl-inverse-text);font-size:12px;opacity:0;transform:translate(-50%,-16px);transition:opacity .15s ease,transform .15s ease;pointer-events:none}.ok-native-list-refresh[data-visible="true"]{opacity:1;transform:translate(-50%,0)}
|
|
453
|
+
.ok-native-list-warning{height:auto;display:flex;flex-direction:column;align-items:stretch;gap:4px;padding:14px 12px;border-top:1px solid;border-bottom:1px solid;box-sizing:border-box;cursor:default}.ok-native-list-warning-title,.ok-native-list-warning-message{font-size:14px;line-height:20px;white-space:normal;overflow-wrap:anywhere}.ok-native-list-warning-title{font-weight:500;color:var(--nl-primary)}.ok-native-list-warning-message{font-weight:400;color:var(--nl-secondary)}
|
|
454
|
+
.ok-native-list-subtitle-segments{display:flex;align-items:center;min-width:0;max-width:100%;height:20px}.ok-native-list-subtitle-segments>.ok-native-list-secondary{flex:0 1 auto;min-width:0}.ok-native-list-subtitle-dot{flex:0 0 4px;width:4px;height:4px;margin:0 6px;border-radius:50%;background:var(--nl-disabled)}.ok-native-list-wallet-row>.ok-native-list-flex{flex:0 1 auto;width:100%;align-items:center}.ok-native-list-wallet-badges{display:flex;gap:4px;justify-content:center;margin-top:4px;height:20px;max-width:100%}.ok-native-list-wallet-badges>.ok-native-list-badge{background:var(--nl-strong);color:var(--nl-secondary);font-size:12px;line-height:16px;height:20px;box-sizing:border-box;padding:2px 4px}.ok-native-list-visual-overlay{position:absolute;display:flex;align-items:center;justify-content:center;box-sizing:border-box;border-radius:50%;overflow:hidden;line-height:1;font-size:10px}.ok-native-list-visual-overlay img,.ok-native-list-visual-overlay svg{width:100%;height:100%;object-fit:contain}
|
|
429
455
|
@media (prefers-reduced-motion:reduce){.ok-native-list-index-preview,.ok-native-list-refresh{transition:none}.ok-native-list-spinner{animation:none}}
|
|
456
|
+
/* OneKey patch: selector controls follow their original semantic colors and geometry. */
|
|
457
|
+
.ok-native-list-checkbox[data-selector="networkSelector"]{padding:0;border-radius:4px;border-color:var(--nl-checkbox-border,var(--nl-separator));background:var(--nl-checkbox-icon,var(--nl-inverse-text))}
|
|
458
|
+
.ok-native-list-checkbox[data-selector="networkSelector"]::after{display:none}
|
|
459
|
+
.ok-native-list-checkbox[data-selector="networkSelector"]>svg{display:none;width:16px;height:16px;color:var(--nl-checkbox-icon,var(--nl-inverse-text));flex-shrink:0}
|
|
460
|
+
.ok-native-list-checkbox[data-selector="networkSelector"][data-state="checked"],.ok-native-list-checkbox[data-selector="networkSelector"][data-state="indeterminate"]{border-color:transparent;background:var(--nl-checkbox-background,var(--nl-primary))}
|
|
461
|
+
.ok-native-list-checkbox[data-selector="networkSelector"][data-state="checked"]>svg[data-state="checked"],.ok-native-list-checkbox[data-selector="networkSelector"][data-state="indeterminate"]>svg[data-state="indeterminate"]{display:block}
|
|
462
|
+
/* OneKey patch: source WalletListItem uses four-point padding on every side. */
|
|
463
|
+
.ok-native-list-wallet-row[data-native-list-selector="walletSidebar"]{border-radius:12px;padding:4px}
|
|
464
|
+
/* OneKey patch: selected group members use the same primary title color as standalone wallets. */
|
|
465
|
+
.ok-native-list-wallet-member[data-native-list-selected="true"]>.ok-native-list-wallet-row[data-native-list-selector="walletSidebar"] .ok-native-list-title{color:var(--nl-primary)}
|
|
466
|
+
.ok-native-list-wallet-row[data-native-list-selector="walletSidebar"] .ok-native-list-wallet-badges{height:18px}
|
|
467
|
+
.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)}
|
|
468
|
+
.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)}
|
|
469
|
+
.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}
|
|
470
|
+
/* OneKey patch: AccountSelectorAccountListItem fixes the borderless Plus slot at top18/right20. */
|
|
471
|
+
.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}
|
|
472
|
+
.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}
|
|
473
|
+
.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)}
|
|
430
474
|
`;
|
|
431
475
|
function createElement(document, tag, className, text) {
|
|
432
476
|
const element = document.createElement(tag);
|
|
@@ -442,12 +486,105 @@ function safeImageUri(uri) {
|
|
|
442
486
|
if (/^(https?:|data:image\/|blob:|file:)/i.test(trimmed) || trimmed.startsWith('/')) return trimmed;
|
|
443
487
|
return undefined;
|
|
444
488
|
}
|
|
489
|
+
|
|
490
|
+
// OneKey patch: retries belong to an image binding and must not outlive recycled rows.
|
|
491
|
+
const webImageRetryCleanup = new WeakMap();
|
|
492
|
+
const webAvatarCleanup = new WeakMap();
|
|
493
|
+
const webAvatarSources = new WeakMap();
|
|
494
|
+
function disposeWebImageRetries(element) {
|
|
495
|
+
let disposed = false;
|
|
496
|
+
const images = element.matches('img') ? [element] : element.querySelectorAll('img');
|
|
497
|
+
images.forEach(image => {
|
|
498
|
+
const avatarCleanup = webAvatarCleanup.get(image);
|
|
499
|
+
const cleanup = webImageRetryCleanup.get(image);
|
|
500
|
+
if (!cleanup && !avatarCleanup) return;
|
|
501
|
+
avatarCleanup?.();
|
|
502
|
+
webAvatarCleanup.delete(image);
|
|
503
|
+
webAvatarSources.delete(image);
|
|
504
|
+
cleanup?.();
|
|
505
|
+
webImageRetryCleanup.delete(image);
|
|
506
|
+
disposed = true;
|
|
507
|
+
});
|
|
508
|
+
return disposed;
|
|
509
|
+
}
|
|
510
|
+
function configureWebImageRetry(image, source, initialUri) {
|
|
511
|
+
const fallbackUri = source.fallbackUri ? safeImageUri(source.fallbackUri) : undefined;
|
|
512
|
+
const retryLimit = Number.isFinite(source.retryTimes) ? Math.max(0, Math.floor(source.retryTimes ?? 0)) : 0;
|
|
513
|
+
if (!fallbackUri && retryLimit === 0) return;
|
|
514
|
+
const view = image.ownerDocument.defaultView;
|
|
515
|
+
let currentUri = initialUri;
|
|
516
|
+
let usedFallback = false;
|
|
517
|
+
let retryCount = 0;
|
|
518
|
+
let retryTimer;
|
|
519
|
+
let disposed = false;
|
|
520
|
+
const clearRetry = () => {
|
|
521
|
+
if (retryTimer !== undefined) view?.clearTimeout(retryTimer);
|
|
522
|
+
retryTimer = undefined;
|
|
523
|
+
};
|
|
524
|
+
const handleError = event => {
|
|
525
|
+
if (disposed || !image.isConnected || retryTimer !== undefined) {
|
|
526
|
+
event.stopImmediatePropagation();
|
|
527
|
+
return;
|
|
528
|
+
}
|
|
529
|
+
if (fallbackUri && !usedFallback && fallbackUri !== currentUri) {
|
|
530
|
+
event.stopImmediatePropagation();
|
|
531
|
+
usedFallback = true;
|
|
532
|
+
currentUri = fallbackUri;
|
|
533
|
+
image.src = currentUri;
|
|
534
|
+
return;
|
|
535
|
+
}
|
|
536
|
+
if (retryCount >= retryLimit || !view) return;
|
|
537
|
+
event.stopImmediatePropagation();
|
|
538
|
+
retryCount += 1;
|
|
539
|
+
retryTimer = view.setTimeout(() => {
|
|
540
|
+
retryTimer = undefined;
|
|
541
|
+
if (disposed || !image.isConnected) return;
|
|
542
|
+
image.removeAttribute('src');
|
|
543
|
+
image.src = currentUri;
|
|
544
|
+
}, Math.floor(Math.random() * 3) * 1000);
|
|
545
|
+
};
|
|
546
|
+
image.addEventListener('error', handleError);
|
|
547
|
+
image.addEventListener('load', clearRetry);
|
|
548
|
+
webImageRetryCleanup.set(image, () => {
|
|
549
|
+
disposed = true;
|
|
550
|
+
clearRetry();
|
|
551
|
+
image.removeEventListener('error', handleError);
|
|
552
|
+
image.removeEventListener('load', clearRetry);
|
|
553
|
+
});
|
|
554
|
+
}
|
|
555
|
+
function configureWebAvatar(image, source, uri) {
|
|
556
|
+
const dispose = acquireNativeListAvatar(image.ownerDocument, uri, resolvedUri => {
|
|
557
|
+
configureWebImageRetry(image, source, resolvedUri);
|
|
558
|
+
image.src = resolvedUri;
|
|
559
|
+
}, () => {
|
|
560
|
+
const fallbackUri = source.fallbackUri ? safeImageUri(source.fallbackUri) : undefined;
|
|
561
|
+
if (fallbackUri) {
|
|
562
|
+
configureWebImageRetry(image, source, fallbackUri);
|
|
563
|
+
image.src = fallbackUri;
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
566
|
+
const ImageEvent = image.ownerDocument.defaultView?.Event;
|
|
567
|
+
if (ImageEvent) image.dispatchEvent(new ImageEvent('error'));
|
|
568
|
+
});
|
|
569
|
+
webAvatarSources.set(image, {
|
|
570
|
+
uri,
|
|
571
|
+
source
|
|
572
|
+
});
|
|
573
|
+
webAvatarCleanup.set(image, dispose);
|
|
574
|
+
}
|
|
445
575
|
function createImage(context, source, className) {
|
|
446
|
-
const
|
|
576
|
+
const avatarUri = canonicalNativeListAvatarUri(source.uri);
|
|
577
|
+
const uri = avatarUri ?? safeImageUri(source.uri);
|
|
447
578
|
if (!uri) return undefined;
|
|
448
579
|
const image = context.document.createElement('img');
|
|
449
580
|
if (className) image.className = className;
|
|
450
|
-
|
|
581
|
+
// OneKey patch: consume recoverable errors before the visual's final fallback listener.
|
|
582
|
+
if (avatarUri) {
|
|
583
|
+
configureWebAvatar(image, source, avatarUri);
|
|
584
|
+
} else {
|
|
585
|
+
configureWebImageRetry(image, source, uri);
|
|
586
|
+
image.src = uri;
|
|
587
|
+
}
|
|
451
588
|
image.alt = '';
|
|
452
589
|
image.draggable = false;
|
|
453
590
|
image.loading = 'lazy';
|
|
@@ -455,6 +592,247 @@ function createImage(context, source, className) {
|
|
|
455
592
|
image.style.objectFit = source.contentFit === 'fill' ? 'fill' : source.contentFit ?? 'cover';
|
|
456
593
|
return image;
|
|
457
594
|
}
|
|
595
|
+
|
|
596
|
+
// OneKey patch: React Native Web paints selector images as centered CSS backgrounds.
|
|
597
|
+
// The image keeps its loading/error lifecycle; only its replaced-element pixels are hidden.
|
|
598
|
+
function paintSelectorImageBackground(image, frame, inset = 0) {
|
|
599
|
+
const paint = createElement(image.ownerDocument, 'span', 'ok-native-list-selector-image-background');
|
|
600
|
+
paint.style.cssText = 'position:absolute;pointer-events:none;border-radius:inherit;background-position:center;background-repeat:no-repeat';
|
|
601
|
+
paint.style.inset = String(inset) + 'px';
|
|
602
|
+
paint.style.backgroundSize = image.style.objectFit === 'fill' ? '100% 100%' : image.style.objectFit === 'center' ? 'auto' : image.style.objectFit;
|
|
603
|
+
image.style.opacity = '0';
|
|
604
|
+
const update = () => {
|
|
605
|
+
paint.style.backgroundImage = 'url(' + JSON.stringify(image.currentSrc || image.src) + ')';
|
|
606
|
+
};
|
|
607
|
+
image.addEventListener('load', update);
|
|
608
|
+
image.addEventListener('error', () => {
|
|
609
|
+
paint.style.backgroundImage = 'none';
|
|
610
|
+
});
|
|
611
|
+
frame.insertBefore(paint, image);
|
|
612
|
+
if (image.complete && image.naturalWidth > 0) update();
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
// OneKey patch: use source SVG paths for selector actions and wallet provider marks.
|
|
616
|
+
const selectorIcons = {
|
|
617
|
+
GlobusOutline: {
|
|
618
|
+
viewBox: '0 0 24 24',
|
|
619
|
+
paths: [{
|
|
620
|
+
d: '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',
|
|
621
|
+
fill: 'currentColor',
|
|
622
|
+
fillRule: 'evenodd',
|
|
623
|
+
opacity: 1.0
|
|
624
|
+
}]
|
|
625
|
+
},
|
|
626
|
+
LockSolid: {
|
|
627
|
+
viewBox: '0 0 24 24',
|
|
628
|
+
paths: [{
|
|
629
|
+
d: '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',
|
|
630
|
+
fill: 'currentColor',
|
|
631
|
+
fillRule: 'evenodd',
|
|
632
|
+
opacity: 1.0
|
|
633
|
+
}]
|
|
634
|
+
},
|
|
635
|
+
GoogleIllus: {
|
|
636
|
+
viewBox: '0 0 24 24',
|
|
637
|
+
paths: [{
|
|
638
|
+
d: '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',
|
|
639
|
+
fill: '#4285F4',
|
|
640
|
+
fillRule: 'nonzero',
|
|
641
|
+
opacity: 1.0
|
|
642
|
+
}, {
|
|
643
|
+
d: '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',
|
|
644
|
+
fill: '#34A853',
|
|
645
|
+
fillRule: 'nonzero',
|
|
646
|
+
opacity: 1.0
|
|
647
|
+
}, {
|
|
648
|
+
d: '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',
|
|
649
|
+
fill: '#FBBC05',
|
|
650
|
+
fillRule: 'nonzero',
|
|
651
|
+
opacity: 1.0
|
|
652
|
+
}, {
|
|
653
|
+
d: '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',
|
|
654
|
+
fill: '#EA4335',
|
|
655
|
+
fillRule: 'nonzero',
|
|
656
|
+
opacity: 1.0
|
|
657
|
+
}]
|
|
658
|
+
},
|
|
659
|
+
AppleBrand: {
|
|
660
|
+
viewBox: '0 0 16 20',
|
|
661
|
+
paths: [{
|
|
662
|
+
d: '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',
|
|
663
|
+
fill: 'currentColor',
|
|
664
|
+
fillRule: 'nonzero',
|
|
665
|
+
opacity: 1.0
|
|
666
|
+
}]
|
|
667
|
+
},
|
|
668
|
+
BotIllus: {
|
|
669
|
+
viewBox: '0 0 24 24',
|
|
670
|
+
paths: [{
|
|
671
|
+
d: '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',
|
|
672
|
+
fill: '#8897A5',
|
|
673
|
+
fillRule: 'nonzero',
|
|
674
|
+
opacity: 1.0
|
|
675
|
+
}, {
|
|
676
|
+
d: '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',
|
|
677
|
+
fill: '#3FA9F5',
|
|
678
|
+
fillRule: 'nonzero',
|
|
679
|
+
opacity: 1.0
|
|
680
|
+
}, {
|
|
681
|
+
d: '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',
|
|
682
|
+
fill: '#8897A5',
|
|
683
|
+
fillRule: 'nonzero',
|
|
684
|
+
opacity: 1.0
|
|
685
|
+
}, {
|
|
686
|
+
d: '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',
|
|
687
|
+
fill: '#8897A5',
|
|
688
|
+
fillRule: 'nonzero',
|
|
689
|
+
opacity: 1.0
|
|
690
|
+
}, {
|
|
691
|
+
d: 'M7.5 12.0a1.5 1.5 0 1 0 3.0 0a1.5 1.5 0 1 0 -3.0 0',
|
|
692
|
+
fill: '#10243E',
|
|
693
|
+
fillRule: 'nonzero',
|
|
694
|
+
opacity: 1.0
|
|
695
|
+
}, {
|
|
696
|
+
d: 'M13.5 12.0a1.5 1.5 0 1 0 3.0 0a1.5 1.5 0 1 0 -3.0 0',
|
|
697
|
+
fill: '#10243E',
|
|
698
|
+
fillRule: 'nonzero',
|
|
699
|
+
opacity: 1.0
|
|
700
|
+
}, {
|
|
701
|
+
d: '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',
|
|
702
|
+
fill: '#10243E',
|
|
703
|
+
fillRule: 'nonzero',
|
|
704
|
+
opacity: 1.0
|
|
705
|
+
}]
|
|
706
|
+
},
|
|
707
|
+
AllNetworksSolid: {
|
|
708
|
+
viewBox: '0 0 24 24',
|
|
709
|
+
paths: [{
|
|
710
|
+
d: 'M15.333 13.998a1.335 1.335 0 1 1 0 2.67 1.335 1.335 0 0 1 0-2.67',
|
|
711
|
+
fill: 'currentColor',
|
|
712
|
+
fillRule: 'nonzero',
|
|
713
|
+
opacity: 1.0
|
|
714
|
+
}, {
|
|
715
|
+
d: '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',
|
|
716
|
+
fill: 'currentColor',
|
|
717
|
+
fillRule: 'evenodd',
|
|
718
|
+
opacity: 1.0
|
|
719
|
+
}]
|
|
720
|
+
},
|
|
721
|
+
CrossedSmallSolid: {
|
|
722
|
+
viewBox: '0 0 24 24',
|
|
723
|
+
paths: [{
|
|
724
|
+
d: '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',
|
|
725
|
+
fill: 'currentColor',
|
|
726
|
+
fillRule: 'nonzero',
|
|
727
|
+
opacity: 1.0
|
|
728
|
+
}]
|
|
729
|
+
},
|
|
730
|
+
AccountErrorCustom: {
|
|
731
|
+
viewBox: '0 0 18 18',
|
|
732
|
+
paths: [{
|
|
733
|
+
d: 'M12.5 12.75a1.25 1.25 0 1 0 0-2.5 1.25 1.25 0 0 0 0 2.5',
|
|
734
|
+
fill: '#000',
|
|
735
|
+
fillRule: 'nonzero',
|
|
736
|
+
opacity: 0.447
|
|
737
|
+
}, {
|
|
738
|
+
d: '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',
|
|
739
|
+
fill: '#000',
|
|
740
|
+
fillRule: 'evenodd',
|
|
741
|
+
opacity: 0.447
|
|
742
|
+
}]
|
|
743
|
+
},
|
|
744
|
+
PlusSmallOutline: {
|
|
745
|
+
viewBox: '0 0 24 24',
|
|
746
|
+
paths: [{
|
|
747
|
+
d: 'M13 11h5v2h-5v5h-2v-5H6v-2h5V6h2z',
|
|
748
|
+
fill: 'currentColor',
|
|
749
|
+
fillRule: 'nonzero',
|
|
750
|
+
opacity: 1.0
|
|
751
|
+
}]
|
|
752
|
+
},
|
|
753
|
+
DotHorOutline: {
|
|
754
|
+
viewBox: '0 0 24 24',
|
|
755
|
+
paths: [{
|
|
756
|
+
d: 'M6 14H2v-4h4zm8 0h-4v-4h4zm8 0h-4v-4h4z',
|
|
757
|
+
fill: 'currentColor',
|
|
758
|
+
fillRule: 'nonzero',
|
|
759
|
+
opacity: 1.0
|
|
760
|
+
}]
|
|
761
|
+
},
|
|
762
|
+
ChevronRightSmallOutline: {
|
|
763
|
+
viewBox: '0 0 24 24',
|
|
764
|
+
paths: [{
|
|
765
|
+
d: 'M15.414 12 10 17.414 8.586 16l4-4-4-4L10 6.586z',
|
|
766
|
+
fill: 'currentColor',
|
|
767
|
+
fillRule: 'nonzero',
|
|
768
|
+
opacity: 1.0
|
|
769
|
+
}]
|
|
770
|
+
},
|
|
771
|
+
DragOutline: {
|
|
772
|
+
viewBox: '0 0 24 24',
|
|
773
|
+
paths: [{
|
|
774
|
+
d: 'M11 21H7v-4h4zm6 0h-4v-4h4zm-6-7H7v-4h4zm6 0h-4v-4h4zm-6-7H7V3h4zm6 0h-4V3h4z',
|
|
775
|
+
fill: 'currentColor',
|
|
776
|
+
fillRule: 'nonzero',
|
|
777
|
+
opacity: 1.0
|
|
778
|
+
}]
|
|
779
|
+
},
|
|
780
|
+
PencilOutline: {
|
|
781
|
+
viewBox: '0 0 24 24',
|
|
782
|
+
paths: [{
|
|
783
|
+
d: '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',
|
|
784
|
+
fill: 'currentColor',
|
|
785
|
+
fillRule: 'evenodd',
|
|
786
|
+
opacity: 1.0
|
|
787
|
+
}]
|
|
788
|
+
},
|
|
789
|
+
CheckboxCheckedCustom: {
|
|
790
|
+
viewBox: '0 0 16 16',
|
|
791
|
+
paths: [{
|
|
792
|
+
d: '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',
|
|
793
|
+
fill: 'currentColor',
|
|
794
|
+
fillRule: 'evenodd',
|
|
795
|
+
opacity: 1.0
|
|
796
|
+
}]
|
|
797
|
+
},
|
|
798
|
+
CheckboxIndeterminateCustom: {
|
|
799
|
+
viewBox: '0 0 16 16',
|
|
800
|
+
paths: [{
|
|
801
|
+
d: 'M4 8a1 1 0 0 1 1-1h6a1 1 0 0 1 0 2H5a1 1 0 0 1-1-1',
|
|
802
|
+
fill: 'currentColor',
|
|
803
|
+
fillRule: 'evenodd',
|
|
804
|
+
opacity: 1.0
|
|
805
|
+
}]
|
|
806
|
+
},
|
|
807
|
+
Circle: {
|
|
808
|
+
viewBox: '0 0 24 24',
|
|
809
|
+
paths: [{
|
|
810
|
+
d: 'M0 12a12 12 0 1 0 24 0a12 12 0 1 0 -24 0',
|
|
811
|
+
fill: 'currentColor',
|
|
812
|
+
fillRule: 'nonzero',
|
|
813
|
+
opacity: 1
|
|
814
|
+
}]
|
|
815
|
+
}
|
|
816
|
+
};
|
|
817
|
+
function applySelectorIcon(element, name) {
|
|
818
|
+
const icon = selectorIcons[name];
|
|
819
|
+
if (!icon) return;
|
|
820
|
+
element.textContent = '';
|
|
821
|
+
const svg = element.ownerDocument.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
822
|
+
svg.setAttribute('viewBox', icon.viewBox);
|
|
823
|
+
svg.setAttribute('width', '24');
|
|
824
|
+
svg.setAttribute('height', '24');
|
|
825
|
+
svg.setAttribute('aria-hidden', 'true');
|
|
826
|
+
icon.paths.forEach(path => {
|
|
827
|
+
const child = element.ownerDocument.createElementNS('http://www.w3.org/2000/svg', 'path');
|
|
828
|
+
child.setAttribute('d', path.d);
|
|
829
|
+
child.setAttribute('fill', path.fill);
|
|
830
|
+
child.setAttribute('fill-rule', path.fillRule);
|
|
831
|
+
child.setAttribute('fill-opacity', String(path.opacity));
|
|
832
|
+
svg.appendChild(child);
|
|
833
|
+
});
|
|
834
|
+
element.appendChild(svg);
|
|
835
|
+
}
|
|
458
836
|
function iconGlyph(name) {
|
|
459
837
|
const normalized = name.toLocaleLowerCase();
|
|
460
838
|
if (normalized.includes('chevron')) {
|
|
@@ -484,7 +862,7 @@ function visualFromRow(row) {
|
|
|
484
862
|
if (row.type === 'metricCard') return row.visual;
|
|
485
863
|
return undefined;
|
|
486
864
|
}
|
|
487
|
-
function createVisual(context, visual) {
|
|
865
|
+
function createVisual(context, visual, selectorPresentation) {
|
|
488
866
|
if (!visual) return undefined;
|
|
489
867
|
if (visual.kind === 'stackedImages') {
|
|
490
868
|
const stack = createElement(context.document, 'span', 'ok-native-list-stacked');
|
|
@@ -500,6 +878,7 @@ function createVisual(context, visual) {
|
|
|
500
878
|
if (visual.kind === 'icon') {
|
|
501
879
|
frame.style.background = visual.backgroundColor ?? 'var(--nl-strong)';
|
|
502
880
|
const fallback = createElement(context.document, 'span', 'ok-native-list-visual-fallback', iconGlyph(visual.name));
|
|
881
|
+
applySelectorIcon(fallback, visual.name);
|
|
503
882
|
if (visual.tintColor) fallback.style.color = visual.tintColor;
|
|
504
883
|
frame.appendChild(fallback);
|
|
505
884
|
return frame;
|
|
@@ -510,6 +889,7 @@ function createVisual(context, visual) {
|
|
|
510
889
|
if (image) {
|
|
511
890
|
image.className = 'ok-native-list-visual-main';
|
|
512
891
|
frame.appendChild(image);
|
|
892
|
+
if (selectorPresentation) paintSelectorImageBackground(image, frame);
|
|
513
893
|
} else {
|
|
514
894
|
frame.appendChild(createElement(context.document, 'span', 'ok-native-list-visual-fallback', 'fallbackText' in visual ? visual.fallbackText ?? '' : ''));
|
|
515
895
|
}
|
|
@@ -520,8 +900,64 @@ function createVisual(context, visual) {
|
|
|
520
900
|
const corner = createElement(context.document, 'span', 'ok-native-list-visual-corner ok-native-list-visual-fallback', iconGlyph(visual.cornerIcon.name));
|
|
521
901
|
if (visual.cornerIcon.tintColor) corner.style.color = visual.cornerIcon.tintColor;
|
|
522
902
|
if (visual.cornerIcon.backgroundColor) corner.style.background = visual.cornerIcon.backgroundColor;
|
|
903
|
+
applySelectorIcon(corner, visual.cornerIcon.name);
|
|
523
904
|
frame.appendChild(corner);
|
|
524
905
|
}
|
|
906
|
+
// OneKey patch: image failure uses the same source-derived fallback as v1.
|
|
907
|
+
if ('fallbackIcon' in visual && visual.fallbackIcon) {
|
|
908
|
+
const icon = visual.fallbackIcon;
|
|
909
|
+
const showFallback = () => {
|
|
910
|
+
if (image) {
|
|
911
|
+
disposeWebImageRetries(image);
|
|
912
|
+
image.remove();
|
|
913
|
+
}
|
|
914
|
+
frame.querySelector('.ok-native-list-visual-fallback:not(.ok-native-list-visual-corner)')?.remove();
|
|
915
|
+
const fallback = createElement(context.document, 'span', 'ok-native-list-visual-fallback');
|
|
916
|
+
applySelectorIcon(fallback, icon.name);
|
|
917
|
+
if (icon.tintColor) fallback.style.color = icon.tintColor;
|
|
918
|
+
frame.prepend(fallback);
|
|
919
|
+
};
|
|
920
|
+
if (image) image.addEventListener('error', showFallback, {
|
|
921
|
+
once: true
|
|
922
|
+
});else showFallback();
|
|
923
|
+
}
|
|
924
|
+
if ('borderStyle' in visual && visual.borderStyle === 'dashed') {
|
|
925
|
+
frame.style.border = '2px dashed ' + (visual.borderColor ?? 'var(--nl-disabled)');
|
|
926
|
+
frame.style.boxSizing = 'border-box';
|
|
927
|
+
}
|
|
928
|
+
if ('overlays' in visual) visual.overlays?.forEach(overlay => {
|
|
929
|
+
const corner = createElement(context.document, 'span', 'ok-native-list-visual-overlay', overlay.text);
|
|
930
|
+
const size = overlay.size ?? 20;
|
|
931
|
+
const isWalletText = selectorPresentation === 'walletSidebar' && !!overlay.text && !overlay.image && !overlay.name;
|
|
932
|
+
corner.style.width = isWalletText && overlay.width === undefined ? 'auto' : String(overlay.width ?? size) + 'px';
|
|
933
|
+
corner.style.height = String(overlay.height ?? (isWalletText ? 16 : size)) + 'px';
|
|
934
|
+
corner.style.padding = isWalletText ? '0 2px' : String(overlay.padding ?? 0) + 'px';
|
|
935
|
+
if (isWalletText) {
|
|
936
|
+
corner.style.fontSize = '12px';
|
|
937
|
+
corner.style.lineHeight = '16px';
|
|
938
|
+
corner.style.fontWeight = '400';
|
|
939
|
+
}
|
|
940
|
+
if (isWalletText || overlay.width !== undefined || overlay.height !== undefined) corner.style.borderRadius = '9999px';
|
|
941
|
+
const offsetX = String(-(overlay.offsetX ?? overlay.offset ?? 2)) + 'px';
|
|
942
|
+
const offsetY = String(-(overlay.offsetY ?? overlay.offset ?? 2)) + 'px';
|
|
943
|
+
corner.style.background = overlay.backgroundColor ?? 'transparent';
|
|
944
|
+
corner.style.color = overlay.tintColor ?? 'var(--nl-secondary)';
|
|
945
|
+
if (overlay.position === 'topLeft') {
|
|
946
|
+
corner.style.left = offsetX;
|
|
947
|
+
corner.style.top = offsetY;
|
|
948
|
+
} else {
|
|
949
|
+
corner.style.right = offsetX;
|
|
950
|
+
corner.style.bottom = offsetY;
|
|
951
|
+
}
|
|
952
|
+
if (overlay.image) {
|
|
953
|
+
const overlayImage = createImage(context, overlay.image);
|
|
954
|
+
if (overlayImage) {
|
|
955
|
+
corner.appendChild(overlayImage);
|
|
956
|
+
if (selectorPresentation) paintSelectorImageBackground(overlayImage, corner, overlay.padding ?? 0);
|
|
957
|
+
}
|
|
958
|
+
} else if (overlay.name) applySelectorIcon(corner, overlay.name);
|
|
959
|
+
frame.appendChild(corner);
|
|
960
|
+
});
|
|
525
961
|
return frame;
|
|
526
962
|
}
|
|
527
963
|
function toneColor(tone, fallback) {
|
|
@@ -567,6 +1003,19 @@ function createCheckbox(context, rowKey, accessory) {
|
|
|
567
1003
|
setData(element, 'checkboxFallback', accessory.state);
|
|
568
1004
|
setData(element, 'nativeListAction', accessory.actionKey ?? 'selection');
|
|
569
1005
|
setData(element, 'selectionScope', accessory.target?.scope ?? 'row');
|
|
1006
|
+
const row = context.snapshot.rows[context.itemIndex];
|
|
1007
|
+
if (row && 'presentation' in row && row.presentation === 'networkSelector') {
|
|
1008
|
+
setData(element, 'selector', 'networkSelector');
|
|
1009
|
+
for (const [state, name] of [['checked', 'CheckboxCheckedCustom'], ['indeterminate', 'CheckboxIndeterminateCustom']]) {
|
|
1010
|
+
const holder = createElement(context.document, 'span');
|
|
1011
|
+
applySelectorIcon(holder, name);
|
|
1012
|
+
const svg = holder.firstElementChild;
|
|
1013
|
+
if (svg) {
|
|
1014
|
+
svg.setAttribute('data-state', state);
|
|
1015
|
+
element.appendChild(svg);
|
|
1016
|
+
}
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
570
1019
|
if (accessory.target?.scope === 'section') setData(element, 'selectionKey', accessory.target.sectionKey);else if (accessory.target?.scope === 'row') setData(element, 'selectionKey', rowKey);
|
|
571
1020
|
return element;
|
|
572
1021
|
}
|
|
@@ -576,6 +1025,7 @@ function createIconAction(context, name, actionKey, disabled, tintColor) {
|
|
|
576
1025
|
element.setAttribute('type', 'button');
|
|
577
1026
|
element.toggleAttribute('disabled', Boolean(disabled));
|
|
578
1027
|
}
|
|
1028
|
+
applySelectorIcon(element, name);
|
|
579
1029
|
if (actionKey) setData(element, 'nativeListAction', actionKey);
|
|
580
1030
|
if (tintColor) element.style.color = tintColor;
|
|
581
1031
|
return element;
|
|
@@ -584,6 +1034,23 @@ function markActionAnchorSource(element, source, slot) {
|
|
|
584
1034
|
setData(element, 'nativeListAnchorSource', source);
|
|
585
1035
|
if (slot !== undefined) setData(element, 'nativeListAnchorSlot', slot);
|
|
586
1036
|
}
|
|
1037
|
+
|
|
1038
|
+
// OneKey patch: the compact zero-count digits share the amount baseline.
|
|
1039
|
+
function applyValueSegments(element, segments, fontSize = 16, lineHeight = 24, weight = 500) {
|
|
1040
|
+
if (!segments?.length) return;
|
|
1041
|
+
element.textContent = '';
|
|
1042
|
+
element.style.fontSize = String(fontSize) + 'px';
|
|
1043
|
+
element.style.lineHeight = String(lineHeight) + 'px';
|
|
1044
|
+
element.style.fontWeight = String(weight);
|
|
1045
|
+
segments.forEach(segment => {
|
|
1046
|
+
const span = createElement(element.ownerDocument, 'span', undefined, segment.text);
|
|
1047
|
+
if (segment.style === 'subscript') {
|
|
1048
|
+
span.style.fontSize = String(Math.ceil(fontSize * 0.6)) + 'px';
|
|
1049
|
+
span.style.lineHeight = String(fontSize) + 'px';
|
|
1050
|
+
}
|
|
1051
|
+
element.appendChild(span);
|
|
1052
|
+
});
|
|
1053
|
+
}
|
|
587
1054
|
function createAccessory(context, rowKey, accessory, slot) {
|
|
588
1055
|
if (accessory.kind === 'checkbox') {
|
|
589
1056
|
const element = createCheckbox(context, rowKey, accessory);
|
|
@@ -593,6 +1060,18 @@ function createAccessory(context, rowKey, accessory, slot) {
|
|
|
593
1060
|
if (accessory.kind === 'icon') {
|
|
594
1061
|
const element = createIconAction(context, accessory.name, accessory.actionKey, accessory.disabled, accessory.tintColor);
|
|
595
1062
|
markActionAnchorSource(element, 'trailingAccessory', slot);
|
|
1063
|
+
setData(element, 'testid', accessory.testID);
|
|
1064
|
+
if (accessory.hoverActionKey) setData(element, 'nativeListHoverAction', accessory.hoverActionKey);
|
|
1065
|
+
if (accessory.accessibilityLabel) element.setAttribute('aria-label', accessory.accessibilityLabel);
|
|
1066
|
+
const row = context.snapshot.rows[context.itemIndex];
|
|
1067
|
+
if (row && 'presentation' in row && row.presentation === 'accountSelector') {
|
|
1068
|
+
setData(element, 'nativeListAnchorInset', 7);
|
|
1069
|
+
// OneKey patch: the create-address button omits IconButton's one-point border.
|
|
1070
|
+
if (row.height !== undefined && accessory.name === 'PlusSmallOutline') {
|
|
1071
|
+
setData(element, 'nativeListAccountControl', 'createAddress');
|
|
1072
|
+
if (!accessory.tintColor) element.style.color = 'var(--nl-icon-subdued)';
|
|
1073
|
+
}
|
|
1074
|
+
}
|
|
596
1075
|
return element;
|
|
597
1076
|
}
|
|
598
1077
|
if (accessory.kind === 'spinner') {
|
|
@@ -608,6 +1087,7 @@ function createAccessory(context, rowKey, accessory, slot) {
|
|
|
608
1087
|
switch (accessory.kind) {
|
|
609
1088
|
case 'value':
|
|
610
1089
|
element.textContent = accessory.text;
|
|
1090
|
+
applyValueSegments(element, accessory.textSegments);
|
|
611
1091
|
if (accessory.secondary) element.classList.add('ok-native-list-accessory-secondary');
|
|
612
1092
|
break;
|
|
613
1093
|
case 'valuePair':
|
|
@@ -646,6 +1126,13 @@ function createAccessory(context, rowKey, accessory, slot) {
|
|
|
646
1126
|
function appendAccessories(parent, context, rowKey, accessories) {
|
|
647
1127
|
if (!accessories?.length) return;
|
|
648
1128
|
const container = createElement(context.document, 'span', 'ok-native-list-accessories');
|
|
1129
|
+
const row = context.snapshot.rows[context.itemIndex];
|
|
1130
|
+
if (row && row.height !== undefined && 'presentation' in row && row.presentation === 'networkSelector') {
|
|
1131
|
+
container.style.gap = accessories.some(accessory => accessory.kind === 'checkbox') ? '12px' : '20px';
|
|
1132
|
+
}
|
|
1133
|
+
if (row && row.height !== undefined && 'presentation' in row && row.presentation === 'accountSelector' && accessories.length === 1 && accessories[0]?.kind === 'icon' && accessories[0].name === 'PlusSmallOutline') {
|
|
1134
|
+
setData(container, 'nativeListAccountControl', 'createAddress');
|
|
1135
|
+
}
|
|
649
1136
|
accessories.forEach((accessory, slot) => container.appendChild(createAccessory(context, rowKey, accessory, slot)));
|
|
650
1137
|
parent.appendChild(container);
|
|
651
1138
|
}
|
|
@@ -673,9 +1160,83 @@ function createSectionHeader(context, row) {
|
|
|
673
1160
|
markActionAnchorSource(titleIcon, 'leadingAction');
|
|
674
1161
|
body.appendChild(titleIcon);
|
|
675
1162
|
}
|
|
676
|
-
|
|
1163
|
+
// OneKey patch: section title help has its own measurable action target.
|
|
1164
|
+
// body.appendChild(createTextColumn(context, row.title, row.subtitle));
|
|
1165
|
+
const column = createTextColumn(context, row.title, row.subtitle);
|
|
1166
|
+
const title = column.firstElementChild;
|
|
1167
|
+
title.classList.add('ok-native-list-section-title');
|
|
1168
|
+
if (row.titleActionKey) {
|
|
1169
|
+
setData(title, 'nativeListAction', row.titleActionKey);
|
|
1170
|
+
markActionAnchorSource(title, 'leadingAction');
|
|
1171
|
+
title.setAttribute('role', 'button');
|
|
1172
|
+
title.tabIndex = 0;
|
|
1173
|
+
title.style.alignSelf = 'flex-start';
|
|
1174
|
+
title.style.maxWidth = '100%';
|
|
1175
|
+
// OneKey patch: explicit network headers reserve a separate 3-point underline area.
|
|
1176
|
+
if (row.presentation !== 'networkSelector' || row.height === undefined) {
|
|
1177
|
+
title.style.textDecoration = 'underline dotted';
|
|
1178
|
+
title.style.textUnderlineOffset = '6px';
|
|
1179
|
+
}
|
|
1180
|
+
if (row.titleActionOnHover) setData(title, 'nativeListHoverAction', true);
|
|
1181
|
+
}
|
|
1182
|
+
if (row.presentation === 'networkSelector' && row.height !== undefined) {
|
|
1183
|
+
body.style.padding = row.variant === 'summary' ? '24px 12px 20px' : '0 12px';
|
|
1184
|
+
body.style.backgroundColor = 'var(--nl-bg)';
|
|
1185
|
+
body.style.gap = row.checkbox ? '12px' : '8px';
|
|
1186
|
+
title.style.fontSize = row.variant === 'summary' ? '16px' : '14px';
|
|
1187
|
+
title.style.lineHeight = row.variant === 'summary' ? '24px' : '20px';
|
|
1188
|
+
title.style.fontWeight = row.variant === 'summary' || row.titleActionKey && !row.checkbox ? '500' : '600';
|
|
1189
|
+
if (row.titleActionKey) {
|
|
1190
|
+
const text = createElement(context.document, 'span', 'ok-native-list-section-title-text', row.title);
|
|
1191
|
+
text.style.overflow = 'hidden';
|
|
1192
|
+
text.style.textOverflow = 'ellipsis';
|
|
1193
|
+
text.style.maxWidth = '100%';
|
|
1194
|
+
const dotted = context.document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
1195
|
+
dotted.setAttribute('height', '2');
|
|
1196
|
+
dotted.style.cssText = 'display:block;position:absolute;left:0;bottom:0;width:100%;height:2px;color:var(--nl-secondary)';
|
|
1197
|
+
const line = context.document.createElementNS('http://www.w3.org/2000/svg', 'line');
|
|
1198
|
+
for (const [key, value] of Object.entries({
|
|
1199
|
+
x1: '1',
|
|
1200
|
+
y1: '1',
|
|
1201
|
+
x2: '100%',
|
|
1202
|
+
y2: '1',
|
|
1203
|
+
stroke: 'currentColor',
|
|
1204
|
+
'stroke-width': '1.5',
|
|
1205
|
+
'stroke-dasharray': '0,4',
|
|
1206
|
+
'stroke-linecap': 'round'
|
|
1207
|
+
})) line.setAttribute(key, value);
|
|
1208
|
+
// OneKey patch: keep both round caps inside the original full-width viewport.
|
|
1209
|
+
const lineViewport = context.document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
|
1210
|
+
lineViewport.setAttribute('width', 'calc(100% - 1px)');
|
|
1211
|
+
lineViewport.setAttribute('height', '2');
|
|
1212
|
+
lineViewport.setAttribute('overflow', 'visible');
|
|
1213
|
+
lineViewport.appendChild(line);
|
|
1214
|
+
dotted.appendChild(lineViewport);
|
|
1215
|
+
// OneKey patch: SVG intrinsic width must not expand the title action beyond its text.
|
|
1216
|
+
title.style.display = 'block';
|
|
1217
|
+
title.style.position = 'relative';
|
|
1218
|
+
title.style.width = 'fit-content';
|
|
1219
|
+
title.style.paddingBottom = '3px';
|
|
1220
|
+
text.style.display = 'block';
|
|
1221
|
+
title.replaceChildren(text, dotted);
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
body.appendChild(column);
|
|
677
1225
|
if (row.value) {
|
|
678
1226
|
const value = createElement(context.document, row.valueActionKey ? 'button' : 'span', row.valueActionKey ? 'ok-native-list-action-button ok-native-list-section-value' : 'ok-native-list-value ok-native-list-section-value', row.value);
|
|
1227
|
+
applyValueSegments(value, row.valueSegments);
|
|
1228
|
+
if (row.presentation === 'networkSelector' && row.height !== undefined) {
|
|
1229
|
+
value.style.fontFamily = 'inherit';
|
|
1230
|
+
value.style.fontSize = '16px';
|
|
1231
|
+
value.style.lineHeight = '24px';
|
|
1232
|
+
value.style.fontWeight = '500';
|
|
1233
|
+
if (row.valueActionKey) {
|
|
1234
|
+
value.style.color = 'var(--nl-secondary)';
|
|
1235
|
+
value.style.padding = '0';
|
|
1236
|
+
value.style.flexShrink = '0';
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
if (row.valueActionTestID) setData(value, 'testid', row.valueActionTestID);
|
|
679
1240
|
if (row.valueActionKey) {
|
|
680
1241
|
value.setAttribute('type', 'button');
|
|
681
1242
|
setData(value, 'nativeListAction', row.valueActionKey);
|
|
@@ -696,6 +1257,7 @@ function createActionRow(context, row) {
|
|
|
696
1257
|
if (row.icon) body.appendChild(createVisual(context, row.icon));
|
|
697
1258
|
const title = createElement(context.document, 'span', 'ok-native-list-action-title', row.title);
|
|
698
1259
|
setData(title, 'tone', row.tone);
|
|
1260
|
+
if (row.presentation === 'accountSelector' && row.icon) title.style.fontWeight = '500';
|
|
699
1261
|
body.appendChild(title);
|
|
700
1262
|
if (row.checkbox) body.appendChild(createCheckbox(context, row.key, row.checkbox));
|
|
701
1263
|
appendAccessories(body, context, row.key, row.trailing);
|
|
@@ -704,6 +1266,13 @@ function createActionRow(context, row) {
|
|
|
704
1266
|
function createSystemRow(context, row) {
|
|
705
1267
|
const body = createElement(context.document, 'div', 'ok-native-list-row ok-native-list-system');
|
|
706
1268
|
setData(body, 'variant', row.variant);
|
|
1269
|
+
if (row.variant === 'warning') {
|
|
1270
|
+
body.classList.add('ok-native-list-warning');
|
|
1271
|
+
body.style.borderColor = row.borderColor ?? 'var(--nl-separator)';
|
|
1272
|
+
body.appendChild(createElement(context.document, 'span', 'ok-native-list-warning-title', row.title));
|
|
1273
|
+
body.appendChild(createElement(context.document, 'span', 'ok-native-list-warning-message', row.message));
|
|
1274
|
+
return body;
|
|
1275
|
+
}
|
|
707
1276
|
if (row.variant === 'loading') body.appendChild(createElement(context.document, 'span', 'ok-native-list-spinner'));
|
|
708
1277
|
const message = row.variant === 'spacer' ? '' : row.message ?? (row.variant === 'end' ? 'End' : '');
|
|
709
1278
|
if (message) body.appendChild(createElement(context.document, 'span', 'ok-native-list-secondary', message));
|
|
@@ -852,12 +1421,31 @@ function createDataRow(context, row) {
|
|
|
852
1421
|
function createIdentityActivityOrMessageRow(context, row) {
|
|
853
1422
|
const presentation = row.type === 'identity' ? row.presentation : undefined;
|
|
854
1423
|
const body = createElement(context.document, 'div', ['ok-native-list-row', 'ok-native-list-standard', row.type === 'identity' && !presentation ? 'ok-native-list-identity-row' : '', presentation === 'networkSelector' ? 'ok-native-list-network-row' : '', presentation === 'walletSidebar' ? 'ok-native-list-wallet-row' : '', presentation === 'accountSelector' ? 'ok-native-list-account-row' : ''].filter(Boolean).join(' '));
|
|
1424
|
+
setData(body, 'nativeListSelector', row.height !== undefined ? presentation : undefined);
|
|
1425
|
+
if (row.type === 'identity' && row.titleActionKey && row.titleActionOnHover) {
|
|
1426
|
+
setData(body, 'nativeListHoverAction', row.titleActionKey);
|
|
1427
|
+
markActionAnchorSource(body, 'leadingAction');
|
|
1428
|
+
}
|
|
855
1429
|
if (row.type === 'identity' && row.leadingAction) {
|
|
856
1430
|
const action = createIconAction(context, row.leadingAction.name, row.leadingAction.actionKey, row.leadingAction.disabled, row.leadingAction.tintColor);
|
|
857
1431
|
markActionAnchorSource(action, 'leadingAction');
|
|
858
1432
|
body.appendChild(action);
|
|
859
1433
|
}
|
|
860
|
-
const visual = createVisual(context, visualFromRow(row));
|
|
1434
|
+
const visual = createVisual(context, visualFromRow(row), row.height !== undefined ? presentation : undefined);
|
|
1435
|
+
if (visual && row.type === 'identity' && row.height !== undefined && row.presentation === 'walletSidebar' && 'fallbackIcon' in row.leading && row.leading.fallbackIcon?.name === 'LockSolid') {
|
|
1436
|
+
// OneKey patch: hidden-wallet locks use WalletAvatar's full 40-point icon.
|
|
1437
|
+
const icon = visual.querySelector('.ok-native-list-visual-fallback svg');
|
|
1438
|
+
if (icon) {
|
|
1439
|
+
icon.style.width = '40px';
|
|
1440
|
+
icon.style.height = '40px';
|
|
1441
|
+
}
|
|
1442
|
+
const fallback = visual.querySelector('.ok-native-list-visual-fallback');
|
|
1443
|
+
if (fallback) {
|
|
1444
|
+
fallback.style.borderRadius = '0';
|
|
1445
|
+
fallback.style.overflow = 'visible';
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
if (visual && row.type === 'identity' && row.height !== undefined && row.presentation === 'walletSidebar' && 'borderStyle' in row.leading && row.leading.borderStyle === 'dashed') visual.style.borderWidth = '1px';
|
|
861
1449
|
if (visual) body.appendChild(visual);
|
|
862
1450
|
if (row.type === 'activity' && row.secondaryLeading) {
|
|
863
1451
|
const secondVisual = createVisual(context, row.secondaryLeading);
|
|
@@ -866,7 +1454,46 @@ function createIdentityActivityOrMessageRow(context, row) {
|
|
|
866
1454
|
if (row.type === 'message' && row.unread) body.appendChild(createElement(context.document, 'span', 'ok-native-list-unread'));
|
|
867
1455
|
const title = row.title;
|
|
868
1456
|
const subtitle = row.type === 'identity' ? row.subtitle : row.type === 'activity' ? row.description : row.body;
|
|
869
|
-
const column = createTextColumn(context, title, subtitle, row.type === 'identity' ? row.tertiary : undefined, row.type === 'identity' ? row.tertiaryTone : undefined, row.type === 'identity' ? row.badges : undefined);
|
|
1457
|
+
const column = createTextColumn(context, title, subtitle, row.type === 'identity' ? row.tertiary : undefined, row.type === 'identity' ? row.tertiaryTone : undefined, row.type === 'identity' && presentation !== 'walletSidebar' ? row.badges : undefined);
|
|
1458
|
+
// OneKey patch: match existing search, subtitle fragments, and sidebar badges.
|
|
1459
|
+
if (row.type === 'identity') {
|
|
1460
|
+
const titleElement = column.firstElementChild;
|
|
1461
|
+
if (row.titleMatch?.length) {
|
|
1462
|
+
const firstText = titleElement.firstChild;
|
|
1463
|
+
if (firstText) firstText.remove();
|
|
1464
|
+
const fragment = context.document.createDocumentFragment();
|
|
1465
|
+
let offset = 0;
|
|
1466
|
+
row.titleMatch.forEach(({
|
|
1467
|
+
start,
|
|
1468
|
+
end
|
|
1469
|
+
}) => {
|
|
1470
|
+
fragment.appendChild(context.document.createTextNode(row.title.slice(offset, start)));
|
|
1471
|
+
const match = createElement(context.document, 'span', 'ok-native-list-info', row.title.slice(start, end));
|
|
1472
|
+
fragment.appendChild(match);
|
|
1473
|
+
offset = end;
|
|
1474
|
+
});
|
|
1475
|
+
fragment.appendChild(context.document.createTextNode(row.title.slice(offset)));
|
|
1476
|
+
titleElement.prepend(fragment);
|
|
1477
|
+
}
|
|
1478
|
+
if (row.subtitleSegments?.length) {
|
|
1479
|
+
column.querySelector('.ok-native-list-secondary')?.remove();
|
|
1480
|
+
const segments = createElement(context.document, 'span', 'ok-native-list-subtitle-segments');
|
|
1481
|
+
row.subtitleSegments.forEach(segment => {
|
|
1482
|
+
if (segment.separatorBefore) segments.appendChild(createElement(context.document, 'span', 'ok-native-list-subtitle-dot'));
|
|
1483
|
+
const text = createElement(context.document, 'span', 'ok-native-list-secondary', segment.text);
|
|
1484
|
+
applyValueSegments(text, segment.textSegments, 14, 20, 400);
|
|
1485
|
+
setData(text, 'tone', segment.tone);
|
|
1486
|
+
text.style.color = segment.tone === 'disabled' ? 'var(--nl-disabled)' : segment.tone === 'caution' ? 'var(--nl-caution)' : toneColor(segment.tone, 'secondary');
|
|
1487
|
+
segments.appendChild(text);
|
|
1488
|
+
});
|
|
1489
|
+
column.insertBefore(segments, titleElement.nextSibling);
|
|
1490
|
+
}
|
|
1491
|
+
if (presentation === 'walletSidebar' && row.badges?.length) {
|
|
1492
|
+
const badges = createElement(context.document, 'span', 'ok-native-list-wallet-badges');
|
|
1493
|
+
row.badges.forEach(badge => badges.appendChild(createBadge(context, badge)));
|
|
1494
|
+
column.appendChild(badges);
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
870
1497
|
if (row.type === 'activity' && row.status) column.appendChild(createElement(context.document, 'span', 'ok-native-list-secondary', row.status));
|
|
871
1498
|
if (row.type === 'activity' && row.footerActions?.length) {
|
|
872
1499
|
const actions = createElement(context.document, 'span', 'ok-native-list-actions');
|
|
@@ -898,14 +1525,32 @@ function createIdentityActivityOrMessageRow(context, row) {
|
|
|
898
1525
|
}
|
|
899
1526
|
return body;
|
|
900
1527
|
}
|
|
1528
|
+
|
|
1529
|
+
// OneKey patch: SizableText enables tabular digits without replacing its font family.
|
|
1530
|
+
function applySelectorTabularNumbers(body, row) {
|
|
1531
|
+
if (!('presentation' in row) || !['accountSelector', 'networkSelector', 'walletSidebar'].includes(row.presentation ?? '')) return;
|
|
1532
|
+
body.style.fontVariantNumeric = 'tabular-nums';
|
|
1533
|
+
body.querySelectorAll('span,button').forEach(text => {
|
|
1534
|
+
text.style.fontVariantNumeric = 'tabular-nums';
|
|
1535
|
+
});
|
|
1536
|
+
}
|
|
901
1537
|
function createWalletGroupRow(context, row) {
|
|
902
1538
|
const body = createElement(context.document, 'div', 'ok-native-list-wallet-group');
|
|
903
1539
|
[row.parent, ...row.children].forEach((member, memberIndex) => {
|
|
904
1540
|
const memberElement = createElement(context.document, 'div', 'ok-native-list-wallet-member');
|
|
905
1541
|
setData(memberElement, 'nativeListGroupMemberKey', member.key);
|
|
1542
|
+
setData(memberElement, 'testid', member.testID);
|
|
906
1543
|
setData(memberElement, 'nativeListGroupParent', memberIndex === 0);
|
|
907
1544
|
setData(memberElement, 'nativeListSelected', member.selected);
|
|
908
|
-
|
|
1545
|
+
// OneKey patch: grouped members have the same selector typography as standalone wallets.
|
|
1546
|
+
// memberElement.appendChild(createIdentityActivityOrMessageRow(context, member));
|
|
1547
|
+
const memberBody = createIdentityActivityOrMessageRow(context, member);
|
|
1548
|
+
applySelectorTabularNumbers(memberBody, member);
|
|
1549
|
+
memberElement.appendChild(memberBody);
|
|
1550
|
+
// OneKey patch: group children use their own measured badge height.
|
|
1551
|
+
memberElement.style.flexBasis = String(member.height ?? 68 + (member.badges?.length ? 24 : 0)) + 'px';
|
|
1552
|
+
memberElement.style.height = memberElement.style.flexBasis;
|
|
1553
|
+
memberElement.style.opacity = String(member.opacity ?? 1);
|
|
909
1554
|
body.appendChild(memberElement);
|
|
910
1555
|
});
|
|
911
1556
|
return body;
|
|
@@ -945,6 +1590,11 @@ export class NativeListWebEngine {
|
|
|
945
1590
|
};
|
|
946
1591
|
mounted = new Map();
|
|
947
1592
|
pool = [];
|
|
1593
|
+
// OneKey patch: URI leases outlive DOM overscan only inside this bounded window.
|
|
1594
|
+
avatarLeases = new Map();
|
|
1595
|
+
avatarOffset = 0;
|
|
1596
|
+
avatarDirection = 1;
|
|
1597
|
+
sectionIndexEntries = [];
|
|
948
1598
|
suppressClickUntil = 0;
|
|
949
1599
|
pullDistance = 0;
|
|
950
1600
|
actionAnchorInstanceId = String(++webNativeListInstanceCounter);
|
|
@@ -953,6 +1603,8 @@ export class NativeListWebEngine {
|
|
|
953
1603
|
lastViewportWidth = -1;
|
|
954
1604
|
lastViewportHeight = -1;
|
|
955
1605
|
destroyed = false;
|
|
1606
|
+
// OneKey patch: warning banners are measured after normal browser text wrapping.
|
|
1607
|
+
measuredWarningHeights = new Map();
|
|
956
1608
|
constructor(host, snapshot, callbacks, virtualizationEnabled = true) {
|
|
957
1609
|
this.document = host.ownerDocument;
|
|
958
1610
|
this.snapshot = validateSnapshot(snapshot);
|
|
@@ -991,6 +1643,9 @@ export class NativeListWebEngine {
|
|
|
991
1643
|
passive: true
|
|
992
1644
|
});
|
|
993
1645
|
this.root.addEventListener('click', this.handleClick);
|
|
1646
|
+
// OneKey patch: preserve web tooltip hover for section titles.
|
|
1647
|
+
this.root.addEventListener('pointerover', this.handleTitlePointerOver);
|
|
1648
|
+
this.root.addEventListener('pointerout', this.handleTitlePointerOut);
|
|
994
1649
|
this.root.addEventListener('keydown', this.handleKeyDown);
|
|
995
1650
|
this.viewport.addEventListener('pointerdown', this.handleReorderPointerDown, {
|
|
996
1651
|
passive: false
|
|
@@ -1125,7 +1780,7 @@ export class NativeListWebEngine {
|
|
|
1125
1780
|
scrollToLocation(params, scroll) {
|
|
1126
1781
|
const index = resolveLocationIndex(this.snapshot.rows, params);
|
|
1127
1782
|
if (index === undefined) {
|
|
1128
|
-
const sectionCount = this.snapshot.rows.filter(row => row.type === 'sectionHeader' && row.variant !== 'summary').length;
|
|
1783
|
+
const sectionCount = this.snapshot.rows.filter(row => row.type === 'sectionHeader' && row.sticky !== false && row.variant !== 'summary').length;
|
|
1129
1784
|
this.emitScrollFailure(params.itemIndex, params.sectionIndex >= sectionCount ? 'section-out-of-range' : 'item-out-of-range');
|
|
1130
1785
|
return;
|
|
1131
1786
|
}
|
|
@@ -1172,6 +1827,8 @@ export class NativeListWebEngine {
|
|
|
1172
1827
|
this.document.defaultView?.removeEventListener('resize', this.handleWindowResize);
|
|
1173
1828
|
this.viewport.removeEventListener('scroll', this.handleScroll);
|
|
1174
1829
|
this.root.removeEventListener('click', this.handleClick);
|
|
1830
|
+
this.root.removeEventListener('pointerover', this.handleTitlePointerOver);
|
|
1831
|
+
this.root.removeEventListener('pointerout', this.handleTitlePointerOut);
|
|
1175
1832
|
this.root.removeEventListener('keydown', this.handleKeyDown);
|
|
1176
1833
|
this.cancelPointerReorder(true);
|
|
1177
1834
|
this.viewport.removeEventListener('pointerdown', this.handleReorderPointerDown);
|
|
@@ -1189,19 +1846,23 @@ export class NativeListWebEngine {
|
|
|
1189
1846
|
this.viewport.removeEventListener('pointerup', this.handlePullEnd);
|
|
1190
1847
|
this.viewport.removeEventListener('pointercancel', this.handlePullEnd);
|
|
1191
1848
|
const host = this.root.parentElement;
|
|
1849
|
+
disposeWebImageRetries(this.root);
|
|
1850
|
+
this.pool.forEach(disposeWebImageRetries);
|
|
1192
1851
|
this.root.remove();
|
|
1193
1852
|
this.hideReorderPreview();
|
|
1194
1853
|
this.reorderPreview.remove();
|
|
1195
1854
|
if (host) host.style.position = this.previousHostPosition;
|
|
1196
1855
|
this.mounted.clear();
|
|
1197
1856
|
this.pool.length = 0;
|
|
1857
|
+
this.avatarLeases.forEach(release => release());
|
|
1858
|
+
this.avatarLeases.clear();
|
|
1198
1859
|
}
|
|
1199
1860
|
setSnapshot(snapshot, selectedKeys) {
|
|
1861
|
+
this.measuredWarningHeights.clear();
|
|
1200
1862
|
this.snapshot = snapshot;
|
|
1201
1863
|
this.rows = effectiveRows(snapshot);
|
|
1202
1864
|
this.selectedKeys = selectedKeys ?? selectionStateFromSnapshot(snapshot).selectedKeys;
|
|
1203
1865
|
if (this.reachedGeneration !== snapshot.generation) this.reachedGeneration = undefined;
|
|
1204
|
-
this.renderSectionIndex();
|
|
1205
1866
|
this.applyTheme();
|
|
1206
1867
|
this.recomputeLayout();
|
|
1207
1868
|
this.renderFooter();
|
|
@@ -1219,6 +1880,11 @@ export class NativeListWebEngine {
|
|
|
1219
1880
|
'--nl-primary': theme.primaryText,
|
|
1220
1881
|
'--nl-secondary': theme.secondaryText,
|
|
1221
1882
|
'--nl-disabled': theme.disabledText,
|
|
1883
|
+
'--nl-caution': theme.caution ?? '#AB6400',
|
|
1884
|
+
'--nl-caution-background': theme.cautionBackground,
|
|
1885
|
+
'--nl-checkbox-background': theme.checkboxBackground,
|
|
1886
|
+
'--nl-checkbox-border': theme.checkboxBorder,
|
|
1887
|
+
'--nl-checkbox-icon': theme.checkboxIcon,
|
|
1222
1888
|
'--nl-icon': theme.icon,
|
|
1223
1889
|
'--nl-icon-subdued': theme.iconSubdued,
|
|
1224
1890
|
'--nl-separator': theme.separator,
|
|
@@ -1242,13 +1908,22 @@ export class NativeListWebEngine {
|
|
|
1242
1908
|
const viewportHeight = this.viewport.clientHeight;
|
|
1243
1909
|
if (this.lastViewportWidth >= 0 && (viewportWidth !== this.lastViewportWidth || viewportHeight !== this.lastViewportHeight)) {
|
|
1244
1910
|
this.invalidateActionAnchor('layout');
|
|
1911
|
+
this.measuredWarningHeights.clear();
|
|
1245
1912
|
}
|
|
1246
1913
|
this.lastViewportWidth = viewportWidth;
|
|
1247
1914
|
this.lastViewportHeight = viewportHeight;
|
|
1248
1915
|
const previousHorizontal = this.layout.horizontal;
|
|
1249
|
-
|
|
1916
|
+
const measuredSnapshot = {
|
|
1917
|
+
...this.snapshot,
|
|
1918
|
+
rows: this.snapshot.rows.map(row => row.type === 'system' && row.variant === 'warning' && row.height === undefined && this.measuredWarningHeights.has(row.key) ? {
|
|
1919
|
+
...row,
|
|
1920
|
+
height: this.measuredWarningHeights.get(row.key)
|
|
1921
|
+
} : row)
|
|
1922
|
+
};
|
|
1923
|
+
this.layout = computeWebListLayout(measuredSnapshot, viewportWidth, viewportHeight, this.reorderCompactKey);
|
|
1250
1924
|
this.content.style.width = String(this.layout.contentWidth) + 'px';
|
|
1251
1925
|
this.content.style.height = String(this.layout.contentHeight) + 'px';
|
|
1926
|
+
this.renderSectionIndex(viewportHeight || DEFAULT_VIEWPORT_HEIGHT);
|
|
1252
1927
|
if (previousHorizontal !== this.layout.horizontal) {
|
|
1253
1928
|
this.viewport.scrollLeft = 0;
|
|
1254
1929
|
this.viewport.scrollTop = 0;
|
|
@@ -1256,7 +1931,44 @@ export class NativeListWebEngine {
|
|
|
1256
1931
|
this.renderWindow();
|
|
1257
1932
|
this.performPendingScroll();
|
|
1258
1933
|
};
|
|
1934
|
+
updateAvatarWindow() {
|
|
1935
|
+
const offset = this.currentOffset();
|
|
1936
|
+
if (offset !== this.avatarOffset) this.avatarDirection = Math.sign(offset - this.avatarOffset);
|
|
1937
|
+
this.avatarOffset = offset;
|
|
1938
|
+
const visible = visibleWebLayoutItems(this.layout, offset, this.viewportLength(), 0);
|
|
1939
|
+
const first = visible[0]?.index ?? -1;
|
|
1940
|
+
const last = visible[visible.length - 1]?.index ?? -1;
|
|
1941
|
+
const candidates = avatarPrefetchWindow(this.rows, first, last, this.avatarDirection);
|
|
1942
|
+
const desired = new Set(candidates.map(({
|
|
1943
|
+
source
|
|
1944
|
+
}) => canonicalNativeListAvatarUri(source.uri)).filter(uri => uri !== undefined));
|
|
1945
|
+
this.avatarLeases.forEach((release, uri) => {
|
|
1946
|
+
if (!desired.has(uri)) {
|
|
1947
|
+
release();
|
|
1948
|
+
this.avatarLeases.delete(uri);
|
|
1949
|
+
}
|
|
1950
|
+
});
|
|
1951
|
+
candidates.forEach(({
|
|
1952
|
+
source,
|
|
1953
|
+
priority
|
|
1954
|
+
}) => {
|
|
1955
|
+
const uri = canonicalNativeListAvatarUri(source.uri);
|
|
1956
|
+
if (!uri) return;
|
|
1957
|
+
const existing = this.avatarLeases.get(uri);
|
|
1958
|
+
if (existing) existing.setPriority(priority);else {
|
|
1959
|
+
let lease;
|
|
1960
|
+
lease = acquireNativeListAvatar(this.document, uri, () => {}, () => {
|
|
1961
|
+
if (this.avatarLeases.get(uri) === lease) {
|
|
1962
|
+
lease?.();
|
|
1963
|
+
this.avatarLeases.delete(uri);
|
|
1964
|
+
}
|
|
1965
|
+
}, priority);
|
|
1966
|
+
this.avatarLeases.set(uri, lease);
|
|
1967
|
+
}
|
|
1968
|
+
});
|
|
1969
|
+
}
|
|
1259
1970
|
renderWindow() {
|
|
1971
|
+
this.updateAvatarWindow();
|
|
1260
1972
|
const viewportLength = this.viewportLength();
|
|
1261
1973
|
const visible = webLayoutItemsForMount(this.layout, this.currentOffset(), viewportLength, this.virtualizationEnabled, viewportLength * OVERSCAN_VIEWPORTS);
|
|
1262
1974
|
const desired = new Set(visible.map(item => item.index));
|
|
@@ -1264,6 +1976,7 @@ export class NativeListWebEngine {
|
|
|
1264
1976
|
if (!desired.has(index)) {
|
|
1265
1977
|
this.invalidateActionAnchorForElement(element);
|
|
1266
1978
|
this.mounted.delete(index);
|
|
1979
|
+
if (disposeWebImageRetries(element)) element.removeAttribute('data-render-signature');
|
|
1267
1980
|
element.remove();
|
|
1268
1981
|
this.pool.push(element);
|
|
1269
1982
|
}
|
|
@@ -1285,6 +1998,20 @@ export class NativeListWebEngine {
|
|
|
1285
1998
|
element.dataset.renderSignature = signature;
|
|
1286
1999
|
}
|
|
1287
2000
|
});
|
|
2001
|
+
let measuredWarningChanged = false;
|
|
2002
|
+
this.mounted.forEach((element, index) => {
|
|
2003
|
+
const row = this.rows[index];
|
|
2004
|
+
if (row?.type !== 'system' || row.variant !== 'warning' || row.height !== undefined) return;
|
|
2005
|
+
const height = element.querySelector('.ok-native-list-warning')?.offsetHeight ?? 0;
|
|
2006
|
+
if (height > 0 && height !== this.measuredWarningHeights.get(row.key)) {
|
|
2007
|
+
this.measuredWarningHeights.set(row.key, height);
|
|
2008
|
+
measuredWarningChanged = true;
|
|
2009
|
+
}
|
|
2010
|
+
});
|
|
2011
|
+
if (measuredWarningChanged) {
|
|
2012
|
+
this.recomputeLayout();
|
|
2013
|
+
return;
|
|
2014
|
+
}
|
|
1288
2015
|
this.updateVisibleSelection();
|
|
1289
2016
|
this.updateVisibleState();
|
|
1290
2017
|
}
|
|
@@ -1295,12 +2022,16 @@ export class NativeListWebEngine {
|
|
|
1295
2022
|
}
|
|
1296
2023
|
renderElement(element, index, row, overlay = false) {
|
|
1297
2024
|
this.invalidateActionAnchorForElement(element);
|
|
2025
|
+
disposeWebImageRetries(element);
|
|
1298
2026
|
const bindingEpoch = String(++this.bindingEpochCounter);
|
|
1299
2027
|
element.className = overlay ? 'ok-native-list-item ok-native-list-sticky' : 'ok-native-list-item';
|
|
1300
2028
|
setData(element, 'nativeListRowKey', row.key);
|
|
1301
2029
|
setData(element, 'nativeListBindingEpoch', bindingEpoch);
|
|
1302
2030
|
setData(element, 'nativeListRowIndex', index);
|
|
1303
2031
|
setData(element, 'nativeListDisabled', Boolean(row.disabled));
|
|
2032
|
+
setData(element, 'testid', row.testID);
|
|
2033
|
+
// OneKey patch: deprecation dims a row without disabling its actions.
|
|
2034
|
+
element.style.opacity = String(row.opacity ?? 1);
|
|
1304
2035
|
setData(element, 'nativeListReorderable', this.isReorderable(row));
|
|
1305
2036
|
setData(element, 'nativeListDragging', this.pointerReorder?.active && this.pointerReorder.sourceKey === row.key);
|
|
1306
2037
|
setData(element, 'separator', row.separator);
|
|
@@ -1320,11 +2051,67 @@ export class NativeListWebEngine {
|
|
|
1320
2051
|
selectedKeys: this.selectedKeys,
|
|
1321
2052
|
itemIndex: index
|
|
1322
2053
|
};
|
|
1323
|
-
|
|
2054
|
+
const body = createRowBody(context, row);
|
|
2055
|
+
applySelectorTabularNumbers(body, row);
|
|
2056
|
+
// OneKey patch: explicit selector fields preserve original page geometry.
|
|
2057
|
+
element.style.contain = row.backgroundFullWidth ? 'layout style' : '';
|
|
2058
|
+
if (row.backgroundColor) body.style.backgroundColor = row.backgroundColor;
|
|
2059
|
+
if (row.backgroundFullWidth && row.backgroundColor) {
|
|
2060
|
+
const bleed = paddingValues(this.snapshot).horizontal;
|
|
2061
|
+
body.style.position = 'relative';
|
|
2062
|
+
body.style.overflow = 'visible';
|
|
2063
|
+
body.style.boxShadow = String(-bleed) + 'px 0 ' + row.backgroundColor + ',' + String(bleed) + 'px 0 ' + row.backgroundColor;
|
|
2064
|
+
}
|
|
2065
|
+
if (row.type === 'identity' && row.height !== undefined) {
|
|
2066
|
+
const title = body.querySelector('.ok-native-list-title');
|
|
2067
|
+
if (row.presentation === 'accountSelector') {
|
|
2068
|
+
body.style.gap = '12px';
|
|
2069
|
+
body.style.borderRadius = '12px';
|
|
2070
|
+
if ('shape' in row.leading && row.leading.shape === 'rounded') {
|
|
2071
|
+
const visual = body.querySelector('.ok-native-list-visual');
|
|
2072
|
+
if (visual) visual.style.borderRadius = '8px';
|
|
2073
|
+
}
|
|
2074
|
+
if (title) title.style.lineHeight = '24px';
|
|
2075
|
+
}
|
|
2076
|
+
if (row.presentation === 'networkSelector') {
|
|
2077
|
+
body.style.borderRadius = '12px';
|
|
2078
|
+
const visual = body.querySelector('.ok-native-list-visual');
|
|
2079
|
+
if (visual) {
|
|
2080
|
+
visual.style.width = '32px';
|
|
2081
|
+
visual.style.height = '32px';
|
|
2082
|
+
visual.style.flexBasis = '32px';
|
|
2083
|
+
}
|
|
2084
|
+
if (row.leading.kind === 'network' && !row.leading.image && !row.leading.fallbackIcon && row.leading.fallbackText) {
|
|
2085
|
+
const fallback = visual?.querySelector('.ok-native-list-visual-fallback');
|
|
2086
|
+
if (fallback) {
|
|
2087
|
+
fallback.style.fontSize = '19px';
|
|
2088
|
+
fallback.style.lineHeight = '27px';
|
|
2089
|
+
fallback.style.fontWeight = '600';
|
|
2090
|
+
fallback.style.color = 'var(--nl-inverse-text)';
|
|
2091
|
+
}
|
|
2092
|
+
}
|
|
2093
|
+
visual?.querySelectorAll('.ok-native-list-visual-main').forEach(image => {
|
|
2094
|
+
image.style.width = '32px';
|
|
2095
|
+
image.style.height = '32px';
|
|
2096
|
+
});
|
|
2097
|
+
if (title) {
|
|
2098
|
+
title.style.fontSize = '16px';
|
|
2099
|
+
title.style.lineHeight = '24px';
|
|
2100
|
+
title.style.fontWeight = '500';
|
|
2101
|
+
}
|
|
2102
|
+
body.querySelectorAll('.ok-native-list-accessory').forEach(value => {
|
|
2103
|
+
value.style.fontSize = '16px';
|
|
2104
|
+
value.style.lineHeight = '24px';
|
|
2105
|
+
value.style.fontWeight = '500';
|
|
2106
|
+
});
|
|
2107
|
+
}
|
|
2108
|
+
}
|
|
2109
|
+
element.replaceChildren(body);
|
|
1324
2110
|
}
|
|
1325
2111
|
renderFooter() {
|
|
1326
2112
|
const row = this.snapshot.fixedFooter;
|
|
1327
2113
|
this.invalidateActionAnchorForElement(this.footer);
|
|
2114
|
+
disposeWebImageRetries(this.footer);
|
|
1328
2115
|
this.footer.replaceChildren();
|
|
1329
2116
|
if (!row) return;
|
|
1330
2117
|
const element = createElement(this.document, 'div', 'ok-native-list-item');
|
|
@@ -1335,20 +2122,52 @@ export class NativeListWebEngine {
|
|
|
1335
2122
|
element.style.height = String(estimateWebRowHeight(row, this.snapshot, this.viewport.clientWidth || DEFAULT_VIEWPORT_WIDTH)) + 'px';
|
|
1336
2123
|
this.footer.appendChild(element);
|
|
1337
2124
|
}
|
|
1338
|
-
|
|
2125
|
+
sectionIndexVisibleEntryIndices(viewportHeight) {
|
|
2126
|
+
const entryCount = this.sectionIndexEntries.length;
|
|
2127
|
+
if (entryCount <= 1) return entryCount ? [0] : [];
|
|
2128
|
+
const availableHeight = Math.max(0, viewportHeight - SECTION_INDEX_EDGE_PADDING * 2);
|
|
2129
|
+
const maxVisible = Math.max(2, Math.floor(availableHeight / SECTION_INDEX_MIN_LABEL_SPACING) + 1);
|
|
2130
|
+
if (entryCount <= maxVisible) {
|
|
2131
|
+
return Array.from({
|
|
2132
|
+
length: entryCount
|
|
2133
|
+
}, (_, index) => index);
|
|
2134
|
+
}
|
|
2135
|
+
const result = new Set();
|
|
2136
|
+
for (let slot = 0; slot < maxVisible; slot += 1) {
|
|
2137
|
+
result.add(Math.round(slot * (entryCount - 1) / (maxVisible - 1)));
|
|
2138
|
+
}
|
|
2139
|
+
return [...result].sort((left, right) => left - right);
|
|
2140
|
+
}
|
|
2141
|
+
renderSectionIndex(viewportHeight) {
|
|
1339
2142
|
this.indexRail.replaceChildren();
|
|
1340
2143
|
if (!sectionIndexEnabled(this.snapshot)) {
|
|
2144
|
+
this.sectionIndexEntries = [];
|
|
2145
|
+
this.indexRail.hidden = true;
|
|
2146
|
+
return;
|
|
2147
|
+
}
|
|
2148
|
+
this.sectionIndexEntries = this.snapshot.rows.flatMap((row, position) => row.type === 'sectionHeader' && row.indexTitle ? [{
|
|
2149
|
+
key: row.key,
|
|
2150
|
+
title: row.indexTitle,
|
|
2151
|
+
position
|
|
2152
|
+
}] : []);
|
|
2153
|
+
if (this.sectionIndexEntries.length === 0 || viewportHeight < SECTION_INDEX_MIN_HEIGHT) {
|
|
1341
2154
|
this.indexRail.hidden = true;
|
|
1342
2155
|
return;
|
|
1343
2156
|
}
|
|
2157
|
+
const visibleEntryIndices = this.sectionIndexVisibleEntryIndices(viewportHeight);
|
|
2158
|
+
setData(this.indexRail, 'compact', visibleEntryIndices.length < this.sectionIndexEntries.length);
|
|
1344
2159
|
const fragment = this.document.createDocumentFragment();
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
2160
|
+
visibleEntryIndices.forEach(entryIndex => {
|
|
2161
|
+
const entry = this.sectionIndexEntries[entryIndex];
|
|
2162
|
+
if (!entry) return;
|
|
2163
|
+
const button = createElement(this.document, 'button', 'ok-native-list-index-button', entry.title);
|
|
1348
2164
|
button.setAttribute('type', 'button');
|
|
1349
|
-
button.setAttribute('aria-label', 'Jump to ' +
|
|
1350
|
-
setData(button, '
|
|
1351
|
-
setData(button, '
|
|
2165
|
+
button.setAttribute('aria-label', 'Jump to ' + entry.title);
|
|
2166
|
+
setData(button, 'sectionEntryIndex', entryIndex);
|
|
2167
|
+
setData(button, 'sectionPosition', entry.position);
|
|
2168
|
+
setData(button, 'sectionKey', entry.key);
|
|
2169
|
+
const progress = this.sectionIndexEntries.length === 1 ? 0.5 : entryIndex / (this.sectionIndexEntries.length - 1);
|
|
2170
|
+
button.style.top = String(SECTION_INDEX_EDGE_PADDING + progress * (viewportHeight - SECTION_INDEX_EDGE_PADDING * 2)) + 'px';
|
|
1352
2171
|
fragment.appendChild(button);
|
|
1353
2172
|
});
|
|
1354
2173
|
this.indexRail.appendChild(fragment);
|
|
@@ -1357,7 +2176,9 @@ export class NativeListWebEngine {
|
|
|
1357
2176
|
updateVisibleSelection() {
|
|
1358
2177
|
const update = (element, row) => {
|
|
1359
2178
|
if (!row) return;
|
|
1360
|
-
|
|
2179
|
+
// OneKey patch: selector adapters mark active rows independently of checkbox selection.
|
|
2180
|
+
// const selected = this.selectedKeys.has(row.key);
|
|
2181
|
+
const selected = row.selected === true || this.selectedKeys.has(row.key);
|
|
1361
2182
|
setData(element, 'nativeListSelected', selected);
|
|
1362
2183
|
element.setAttribute('aria-selected', String(selected));
|
|
1363
2184
|
element.querySelectorAll('.ok-native-list-checkbox').forEach(checkbox => {
|
|
@@ -1396,7 +2217,9 @@ export class NativeListWebEngine {
|
|
|
1396
2217
|
}
|
|
1397
2218
|
this.checkEndReached(last?.index ?? -1);
|
|
1398
2219
|
this.updateStickyHeader(first?.index ?? -1);
|
|
1399
|
-
|
|
2220
|
+
// OneKey patch: index highlighting follows header positions at scroll boundaries.
|
|
2221
|
+
// this.updateSectionIndex(first?.index ?? -1);
|
|
2222
|
+
this.updateSectionIndex();
|
|
1400
2223
|
}
|
|
1401
2224
|
updateStickyHeader(firstVisibleIndex) {
|
|
1402
2225
|
if (!this.snapshot.layout.stickyHeaders || this.layout.horizontal || firstVisibleIndex < 0) {
|
|
@@ -1407,7 +2230,7 @@ export class NativeListWebEngine {
|
|
|
1407
2230
|
let index = -1;
|
|
1408
2231
|
for (let cursor = firstVisibleIndex; cursor >= 0; cursor -= 1) {
|
|
1409
2232
|
const row = this.rows[cursor];
|
|
1410
|
-
if (row?.type === 'sectionHeader' && row.variant !== 'summary') {
|
|
2233
|
+
if (row?.type === 'sectionHeader' && row.sticky !== false && row.variant !== 'summary') {
|
|
1411
2234
|
index = cursor;
|
|
1412
2235
|
break;
|
|
1413
2236
|
}
|
|
@@ -1433,7 +2256,7 @@ export class NativeListWebEngine {
|
|
|
1433
2256
|
let nextIndex = -1;
|
|
1434
2257
|
for (let cursor = index + 1; cursor < this.rows.length; cursor += 1) {
|
|
1435
2258
|
const candidate = this.rows[cursor];
|
|
1436
|
-
if (candidate?.type === 'sectionHeader' && candidate.variant !== 'summary') {
|
|
2259
|
+
if (candidate?.type === 'sectionHeader' && candidate.sticky !== false && candidate.variant !== 'summary') {
|
|
1437
2260
|
nextIndex = cursor;
|
|
1438
2261
|
break;
|
|
1439
2262
|
}
|
|
@@ -1443,10 +2266,15 @@ export class NativeListWebEngine {
|
|
|
1443
2266
|
this.sticky.style.transform = 'translate3d(0,' + String(translate) + 'px,0)';
|
|
1444
2267
|
this.updateVisibleSelection();
|
|
1445
2268
|
}
|
|
1446
|
-
|
|
2269
|
+
|
|
2270
|
+
// private updateSectionIndex(firstVisibleIndex: number) {
|
|
2271
|
+
updateSectionIndex() {
|
|
1447
2272
|
let activeKey;
|
|
1448
2273
|
this.snapshot.rows.forEach((row, index) => {
|
|
1449
|
-
if (
|
|
2274
|
+
if (
|
|
2275
|
+
// OneKey patch: a spacer ending exactly at the viewport is not the active section.
|
|
2276
|
+
// index <= firstVisibleIndex &&
|
|
2277
|
+
itemStart(this.layout.items[index], this.layout.horizontal) <= this.currentOffset() && row.type === 'sectionHeader' && row.sticky !== false && row.indexTitle) activeKey = row.key;
|
|
1450
2278
|
});
|
|
1451
2279
|
this.indexRail.querySelectorAll('[data-section-key]').forEach(button => setData(button, 'active', button.dataset.sectionKey === activeKey));
|
|
1452
2280
|
}
|
|
@@ -1539,7 +2367,14 @@ export class NativeListWebEngine {
|
|
|
1539
2367
|
const bindingEpoch = rowElement.dataset.nativeListBindingEpoch;
|
|
1540
2368
|
if (!source || !bindingEpoch || !rowElement.contains(actionElement)) return undefined;
|
|
1541
2369
|
this.invalidateActionAnchor('rebind');
|
|
1542
|
-
const
|
|
2370
|
+
const actualRect = actionElement.getBoundingClientRect();
|
|
2371
|
+
const inset = Number(actionElement.dataset.nativeListAnchorInset ?? 0);
|
|
2372
|
+
const rect = {
|
|
2373
|
+
left: actualRect.left + inset,
|
|
2374
|
+
top: actualRect.top + inset,
|
|
2375
|
+
width: actualRect.width - inset * 2,
|
|
2376
|
+
height: actualRect.height - inset * 2
|
|
2377
|
+
};
|
|
1543
2378
|
const token = [this.actionAnchorInstanceId, this.snapshot.generation, ++this.actionAnchorCounter, bindingEpoch].join(':');
|
|
1544
2379
|
const slotValue = actionElement.dataset.nativeListAnchorSlot;
|
|
1545
2380
|
const direction = this.document.defaultView?.getComputedStyle(actionElement).direction === 'rtl' || actionElement.closest('[dir="rtl"]') ? 'rtl' : 'ltr';
|
|
@@ -1577,7 +2412,9 @@ export class NativeListWebEngine {
|
|
|
1577
2412
|
});
|
|
1578
2413
|
}
|
|
1579
2414
|
handleRowPress(row, rowElement, sourceElement = rowElement) {
|
|
1580
|
-
|
|
2415
|
+
// OneKey patch: missing-address rows keep their create-address accessory interactive.
|
|
2416
|
+
// if (row.disabled) return;
|
|
2417
|
+
if (row.disabled || row.pressDisabled) return;
|
|
1581
2418
|
if (this.snapshot.selection?.rowPressToggles && this.snapshot.selection.mode !== 'none' && isSelectableRow(row)) {
|
|
1582
2419
|
this.activateSelection({
|
|
1583
2420
|
scope: 'row'
|
|
@@ -1597,6 +2434,27 @@ export class NativeListWebEngine {
|
|
|
1597
2434
|
this.emitRowAction(row, actionKey);
|
|
1598
2435
|
}
|
|
1599
2436
|
}
|
|
2437
|
+
|
|
2438
|
+
// OneKey patch: hover opens the same anchored help action as native taps.
|
|
2439
|
+
handleTitlePointerOver = event => {
|
|
2440
|
+
const target = event.target;
|
|
2441
|
+
if (!(target instanceof Element)) return;
|
|
2442
|
+
const action = target.closest('[data-native-list-hover-action]');
|
|
2443
|
+
if (!action || event.relatedTarget instanceof Node && action.contains(event.relatedTarget)) return;
|
|
2444
|
+
const rowElement = action.closest('[data-native-list-row-key]');
|
|
2445
|
+
const row = this.rowAtElement(rowElement);
|
|
2446
|
+
const memberKey = action.closest('[data-native-list-group-member-key]')?.dataset.nativeListGroupMemberKey;
|
|
2447
|
+
const sourceRow = row?.type === 'walletGroup' ? [row.parent, ...row.children].find(member => member.key === memberKey) ?? row : row;
|
|
2448
|
+
const actionKey = action.dataset.nativeListHoverAction === 'true' ? action.dataset.nativeListAction : action.dataset.nativeListHoverAction;
|
|
2449
|
+
if (sourceRow && !sourceRow.disabled && actionKey) this.emitRowAction(sourceRow, actionKey, action, rowElement ?? undefined);
|
|
2450
|
+
};
|
|
2451
|
+
handleTitlePointerOut = event => {
|
|
2452
|
+
const target = event.target;
|
|
2453
|
+
if (!(target instanceof Element)) return;
|
|
2454
|
+
const action = target.closest('[data-native-list-hover-action]');
|
|
2455
|
+
if (!action || event.relatedTarget instanceof Node && action.contains(event.relatedTarget)) return;
|
|
2456
|
+
if (this.actionAnchor?.actionElement === action) this.invalidateActionAnchor('pointerLeave');
|
|
2457
|
+
};
|
|
1600
2458
|
handleClick = event => {
|
|
1601
2459
|
if (Date.now() < this.suppressClickUntil) {
|
|
1602
2460
|
event.preventDefault();
|
|
@@ -1627,6 +2485,12 @@ export class NativeListWebEngine {
|
|
|
1627
2485
|
this.handleRowPress(sourceRow, rowElement ?? undefined, memberElement ?? rowElement ?? undefined);
|
|
1628
2486
|
};
|
|
1629
2487
|
handleKeyDown = event => {
|
|
2488
|
+
// OneKey patch: non-button title help supports keyboard activation.
|
|
2489
|
+
if ((event.key === 'Enter' || event.key === ' ') && event.target instanceof HTMLElement && event.target.matches('[role="button"][data-native-list-action]')) {
|
|
2490
|
+
event.preventDefault();
|
|
2491
|
+
event.target.click();
|
|
2492
|
+
return;
|
|
2493
|
+
}
|
|
1630
2494
|
if (event.key === 'Escape') {
|
|
1631
2495
|
if (this.pointerReorder?.active) {
|
|
1632
2496
|
event.preventDefault();
|
|
@@ -1729,7 +2593,10 @@ export class NativeListWebEngine {
|
|
|
1729
2593
|
if (this.frameHandle !== undefined || this.destroyed) return;
|
|
1730
2594
|
this.frameHandle = this.requestFrame(() => {
|
|
1731
2595
|
this.frameHandle = undefined;
|
|
1732
|
-
if (this.virtualizationEnabled) this.renderWindow();else
|
|
2596
|
+
if (this.virtualizationEnabled) this.renderWindow();else {
|
|
2597
|
+
this.updateAvatarWindow();
|
|
2598
|
+
this.updateVisibleState();
|
|
2599
|
+
}
|
|
1733
2600
|
});
|
|
1734
2601
|
}
|
|
1735
2602
|
requestFrame(callback) {
|
|
@@ -1740,13 +2607,20 @@ export class NativeListWebEngine {
|
|
|
1740
2607
|
const view = this.document.defaultView;
|
|
1741
2608
|
if (view?.cancelAnimationFrame) view.cancelAnimationFrame(handle);else view?.clearTimeout(handle);
|
|
1742
2609
|
}
|
|
1743
|
-
selectIndexPosition(position, title) {
|
|
2610
|
+
selectIndexPosition(position, title, previewClientY) {
|
|
1744
2611
|
this.scrollToIndex(position, {
|
|
1745
2612
|
animated: false,
|
|
1746
2613
|
alignment: 'start',
|
|
1747
2614
|
viewPosition: 0,
|
|
1748
2615
|
viewOffset: 0
|
|
1749
2616
|
});
|
|
2617
|
+
const frame = this.viewportFrame.getBoundingClientRect();
|
|
2618
|
+
if (previewClientY !== undefined && frame.height > 0) {
|
|
2619
|
+
const previewY = Math.min(frame.height - 24, Math.max(24, previewClientY - frame.top));
|
|
2620
|
+
this.indexPreview.style.top = String(previewY) + 'px';
|
|
2621
|
+
} else {
|
|
2622
|
+
this.indexPreview.style.top = '50%';
|
|
2623
|
+
}
|
|
1750
2624
|
this.indexPreview.textContent = title;
|
|
1751
2625
|
setData(this.indexPreview, 'visible', true);
|
|
1752
2626
|
if (this.previewTimer !== undefined) this.document.defaultView?.clearTimeout(this.previewTimer);
|
|
@@ -1754,24 +2628,40 @@ export class NativeListWebEngine {
|
|
|
1754
2628
|
setData(this.indexPreview, 'visible', false);
|
|
1755
2629
|
}, 180);
|
|
1756
2630
|
}
|
|
1757
|
-
|
|
1758
|
-
const
|
|
1759
|
-
if (
|
|
1760
|
-
|
|
2631
|
+
sectionIndexEntryAtEvent(event) {
|
|
2632
|
+
const rail = this.indexRail.getBoundingClientRect();
|
|
2633
|
+
if (this.sectionIndexEntries.length === 0 || rail.height <= 0) {
|
|
2634
|
+
return undefined;
|
|
2635
|
+
}
|
|
2636
|
+
const availableHeight = Math.max(1, rail.height - SECTION_INDEX_EDGE_PADDING * 2);
|
|
2637
|
+
const progress = Math.min(1, Math.max(0, (event.clientY - rail.top - SECTION_INDEX_EDGE_PADDING) / availableHeight));
|
|
2638
|
+
const entryIndex = Math.round(progress * (this.sectionIndexEntries.length - 1));
|
|
2639
|
+
const entry = this.sectionIndexEntries[entryIndex];
|
|
2640
|
+
return entry ? {
|
|
2641
|
+
entry,
|
|
2642
|
+
previewClientY: event.clientY
|
|
2643
|
+
} : undefined;
|
|
1761
2644
|
}
|
|
1762
2645
|
handleIndexPointer = event => {
|
|
1763
2646
|
if (event.type === 'pointermove' && event.buttons === 0) return;
|
|
1764
|
-
const
|
|
1765
|
-
if (!
|
|
2647
|
+
const selection = this.sectionIndexEntryAtEvent(event);
|
|
2648
|
+
if (!selection) return;
|
|
1766
2649
|
event.preventDefault();
|
|
1767
|
-
|
|
2650
|
+
if (event.type === 'pointerdown') {
|
|
2651
|
+
this.indexRail.setPointerCapture?.(event.pointerId);
|
|
2652
|
+
}
|
|
2653
|
+
this.selectIndexPosition(selection.entry.position, selection.entry.title, selection.previewClientY);
|
|
1768
2654
|
};
|
|
1769
2655
|
handleIndexClick = event => {
|
|
2656
|
+
if ('detail' in event && typeof event.detail === 'number' && event.detail > 0) return;
|
|
1770
2657
|
const target = event.target;
|
|
1771
2658
|
if (!(target instanceof Element)) return;
|
|
1772
|
-
const button = target.closest('[data-section-
|
|
2659
|
+
const button = target.closest('[data-section-entry-index]');
|
|
1773
2660
|
if (!button) return;
|
|
1774
|
-
this.
|
|
2661
|
+
const entry = this.sectionIndexEntries[Number(button.dataset.sectionEntryIndex)];
|
|
2662
|
+
if (!entry) return;
|
|
2663
|
+
const rect = button.getBoundingClientRect();
|
|
2664
|
+
this.selectIndexPosition(entry.position, entry.title, rect.top + rect.height / 2);
|
|
1775
2665
|
};
|
|
1776
2666
|
handlePullStart = event => {
|
|
1777
2667
|
if (this.pointerReorder?.pointerId === event.pointerId || !this.snapshot.capabilities?.pullToRefresh || this.viewport.scrollTop > 0 || event.pointerType !== 'touch' && event.pointerType !== 'pen') return;
|
|
@@ -1816,7 +2706,14 @@ export class NativeListWebEngine {
|
|
|
1816
2706
|
const index = Number(rowElement?.dataset.nativeListRowIndex);
|
|
1817
2707
|
const row = this.rows[index];
|
|
1818
2708
|
if (!row || !this.isReorderable(row)) return;
|
|
1819
|
-
|
|
2709
|
+
// OneKey patch: a child drag reorders its parent wallet group as one item.
|
|
2710
|
+
// if (
|
|
2711
|
+
// row.type === 'walletGroup' &&
|
|
2712
|
+
// target.closest<HTMLElement>('[data-native-list-group-parent]')?.dataset
|
|
2713
|
+
// .nativeListGroupParent !== 'true'
|
|
2714
|
+
// )
|
|
2715
|
+
// return;
|
|
2716
|
+
|
|
1820
2717
|
const view = this.document.defaultView;
|
|
1821
2718
|
const state = {
|
|
1822
2719
|
pointerId: event.pointerId,
|
|
@@ -1832,9 +2729,8 @@ export class NativeListWebEngine {
|
|
|
1832
2729
|
active: false
|
|
1833
2730
|
};
|
|
1834
2731
|
this.pointerReorder = state;
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
} else {
|
|
2732
|
+
// OneKey patch: normal wallet taps retain their target until a drag is activated.
|
|
2733
|
+
if (state.pointerType !== 'mouse') {
|
|
1838
2734
|
state.longPressTimer = view?.setTimeout(() => this.activatePointerReorder(state), REORDER_TOUCH_LONG_PRESS_MS);
|
|
1839
2735
|
}
|
|
1840
2736
|
};
|
|
@@ -1935,6 +2831,20 @@ export class NativeListWebEngine {
|
|
|
1935
2831
|
state.previewOffsetX = state.startX - rect.left;
|
|
1936
2832
|
state.previewOffsetY = Math.min(previewHeight, Math.max(0, state.startY - rect.top));
|
|
1937
2833
|
this.reorderPreview.replaceChildren(previewRow.cloneNode(true));
|
|
2834
|
+
// Cloned previews need their own lease when a source row is recycled during dragging.
|
|
2835
|
+
const originals = previewRow.querySelectorAll('img');
|
|
2836
|
+
this.reorderPreview.querySelectorAll('img').forEach((image, index) => {
|
|
2837
|
+
const original = originals.item(index);
|
|
2838
|
+
const avatar = original ? webAvatarSources.get(original) : undefined;
|
|
2839
|
+
if (!avatar) return;
|
|
2840
|
+
const paint = image.previousElementSibling;
|
|
2841
|
+
if (paint?.classList.contains('ok-native-list-selector-image-background')) {
|
|
2842
|
+
image.addEventListener('load', () => {
|
|
2843
|
+
paint.style.backgroundImage = 'url(' + JSON.stringify(image.currentSrc || image.src) + ')';
|
|
2844
|
+
});
|
|
2845
|
+
}
|
|
2846
|
+
configureWebAvatar(image, avatar.source, avatar.uri);
|
|
2847
|
+
});
|
|
1938
2848
|
const sourceRow = state.workingRows[state.currentIndex];
|
|
1939
2849
|
const badgeText = sourceRow ? webWalletGroupReorderBadge(sourceRow) : undefined;
|
|
1940
2850
|
if (badgeText) {
|
|
@@ -1970,6 +2880,7 @@ export class NativeListWebEngine {
|
|
|
1970
2880
|
}
|
|
1971
2881
|
clearReorderPreviewVisual() {
|
|
1972
2882
|
this.reorderPreview.hidden = true;
|
|
2883
|
+
disposeWebImageRetries(this.reorderPreview);
|
|
1973
2884
|
this.reorderPreview.replaceChildren();
|
|
1974
2885
|
this.reorderPreview.style.removeProperty('transform');
|
|
1975
2886
|
this.reorderPreview.style.removeProperty('transition');
|