@ionic/portals-react-native 0.5.2 → 0.7.0
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/ReactNativePortals.podspec +39 -14
- package/android/build.gradle +78 -108
- package/android/gradle.properties +5 -3
- package/android/src/main/java/io/ionic/portals/reactnative/PortalView.kt +11 -8
- package/android/src/main/java/io/ionic/portals/reactnative/ReactNativePortalManager.kt +24 -24
- package/android/src/main/java/io/ionic/portals/reactnative/ReactNativePortalsModule.kt +0 -34
- package/android/src/main/java/io/ionic/portals/reactnative/ReactNativeWebVitalsModule.kt +0 -34
- package/ios/AssetMap+Codable.swift +33 -0
- package/ios/LiveUpdateManager+Async.swift +16 -46
- package/ios/Podfile +29 -4
- package/ios/Podfile.lock +478 -241
- package/ios/Portal.swift +50 -54
- package/ios/{PortalManager.m → PortalManager.mm} +0 -3
- package/ios/PortalView.swift +22 -12
- package/ios/{PortalWebVitals.m → PortalWebVitals.mm} +0 -1
- package/ios/PortalsConfig.swift +1 -88
- package/ios/PortalsReactNative-Bridging-Header.h +2 -0
- package/ios/PortalsReactNative.swift +17 -51
- package/ios/SyncResult+SyncError+Encodable.swift +55 -0
- package/ios/WebVitals.swift +17 -34
- package/package.json +62 -43
- package/src/{PortalView.android.tsx → BasePortalView.android.tsx} +2 -3
- package/src/{PortalView.tsx → BasePortalView.tsx} +2 -3
- package/src/{index.ts → index.tsx} +43 -96
- package/ios/AssetMap+Dict.swift +0 -28
- package/ios/LiveUpdate+Dict.swift +0 -30
- package/ios/LiveUpdateManagerError+Dict.swift +0 -19
- package/ios/ReactNativePortals.xcodeproj/project.pbxproj +0 -465
- package/ios/ReactNativePortals.xcodeproj/xcshareddata/xcschemes/ReactNativePortals.xcscheme +0 -67
- package/ios/ReactNativePortals.xcworkspace/contents.xcworkspacedata +0 -10
- package/ios/ReactNativePortals.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
- package/ios/SyncResult+Dict.swift +0 -35
- package/lib/commonjs/PortalView.android.js +0 -28
- package/lib/commonjs/PortalView.android.js.map +0 -1
- package/lib/commonjs/PortalView.js +0 -15
- package/lib/commonjs/PortalView.js.map +0 -1
- package/lib/commonjs/index.js +0 -200
- package/lib/commonjs/index.js.map +0 -1
- package/lib/module/PortalView.android.js +0 -20
- package/lib/module/PortalView.android.js.map +0 -1
- package/lib/module/PortalView.js +0 -8
- package/lib/module/PortalView.js.map +0 -1
- package/lib/module/index.js +0 -176
- package/lib/module/index.js.map +0 -1
- package/lib/typescript/PortalView.android.d.ts +0 -4
- package/lib/typescript/PortalView.d.ts +0 -4
- package/lib/typescript/index.d.ts +0 -181
- /package/ios/{PortalView.m → PortalView.mm} +0 -0
- /package/ios/{PortalsPubSub.m → PortalsPubSub.mm} +0 -0
|
@@ -1,21 +1,46 @@
|
|
|
1
|
-
require
|
|
1
|
+
require "json"
|
|
2
2
|
|
|
3
|
-
package = JSON.parse(File.read(File.join(__dir__,
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
4
|
+
folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
|
|
4
5
|
|
|
5
6
|
Pod::Spec.new do |s|
|
|
6
|
-
s.name =
|
|
7
|
-
s.version = package[
|
|
8
|
-
s.summary = package[
|
|
9
|
-
s.homepage = package[
|
|
10
|
-
s.license = package[
|
|
11
|
-
s.authors = package[
|
|
7
|
+
s.name = "ReactNativePortals"
|
|
8
|
+
s.version = package["version"]
|
|
9
|
+
s.summary = package["description"]
|
|
10
|
+
s.homepage = package["homepage"]
|
|
11
|
+
s.license = package["license"]
|
|
12
|
+
s.authors = package["author"]
|
|
12
13
|
|
|
13
|
-
s.platforms = { ios
|
|
14
|
-
s.source = { git
|
|
14
|
+
s.platforms = { :ios => min_ios_version_supported }
|
|
15
|
+
s.source = { :git => "https://github.com/ionic-team/ionic-portals-react-native.git", :tag => "#{s.version}" }
|
|
15
16
|
|
|
16
|
-
s.source_files =
|
|
17
|
+
s.source_files = "ios/**/*.{h,m,mm,swift}"
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
# Use install_modules_dependencies helper to install the dependencies if React Native version >=0.71.0.
|
|
20
|
+
# See https://github.com/facebook/react-native/blob/febf6b7f33fdb4904669f99d795eba4c0f95d7bf/scripts/cocoapods/new_architecture.rb#L79.
|
|
21
|
+
if respond_to?(:install_modules_dependencies, true)
|
|
22
|
+
s.dependency 'IonicPortals', '~> 0.11.0'
|
|
23
|
+
s.dependency 'IonicLiveUpdates', '~> 0.5.2'
|
|
24
|
+
install_modules_dependencies(s)
|
|
25
|
+
|
|
26
|
+
else
|
|
27
|
+
s.dependency "React-Core"
|
|
28
|
+
s.dependency 'IonicPortals', '~> 0.11.0'
|
|
29
|
+
s.dependency 'IonicLiveUpdates', '~> 0.5.2'
|
|
30
|
+
|
|
31
|
+
# Don't install the dependencies when we run `pod install` in the old architecture.
|
|
32
|
+
if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
|
|
33
|
+
s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
|
|
34
|
+
s.pod_target_xcconfig = {
|
|
35
|
+
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
|
|
36
|
+
"OTHER_CPLUSPLUSFLAGS" => "-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1",
|
|
37
|
+
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
|
|
38
|
+
}
|
|
39
|
+
s.dependency "React-Codegen"
|
|
40
|
+
s.dependency "RCT-Folly"
|
|
41
|
+
s.dependency "RCTRequired"
|
|
42
|
+
s.dependency "RCTTypeSafety"
|
|
43
|
+
s.dependency "ReactCommon/turbomodule/core"
|
|
44
|
+
end
|
|
45
|
+
end
|
|
21
46
|
end
|
package/android/build.gradle
CHANGED
|
@@ -1,131 +1,101 @@
|
|
|
1
1
|
buildscript {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
// Buildscript is evaluated before everything else so we can't use getExtOrDefault
|
|
3
|
+
def kotlin_version = rootProject.ext.has("kotlinVersion") ? rootProject.ext.get("kotlinVersion") : project.properties["PortalsReactNative_kotlinVersion"]
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
repositories {
|
|
6
|
+
google()
|
|
7
|
+
mavenCentral()
|
|
8
|
+
}
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
10
|
+
dependencies {
|
|
11
|
+
classpath "com.android.tools.build:gradle:7.2.1"
|
|
12
|
+
// noinspection DifferentKotlinGradleVersion
|
|
13
|
+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
|
14
|
+
}
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
def reactNativeArchitectures() {
|
|
18
|
+
def value = rootProject.getProperties().get("reactNativeArchitectures")
|
|
19
|
+
return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
|
|
20
|
+
}
|
|
19
21
|
|
|
20
|
-
def
|
|
21
|
-
|
|
22
|
+
def isNewArchitectureEnabled() {
|
|
23
|
+
return rootProject.hasProperty("newArchEnabled") && rootProject.getProperty("newArchEnabled") == "true"
|
|
22
24
|
}
|
|
23
25
|
|
|
24
|
-
android
|
|
25
|
-
|
|
26
|
-
defaultConfig {
|
|
27
|
-
minSdkVersion 16
|
|
28
|
-
targetSdkVersion getExtOrIntegerDefault('targetSdkVersion')
|
|
29
|
-
versionCode 1
|
|
30
|
-
versionName "1.0"
|
|
31
|
-
}
|
|
26
|
+
apply plugin: "com.android.library"
|
|
27
|
+
apply plugin: "kotlin-android"
|
|
32
28
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
minifyEnabled false
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
lintOptions {
|
|
39
|
-
disable 'GradleCompatible'
|
|
40
|
-
}
|
|
29
|
+
if (isNewArchitectureEnabled()) {
|
|
30
|
+
apply plugin: "com.facebook.react"
|
|
41
31
|
}
|
|
42
32
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
33
|
+
def getExtOrDefault(name) {
|
|
34
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : project.properties["PortalsReactNative_" + name]
|
|
35
|
+
}
|
|
46
36
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
37
|
+
def getExtOrIntegerDefault(name) {
|
|
38
|
+
return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties["PortalsReactNative_" + name]).toInteger()
|
|
50
39
|
}
|
|
51
40
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
41
|
+
def supportsNamespace() {
|
|
42
|
+
def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')
|
|
43
|
+
def major = parsed[0].toInteger()
|
|
44
|
+
def minor = parsed[1].toInteger()
|
|
55
45
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
defaultDir = new File(
|
|
64
|
-
projectDir,
|
|
65
|
-
'/../../../node_modules/react-native/android'
|
|
66
|
-
)
|
|
67
|
-
}
|
|
46
|
+
// Namespace support was added in 7.3.0
|
|
47
|
+
return (major == 7 && minor >= 3) || major >= 8
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
android {
|
|
51
|
+
if (supportsNamespace()) {
|
|
52
|
+
namespace "com.ionic.portalsreactnative"
|
|
68
53
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
logger.info(":${project.name}:reactNativeAndroidRoot ${defaultDir.canonicalPath}")
|
|
76
|
-
found = true
|
|
77
|
-
} else {
|
|
78
|
-
def parentDir = rootProject.projectDir
|
|
79
|
-
|
|
80
|
-
1.upto(5, {
|
|
81
|
-
if (found) return true
|
|
82
|
-
parentDir = parentDir.parentFile
|
|
83
|
-
|
|
84
|
-
def androidSourcesDir = new File(
|
|
85
|
-
parentDir,
|
|
86
|
-
'node_modules/react-native'
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
def androidPrebuiltBinaryDir = new File(
|
|
90
|
-
parentDir,
|
|
91
|
-
'node_modules/react-native/android'
|
|
92
|
-
)
|
|
93
|
-
|
|
94
|
-
if (androidPrebuiltBinaryDir.exists()) {
|
|
95
|
-
maven {
|
|
96
|
-
url androidPrebuiltBinaryDir.toString()
|
|
97
|
-
name androidSourcesName
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
logger.info(":${project.name}:reactNativeAndroidRoot ${androidPrebuiltBinaryDir.canonicalPath}")
|
|
101
|
-
found = true
|
|
102
|
-
} else if (androidSourcesDir.exists()) {
|
|
103
|
-
maven {
|
|
104
|
-
url androidSourcesDir.toString()
|
|
105
|
-
name androidSourcesName
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
logger.info(":${project.name}:reactNativeAndroidRoot ${androidSourcesDir.canonicalPath}")
|
|
109
|
-
found = true
|
|
110
|
-
}
|
|
111
|
-
})
|
|
54
|
+
sourceSets {
|
|
55
|
+
main {
|
|
56
|
+
manifest.srcFile "src/main/AndroidManifestNew.xml"
|
|
57
|
+
}
|
|
112
58
|
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
compileSdkVersion getExtOrIntegerDefault("compileSdkVersion")
|
|
62
|
+
|
|
63
|
+
defaultConfig {
|
|
64
|
+
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
|
|
65
|
+
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
|
|
66
|
+
|
|
67
|
+
}
|
|
113
68
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
"Ensure you have you installed React Native as a dependency in your project and try again."
|
|
118
|
-
)
|
|
69
|
+
buildTypes {
|
|
70
|
+
release {
|
|
71
|
+
minifyEnabled false
|
|
119
72
|
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
lintOptions {
|
|
76
|
+
disable "GradleCompatible"
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
compileOptions {
|
|
80
|
+
sourceCompatibility JavaVersion.VERSION_1_8
|
|
81
|
+
targetCompatibility JavaVersion.VERSION_1_8
|
|
82
|
+
}
|
|
120
83
|
}
|
|
121
84
|
|
|
85
|
+
repositories {
|
|
86
|
+
mavenCentral()
|
|
87
|
+
google()
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
def kotlin_version = getExtOrDefault("kotlinVersion")
|
|
91
|
+
|
|
122
92
|
dependencies {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.3"
|
|
93
|
+
// For < 0.71, this will be from the local maven repo
|
|
94
|
+
// For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
|
|
95
|
+
//noinspection GradleDynamicVersion
|
|
96
|
+
implementation "com.facebook.react:react-native:+"
|
|
97
|
+
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
98
|
+
implementation "io.ionic:portals:0.10.+"
|
|
99
|
+
implementation "io.ionic:liveupdates:0.5.+"
|
|
131
100
|
}
|
|
101
|
+
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
PortalsReactNative_kotlinVersion=1.8.0
|
|
2
|
+
PortalsReactNative_minSdkVersion=21
|
|
3
|
+
PortalsReactNative_targetSdkVersion=33
|
|
4
|
+
PortalsReactNative_compileSdkVersion=33
|
|
5
|
+
PortalsReactNative_ndkversion=21.4.7075529
|
|
4
6
|
android.useAndroidX=true
|
|
@@ -9,6 +9,7 @@ import androidx.fragment.app.FragmentActivity
|
|
|
9
9
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
10
10
|
import com.facebook.react.bridge.ReadableArray
|
|
11
11
|
import com.facebook.react.bridge.ReadableMap
|
|
12
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
12
13
|
import com.facebook.react.uimanager.ThemedReactContext
|
|
13
14
|
import com.facebook.react.uimanager.ViewGroupManager
|
|
14
15
|
import com.facebook.react.uimanager.annotations.ReactProp
|
|
@@ -32,7 +33,7 @@ internal class PortalViewManager(private val context: ReactApplicationContext) :
|
|
|
32
33
|
when (fragmentMap[viewGroup.id]) {
|
|
33
34
|
null -> fragmentMap[viewGroup.id] = PortalViewState(
|
|
34
35
|
fragment = null,
|
|
35
|
-
portal = RNPortalManager.
|
|
36
|
+
portal = RNPortalManager.createPortal(portal),
|
|
36
37
|
initialContext = portal.getMap("initialContext")?.toHashMap()
|
|
37
38
|
)
|
|
38
39
|
}
|
|
@@ -68,13 +69,15 @@ internal class PortalViewManager(private val context: ReactApplicationContext) :
|
|
|
68
69
|
setupLayout(parentView)
|
|
69
70
|
|
|
70
71
|
val portal = rnPortal.builder.create()
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
72
|
+
val vitals: List<String>? = rnPortal.vitals
|
|
73
|
+
|
|
74
|
+
if (vitals != null) {
|
|
75
|
+
val vitalsPlugin = WebVitals { name, metric, duration ->
|
|
76
|
+
val stringMetric = metric.toString().lowercase()
|
|
77
|
+
if (vitals.contains(stringMetric)) {
|
|
78
|
+
context
|
|
79
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
80
|
+
.emit("vitals:$stringMetric", mapOf("duration" to duration, "portalName" to name).toReadableMap())
|
|
78
81
|
}
|
|
79
82
|
}
|
|
80
83
|
portal.addPluginInstance(vitalsPlugin)
|
|
@@ -17,9 +17,7 @@ internal data class RNPortal(
|
|
|
17
17
|
val builder: PortalBuilder,
|
|
18
18
|
val index: String?,
|
|
19
19
|
val plugins: List<PortalPlugin>,
|
|
20
|
-
var
|
|
21
|
-
var onTTFB: ((Long) -> Unit)? = null,
|
|
22
|
-
var onFID: ((Long) -> Unit)? = null
|
|
20
|
+
var vitals: MutableList<String>? = null
|
|
23
21
|
)
|
|
24
22
|
|
|
25
23
|
internal data class PortalPlugin(val androidClassPath: String, val iosClassName: String) {
|
|
@@ -43,13 +41,12 @@ internal data class PortalPlugin(val androidClassPath: String, val iosClassName:
|
|
|
43
41
|
|
|
44
42
|
internal object RNPortalManager {
|
|
45
43
|
private val manager = PortalManager
|
|
46
|
-
private val portals: ConcurrentHashMap<String, RNPortal> = ConcurrentHashMap()
|
|
47
44
|
private lateinit var reactApplicationContext: ReactApplicationContext
|
|
48
45
|
private var usesSecureLiveUpdates = false
|
|
49
46
|
|
|
50
47
|
fun register(key: String) = manager.register(key)
|
|
51
48
|
|
|
52
|
-
fun
|
|
49
|
+
fun createPortal(map: ReadableMap): RNPortal? {
|
|
53
50
|
val name = map.getString("name") ?: return null
|
|
54
51
|
val portalBuilder = PortalBuilder(name)
|
|
55
52
|
|
|
@@ -60,13 +57,16 @@ internal object RNPortalManager {
|
|
|
60
57
|
?.toHashMap()
|
|
61
58
|
?.let(portalBuilder::setInitialContext)
|
|
62
59
|
|
|
60
|
+
if (map.hasKey("devMode")) {
|
|
61
|
+
map.getBoolean("devMode").let(portalBuilder::setDevMode)
|
|
62
|
+
}
|
|
63
63
|
|
|
64
64
|
val plugins: List<PortalPlugin> = map.getArray("plugins")
|
|
65
65
|
?.let { rnArray ->
|
|
66
66
|
val list = mutableListOf<PortalPlugin>()
|
|
67
67
|
for (idx in 0 until rnArray.size()) {
|
|
68
68
|
rnArray.getMap(idx)
|
|
69
|
-
|
|
69
|
+
.let(PortalPlugin.Companion::fromReadableMap)
|
|
70
70
|
?.let(list::add)
|
|
71
71
|
}
|
|
72
72
|
return@let list
|
|
@@ -84,7 +84,7 @@ internal object RNPortalManager {
|
|
|
84
84
|
|
|
85
85
|
for (idx in 0 until rnArray.size()) {
|
|
86
86
|
rnArray.getMap(idx)
|
|
87
|
-
|
|
87
|
+
.let assetMap@{ map ->
|
|
88
88
|
val name = map.getString("name") ?: return@assetMap null
|
|
89
89
|
AssetMap(
|
|
90
90
|
name = name,
|
|
@@ -105,11 +105,11 @@ internal object RNPortalManager {
|
|
|
105
105
|
val appId = readableMap.getString("appId") ?: return@let null
|
|
106
106
|
val channel = readableMap.getString("channel") ?: return@let null
|
|
107
107
|
val syncOnAdd = readableMap.getBoolean("syncOnAdd")
|
|
108
|
-
Pair(LiveUpdate(appId, channel,
|
|
108
|
+
Pair(LiveUpdate(appId, channel, usesSecureLiveUpdates), syncOnAdd)
|
|
109
109
|
}
|
|
110
110
|
?.let { (liveUpdate, updateOnAppLoad) ->
|
|
111
111
|
portalBuilder.setLiveUpdateConfig(
|
|
112
|
-
context =
|
|
112
|
+
context = reactApplicationContext,
|
|
113
113
|
liveUpdateConfig = liveUpdate,
|
|
114
114
|
updateOnAppLoad = updateOnAppLoad
|
|
115
115
|
)
|
|
@@ -118,19 +118,26 @@ internal object RNPortalManager {
|
|
|
118
118
|
portalBuilder
|
|
119
119
|
.addPlugin(PortalsPlugin::class.java)
|
|
120
120
|
|
|
121
|
-
val
|
|
121
|
+
val vitals = map.getArray("webVitals")
|
|
122
|
+
val maybeList = if (vitals != null) {
|
|
123
|
+
val size = vitals.size()
|
|
124
|
+
(0 until size).fold(mutableListOf<String>()) { list, next ->
|
|
125
|
+
val vital = vitals.getString(next)
|
|
126
|
+
list.add(vital)
|
|
127
|
+
return@fold list
|
|
128
|
+
}
|
|
129
|
+
} else {
|
|
130
|
+
null
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return RNPortal(
|
|
122
134
|
builder = portalBuilder,
|
|
123
135
|
index = map.getString("index"),
|
|
124
|
-
plugins = plugins
|
|
136
|
+
plugins = plugins,
|
|
137
|
+
vitals = maybeList
|
|
125
138
|
)
|
|
126
|
-
|
|
127
|
-
portals[name] = rnPortal
|
|
128
|
-
return rnPortal
|
|
129
139
|
}
|
|
130
140
|
|
|
131
|
-
fun getPortal(name: String): RNPortal = portals[name]
|
|
132
|
-
?: throw IllegalStateException("Portal with portalId $name not found in RNPortalManager")
|
|
133
|
-
|
|
134
141
|
fun enableSecureLiveUpdates(keyPath: String) {
|
|
135
142
|
LiveUpdateManager.secureLiveUpdatePEM = keyPath
|
|
136
143
|
usesSecureLiveUpdates = true
|
|
@@ -162,13 +169,6 @@ internal object RNPortalManager {
|
|
|
162
169
|
LiveUpdateManager.secureLiveUpdatePEM = it
|
|
163
170
|
usesSecureLiveUpdates = true
|
|
164
171
|
}
|
|
165
|
-
|
|
166
|
-
val portalJsonArray = configJson.getJSONArray("portals")
|
|
167
|
-
|
|
168
|
-
for (index in 0 until portalJsonArray.length()) {
|
|
169
|
-
val portalJson = portalJsonArray.getJSONObject(index)
|
|
170
|
-
addPortal(portalJson.toReactMap())
|
|
171
|
-
}
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
174
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
package io.ionic.portals.reactnative
|
|
2
2
|
|
|
3
3
|
import com.facebook.react.bridge.*
|
|
4
|
-
import io.ionic.portals.Portal
|
|
5
4
|
|
|
6
5
|
internal class PortalManagerModule(reactContext: ReactApplicationContext) :
|
|
7
6
|
ReactContextBaseJavaModule(reactContext) {
|
|
@@ -17,39 +16,6 @@ internal class PortalManagerModule(reactContext: ReactApplicationContext) :
|
|
|
17
16
|
promise.resolve(null)
|
|
18
17
|
}
|
|
19
18
|
|
|
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
|
-
}
|
|
29
|
-
|
|
30
|
-
@ReactMethod
|
|
31
|
-
fun addPortals(array: ReadableArray, promise: Promise) {
|
|
32
|
-
val portals = WritableNativeArray()
|
|
33
|
-
|
|
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
|
-
}
|
|
39
|
-
|
|
40
|
-
promise.resolve(portals)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
@ReactMethod
|
|
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.")
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
19
|
@ReactMethod
|
|
54
20
|
fun enableSecureLiveUpdates(keyPath: String, promise: Promise) {
|
|
55
21
|
RNPortalManager.enableSecureLiveUpdates(keyPath)
|
|
@@ -4,44 +4,10 @@ import com.facebook.react.bridge.Promise
|
|
|
4
4
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
5
5
|
import com.facebook.react.bridge.ReactContextBaseJavaModule
|
|
6
6
|
import com.facebook.react.bridge.ReactMethod
|
|
7
|
-
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
8
7
|
|
|
9
8
|
internal class PortalWebVitalsModule(reactContext: ReactApplicationContext): ReactContextBaseJavaModule(reactContext) {
|
|
10
9
|
override fun getName() = "IONPortalsWebVitals"
|
|
11
10
|
|
|
12
|
-
@ReactMethod
|
|
13
|
-
fun registerOnFirstContentfulPaint(portalName: String, promise: Promise) {
|
|
14
|
-
RNPortalManager.getPortal(portalName).onFCP = { duration ->
|
|
15
|
-
reactApplicationContext
|
|
16
|
-
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
17
|
-
.emit("vitals:fcp", mapOf("duration" to duration, "portalName" to portalName).toReadableMap())
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
promise.resolve(null)
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
@ReactMethod
|
|
24
|
-
fun registerOnFirstInputDelay(portalName: String, promise: Promise) {
|
|
25
|
-
RNPortalManager.getPortal(portalName).onFID = { duration ->
|
|
26
|
-
reactApplicationContext
|
|
27
|
-
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
28
|
-
.emit("vitals:fid", mapOf("duration" to duration, "portalName" to portalName).toReadableMap())
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
promise.resolve(null)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
@ReactMethod
|
|
35
|
-
fun registerOnTimeToFirstByte(portalName: String, promise: Promise) {
|
|
36
|
-
RNPortalManager.getPortal(portalName).onTTFB = { duration ->
|
|
37
|
-
reactApplicationContext
|
|
38
|
-
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
39
|
-
.emit("vitals:ttfb", mapOf("duration" to duration, "portalName" to portalName).toReadableMap())
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
promise.resolve(null)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
11
|
@ReactMethod
|
|
46
12
|
fun addListener(eventName: String) {
|
|
47
13
|
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
//
|
|
2
|
+
// IonicPortals+Codable.swift
|
|
3
|
+
// ReactNativePortals
|
|
4
|
+
//
|
|
5
|
+
// Created by Trevor Lambert on 6/5/24.
|
|
6
|
+
// Copyright © 2024 Facebook. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
import Foundation
|
|
10
|
+
import IonicPortals
|
|
11
|
+
|
|
12
|
+
extension AssetMap: Encodable {
|
|
13
|
+
enum CodingKeys: String, CodingKey {
|
|
14
|
+
case startDir, virtualPath, name
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
public func encode(to encoder: Encoder) throws {
|
|
18
|
+
var container = encoder.container(keyedBy: CodingKeys.self)
|
|
19
|
+
try container.encode(startDir, forKey: .startDir)
|
|
20
|
+
try container.encode(virtualPath, forKey: .virtualPath)
|
|
21
|
+
try container.encode(name, forKey: .name)
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
extension AssetMap: Decodable {
|
|
26
|
+
public init(from decoder: Decoder) throws {
|
|
27
|
+
let container = try decoder.container(keyedBy: CodingKeys.self)
|
|
28
|
+
let name = try container.decode(String.self, forKey: .name)
|
|
29
|
+
let startDir = try container.decodeIfPresent(String.self, forKey: .startDir) ?? ""
|
|
30
|
+
let virtualPath = try container.decodeIfPresent(String.self, forKey: .virtualPath)
|
|
31
|
+
self.init(name: name, virtualPath: virtualPath, startDir: startDir)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -7,63 +7,33 @@
|
|
|
7
7
|
//
|
|
8
8
|
|
|
9
9
|
import IonicLiveUpdates
|
|
10
|
+
import Capacitor
|
|
10
11
|
|
|
11
|
-
struct SyncResults {
|
|
12
|
+
struct SyncResults: Encodable {
|
|
12
13
|
var results: [LiveUpdateManager.SyncResult]
|
|
13
|
-
var errors: [LiveUpdateManager.
|
|
14
|
+
var errors: [LiveUpdateManager.SyncError]
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
extension SyncResults {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
init(_ results: ([LiveUpdateManager.SyncResult], [LiveUpdateManager.SyncError])) {
|
|
19
|
+
self.results = results.0
|
|
20
|
+
self.errors = results.1
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
var dict: JSValue {
|
|
24
|
+
get throws {
|
|
25
|
+
try JSValueEncoder(optionalEncodingStrategy: .undefined)
|
|
26
|
+
.encode(self)
|
|
27
|
+
}
|
|
22
28
|
}
|
|
23
29
|
}
|
|
24
30
|
|
|
25
31
|
extension LiveUpdateManager {
|
|
26
32
|
func syncSome(_ appIds: [String]) async -> SyncResults {
|
|
27
|
-
await
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
private func _syncSome(_ appIds: [String]) -> AsyncStream<Result<LiveUpdateManager.SyncResult, 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<LiveUpdateManager.SyncResult, LiveUpdateManager.Error>> {
|
|
46
|
-
AsyncStream { continuation in
|
|
47
|
-
sync(isParallel: true) {
|
|
48
|
-
continuation.finish()
|
|
49
|
-
} appComplete: { result in
|
|
50
|
-
continuation.yield(result)
|
|
51
|
-
}
|
|
52
|
-
}
|
|
33
|
+
SyncResults(await sync(appIds: appIds))
|
|
53
34
|
}
|
|
54
|
-
}
|
|
55
35
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
get async {
|
|
59
|
-
await reduce(into: SyncResults(results: [], errors: [])) { acc, next in
|
|
60
|
-
switch next {
|
|
61
|
-
case .success(let liveUpdate):
|
|
62
|
-
acc.results.append(liveUpdate)
|
|
63
|
-
case .failure(let error):
|
|
64
|
-
acc.errors.append(error)
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
36
|
+
func syncAll() async -> SyncResults {
|
|
37
|
+
SyncResults(await sync())
|
|
68
38
|
}
|
|
69
39
|
}
|