@onekeyfe/react-native-native-list 3.0.105
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 +342 -0
- package/android/CMakeLists.txt +20 -0
- package/android/build.gradle +105 -0
- package/android/gradle.properties +4 -0
- package/android/src/main/AndroidManifest.xml +1 -0
- package/android/src/main/cpp/cpp-adapter.cpp +6 -0
- package/android/src/main/java/com/onekey/nativelist/HybridNativeList.kt +125 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListAdapter.kt +165 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListModels.kt +147 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListPackage.kt +25 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListRowView.kt +2939 -0
- package/android/src/main/java/com/onekey/nativelist/NativeListView.kt +1794 -0
- package/common/fonts/Roobert-Bold.ttf +0 -0
- package/common/fonts/Roobert-Medium.ttf +0 -0
- package/common/fonts/Roobert-Regular.ttf +0 -0
- package/common/fonts/Roobert-SemiBold.ttf +0 -0
- package/docs/DESIGN.md +129 -0
- package/ios/HybridNativeList.swift +131 -0
- package/ios/NativeListCell.swift +2858 -0
- package/ios/NativeListDesignAssets.swift +110 -0
- package/ios/NativeListModels.swift +215 -0
- package/ios/RNCNativeListView.swift +1737 -0
- package/ios/Resources/NativeListIcons.xcassets/Contents.json +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_arrow_bottom.imageset/Contents.json +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_arrow_bottom.imageset/icon.svg +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_arrow_top.imageset/Contents.json +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_arrow_top.imageset/icon.svg +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_chart_trending_up.imageset/Contents.json +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_chart_trending_up.imageset/icon.svg +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_checkbox_checked.imageset/Contents.json +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_checkbox_checked.imageset/icon.svg +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_checkbox_indeterminate.imageset/Contents.json +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_checkbox_indeterminate.imageset/icon.svg +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_chevron_bottom.imageset/Contents.json +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_chevron_bottom.imageset/icon.svg +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_chevron_grabber_ver.imageset/Contents.json +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_chevron_grabber_ver.imageset/icon.svg +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_chevron_right_small.imageset/Contents.json +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_chevron_right_small.imageset/icon.svg +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_chevron_top.imageset/Contents.json +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_chevron_top.imageset/icon.svg +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_dot_hor.imageset/Contents.json +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_dot_hor.imageset/icon.svg +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_drag.imageset/Contents.json +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_drag.imageset/icon.svg +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_error_solid.imageset/Contents.json +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_error_solid.imageset/icon.svg +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_image_square_waves.imageset/Contents.json +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_image_square_waves.imageset/icon.svg +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_info_circle.imageset/Contents.json +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_info_circle.imageset/icon.svg +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_minus_circle.imageset/Contents.json +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_minus_circle.imageset/icon.svg +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_minus_circle_solid.imageset/Contents.json +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_minus_circle_solid.imageset/icon.svg +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_pencil.imageset/Contents.json +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_pencil.imageset/icon.svg +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_plus_circle.imageset/Contents.json +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_plus_circle.imageset/icon.svg +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_plus_small.imageset/Contents.json +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_plus_small.imageset/icon.svg +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_questionmark_solid.imageset/Contents.json +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_questionmark_solid.imageset/icon.svg +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_shield_exclamation.imageset/Contents.json +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_shield_exclamation.imageset/icon.svg +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_speaker_promote.imageset/Contents.json +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_speaker_promote.imageset/icon.svg +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_star.imageset/Contents.json +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_star.imageset/icon.svg +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_star_solid.imageset/Contents.json +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_star_solid.imageset/icon.svg +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_swap_hor.imageset/Contents.json +1 -0
- package/ios/Resources/NativeListIcons.xcassets/onekey_swap_hor.imageset/icon.svg +1 -0
- package/lib/module/NativeList.js +183 -0
- package/lib/module/NativeList.nitro.js +4 -0
- package/lib/module/NativeList.types.js +4 -0
- package/lib/module/NativeList.web.js +167 -0
- package/lib/module/index.js +6 -0
- package/lib/module/models.js +2 -0
- package/lib/module/package.json +1 -0
- package/lib/module/scrolling.js +121 -0
- package/lib/module/selection.js +85 -0
- package/lib/module/validation.js +562 -0
- package/lib/module/web/NativeListWebEngine.js +2238 -0
- package/lib/nitrogen/generated/.gitattributes +1 -0
- package/lib/nitrogen/generated/android/c++/JFunc_void_std__string.hpp +76 -0
- package/lib/nitrogen/generated/android/c++/JHybridNativeListSpec.cpp +201 -0
- package/lib/nitrogen/generated/android/c++/JHybridNativeListSpec.hpp +84 -0
- package/lib/nitrogen/generated/android/c++/JNativeListScrollAlignment.hpp +64 -0
- package/lib/nitrogen/generated/android/c++/views/JHybridNativeListStateUpdater.cpp +104 -0
- package/lib/nitrogen/generated/android/c++/views/JHybridNativeListStateUpdater.hpp +54 -0
- package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/nativelist/Func_void_std__string.kt +78 -0
- package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/nativelist/HybridNativeListSpec.kt +177 -0
- package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/nativelist/NativeListScrollAlignment.kt +25 -0
- package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/nativelist/nativelistOnLoad.kt +35 -0
- package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/nativelist/views/HybridNativeListManager.kt +96 -0
- package/lib/nitrogen/generated/android/kotlin/com/margelo/nitro/nativelist/views/HybridNativeListStateUpdater.kt +23 -0
- package/lib/nitrogen/generated/android/nativelist+autolinking.cmake +83 -0
- package/lib/nitrogen/generated/android/nativelist+autolinking.gradle +27 -0
- package/lib/nitrogen/generated/android/nativelistOnLoad.cpp +58 -0
- package/lib/nitrogen/generated/android/nativelistOnLoad.hpp +34 -0
- package/lib/nitrogen/generated/ios/NativeListModule+autolinking.rb +62 -0
- package/lib/nitrogen/generated/ios/NativeListModule-Swift-Cxx-Bridge.cpp +41 -0
- package/lib/nitrogen/generated/ios/NativeListModule-Swift-Cxx-Bridge.hpp +91 -0
- package/lib/nitrogen/generated/ios/NativeListModule-Swift-Cxx-Umbrella.hpp +49 -0
- package/lib/nitrogen/generated/ios/NativeListModuleAutolinking.mm +33 -0
- package/lib/nitrogen/generated/ios/NativeListModuleAutolinking.swift +26 -0
- package/lib/nitrogen/generated/ios/c++/HybridNativeListSpecSwift.cpp +11 -0
- package/lib/nitrogen/generated/ios/c++/HybridNativeListSpecSwift.hpp +180 -0
- package/lib/nitrogen/generated/ios/c++/views/HybridNativeListComponent.mm +180 -0
- package/lib/nitrogen/generated/ios/swift/Func_void_std__string.swift +46 -0
- package/lib/nitrogen/generated/ios/swift/HybridNativeListSpec.swift +69 -0
- package/lib/nitrogen/generated/ios/swift/HybridNativeListSpec_cxx.swift +447 -0
- package/lib/nitrogen/generated/ios/swift/NativeListScrollAlignment.swift +48 -0
- package/lib/nitrogen/generated/shared/c++/HybridNativeListSpec.cpp +43 -0
- package/lib/nitrogen/generated/shared/c++/HybridNativeListSpec.hpp +87 -0
- package/lib/nitrogen/generated/shared/c++/NativeListScrollAlignment.hpp +84 -0
- package/lib/nitrogen/generated/shared/c++/views/HybridNativeListComponent.cpp +46 -0
- package/lib/nitrogen/generated/shared/c++/views/HybridNativeListComponent.hpp +103 -0
- package/lib/nitrogen/generated/shared/json/NativeListConfig.json +16 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/NativeList.d.ts +18 -0
- package/lib/typescript/src/NativeList.nitro.d.ts +29 -0
- package/lib/typescript/src/NativeList.types.d.ts +87 -0
- package/lib/typescript/src/NativeList.web.d.ts +19 -0
- package/lib/typescript/src/index.d.ts +7 -0
- package/lib/typescript/src/models.d.ts +456 -0
- package/lib/typescript/src/scrolling.d.ts +32 -0
- package/lib/typescript/src/selection.d.ts +27 -0
- package/lib/typescript/src/validation.d.ts +7 -0
- package/lib/typescript/src/web/NativeListWebEngine.d.ts +203 -0
- package/nitro.json +23 -0
- package/nitrogen/generated/.gitattributes +1 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__string.hpp +76 -0
- package/nitrogen/generated/android/c++/JHybridNativeListSpec.cpp +201 -0
- package/nitrogen/generated/android/c++/JHybridNativeListSpec.hpp +84 -0
- package/nitrogen/generated/android/c++/JNativeListScrollAlignment.hpp +64 -0
- package/nitrogen/generated/android/c++/views/JHybridNativeListStateUpdater.cpp +104 -0
- package/nitrogen/generated/android/c++/views/JHybridNativeListStateUpdater.hpp +54 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nativelist/Func_void_std__string.kt +78 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nativelist/HybridNativeListSpec.kt +177 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nativelist/NativeListScrollAlignment.kt +25 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nativelist/nativelistOnLoad.kt +35 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nativelist/views/HybridNativeListManager.kt +96 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nativelist/views/HybridNativeListStateUpdater.kt +23 -0
- package/nitrogen/generated/android/nativelist+autolinking.cmake +83 -0
- package/nitrogen/generated/android/nativelist+autolinking.gradle +27 -0
- package/nitrogen/generated/android/nativelistOnLoad.cpp +58 -0
- package/nitrogen/generated/android/nativelistOnLoad.hpp +34 -0
- package/nitrogen/generated/ios/NativeListModule+autolinking.rb +62 -0
- package/nitrogen/generated/ios/NativeListModule-Swift-Cxx-Bridge.cpp +41 -0
- package/nitrogen/generated/ios/NativeListModule-Swift-Cxx-Bridge.hpp +91 -0
- package/nitrogen/generated/ios/NativeListModule-Swift-Cxx-Umbrella.hpp +49 -0
- package/nitrogen/generated/ios/NativeListModuleAutolinking.mm +33 -0
- package/nitrogen/generated/ios/NativeListModuleAutolinking.swift +26 -0
- package/nitrogen/generated/ios/c++/HybridNativeListSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridNativeListSpecSwift.hpp +180 -0
- package/nitrogen/generated/ios/c++/views/HybridNativeListComponent.mm +180 -0
- package/nitrogen/generated/ios/swift/Func_void_std__string.swift +46 -0
- package/nitrogen/generated/ios/swift/HybridNativeListSpec.swift +69 -0
- package/nitrogen/generated/ios/swift/HybridNativeListSpec_cxx.swift +447 -0
- package/nitrogen/generated/ios/swift/NativeListScrollAlignment.swift +48 -0
- package/nitrogen/generated/shared/c++/HybridNativeListSpec.cpp +43 -0
- package/nitrogen/generated/shared/c++/HybridNativeListSpec.hpp +87 -0
- package/nitrogen/generated/shared/c++/NativeListScrollAlignment.hpp +84 -0
- package/nitrogen/generated/shared/c++/views/HybridNativeListComponent.cpp +46 -0
- package/nitrogen/generated/shared/c++/views/HybridNativeListComponent.hpp +103 -0
- package/nitrogen/generated/shared/json/NativeListConfig.json +16 -0
- package/package.json +126 -0
- package/react-native-native-list.podspec +38 -0
- package/react-native.config.js +19 -0
- package/src/NativeList.nitro.ts +48 -0
- package/src/NativeList.tsx +298 -0
- package/src/NativeList.types.ts +125 -0
- package/src/NativeList.web.tsx +258 -0
- package/src/index.ts +35 -0
- package/src/models.ts +604 -0
- package/src/scrolling.ts +189 -0
- package/src/selection.ts +159 -0
- package/src/validation.ts +877 -0
- package/src/web/NativeListWebEngine.ts +3767 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/docs/DESIGN.md
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Native List Design
|
|
2
|
+
|
|
3
|
+
## Scope
|
|
4
|
+
|
|
5
|
+
`@onekeyfe/react-native-native-list` is a Nitro View, template-driven list for
|
|
6
|
+
React Native 0.86. The native view owns cell creation, recycling, layout,
|
|
7
|
+
selection feedback, image request cancellation, and scrolling. JavaScript sends
|
|
8
|
+
normalized plain data; rows never contain a `ReactNode`, function, or arbitrary
|
|
9
|
+
style object.
|
|
10
|
+
|
|
11
|
+
The component supports `identity`, `rail`, `activity`, `message`, `dataRow`,
|
|
12
|
+
`mediaTile`, `metricCard`, `sectionHeader`, `action`, and `system` rows.
|
|
13
|
+
`metricCard` supports a compact KPI template and the fixed `activity` and
|
|
14
|
+
`performance` Portfolio & PnL composites. Their bounded metric arrays and
|
|
15
|
+
progress value have dedicated native binders on both mobile platforms.
|
|
16
|
+
|
|
17
|
+
## Public data boundary
|
|
18
|
+
|
|
19
|
+
The exported TypeScript model is a discriminated union. Every row has a stable
|
|
20
|
+
`key`, bounded text and accessory arrays, and a fixed `size`/`density` variant.
|
|
21
|
+
Business concepts such as asset, account, network, wallet, and settings map to
|
|
22
|
+
the same presentation templates instead of introducing business-specific row
|
|
23
|
+
types.
|
|
24
|
+
|
|
25
|
+
The wrapper validates and normalizes data before serializing it. A structural
|
|
26
|
+
change is one snapshot payload. Frequently changing fields use one batch patch
|
|
27
|
+
payload keyed by row key. Neither API performs one native call per row. The
|
|
28
|
+
native side rejects malformed or duplicate-key payloads without partially
|
|
29
|
+
applying them.
|
|
30
|
+
|
|
31
|
+
Section headers, footers, separators, empty rows, and fixed-footer descriptors
|
|
32
|
+
are represented as rows in one flattened native data source. `groupId` and
|
|
33
|
+
`groupPosition` preserve continuous card geometry without nesting lists inside
|
|
34
|
+
cells.
|
|
35
|
+
|
|
36
|
+
## Native architecture
|
|
37
|
+
|
|
38
|
+
- iOS 15.5+: `UICollectionView`, `UICollectionViewDiffableDataSource`, and a
|
|
39
|
+
native flow layout.
|
|
40
|
+
- Android API 24+: `RecyclerView`, `ListAdapter`, and `DiffUtil.ItemCallback`.
|
|
41
|
+
- Web: a platform-resolved React host backed by a pure DOM engine. The engine
|
|
42
|
+
owns layout, viewport windowing, recycled row elements, selection feedback,
|
|
43
|
+
section-index navigation, and the same imperative API as mobile; React does
|
|
44
|
+
not create a component subtree per row.
|
|
45
|
+
- Nitro View: the generated HybridView host receives the initial snapshot as
|
|
46
|
+
one string and exposes HybridView methods for subsequent snapshots, patches,
|
|
47
|
+
selection reconciliation, and scrolling. Nitro callback props carry bounded
|
|
48
|
+
JSON payloads which the wrapper decodes into strict public event types.
|
|
49
|
+
|
|
50
|
+
`linear`, `sectioned`, `grid`, and `table` are observable native container
|
|
51
|
+
semantics. Linear is a full-width stream. Sectioned adds a visual break before
|
|
52
|
+
section-header rows and can pin those rows. Grid allocates native spans and
|
|
53
|
+
makes structural rows full-span. Table uses compact alternating rows and fixed
|
|
54
|
+
weighted/aligned columns. Orientation, refresh, load-more, visibility events,
|
|
55
|
+
empty state, fixed footer, and native reordering are capabilities, not row
|
|
56
|
+
types.
|
|
57
|
+
|
|
58
|
+
## Section index
|
|
59
|
+
|
|
60
|
+
The mobile section index is an opt-in capability for vertical `sectioned`
|
|
61
|
+
snapshots. Indexed section headers carry a bounded `indexTitle`; their stable
|
|
62
|
+
row `key` is also the scroll target, so the feature needs no extra bridge event
|
|
63
|
+
or parallel identity. Headers without `indexTitle` remain in the list but are
|
|
64
|
+
omitted from the rail, which supports sparse alphabets and dynamic search
|
|
65
|
+
results. An enabled snapshot with no indexed headers hides the rail.
|
|
66
|
+
|
|
67
|
+
iOS and Android render a native trailing overlay, reserve a trailing content
|
|
68
|
+
gutter, follow RTL layout direction, highlight the visible section, and expose
|
|
69
|
+
the rail as one adjustable accessibility control. Touch-drag navigation scrolls
|
|
70
|
+
immediately, shows a centered title preview, and emits selection feedback when
|
|
71
|
+
the active entry changes unless `hapticsEnabled` is false. Web renders the same
|
|
72
|
+
explicit index entries as a DOM overlay with click and pointer-drag navigation.
|
|
73
|
+
Snapshot order is authoritative; no platform sorts, uppercases, or synthesizes
|
|
74
|
+
missing entries.
|
|
75
|
+
|
|
76
|
+
## Selection ownership
|
|
77
|
+
|
|
78
|
+
Native state is authoritative for immediate visible feedback. `none`, `single`,
|
|
79
|
+
and `multiple` modes are supported. Row presses may toggle selection. Row,
|
|
80
|
+
section, and list actions update all affected keys in one native transaction and
|
|
81
|
+
emit one `selectionDelta` containing `addedKeys` and `removedKeys`.
|
|
82
|
+
|
|
83
|
+
Checkboxes support `checked`, `unchecked`, and `indeterminate`, plus `disabled`
|
|
84
|
+
and `loading`. Section and global three-state values are derived from selectable
|
|
85
|
+
descendants. JavaScript may later reconcile native state with one selection
|
|
86
|
+
snapshot or batch patch; reconciliation does not emit another delta.
|
|
87
|
+
|
|
88
|
+
## Images and OneKeyImage
|
|
89
|
+
|
|
90
|
+
A React `OneKeyImage` component cannot be mounted inside a recycled native cell
|
|
91
|
+
without reintroducing a React subtree per row. Instead, OneKeyImage source data
|
|
92
|
+
is normalized into the list's bounded `ImageSource` descriptor. Each fixed image
|
|
93
|
+
slot embeds `OneKeyImageReusableView`, the native-only host exported by
|
|
94
|
+
`@onekeyfe/react-native-image`. This means iOS uses the same SDWebImage pipeline
|
|
95
|
+
and Android uses the same Glide pipeline as `OneKeyImage`, including its cache,
|
|
96
|
+
SVG/WebP/AVIF support, TOS sizing, animated-image safety, placeholders, and
|
|
97
|
+
recycling behavior.
|
|
98
|
+
|
|
99
|
+
`ImageSource` mirrors the serializable OneKeyImage request options: URI,
|
|
100
|
+
dimensions, headers, content fit, cache policy, autoplay, TOS optimization,
|
|
101
|
+
overscan, and loading strategy. Every bind supplies a stable row/slot recycling
|
|
102
|
+
key. Rebinding or recycling calls OneKeyImage's recycle hook, which cancels stale
|
|
103
|
+
work before the slot accepts its next source. Token/network overlays, double
|
|
104
|
+
activity visuals, and stacks of up to three sources all use the same fixed slot
|
|
105
|
+
pool.
|
|
106
|
+
|
|
107
|
+
## Update and event policy
|
|
108
|
+
|
|
109
|
+
Snapshot application uses stable keys and platform diffing. A patch updates only
|
|
110
|
+
changed models and rebinds/reconfigures only the corresponding visible cells.
|
|
111
|
+
Selection-only changes use native payload updates and never require rebuilding
|
|
112
|
+
all JavaScript rows.
|
|
113
|
+
|
|
114
|
+
`visibleRangeChanged` is coalesced to at most once per animation frame and only
|
|
115
|
+
emitted when the first/last visible keys change. `endReached` is edge-triggered
|
|
116
|
+
per content generation. Other public events are `rowAction`, `selectionDelta`,
|
|
117
|
+
and `reorder`.
|
|
118
|
+
|
|
119
|
+
## Height, layout, and performance constraints
|
|
120
|
+
|
|
121
|
+
Template sizes are fixed to a small set of variants. `message` body text is
|
|
122
|
+
bounded to four lines and uses a deterministic template height. System spacers
|
|
123
|
+
are explicit and bounded. Images have explicit sizes, and grid columns are fixed
|
|
124
|
+
per snapshot. This keeps layout work predictable for 1,000- and 5,000-row
|
|
125
|
+
workloads without an unbounded self-sizing pass.
|
|
126
|
+
|
|
127
|
+
The native list runs in the main UI runtime. OneKey's background and main
|
|
128
|
+
JavaScript heaps are not shared, so this API accepts normalized serializable data
|
|
129
|
+
and never depends on background-runtime object identity.
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import UIKit
|
|
3
|
+
|
|
4
|
+
final class HybridNativeList: HybridNativeListSpec {
|
|
5
|
+
private let hostView = NativeListView(frame: .zero)
|
|
6
|
+
|
|
7
|
+
var view: UIView { hostView }
|
|
8
|
+
|
|
9
|
+
var snapshotJson: String = "" {
|
|
10
|
+
didSet {
|
|
11
|
+
guard snapshotJson != oldValue else { return }
|
|
12
|
+
runOnMain { [weak self] in
|
|
13
|
+
guard let self else { return }
|
|
14
|
+
self.hostView.applySnapshotJson(self.snapshotJson)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
var onRowAction: ((_ payloadJson: String) -> Void)?
|
|
20
|
+
var onActionAnchorInvalidated: ((_ payloadJson: String) -> Void)?
|
|
21
|
+
var onSelectionDelta: ((_ payloadJson: String) -> Void)?
|
|
22
|
+
var onReorder: ((_ payloadJson: String) -> Void)?
|
|
23
|
+
var onEndReached: ((_ payloadJson: String) -> Void)?
|
|
24
|
+
var onVisibleRangeChanged: ((_ payloadJson: String) -> Void)?
|
|
25
|
+
|
|
26
|
+
override init() {
|
|
27
|
+
super.init()
|
|
28
|
+
hostView.onRowAction = { [weak self] in self?.onRowAction?($0) }
|
|
29
|
+
hostView.onActionAnchorInvalidated = { [weak self] in self?.onActionAnchorInvalidated?($0) }
|
|
30
|
+
hostView.onSelectionDelta = { [weak self] in self?.onSelectionDelta?($0) }
|
|
31
|
+
hostView.onReorder = { [weak self] in self?.onReorder?($0) }
|
|
32
|
+
hostView.onEndReached = { [weak self] in self?.onEndReached?($0) }
|
|
33
|
+
hostView.onVisibleRangeChanged = { [weak self] in self?.onVisibleRangeChanged?($0) }
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
func applySnapshot(snapshotJson: String) throws {
|
|
37
|
+
runOnMain { [weak self] in self?.hostView.applySnapshotJson(snapshotJson) }
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
func applyPatches(patchesJson: String) throws {
|
|
41
|
+
runOnMain { [weak self] in self?.hostView.applyPatchesJson(patchesJson) }
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
func reconcileSelection(selectedKeysJson: String) throws {
|
|
45
|
+
runOnMain { [weak self] in self?.hostView.reconcileSelectionJson(selectedKeysJson) }
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
func scrollToKey(
|
|
49
|
+
key: String,
|
|
50
|
+
animated: Bool,
|
|
51
|
+
alignment: NativeListScrollAlignment,
|
|
52
|
+
viewPosition: Double,
|
|
53
|
+
viewOffset: Double
|
|
54
|
+
) throws {
|
|
55
|
+
runOnMain { [weak self] in
|
|
56
|
+
self?.hostView.scrollToKey(
|
|
57
|
+
key,
|
|
58
|
+
animated: animated,
|
|
59
|
+
alignment: alignment.stringValue,
|
|
60
|
+
viewPosition: viewPosition,
|
|
61
|
+
viewOffset: viewOffset
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
func scrollToIndex(
|
|
67
|
+
index: Double,
|
|
68
|
+
animated: Bool,
|
|
69
|
+
alignment: NativeListScrollAlignment,
|
|
70
|
+
viewPosition: Double,
|
|
71
|
+
viewOffset: Double
|
|
72
|
+
) throws {
|
|
73
|
+
guard index.isFinite,
|
|
74
|
+
index >= 0,
|
|
75
|
+
index.rounded(.towardZero) == index,
|
|
76
|
+
index <= Double(Int.max) else { return }
|
|
77
|
+
runOnMain { [weak self] in
|
|
78
|
+
self?.hostView.scrollToIndex(
|
|
79
|
+
Int(index),
|
|
80
|
+
animated: animated,
|
|
81
|
+
alignment: alignment.stringValue,
|
|
82
|
+
viewPosition: viewPosition,
|
|
83
|
+
viewOffset: viewOffset
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
func scrollToOffset(offset: Double, animated: Bool) throws {
|
|
89
|
+
guard offset.isFinite, offset >= 0 else { return }
|
|
90
|
+
runOnMain { [weak self] in
|
|
91
|
+
self?.hostView.scrollToOffset(offset, animated: animated)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
func scrollToEnd(animated: Bool) throws {
|
|
96
|
+
runOnMain { [weak self] in self?.hostView.scrollToEnd(animated: animated) }
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
func setActionAnchorState(stateJson: String) throws {
|
|
100
|
+
runOnMain { [weak self] in self?.hostView.setActionAnchorStateJson(stateJson) }
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
func setRefreshing(refreshing: Bool) throws {
|
|
104
|
+
runOnMain { [weak self] in self?.hostView.setRefreshing(refreshing) }
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
func onDropView() {
|
|
108
|
+
runOnMain { [weak self] in self?.hostView.disposeActionAnchor() }
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
func dispose() {
|
|
112
|
+
runOnMain { [weak self] in self?.hostView.disposeActionAnchor() }
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
deinit {
|
|
116
|
+
if Thread.isMainThread {
|
|
117
|
+
hostView.disposeActionAnchor()
|
|
118
|
+
} else {
|
|
119
|
+
let view = hostView
|
|
120
|
+
DispatchQueue.main.async { view.disposeActionAnchor() }
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
private func runOnMain(_ work: @escaping () -> Void) {
|
|
125
|
+
if Thread.isMainThread {
|
|
126
|
+
work()
|
|
127
|
+
} else {
|
|
128
|
+
DispatchQueue.main.async(execute: work)
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|