@onekeyfe/react-native-native-list 3.0.112 → 3.0.113
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/README.md +57 -3
- package/android/src/main/java/com/onekey/nativelist/NativeListAdapter.kt +17 -1
- package/android/src/main/java/com/onekey/nativelist/NativeListRowView.kt +543 -26
- package/android/src/main/java/com/onekey/nativelist/NativeListView.kt +26 -2
- package/ios/NativeListCell.swift +504 -20
- package/ios/NativeListDesignAssets.swift +8 -0
- package/ios/RNCNativeListView.swift +85 -7
- package/ios/Resources/NativeListIcons.xcassets/onekey_badge_verified_solid.imageset/Contents.json +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_badge_verified_solid.imageset/icon.svg +1 -0
- package/lib/module/validation.js +129 -1
- package/lib/module/web/NativeListWebEngine.js +357 -5
- package/lib/typescript/src/models.d.ts +82 -2
- package/lib/typescript/src/web/NativeListWebEngine.d.ts +26 -1
- package/package.json +2 -2
- package/src/models.ts +121 -3
- package/src/validation.ts +206 -0
- package/src/web/NativeListWebEngine.ts +578 -4
|
@@ -3,6 +3,8 @@ import type {
|
|
|
3
3
|
CheckboxState,
|
|
4
4
|
ImageSource,
|
|
5
5
|
LeadingVisual,
|
|
6
|
+
MarketRow,
|
|
7
|
+
MarketTextStyle,
|
|
6
8
|
NativeListSnapshot,
|
|
7
9
|
NativeListActionAnchor,
|
|
8
10
|
NativeListActionSource,
|
|
@@ -60,6 +62,10 @@ export const WEB_REORDER_ANIMATION = {
|
|
|
60
62
|
} as const;
|
|
61
63
|
|
|
62
64
|
const REORDER_TOUCH_LONG_PRESS_MS = 120;
|
|
65
|
+
const MARKET_LONG_PRESS_MS = 800;
|
|
66
|
+
const MARKET_MOVE_CANCEL_PX = 10;
|
|
67
|
+
export const WEB_MARKET_VERIFIED_PATH =
|
|
68
|
+
'M9.483 11.458v3.5h-1v-3.5z M10.467 2.698a2.03 2.03 0 0 1 3.065 0l1.358 1.564a.03.03 0 0 0 .028.01l2.046-.325a2.03 2.03 0 0 1 2.347 1.971l.037 2.07q0 .016.014.026l1.776 1.066a2.03 2.03 0 0 1 .532 3.019l-1.304 1.609a.03.03 0 0 0-.005.03l.675 1.956a2.03 2.03 0 0 1-1.533 2.656l-2.033.394a.03.03 0 0 0-.023.019l-.741 1.933a2.03 2.03 0 0 1-2.88 1.05l-1.811-1.006a.03.03 0 0 0-.03 0l-1.811 1.005a2.03 2.03 0 0 1-2.88-1.049l-.742-1.933a.03.03 0 0 0-.023-.019l-2.033-.394a2.03 2.03 0 0 1-1.532-2.656l.675-1.957a.03.03 0 0 0-.005-.029l-1.304-1.61a2.03 2.03 0 0 1 .532-3.018l1.776-1.066a.03.03 0 0 0 .014-.026l.035-2.07a2.03 2.03 0 0 1 2.349-1.97l2.045.324a.03.03 0 0 0 .028-.01zm1.516 3.76a.5.5 0 0 0-.447.276l-1.861 3.724H8.483a1 1 0 0 0-1 1v3.5a1 1 0 0 0 1 1h6.692a2 2 0 0 0 1.981-1.73l.341-2.5a2 2 0 0 0-1.982-2.27h-1.939l.197-1.269a1.5 1.5 0 0 0-1.481-1.731z';
|
|
63
69
|
const REORDER_MOUSE_MOVE_THRESHOLD_PX = 5;
|
|
64
70
|
const REORDER_EDGE_RATIO = 0.25;
|
|
65
71
|
const REORDER_MAX_SPEED_ZONE_RATIO = 0.05;
|
|
@@ -108,6 +114,50 @@ export type WebListLayout = Readonly<{
|
|
|
108
114
|
horizontal: boolean;
|
|
109
115
|
}>;
|
|
110
116
|
|
|
117
|
+
export type WebMarketLayoutStyle = Readonly<{
|
|
118
|
+
horizontalPadding: number;
|
|
119
|
+
verticalPadding: number;
|
|
120
|
+
leadingGap: number;
|
|
121
|
+
titleBadgeGap: number;
|
|
122
|
+
trailingGap: number;
|
|
123
|
+
imageWidth: number;
|
|
124
|
+
imageHeight: number;
|
|
125
|
+
imageCornerRadius: number;
|
|
126
|
+
changeWidth: number;
|
|
127
|
+
changeHeight: number;
|
|
128
|
+
changeCornerRadius: number;
|
|
129
|
+
}>;
|
|
130
|
+
|
|
131
|
+
/** Resolves every reusable Market geometry field, including legacy defaults. */
|
|
132
|
+
export function resolveWebMarketLayoutStyle(
|
|
133
|
+
row: MarketRow
|
|
134
|
+
): WebMarketLayoutStyle {
|
|
135
|
+
const style = row.style;
|
|
136
|
+
const imageWidth = style?.image?.width ?? (row.variant === 'stock' ? 40 : 32);
|
|
137
|
+
const imageHeight =
|
|
138
|
+
style?.image?.height ?? (row.variant === 'stock' ? 40 : 32);
|
|
139
|
+
return {
|
|
140
|
+
horizontalPadding:
|
|
141
|
+
style?.horizontalPadding ?? (row.variant === 'perp' ? 16 : 20),
|
|
142
|
+
verticalPadding: style?.verticalPadding ?? 12,
|
|
143
|
+
leadingGap: style?.leadingGap ?? (row.variant === 'perp' ? 8 : 14),
|
|
144
|
+
titleBadgeGap: style?.titleBadgeGap ?? 4,
|
|
145
|
+
trailingGap: style?.trailingGap ?? 8,
|
|
146
|
+
imageWidth,
|
|
147
|
+
imageHeight,
|
|
148
|
+
imageCornerRadius:
|
|
149
|
+
style?.image?.cornerRadius ??
|
|
150
|
+
(style?.image?.shape === 'square'
|
|
151
|
+
? 0
|
|
152
|
+
: style?.image?.shape === 'rounded'
|
|
153
|
+
? 8
|
|
154
|
+
: Math.min(imageWidth, imageHeight) / 2),
|
|
155
|
+
changeWidth: style?.changeWidth ?? 80,
|
|
156
|
+
changeHeight: style?.changeHeight ?? 32,
|
|
157
|
+
changeCornerRadius: style?.changeCornerRadius ?? 8,
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
111
161
|
export type NativeListWebCallbacks = Readonly<{
|
|
112
162
|
onRowAction?: (event: RowActionEvent) => void;
|
|
113
163
|
onActionAnchorInvalidated?: (event: ActionAnchorInvalidatedEvent) => void;
|
|
@@ -450,7 +500,15 @@ export function estimateWebRowHeight(
|
|
|
450
500
|
}
|
|
451
501
|
case 'system':
|
|
452
502
|
base =
|
|
453
|
-
row.variant === '
|
|
503
|
+
row.variant === 'loading' && row.loadingStyle === 'skeleton'
|
|
504
|
+
? 56
|
|
505
|
+
: row.variant === 'loading' && row.loadingStyle === 'spinner'
|
|
506
|
+
? 52
|
|
507
|
+
: 'presentation' in row && row.presentation === 'market'
|
|
508
|
+
? row.variant === 'loading'
|
|
509
|
+
? 68
|
|
510
|
+
: 44
|
|
511
|
+
: row.variant === 'noMatch' || row.variant === 'end'
|
|
454
512
|
? 36
|
|
455
513
|
: row.variant === 'retry'
|
|
456
514
|
? 44
|
|
@@ -462,6 +520,14 @@ export function estimateWebRowHeight(
|
|
|
462
520
|
case 'dataRow':
|
|
463
521
|
base = row.columns.some((column) => column.secondaryText) ? 60 : 56;
|
|
464
522
|
break;
|
|
523
|
+
case 'market': {
|
|
524
|
+
const marketStyle = resolveWebMarketLayoutStyle(row);
|
|
525
|
+
base = Math.max(
|
|
526
|
+
row.variant === 'stock' ? 72 : 68,
|
|
527
|
+
marketStyle.imageHeight + marketStyle.verticalPadding * 2
|
|
528
|
+
);
|
|
529
|
+
break;
|
|
530
|
+
}
|
|
465
531
|
case 'identity':
|
|
466
532
|
base = row.tertiary ? 72 : row.subtitle ? 60 : 56;
|
|
467
533
|
break;
|
|
@@ -742,6 +808,30 @@ export function webRowRenderSignature(row: RowModel): string {
|
|
|
742
808
|
return JSON.stringify(rowWithoutSelectionState(row));
|
|
743
809
|
}
|
|
744
810
|
|
|
811
|
+
const MARKET_QUOTE_PATCH_FIELDS = new Set([
|
|
812
|
+
'revision',
|
|
813
|
+
'price',
|
|
814
|
+
'priceSegments',
|
|
815
|
+
'change',
|
|
816
|
+
'accessibilityLabel',
|
|
817
|
+
]);
|
|
818
|
+
|
|
819
|
+
export function isWebMarketQuotePatch(patch: RowPatch): boolean {
|
|
820
|
+
return (
|
|
821
|
+
patch.type === 'market' &&
|
|
822
|
+
Object.keys(patch.changes).every((key) =>
|
|
823
|
+
MARKET_QUOTE_PATCH_FIELDS.has(key)
|
|
824
|
+
)
|
|
825
|
+
);
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
/** Number of Market image-binding passes caused by one Web patch transaction. */
|
|
829
|
+
export function webMarketImageBindDeltaForPatches(
|
|
830
|
+
patches: readonly RowPatch[]
|
|
831
|
+
): 0 | 1 {
|
|
832
|
+
return patches.length > 0 && patches.every(isWebMarketQuotePatch) ? 0 : 1;
|
|
833
|
+
}
|
|
834
|
+
|
|
745
835
|
// OneKey patch: selector names must shrink before the sidebar clips their contents.
|
|
746
836
|
export const WEB_LIST_CSS = `
|
|
747
837
|
[data-native-list-selector="walletSidebar"] .ok-native-list-title{max-width:100%;min-width:0}
|
|
@@ -798,11 +888,14 @@ export const WEB_LIST_CSS = `
|
|
|
798
888
|
.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}
|
|
799
889
|
.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)}
|
|
800
890
|
.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}
|
|
891
|
+
.ok-native-list-market{padding:12px 20px;gap:14px}.ok-native-list-market>.ok-native-list-visual{width:32px;height:32px;flex-basis:32px}.ok-native-list-market[data-variant="stock"]>.ok-native-list-visual{width:40px;height:40px;flex-basis:40px}.ok-native-list-market>.ok-native-list-visual>.ok-native-list-visual-main{width:100%;height:100%}.ok-native-list-market-main{display:flex;flex:1;min-width:0;flex-direction:column;justify-content:center}.ok-native-list-market-title-line{display:flex;align-items:center;min-width:0;gap:4px}.ok-native-list-market-title{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--nl-primary);font-size:16px;line-height:24px;font-weight:500}.ok-native-list-market-subtitle{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;color:var(--nl-secondary);font-size:14px;line-height:20px;font-weight:400}.ok-native-list-market-badge{display:inline-flex;flex:0 0 auto;align-items:center;justify-content:center;box-sizing:border-box;max-width:72px;height:18px;padding:0 5px;border:0;border-radius:4px;background:var(--nl-strong);color:var(--nl-secondary);font:500 11px/18px inherit;overflow:hidden;white-space:nowrap}.ok-native-list-market-badge img{width:14px;height:14px;object-fit:contain}.ok-native-list-market-trailing{display:flex;flex:0 0 auto;align-items:center;gap:8px}.ok-native-list-market-price{max-width:112px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-align:right;color:var(--nl-primary);font-size:16px;line-height:24px;font-weight:500;font-variant-numeric:tabular-nums}.ok-native-list-market-change{display:flex;align-items:center;justify-content:center;box-sizing:border-box;width:80px;height:32px;border-radius:8px;color:#fff;background:#8d8d8d;font-size:14px;line-height:20px;font-weight:500;font-variant-numeric:tabular-nums;white-space:nowrap}.ok-native-list-market-change[data-tone="positive"]{background:var(--nl-positive)}.ok-native-list-market-change[data-tone="negative"]{background:var(--nl-negative)}
|
|
892
|
+
.ok-native-list-market-badge>svg,.ok-native-list-market-badge>.ok-native-list-market-badge-icon>svg{display:block;width:16px;height:16px;flex:0 0 16px}.ok-native-list-system[data-native-list-presentation="market"]{box-sizing:border-box;padding:12px 20px}.ok-native-list-system[data-native-list-presentation="market"]>.ok-native-list-spinner{width:32px;height:32px}
|
|
801
893
|
.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)}
|
|
802
894
|
.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)}
|
|
803
895
|
.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)}
|
|
804
896
|
.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}
|
|
805
|
-
|
|
897
|
+
.ok-native-list-row.ok-native-list-market-skeleton{padding:12px 20px;gap:0}.ok-native-list-skeleton-left{display:flex;align-items:center;gap:12px;flex:1}.ok-native-list-skeleton-text{display:flex;flex-direction:column;gap:4px}.ok-native-list-skeleton-right{display:flex;align-items:center;gap:8px}.ok-native-list-skeleton-mark{display:block;flex-shrink:0;border-radius:8px;animation:ok-native-list-skeleton 1.5s linear infinite alternate}@keyframes ok-native-list-skeleton{from{background-color:var(--nl-skeleton-base)}to{background-color:var(--nl-skeleton-highlight)}}.ok-native-list-market-spinner{display:block;width:20px;height:20px;flex-shrink:0;color:var(--nl-icon);animation:ok-native-list-spin .75s linear infinite}
|
|
898
|
+
@media (prefers-reduced-motion:reduce){.ok-native-list-index-preview,.ok-native-list-refresh{transition:none}.ok-native-list-spinner,.ok-native-list-market-spinner{animation:none}.ok-native-list-skeleton-mark{animation:none;background:var(--nl-skeleton-base)}}
|
|
806
899
|
/* OneKey patch: selector controls follow their original semantic colors and geometry. */
|
|
807
900
|
.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))}
|
|
808
901
|
.ok-native-list-checkbox[data-selector="networkSelector"]::after{display:none}
|
|
@@ -1280,6 +1373,17 @@ const selectorIcons: Readonly<
|
|
|
1280
1373
|
},
|
|
1281
1374
|
],
|
|
1282
1375
|
},
|
|
1376
|
+
BadgeVerifiedSolid: {
|
|
1377
|
+
viewBox: '0 0 24 24',
|
|
1378
|
+
paths: [
|
|
1379
|
+
{
|
|
1380
|
+
d: WEB_MARKET_VERIFIED_PATH,
|
|
1381
|
+
fill: 'currentColor',
|
|
1382
|
+
fillRule: 'evenodd',
|
|
1383
|
+
opacity: 1,
|
|
1384
|
+
},
|
|
1385
|
+
],
|
|
1386
|
+
},
|
|
1283
1387
|
};
|
|
1284
1388
|
function applySelectorIcon(element: HTMLElement, name: string) {
|
|
1285
1389
|
const icon = selectorIcons[name];
|
|
@@ -1335,6 +1439,7 @@ function visualFromRow(row: RowModel): LeadingVisual | undefined {
|
|
|
1335
1439
|
if (row.type === 'activity') return row.leading;
|
|
1336
1440
|
if (row.type === 'message') return row.leading;
|
|
1337
1441
|
if (row.type === 'dataRow') return row.leading;
|
|
1442
|
+
if (row.type === 'market') return row.leading;
|
|
1338
1443
|
if (row.type === 'metricCard') return row.visual;
|
|
1339
1444
|
return undefined;
|
|
1340
1445
|
}
|
|
@@ -2089,6 +2194,98 @@ function createSystemRow(
|
|
|
2089
2194
|
'ok-native-list-row ok-native-list-system'
|
|
2090
2195
|
);
|
|
2091
2196
|
setData(body, 'variant', row.variant);
|
|
2197
|
+
if ('presentation' in row)
|
|
2198
|
+
setData(body, 'nativeListPresentation', row.presentation);
|
|
2199
|
+
if (row.variant === 'loading' && row.loadingStyle === 'skeleton') {
|
|
2200
|
+
body.classList.add('ok-native-list-market-skeleton');
|
|
2201
|
+
const background = resolvedTheme(context.snapshot).background;
|
|
2202
|
+
const rgb = Number.parseInt(background.slice(1, 7), 16);
|
|
2203
|
+
const dark =
|
|
2204
|
+
((rgb >> 16) & 255) * 0.299 +
|
|
2205
|
+
((rgb >> 8) & 255) * 0.587 +
|
|
2206
|
+
(rgb & 255) * 0.114 <
|
|
2207
|
+
128;
|
|
2208
|
+
body.style.setProperty('--nl-skeleton-base', dark ? '#111111' : '#fafafa');
|
|
2209
|
+
body.style.setProperty(
|
|
2210
|
+
'--nl-skeleton-highlight',
|
|
2211
|
+
dark ? '#333333' : '#cdcdcd'
|
|
2212
|
+
);
|
|
2213
|
+
const left = createElement(
|
|
2214
|
+
context.document,
|
|
2215
|
+
'div',
|
|
2216
|
+
'ok-native-list-skeleton-left'
|
|
2217
|
+
);
|
|
2218
|
+
const mark = (width: number, height: number, circle = false) => {
|
|
2219
|
+
const element = createElement(
|
|
2220
|
+
context.document,
|
|
2221
|
+
'span',
|
|
2222
|
+
'ok-native-list-skeleton-mark'
|
|
2223
|
+
);
|
|
2224
|
+
element.style.width = `${width}px`;
|
|
2225
|
+
element.style.height = `${height}px`;
|
|
2226
|
+
if (circle) element.style.borderRadius = '50%';
|
|
2227
|
+
return element;
|
|
2228
|
+
};
|
|
2229
|
+
left.appendChild(mark(32, 32, true));
|
|
2230
|
+
const text = createElement(
|
|
2231
|
+
context.document,
|
|
2232
|
+
'div',
|
|
2233
|
+
'ok-native-list-skeleton-text'
|
|
2234
|
+
);
|
|
2235
|
+
text.appendChild(mark(80, 16));
|
|
2236
|
+
text.appendChild(mark(60, 12));
|
|
2237
|
+
left.appendChild(text);
|
|
2238
|
+
body.appendChild(left);
|
|
2239
|
+
const right = createElement(
|
|
2240
|
+
context.document,
|
|
2241
|
+
'div',
|
|
2242
|
+
'ok-native-list-skeleton-right'
|
|
2243
|
+
);
|
|
2244
|
+
right.appendChild(mark(80, 18));
|
|
2245
|
+
right.appendChild(mark(80, 18));
|
|
2246
|
+
body.appendChild(right);
|
|
2247
|
+
return body;
|
|
2248
|
+
}
|
|
2249
|
+
if (row.variant === 'loading' && row.loadingStyle === 'spinner') {
|
|
2250
|
+
body.style.justifyContent = 'center';
|
|
2251
|
+
body.style.padding = '16px';
|
|
2252
|
+
const spinner = createElement(
|
|
2253
|
+
context.document,
|
|
2254
|
+
'span',
|
|
2255
|
+
'ok-native-list-market-spinner'
|
|
2256
|
+
);
|
|
2257
|
+
spinner.setAttribute('role', 'progressbar');
|
|
2258
|
+
// Same 20px SVG and 750ms rotation as react-native-web ActivityIndicator.
|
|
2259
|
+
spinner.innerHTML =
|
|
2260
|
+
'<svg viewBox="0 0 32 32" width="20" height="20"><circle cx="16" cy="16" r="14" fill="none" stroke="currentColor" stroke-width="4" opacity="0.2"/><circle cx="16" cy="16" r="14" fill="none" stroke="currentColor" stroke-width="4" stroke-dasharray="80" stroke-dashoffset="60"/></svg>';
|
|
2261
|
+
body.appendChild(spinner);
|
|
2262
|
+
return body;
|
|
2263
|
+
}
|
|
2264
|
+
if ('presentation' in row && row.presentation === 'market') {
|
|
2265
|
+
if (row.variant === 'noMatch') {
|
|
2266
|
+
body.style.justifyContent = 'center';
|
|
2267
|
+
body.style.padding = '32px';
|
|
2268
|
+
const message = createElement(context.document, 'span', '', row.message);
|
|
2269
|
+
message.style.fontSize = '16px';
|
|
2270
|
+
message.style.lineHeight = '24px';
|
|
2271
|
+
body.appendChild(message);
|
|
2272
|
+
return body;
|
|
2273
|
+
}
|
|
2274
|
+
if (row.variant === 'end') {
|
|
2275
|
+
body.style.justifyContent = 'center';
|
|
2276
|
+
body.style.padding = '16px';
|
|
2277
|
+
body.style.gap = '8px';
|
|
2278
|
+
for (const width of [80, 4, 80]) {
|
|
2279
|
+
const mark = createElement(context.document, 'span', '');
|
|
2280
|
+
mark.style.width = String(width) + 'px';
|
|
2281
|
+
mark.style.height = width === 4 ? '4px' : '1px';
|
|
2282
|
+
mark.style.borderRadius = width === 4 ? '2px' : '0';
|
|
2283
|
+
mark.style.background = 'var(--nl-separator)';
|
|
2284
|
+
body.appendChild(mark);
|
|
2285
|
+
}
|
|
2286
|
+
return body;
|
|
2287
|
+
}
|
|
2288
|
+
}
|
|
2092
2289
|
if (row.variant === 'warning') {
|
|
2093
2290
|
body.classList.add('ok-native-list-warning');
|
|
2094
2291
|
body.style.borderColor = row.borderColor ?? 'var(--nl-separator)';
|
|
@@ -2784,6 +2981,266 @@ function createWalletGroupRow(
|
|
|
2784
2981
|
return body;
|
|
2785
2982
|
}
|
|
2786
2983
|
|
|
2984
|
+
function marketFontWeight(
|
|
2985
|
+
value: MarketTextStyle['fontWeight'] | undefined,
|
|
2986
|
+
fallback: number
|
|
2987
|
+
): number {
|
|
2988
|
+
if (value === 'bold') return 700;
|
|
2989
|
+
if (value === 'semibold') return 600;
|
|
2990
|
+
if (value === 'medium') return 500;
|
|
2991
|
+
if (value === 'regular') return 400;
|
|
2992
|
+
return fallback;
|
|
2993
|
+
}
|
|
2994
|
+
|
|
2995
|
+
function applyMarketTextStyle(
|
|
2996
|
+
element: HTMLElement,
|
|
2997
|
+
style: MarketTextStyle | undefined,
|
|
2998
|
+
defaults: Readonly<{
|
|
2999
|
+
fontSize: number;
|
|
3000
|
+
lineHeight: number;
|
|
3001
|
+
weight: number;
|
|
3002
|
+
alignment: 'start' | 'center' | 'end';
|
|
3003
|
+
}>
|
|
3004
|
+
) {
|
|
3005
|
+
element.style.fontSize = String(style?.fontSize ?? defaults.fontSize) + 'px';
|
|
3006
|
+
element.style.lineHeight =
|
|
3007
|
+
String(style?.lineHeight ?? defaults.lineHeight) + 'px';
|
|
3008
|
+
element.style.fontWeight = String(
|
|
3009
|
+
marketFontWeight(style?.fontWeight, defaults.weight)
|
|
3010
|
+
);
|
|
3011
|
+
element.style.color = style?.color ?? '';
|
|
3012
|
+
element.style.textAlign = style?.alignment ?? defaults.alignment;
|
|
3013
|
+
element.style.whiteSpace = style?.lines === 2 ? 'normal' : 'nowrap';
|
|
3014
|
+
element.style.display = '';
|
|
3015
|
+
element.style.removeProperty('-webkit-line-clamp');
|
|
3016
|
+
element.style.removeProperty('-webkit-box-orient');
|
|
3017
|
+
if (style?.lines === 2) {
|
|
3018
|
+
element.style.display = '-webkit-box';
|
|
3019
|
+
element.style.setProperty('-webkit-line-clamp', '2');
|
|
3020
|
+
element.style.setProperty('-webkit-box-orient', 'vertical');
|
|
3021
|
+
}
|
|
3022
|
+
}
|
|
3023
|
+
|
|
3024
|
+
function setMarketQuoteContent(element: HTMLElement, row: MarketRow) {
|
|
3025
|
+
const style = row.style;
|
|
3026
|
+
const layoutStyle = resolveWebMarketLayoutStyle(row);
|
|
3027
|
+
const price = element.querySelector<HTMLElement>(
|
|
3028
|
+
'.ok-native-list-market-price'
|
|
3029
|
+
);
|
|
3030
|
+
if (price) {
|
|
3031
|
+
price.textContent = row.price;
|
|
3032
|
+
applyMarketTextStyle(price, style?.price, {
|
|
3033
|
+
fontSize: 16,
|
|
3034
|
+
lineHeight: 24,
|
|
3035
|
+
weight: 500,
|
|
3036
|
+
alignment: 'end',
|
|
3037
|
+
});
|
|
3038
|
+
applyValueSegments(
|
|
3039
|
+
price,
|
|
3040
|
+
row.priceSegments,
|
|
3041
|
+
style?.price?.fontSize ?? 16,
|
|
3042
|
+
style?.price?.lineHeight ?? 24,
|
|
3043
|
+
marketFontWeight(style?.price?.fontWeight, 500)
|
|
3044
|
+
);
|
|
3045
|
+
}
|
|
3046
|
+
const change = element.querySelector<HTMLElement>(
|
|
3047
|
+
'.ok-native-list-market-change'
|
|
3048
|
+
);
|
|
3049
|
+
if (change) {
|
|
3050
|
+
change.textContent = row.change.text;
|
|
3051
|
+
setData(change, 'tone', row.change.tone);
|
|
3052
|
+
applyMarketTextStyle(change, style?.change, {
|
|
3053
|
+
fontSize: 14,
|
|
3054
|
+
lineHeight: 20,
|
|
3055
|
+
weight: 500,
|
|
3056
|
+
alignment: 'center',
|
|
3057
|
+
});
|
|
3058
|
+
applyValueSegments(
|
|
3059
|
+
change,
|
|
3060
|
+
row.change.textSegments,
|
|
3061
|
+
style?.change?.fontSize ?? 14,
|
|
3062
|
+
style?.change?.lineHeight ?? 20,
|
|
3063
|
+
marketFontWeight(style?.change?.fontWeight, 500)
|
|
3064
|
+
);
|
|
3065
|
+
change.style.width = String(layoutStyle.changeWidth) + 'px';
|
|
3066
|
+
change.style.height = String(layoutStyle.changeHeight) + 'px';
|
|
3067
|
+
change.style.borderRadius = String(layoutStyle.changeCornerRadius) + 'px';
|
|
3068
|
+
change.style.color = row.change.textColor ?? style?.change?.color ?? '';
|
|
3069
|
+
change.style.background = row.change.backgroundColor ?? '';
|
|
3070
|
+
}
|
|
3071
|
+
element.setAttribute(
|
|
3072
|
+
'aria-label',
|
|
3073
|
+
row.accessibilityLabel ??
|
|
3074
|
+
[row.title, row.subtitle, row.price, row.change.text]
|
|
3075
|
+
.filter(Boolean)
|
|
3076
|
+
.join(', ')
|
|
3077
|
+
);
|
|
3078
|
+
}
|
|
3079
|
+
|
|
3080
|
+
function createMarketRow(context: RenderContext, row: MarketRow): HTMLElement {
|
|
3081
|
+
const body = createElement(
|
|
3082
|
+
context.document,
|
|
3083
|
+
'div',
|
|
3084
|
+
'ok-native-list-row ok-native-list-market'
|
|
3085
|
+
);
|
|
3086
|
+
setData(body, 'variant', row.variant);
|
|
3087
|
+
const style = row.style;
|
|
3088
|
+
const layoutStyle = resolveWebMarketLayoutStyle(row);
|
|
3089
|
+
body.style.padding =
|
|
3090
|
+
String(layoutStyle.verticalPadding) +
|
|
3091
|
+
'px ' +
|
|
3092
|
+
String(layoutStyle.horizontalPadding) +
|
|
3093
|
+
'px';
|
|
3094
|
+
body.style.gap = '0px';
|
|
3095
|
+
const visual = createVisual(context, row.leading);
|
|
3096
|
+
if (visual) {
|
|
3097
|
+
const width = layoutStyle.imageWidth;
|
|
3098
|
+
const height = layoutStyle.imageHeight;
|
|
3099
|
+
visual.style.width = String(width) + 'px';
|
|
3100
|
+
visual.style.height = String(height) + 'px';
|
|
3101
|
+
visual.style.flexBasis = String(width) + 'px';
|
|
3102
|
+
visual.style.borderRadius = String(layoutStyle.imageCornerRadius) + 'px';
|
|
3103
|
+
const borderColor = 'borderColor' in row.leading ? row.leading.borderColor : undefined;
|
|
3104
|
+
if (borderColor) {
|
|
3105
|
+
visual.style.border = '1px solid ' + borderColor;
|
|
3106
|
+
visual.style.boxSizing = 'border-box';
|
|
3107
|
+
}
|
|
3108
|
+
visual.querySelectorAll<HTMLElement>('img').forEach((image) => {
|
|
3109
|
+
if (!image.classList.contains('ok-native-list-visual-corner')) {
|
|
3110
|
+
image.style.width = '100%';
|
|
3111
|
+
image.style.height = '100%';
|
|
3112
|
+
if (borderColor) {
|
|
3113
|
+
image.style.borderRadius = '0';
|
|
3114
|
+
image.style.clipPath = 'inset(-1px round ' + String(layoutStyle.imageCornerRadius) + 'px)';
|
|
3115
|
+
}
|
|
3116
|
+
image.style.objectFit =
|
|
3117
|
+
style?.image?.contentFit ?? image.style.objectFit;
|
|
3118
|
+
} else {
|
|
3119
|
+
image.style.width = '20px';
|
|
3120
|
+
image.style.height = '20px';
|
|
3121
|
+
if (borderColor) {
|
|
3122
|
+
image.style.right = '-5px';
|
|
3123
|
+
image.style.bottom = '-5px';
|
|
3124
|
+
}
|
|
3125
|
+
}
|
|
3126
|
+
});
|
|
3127
|
+
visual.style.marginRight = String(layoutStyle.leadingGap) + 'px';
|
|
3128
|
+
body.appendChild(visual);
|
|
3129
|
+
}
|
|
3130
|
+
const main = createElement(
|
|
3131
|
+
context.document,
|
|
3132
|
+
'span',
|
|
3133
|
+
'ok-native-list-market-main'
|
|
3134
|
+
);
|
|
3135
|
+
main.style.gap = String(style?.lineGap ?? 0) + 'px';
|
|
3136
|
+
const titleLine = createElement(
|
|
3137
|
+
context.document,
|
|
3138
|
+
'span',
|
|
3139
|
+
'ok-native-list-market-title-line'
|
|
3140
|
+
);
|
|
3141
|
+
titleLine.style.gap = String(layoutStyle.titleBadgeGap) + 'px';
|
|
3142
|
+
const title = createElement(
|
|
3143
|
+
context.document,
|
|
3144
|
+
'span',
|
|
3145
|
+
'ok-native-list-market-title',
|
|
3146
|
+
row.title
|
|
3147
|
+
);
|
|
3148
|
+
applyMarketTextStyle(title, style?.title, {
|
|
3149
|
+
fontSize: 16,
|
|
3150
|
+
lineHeight: 24,
|
|
3151
|
+
weight: 500,
|
|
3152
|
+
alignment: 'start',
|
|
3153
|
+
});
|
|
3154
|
+
titleLine.appendChild(title);
|
|
3155
|
+
row.badges?.forEach((badge, slot) => {
|
|
3156
|
+
const element = createElement(
|
|
3157
|
+
context.document,
|
|
3158
|
+
badge.actionKey ? 'button' : 'span',
|
|
3159
|
+
'ok-native-list-market-badge',
|
|
3160
|
+
badge.text
|
|
3161
|
+
);
|
|
3162
|
+
if (badge.actionKey) {
|
|
3163
|
+
element.setAttribute('type', 'button');
|
|
3164
|
+
setData(element, 'nativeListAction', badge.actionKey);
|
|
3165
|
+
markActionAnchorSource(element, 'marketBadge', slot);
|
|
3166
|
+
}
|
|
3167
|
+
setData(element, 'tone', badge.tone);
|
|
3168
|
+
element.style.color =
|
|
3169
|
+
badge.textColor ??
|
|
3170
|
+
(badge.tone === 'success'
|
|
3171
|
+
? 'var(--nl-positive)'
|
|
3172
|
+
: badge.tone === 'danger'
|
|
3173
|
+
? 'var(--nl-negative)'
|
|
3174
|
+
: badge.tone === 'info'
|
|
3175
|
+
? 'var(--nl-info)'
|
|
3176
|
+
: badge.tone === 'warning'
|
|
3177
|
+
? 'var(--nl-primary)'
|
|
3178
|
+
: '');
|
|
3179
|
+
element.style.background =
|
|
3180
|
+
badge.backgroundColor ??
|
|
3181
|
+
((badge.icon || badge.iconName) && !badge.text ? 'transparent' : '');
|
|
3182
|
+
if ((badge.icon || badge.iconName) && !badge.text) {
|
|
3183
|
+
element.style.padding = '0';
|
|
3184
|
+
}
|
|
3185
|
+
if (badge.accessibilityLabel)
|
|
3186
|
+
element.setAttribute('aria-label', badge.accessibilityLabel);
|
|
3187
|
+
if (badge.icon) {
|
|
3188
|
+
const icon = createImage(context, badge.icon);
|
|
3189
|
+
if (icon) {
|
|
3190
|
+
icon.style.borderRadius = '50%';
|
|
3191
|
+
element.prepend(icon);
|
|
3192
|
+
}
|
|
3193
|
+
}
|
|
3194
|
+
if (badge.iconName === 'verified') {
|
|
3195
|
+
const icon = createElement(
|
|
3196
|
+
context.document,
|
|
3197
|
+
'span',
|
|
3198
|
+
'ok-native-list-market-badge-icon'
|
|
3199
|
+
);
|
|
3200
|
+
applySelectorIcon(icon, 'BadgeVerifiedSolid');
|
|
3201
|
+
element.prepend(icon);
|
|
3202
|
+
}
|
|
3203
|
+
titleLine.appendChild(element);
|
|
3204
|
+
});
|
|
3205
|
+
main.appendChild(titleLine);
|
|
3206
|
+
if (row.subtitle || row.subtitleSegments?.length) {
|
|
3207
|
+
const subtitle = createElement(
|
|
3208
|
+
context.document,
|
|
3209
|
+
'span',
|
|
3210
|
+
'ok-native-list-market-subtitle',
|
|
3211
|
+
row.subtitle
|
|
3212
|
+
);
|
|
3213
|
+
applyMarketTextStyle(subtitle, style?.subtitle, {
|
|
3214
|
+
fontSize: 14,
|
|
3215
|
+
lineHeight: 20,
|
|
3216
|
+
weight: 400,
|
|
3217
|
+
alignment: 'start',
|
|
3218
|
+
});
|
|
3219
|
+
applyValueSegments(
|
|
3220
|
+
subtitle,
|
|
3221
|
+
row.subtitleSegments,
|
|
3222
|
+
style?.subtitle?.fontSize ?? 14,
|
|
3223
|
+
style?.subtitle?.lineHeight ?? 20,
|
|
3224
|
+
marketFontWeight(style?.subtitle?.fontWeight, 400)
|
|
3225
|
+
);
|
|
3226
|
+
main.appendChild(subtitle);
|
|
3227
|
+
}
|
|
3228
|
+
body.appendChild(main);
|
|
3229
|
+
const trailing = createElement(
|
|
3230
|
+
context.document,
|
|
3231
|
+
'span',
|
|
3232
|
+
'ok-native-list-market-trailing'
|
|
3233
|
+
);
|
|
3234
|
+
trailing.style.gap = String(layoutStyle.trailingGap) + 'px';
|
|
3235
|
+
trailing.append(
|
|
3236
|
+
createElement(context.document, 'span', 'ok-native-list-market-price'),
|
|
3237
|
+
createElement(context.document, 'span', 'ok-native-list-market-change')
|
|
3238
|
+
);
|
|
3239
|
+
body.appendChild(trailing);
|
|
3240
|
+
setMarketQuoteContent(body, row);
|
|
3241
|
+
return body;
|
|
3242
|
+
}
|
|
3243
|
+
|
|
2787
3244
|
function createRowBody(context: RenderContext, row: RowModel): HTMLElement {
|
|
2788
3245
|
switch (row.type) {
|
|
2789
3246
|
case 'walletGroup':
|
|
@@ -2802,6 +3259,8 @@ function createRowBody(context: RenderContext, row: RowModel): HTMLElement {
|
|
|
2802
3259
|
return createMetricRow(context, row);
|
|
2803
3260
|
case 'dataRow':
|
|
2804
3261
|
return createDataRow(context, row);
|
|
3262
|
+
case 'market':
|
|
3263
|
+
return createMarketRow(context, row);
|
|
2805
3264
|
case 'identity':
|
|
2806
3265
|
case 'activity':
|
|
2807
3266
|
case 'message':
|
|
@@ -2869,6 +3328,16 @@ export class NativeListWebEngine {
|
|
|
2869
3328
|
);
|
|
2870
3329
|
private actionAnchorCounter = 0;
|
|
2871
3330
|
private bindingEpochCounter = 0;
|
|
3331
|
+
private marketPointer:
|
|
3332
|
+
| Readonly<{
|
|
3333
|
+
pointerId: number;
|
|
3334
|
+
rowKey: string;
|
|
3335
|
+
startX: number;
|
|
3336
|
+
startY: number;
|
|
3337
|
+
timer: number;
|
|
3338
|
+
}>
|
|
3339
|
+
| undefined;
|
|
3340
|
+
private marketLongPressFired = false;
|
|
2872
3341
|
private lastViewportWidth = -1;
|
|
2873
3342
|
private lastViewportHeight = -1;
|
|
2874
3343
|
private destroyed = false;
|
|
@@ -2959,6 +3428,10 @@ export class NativeListWebEngine {
|
|
|
2959
3428
|
passive: true,
|
|
2960
3429
|
});
|
|
2961
3430
|
this.root.addEventListener('click', this.handleClick);
|
|
3431
|
+
this.root.addEventListener('pointerdown', this.handleMarketPointerDown);
|
|
3432
|
+
this.root.addEventListener('pointermove', this.handleMarketPointerMove);
|
|
3433
|
+
this.root.addEventListener('pointerup', this.handleMarketPointerEnd);
|
|
3434
|
+
this.root.addEventListener('pointercancel', this.handleMarketPointerEnd);
|
|
2962
3435
|
// OneKey patch: preserve web tooltip hover for section titles.
|
|
2963
3436
|
this.root.addEventListener('pointerover', this.handleTitlePointerOver);
|
|
2964
3437
|
this.root.addEventListener('pointerout', this.handleTitlePointerOut);
|
|
@@ -3034,7 +3507,6 @@ export class NativeListWebEngine {
|
|
|
3034
3507
|
applyPatches(patches: readonly RowPatch[]) {
|
|
3035
3508
|
if (patches.length === 0) return;
|
|
3036
3509
|
const next = applyRowPatches(this.snapshot, patches);
|
|
3037
|
-
this.invalidateActionAnchor('snapshot');
|
|
3038
3510
|
const selection = new Set(this.selectedKeys);
|
|
3039
3511
|
patches.forEach((patch) => {
|
|
3040
3512
|
const selected =
|
|
@@ -3042,6 +3514,29 @@ export class NativeListWebEngine {
|
|
|
3042
3514
|
if (selected === true) selection.add(patch.key);
|
|
3043
3515
|
else if (selected === false) selection.delete(patch.key);
|
|
3044
3516
|
});
|
|
3517
|
+
if (webMarketImageBindDeltaForPatches(patches) === 0) {
|
|
3518
|
+
this.snapshot = next;
|
|
3519
|
+
this.rows = effectiveRows(next);
|
|
3520
|
+
this.selectedKeys = selection;
|
|
3521
|
+
patches.forEach((patch) => {
|
|
3522
|
+
const index = this.rows.findIndex((row) => row.key === patch.key);
|
|
3523
|
+
const row = this.rows[index];
|
|
3524
|
+
const element = this.mounted.get(index);
|
|
3525
|
+
if (row?.type === 'market' && element) {
|
|
3526
|
+
setMarketQuoteContent(element, row);
|
|
3527
|
+
element.dataset.renderSignature = webRowRenderSignature(row);
|
|
3528
|
+
}
|
|
3529
|
+
if (
|
|
3530
|
+
row?.type === 'market' &&
|
|
3531
|
+
this.sticky.dataset.nativeListRowKey === row.key
|
|
3532
|
+
) {
|
|
3533
|
+
setMarketQuoteContent(this.sticky, row);
|
|
3534
|
+
this.sticky.dataset.renderSignature = webRowRenderSignature(row);
|
|
3535
|
+
}
|
|
3536
|
+
});
|
|
3537
|
+
return;
|
|
3538
|
+
}
|
|
3539
|
+
this.invalidateActionAnchor('snapshot');
|
|
3045
3540
|
this.setSnapshot(next, selection);
|
|
3046
3541
|
}
|
|
3047
3542
|
|
|
@@ -3180,6 +3675,11 @@ export class NativeListWebEngine {
|
|
|
3180
3675
|
);
|
|
3181
3676
|
this.viewport.removeEventListener('scroll', this.handleScroll);
|
|
3182
3677
|
this.root.removeEventListener('click', this.handleClick);
|
|
3678
|
+
this.cancelMarketPointer();
|
|
3679
|
+
this.root.removeEventListener('pointerdown', this.handleMarketPointerDown);
|
|
3680
|
+
this.root.removeEventListener('pointermove', this.handleMarketPointerMove);
|
|
3681
|
+
this.root.removeEventListener('pointerup', this.handleMarketPointerEnd);
|
|
3682
|
+
this.root.removeEventListener('pointercancel', this.handleMarketPointerEnd);
|
|
3183
3683
|
this.root.removeEventListener('pointerover', this.handleTitlePointerOver);
|
|
3184
3684
|
this.root.removeEventListener('pointerout', this.handleTitlePointerOut);
|
|
3185
3685
|
this.root.removeEventListener('keydown', this.handleKeyDown);
|
|
@@ -3230,6 +3730,7 @@ export class NativeListWebEngine {
|
|
|
3230
3730
|
snapshot: NativeListSnapshot,
|
|
3231
3731
|
selectedKeys?: ReadonlySet<string>
|
|
3232
3732
|
) {
|
|
3733
|
+
this.cancelMarketPointer();
|
|
3233
3734
|
this.measuredWarningHeights.clear();
|
|
3234
3735
|
this.snapshot = snapshot;
|
|
3235
3736
|
this.rows = effectiveRows(snapshot);
|
|
@@ -3580,6 +4081,17 @@ export class NativeListWebEngine {
|
|
|
3580
4081
|
}
|
|
3581
4082
|
}
|
|
3582
4083
|
element.replaceChildren(body);
|
|
4084
|
+
if (
|
|
4085
|
+
row.type === 'market' &&
|
|
4086
|
+
row.diagnostics?.imageBindActionKey &&
|
|
4087
|
+
body.querySelector('img')
|
|
4088
|
+
) {
|
|
4089
|
+
this.callbacks.onRowAction?.({
|
|
4090
|
+
rowKey: row.key,
|
|
4091
|
+
actionKey: row.diagnostics.imageBindActionKey,
|
|
4092
|
+
sectionKey: row.sectionKey,
|
|
4093
|
+
});
|
|
4094
|
+
}
|
|
3583
4095
|
}
|
|
3584
4096
|
|
|
3585
4097
|
private renderFooter() {
|
|
@@ -4102,6 +4614,8 @@ export class NativeListWebEngine {
|
|
|
4102
4614
|
? row.actionKey
|
|
4103
4615
|
: row.type === 'system' && row.variant === 'retry'
|
|
4104
4616
|
? row.actionKey
|
|
4617
|
+
: row.type === 'market' && row.pressActionKey
|
|
4618
|
+
? row.pressActionKey
|
|
4105
4619
|
: 'press';
|
|
4106
4620
|
if (rowElement && sourceElement) {
|
|
4107
4621
|
const anchor = this.createActionAnchor(sourceElement, rowElement, 'row');
|
|
@@ -4116,6 +4630,64 @@ export class NativeListWebEngine {
|
|
|
4116
4630
|
}
|
|
4117
4631
|
}
|
|
4118
4632
|
|
|
4633
|
+
private cancelMarketPointer() {
|
|
4634
|
+
const state = this.marketPointer;
|
|
4635
|
+
if (!state) return;
|
|
4636
|
+
this.document.defaultView?.clearTimeout(state.timer);
|
|
4637
|
+
this.marketPointer = undefined;
|
|
4638
|
+
}
|
|
4639
|
+
|
|
4640
|
+
private handleMarketPointerDown = (event: PointerEvent) => {
|
|
4641
|
+
if (event.button !== 0 || !(event.target instanceof Element)) return;
|
|
4642
|
+
this.marketLongPressFired = false;
|
|
4643
|
+
if (event.target.closest('[data-native-list-action]')) return;
|
|
4644
|
+
const rowElement = event.target.closest<HTMLElement>(
|
|
4645
|
+
'[data-native-list-row-key]'
|
|
4646
|
+
);
|
|
4647
|
+
const row = this.rowAtElement(rowElement);
|
|
4648
|
+
if (row?.type !== 'market' || row.disabled) return;
|
|
4649
|
+
this.cancelMarketPointer();
|
|
4650
|
+
if (row.pressInActionKey)
|
|
4651
|
+
this.emitRowAction(
|
|
4652
|
+
row,
|
|
4653
|
+
row.pressInActionKey,
|
|
4654
|
+
rowElement ?? undefined,
|
|
4655
|
+
rowElement ?? undefined
|
|
4656
|
+
);
|
|
4657
|
+
if (!row.longPressActionKey || !rowElement) return;
|
|
4658
|
+
markActionAnchorSource(rowElement, 'row');
|
|
4659
|
+
const timer = this.document.defaultView?.setTimeout(() => {
|
|
4660
|
+
const current = this.marketPointer;
|
|
4661
|
+
if (!current || current.pointerId !== event.pointerId) return;
|
|
4662
|
+
this.marketPointer = undefined;
|
|
4663
|
+
this.marketLongPressFired = true;
|
|
4664
|
+
this.emitRowAction(row, row.longPressActionKey!, rowElement, rowElement);
|
|
4665
|
+
}, MARKET_LONG_PRESS_MS);
|
|
4666
|
+
if (timer === undefined) return;
|
|
4667
|
+
this.marketPointer = {
|
|
4668
|
+
pointerId: event.pointerId,
|
|
4669
|
+
rowKey: row.key,
|
|
4670
|
+
startX: event.clientX,
|
|
4671
|
+
startY: event.clientY,
|
|
4672
|
+
timer,
|
|
4673
|
+
};
|
|
4674
|
+
};
|
|
4675
|
+
|
|
4676
|
+
private handleMarketPointerMove = (event: PointerEvent) => {
|
|
4677
|
+
const state = this.marketPointer;
|
|
4678
|
+
if (!state || state.pointerId !== event.pointerId) return;
|
|
4679
|
+
if (
|
|
4680
|
+
Math.abs(event.clientX - state.startX) > MARKET_MOVE_CANCEL_PX ||
|
|
4681
|
+
Math.abs(event.clientY - state.startY) > MARKET_MOVE_CANCEL_PX
|
|
4682
|
+
)
|
|
4683
|
+
this.cancelMarketPointer();
|
|
4684
|
+
};
|
|
4685
|
+
|
|
4686
|
+
private handleMarketPointerEnd = (event: PointerEvent) => {
|
|
4687
|
+
if (this.marketPointer?.pointerId === event.pointerId)
|
|
4688
|
+
this.cancelMarketPointer();
|
|
4689
|
+
};
|
|
4690
|
+
|
|
4119
4691
|
// OneKey patch: hover opens the same anchored help action as native taps.
|
|
4120
4692
|
private handleTitlePointerOver = (event: PointerEvent) => {
|
|
4121
4693
|
const target = event.target;
|
|
@@ -4167,7 +4739,8 @@ export class NativeListWebEngine {
|
|
|
4167
4739
|
};
|
|
4168
4740
|
|
|
4169
4741
|
private handleClick = (event: Event) => {
|
|
4170
|
-
if (Date.now() < this.suppressClickUntil) {
|
|
4742
|
+
if (this.marketLongPressFired || Date.now() < this.suppressClickUntil) {
|
|
4743
|
+
this.marketLongPressFired = false;
|
|
4171
4744
|
event.preventDefault();
|
|
4172
4745
|
event.stopPropagation();
|
|
4173
4746
|
return;
|
|
@@ -4340,6 +4913,7 @@ export class NativeListWebEngine {
|
|
|
4340
4913
|
}
|
|
4341
4914
|
|
|
4342
4915
|
private handleScroll = () => {
|
|
4916
|
+
this.cancelMarketPointer();
|
|
4343
4917
|
this.invalidateActionAnchor('scroll');
|
|
4344
4918
|
this.scheduleFrame();
|
|
4345
4919
|
};
|