react-native-list 1.0.0 → 2.0.0-alpha.1
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 +190 -32
- package/ReactNativeList.podspec +39 -0
- package/android/CMakeLists.txt +48 -0
- package/android/build.gradle +151 -0
- package/android/fix-prefab.gradle +51 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/cpp/JHybridUiListModule.cpp +192 -0
- package/android/src/main/cpp/JHybridUiListModule.h +50 -0
- package/android/src/main/cpp/cpp-adapter.cpp +12 -0
- package/android/src/main/java/com/hannojg/reactnativelist/ReactNativeListPackage.kt +27 -0
- package/android/src/main/java/com/margelo/nitro/reactnativelist/HybridNativeListDataSource.kt +146 -0
- package/android/src/main/java/com/margelo/nitro/reactnativelist/HybridNativeListLayout.kt +86 -0
- package/android/src/main/java/com/margelo/nitro/reactnativelist/HybridUiListModule.kt +116 -0
- package/android/src/main/java/com/margelo/nitro/reactnativelist/HybridUiListView.kt +410 -0
- package/android/src/main/java/com/margelo/nitro/reactnativelist/HybridViewHolder.kt +9 -0
- package/android/src/main/java/com/margelo/nitro/reactnativelist/NativeListAdapter.kt +217 -0
- package/ios/DataSource/HybridNativeListDataSource.swift +213 -0
- package/ios/HybridObjects/HybridUiListModule.swift +49 -0
- package/ios/HybridObjects/HybridViewHolder.swift +16 -0
- package/ios/Layout/HybridNativeListLayout.swift +128 -0
- package/ios/Utils/ErrorUtils.h +26 -0
- package/ios/Utils/HybridIOSWorkletsModuleProxyHolder.swift +10 -0
- package/ios/Utils/SurfaceHelper.h +20 -0
- package/ios/Utils/SurfaceHelper.mm +144 -0
- package/ios/Utils/SurfacePresenterRegistry.h +17 -0
- package/ios/Utils/SurfacePresenterRegistry.m +31 -0
- package/ios/Utils/TurboModuleInstaller.h +18 -0
- package/ios/Utils/TurboModuleInstaller.mm +267 -0
- package/ios/Views/HostCell.swift +216 -0
- package/ios/Views/HybridUiListView.swift +695 -0
- package/metro/RendererProxyThreadSwitch.js +66 -0
- package/metro-config.d.ts +1 -0
- package/metro-config.js +52 -0
- package/nitro.json +47 -0
- package/nitrogen/generated/.gitattributes +1 -0
- package/nitrogen/generated/android/ReactNativeList+autolinking.cmake +99 -0
- package/nitrogen/generated/android/ReactNativeList+autolinking.gradle +27 -0
- package/nitrogen/generated/android/ReactNativeListOnLoad.cpp +156 -0
- package/nitrogen/generated/android/ReactNativeListOnLoad.hpp +34 -0
- package/nitrogen/generated/android/c++/JFunc_bool_NativeListItem_NativeListItem.hpp +83 -0
- package/nitrogen/generated/android/c++/JFunc_bool_double_NativeListItem_double.hpp +83 -0
- package/nitrogen/generated/android/c++/JFunc_double_std__string.hpp +78 -0
- package/nitrogen/generated/android/c++/JHybridIOSWorkletsModuleProxyHolderSpec.cpp +49 -0
- package/nitrogen/generated/android/c++/JHybridIOSWorkletsModuleProxyHolderSpec.hpp +63 -0
- package/nitrogen/generated/android/c++/JHybridNativeLinearListLayoutSpec.cpp +63 -0
- package/nitrogen/generated/android/c++/JHybridNativeLinearListLayoutSpec.hpp +65 -0
- package/nitrogen/generated/android/c++/JHybridNativeListDataSourceSpec.cpp +101 -0
- package/nitrogen/generated/android/c++/JHybridNativeListDataSourceSpec.hpp +70 -0
- package/nitrogen/generated/android/c++/JHybridNativeListLayoutSpec.cpp +49 -0
- package/nitrogen/generated/android/c++/JHybridNativeListLayoutSpec.hpp +63 -0
- package/nitrogen/generated/android/c++/JHybridUiListModuleSpec.cpp +65 -0
- package/nitrogen/generated/android/c++/JHybridUiListModuleSpec.hpp +64 -0
- package/nitrogen/generated/android/c++/JHybridUiListViewSpec.cpp +92 -0
- package/nitrogen/generated/android/c++/JHybridUiListViewSpec.hpp +67 -0
- package/nitrogen/generated/android/c++/JHybridViewHolderSpec.cpp +49 -0
- package/nitrogen/generated/android/c++/JHybridViewHolderSpec.hpp +63 -0
- package/nitrogen/generated/android/c++/JNativeItemSizeEstimate.hpp +61 -0
- package/nitrogen/generated/android/c++/JNativeLinearListLayoutConfig.hpp +81 -0
- package/nitrogen/generated/android/c++/JNativeLinearListLayoutIOSConfig.hpp +59 -0
- package/nitrogen/generated/android/c++/JNativeListItem.hpp +76 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_HybridIOSWorkletsModuleProxyHolderSpec.cpp +26 -0
- package/nitrogen/generated/android/c++/JVariant_NullType_HybridIOSWorkletsModuleProxyHolderSpec.hpp +72 -0
- package/nitrogen/generated/android/c++/views/JHybridUiListViewStateUpdater.cpp +53 -0
- package/nitrogen/generated/android/c++/views/JHybridUiListViewStateUpdater.hpp +49 -0
- package/nitrogen/generated/android/c++/views/JHybridViewHolderStateUpdater.cpp +53 -0
- package/nitrogen/generated/android/c++/views/JHybridViewHolderStateUpdater.hpp +49 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/Func_bool_NativeListItem_NativeListItem.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/Func_bool_double_NativeListItem_double.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/Func_double_std__string.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridIOSWorkletsModuleProxyHolderSpec.kt +52 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridNativeLinearListLayoutSpec.kt +54 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridNativeListDataSourceSpec.kt +87 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridNativeListLayoutSpec.kt +52 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridUiListModuleSpec.kt +59 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridUiListViewSpec.kt +76 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/HybridViewHolderSpec.kt +53 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/NativeItemSizeEstimate.kt +56 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/NativeLinearListLayoutConfig.kt +76 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/NativeLinearListLayoutIOSConfig.kt +51 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/NativeListItem.kt +71 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/ReactNativeListOnLoad.kt +35 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/Variant_NullType_HybridIOSWorkletsModuleProxyHolderSpec.kt +62 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/views/HybridUiListViewManager.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/views/HybridUiListViewStateUpdater.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/views/HybridViewHolderManager.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/reactnativelist/views/HybridViewHolderStateUpdater.kt +23 -0
- package/nitrogen/generated/ios/ReactNativeList+autolinking.rb +62 -0
- package/nitrogen/generated/ios/ReactNativeList-Swift-Cxx-Bridge.cpp +162 -0
- package/nitrogen/generated/ios/ReactNativeList-Swift-Cxx-Bridge.hpp +368 -0
- package/nitrogen/generated/ios/ReactNativeList-Swift-Cxx-Umbrella.hpp +92 -0
- package/nitrogen/generated/ios/ReactNativeListAutolinking.mm +83 -0
- package/nitrogen/generated/ios/ReactNativeListAutolinking.swift +86 -0
- package/nitrogen/generated/ios/c++/HybridIOSWorkletsModuleProxyHolderSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridIOSWorkletsModuleProxyHolderSpecSwift.hpp +75 -0
- package/nitrogen/generated/ios/c++/HybridNativeLinearListLayoutSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridNativeLinearListLayoutSpecSwift.hpp +92 -0
- package/nitrogen/generated/ios/c++/HybridNativeListDataSourceSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridNativeListDataSourceSpecSwift.hpp +132 -0
- package/nitrogen/generated/ios/c++/HybridNativeListLayoutSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridNativeListLayoutSpecSwift.hpp +75 -0
- package/nitrogen/generated/ios/c++/HybridUiListModuleSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridUiListModuleSpecSwift.hpp +93 -0
- package/nitrogen/generated/ios/c++/HybridUiListViewSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridUiListViewSpecSwift.hpp +121 -0
- package/nitrogen/generated/ios/c++/HybridViewHolderSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridViewHolderSpecSwift.hpp +75 -0
- package/nitrogen/generated/ios/c++/views/HybridUiListViewComponent.mm +118 -0
- package/nitrogen/generated/ios/c++/views/HybridViewHolderComponent.mm +118 -0
- package/nitrogen/generated/ios/swift/Func_bool_NativeListItem_NativeListItem.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_bool_double_NativeListItem_double.swift +47 -0
- package/nitrogen/generated/ios/swift/Func_double_std__string.swift +47 -0
- package/nitrogen/generated/ios/swift/HybridIOSWorkletsModuleProxyHolderSpec.swift +55 -0
- package/nitrogen/generated/ios/swift/HybridIOSWorkletsModuleProxyHolderSpec_cxx.swift +128 -0
- package/nitrogen/generated/ios/swift/HybridNativeLinearListLayoutSpec.swift +55 -0
- package/nitrogen/generated/ios/swift/HybridNativeLinearListLayoutSpec_cxx.swift +140 -0
- package/nitrogen/generated/ios/swift/HybridNativeListDataSourceSpec.swift +62 -0
- package/nitrogen/generated/ios/swift/HybridNativeListDataSourceSpec_cxx.swift +222 -0
- package/nitrogen/generated/ios/swift/HybridNativeListLayoutSpec.swift +55 -0
- package/nitrogen/generated/ios/swift/HybridNativeListLayoutSpec_cxx.swift +128 -0
- package/nitrogen/generated/ios/swift/HybridUiListModuleSpec.swift +56 -0
- package/nitrogen/generated/ios/swift/HybridUiListModuleSpec_cxx.swift +175 -0
- package/nitrogen/generated/ios/swift/HybridUiListViewSpec.swift +59 -0
- package/nitrogen/generated/ios/swift/HybridUiListViewSpec_cxx.swift +227 -0
- package/nitrogen/generated/ios/swift/HybridViewHolderSpec.swift +55 -0
- package/nitrogen/generated/ios/swift/HybridViewHolderSpec_cxx.swift +147 -0
- package/nitrogen/generated/ios/swift/NativeItemSizeEstimate.swift +60 -0
- package/nitrogen/generated/ios/swift/NativeLinearListLayoutConfig.swift +60 -0
- package/nitrogen/generated/ios/swift/NativeLinearListLayoutIOSConfig.swift +35 -0
- package/nitrogen/generated/ios/swift/NativeListItem.swift +75 -0
- package/nitrogen/generated/ios/swift/Variant_NullType__any_HybridIOSWorkletsModuleProxyHolderSpec_.swift +30 -0
- package/nitrogen/generated/shared/c++/HybridIOSWorkletsModuleProxyHolderSpec.cpp +21 -0
- package/nitrogen/generated/shared/c++/HybridIOSWorkletsModuleProxyHolderSpec.hpp +62 -0
- package/nitrogen/generated/shared/c++/HybridNativeLinearListLayoutSpec.cpp +22 -0
- package/nitrogen/generated/shared/c++/HybridNativeLinearListLayoutSpec.hpp +67 -0
- package/nitrogen/generated/shared/c++/HybridNativeListDataSourceSpec.cpp +28 -0
- package/nitrogen/generated/shared/c++/HybridNativeListDataSourceSpec.hpp +72 -0
- package/nitrogen/generated/shared/c++/HybridNativeListLayoutSpec.cpp +21 -0
- package/nitrogen/generated/shared/c++/HybridNativeListLayoutSpec.hpp +62 -0
- package/nitrogen/generated/shared/c++/HybridUiListModuleSpec.cpp +22 -0
- package/nitrogen/generated/shared/c++/HybridUiListModuleSpec.hpp +68 -0
- package/nitrogen/generated/shared/c++/HybridUiListViewSpec.cpp +25 -0
- package/nitrogen/generated/shared/c++/HybridUiListViewSpec.hpp +79 -0
- package/nitrogen/generated/shared/c++/HybridUiManagerHelperSpec.cpp +23 -0
- package/nitrogen/generated/shared/c++/HybridUiManagerHelperSpec.hpp +65 -0
- package/nitrogen/generated/shared/c++/HybridViewHolderSpec.cpp +21 -0
- package/nitrogen/generated/shared/c++/HybridViewHolderSpec.hpp +62 -0
- package/nitrogen/generated/shared/c++/NativeItemSizeEstimate.hpp +87 -0
- package/nitrogen/generated/shared/c++/NativeLinearListLayoutConfig.hpp +105 -0
- package/nitrogen/generated/shared/c++/NativeLinearListLayoutIOSConfig.hpp +85 -0
- package/nitrogen/generated/shared/c++/NativeListItem.hpp +101 -0
- package/nitrogen/generated/shared/c++/views/HybridUiListViewComponent.cpp +72 -0
- package/nitrogen/generated/shared/c++/views/HybridUiListViewComponent.hpp +109 -0
- package/nitrogen/generated/shared/c++/views/HybridViewHolderComponent.cpp +72 -0
- package/nitrogen/generated/shared/c++/views/HybridViewHolderComponent.hpp +109 -0
- package/nitrogen/generated/shared/json/UiListViewConfig.json +9 -0
- package/nitrogen/generated/shared/json/ViewHolderConfig.json +9 -0
- package/package.json +152 -5
- package/react-native.config.js +16 -0
- package/src/ListDataSource.ts +232 -0
- package/src/ListLayout.ts +95 -0
- package/src/UiListModule.ts +5 -0
- package/src/hooks/useChangeEffect.ts +50 -0
- package/src/index.tsx +49 -0
- package/src/privateGlobals.ts +20 -0
- package/src/renderer/fabric/RenderHelper.ts +29 -0
- package/src/renderer/fabric/UiManagerHelper.ts +5 -0
- package/src/renderer/react/ReactFabricMirror.bundle.js +1984 -0
- package/src/renderer/react/ReactFabricMirror.ts +766 -0
- package/src/renderer/react/ReactFabricRenderer.ts +11 -0
- package/src/specs/IOSWorkletsModuleProxyHolder.nitro.ts +6 -0
- package/src/specs/NativeLinearListLayout.nitro.ts +23 -0
- package/src/specs/NativeListDataSource.nitro.ts +28 -0
- package/src/specs/NativeListLayout.nitro.ts +6 -0
- package/src/specs/UIListModule.nitro.ts +13 -0
- package/src/specs/UIManagerHelper.nitro.ts +34 -0
- package/src/specs/UiListView.nitro.ts +31 -0
- package/src/specs/ViewHolder.nitro.ts +11 -0
- package/src/views/List.tsx +525 -0
- package/src/views/UiListHostComponent.ts +8 -0
- package/FillRateHelper.js +0 -179
- package/FlatList.js +0 -494
- package/LICENSE.md +0 -31
- package/ListView/__mocks__/ListViewMock.js +0 -55
- package/MetroListView.js +0 -166
- package/SectionList.js +0 -291
- package/ViewabilityHelper.js +0 -260
- package/VirtualizeUtils.js +0 -163
- package/VirtualizedList.js +0 -861
- package/VirtualizedSectionList.js +0 -397
- package/__flowtests__/FlatList-flowtest.js +0 -90
- package/__flowtests__/SectionList-flowtest.js +0 -89
- package/__tests__/FillRateHelper-test.js +0 -106
- package/__tests__/FlatList-test.js +0 -64
- package/__tests__/SectionList-test.js +0 -67
- package/__tests__/ViewabilityHelper-test.js +0 -359
- package/__tests__/VirtualizeUtils-test.js +0 -74
- package/__tests__/__snapshots__/FlatList-test.js.snap +0 -251
- package/__tests__/__snapshots__/SectionList-test.js.snap +0 -283
- package/index.js +0 -5
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import DifferenceKit
|
|
2
|
+
import Foundation
|
|
3
|
+
import NitroModules
|
|
4
|
+
|
|
5
|
+
final class DiffableListItem: Differentiable {
|
|
6
|
+
typealias DifferenceIdentifier = String
|
|
7
|
+
|
|
8
|
+
let nativeItem: NativeListItem
|
|
9
|
+
private let contentEqual: (NativeListItem, NativeListItem) -> Bool
|
|
10
|
+
|
|
11
|
+
init(
|
|
12
|
+
nativeItem: NativeListItem,
|
|
13
|
+
contentEqual: @escaping (NativeListItem, NativeListItem) -> Bool
|
|
14
|
+
) {
|
|
15
|
+
self.nativeItem = nativeItem
|
|
16
|
+
self.contentEqual = contentEqual
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
var differenceIdentifier: String {
|
|
20
|
+
return nativeItem.type + ":" + nativeItem.key
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
func isContentEqual(to source: DiffableListItem) -> Bool {
|
|
24
|
+
if nativeItem.type != source.nativeItem.type {
|
|
25
|
+
return false
|
|
26
|
+
}
|
|
27
|
+
if nativeItem.width != source.nativeItem.width {
|
|
28
|
+
return false
|
|
29
|
+
}
|
|
30
|
+
if nativeItem.height != source.nativeItem.height {
|
|
31
|
+
return false
|
|
32
|
+
}
|
|
33
|
+
return contentEqual(source.nativeItem, nativeItem)
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
protocol NativeListDataSourceObserver: AnyObject {
|
|
38
|
+
func dataSourceDidReload(
|
|
39
|
+
_ dataSource: HybridNativeListDataSource,
|
|
40
|
+
animated: Bool,
|
|
41
|
+
changeset: StagedChangeset<[DiffableListItem]>?
|
|
42
|
+
)
|
|
43
|
+
func dataSourceDidInsert(_ dataSource: HybridNativeListDataSource, index: Int)
|
|
44
|
+
func dataSourceDidUpdate(
|
|
45
|
+
_ dataSource: HybridNativeListDataSource,
|
|
46
|
+
index: Int,
|
|
47
|
+
previousItem: NativeListItem
|
|
48
|
+
)
|
|
49
|
+
func dataSourceDidRemove(
|
|
50
|
+
_ dataSource: HybridNativeListDataSource,
|
|
51
|
+
index: Int,
|
|
52
|
+
removedItem: NativeListItem
|
|
53
|
+
)
|
|
54
|
+
func dataSourceDidMove(_ dataSource: HybridNativeListDataSource, fromIndex: Int, toIndex: Int)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
class HybridNativeListDataSource: HybridNativeListDataSourceSpec {
|
|
58
|
+
weak var observer: NativeListDataSourceObserver?
|
|
59
|
+
private var items: [DiffableListItem] = []
|
|
60
|
+
private var pendingTargetItems: [DiffableListItem]?
|
|
61
|
+
private var animatedReloadSourceItems: [DiffableListItem]?
|
|
62
|
+
private var contentEqual: (NativeListItem, NativeListItem) -> Bool = { _, _ in false }
|
|
63
|
+
|
|
64
|
+
func dispose() {
|
|
65
|
+
observer = nil
|
|
66
|
+
items.removeAll()
|
|
67
|
+
pendingTargetItems = nil
|
|
68
|
+
animatedReloadSourceItems = nil
|
|
69
|
+
contentEqual = { _, _ in false }
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
func setContentEqualCallback(
|
|
73
|
+
isContentEqual: @escaping (NativeListItem, NativeListItem) -> Bool
|
|
74
|
+
) throws {
|
|
75
|
+
contentEqual = isContentEqual
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
func replaceData(items newItems: [NativeListItem], animated: Bool) throws {
|
|
79
|
+
let targetItems = wrap(newItems)
|
|
80
|
+
guard animated, observer != nil else {
|
|
81
|
+
pendingTargetItems = nil
|
|
82
|
+
animatedReloadSourceItems = nil
|
|
83
|
+
items = targetItems
|
|
84
|
+
observer?.dataSourceDidReload(self, animated: false, changeset: nil)
|
|
85
|
+
return
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
animatedReloadSourceItems = items
|
|
89
|
+
let changeset = StagedChangeset(source: items, target: targetItems)
|
|
90
|
+
guard !changeset.isEmpty else {
|
|
91
|
+
pendingTargetItems = nil
|
|
92
|
+
animatedReloadSourceItems = nil
|
|
93
|
+
items = targetItems
|
|
94
|
+
observer?.dataSourceDidReload(self, animated: false, changeset: nil)
|
|
95
|
+
return
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
pendingTargetItems = targetItems
|
|
99
|
+
observer?.dataSourceDidReload(self, animated: true, changeset: changeset)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
func insertItem(index: Double, item: NativeListItem) throws {
|
|
103
|
+
let itemIndex = validInsertionIndex(index)
|
|
104
|
+
let wrappedItem = wrap(item)
|
|
105
|
+
items.insert(wrappedItem, at: itemIndex)
|
|
106
|
+
observer?.dataSourceDidInsert(self, index: itemIndex)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
func updateItem(index: Double, item: NativeListItem) throws {
|
|
110
|
+
let itemIndex = validExistingIndex(index)
|
|
111
|
+
let previousItem = items[itemIndex].nativeItem
|
|
112
|
+
let wrappedItem = wrap(item)
|
|
113
|
+
items[itemIndex] = wrappedItem
|
|
114
|
+
observer?.dataSourceDidUpdate(self, index: itemIndex, previousItem: previousItem)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
func removeItem(index: Double) throws {
|
|
118
|
+
let itemIndex = validExistingIndex(index)
|
|
119
|
+
let removedItem = items.remove(at: itemIndex).nativeItem
|
|
120
|
+
observer?.dataSourceDidRemove(self, index: itemIndex, removedItem: removedItem)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
func moveItem(fromIndex: Double, toIndex: Double) throws {
|
|
124
|
+
let sourceIndex = validExistingIndex(fromIndex)
|
|
125
|
+
let targetIndex = validExistingIndex(toIndex)
|
|
126
|
+
let item = items.remove(at: sourceIndex)
|
|
127
|
+
items.insert(item, at: targetIndex)
|
|
128
|
+
observer?.dataSourceDidMove(self, fromIndex: sourceIndex, toIndex: targetIndex)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
func getCount() throws -> Double {
|
|
132
|
+
return Double(items.count)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
func getItem(index: Double) throws -> NativeListItem {
|
|
136
|
+
let itemIndex = validExistingIndex(index)
|
|
137
|
+
return item(at: itemIndex)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
func item(at index: Int) -> NativeListItem {
|
|
141
|
+
return items[index].nativeItem
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
func itemForCollectionViewQuery(at index: Int) -> NativeListItem {
|
|
145
|
+
if items.indices.contains(index) {
|
|
146
|
+
return items[index].nativeItem
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// During DifferenceKit staged reloads, UICollectionViewFlowLayout can still ask for
|
|
150
|
+
// sizing information from the pre-animation snapshot after the stage data was applied.
|
|
151
|
+
if let animatedReloadSourceItems, animatedReloadSourceItems.indices.contains(index) {
|
|
152
|
+
return animatedReloadSourceItems[index].nativeItem
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
preconditionFailure("List item index \(index) is out of bounds for collection view query.")
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
func replaceWrappedItemsFromCollectionView(_ nextItems: [DiffableListItem]) {
|
|
159
|
+
items = nextItems
|
|
160
|
+
|
|
161
|
+
guard let pendingTargetItems else {
|
|
162
|
+
animatedReloadSourceItems = nil
|
|
163
|
+
return
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
if hasSameIdentity(nextItems, pendingTargetItems) {
|
|
167
|
+
self.pendingTargetItems = nil
|
|
168
|
+
animatedReloadSourceItems = nil
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
func itemsForPremeasurement() -> [NativeListItem] {
|
|
173
|
+
let sourceItems = pendingTargetItems ?? items
|
|
174
|
+
return sourceItems.map { item in
|
|
175
|
+
item.nativeItem
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
private func wrap(_ item: NativeListItem) -> DiffableListItem {
|
|
180
|
+
return DiffableListItem(nativeItem: item, contentEqual: contentEqual)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
private func wrap(_ nativeItems: [NativeListItem]) -> [DiffableListItem] {
|
|
184
|
+
return nativeItems.map { item in
|
|
185
|
+
wrap(item)
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
private func hasSameIdentity(
|
|
190
|
+
_ firstItems: [DiffableListItem],
|
|
191
|
+
_ secondItems: [DiffableListItem]
|
|
192
|
+
) -> Bool {
|
|
193
|
+
if firstItems.count != secondItems.count {
|
|
194
|
+
return false
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
return zip(firstItems, secondItems).allSatisfy { firstItem, secondItem in
|
|
198
|
+
return firstItem.differenceIdentifier == secondItem.differenceIdentifier
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
private func validExistingIndex(_ value: Double) -> Int {
|
|
203
|
+
let index = Int(value)
|
|
204
|
+
precondition(index >= 0 && index < items.count, "List index \(index) is out of bounds.")
|
|
205
|
+
return index
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
private func validInsertionIndex(_ value: Double) -> Int {
|
|
209
|
+
let index = Int(value)
|
|
210
|
+
precondition(index >= 0 && index <= items.count, "List index \(index) is out of bounds.")
|
|
211
|
+
return index
|
|
212
|
+
}
|
|
213
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
//
|
|
2
|
+
// HybridUiListModule.swift
|
|
3
|
+
// ReactNativeList
|
|
4
|
+
//
|
|
5
|
+
// Created by Hanno Gödecke on 14.02.26.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
import NitroModules
|
|
10
|
+
|
|
11
|
+
class HybridUiListModule : HybridUiListModuleSpec {
|
|
12
|
+
func iosGetWorkletsModule() throws -> any HybridIOSWorkletsModuleProxyHolderSpec {
|
|
13
|
+
do {
|
|
14
|
+
let holderBox = try TurboModuleInstaller.createWorkletsModuleProxyHolder()
|
|
15
|
+
return HybridIOSWorkletsModuleProxyHolder(holderBox: holderBox)
|
|
16
|
+
} catch {
|
|
17
|
+
throw RuntimeError.error(withMessage: String(describing: error))
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
func setupRuntime(workletsModuleHolder: Variant_NullType__any_HybridIOSWorkletsModuleProxyHolderSpec_?) throws {
|
|
22
|
+
if (!Thread.isMainThread) {
|
|
23
|
+
throw RuntimeError.error(withMessage: "setupRuntime() must be called from UI thread!")
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
guard let workletsModuleHolder else {
|
|
27
|
+
throw RuntimeError.error(withMessage: "setupRuntime() requires IOSWorkletsModuleProxyHolder on iOS.")
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let holder: HybridIOSWorkletsModuleProxyHolder
|
|
31
|
+
switch workletsModuleHolder {
|
|
32
|
+
case .first:
|
|
33
|
+
throw RuntimeError.error(withMessage: "setupRuntime() received null holder on iOS.")
|
|
34
|
+
case .second(let anyHolder):
|
|
35
|
+
guard let concreteHolder = anyHolder as? HybridIOSWorkletsModuleProxyHolder else {
|
|
36
|
+
throw RuntimeError.error(withMessage: "setupRuntime() received unexpected holder type.")
|
|
37
|
+
}
|
|
38
|
+
holder = concreteHolder
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
do {
|
|
42
|
+
_ = try TurboModuleInstaller.installNativeModuleProxyInUIRuntime(withHolder: holder.holderBox)
|
|
43
|
+
_ = try TurboModuleInstaller.setupEventInterceptor()
|
|
44
|
+
} catch {
|
|
45
|
+
let message = String(describing: error)
|
|
46
|
+
throw RuntimeError.error(withMessage: message)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
//
|
|
2
|
+
// HybridVIewHolder.swift
|
|
3
|
+
// ReactNativeList
|
|
4
|
+
//
|
|
5
|
+
// Created by Hanno Gödecke on 14.02.26.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
|
|
10
|
+
class HybridViewHolder : HybridViewHolderSpec {
|
|
11
|
+
var view: UIView = UIView()
|
|
12
|
+
|
|
13
|
+
typealias ViewType = UIView
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import NitroModules
|
|
2
|
+
import UIKit
|
|
3
|
+
|
|
4
|
+
class HybridNativeListLayout: HybridNativeListLayoutSpec {}
|
|
5
|
+
|
|
6
|
+
protocol NativeListLayoutProviding: AnyObject {
|
|
7
|
+
func makeCollectionViewLayout(owner: HybridUiListView) -> UICollectionViewLayout
|
|
8
|
+
func layoutSize(contentSize: CGSize) -> CGSize
|
|
9
|
+
func itemContentInset() -> UIEdgeInsets
|
|
10
|
+
func estimatedContentWidth(collectionViewWidth: CGFloat, viewWidth: CGFloat) -> CGFloat
|
|
11
|
+
func estimatedContentHeight(collectionViewHeight: CGFloat, viewHeight: CGFloat) -> CGFloat
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
class HybridNativeLinearListLayout: HybridNativeLinearListLayoutSpec, NativeListLayoutProviding {
|
|
15
|
+
private var topInset: CGFloat = 16
|
|
16
|
+
private var bottomInset: CGFloat = 16
|
|
17
|
+
private var itemSpacing: CGFloat = 12
|
|
18
|
+
private var itemHorizontalInset: CGFloat = 0
|
|
19
|
+
private var itemVerticalInset: CGFloat = 0
|
|
20
|
+
private var estimatedItemWidth: CGFloat?
|
|
21
|
+
private var estimatedItemHeight: CGFloat?
|
|
22
|
+
|
|
23
|
+
func dispose() {
|
|
24
|
+
topInset = 16
|
|
25
|
+
bottomInset = 16
|
|
26
|
+
itemSpacing = 12
|
|
27
|
+
itemHorizontalInset = 0
|
|
28
|
+
itemVerticalInset = 0
|
|
29
|
+
estimatedItemWidth = nil
|
|
30
|
+
estimatedItemHeight = nil
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
func setConfig(config: NativeLinearListLayoutConfig) throws {
|
|
34
|
+
topInset = CGFloat(config.topInset)
|
|
35
|
+
bottomInset = CGFloat(config.bottomInset)
|
|
36
|
+
itemSpacing = CGFloat(config.itemSpacing)
|
|
37
|
+
itemHorizontalInset = CGFloat(config.itemHorizontalInset)
|
|
38
|
+
itemVerticalInset = CGFloat(config.itemVerticalInset)
|
|
39
|
+
|
|
40
|
+
let estimatedItemSize = config.iosConfig?.estimatedItemSize
|
|
41
|
+
if let width = estimatedItemSize?.width {
|
|
42
|
+
estimatedItemWidth = CGFloat(width)
|
|
43
|
+
} else {
|
|
44
|
+
estimatedItemWidth = nil
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if let height = estimatedItemSize?.height {
|
|
48
|
+
estimatedItemHeight = CGFloat(height)
|
|
49
|
+
} else {
|
|
50
|
+
estimatedItemHeight = nil
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
func makeCollectionViewLayout(owner: HybridUiListView) -> UICollectionViewLayout {
|
|
55
|
+
let layout = UICollectionViewFlowLayout()
|
|
56
|
+
layout.scrollDirection = .vertical
|
|
57
|
+
layout.minimumLineSpacing = itemSpacing
|
|
58
|
+
layout.minimumInteritemSpacing = 0
|
|
59
|
+
layout.sectionInset = UIEdgeInsets(
|
|
60
|
+
top: topInset,
|
|
61
|
+
left: 0,
|
|
62
|
+
bottom: bottomInset,
|
|
63
|
+
right: 0
|
|
64
|
+
)
|
|
65
|
+
// FlowLayout owns the vertical offset bookkeeping; we only provide measured sizes.
|
|
66
|
+
layout.estimatedItemSize = .zero
|
|
67
|
+
return layout
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
func layoutSize(contentSize: CGSize) -> CGSize {
|
|
71
|
+
let width = ceil(contentSize.width + itemHorizontalInset * 2)
|
|
72
|
+
let height = ceil(contentSize.height + itemVerticalInset * 2)
|
|
73
|
+
return CGSize(width: width, height: height)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
func itemContentInset() -> UIEdgeInsets {
|
|
77
|
+
return UIEdgeInsets(
|
|
78
|
+
top: itemVerticalInset,
|
|
79
|
+
left: itemHorizontalInset,
|
|
80
|
+
bottom: itemVerticalInset,
|
|
81
|
+
right: itemHorizontalInset
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
func estimatedContentWidth(collectionViewWidth: CGFloat, viewWidth: CGFloat) -> CGFloat {
|
|
86
|
+
// FlowLayout may ask for sizes before a cell has rendered. A user-provided
|
|
87
|
+
// estimate is only used for that first pass; measured and explicit item sizes
|
|
88
|
+
// are resolved by HybridUiListView before this fallback is reached.
|
|
89
|
+
if let estimatedItemWidth, estimatedItemWidth.isFinite, estimatedItemWidth > 0 {
|
|
90
|
+
return estimatedItemWidth
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
let availableWidth = collectionViewWidth - itemHorizontalInset * 2
|
|
94
|
+
if availableWidth.isFinite && availableWidth > 0 {
|
|
95
|
+
return availableWidth
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
let fallbackWidth = viewWidth - itemHorizontalInset * 2
|
|
99
|
+
if fallbackWidth.isFinite && fallbackWidth > 0 {
|
|
100
|
+
return fallbackWidth
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return 1
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
func estimatedContentHeight(collectionViewHeight: CGFloat, viewHeight: CGFloat) -> CGFloat {
|
|
107
|
+
// Keep the built-in fallback finite so FlowLayout can place initial cells,
|
|
108
|
+
// then let real measurements replace it after cells bind their content.
|
|
109
|
+
if let estimatedItemHeight, estimatedItemHeight.isFinite, estimatedItemHeight > 0 {
|
|
110
|
+
return estimatedItemHeight
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if collectionViewHeight.isFinite && collectionViewHeight > 0 {
|
|
114
|
+
return collectionViewHeight / 2
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if viewHeight.isFinite && viewHeight > 0 {
|
|
118
|
+
return viewHeight / 2
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
let screenHeight = UIScreen.main.bounds.height
|
|
122
|
+
if screenHeight.isFinite && screenHeight > 0 {
|
|
123
|
+
return screenHeight / 2
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return 120
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//
|
|
2
|
+
// ErrorUtils.h
|
|
3
|
+
// ReactNativeList
|
|
4
|
+
//
|
|
5
|
+
// Created by Hanno Gödecke on 15.02.26.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#import <Foundation/Foundation.h>
|
|
9
|
+
|
|
10
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
11
|
+
|
|
12
|
+
static NSString *const kInstallerErrorDomain = @"ReactNativeList.HybridUiListTurboModuleInstaller";
|
|
13
|
+
|
|
14
|
+
inline void assignError(NSError *__autoreleasing _Nullable *error, NSString *message)
|
|
15
|
+
{
|
|
16
|
+
if (error == nil) {
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
*error = [NSError errorWithDomain:kInstallerErrorDomain
|
|
21
|
+
code:1
|
|
22
|
+
userInfo:@{
|
|
23
|
+
NSLocalizedDescriptionKey : message,
|
|
24
|
+
}];
|
|
25
|
+
}
|
|
26
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
class HybridIOSWorkletsModuleProxyHolder: HybridIOSWorkletsModuleProxyHolderSpec {
|
|
4
|
+
let holderBox: HybridWorkletsModuleProxyHolderBox
|
|
5
|
+
|
|
6
|
+
init(holderBox: HybridWorkletsModuleProxyHolderBox) {
|
|
7
|
+
self.holderBox = holderBox
|
|
8
|
+
super.init()
|
|
9
|
+
}
|
|
10
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//
|
|
2
|
+
// SurfaceHelper.h
|
|
3
|
+
// ReactNativeList
|
|
4
|
+
//
|
|
5
|
+
// Created by Hanno Gödecke on 15.02.26.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#import <Foundation/Foundation.h>
|
|
9
|
+
#import <React/RCTPrimitives.h>
|
|
10
|
+
#import <UIKit/UIKit.h>
|
|
11
|
+
|
|
12
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
13
|
+
|
|
14
|
+
@interface SurfaceHelper : NSObject
|
|
15
|
+
+ (nullable NSNumber *)createExternalSurface:(NSError * _Nullable * _Nullable)error;
|
|
16
|
+
+ (BOOL)releaseExternalSurface:(ReactTag)surfaceId error:(NSError * _Nullable * _Nullable)error;
|
|
17
|
+
+ (nullable UIView *)getViewByTag:(ReactTag)tag error:(NSError * _Nullable * _Nullable)error;
|
|
18
|
+
@end
|
|
19
|
+
|
|
20
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
//
|
|
2
|
+
// SurfaceHelper.m
|
|
3
|
+
// ReactNativeList
|
|
4
|
+
//
|
|
5
|
+
// Created by Hanno Gödecke on 15.02.26.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
#import "SurfaceHelper.h"
|
|
9
|
+
#import "SurfacePresenterRegistry.h"
|
|
10
|
+
#import "ErrorUtils.h"
|
|
11
|
+
|
|
12
|
+
#import <React/RCTBridge+Private.h>
|
|
13
|
+
#import <React/RCTBridge.h>
|
|
14
|
+
#import <React/RCTFabricSurface.h>
|
|
15
|
+
#import <React/RCTSurfacePresenterStub.h>
|
|
16
|
+
#import <React/RCTSurfacePresenter.h>
|
|
17
|
+
#import <React/RCTSurfaceProtocol.h>
|
|
18
|
+
|
|
19
|
+
#import <React/RCTComponentViewProtocol.h>
|
|
20
|
+
#import <React/RCTComponentViewRegistry.h>
|
|
21
|
+
#import <React/RCTMountingManager.h>
|
|
22
|
+
|
|
23
|
+
using namespace facebook;
|
|
24
|
+
using namespace facebook::react;
|
|
25
|
+
|
|
26
|
+
namespace {
|
|
27
|
+
static NSMutableDictionary<NSNumber *, id<RCTSurfaceProtocol>> *externalSurfaces()
|
|
28
|
+
{
|
|
29
|
+
static NSMutableDictionary<NSNumber *, id<RCTSurfaceProtocol>> *surfaces = nil;
|
|
30
|
+
static dispatch_once_t onceToken;
|
|
31
|
+
dispatch_once(&onceToken, ^{
|
|
32
|
+
surfaces = [NSMutableDictionary new];
|
|
33
|
+
});
|
|
34
|
+
return surfaces;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
inline RCTSurfacePresenter* _Nullable resolveSurfacePresenter(RCTBridge *bridge)
|
|
38
|
+
{
|
|
39
|
+
id<RCTSurfacePresenterStub> surfacePresenter =
|
|
40
|
+
(id<RCTSurfacePresenterStub>)[SurfacePresenterRegistry currentSurfacePresenter];
|
|
41
|
+
if (surfacePresenter != nil) {
|
|
42
|
+
return surfacePresenter;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return [bridge surfacePresenter];
|
|
46
|
+
}
|
|
47
|
+
} // namespace
|
|
48
|
+
|
|
49
|
+
@implementation SurfaceHelper
|
|
50
|
+
|
|
51
|
+
+ (nullable NSNumber *)createExternalSurface:(NSError *__autoreleasing _Nullable * _Nullable)error
|
|
52
|
+
{
|
|
53
|
+
@try {
|
|
54
|
+
if (![NSThread isMainThread]) {
|
|
55
|
+
assignError(error, @"createExternalSurface() must run on the main thread.");
|
|
56
|
+
return nil;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
RCTBridge *bridge = [RCTBridge currentBridge];
|
|
60
|
+
if (bridge == nil) {
|
|
61
|
+
assignError(error, @"Could not access RCTBridge.currentBridge.");
|
|
62
|
+
return nil;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
RCTSurfacePresenter *surfacePresenter = resolveSurfacePresenter(bridge);
|
|
66
|
+
if (surfacePresenter == nil) {
|
|
67
|
+
assignError(error, @"Could not access an active RCTSurfacePresenter.");
|
|
68
|
+
return nil;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
id<RCTSurfaceProtocol> surface = [surfacePresenter createFabricSurfaceForModuleName:@"" initialProperties:@{}];
|
|
72
|
+
if (surface == nil) {
|
|
73
|
+
assignError(error, @"Failed to create Fabric surface.");
|
|
74
|
+
return nil;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (![surface isKindOfClass:[RCTFabricSurface class]]) {
|
|
78
|
+
assignError(error, @"Expected a RCTFabricSurface instance.");
|
|
79
|
+
return nil;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
[surface start];
|
|
83
|
+
NSNumber *surfaceId = @(surface.rootTag);
|
|
84
|
+
externalSurfaces()[surfaceId] = surface;
|
|
85
|
+
NSLog(@"Created external surface %@", surfaceId);
|
|
86
|
+
return surfaceId;
|
|
87
|
+
} @catch (NSException *exception) {
|
|
88
|
+
assignError(error, [NSString stringWithFormat:@"Surface creation failed with NSException: %@", exception.reason]);
|
|
89
|
+
return nil;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
+ (BOOL)releaseExternalSurface:(ReactTag)surfaceId error:(NSError * _Nullable __autoreleasing * _Nullable)error {
|
|
94
|
+
@try {
|
|
95
|
+
if (![NSThread isMainThread]) {
|
|
96
|
+
assignError(error, @"releaseExternalSurface() must run on the main thread.");
|
|
97
|
+
return NO;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
NSNumber *surfaceKey = @(surfaceId);
|
|
101
|
+
id<RCTSurfaceProtocol> surface = externalSurfaces()[surfaceKey];
|
|
102
|
+
if (surface == nil) {
|
|
103
|
+
return YES;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
[surface stop];
|
|
107
|
+
[externalSurfaces() removeObjectForKey:surfaceKey];
|
|
108
|
+
return YES;
|
|
109
|
+
} @catch (NSException *exception) {
|
|
110
|
+
assignError(error, [NSString stringWithFormat:@"Surface release failed with NSException: %@", exception.reason]);
|
|
111
|
+
return NO;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
+ (nullable UIView *)getViewByTag:(ReactTag)tag error:(NSError * _Nullable __autoreleasing * _Nullable)error {
|
|
116
|
+
if (![NSThread isMainThread]) {
|
|
117
|
+
assignError(error, @"getViewByTag() must run on the main thread.");
|
|
118
|
+
return nil;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
RCTBridge *bridge = [RCTBridge currentBridge];
|
|
122
|
+
if (bridge == nil) {
|
|
123
|
+
assignError(error, @"Could not access RCTBridge.currentBridge.");
|
|
124
|
+
return nil;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
RCTSurfacePresenter *surfacePresenter = resolveSurfacePresenter(bridge);
|
|
128
|
+
if (surfacePresenter == nil) {
|
|
129
|
+
assignError(error, @"Could not access an active RCTSurfacePresenter.");
|
|
130
|
+
return nil;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
RCTComponentViewRegistry *componentViewRegistry = surfacePresenter.mountingManager.componentViewRegistry;
|
|
134
|
+
Tag intTag = static_cast<Tag>(tag);
|
|
135
|
+
UIView<RCTComponentViewProtocol> *componentView = [componentViewRegistry findComponentViewWithTag:intTag];
|
|
136
|
+
if (componentView == nil) {
|
|
137
|
+
assignError(error, [NSString stringWithFormat:@"Could not resolve view with tag %d on surface %@", intTag, @-1]);
|
|
138
|
+
return nil;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return componentView;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
@end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
#import <Foundation/Foundation.h>
|
|
2
|
+
|
|
3
|
+
#import <React/RCTBridgeModule.h>
|
|
4
|
+
|
|
5
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A module whos purpose it is to receive the surface presenter.
|
|
9
|
+
* (RN injects this during module instantiation).
|
|
10
|
+
*/
|
|
11
|
+
@interface SurfacePresenterRegistry : NSObject <RCTBridgeModule>
|
|
12
|
+
|
|
13
|
+
+ (nullable id)currentSurfacePresenter;
|
|
14
|
+
|
|
15
|
+
@end
|
|
16
|
+
|
|
17
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#import "SurfacePresenterRegistry.h"
|
|
2
|
+
|
|
3
|
+
#import <React/RCTSurfacePresenterStub.h>
|
|
4
|
+
|
|
5
|
+
@protocol RCTTurboModule;
|
|
6
|
+
|
|
7
|
+
static __weak id<RCTSurfacePresenterStub> sCurrentSurfacePresenter = nil;
|
|
8
|
+
|
|
9
|
+
@interface SurfacePresenterRegistry () <RCTTurboModule>
|
|
10
|
+
@end
|
|
11
|
+
|
|
12
|
+
@implementation SurfacePresenterRegistry
|
|
13
|
+
|
|
14
|
+
RCT_EXPORT_MODULE(HybridUiListSurfacePresenterRegistry);
|
|
15
|
+
|
|
16
|
+
+ (BOOL)requiresMainQueueSetup
|
|
17
|
+
{
|
|
18
|
+
return NO;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
+ (nullable id)currentSurfacePresenter
|
|
22
|
+
{
|
|
23
|
+
return sCurrentSurfacePresenter;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
- (void)setSurfacePresenter:(id<RCTSurfacePresenterStub>)surfacePresenter
|
|
27
|
+
{
|
|
28
|
+
sCurrentSurfacePresenter = surfacePresenter;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
@end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#import <Foundation/Foundation.h>
|
|
2
|
+
|
|
3
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@interface HybridWorkletsModuleProxyHolderBox : NSObject
|
|
7
|
+
@end
|
|
8
|
+
|
|
9
|
+
@interface TurboModuleInstaller : NSObject
|
|
10
|
+
|
|
11
|
+
+ (nullable HybridWorkletsModuleProxyHolderBox *)createWorkletsModuleProxyHolder:(NSError * _Nullable * _Nullable)error;
|
|
12
|
+
+ (BOOL)installNativeModuleProxyInUIRuntimeWithHolder:(HybridWorkletsModuleProxyHolderBox *)holder
|
|
13
|
+
error:(NSError * _Nullable * _Nullable)error;
|
|
14
|
+
+ (BOOL)setupEventInterceptor:(NSError * _Nullable * _Nullable)error;
|
|
15
|
+
|
|
16
|
+
@end
|
|
17
|
+
|
|
18
|
+
NS_ASSUME_NONNULL_END
|