@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
|
@@ -20,6 +20,9 @@ export const WEB_REORDER_ANIMATION = {
|
|
|
20
20
|
dropTimingFunction: 'ease'
|
|
21
21
|
};
|
|
22
22
|
const REORDER_TOUCH_LONG_PRESS_MS = 120;
|
|
23
|
+
const MARKET_LONG_PRESS_MS = 800;
|
|
24
|
+
const MARKET_MOVE_CANCEL_PX = 10;
|
|
25
|
+
export const WEB_MARKET_VERIFIED_PATH = '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';
|
|
23
26
|
const REORDER_MOUSE_MOVE_THRESHOLD_PX = 5;
|
|
24
27
|
const REORDER_EDGE_RATIO = 0.25;
|
|
25
28
|
const REORDER_MAX_SPEED_ZONE_RATIO = 0.05;
|
|
@@ -50,6 +53,25 @@ const defaultTheme = {
|
|
|
50
53
|
inverseText: '#FCFCFC',
|
|
51
54
|
info: '#0D74CE'
|
|
52
55
|
};
|
|
56
|
+
/** Resolves every reusable Market geometry field, including legacy defaults. */
|
|
57
|
+
export function resolveWebMarketLayoutStyle(row) {
|
|
58
|
+
const style = row.style;
|
|
59
|
+
const imageWidth = style?.image?.width ?? (row.variant === 'stock' ? 40 : 32);
|
|
60
|
+
const imageHeight = style?.image?.height ?? (row.variant === 'stock' ? 40 : 32);
|
|
61
|
+
return {
|
|
62
|
+
horizontalPadding: style?.horizontalPadding ?? (row.variant === 'perp' ? 16 : 20),
|
|
63
|
+
verticalPadding: style?.verticalPadding ?? 12,
|
|
64
|
+
leadingGap: style?.leadingGap ?? (row.variant === 'perp' ? 8 : 14),
|
|
65
|
+
titleBadgeGap: style?.titleBadgeGap ?? 4,
|
|
66
|
+
trailingGap: style?.trailingGap ?? 8,
|
|
67
|
+
imageWidth,
|
|
68
|
+
imageHeight,
|
|
69
|
+
imageCornerRadius: style?.image?.cornerRadius ?? (style?.image?.shape === 'square' ? 0 : style?.image?.shape === 'rounded' ? 8 : Math.min(imageWidth, imageHeight) / 2),
|
|
70
|
+
changeWidth: style?.changeWidth ?? 80,
|
|
71
|
+
changeHeight: style?.changeHeight ?? 32,
|
|
72
|
+
changeCornerRadius: style?.changeCornerRadius ?? 8
|
|
73
|
+
};
|
|
74
|
+
}
|
|
53
75
|
export function webActionAnchorPayload(token, rect, source, generation, layoutDirection, slot) {
|
|
54
76
|
return {
|
|
55
77
|
token,
|
|
@@ -195,7 +217,7 @@ export function estimateWebRowHeight(row, snapshot, availableWidth) {
|
|
|
195
217
|
break;
|
|
196
218
|
}
|
|
197
219
|
case 'system':
|
|
198
|
-
base = row.variant === 'noMatch' || row.variant === 'end' ? 36 : row.variant === 'retry' ? 44 : 56;
|
|
220
|
+
base = row.variant === 'loading' && row.loadingStyle === 'skeleton' ? 56 : row.variant === 'loading' && row.loadingStyle === 'spinner' ? 52 : 'presentation' in row && row.presentation === 'market' ? row.variant === 'loading' ? 68 : 44 : row.variant === 'noMatch' || row.variant === 'end' ? 36 : row.variant === 'retry' ? 44 : 56;
|
|
199
221
|
break;
|
|
200
222
|
case 'action':
|
|
201
223
|
base = row.presentation === 'accountSelector' ? 48 : row.icon ? 60 : 44;
|
|
@@ -203,6 +225,12 @@ export function estimateWebRowHeight(row, snapshot, availableWidth) {
|
|
|
203
225
|
case 'dataRow':
|
|
204
226
|
base = row.columns.some(column => column.secondaryText) ? 60 : 56;
|
|
205
227
|
break;
|
|
228
|
+
case 'market':
|
|
229
|
+
{
|
|
230
|
+
const marketStyle = resolveWebMarketLayoutStyle(row);
|
|
231
|
+
base = Math.max(row.variant === 'stock' ? 72 : 68, marketStyle.imageHeight + marketStyle.verticalPadding * 2);
|
|
232
|
+
break;
|
|
233
|
+
}
|
|
206
234
|
case 'identity':
|
|
207
235
|
base = row.tertiary ? 72 : row.subtitle ? 60 : 56;
|
|
208
236
|
break;
|
|
@@ -391,6 +419,15 @@ function rowWithoutSelectionState(row) {
|
|
|
391
419
|
export function webRowRenderSignature(row) {
|
|
392
420
|
return JSON.stringify(rowWithoutSelectionState(row));
|
|
393
421
|
}
|
|
422
|
+
const MARKET_QUOTE_PATCH_FIELDS = new Set(['revision', 'price', 'priceSegments', 'change', 'accessibilityLabel']);
|
|
423
|
+
export function isWebMarketQuotePatch(patch) {
|
|
424
|
+
return patch.type === 'market' && Object.keys(patch.changes).every(key => MARKET_QUOTE_PATCH_FIELDS.has(key));
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/** Number of Market image-binding passes caused by one Web patch transaction. */
|
|
428
|
+
export function webMarketImageBindDeltaForPatches(patches) {
|
|
429
|
+
return patches.length > 0 && patches.every(isWebMarketQuotePatch) ? 0 : 1;
|
|
430
|
+
}
|
|
394
431
|
|
|
395
432
|
// OneKey patch: selector names must shrink before the sidebar clips their contents.
|
|
396
433
|
export const WEB_LIST_CSS = `
|
|
@@ -448,11 +485,14 @@ export const WEB_LIST_CSS = `
|
|
|
448
485
|
.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}
|
|
449
486
|
.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)}
|
|
450
487
|
.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}
|
|
488
|
+
.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)}
|
|
489
|
+
.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}
|
|
451
490
|
.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)}
|
|
452
491
|
.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
492
|
.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
493
|
.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}
|
|
455
|
-
|
|
494
|
+
.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}
|
|
495
|
+
@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)}}
|
|
456
496
|
/* OneKey patch: selector controls follow their original semantic colors and geometry. */
|
|
457
497
|
.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
498
|
.ok-native-list-checkbox[data-selector="networkSelector"]::after{display:none}
|
|
@@ -812,6 +852,15 @@ const selectorIcons = {
|
|
|
812
852
|
fillRule: 'nonzero',
|
|
813
853
|
opacity: 1
|
|
814
854
|
}]
|
|
855
|
+
},
|
|
856
|
+
BadgeVerifiedSolid: {
|
|
857
|
+
viewBox: '0 0 24 24',
|
|
858
|
+
paths: [{
|
|
859
|
+
d: WEB_MARKET_VERIFIED_PATH,
|
|
860
|
+
fill: 'currentColor',
|
|
861
|
+
fillRule: 'evenodd',
|
|
862
|
+
opacity: 1
|
|
863
|
+
}]
|
|
815
864
|
}
|
|
816
865
|
};
|
|
817
866
|
function applySelectorIcon(element, name) {
|
|
@@ -859,6 +908,7 @@ function visualFromRow(row) {
|
|
|
859
908
|
if (row.type === 'activity') return row.leading;
|
|
860
909
|
if (row.type === 'message') return row.leading;
|
|
861
910
|
if (row.type === 'dataRow') return row.leading;
|
|
911
|
+
if (row.type === 'market') return row.leading;
|
|
862
912
|
if (row.type === 'metricCard') return row.visual;
|
|
863
913
|
return undefined;
|
|
864
914
|
}
|
|
@@ -1266,6 +1316,69 @@ function createActionRow(context, row) {
|
|
|
1266
1316
|
function createSystemRow(context, row) {
|
|
1267
1317
|
const body = createElement(context.document, 'div', 'ok-native-list-row ok-native-list-system');
|
|
1268
1318
|
setData(body, 'variant', row.variant);
|
|
1319
|
+
if ('presentation' in row) setData(body, 'nativeListPresentation', row.presentation);
|
|
1320
|
+
if (row.variant === 'loading' && row.loadingStyle === 'skeleton') {
|
|
1321
|
+
body.classList.add('ok-native-list-market-skeleton');
|
|
1322
|
+
const background = resolvedTheme(context.snapshot).background;
|
|
1323
|
+
const rgb = Number.parseInt(background.slice(1, 7), 16);
|
|
1324
|
+
const dark = (rgb >> 16 & 255) * 0.299 + (rgb >> 8 & 255) * 0.587 + (rgb & 255) * 0.114 < 128;
|
|
1325
|
+
body.style.setProperty('--nl-skeleton-base', dark ? '#111111' : '#fafafa');
|
|
1326
|
+
body.style.setProperty('--nl-skeleton-highlight', dark ? '#333333' : '#cdcdcd');
|
|
1327
|
+
const left = createElement(context.document, 'div', 'ok-native-list-skeleton-left');
|
|
1328
|
+
const mark = (width, height, circle = false) => {
|
|
1329
|
+
const element = createElement(context.document, 'span', 'ok-native-list-skeleton-mark');
|
|
1330
|
+
element.style.width = `${width}px`;
|
|
1331
|
+
element.style.height = `${height}px`;
|
|
1332
|
+
if (circle) element.style.borderRadius = '50%';
|
|
1333
|
+
return element;
|
|
1334
|
+
};
|
|
1335
|
+
left.appendChild(mark(32, 32, true));
|
|
1336
|
+
const text = createElement(context.document, 'div', 'ok-native-list-skeleton-text');
|
|
1337
|
+
text.appendChild(mark(80, 16));
|
|
1338
|
+
text.appendChild(mark(60, 12));
|
|
1339
|
+
left.appendChild(text);
|
|
1340
|
+
body.appendChild(left);
|
|
1341
|
+
const right = createElement(context.document, 'div', 'ok-native-list-skeleton-right');
|
|
1342
|
+
right.appendChild(mark(80, 18));
|
|
1343
|
+
right.appendChild(mark(80, 18));
|
|
1344
|
+
body.appendChild(right);
|
|
1345
|
+
return body;
|
|
1346
|
+
}
|
|
1347
|
+
if (row.variant === 'loading' && row.loadingStyle === 'spinner') {
|
|
1348
|
+
body.style.justifyContent = 'center';
|
|
1349
|
+
body.style.padding = '16px';
|
|
1350
|
+
const spinner = createElement(context.document, 'span', 'ok-native-list-market-spinner');
|
|
1351
|
+
spinner.setAttribute('role', 'progressbar');
|
|
1352
|
+
// Same 20px SVG and 750ms rotation as react-native-web ActivityIndicator.
|
|
1353
|
+
spinner.innerHTML = '<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>';
|
|
1354
|
+
body.appendChild(spinner);
|
|
1355
|
+
return body;
|
|
1356
|
+
}
|
|
1357
|
+
if ('presentation' in row && row.presentation === 'market') {
|
|
1358
|
+
if (row.variant === 'noMatch') {
|
|
1359
|
+
body.style.justifyContent = 'center';
|
|
1360
|
+
body.style.padding = '32px';
|
|
1361
|
+
const message = createElement(context.document, 'span', '', row.message);
|
|
1362
|
+
message.style.fontSize = '16px';
|
|
1363
|
+
message.style.lineHeight = '24px';
|
|
1364
|
+
body.appendChild(message);
|
|
1365
|
+
return body;
|
|
1366
|
+
}
|
|
1367
|
+
if (row.variant === 'end') {
|
|
1368
|
+
body.style.justifyContent = 'center';
|
|
1369
|
+
body.style.padding = '16px';
|
|
1370
|
+
body.style.gap = '8px';
|
|
1371
|
+
for (const width of [80, 4, 80]) {
|
|
1372
|
+
const mark = createElement(context.document, 'span', '');
|
|
1373
|
+
mark.style.width = String(width) + 'px';
|
|
1374
|
+
mark.style.height = width === 4 ? '4px' : '1px';
|
|
1375
|
+
mark.style.borderRadius = width === 4 ? '2px' : '0';
|
|
1376
|
+
mark.style.background = 'var(--nl-separator)';
|
|
1377
|
+
body.appendChild(mark);
|
|
1378
|
+
}
|
|
1379
|
+
return body;
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1269
1382
|
if (row.variant === 'warning') {
|
|
1270
1383
|
body.classList.add('ok-native-list-warning');
|
|
1271
1384
|
body.style.borderColor = row.borderColor ?? 'var(--nl-separator)';
|
|
@@ -1555,6 +1668,163 @@ function createWalletGroupRow(context, row) {
|
|
|
1555
1668
|
});
|
|
1556
1669
|
return body;
|
|
1557
1670
|
}
|
|
1671
|
+
function marketFontWeight(value, fallback) {
|
|
1672
|
+
if (value === 'bold') return 700;
|
|
1673
|
+
if (value === 'semibold') return 600;
|
|
1674
|
+
if (value === 'medium') return 500;
|
|
1675
|
+
if (value === 'regular') return 400;
|
|
1676
|
+
return fallback;
|
|
1677
|
+
}
|
|
1678
|
+
function applyMarketTextStyle(element, style, defaults) {
|
|
1679
|
+
element.style.fontSize = String(style?.fontSize ?? defaults.fontSize) + 'px';
|
|
1680
|
+
element.style.lineHeight = String(style?.lineHeight ?? defaults.lineHeight) + 'px';
|
|
1681
|
+
element.style.fontWeight = String(marketFontWeight(style?.fontWeight, defaults.weight));
|
|
1682
|
+
element.style.color = style?.color ?? '';
|
|
1683
|
+
element.style.textAlign = style?.alignment ?? defaults.alignment;
|
|
1684
|
+
element.style.whiteSpace = style?.lines === 2 ? 'normal' : 'nowrap';
|
|
1685
|
+
element.style.display = '';
|
|
1686
|
+
element.style.removeProperty('-webkit-line-clamp');
|
|
1687
|
+
element.style.removeProperty('-webkit-box-orient');
|
|
1688
|
+
if (style?.lines === 2) {
|
|
1689
|
+
element.style.display = '-webkit-box';
|
|
1690
|
+
element.style.setProperty('-webkit-line-clamp', '2');
|
|
1691
|
+
element.style.setProperty('-webkit-box-orient', 'vertical');
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1694
|
+
function setMarketQuoteContent(element, row) {
|
|
1695
|
+
const style = row.style;
|
|
1696
|
+
const layoutStyle = resolveWebMarketLayoutStyle(row);
|
|
1697
|
+
const price = element.querySelector('.ok-native-list-market-price');
|
|
1698
|
+
if (price) {
|
|
1699
|
+
price.textContent = row.price;
|
|
1700
|
+
applyMarketTextStyle(price, style?.price, {
|
|
1701
|
+
fontSize: 16,
|
|
1702
|
+
lineHeight: 24,
|
|
1703
|
+
weight: 500,
|
|
1704
|
+
alignment: 'end'
|
|
1705
|
+
});
|
|
1706
|
+
applyValueSegments(price, row.priceSegments, style?.price?.fontSize ?? 16, style?.price?.lineHeight ?? 24, marketFontWeight(style?.price?.fontWeight, 500));
|
|
1707
|
+
}
|
|
1708
|
+
const change = element.querySelector('.ok-native-list-market-change');
|
|
1709
|
+
if (change) {
|
|
1710
|
+
change.textContent = row.change.text;
|
|
1711
|
+
setData(change, 'tone', row.change.tone);
|
|
1712
|
+
applyMarketTextStyle(change, style?.change, {
|
|
1713
|
+
fontSize: 14,
|
|
1714
|
+
lineHeight: 20,
|
|
1715
|
+
weight: 500,
|
|
1716
|
+
alignment: 'center'
|
|
1717
|
+
});
|
|
1718
|
+
applyValueSegments(change, row.change.textSegments, style?.change?.fontSize ?? 14, style?.change?.lineHeight ?? 20, marketFontWeight(style?.change?.fontWeight, 500));
|
|
1719
|
+
change.style.width = String(layoutStyle.changeWidth) + 'px';
|
|
1720
|
+
change.style.height = String(layoutStyle.changeHeight) + 'px';
|
|
1721
|
+
change.style.borderRadius = String(layoutStyle.changeCornerRadius) + 'px';
|
|
1722
|
+
change.style.color = row.change.textColor ?? style?.change?.color ?? '';
|
|
1723
|
+
change.style.background = row.change.backgroundColor ?? '';
|
|
1724
|
+
}
|
|
1725
|
+
element.setAttribute('aria-label', row.accessibilityLabel ?? [row.title, row.subtitle, row.price, row.change.text].filter(Boolean).join(', '));
|
|
1726
|
+
}
|
|
1727
|
+
function createMarketRow(context, row) {
|
|
1728
|
+
const body = createElement(context.document, 'div', 'ok-native-list-row ok-native-list-market');
|
|
1729
|
+
setData(body, 'variant', row.variant);
|
|
1730
|
+
const style = row.style;
|
|
1731
|
+
const layoutStyle = resolveWebMarketLayoutStyle(row);
|
|
1732
|
+
body.style.padding = String(layoutStyle.verticalPadding) + 'px ' + String(layoutStyle.horizontalPadding) + 'px';
|
|
1733
|
+
body.style.gap = '0px';
|
|
1734
|
+
const visual = createVisual(context, row.leading);
|
|
1735
|
+
if (visual) {
|
|
1736
|
+
const width = layoutStyle.imageWidth;
|
|
1737
|
+
const height = layoutStyle.imageHeight;
|
|
1738
|
+
visual.style.width = String(width) + 'px';
|
|
1739
|
+
visual.style.height = String(height) + 'px';
|
|
1740
|
+
visual.style.flexBasis = String(width) + 'px';
|
|
1741
|
+
visual.style.borderRadius = String(layoutStyle.imageCornerRadius) + 'px';
|
|
1742
|
+
const borderColor = 'borderColor' in row.leading ? row.leading.borderColor : undefined;
|
|
1743
|
+
if (borderColor) {
|
|
1744
|
+
visual.style.border = '1px solid ' + borderColor;
|
|
1745
|
+
visual.style.boxSizing = 'border-box';
|
|
1746
|
+
}
|
|
1747
|
+
visual.querySelectorAll('img').forEach(image => {
|
|
1748
|
+
if (!image.classList.contains('ok-native-list-visual-corner')) {
|
|
1749
|
+
image.style.width = '100%';
|
|
1750
|
+
image.style.height = '100%';
|
|
1751
|
+
if (borderColor) {
|
|
1752
|
+
image.style.borderRadius = '0';
|
|
1753
|
+
image.style.clipPath = 'inset(-1px round ' + String(layoutStyle.imageCornerRadius) + 'px)';
|
|
1754
|
+
}
|
|
1755
|
+
image.style.objectFit = style?.image?.contentFit ?? image.style.objectFit;
|
|
1756
|
+
} else {
|
|
1757
|
+
image.style.width = '20px';
|
|
1758
|
+
image.style.height = '20px';
|
|
1759
|
+
if (borderColor) {
|
|
1760
|
+
image.style.right = '-5px';
|
|
1761
|
+
image.style.bottom = '-5px';
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
});
|
|
1765
|
+
visual.style.marginRight = String(layoutStyle.leadingGap) + 'px';
|
|
1766
|
+
body.appendChild(visual);
|
|
1767
|
+
}
|
|
1768
|
+
const main = createElement(context.document, 'span', 'ok-native-list-market-main');
|
|
1769
|
+
main.style.gap = String(style?.lineGap ?? 0) + 'px';
|
|
1770
|
+
const titleLine = createElement(context.document, 'span', 'ok-native-list-market-title-line');
|
|
1771
|
+
titleLine.style.gap = String(layoutStyle.titleBadgeGap) + 'px';
|
|
1772
|
+
const title = createElement(context.document, 'span', 'ok-native-list-market-title', row.title);
|
|
1773
|
+
applyMarketTextStyle(title, style?.title, {
|
|
1774
|
+
fontSize: 16,
|
|
1775
|
+
lineHeight: 24,
|
|
1776
|
+
weight: 500,
|
|
1777
|
+
alignment: 'start'
|
|
1778
|
+
});
|
|
1779
|
+
titleLine.appendChild(title);
|
|
1780
|
+
row.badges?.forEach((badge, slot) => {
|
|
1781
|
+
const element = createElement(context.document, badge.actionKey ? 'button' : 'span', 'ok-native-list-market-badge', badge.text);
|
|
1782
|
+
if (badge.actionKey) {
|
|
1783
|
+
element.setAttribute('type', 'button');
|
|
1784
|
+
setData(element, 'nativeListAction', badge.actionKey);
|
|
1785
|
+
markActionAnchorSource(element, 'marketBadge', slot);
|
|
1786
|
+
}
|
|
1787
|
+
setData(element, 'tone', badge.tone);
|
|
1788
|
+
element.style.color = badge.textColor ?? (badge.tone === 'success' ? 'var(--nl-positive)' : badge.tone === 'danger' ? 'var(--nl-negative)' : badge.tone === 'info' ? 'var(--nl-info)' : badge.tone === 'warning' ? 'var(--nl-primary)' : '');
|
|
1789
|
+
element.style.background = badge.backgroundColor ?? ((badge.icon || badge.iconName) && !badge.text ? 'transparent' : '');
|
|
1790
|
+
if ((badge.icon || badge.iconName) && !badge.text) {
|
|
1791
|
+
element.style.padding = '0';
|
|
1792
|
+
}
|
|
1793
|
+
if (badge.accessibilityLabel) element.setAttribute('aria-label', badge.accessibilityLabel);
|
|
1794
|
+
if (badge.icon) {
|
|
1795
|
+
const icon = createImage(context, badge.icon);
|
|
1796
|
+
if (icon) {
|
|
1797
|
+
icon.style.borderRadius = '50%';
|
|
1798
|
+
element.prepend(icon);
|
|
1799
|
+
}
|
|
1800
|
+
}
|
|
1801
|
+
if (badge.iconName === 'verified') {
|
|
1802
|
+
const icon = createElement(context.document, 'span', 'ok-native-list-market-badge-icon');
|
|
1803
|
+
applySelectorIcon(icon, 'BadgeVerifiedSolid');
|
|
1804
|
+
element.prepend(icon);
|
|
1805
|
+
}
|
|
1806
|
+
titleLine.appendChild(element);
|
|
1807
|
+
});
|
|
1808
|
+
main.appendChild(titleLine);
|
|
1809
|
+
if (row.subtitle || row.subtitleSegments?.length) {
|
|
1810
|
+
const subtitle = createElement(context.document, 'span', 'ok-native-list-market-subtitle', row.subtitle);
|
|
1811
|
+
applyMarketTextStyle(subtitle, style?.subtitle, {
|
|
1812
|
+
fontSize: 14,
|
|
1813
|
+
lineHeight: 20,
|
|
1814
|
+
weight: 400,
|
|
1815
|
+
alignment: 'start'
|
|
1816
|
+
});
|
|
1817
|
+
applyValueSegments(subtitle, row.subtitleSegments, style?.subtitle?.fontSize ?? 14, style?.subtitle?.lineHeight ?? 20, marketFontWeight(style?.subtitle?.fontWeight, 400));
|
|
1818
|
+
main.appendChild(subtitle);
|
|
1819
|
+
}
|
|
1820
|
+
body.appendChild(main);
|
|
1821
|
+
const trailing = createElement(context.document, 'span', 'ok-native-list-market-trailing');
|
|
1822
|
+
trailing.style.gap = String(layoutStyle.trailingGap) + 'px';
|
|
1823
|
+
trailing.append(createElement(context.document, 'span', 'ok-native-list-market-price'), createElement(context.document, 'span', 'ok-native-list-market-change'));
|
|
1824
|
+
body.appendChild(trailing);
|
|
1825
|
+
setMarketQuoteContent(body, row);
|
|
1826
|
+
return body;
|
|
1827
|
+
}
|
|
1558
1828
|
function createRowBody(context, row) {
|
|
1559
1829
|
switch (row.type) {
|
|
1560
1830
|
case 'walletGroup':
|
|
@@ -1573,6 +1843,8 @@ function createRowBody(context, row) {
|
|
|
1573
1843
|
return createMetricRow(context, row);
|
|
1574
1844
|
case 'dataRow':
|
|
1575
1845
|
return createDataRow(context, row);
|
|
1846
|
+
case 'market':
|
|
1847
|
+
return createMarketRow(context, row);
|
|
1576
1848
|
case 'identity':
|
|
1577
1849
|
case 'activity':
|
|
1578
1850
|
case 'message':
|
|
@@ -1600,6 +1872,7 @@ export class NativeListWebEngine {
|
|
|
1600
1872
|
actionAnchorInstanceId = String(++webNativeListInstanceCounter);
|
|
1601
1873
|
actionAnchorCounter = 0;
|
|
1602
1874
|
bindingEpochCounter = 0;
|
|
1875
|
+
marketLongPressFired = false;
|
|
1603
1876
|
lastViewportWidth = -1;
|
|
1604
1877
|
lastViewportHeight = -1;
|
|
1605
1878
|
destroyed = false;
|
|
@@ -1643,6 +1916,10 @@ export class NativeListWebEngine {
|
|
|
1643
1916
|
passive: true
|
|
1644
1917
|
});
|
|
1645
1918
|
this.root.addEventListener('click', this.handleClick);
|
|
1919
|
+
this.root.addEventListener('pointerdown', this.handleMarketPointerDown);
|
|
1920
|
+
this.root.addEventListener('pointermove', this.handleMarketPointerMove);
|
|
1921
|
+
this.root.addEventListener('pointerup', this.handleMarketPointerEnd);
|
|
1922
|
+
this.root.addEventListener('pointercancel', this.handleMarketPointerEnd);
|
|
1646
1923
|
// OneKey patch: preserve web tooltip hover for section titles.
|
|
1647
1924
|
this.root.addEventListener('pointerover', this.handleTitlePointerOver);
|
|
1648
1925
|
this.root.addEventListener('pointerout', this.handleTitlePointerOut);
|
|
@@ -1698,12 +1975,31 @@ export class NativeListWebEngine {
|
|
|
1698
1975
|
applyPatches(patches) {
|
|
1699
1976
|
if (patches.length === 0) return;
|
|
1700
1977
|
const next = applyRowPatches(this.snapshot, patches);
|
|
1701
|
-
this.invalidateActionAnchor('snapshot');
|
|
1702
1978
|
const selection = new Set(this.selectedKeys);
|
|
1703
1979
|
patches.forEach(patch => {
|
|
1704
1980
|
const selected = 'selected' in patch.changes ? patch.changes.selected : undefined;
|
|
1705
1981
|
if (selected === true) selection.add(patch.key);else if (selected === false) selection.delete(patch.key);
|
|
1706
1982
|
});
|
|
1983
|
+
if (webMarketImageBindDeltaForPatches(patches) === 0) {
|
|
1984
|
+
this.snapshot = next;
|
|
1985
|
+
this.rows = effectiveRows(next);
|
|
1986
|
+
this.selectedKeys = selection;
|
|
1987
|
+
patches.forEach(patch => {
|
|
1988
|
+
const index = this.rows.findIndex(row => row.key === patch.key);
|
|
1989
|
+
const row = this.rows[index];
|
|
1990
|
+
const element = this.mounted.get(index);
|
|
1991
|
+
if (row?.type === 'market' && element) {
|
|
1992
|
+
setMarketQuoteContent(element, row);
|
|
1993
|
+
element.dataset.renderSignature = webRowRenderSignature(row);
|
|
1994
|
+
}
|
|
1995
|
+
if (row?.type === 'market' && this.sticky.dataset.nativeListRowKey === row.key) {
|
|
1996
|
+
setMarketQuoteContent(this.sticky, row);
|
|
1997
|
+
this.sticky.dataset.renderSignature = webRowRenderSignature(row);
|
|
1998
|
+
}
|
|
1999
|
+
});
|
|
2000
|
+
return;
|
|
2001
|
+
}
|
|
2002
|
+
this.invalidateActionAnchor('snapshot');
|
|
1707
2003
|
this.setSnapshot(next, selection);
|
|
1708
2004
|
}
|
|
1709
2005
|
reconcileSelection(keys) {
|
|
@@ -1827,6 +2123,11 @@ export class NativeListWebEngine {
|
|
|
1827
2123
|
this.document.defaultView?.removeEventListener('resize', this.handleWindowResize);
|
|
1828
2124
|
this.viewport.removeEventListener('scroll', this.handleScroll);
|
|
1829
2125
|
this.root.removeEventListener('click', this.handleClick);
|
|
2126
|
+
this.cancelMarketPointer();
|
|
2127
|
+
this.root.removeEventListener('pointerdown', this.handleMarketPointerDown);
|
|
2128
|
+
this.root.removeEventListener('pointermove', this.handleMarketPointerMove);
|
|
2129
|
+
this.root.removeEventListener('pointerup', this.handleMarketPointerEnd);
|
|
2130
|
+
this.root.removeEventListener('pointercancel', this.handleMarketPointerEnd);
|
|
1830
2131
|
this.root.removeEventListener('pointerover', this.handleTitlePointerOver);
|
|
1831
2132
|
this.root.removeEventListener('pointerout', this.handleTitlePointerOut);
|
|
1832
2133
|
this.root.removeEventListener('keydown', this.handleKeyDown);
|
|
@@ -1858,6 +2159,7 @@ export class NativeListWebEngine {
|
|
|
1858
2159
|
this.avatarLeases.clear();
|
|
1859
2160
|
}
|
|
1860
2161
|
setSnapshot(snapshot, selectedKeys) {
|
|
2162
|
+
this.cancelMarketPointer();
|
|
1861
2163
|
this.measuredWarningHeights.clear();
|
|
1862
2164
|
this.snapshot = snapshot;
|
|
1863
2165
|
this.rows = effectiveRows(snapshot);
|
|
@@ -2107,6 +2409,13 @@ export class NativeListWebEngine {
|
|
|
2107
2409
|
}
|
|
2108
2410
|
}
|
|
2109
2411
|
element.replaceChildren(body);
|
|
2412
|
+
if (row.type === 'market' && row.diagnostics?.imageBindActionKey && body.querySelector('img')) {
|
|
2413
|
+
this.callbacks.onRowAction?.({
|
|
2414
|
+
rowKey: row.key,
|
|
2415
|
+
actionKey: row.diagnostics.imageBindActionKey,
|
|
2416
|
+
sectionKey: row.sectionKey
|
|
2417
|
+
});
|
|
2418
|
+
}
|
|
2110
2419
|
}
|
|
2111
2420
|
renderFooter() {
|
|
2112
2421
|
const row = this.snapshot.fixedFooter;
|
|
@@ -2421,7 +2730,7 @@ export class NativeListWebEngine {
|
|
|
2421
2730
|
}, row);
|
|
2422
2731
|
return;
|
|
2423
2732
|
}
|
|
2424
|
-
const actionKey = row.type === 'action' ? row.actionKey : row.type === 'system' && row.variant === 'retry' ? row.actionKey : 'press';
|
|
2733
|
+
const actionKey = row.type === 'action' ? row.actionKey : row.type === 'system' && row.variant === 'retry' ? row.actionKey : row.type === 'market' && row.pressActionKey ? row.pressActionKey : 'press';
|
|
2425
2734
|
if (rowElement && sourceElement) {
|
|
2426
2735
|
const anchor = this.createActionAnchor(sourceElement, rowElement, 'row');
|
|
2427
2736
|
this.callbacks.onRowAction?.({
|
|
@@ -2434,6 +2743,47 @@ export class NativeListWebEngine {
|
|
|
2434
2743
|
this.emitRowAction(row, actionKey);
|
|
2435
2744
|
}
|
|
2436
2745
|
}
|
|
2746
|
+
cancelMarketPointer() {
|
|
2747
|
+
const state = this.marketPointer;
|
|
2748
|
+
if (!state) return;
|
|
2749
|
+
this.document.defaultView?.clearTimeout(state.timer);
|
|
2750
|
+
this.marketPointer = undefined;
|
|
2751
|
+
}
|
|
2752
|
+
handleMarketPointerDown = event => {
|
|
2753
|
+
if (event.button !== 0 || !(event.target instanceof Element)) return;
|
|
2754
|
+
this.marketLongPressFired = false;
|
|
2755
|
+
if (event.target.closest('[data-native-list-action]')) return;
|
|
2756
|
+
const rowElement = event.target.closest('[data-native-list-row-key]');
|
|
2757
|
+
const row = this.rowAtElement(rowElement);
|
|
2758
|
+
if (row?.type !== 'market' || row.disabled) return;
|
|
2759
|
+
this.cancelMarketPointer();
|
|
2760
|
+
if (row.pressInActionKey) this.emitRowAction(row, row.pressInActionKey, rowElement ?? undefined, rowElement ?? undefined);
|
|
2761
|
+
if (!row.longPressActionKey || !rowElement) return;
|
|
2762
|
+
markActionAnchorSource(rowElement, 'row');
|
|
2763
|
+
const timer = this.document.defaultView?.setTimeout(() => {
|
|
2764
|
+
const current = this.marketPointer;
|
|
2765
|
+
if (!current || current.pointerId !== event.pointerId) return;
|
|
2766
|
+
this.marketPointer = undefined;
|
|
2767
|
+
this.marketLongPressFired = true;
|
|
2768
|
+
this.emitRowAction(row, row.longPressActionKey, rowElement, rowElement);
|
|
2769
|
+
}, MARKET_LONG_PRESS_MS);
|
|
2770
|
+
if (timer === undefined) return;
|
|
2771
|
+
this.marketPointer = {
|
|
2772
|
+
pointerId: event.pointerId,
|
|
2773
|
+
rowKey: row.key,
|
|
2774
|
+
startX: event.clientX,
|
|
2775
|
+
startY: event.clientY,
|
|
2776
|
+
timer
|
|
2777
|
+
};
|
|
2778
|
+
};
|
|
2779
|
+
handleMarketPointerMove = event => {
|
|
2780
|
+
const state = this.marketPointer;
|
|
2781
|
+
if (!state || state.pointerId !== event.pointerId) return;
|
|
2782
|
+
if (Math.abs(event.clientX - state.startX) > MARKET_MOVE_CANCEL_PX || Math.abs(event.clientY - state.startY) > MARKET_MOVE_CANCEL_PX) this.cancelMarketPointer();
|
|
2783
|
+
};
|
|
2784
|
+
handleMarketPointerEnd = event => {
|
|
2785
|
+
if (this.marketPointer?.pointerId === event.pointerId) this.cancelMarketPointer();
|
|
2786
|
+
};
|
|
2437
2787
|
|
|
2438
2788
|
// OneKey patch: hover opens the same anchored help action as native taps.
|
|
2439
2789
|
handleTitlePointerOver = event => {
|
|
@@ -2456,7 +2806,8 @@ export class NativeListWebEngine {
|
|
|
2456
2806
|
if (this.actionAnchor?.actionElement === action) this.invalidateActionAnchor('pointerLeave');
|
|
2457
2807
|
};
|
|
2458
2808
|
handleClick = event => {
|
|
2459
|
-
if (Date.now() < this.suppressClickUntil) {
|
|
2809
|
+
if (this.marketLongPressFired || Date.now() < this.suppressClickUntil) {
|
|
2810
|
+
this.marketLongPressFired = false;
|
|
2460
2811
|
event.preventDefault();
|
|
2461
2812
|
event.stopPropagation();
|
|
2462
2813
|
return;
|
|
@@ -2581,6 +2932,7 @@ export class NativeListWebEngine {
|
|
|
2581
2932
|
});
|
|
2582
2933
|
}
|
|
2583
2934
|
handleScroll = () => {
|
|
2935
|
+
this.cancelMarketPointer();
|
|
2584
2936
|
this.invalidateActionAnchor('scroll');
|
|
2585
2937
|
this.scheduleFrame();
|
|
2586
2938
|
};
|
|
@@ -28,6 +28,57 @@ export type BadgeModel = Readonly<{
|
|
|
28
28
|
text: string;
|
|
29
29
|
tone?: 'neutral' | 'info' | 'success' | 'warning' | 'danger';
|
|
30
30
|
}>;
|
|
31
|
+
export type MarketTextStyle = Readonly<{
|
|
32
|
+
fontSize?: number;
|
|
33
|
+
fontWeight?: 'regular' | 'medium' | 'semibold' | 'bold';
|
|
34
|
+
color?: string;
|
|
35
|
+
lineHeight?: number;
|
|
36
|
+
lines?: 1 | 2;
|
|
37
|
+
alignment?: 'start' | 'center' | 'end';
|
|
38
|
+
}>;
|
|
39
|
+
export type MarketImageStyle = Readonly<{
|
|
40
|
+
width?: number;
|
|
41
|
+
height?: number;
|
|
42
|
+
shape?: 'circle' | 'rounded' | 'square';
|
|
43
|
+
cornerRadius?: number;
|
|
44
|
+
contentFit?: ImageContentFit;
|
|
45
|
+
}>;
|
|
46
|
+
export type MarketRowStyle = Readonly<{
|
|
47
|
+
horizontalPadding?: number;
|
|
48
|
+
verticalPadding?: number;
|
|
49
|
+
leadingGap?: number;
|
|
50
|
+
/** Space between title and subtitle; 0 by default, bounded to 0..16. */
|
|
51
|
+
lineGap?: number;
|
|
52
|
+
titleBadgeGap?: number;
|
|
53
|
+
trailingGap?: number;
|
|
54
|
+
image?: MarketImageStyle;
|
|
55
|
+
title?: MarketTextStyle;
|
|
56
|
+
subtitle?: MarketTextStyle;
|
|
57
|
+
price?: MarketTextStyle;
|
|
58
|
+
change?: MarketTextStyle;
|
|
59
|
+
changeWidth?: number;
|
|
60
|
+
changeHeight?: number;
|
|
61
|
+
changeCornerRadius?: number;
|
|
62
|
+
}>;
|
|
63
|
+
export type MarketBadgeModel = Readonly<{
|
|
64
|
+
key: string;
|
|
65
|
+
text?: string;
|
|
66
|
+
/** Finite native glyph set; currently only the community verified mark. */
|
|
67
|
+
iconName?: 'verified';
|
|
68
|
+
icon?: ImageSource;
|
|
69
|
+
tone?: 'neutral' | 'info' | 'success' | 'warning' | 'danger';
|
|
70
|
+
textColor?: string;
|
|
71
|
+
backgroundColor?: string;
|
|
72
|
+
actionKey?: string;
|
|
73
|
+
accessibilityLabel?: string;
|
|
74
|
+
}>;
|
|
75
|
+
export type MarketChangeModel = Readonly<{
|
|
76
|
+
text: string;
|
|
77
|
+
textSegments?: readonly ValueTextSegment[];
|
|
78
|
+
tone: 'positive' | 'negative' | 'neutral';
|
|
79
|
+
textColor?: string;
|
|
80
|
+
backgroundColor?: string;
|
|
81
|
+
}>;
|
|
31
82
|
export type SelectorTextSegment = Readonly<{
|
|
32
83
|
text: string;
|
|
33
84
|
textSegments?: readonly ValueTextSegment[];
|
|
@@ -261,6 +312,26 @@ export type DataRow = RowBase & Readonly<{
|
|
|
261
312
|
favorite?: boolean;
|
|
262
313
|
favoriteActive?: boolean;
|
|
263
314
|
}>;
|
|
315
|
+
/** Native Market quote row. All values are already localized/formatted strings. */
|
|
316
|
+
export type MarketRow = RowBase & Readonly<{
|
|
317
|
+
type: 'market';
|
|
318
|
+
variant: 'token' | 'stock' | 'perp';
|
|
319
|
+
leading: LeadingVisual;
|
|
320
|
+
title: string;
|
|
321
|
+
subtitle?: string;
|
|
322
|
+
subtitleSegments?: readonly ValueTextSegment[];
|
|
323
|
+
price: string;
|
|
324
|
+
priceSegments?: readonly ValueTextSegment[];
|
|
325
|
+
change: MarketChangeModel;
|
|
326
|
+
badges?: readonly MarketBadgeModel[];
|
|
327
|
+
pressActionKey?: string;
|
|
328
|
+
pressInActionKey?: string;
|
|
329
|
+
longPressActionKey?: string;
|
|
330
|
+
diagnostics?: Readonly<{
|
|
331
|
+
imageBindActionKey?: string;
|
|
332
|
+
}>;
|
|
333
|
+
style?: MarketRowStyle;
|
|
334
|
+
}>;
|
|
264
335
|
export type MediaTileRow = RowBase & Readonly<{
|
|
265
336
|
type: 'mediaTile';
|
|
266
337
|
variant: 'gallery' | 'browserPreview';
|
|
@@ -335,10 +406,13 @@ export type ActionRow = RowBase & Readonly<{
|
|
|
335
406
|
export type SystemRow = RowBase & (Readonly<{
|
|
336
407
|
type: 'system';
|
|
337
408
|
variant: 'loading';
|
|
409
|
+
presentation?: 'market';
|
|
410
|
+
loadingStyle?: 'skeleton' | 'spinner';
|
|
338
411
|
message?: string;
|
|
339
412
|
}> | Readonly<{
|
|
340
413
|
type: 'system';
|
|
341
414
|
variant: 'retry';
|
|
415
|
+
presentation?: 'market';
|
|
342
416
|
message: string;
|
|
343
417
|
actionKey: string;
|
|
344
418
|
}> | Readonly<{
|
|
@@ -350,17 +424,19 @@ export type SystemRow = RowBase & (Readonly<{
|
|
|
350
424
|
}> | Readonly<{
|
|
351
425
|
type: 'system';
|
|
352
426
|
variant: 'noMatch';
|
|
427
|
+
presentation?: 'market';
|
|
353
428
|
message: string;
|
|
354
429
|
}> | Readonly<{
|
|
355
430
|
type: 'system';
|
|
356
431
|
variant: 'end';
|
|
432
|
+
presentation?: 'market';
|
|
357
433
|
message?: string;
|
|
358
434
|
}> | Readonly<{
|
|
359
435
|
type: 'system';
|
|
360
436
|
variant: 'spacer';
|
|
361
437
|
height: number;
|
|
362
438
|
}>);
|
|
363
|
-
export type RowModel = IdentityRow | WalletGroupRow | RailRow | ActivityRow | MessageRow | DataRow | MediaTileRow | MetricCardRow | SectionHeaderRow | ActionRow | SystemRow;
|
|
439
|
+
export type RowModel = IdentityRow | WalletGroupRow | RailRow | ActivityRow | MessageRow | DataRow | MarketRow | MediaTileRow | MetricCardRow | SectionHeaderRow | ActionRow | SystemRow;
|
|
364
440
|
export type NativeListTheme = Readonly<{
|
|
365
441
|
checkboxBackground?: string;
|
|
366
442
|
checkboxBorder?: string;
|
|
@@ -445,6 +521,10 @@ export type RowPatch = Readonly<{
|
|
|
445
521
|
type: 'dataRow';
|
|
446
522
|
key: string;
|
|
447
523
|
changes: Partial<Pick<DataRow, CommonPatchFields | 'leading' | 'columns' | 'checkbox' | 'index' | 'badge' | 'badges' | 'favorite' | 'favoriteActive'>>;
|
|
524
|
+
}> | Readonly<{
|
|
525
|
+
type: 'market';
|
|
526
|
+
key: string;
|
|
527
|
+
changes: Partial<Pick<MarketRow, CommonPatchFields | 'leading' | 'title' | 'subtitle' | 'subtitleSegments' | 'price' | 'priceSegments' | 'change' | 'badges' | 'pressActionKey' | 'pressInActionKey' | 'longPressActionKey' | 'diagnostics' | 'style'>>;
|
|
448
528
|
}> | Readonly<{
|
|
449
529
|
type: 'mediaTile';
|
|
450
530
|
key: string;
|
|
@@ -470,7 +550,7 @@ export type RowPatch = Readonly<{
|
|
|
470
550
|
message?: string;
|
|
471
551
|
}>;
|
|
472
552
|
}>;
|
|
473
|
-
export type NativeListActionSource = 'row' | 'leadingAction' | 'trailingAccessory' | 'footerAction' | 'mediaClose';
|
|
553
|
+
export type NativeListActionSource = 'row' | 'marketBadge' | 'leadingAction' | 'trailingAccessory' | 'footerAction' | 'mediaClose';
|
|
474
554
|
export type NativeListWindowRect = Readonly<{
|
|
475
555
|
x: number;
|
|
476
556
|
y: number;
|