@onekeyfe/react-native-native-list 3.0.157-alpha.254 → 3.0.157-alpha.255
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/build.gradle +7 -0
- package/android/src/main/java/com/onekey/nativelist/HybridNativeList.kt +20 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListActivityDetailsView.kt +179 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListActivityRenderer.kt +23 -2
- package/android/src/main/java/com/onekey/nativelist/NativeListContainerSlotAdapter.kt +53 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListEndAlignment.kt +5 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListMediaPreviewSlot.kt +215 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListMediaTileRenderer.kt +15 -6
- package/android/src/main/java/com/onekey/nativelist/NativeListModels.kt +3 -1
- package/android/src/main/java/com/onekey/nativelist/NativeListScrollPositionTracker.kt +29 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListSectionHeaderRenderer.kt +16 -1
- package/android/src/main/java/com/onekey/nativelist/NativeListView.kt +163 -26
- package/android/src/main/res/values/native_scroll_coordinator_ids.xml +4 -0
- package/android/src/test/java/com/margelo/nitro/nativelist/NativeListEndAlignmentTest.kt +34 -0
- package/android/src/test/java/com/margelo/nitro/nativelist/NativeListScrollPositionTrackerTest.kt +28 -0
- package/docs/DESIGN.md +4 -2
- package/docs/ROW_TEMPLATES.md +45 -0
- package/docs/SPEC.md +227 -1
- package/docs/STYLE_SPEC.md +8 -0
- package/ios/HybridNativeList.swift +30 -0
- package/ios/NativeListActivityDetailsView.swift +229 -0
- package/ios/NativeListActivityRenderer.swift +24 -2
- package/ios/NativeListMediaPreviewSlot.swift +199 -0
- package/ios/NativeListMediaTileRenderer.swift +10 -4
- package/ios/NativeListModels.swift +4 -1
- package/ios/NativeListScrollPositionTracker.swift +30 -0
- package/ios/NativeListSectionHeaderRenderer.swift +27 -1
- package/ios/RNCNativeListView.swift +159 -4
- package/ios/tests/NativeListActivityPresentationTests.swift +43 -0
- package/ios/tests/NativeListLifecycleTests.swift +123 -0
- package/ios/tests/NativeListMediaVisibilityTests.swift +42 -0
- package/ios/tests/NativeListScrollPositionTrackerTests.swift +25 -0
- package/lib/module/NativeList.js +56 -3
- package/lib/module/NativeList.web.js +5 -0
- package/lib/module/validation.js +64 -4
- package/lib/nitrogen/generated/android/c++/JFunc_void_bool.hpp +75 -0
- package/lib/nitrogen/generated/android/c++/JHybridNativeListSpec.cpp +39 -3
- package/lib/nitrogen/generated/android/c++/JHybridNativeListSpec.hpp +6 -0
- package/lib/nitrogen/generated/android/c++/views/JHybridNativeListStateUpdater.cpp +15 -0
- package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/nativelist/Func_void_bool.kt +78 -0
- package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/nativelist/HybridNativeListSpec.kt +26 -0
- package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/nativelist/views/HybridNativeListManager.kt +24 -9
- package/lib/nitrogen/generated/android/nativelistOnLoad.cpp +2 -0
- package/lib/nitrogen/generated/ios/NativeListModule-Swift-Cxx-Bridge.cpp +8 -0
- package/lib/nitrogen/generated/ios/NativeListModule-Swift-Cxx-Bridge.hpp +37 -0
- package/lib/nitrogen/generated/ios/c++/HybridNativeListSpecSwift.hpp +23 -2
- package/lib/nitrogen/generated/ios/c++/views/HybridNativeListComponent.mm +32 -0
- package/lib/nitrogen/generated/ios/swift/Func_void_bool.swift +46 -0
- package/lib/nitrogen/generated/ios/swift/HybridNativeListSpec.swift +3 -0
- package/lib/nitrogen/generated/ios/swift/HybridNativeListSpec_cxx.swift +54 -0
- package/lib/nitrogen/generated/shared/c++/HybridNativeListSpec.cpp +6 -0
- package/lib/nitrogen/generated/shared/c++/HybridNativeListSpec.hpp +8 -2
- package/lib/nitrogen/generated/shared/c++/views/HybridNativeListComponent.cpp +6 -0
- package/lib/nitrogen/generated/shared/c++/views/HybridNativeListComponent.hpp +11 -2
- package/lib/nitrogen/generated/shared/json/NativeListConfig.json +3 -0
- package/lib/typescript/src/NativeList.nitro.d.ts +3 -0
- package/lib/typescript/src/NativeList.types.d.ts +14 -1
- package/lib/typescript/src/models.d.ts +33 -5
- package/nitrogen/generated/android/c++/JFunc_void_bool.hpp +75 -0
- package/nitrogen/generated/android/c++/JHybridNativeListSpec.cpp +39 -3
- package/nitrogen/generated/android/c++/JHybridNativeListSpec.hpp +6 -0
- package/nitrogen/generated/android/c++/views/JHybridNativeListStateUpdater.cpp +15 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nativelist/Func_void_bool.kt +78 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nativelist/HybridNativeListSpec.kt +26 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nativelist/views/HybridNativeListManager.kt +24 -9
- package/nitrogen/generated/android/nativelistOnLoad.cpp +2 -0
- package/nitrogen/generated/ios/NativeListModule-Swift-Cxx-Bridge.cpp +8 -0
- package/nitrogen/generated/ios/NativeListModule-Swift-Cxx-Bridge.hpp +37 -0
- package/nitrogen/generated/ios/c++/HybridNativeListSpecSwift.hpp +23 -2
- package/nitrogen/generated/ios/c++/views/HybridNativeListComponent.mm +32 -0
- package/nitrogen/generated/ios/swift/Func_void_bool.swift +46 -0
- package/nitrogen/generated/ios/swift/HybridNativeListSpec.swift +3 -0
- package/nitrogen/generated/ios/swift/HybridNativeListSpec_cxx.swift +54 -0
- package/nitrogen/generated/shared/c++/HybridNativeListSpec.cpp +6 -0
- package/nitrogen/generated/shared/c++/HybridNativeListSpec.hpp +8 -2
- package/nitrogen/generated/shared/c++/views/HybridNativeListComponent.cpp +6 -0
- package/nitrogen/generated/shared/c++/views/HybridNativeListComponent.hpp +11 -2
- package/nitrogen/generated/shared/json/NativeListConfig.json +3 -0
- package/package.json +6 -5
- package/scripts/enable-container-slots.mjs +58 -0
- package/scripts/enable-container-slots.test.mjs +58 -0
- package/src/NativeList.nitro.ts +3 -0
- package/src/NativeList.tsx +84 -2
- package/src/NativeList.types.ts +14 -1
- package/src/NativeList.web.tsx +5 -0
- package/src/models.ts +38 -1
- package/src/validation.ts +146 -4
package/src/models.ts
CHANGED
|
@@ -517,6 +517,16 @@ export type RailRow = RowBase &
|
|
|
517
517
|
style?: RailRowStyle;
|
|
518
518
|
}>;
|
|
519
519
|
|
|
520
|
+
export type ActivityAmount = Readonly<{
|
|
521
|
+
key: string;
|
|
522
|
+
text: string;
|
|
523
|
+
textSegments?: readonly ValueTextSegment[];
|
|
524
|
+
leading?: LeadingVisual;
|
|
525
|
+
tone?: TextTone;
|
|
526
|
+
secondaryText?: string;
|
|
527
|
+
secondaryTextSegments?: readonly ValueTextSegment[];
|
|
528
|
+
}>;
|
|
529
|
+
|
|
520
530
|
export type ActivityRow = RowBase &
|
|
521
531
|
Readonly<{
|
|
522
532
|
type: 'activity';
|
|
@@ -527,6 +537,18 @@ export type ActivityRow = RowBase &
|
|
|
527
537
|
status?: string;
|
|
528
538
|
primaryAmount?: string;
|
|
529
539
|
secondaryAmount?: string;
|
|
540
|
+
amounts?: readonly ActivityAmount[];
|
|
541
|
+
badges?: readonly BadgeModel[];
|
|
542
|
+
presentation?: 'stacked' | 'table';
|
|
543
|
+
fee?: Readonly<{
|
|
544
|
+
label?: string;
|
|
545
|
+
primary: string;
|
|
546
|
+
primaryTextSegments?: readonly ValueTextSegment[];
|
|
547
|
+
secondary?: string;
|
|
548
|
+
secondaryTextSegments?: readonly ValueTextSegment[];
|
|
549
|
+
hidden?: boolean;
|
|
550
|
+
}>;
|
|
551
|
+
descriptionActionKey?: string;
|
|
530
552
|
footerActions?: readonly FooterAction[];
|
|
531
553
|
style?: ActivityRowStyle;
|
|
532
554
|
}>;
|
|
@@ -601,6 +623,11 @@ export type MediaTileRow = RowBase &
|
|
|
601
623
|
Readonly<{
|
|
602
624
|
type: 'mediaTile';
|
|
603
625
|
variant: 'gallery' | 'browserPreview';
|
|
626
|
+
/** Native preview; video candidates display a silent first frame, never autoplay. */
|
|
627
|
+
media?: Readonly<{
|
|
628
|
+
source: ImageSource;
|
|
629
|
+
probeOrder: readonly ('image' | 'video')[];
|
|
630
|
+
}>;
|
|
604
631
|
image?: ImageSource;
|
|
605
632
|
imageState?: 'empty' | 'error';
|
|
606
633
|
networkImage?: ImageSource;
|
|
@@ -650,6 +677,7 @@ export type SectionHeaderRow = RowBase &
|
|
|
650
677
|
indexTitle?: string;
|
|
651
678
|
variant?: 'summary' | 'gallery' | 'history';
|
|
652
679
|
title: string;
|
|
680
|
+
titleLoading?: boolean;
|
|
653
681
|
subtitle?: string;
|
|
654
682
|
value?: string;
|
|
655
683
|
valueActionKey?: string;
|
|
@@ -795,7 +823,7 @@ export type NativeListSnapshot = Readonly<{
|
|
|
795
823
|
layout: Readonly<{
|
|
796
824
|
kind: NativeListLayout;
|
|
797
825
|
orientation?: NativeListOrientation;
|
|
798
|
-
gridColumns?: 2 | 3 | 4;
|
|
826
|
+
gridColumns?: 2 | 3 | 4 | 5 | 6 | 7;
|
|
799
827
|
stickyHeaders?: boolean;
|
|
800
828
|
contentPadding?: number;
|
|
801
829
|
contentPaddingHorizontal?: number;
|
|
@@ -813,6 +841,7 @@ export type NativeListSnapshot = Readonly<{
|
|
|
813
841
|
reorderable?: boolean;
|
|
814
842
|
pullToRefresh?: boolean;
|
|
815
843
|
refreshing?: boolean;
|
|
844
|
+
refreshTriggerDistance?: number;
|
|
816
845
|
loadMore?: boolean;
|
|
817
846
|
endReachedThreshold?: number;
|
|
818
847
|
sectionIndex?: SectionIndexConfig;
|
|
@@ -882,6 +911,11 @@ export type RowPatch =
|
|
|
882
911
|
| 'title'
|
|
883
912
|
| 'description'
|
|
884
913
|
| 'status'
|
|
914
|
+
| 'amounts'
|
|
915
|
+
| 'badges'
|
|
916
|
+
| 'presentation'
|
|
917
|
+
| 'fee'
|
|
918
|
+
| 'descriptionActionKey'
|
|
885
919
|
| 'primaryAmount'
|
|
886
920
|
| 'secondaryAmount'
|
|
887
921
|
| 'leading'
|
|
@@ -957,6 +991,7 @@ export type RowPatch =
|
|
|
957
991
|
| CommonPatchFields
|
|
958
992
|
| 'image'
|
|
959
993
|
| 'imageState'
|
|
994
|
+
| 'media'
|
|
960
995
|
| 'networkImage'
|
|
961
996
|
| 'title'
|
|
962
997
|
| 'subtitle'
|
|
@@ -993,6 +1028,7 @@ export type RowPatch =
|
|
|
993
1028
|
SectionHeaderRow,
|
|
994
1029
|
| CommonPatchFields
|
|
995
1030
|
| 'variant'
|
|
1031
|
+
| 'titleLoading'
|
|
996
1032
|
| 'title'
|
|
997
1033
|
| 'subtitle'
|
|
998
1034
|
| 'value'
|
|
@@ -1036,6 +1072,7 @@ export type NativeListActionSource =
|
|
|
1036
1072
|
| 'leadingAction'
|
|
1037
1073
|
| 'trailingAccessory'
|
|
1038
1074
|
| 'footerAction'
|
|
1075
|
+
| 'description'
|
|
1039
1076
|
| 'mediaClose';
|
|
1040
1077
|
|
|
1041
1078
|
export type NativeListWindowRect = Readonly<{
|
package/src/validation.ts
CHANGED
|
@@ -175,6 +175,11 @@ const TEXT_STYLE_KEYS_BY_ROW_TYPE: Readonly<
|
|
|
175
175
|
'title',
|
|
176
176
|
'description',
|
|
177
177
|
'status',
|
|
178
|
+
'amounts',
|
|
179
|
+
'badges',
|
|
180
|
+
'presentation',
|
|
181
|
+
'fee',
|
|
182
|
+
'descriptionActionKey',
|
|
178
183
|
'primaryAmount',
|
|
179
184
|
'secondaryAmount',
|
|
180
185
|
],
|
|
@@ -183,7 +188,7 @@ const TEXT_STYLE_KEYS_BY_ROW_TYPE: Readonly<
|
|
|
183
188
|
market: ['title', 'subtitle', 'price', 'change'],
|
|
184
189
|
mediaTile: ['title', 'subtitle', 'badge'],
|
|
185
190
|
metricCard: ['title', 'value', 'subtitle', 'trend'],
|
|
186
|
-
sectionHeader: ['title', 'subtitle', 'value'],
|
|
191
|
+
sectionHeader: ['titleLoading', 'title', 'subtitle', 'value'],
|
|
187
192
|
action: ['title', 'value'],
|
|
188
193
|
system: ['title', 'message', 'actionText'],
|
|
189
194
|
};
|
|
@@ -917,7 +922,84 @@ function assertVisual(row: RowModel, path: string): void {
|
|
|
917
922
|
});
|
|
918
923
|
}
|
|
919
924
|
|
|
920
|
-
function assertActivity(row: ActivityRow
|
|
925
|
+
function assertActivity(row: Partial<ActivityRow>, path: string): void {
|
|
926
|
+
assertText(row.title, `${path}.title`);
|
|
927
|
+
assertText(row.description, `${path}.description`);
|
|
928
|
+
if (
|
|
929
|
+
row.presentation !== undefined &&
|
|
930
|
+
!['stacked', 'table'].includes(row.presentation)
|
|
931
|
+
)
|
|
932
|
+
fail(`${path}.presentation`, 'must be stacked or table');
|
|
933
|
+
if (row.descriptionActionKey !== undefined)
|
|
934
|
+
assertKey(row.descriptionActionKey, `${path}.descriptionActionKey`);
|
|
935
|
+
if ((row.amounts?.length ?? 0) > 32)
|
|
936
|
+
fail(`${path}.amounts`, 'supports at most 32 amount lines');
|
|
937
|
+
const amountKeys = new Set<string>();
|
|
938
|
+
row.amounts?.forEach((amount, index) => {
|
|
939
|
+
const amountPath = `${path}.amounts[${index}]`;
|
|
940
|
+
assertKey(amount.key, `${amountPath}.key`);
|
|
941
|
+
if (amountKeys.has(amount.key)) fail(amountPath, 'duplicate amount key');
|
|
942
|
+
amountKeys.add(amount.key);
|
|
943
|
+
assertText(amount.text, `${amountPath}.text`);
|
|
944
|
+
assertLeadingVisual(amount.leading, `${amountPath}.leading`);
|
|
945
|
+
assertText(amount.secondaryText, `${amountPath}.secondaryText`);
|
|
946
|
+
if (
|
|
947
|
+
amount.tone !== undefined &&
|
|
948
|
+
!['primary', 'secondary', 'positive', 'negative'].includes(amount.tone)
|
|
949
|
+
)
|
|
950
|
+
fail(`${amountPath}.tone`, 'invalid text tone');
|
|
951
|
+
amount.textSegments?.forEach((segment, segmentIndex) => {
|
|
952
|
+
assertText(
|
|
953
|
+
segment.text,
|
|
954
|
+
`${amountPath}.textSegments[${segmentIndex}].text`
|
|
955
|
+
);
|
|
956
|
+
if (segment.style !== undefined && segment.style !== 'subscript')
|
|
957
|
+
fail(amountPath, 'invalid text segment style');
|
|
958
|
+
});
|
|
959
|
+
});
|
|
960
|
+
const assertActivitySegments = (
|
|
961
|
+
segments: readonly { text: string; style?: string }[] | undefined,
|
|
962
|
+
segmentPath: string
|
|
963
|
+
) =>
|
|
964
|
+
segments?.forEach((segment, index) => {
|
|
965
|
+
assertText(segment.text, `${segmentPath}[${index}].text`);
|
|
966
|
+
if (segment.style !== undefined && segment.style !== 'subscript')
|
|
967
|
+
fail(segmentPath, 'invalid text segment style');
|
|
968
|
+
});
|
|
969
|
+
row.amounts?.forEach((amount, index) =>
|
|
970
|
+
assertActivitySegments(
|
|
971
|
+
amount.secondaryTextSegments,
|
|
972
|
+
`${path}.amounts[${index}].secondaryTextSegments`
|
|
973
|
+
)
|
|
974
|
+
);
|
|
975
|
+
assertActivitySegments(
|
|
976
|
+
row.fee?.primaryTextSegments,
|
|
977
|
+
`${path}.fee.primaryTextSegments`
|
|
978
|
+
);
|
|
979
|
+
assertActivitySegments(
|
|
980
|
+
row.fee?.secondaryTextSegments,
|
|
981
|
+
`${path}.fee.secondaryTextSegments`
|
|
982
|
+
);
|
|
983
|
+
assertText(row.fee?.label, `${path}.fee.label`);
|
|
984
|
+
assertText(row.fee?.primary, `${path}.fee.primary`);
|
|
985
|
+
assertText(row.fee?.secondary, `${path}.fee.secondary`);
|
|
986
|
+
if ((row.badges?.length ?? 0) > 4)
|
|
987
|
+
fail(`${path}.badges`, 'supports at most 4 activity badges');
|
|
988
|
+
const badgeKeys = new Set<string>();
|
|
989
|
+
row.badges?.forEach((badge, index) => {
|
|
990
|
+
assertKey(badge.key, `${path}.badges[${index}].key`);
|
|
991
|
+
if (badgeKeys.has(badge.key)) fail(`${path}.badges`, 'duplicate badge key');
|
|
992
|
+
badgeKeys.add(badge.key);
|
|
993
|
+
assertText(badge.text, `${path}.badges[${index}].text`);
|
|
994
|
+
if (
|
|
995
|
+
badge.tone !== undefined &&
|
|
996
|
+
!['neutral', 'info', 'success', 'warning', 'danger'].includes(badge.tone)
|
|
997
|
+
)
|
|
998
|
+
fail(`${path}.badges`, 'invalid badge tone');
|
|
999
|
+
});
|
|
1000
|
+
if (row.fee?.hidden !== undefined && typeof row.fee.hidden !== 'boolean')
|
|
1001
|
+
fail(`${path}.fee.hidden`, 'must be boolean');
|
|
1002
|
+
|
|
921
1003
|
if ((row.footerActions?.length ?? 0) > MAX_FOOTER_ACTIONS) {
|
|
922
1004
|
fail(
|
|
923
1005
|
`${path}.footerActions`,
|
|
@@ -1119,6 +1201,7 @@ function assertRow(
|
|
|
1119
1201
|
assertMarketRow(row, path);
|
|
1120
1202
|
break;
|
|
1121
1203
|
case 'mediaTile':
|
|
1204
|
+
assertMediaPreview(row.media, `${path}.media`);
|
|
1122
1205
|
assertImage(row.image, `${path}.image`);
|
|
1123
1206
|
if (
|
|
1124
1207
|
row.imageState !== undefined &&
|
|
@@ -1126,10 +1209,14 @@ function assertRow(
|
|
|
1126
1209
|
) {
|
|
1127
1210
|
fail(`${path}.imageState`, 'must be empty or error when provided');
|
|
1128
1211
|
}
|
|
1129
|
-
if (
|
|
1212
|
+
if (
|
|
1213
|
+
row.imageState === undefined &&
|
|
1214
|
+
row.image === undefined &&
|
|
1215
|
+
row.media === undefined
|
|
1216
|
+
) {
|
|
1130
1217
|
fail(
|
|
1131
1218
|
`${path}.image`,
|
|
1132
|
-
'is required unless imageState is empty or error'
|
|
1219
|
+
'is required unless media is provided or imageState is empty or error'
|
|
1133
1220
|
);
|
|
1134
1221
|
}
|
|
1135
1222
|
assertImage(row.networkImage, `${path}.networkImage`);
|
|
@@ -1168,6 +1255,11 @@ function assertRow(
|
|
|
1168
1255
|
}
|
|
1169
1256
|
break;
|
|
1170
1257
|
case 'sectionHeader':
|
|
1258
|
+
if (
|
|
1259
|
+
row.titleLoading !== undefined &&
|
|
1260
|
+
typeof row.titleLoading !== 'boolean'
|
|
1261
|
+
)
|
|
1262
|
+
fail(`${path}.titleLoading`, 'must be boolean');
|
|
1171
1263
|
assertKey(row.sectionKey, `${path}.sectionKey`);
|
|
1172
1264
|
if (
|
|
1173
1265
|
row.presentation !== undefined &&
|
|
@@ -1292,14 +1384,57 @@ function assertGroups(rows: readonly RowModel[]): void {
|
|
|
1292
1384
|
}
|
|
1293
1385
|
}
|
|
1294
1386
|
|
|
1387
|
+
function assertMediaPreview(value: unknown, path: string) {
|
|
1388
|
+
if (value === undefined) return;
|
|
1389
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
1390
|
+
fail(path, 'must be a media descriptor');
|
|
1391
|
+
const media = value as {
|
|
1392
|
+
source?: import('./models').ImageSource;
|
|
1393
|
+
probeOrder?: unknown;
|
|
1394
|
+
};
|
|
1395
|
+
assertImage(media.source, `${path}.source`);
|
|
1396
|
+
if (!media.source) fail(`${path}.source`, 'is required');
|
|
1397
|
+
const order = media.probeOrder;
|
|
1398
|
+
if (
|
|
1399
|
+
!Array.isArray(order) ||
|
|
1400
|
+
order.length < 1 ||
|
|
1401
|
+
order.length > 2 ||
|
|
1402
|
+
order.some((kind) => kind !== 'image' && kind !== 'video') ||
|
|
1403
|
+
new Set(order).size !== order.length
|
|
1404
|
+
) {
|
|
1405
|
+
fail(
|
|
1406
|
+
`${path}.probeOrder`,
|
|
1407
|
+
'must contain one or two distinct image/video candidates'
|
|
1408
|
+
);
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1295
1412
|
export function validateSnapshot(
|
|
1296
1413
|
snapshot: NativeListSnapshot
|
|
1297
1414
|
): NativeListSnapshot {
|
|
1415
|
+
if (
|
|
1416
|
+
snapshot.capabilities?.refreshTriggerDistance !== undefined &&
|
|
1417
|
+
(!Number.isFinite(snapshot.capabilities.refreshTriggerDistance) ||
|
|
1418
|
+
snapshot.capabilities.refreshTriggerDistance <= 0)
|
|
1419
|
+
)
|
|
1420
|
+
fail(
|
|
1421
|
+
'capabilities.refreshTriggerDistance',
|
|
1422
|
+
'must be a positive finite number'
|
|
1423
|
+
);
|
|
1424
|
+
|
|
1298
1425
|
assertPlainSerializable(snapshot, 'snapshot', new Set<object>());
|
|
1299
1426
|
if (snapshot.schemaVersion !== 1) fail('snapshot.schemaVersion', 'must be 1');
|
|
1300
1427
|
if (!Number.isSafeInteger(snapshot.generation) || snapshot.generation < 0) {
|
|
1301
1428
|
fail('snapshot.generation', 'must be a non-negative safe integer');
|
|
1302
1429
|
}
|
|
1430
|
+
if (
|
|
1431
|
+
snapshot.layout.gridColumns !== undefined &&
|
|
1432
|
+
(!Number.isInteger(snapshot.layout.gridColumns) ||
|
|
1433
|
+
snapshot.layout.gridColumns < 2 ||
|
|
1434
|
+
snapshot.layout.gridColumns > 7)
|
|
1435
|
+
) {
|
|
1436
|
+
fail('snapshot.layout.gridColumns', 'must be an integer from 2 to 7');
|
|
1437
|
+
}
|
|
1303
1438
|
if (snapshot.layout.kind === 'grid' && !snapshot.layout.gridColumns) {
|
|
1304
1439
|
fail('snapshot.layout.gridColumns', 'is required for grid layout');
|
|
1305
1440
|
}
|
|
@@ -1508,6 +1643,7 @@ function assertPatchChanges(patch: RowPatch, index: number): void {
|
|
|
1508
1643
|
assertLeadingVisual(patch.changes.visual, `${path}.visual`);
|
|
1509
1644
|
break;
|
|
1510
1645
|
case 'activity':
|
|
1646
|
+
assertActivity(patch.changes, path);
|
|
1511
1647
|
assertText(patch.changes.title, `${path}.title`);
|
|
1512
1648
|
assertText(patch.changes.description, `${path}.description`);
|
|
1513
1649
|
assertText(patch.changes.status, `${path}.status`);
|
|
@@ -1576,6 +1712,7 @@ function assertPatchChanges(patch: RowPatch, index: number): void {
|
|
|
1576
1712
|
);
|
|
1577
1713
|
break;
|
|
1578
1714
|
case 'mediaTile':
|
|
1715
|
+
assertMediaPreview(patch.changes.media, `${path}.media`);
|
|
1579
1716
|
assertImage(patch.changes.image, `${path}.image`);
|
|
1580
1717
|
if (
|
|
1581
1718
|
patch.changes.imageState !== undefined &&
|
|
@@ -1623,6 +1760,11 @@ function assertPatchChanges(patch: RowPatch, index: number): void {
|
|
|
1623
1760
|
}
|
|
1624
1761
|
break;
|
|
1625
1762
|
case 'sectionHeader':
|
|
1763
|
+
if (
|
|
1764
|
+
patch.changes.titleLoading !== undefined &&
|
|
1765
|
+
typeof patch.changes.titleLoading !== 'boolean'
|
|
1766
|
+
)
|
|
1767
|
+
fail(`${path}.titleLoading`, 'must be boolean');
|
|
1626
1768
|
assertSectionHeaderVariant(patch.changes.variant, `${path}.variant`);
|
|
1627
1769
|
assertText(patch.changes.title, `${path}.title`);
|
|
1628
1770
|
assertText(patch.changes.subtitle, `${path}.subtitle`);
|