@ionic/portals-react-native 0.0.6 → 0.2.0-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 +11 -159
- package/ReactNativePortals.podspec +2 -1
- package/android/build.gradle +1 -1
- package/android/src/main/java/io/ionic/portals/reactnative/PortalView.kt +132 -0
- package/android/src/main/java/io/ionic/portals/reactnative/ReactNativeLiveUpdatesModule.kt +10 -28
- package/android/src/main/java/io/ionic/portals/reactnative/ReactNativePortalManager.kt +149 -0
- package/android/src/main/java/io/ionic/portals/reactnative/ReactNativePortalsModule.kt +76 -215
- package/android/src/main/java/io/ionic/portals/reactnative/ReactNativePortalsPackage.kt +0 -1
- package/android/src/main/java/io/ionic/portals/reactnative/ReactNativePortalsPubSub.kt +45 -0
- package/ios/LiveUpdate+Dict.swift +30 -0
- package/ios/LiveUpdateManager+Async.swift +69 -0
- package/ios/LiveUpdateManagerError+Dict.swift +19 -0
- package/ios/Podfile +2 -1
- package/ios/Podfile.lock +13 -12
- package/ios/Portal+Dict.swift +35 -0
- package/ios/PortalManager.m +10 -4
- package/ios/PortalView.m +2 -3
- package/ios/PortalView.swift +67 -0
- package/ios/PortalsConfig.swift +92 -0
- package/ios/PortalsPubSub.m +3 -3
- package/ios/PortalsPubSub.swift +47 -0
- package/ios/PortalsReactNative.swift +104 -0
- package/ios/ReactNativePortals.xcodeproj/project.pbxproj +32 -8
- package/lib/commonjs/index.js +108 -13
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/index.js +104 -12
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/index.d.ts +106 -3
- package/package.json +3 -1
- package/src/index.ts +127 -13
- package/ios/LiveUpdatesManager.m +0 -16
- package/ios/ReactNativePortals.swift +0 -264
|
@@ -1,262 +1,123 @@
|
|
|
1
1
|
package io.ionic.portals.reactnative
|
|
2
2
|
|
|
3
|
-
import android.util.Log
|
|
4
|
-
import android.view.Choreographer
|
|
5
|
-
import android.view.View
|
|
6
|
-
import android.view.ViewGroup
|
|
7
|
-
import android.widget.FrameLayout
|
|
8
|
-
import androidx.fragment.app.FragmentActivity
|
|
9
3
|
import com.facebook.react.bridge.*
|
|
10
|
-
import
|
|
11
|
-
import com.facebook.react.uimanager.ThemedReactContext
|
|
12
|
-
import com.facebook.react.uimanager.ViewGroupManager
|
|
13
|
-
import com.facebook.react.uimanager.annotations.ReactProp
|
|
14
|
-
import com.getcapacitor.JSObject
|
|
15
|
-
import com.getcapacitor.Plugin
|
|
16
|
-
import io.ionic.liveupdates.LiveUpdate
|
|
17
|
-
import io.ionic.portals.*
|
|
18
|
-
import org.json.JSONArray
|
|
19
|
-
import org.json.JSONException
|
|
20
|
-
import org.json.JSONObject
|
|
4
|
+
import io.ionic.portals.Portal
|
|
21
5
|
|
|
22
6
|
internal class PortalManagerModule(reactContext: ReactApplicationContext) :
|
|
23
7
|
ReactContextBaseJavaModule(reactContext) {
|
|
24
|
-
override fun getName() = "
|
|
8
|
+
override fun getName() = "IONPortalsReactNative"
|
|
25
9
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
PortalManager.register(key)
|
|
10
|
+
init {
|
|
11
|
+
RNPortalManager.registerFromConfigIfAvailable(reactContext)
|
|
29
12
|
}
|
|
30
13
|
|
|
31
14
|
@ReactMethod
|
|
32
|
-
fun
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
map.getString("startDir")
|
|
37
|
-
?.let(portalBuilder::setStartDir)
|
|
38
|
-
|
|
39
|
-
map.getMap("initialContext")
|
|
40
|
-
?.toHashMap()
|
|
41
|
-
?.let(portalBuilder::setInitialContext)
|
|
15
|
+
fun register(key: String, promise: Promise) {
|
|
16
|
+
RNPortalManager.register(key)
|
|
17
|
+
promise.resolve(null)
|
|
18
|
+
}
|
|
42
19
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
20
|
+
@ReactMethod
|
|
21
|
+
fun addPortal(map: ReadableMap, promise: Promise) {
|
|
22
|
+
val portal = RNPortalManager.addPortal(map)
|
|
23
|
+
if (portal == null) {
|
|
24
|
+
promise.reject(null, "Invalid Portal configuration.")
|
|
25
|
+
} else {
|
|
26
|
+
promise.resolve(portal.toReadableMap())
|
|
27
|
+
}
|
|
28
|
+
}
|
|
51
29
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
val channel = readableMap.getString("channel") ?: return@let null
|
|
56
|
-
val syncOnAdd = readableMap.getBoolean("syncOnAdd")
|
|
57
|
-
Pair(LiveUpdate(appId, channel), syncOnAdd)
|
|
58
|
-
}
|
|
59
|
-
?.let { pair ->
|
|
60
|
-
portalBuilder.setLiveUpdateConfig(
|
|
61
|
-
context = reactApplicationContext,
|
|
62
|
-
liveUpdateConfig = pair.first,
|
|
63
|
-
updateOnAppLoad = pair.second
|
|
64
|
-
)
|
|
65
|
-
}
|
|
30
|
+
@ReactMethod
|
|
31
|
+
fun addPortals(array: ReadableArray, promise: Promise) {
|
|
32
|
+
val portals = WritableNativeArray()
|
|
66
33
|
|
|
67
|
-
|
|
68
|
-
.
|
|
69
|
-
.
|
|
34
|
+
for (i in 0 until array.size()) {
|
|
35
|
+
val map = array.getMap(i) ?: continue
|
|
36
|
+
val portal = RNPortalManager.addPortal(map) ?: continue
|
|
37
|
+
portals.pushMap(portal.toReadableMap())
|
|
38
|
+
}
|
|
70
39
|
|
|
71
|
-
|
|
40
|
+
promise.resolve(portals)
|
|
72
41
|
}
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
internal class PortalsPubSubModule(reactContext: ReactApplicationContext) :
|
|
76
|
-
ReactContextBaseJavaModule(reactContext) {
|
|
77
|
-
override fun getName() = "IONPortalPubSub"
|
|
78
42
|
|
|
79
43
|
@ReactMethod
|
|
80
|
-
fun
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
44
|
+
fun getPortal(name: String, promise: Promise) {
|
|
45
|
+
try {
|
|
46
|
+
val portal = RNPortalManager.getPortal(name)
|
|
47
|
+
promise.resolve(portal.toReadableMap())
|
|
48
|
+
} catch (e: IllegalStateException) {
|
|
49
|
+
promise.reject(null, "Portal named $name not registered.")
|
|
85
50
|
}
|
|
86
|
-
|
|
87
|
-
promise.resolve(reference)
|
|
88
51
|
}
|
|
89
52
|
|
|
90
53
|
@ReactMethod
|
|
91
|
-
fun
|
|
92
|
-
|
|
54
|
+
fun enableSecureLiveUpdates(keyPath: String, promise: Promise) {
|
|
55
|
+
RNPortalManager.enableSecureLiveUpdates(keyPath)
|
|
56
|
+
promise.resolve(null)
|
|
93
57
|
}
|
|
94
58
|
|
|
95
59
|
@ReactMethod
|
|
96
|
-
fun
|
|
97
|
-
|
|
60
|
+
fun syncOne(appId: String, promise: Promise) {
|
|
61
|
+
LiveUpdatesModule.syncOne(appId, reactApplicationContext, promise)
|
|
98
62
|
}
|
|
99
63
|
|
|
100
|
-
// These are required to be an EventEmitter in javascript
|
|
101
|
-
|
|
102
64
|
@ReactMethod
|
|
103
|
-
fun
|
|
65
|
+
fun syncSome(appIds: ReadableArray, promise: Promise) {
|
|
66
|
+
LiveUpdatesModule.syncSome(appIds, reactApplicationContext, promise)
|
|
104
67
|
}
|
|
105
68
|
|
|
106
69
|
@ReactMethod
|
|
107
|
-
fun
|
|
70
|
+
fun syncAll(promise: Promise) {
|
|
71
|
+
LiveUpdatesModule.syncAll(reactApplicationContext, promise)
|
|
108
72
|
}
|
|
109
73
|
}
|
|
110
74
|
|
|
111
|
-
|
|
112
|
-
keys
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
} catch (_: JSONException) {
|
|
75
|
+
fun Map<*, *>.toReadableMap(): ReadableMap {
|
|
76
|
+
return keys.fold(WritableNativeMap()) { map, key ->
|
|
77
|
+
val key = key as String
|
|
78
|
+
when (val value = get(key)) {
|
|
79
|
+
is String -> map.putString(key, value)
|
|
80
|
+
is Boolean -> map.putBoolean(key, value)
|
|
81
|
+
is Int -> map.putInt(key, value)
|
|
82
|
+
is Double -> map.putDouble(key, value)
|
|
83
|
+
is Map<*, *> -> map.putMap(key, value.toReadableMap())
|
|
84
|
+
is List<*> -> map.putArray(key, value.toReadableArray())
|
|
85
|
+
null -> map.putNull(key)
|
|
86
|
+
else -> map.putString(key, value.toString())
|
|
125
87
|
}
|
|
126
|
-
|
|
127
88
|
return@fold map
|
|
128
89
|
}
|
|
90
|
+
}
|
|
129
91
|
|
|
130
|
-
|
|
131
|
-
(0 until
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
else -> array.pushString(value.toString())
|
|
142
|
-
}
|
|
143
|
-
} catch (_: JSONException) {
|
|
92
|
+
fun List<*>.toReadableArray(): ReadableArray {
|
|
93
|
+
return (0 until size).fold(WritableNativeArray()) { array, index ->
|
|
94
|
+
when (val value = get(index)) {
|
|
95
|
+
is String -> array.pushString(value)
|
|
96
|
+
is Boolean -> array.pushBoolean(value)
|
|
97
|
+
is Int -> array.pushInt(value)
|
|
98
|
+
is Double -> array.pushDouble(value)
|
|
99
|
+
is Map<*, *> -> array.pushMap(value.toReadableMap())
|
|
100
|
+
is List<*> -> array.pushArray(value.toReadableArray())
|
|
101
|
+
null -> array.pushNull()
|
|
102
|
+
else -> array.pushString(value.toString())
|
|
144
103
|
}
|
|
145
104
|
|
|
146
105
|
return@fold array
|
|
147
106
|
}
|
|
107
|
+
}
|
|
148
108
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
)
|
|
156
|
-
|
|
157
|
-
internal class PortalViewManager(private val context: ReactApplicationContext) :
|
|
158
|
-
ViewGroupManager<FrameLayout>() {
|
|
159
|
-
private val createId = 1
|
|
160
|
-
private val fragmentMap = mutableMapOf<Int, PortalViewState>()
|
|
161
|
-
|
|
162
|
-
@ReactProp(name = "name")
|
|
163
|
-
fun setPortal(viewGroup: ViewGroup, portalName: String) {
|
|
164
|
-
when (val viewState = fragmentMap[viewGroup.id]) {
|
|
165
|
-
null -> fragmentMap[viewGroup.id] = PortalViewState(
|
|
166
|
-
fragment = null,
|
|
167
|
-
portal = PortalManager.getPortal(portalName),
|
|
168
|
-
initialContext = null
|
|
169
|
-
)
|
|
170
|
-
else -> viewState.portal = PortalManager.getPortal(portalName)
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
@ReactProp(name = "initialContext")
|
|
175
|
-
fun setInitialContext(viewGroup: ViewGroup, initialContext: ReadableMap) {
|
|
176
|
-
when (val viewState = fragmentMap[viewGroup.id]) {
|
|
177
|
-
null -> fragmentMap[viewGroup.id] = PortalViewState(
|
|
178
|
-
fragment = null,
|
|
179
|
-
portal = null,
|
|
180
|
-
initialContext = initialContext.toHashMap()
|
|
181
|
-
)
|
|
182
|
-
else -> viewState.initialContext = initialContext.toHashMap()
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
override fun getName() = "AndroidPortalView"
|
|
187
|
-
|
|
188
|
-
override fun createViewInstance(reactContext: ThemedReactContext): FrameLayout {
|
|
189
|
-
return FrameLayout(reactContext)
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
override fun getCommandsMap(): MutableMap<String, Int>? {
|
|
193
|
-
return mutableMapOf("create" to createId)
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
override fun receiveCommand(root: FrameLayout, commandId: String?, args: ReadableArray?) {
|
|
197
|
-
super.receiveCommand(root, commandId, args)
|
|
198
|
-
val viewId = args?.getInt(0) ?: return
|
|
199
|
-
|
|
200
|
-
@Suppress("NAME_SHADOWING")
|
|
201
|
-
val commandId = commandId?.toIntOrNull() ?: return
|
|
202
|
-
|
|
203
|
-
when (commandId) {
|
|
204
|
-
createId -> createFragment(root, viewId)
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
private fun createFragment(root: FrameLayout, viewId: Int) {
|
|
209
|
-
val viewState = fragmentMap[viewId] ?: return
|
|
210
|
-
val portal = viewState.portal ?: return
|
|
211
|
-
|
|
212
|
-
val parentView = root.findViewById<ViewGroup>(viewId)
|
|
213
|
-
setupLayout(parentView)
|
|
214
|
-
|
|
215
|
-
val portalFragment = PortalFragment(portal)
|
|
216
|
-
viewState.initialContext?.let(portalFragment::setInitialContext)
|
|
217
|
-
|
|
218
|
-
viewState.fragment = portalFragment
|
|
219
|
-
|
|
220
|
-
val fragmentActivity = context.currentActivity as? FragmentActivity ?: return
|
|
221
|
-
fragmentActivity.supportFragmentManager
|
|
222
|
-
.beginTransaction()
|
|
223
|
-
.replace(viewId, portalFragment, "$viewId")
|
|
224
|
-
.commit()
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
override fun onDropViewInstance(view: FrameLayout) {
|
|
228
|
-
super.onDropViewInstance(view)
|
|
229
|
-
val viewState = fragmentMap[view.id] ?: return
|
|
230
|
-
|
|
231
|
-
try {
|
|
232
|
-
viewState.fragment
|
|
233
|
-
?.parentFragmentManager
|
|
234
|
-
?.beginTransaction()
|
|
235
|
-
?.remove(viewState.fragment!!)
|
|
236
|
-
?.commit()
|
|
237
|
-
} catch (e: IllegalStateException) {
|
|
238
|
-
Log.i("io.ionic.portals.rn", "Parent fragment manager not available")
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
fragmentMap.remove(view.id)
|
|
242
|
-
}
|
|
109
|
+
@Suppress("UNCHECKED_CAST")
|
|
110
|
+
fun Portal.toReadableMap(): ReadableMap {
|
|
111
|
+
val map = WritableNativeMap()
|
|
112
|
+
map.putString("name", name)
|
|
113
|
+
map.putString("startDir", startDir)
|
|
114
|
+
RNPortalManager.indexMap[name]?.let { map.putString("index", it) }
|
|
243
115
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
override fun doFrame(frameTimeNanos: Long) {
|
|
247
|
-
layoutPortal(view)
|
|
248
|
-
view.viewTreeObserver.dispatchOnGlobalLayout()
|
|
249
|
-
Choreographer.getInstance().postFrameCallback(this)
|
|
250
|
-
}
|
|
251
|
-
})
|
|
116
|
+
initialContext?.let {
|
|
117
|
+
if (it is Map<*, *>) map.putMap("initialContext", it.toReadableMap())
|
|
252
118
|
}
|
|
253
119
|
|
|
254
|
-
|
|
255
|
-
view.measure(
|
|
256
|
-
View.MeasureSpec.makeMeasureSpec(view.measuredWidth, View.MeasureSpec.EXACTLY),
|
|
257
|
-
View.MeasureSpec.makeMeasureSpec(view.measuredHeight, View.MeasureSpec.EXACTLY)
|
|
258
|
-
)
|
|
120
|
+
liveUpdateConfig?.let { map.putMap("liveUpdate", it.toReadableMap()) }
|
|
259
121
|
|
|
260
|
-
|
|
261
|
-
}
|
|
122
|
+
return map
|
|
262
123
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
package io.ionic.portals.reactnative
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.*
|
|
4
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
5
|
+
import com.getcapacitor.JSObject
|
|
6
|
+
import io.ionic.portals.PortalsPlugin
|
|
7
|
+
import org.json.JSONObject
|
|
8
|
+
|
|
9
|
+
internal class PortalsPubSubModule(reactContext: ReactApplicationContext) :
|
|
10
|
+
ReactContextBaseJavaModule(reactContext) {
|
|
11
|
+
override fun getName() = "IONPortalPubSub"
|
|
12
|
+
|
|
13
|
+
@ReactMethod
|
|
14
|
+
fun subscribe(topic: String, promise: Promise) {
|
|
15
|
+
val reference = PortalsPlugin.subscribe(topic) { result ->
|
|
16
|
+
reactApplicationContext
|
|
17
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
18
|
+
.emit("PortalsSubscription", result.toJSObject().toReactMap())
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
promise.resolve(reference)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@ReactMethod
|
|
25
|
+
fun publish(topic: String, data: ReadableMap) {
|
|
26
|
+
PortalsPlugin.publish(topic, data.toJSObject())
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@ReactMethod
|
|
30
|
+
fun unsubscribe(topic: String, reference: Int) {
|
|
31
|
+
PortalsPlugin.unsubscribe(topic, reference)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// These are required to be an EventEmitter in javascript
|
|
35
|
+
|
|
36
|
+
@ReactMethod
|
|
37
|
+
fun addListener(eventName: String) {
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@ReactMethod
|
|
41
|
+
fun removeListeners(count: Int) {
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
private fun ReadableMap.toJSObject(): JSObject = JSObject.fromJSONObject(JSONObject(toHashMap()))
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//
|
|
2
|
+
// LiveUpdate+Dict.swift
|
|
3
|
+
// ReactNativePortals
|
|
4
|
+
//
|
|
5
|
+
// Created by Steven Sherry on 10/5/22.
|
|
6
|
+
// Copyright © 2022 Ionic. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
import IonicLiveUpdates
|
|
10
|
+
|
|
11
|
+
extension LiveUpdate {
|
|
12
|
+
init?(_ dict: [String: Any]) {
|
|
13
|
+
guard let appId = dict["appId"] as? String,
|
|
14
|
+
let channel = dict["channel"] as? String,
|
|
15
|
+
let syncOnAdd = dict["syncOnAdd"] as? Bool
|
|
16
|
+
else { return nil }
|
|
17
|
+
|
|
18
|
+
self.init(appId: appId, channel: channel, syncOnAdd: syncOnAdd)
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
extension LiveUpdate {
|
|
23
|
+
var dict: [String: Any] {
|
|
24
|
+
return [
|
|
25
|
+
"appId": appId,
|
|
26
|
+
"channel": channel,
|
|
27
|
+
"syncOnAdd": syncOnAdd
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
//
|
|
2
|
+
// LiveUpdateManager+Async.swift
|
|
3
|
+
// ReactNativePortals
|
|
4
|
+
//
|
|
5
|
+
// Created by Steven Sherry on 10/5/22.
|
|
6
|
+
// Copyright © 2022 Ionic. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
import IonicLiveUpdates
|
|
10
|
+
|
|
11
|
+
struct SyncResults {
|
|
12
|
+
var liveUpdates: [LiveUpdate]
|
|
13
|
+
var errors: [LiveUpdateManager.Error]
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
extension SyncResults {
|
|
17
|
+
var dict: [String: Any] {
|
|
18
|
+
return [
|
|
19
|
+
"liveUpdates": liveUpdates.map(\.dict),
|
|
20
|
+
"errors": errors.map(\.dict)
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
extension LiveUpdateManager {
|
|
26
|
+
func syncSome(_ appIds: [String]) async -> SyncResults {
|
|
27
|
+
await _syncSome(appIds).syncResults
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
private func _syncSome(_ appIds: [String]) -> AsyncStream<Result<LiveUpdate, LiveUpdateManager.Error>> {
|
|
31
|
+
AsyncStream { continuation in
|
|
32
|
+
sync(appIds: appIds, isParallel: true) {
|
|
33
|
+
continuation.finish()
|
|
34
|
+
} appComplete: { result in
|
|
35
|
+
continuation.yield(result)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
func syncAll() async -> SyncResults {
|
|
41
|
+
await _syncAll().syncResults
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
private func _syncAll() -> AsyncStream<Result<LiveUpdate, LiveUpdateManager.Error>> {
|
|
46
|
+
AsyncStream { continuation in
|
|
47
|
+
sync(isParallel: true) {
|
|
48
|
+
continuation.finish()
|
|
49
|
+
} appComplete: { result in
|
|
50
|
+
continuation.yield(result)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
extension AsyncStream where Element == Result<LiveUpdate, LiveUpdateManager.Error> {
|
|
57
|
+
var syncResults: SyncResults {
|
|
58
|
+
get async {
|
|
59
|
+
await reduce(into: SyncResults(liveUpdates: [], errors: [])) { acc, next in
|
|
60
|
+
switch next {
|
|
61
|
+
case .success(let liveUpdate):
|
|
62
|
+
acc.liveUpdates.append(liveUpdate)
|
|
63
|
+
case .failure(let error):
|
|
64
|
+
acc.errors.append(error)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//
|
|
2
|
+
// LiveUpdateManagerError+Dict.swift
|
|
3
|
+
// ReactNativePortals
|
|
4
|
+
//
|
|
5
|
+
// Created by Steven Sherry on 10/5/22.
|
|
6
|
+
// Copyright © 2022 Ionic. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
import IonicLiveUpdates
|
|
10
|
+
|
|
11
|
+
extension LiveUpdateManager.Error {
|
|
12
|
+
var dict: [String: Any] {
|
|
13
|
+
return [
|
|
14
|
+
"appId": appId,
|
|
15
|
+
"failStep": failStep.rawValue.uppercased(),
|
|
16
|
+
"message": localizedDescription
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
}
|
package/ios/Podfile
CHANGED
package/ios/Podfile.lock
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
PODS:
|
|
2
2
|
- boost-for-react-native (1.63.0)
|
|
3
|
-
- Capacitor (3.
|
|
3
|
+
- Capacitor (3.7.0):
|
|
4
4
|
- CapacitorCordova
|
|
5
|
-
- CapacitorCordova (3.
|
|
5
|
+
- CapacitorCordova (3.7.0)
|
|
6
6
|
- DoubleConversion (1.1.6)
|
|
7
7
|
- FBLazyVector (0.63.4)
|
|
8
8
|
- FBReactNativeSpec (0.63.4):
|
|
@@ -22,10 +22,10 @@ PODS:
|
|
|
22
22
|
- DoubleConversion
|
|
23
23
|
- glog
|
|
24
24
|
- glog (0.3.5)
|
|
25
|
-
- IonicLiveUpdates (0.
|
|
26
|
-
- IonicPortals (0.6.
|
|
27
|
-
- Capacitor (~> 3.
|
|
28
|
-
- IonicLiveUpdates (
|
|
25
|
+
- IonicLiveUpdates (0.2.0)
|
|
26
|
+
- IonicPortals (0.6.4):
|
|
27
|
+
- Capacitor (~> 3.7)
|
|
28
|
+
- IonicLiveUpdates (< 0.3.0, >= 0.1.2)
|
|
29
29
|
- RCTRequired (0.63.4)
|
|
30
30
|
- RCTTypeSafety (0.63.4):
|
|
31
31
|
- FBLazyVector (= 0.63.4)
|
|
@@ -260,7 +260,8 @@ DEPENDENCIES:
|
|
|
260
260
|
- FBReactNativeSpec (from `../node_modules/react-native/Libraries/FBReactNativeSpec`)
|
|
261
261
|
- Folly (from `../node_modules/react-native/third-party-podspecs/Folly.podspec`)
|
|
262
262
|
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
|
|
263
|
-
-
|
|
263
|
+
- IonicLiveUpdates (~> 0.2.0)
|
|
264
|
+
- IonicPortals (~> 0.6.4)
|
|
264
265
|
- RCTRequired (from `../node_modules/react-native/Libraries/RCTRequired`)
|
|
265
266
|
- RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`)
|
|
266
267
|
- React (from `../node_modules/react-native/`)
|
|
@@ -349,15 +350,15 @@ EXTERNAL SOURCES:
|
|
|
349
350
|
|
|
350
351
|
SPEC CHECKSUMS:
|
|
351
352
|
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
|
|
352
|
-
Capacitor:
|
|
353
|
-
CapacitorCordova:
|
|
353
|
+
Capacitor: 747a1e47077e8f82abf2209867c440d7366ad68c
|
|
354
|
+
CapacitorCordova: e6b42a8e8d5986c1eb8f02ac0be205fafc32ac33
|
|
354
355
|
DoubleConversion: cde416483dac037923206447da6e1454df403714
|
|
355
356
|
FBLazyVector: 3bb422f41b18121b71783a905c10e58606f7dc3e
|
|
356
357
|
FBReactNativeSpec: f2c97f2529dd79c083355182cc158c9f98f4bd6e
|
|
357
358
|
Folly: b73c3869541e86821df3c387eb0af5f65addfab4
|
|
358
359
|
glog: 40a13f7840415b9a77023fbcae0f1e6f43192af3
|
|
359
|
-
IonicLiveUpdates:
|
|
360
|
-
IonicPortals:
|
|
360
|
+
IonicLiveUpdates: e9cfcb6cbcf67d7b171eae417fa2802cc5826d72
|
|
361
|
+
IonicPortals: 50634da3bd7a3cf9127bbad5f21fd23afde4f0ff
|
|
361
362
|
RCTRequired: 082f10cd3f905d6c124597fd1c14f6f2655ff65e
|
|
362
363
|
RCTTypeSafety: 8c9c544ecbf20337d069e4ae7fd9a377aadf504b
|
|
363
364
|
React: b0a957a2c44da4113b0c4c9853d8387f8e64e615
|
|
@@ -380,6 +381,6 @@ SPEC CHECKSUMS:
|
|
|
380
381
|
ReactCommon: 73d79c7039f473b76db6ff7c6b159c478acbbb3b
|
|
381
382
|
Yoga: 4bd86afe9883422a7c4028c00e34790f560923d6
|
|
382
383
|
|
|
383
|
-
PODFILE CHECKSUM:
|
|
384
|
+
PODFILE CHECKSUM: 9dce8640a99e055a2e7fad56d00e49829114eae1
|
|
384
385
|
|
|
385
386
|
COCOAPODS: 1.11.2
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Portal+Dict.swift
|
|
3
|
+
// ReactNativePortals
|
|
4
|
+
//
|
|
5
|
+
// Created by Steven Sherry on 10/5/22.
|
|
6
|
+
// Copyright © 2022 Ionic. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
import Capacitor
|
|
10
|
+
import IonicLiveUpdates
|
|
11
|
+
import IonicPortals
|
|
12
|
+
|
|
13
|
+
extension Portal {
|
|
14
|
+
init?(_ dict: [String: Any], _ liveUpdateManager: LiveUpdateManager) {
|
|
15
|
+
guard let name = dict["name"] as? String else { return nil }
|
|
16
|
+
self.init(
|
|
17
|
+
name: name,
|
|
18
|
+
startDir: dict["startDir"] as? String,
|
|
19
|
+
index: dict["index"] as? String ?? "index.html",
|
|
20
|
+
initialContext: JSTypes.coerceDictionaryToJSObject(dict["initialContext"] as? [String: Any]) ?? [:],
|
|
21
|
+
liveUpdateManager: liveUpdateManager,
|
|
22
|
+
liveUpdateConfig: (dict["liveUpdate"] as? [String: Any]).flatMap(LiveUpdate.init)
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
var dict: [String: Any] {
|
|
27
|
+
return [
|
|
28
|
+
"name": name,
|
|
29
|
+
"startDir": startDir,
|
|
30
|
+
"index": index,
|
|
31
|
+
"initialContext": initialContext,
|
|
32
|
+
"liveUpdateConfig": liveUpdateConfig?.dict as Any
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
}
|
package/ios/PortalManager.m
CHANGED
|
@@ -3,12 +3,18 @@
|
|
|
3
3
|
// ReactNativePortals
|
|
4
4
|
//
|
|
5
5
|
// Created by Steven Sherry on 4/1/22.
|
|
6
|
-
// Copyright © 2022
|
|
6
|
+
// Copyright © 2022 Ionic. All rights reserved.
|
|
7
7
|
//
|
|
8
8
|
|
|
9
9
|
#import <React/RCTBridgeModule.h>
|
|
10
10
|
|
|
11
|
-
@interface RCT_EXTERN_MODULE(
|
|
12
|
-
RCT_EXTERN_METHOD(register: (NSString *) key)
|
|
13
|
-
RCT_EXTERN_METHOD(
|
|
11
|
+
@interface RCT_EXTERN_MODULE(IONPortalsReactNative, NSObject)
|
|
12
|
+
RCT_EXTERN_METHOD(register: (NSString *) key resolver: (RCTPromiseResolveBlock) resolver rejector: (RCTPromiseRejectBlock) rejector)
|
|
13
|
+
RCT_EXTERN_METHOD(enableSecureLiveUpdates: (NSString *) publicKeyPath resolver: (RCTPromiseResolveBlock) resolver rejector: (RCTPromiseRejectBlock) rejector)
|
|
14
|
+
RCT_EXTERN_METHOD(addPortal: (NSDictionary) portal resolver: (RCTPromiseResolveBlock) resolver rejector: (RCTPromiseRejectBlock) rejector)
|
|
15
|
+
RCT_EXTERN_METHOD(addPortals: (NSArray) portals resolver: (RCTPromiseResolveBlock) resolver rejector: (RCTPromiseRejectBlock) rejector)
|
|
16
|
+
RCT_EXTERN_METHOD(getPortal: (NSString *) name resolver: (RCTPromiseResolveBlock) resolver rejector: (RCTPromiseRejectBlock) rejector)
|
|
17
|
+
RCT_EXTERN_METHOD(syncOne: (NSString *) appId resolver: (RCTPromiseResolveBlock) resolver rejector: (RCTPromiseRejectBlock) rejector)
|
|
18
|
+
RCT_EXTERN_METHOD(syncSome: (NSArray) appIds resolver: (RCTPromiseResolveBlock) resolver rejector: (RCTPromiseRejectBlock) rejector)
|
|
19
|
+
RCT_EXTERN_METHOD(syncAll: (RCTPromiseResolveBlock) resolver)
|
|
14
20
|
@end
|
package/ios/PortalView.m
CHANGED
|
@@ -3,12 +3,11 @@
|
|
|
3
3
|
// ReactNativePortals
|
|
4
4
|
//
|
|
5
5
|
// Created by Steven Sherry on 4/1/22.
|
|
6
|
-
// Copyright © 2022
|
|
6
|
+
// Copyright © 2022 Ionic. All rights reserved.
|
|
7
7
|
//
|
|
8
8
|
|
|
9
9
|
#import <React/RCTViewManager.h>
|
|
10
10
|
|
|
11
11
|
@interface RCT_EXTERN_MODULE(IONPortalViewManager, RCTViewManager)
|
|
12
|
-
RCT_EXPORT_VIEW_PROPERTY(
|
|
13
|
-
RCT_EXPORT_VIEW_PROPERTY(initialContext, NSDictionary)
|
|
12
|
+
RCT_EXPORT_VIEW_PROPERTY(portal, NSDictionary)
|
|
14
13
|
@end
|