@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
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import CoreText
|
|
2
|
+
import UIKit
|
|
3
|
+
|
|
4
|
+
private final class NativeListResourceToken {}
|
|
5
|
+
|
|
6
|
+
enum NativeListFontWeight {
|
|
7
|
+
case regular
|
|
8
|
+
case medium
|
|
9
|
+
case semibold
|
|
10
|
+
case bold
|
|
11
|
+
|
|
12
|
+
fileprivate var postScriptName: String {
|
|
13
|
+
switch self {
|
|
14
|
+
case .regular: return "Roobert-Regular"
|
|
15
|
+
case .medium: return "Roobert-Medium"
|
|
16
|
+
case .semibold: return "Roobert-SemiBold"
|
|
17
|
+
case .bold: return "Roobert-Bold"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
fileprivate var systemWeight: UIFont.Weight {
|
|
22
|
+
switch self {
|
|
23
|
+
case .regular: return .regular
|
|
24
|
+
case .medium: return .medium
|
|
25
|
+
case .semibold: return .semibold
|
|
26
|
+
case .bold: return .bold
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
private enum NativeListResources {
|
|
32
|
+
static let bundle: Bundle = {
|
|
33
|
+
let owners = [Bundle(for: NativeListResourceToken.self), .main]
|
|
34
|
+
for owner in owners {
|
|
35
|
+
if let url = owner.url(forResource: "NativeListResources", withExtension: "bundle"),
|
|
36
|
+
let bundle = Bundle(url: url) {
|
|
37
|
+
return bundle
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return Bundle(for: NativeListResourceToken.self)
|
|
41
|
+
}()
|
|
42
|
+
|
|
43
|
+
static let registerFonts: Void = {
|
|
44
|
+
["Regular", "Medium", "SemiBold", "Bold"].forEach { weight in
|
|
45
|
+
let directURL = bundle.url(forResource: "Roobert-\(weight)", withExtension: "ttf")
|
|
46
|
+
let nestedURL = bundle.url(
|
|
47
|
+
forResource: "Roobert-\(weight)",
|
|
48
|
+
withExtension: "ttf",
|
|
49
|
+
subdirectory: "fonts"
|
|
50
|
+
)
|
|
51
|
+
guard let url = directURL ?? nestedURL else { return }
|
|
52
|
+
CTFontManagerRegisterFontsForURL(url as CFURL, .process, nil)
|
|
53
|
+
}
|
|
54
|
+
}()
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
func nativeListFont(ofSize size: CGFloat, weight: NativeListFontWeight = .regular) -> UIFont {
|
|
58
|
+
_ = NativeListResources.registerFonts
|
|
59
|
+
return UIFont(name: weight.postScriptName, size: size)
|
|
60
|
+
?? UIFont.systemFont(ofSize: size, weight: weight.systemWeight)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
func nativeListTabularFont(
|
|
64
|
+
ofSize size: CGFloat,
|
|
65
|
+
weight: NativeListFontWeight = .regular
|
|
66
|
+
) -> UIFont {
|
|
67
|
+
let font = nativeListFont(ofSize: size, weight: weight)
|
|
68
|
+
let settings: [[UIFontDescriptor.FeatureKey: Int]] = [[
|
|
69
|
+
.type: kNumberSpacingType,
|
|
70
|
+
.selector: kMonospacedNumbersSelector,
|
|
71
|
+
]]
|
|
72
|
+
let descriptor = font.fontDescriptor.addingAttributes([
|
|
73
|
+
.featureSettings: settings,
|
|
74
|
+
])
|
|
75
|
+
return UIFont(descriptor: descriptor, size: size)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
func nativeListIcon(named name: String) -> UIImage? {
|
|
79
|
+
let assetName: String
|
|
80
|
+
switch name {
|
|
81
|
+
case "ArrowBottomOutline": assetName = "onekey_arrow_bottom"
|
|
82
|
+
case "ArrowTopOutline": assetName = "onekey_arrow_top"
|
|
83
|
+
case "ChartTrendingUpOutline": assetName = "onekey_chart_trending_up"
|
|
84
|
+
case "SwapHorOutline": assetName = "onekey_swap_hor"
|
|
85
|
+
case "ShieldExclamationOutline": assetName = "onekey_shield_exclamation"
|
|
86
|
+
case "InfoCircleOutline": assetName = "onekey_info_circle"
|
|
87
|
+
case "SpeakerPromoteOutline": assetName = "onekey_speaker_promote"
|
|
88
|
+
case "PlusCircleOutline": assetName = "onekey_plus_circle"
|
|
89
|
+
case "PlusSmallOutline": assetName = "onekey_plus_small"
|
|
90
|
+
case "DotHorOutline": assetName = "onekey_dot_hor"
|
|
91
|
+
case "PencilOutline": assetName = "onekey_pencil"
|
|
92
|
+
case "MinusCircleSolid": assetName = "onekey_minus_circle_solid"
|
|
93
|
+
case "MinusCircleOutline": assetName = "onekey_minus_circle"
|
|
94
|
+
case "ChevronRightSmallOutline": assetName = "onekey_chevron_right_small"
|
|
95
|
+
case "DragOutline": assetName = "onekey_drag"
|
|
96
|
+
case "StarOutline": assetName = "onekey_star"
|
|
97
|
+
case "StarSolid": assetName = "onekey_star_solid"
|
|
98
|
+
case "ChevronGrabberVerOutline": assetName = "onekey_chevron_grabber_ver"
|
|
99
|
+
case "ChevronBottomOutline": assetName = "onekey_chevron_bottom"
|
|
100
|
+
case "ChevronTopOutline": assetName = "onekey_chevron_top"
|
|
101
|
+
case "CheckboxCheckedCustom": assetName = "onekey_checkbox_checked"
|
|
102
|
+
case "CheckboxIndeterminateCustom": assetName = "onekey_checkbox_indeterminate"
|
|
103
|
+
case "ErrorSolid": assetName = "onekey_error_solid"
|
|
104
|
+
case "QuestionmarkSolid": assetName = "onekey_questionmark_solid"
|
|
105
|
+
case "ImageSquareWavesOutline": assetName = "onekey_image_square_waves"
|
|
106
|
+
default: return nil
|
|
107
|
+
}
|
|
108
|
+
return UIImage(named: assetName, in: NativeListResources.bundle, compatibleWith: nil)?
|
|
109
|
+
.withRenderingMode(.alwaysTemplate)
|
|
110
|
+
}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import UIKit
|
|
3
|
+
|
|
4
|
+
struct NativeListItem {
|
|
5
|
+
let key: String
|
|
6
|
+
let type: String
|
|
7
|
+
let sectionKey: String?
|
|
8
|
+
let revision: Int
|
|
9
|
+
let data: [String: Any]
|
|
10
|
+
let content: String
|
|
11
|
+
|
|
12
|
+
var isSelectable: Bool {
|
|
13
|
+
let disabled = data["disabled"] as? Bool ?? false
|
|
14
|
+
return !disabled && Self.selectableTypes.contains(type)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
var isReorderable: Bool {
|
|
18
|
+
guard !data.bool("disabled") else { return false }
|
|
19
|
+
if type == "rail", data.bool("draggable") { return true }
|
|
20
|
+
if type == "identity", data.bool("draggable") { return true }
|
|
21
|
+
if type == "walletGroup", data.bool("draggable") { return true }
|
|
22
|
+
return data.dictionaries("trailing").contains { $0.string("kind") == "drag" }
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
init(data: [String: Any]) throws {
|
|
26
|
+
guard let key = data["key"] as? String, !key.isEmpty,
|
|
27
|
+
let type = data["type"] as? String, !type.isEmpty else {
|
|
28
|
+
throw NativeListModelError.invalidRow
|
|
29
|
+
}
|
|
30
|
+
self.key = key
|
|
31
|
+
self.type = type
|
|
32
|
+
self.sectionKey = data["sectionKey"] as? String
|
|
33
|
+
self.revision = data["revision"] as? Int ?? 0
|
|
34
|
+
self.data = data
|
|
35
|
+
let jsonData = try JSONSerialization.data(withJSONObject: data, options: [.sortedKeys])
|
|
36
|
+
self.content = String(data: jsonData, encoding: .utf8) ?? ""
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private static let selectableTypes: Set<String> = [
|
|
40
|
+
"identity", "rail", "activity", "message", "dataRow", "mediaTile", "metricCard",
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
struct NativeListConfig {
|
|
45
|
+
let generation: Int
|
|
46
|
+
let layout: String
|
|
47
|
+
let orientation: String
|
|
48
|
+
let gridColumns: Int
|
|
49
|
+
let stickyHeaders: Bool
|
|
50
|
+
let contentPadding: CGFloat
|
|
51
|
+
let contentPaddingHorizontal: CGFloat
|
|
52
|
+
let contentPaddingTop: CGFloat
|
|
53
|
+
let contentPaddingBottom: CGFloat
|
|
54
|
+
let itemSpacing: CGFloat
|
|
55
|
+
let selectionMode: String
|
|
56
|
+
let rowPressToggles: Bool
|
|
57
|
+
var selectedKeys: Set<String>
|
|
58
|
+
let reorderable: Bool
|
|
59
|
+
let pullToRefresh: Bool
|
|
60
|
+
var refreshing: Bool
|
|
61
|
+
let loadMore: Bool
|
|
62
|
+
let endReachedThreshold: Double
|
|
63
|
+
let sectionIndexEnabled: Bool
|
|
64
|
+
let sectionIndexHapticsEnabled: Bool
|
|
65
|
+
let theme: [String: Any]?
|
|
66
|
+
let fixedFooter: NativeListItem?
|
|
67
|
+
var items: [NativeListItem]
|
|
68
|
+
|
|
69
|
+
static func parse(json: String) throws -> NativeListConfig {
|
|
70
|
+
guard let bytes = json.data(using: .utf8),
|
|
71
|
+
let root = try JSONSerialization.jsonObject(with: bytes) as? [String: Any],
|
|
72
|
+
root["schemaVersion"] as? Int == 1,
|
|
73
|
+
let generation = root["generation"] as? Int,
|
|
74
|
+
let layoutData = root["layout"] as? [String: Any],
|
|
75
|
+
let layout = layoutData["kind"] as? String,
|
|
76
|
+
let rowData = root["rows"] as? [[String: Any]] else {
|
|
77
|
+
throw NativeListModelError.invalidSnapshot
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
var items = try rowData.map(NativeListItem.init)
|
|
81
|
+
let keys = Set(items.map(\.key))
|
|
82
|
+
guard keys.count == items.count else { throw NativeListModelError.duplicateKey }
|
|
83
|
+
if items.isEmpty, let emptyData = root["emptyState"] as? [String: Any] {
|
|
84
|
+
items = [try NativeListItem(data: emptyData)]
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
let selection = root["selection"] as? [String: Any]
|
|
88
|
+
let selectedKeys = Set(selection?["selectedKeys"] as? [String] ?? [])
|
|
89
|
+
guard selectedKeys.isSubset(of: keys) else { throw NativeListModelError.unknownSelectionKey }
|
|
90
|
+
let capabilities = root["capabilities"] as? [String: Any]
|
|
91
|
+
let sectionIndex = capabilities?["sectionIndex"] as? [String: Any]
|
|
92
|
+
let footer = try (root["fixedFooter"] as? [String: Any]).map(NativeListItem.init)
|
|
93
|
+
|
|
94
|
+
let contentPadding = max(0, CGFloat(layoutData.double("contentPadding")))
|
|
95
|
+
let contentPaddingHorizontal = layoutData["contentPaddingHorizontal"] == nil
|
|
96
|
+
? contentPadding
|
|
97
|
+
: max(0, CGFloat(layoutData.double("contentPaddingHorizontal")))
|
|
98
|
+
let contentPaddingTop = layoutData["contentPaddingTop"] == nil
|
|
99
|
+
? contentPadding
|
|
100
|
+
: max(0, CGFloat(layoutData.double("contentPaddingTop")))
|
|
101
|
+
let contentPaddingBottom = layoutData["contentPaddingBottom"] == nil
|
|
102
|
+
? contentPadding
|
|
103
|
+
: max(0, CGFloat(layoutData.double("contentPaddingBottom")))
|
|
104
|
+
|
|
105
|
+
return NativeListConfig(
|
|
106
|
+
generation: generation,
|
|
107
|
+
layout: layout,
|
|
108
|
+
orientation: layoutData["orientation"] as? String ?? "vertical",
|
|
109
|
+
gridColumns: min(4, max(1, layoutData["gridColumns"] as? Int ?? 1)),
|
|
110
|
+
stickyHeaders: layoutData["stickyHeaders"] as? Bool ?? false,
|
|
111
|
+
contentPadding: contentPadding,
|
|
112
|
+
contentPaddingHorizontal: contentPaddingHorizontal,
|
|
113
|
+
contentPaddingTop: contentPaddingTop,
|
|
114
|
+
contentPaddingBottom: contentPaddingBottom,
|
|
115
|
+
itemSpacing: max(0, layoutData["itemSpacing"] as? CGFloat ?? 0),
|
|
116
|
+
selectionMode: selection?["mode"] as? String ?? "none",
|
|
117
|
+
rowPressToggles: selection?["rowPressToggles"] as? Bool ?? false,
|
|
118
|
+
selectedKeys: selectedKeys,
|
|
119
|
+
reorderable: capabilities?["reorderable"] as? Bool ?? false,
|
|
120
|
+
pullToRefresh: capabilities?["pullToRefresh"] as? Bool ?? false,
|
|
121
|
+
refreshing: capabilities?["refreshing"] as? Bool ?? false,
|
|
122
|
+
loadMore: capabilities?["loadMore"] as? Bool ?? false,
|
|
123
|
+
endReachedThreshold: capabilities?["endReachedThreshold"] as? Double ?? 0.2,
|
|
124
|
+
sectionIndexEnabled: sectionIndex?["enabled"] as? Bool ?? false,
|
|
125
|
+
sectionIndexHapticsEnabled: sectionIndex?["hapticsEnabled"] as? Bool ?? true,
|
|
126
|
+
theme: root["theme"] as? [String: Any],
|
|
127
|
+
fixedFooter: footer,
|
|
128
|
+
items: items
|
|
129
|
+
)
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
enum NativeListModelError: Error {
|
|
134
|
+
case invalidSnapshot
|
|
135
|
+
case invalidRow
|
|
136
|
+
case duplicateKey
|
|
137
|
+
case unknownSelectionKey
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
struct NativeSelectionTarget {
|
|
141
|
+
let scope: String
|
|
142
|
+
let key: String?
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
extension Dictionary where Key == String, Value == Any {
|
|
146
|
+
func string(_ key: String, default fallback: String = "") -> String {
|
|
147
|
+
self[key] as? String ?? fallback
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
func bool(_ key: String, default fallback: Bool = false) -> Bool {
|
|
151
|
+
self[key] as? Bool ?? fallback
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
func int(_ key: String, default fallback: Int = 0) -> Int {
|
|
155
|
+
if let value = self[key] as? Int { return value }
|
|
156
|
+
if let value = self[key] as? NSNumber { return value.intValue }
|
|
157
|
+
return fallback
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
func double(_ key: String, default fallback: Double = 0) -> Double {
|
|
161
|
+
if let value = self[key] as? Double { return value }
|
|
162
|
+
if let value = self[key] as? NSNumber { return value.doubleValue }
|
|
163
|
+
return fallback
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
func dictionary(_ key: String) -> [String: Any]? {
|
|
167
|
+
self[key] as? [String: Any]
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
func dictionaries(_ key: String) -> [[String: Any]] {
|
|
171
|
+
self[key] as? [[String: Any]] ?? []
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
extension UIColor {
|
|
176
|
+
convenience init(nativeListHex value: String, fallback: UIColor) {
|
|
177
|
+
let value = value.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
|
|
178
|
+
var hex: UInt64 = 0
|
|
179
|
+
guard Scanner(string: value).scanHexInt64(&hex) else {
|
|
180
|
+
self.init(cgColor: fallback.cgColor)
|
|
181
|
+
return
|
|
182
|
+
}
|
|
183
|
+
let red: CGFloat
|
|
184
|
+
let green: CGFloat
|
|
185
|
+
let blue: CGFloat
|
|
186
|
+
let alpha: CGFloat
|
|
187
|
+
switch value.count {
|
|
188
|
+
case 8:
|
|
189
|
+
red = CGFloat((hex >> 24) & 0xff) / 255
|
|
190
|
+
green = CGFloat((hex >> 16) & 0xff) / 255
|
|
191
|
+
blue = CGFloat((hex >> 8) & 0xff) / 255
|
|
192
|
+
alpha = CGFloat(hex & 0xff) / 255
|
|
193
|
+
case 6:
|
|
194
|
+
red = CGFloat((hex >> 16) & 0xff) / 255
|
|
195
|
+
green = CGFloat((hex >> 8) & 0xff) / 255
|
|
196
|
+
blue = CGFloat(hex & 0xff) / 255
|
|
197
|
+
alpha = 1
|
|
198
|
+
default:
|
|
199
|
+
self.init(cgColor: fallback.cgColor)
|
|
200
|
+
return
|
|
201
|
+
}
|
|
202
|
+
self.init(red: red, green: green, blue: blue, alpha: alpha)
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
func nativeListColor(
|
|
207
|
+
_ theme: [String: Any]?,
|
|
208
|
+
_ key: String,
|
|
209
|
+
_ fallback: String
|
|
210
|
+
) -> UIColor {
|
|
211
|
+
UIColor(
|
|
212
|
+
nativeListHex: theme?[key] as? String ?? fallback,
|
|
213
|
+
fallback: UIColor(nativeListHex: fallback, fallback: .black)
|
|
214
|
+
)
|
|
215
|
+
}
|