expo-updates 1.0.0-canary-20241021-7aba813 → 1.0.0-canary-20250122-166c2cb
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/CHANGELOG.md +83 -0
- package/android/build.gradle +3 -2
- package/android/proguard-rules.pro +1 -1
- package/android/src/main/java/expo/modules/updates/UpdatesController.kt +5 -5
- package/android/src/main/java/expo/modules/updates/UpdatesModule.kt +22 -9
- package/android/src/main/java/expo/modules/updates/errorrecovery/ErrorRecovery.kt +5 -5
- package/android/src/main/java/expo/modules/updates/events/IUpdatesEventManager.kt +4 -4
- package/android/src/main/java/expo/modules/updates/events/NoOpUpdatesEventManager.kt +2 -2
- package/android/src/main/java/expo/modules/updates/events/UpdatesEventManager.kt +8 -12
- package/android/src/main/java/expo/modules/updates/loader/FileDownloader.kt +25 -24
- package/android/src/main/java/expo/modules/updates/loader/LoaderTask.kt +70 -58
- package/android/src/main/java/expo/modules/updates/procedures/RecreateReactContextProcedure.kt +1 -1
- package/android/src/main/java/expo/modules/updates/procedures/RelaunchProcedure.kt +3 -3
- package/android/src/main/java/expo/modules/updates/procedures/RestartReactAppExtensions.kt +2 -2
- package/android/src/main/java/expo/modules/updates/procedures/StartupProcedure.kt +2 -0
- package/android/src/main/java/expo/modules/updates/procedures/StateMachineProcedure.kt +3 -2
- package/android/src/main/java/expo/modules/updates/procedures/StateMachineSerialExecutorQueue.kt +2 -2
- package/android/src/main/java/expo/modules/updates/statemachine/UpdatesStateContext.kt +20 -15
- package/android/src/main/java/expo/modules/updates/statemachine/UpdatesStateEvent.kt +9 -7
- package/android/src/main/java/expo/modules/updates/statemachine/UpdatesStateEventType.kt +2 -0
- package/android/src/main/java/expo/modules/updates/statemachine/UpdatesStateMachine.kt +13 -5
- package/build/ExpoUpdates.web.d.ts +33 -2
- package/build/ExpoUpdates.web.d.ts.map +1 -1
- package/build/ExpoUpdates.web.js +50 -3
- package/build/ExpoUpdates.web.js.map +1 -1
- package/build/ExpoUpdatesModule.types.d.ts +48 -5
- package/build/ExpoUpdatesModule.types.d.ts.map +1 -1
- package/build/ExpoUpdatesModule.types.js.map +1 -1
- package/build/Updates.d.ts.map +1 -1
- package/build/Updates.js +5 -4
- package/build/Updates.js.map +1 -1
- package/build/Updates.types.d.ts +2 -8
- package/build/Updates.types.d.ts.map +1 -1
- package/build/Updates.types.js.map +1 -1
- package/build/UseUpdates.d.ts.map +1 -1
- package/build/UseUpdates.js +1 -1
- package/build/UseUpdates.js.map +1 -1
- package/build/UseUpdates.types.d.ts +14 -5
- package/build/UseUpdates.types.d.ts.map +1 -1
- package/build/UseUpdates.types.js.map +1 -1
- package/build/UseUpdatesUtils.d.ts +2 -14
- package/build/UseUpdatesUtils.d.ts.map +1 -1
- package/build/UseUpdatesUtils.js +4 -1
- package/build/UseUpdatesUtils.js.map +1 -1
- package/cli/build/syncConfigurationToNativeAsync.js +1 -0
- package/cli/src/syncConfigurationToNativeAsync.ts +1 -0
- package/e2e/fixtures/App.tsx +18 -0
- package/e2e/fixtures/Updates-error-recovery.e2e.ts +2 -2
- package/e2e/fixtures/Updates-fingerprint.e2e.ts +0 -38
- package/e2e/fixtures/Updates-startup.e2e.ts +18 -3
- package/e2e/fixtures/Updates.e2e.ts +33 -44
- package/e2e/fixtures/project_files/.fingerprintignore +3 -1
- package/e2e/setup/project.ts +8 -3
- package/e2e-cli/jest.config.js +8 -0
- package/expo-updates-gradle-plugin/build.gradle.kts +1 -1
- package/ios/EXUpdates/AppController.swift +10 -8
- package/ios/EXUpdates/AppLauncher/AppLauncherWithDatabase.swift +3 -3
- package/ios/EXUpdates/AppLoader/AppLoaderTask.swift +9 -11
- package/ios/EXUpdates/AppLoader/FileDownloader.swift +4 -4
- package/ios/EXUpdates/AppLoader/RemoteAppLoader.swift +1 -1
- package/ios/EXUpdates/Database/UpdatesDatabase.swift +2 -2
- package/ios/EXUpdates/Database/UpdatesDatabaseInitialization.swift +14 -6
- package/ios/EXUpdates/Database/UpdatesReaper.swift +4 -3
- package/ios/EXUpdates/DevLauncherAppController.swift +4 -2
- package/ios/EXUpdates/DisabledAppController.swift +5 -1
- package/ios/EXUpdates/EnabledAppController.swift +1 -44
- package/ios/EXUpdates/ErrorRecovery.swift +4 -2
- package/ios/EXUpdates/Events/NoOpUpdatesEventManager.swift +1 -1
- package/ios/EXUpdates/Events/QueueUpdatesEventManager.swift +6 -12
- package/ios/EXUpdates/Events/UpdatesEventManager.swift +5 -1
- package/ios/EXUpdates/Logging/UpdatesLogger.swift +4 -2
- package/ios/EXUpdates/Procedures/CheckForUpdateProcedure.swift +11 -13
- package/ios/EXUpdates/Procedures/FetchUpdateProcedure.swift +6 -6
- package/ios/EXUpdates/Procedures/RecreateReactContextProcedure.swift +2 -2
- package/ios/EXUpdates/Procedures/RelaunchProcedure.swift +6 -4
- package/ios/EXUpdates/Procedures/StartupProcedure.swift +16 -14
- package/ios/EXUpdates/Procedures/StateMachineProcedure.swift +9 -9
- package/ios/EXUpdates/Procedures/StateMachineSerialExecutorQueue.swift +2 -2
- package/ios/EXUpdates/ReactDelegateHandler/ExpoUpdatesReactDelegateHandler.swift +32 -0
- package/ios/EXUpdates/UpdatesModule.swift +15 -5
- package/ios/EXUpdates/UpdatesStateMachine.swift +126 -156
- package/ios/Tests/AppLauncherWithDatabaseSpec.swift +3 -2
- package/ios/Tests/DatabaseInitializationSpec.swift +37 -16
- package/ios/Tests/DatabaseIntegrityCheckSpec.swift +1 -1
- package/ios/Tests/ErrorRecoverySpec.swift +1 -1
- package/ios/Tests/FileDownloaderManifestParsingSpec.swift +24 -24
- package/ios/Tests/FileDownloaderSpec.swift +9 -9
- package/ios/Tests/UpdatesBuildDataSpec.swift +1 -1
- package/ios/Tests/UpdatesDatabaseSpec.swift +1 -1
- package/ios/Tests/UpdatesLoggerSpec.swift +29 -9
- package/ios/Tests/UpdatesStateMachineSpec.swift +71 -34
- package/package.json +13 -14
- package/src/ExpoUpdates.web.ts +78 -3
- package/src/ExpoUpdatesModule.types.ts +61 -4
- package/src/Updates.ts +9 -5
- package/src/Updates.types.ts +2 -10
- package/src/UseUpdates.ts +1 -2
- package/src/UseUpdates.types.ts +14 -5
- package/src/UseUpdatesUtils.ts +10 -17
- package/utils/build/createFingerprintAsync.d.ts +1 -1
- package/utils/build/createFingerprintAsync.js +1 -1
- package/utils/build/resolveRuntimeVersionAsync.d.ts +1 -1
- package/utils/src/createFingerprintAsync.ts +1 -1
- package/utils/src/resolveRuntimeVersionAsync.ts +1 -1
- package/fingerprint.d.ts +0 -1
- package/fingerprint.js +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,89 @@
|
|
|
4
4
|
|
|
5
5
|
### 🛠 Breaking changes
|
|
6
6
|
|
|
7
|
+
- Remove a few long-deprecated typescript types. ([#34215](https://github.com/expo/expo/pull/34215) by [@wschurman](https://github.com/wschurman))
|
|
8
|
+
|
|
9
|
+
### 🎉 New features
|
|
10
|
+
|
|
11
|
+
- Add new state machine context about startup procedure. ([#32433](https://github.com/expo/expo/pull/32433) by [@wschurman](https://github.com/wschurman))
|
|
12
|
+
|
|
13
|
+
### 🐛 Bug fixes
|
|
14
|
+
|
|
15
|
+
- Fix an issue where `launchFallbackUpdateFromDisk` is called from a foreground thread leading to ANRs. ([#33693](https://github.com/expo/expo/pull/33693) by [@alanjhughes](https://github.com/alanjhughes))
|
|
16
|
+
- [android] Use more robust mechanism for determining empty multipart bodies. ([#33977](https://github.com/expo/expo/pull/33977) by [@wschurman](https://github.com/wschurman))
|
|
17
|
+
|
|
18
|
+
### 💡 Others
|
|
19
|
+
|
|
20
|
+
- [iOS] Inject logger from controllers down to dependent objects. ([#34035](https://github.com/expo/expo/pull/34035) by [@wschurman](https://github.com/wschurman))
|
|
21
|
+
|
|
22
|
+
## 0.26.10 - 2024-12-05
|
|
23
|
+
|
|
24
|
+
### 🐛 Bug fixes
|
|
25
|
+
|
|
26
|
+
- Fix black screen appearing instead of the splashscreen on launch. ([#33432](https://github.com/expo/expo/pull/33432) by [@alanjhughes](https://github.com/alanjhughes))
|
|
27
|
+
|
|
28
|
+
## 0.26.9 — 2024-11-22
|
|
29
|
+
|
|
30
|
+
### 🐛 Bug fixes
|
|
31
|
+
|
|
32
|
+
- Fixed `Inconsistent JVM-target compatibility` error when building with JDK 21. ([#33148](https://github.com/expo/expo/pull/33148) by [@kudo](https://github.com/kudo))
|
|
33
|
+
|
|
34
|
+
### 💡 Others
|
|
35
|
+
|
|
36
|
+
- Introduced `ReactNativeFeatureFlags` compat to fix React Native 0.77 breaking changes. ([#33077](https://github.com/expo/expo/pull/33077) by [@kudo](https://github.com/kudo))
|
|
37
|
+
|
|
38
|
+
## 0.26.8 — 2024-11-20
|
|
39
|
+
|
|
40
|
+
_This version does not introduce any user-facing changes._
|
|
41
|
+
|
|
42
|
+
## 0.26.7 — 2024-11-14
|
|
43
|
+
|
|
44
|
+
_This version does not introduce any user-facing changes._
|
|
45
|
+
|
|
46
|
+
## 0.26.6 — 2024-11-13
|
|
47
|
+
|
|
48
|
+
### 💡 Others
|
|
49
|
+
|
|
50
|
+
- Upgrade `express` to `4.21.1` for `send`. ([#32852](https://github.com/expo/expo/pull/32852) by [@MWein](https://github.com/MWein))
|
|
51
|
+
|
|
52
|
+
## 0.26.5 — 2024-11-07
|
|
53
|
+
|
|
54
|
+
_This version does not introduce any user-facing changes._
|
|
55
|
+
|
|
56
|
+
## 0.26.4 — 2024-11-04
|
|
57
|
+
|
|
58
|
+
### 🐛 Bug fixes
|
|
59
|
+
|
|
60
|
+
- Improve web native module interface completeness ([#32512](https://github.com/expo/expo/pull/32512) by [@wschurman](https://github.com/wschurman))
|
|
61
|
+
|
|
62
|
+
## 0.26.3 — 2024-10-31
|
|
63
|
+
|
|
64
|
+
_This version does not introduce any user-facing changes._
|
|
65
|
+
|
|
66
|
+
## 0.26.2 — 2024-10-24
|
|
67
|
+
|
|
68
|
+
### 🐛 Bug fixes
|
|
69
|
+
|
|
70
|
+
- Move event emitting responsibility to module. ([#32248](https://github.com/expo/expo/pull/32248) by [@wschurman](https://github.com/wschurman))
|
|
71
|
+
|
|
72
|
+
### 💡 Others
|
|
73
|
+
|
|
74
|
+
- Use enum event in OnStartObserving and OnStopObserving. ([#32252](https://github.com/expo/expo/pull/32252) by [@wschurman](https://github.com/wschurman))
|
|
75
|
+
|
|
76
|
+
## 0.26.1 — 2024-10-22
|
|
77
|
+
|
|
78
|
+
### 🐛 Bug fixes
|
|
79
|
+
|
|
80
|
+
- Fixed Android launch crash when R8 is enabled. ([#32226](https://github.com/expo/expo/pull/32226) by [@kudo](https://github.com/kudo))
|
|
81
|
+
|
|
82
|
+
### 💡 Others
|
|
83
|
+
|
|
84
|
+
- Fixed updates E2E tests. ([#32226](https://github.com/expo/expo/pull/32226) by [@kudo](https://github.com/kudo))
|
|
85
|
+
|
|
86
|
+
## 0.26.0 — 2024-10-22
|
|
87
|
+
|
|
88
|
+
### 🛠 Breaking changes
|
|
89
|
+
|
|
7
90
|
- Bumped iOS and tvOS deployment target to 15.1. ([#30840](https://github.com/expo/expo/pull/30840) by [@tsapeta](https://github.com/tsapeta))
|
|
8
91
|
|
|
9
92
|
### 🎉 New features
|
package/android/build.gradle
CHANGED
|
@@ -16,11 +16,12 @@ apply plugin: 'com.android.library'
|
|
|
16
16
|
apply plugin: 'com.google.devtools.ksp'
|
|
17
17
|
|
|
18
18
|
group = 'host.exp.exponent'
|
|
19
|
-
version = '0.
|
|
19
|
+
version = '0.26.9'
|
|
20
20
|
|
|
21
21
|
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
|
|
22
22
|
apply from: expoModulesCorePlugin
|
|
23
23
|
applyKotlinExpoModulesCorePlugin()
|
|
24
|
+
applyKspJvmToolchain()
|
|
24
25
|
useCoreDependencies()
|
|
25
26
|
useDefaultAndroidSdkVersions()
|
|
26
27
|
useExpoPublishing()
|
|
@@ -62,7 +63,7 @@ android {
|
|
|
62
63
|
namespace "expo.modules.updates"
|
|
63
64
|
defaultConfig {
|
|
64
65
|
versionCode 31
|
|
65
|
-
versionName '0.
|
|
66
|
+
versionName '0.26.9'
|
|
66
67
|
consumerProguardFiles("proguard-rules.pro")
|
|
67
68
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
68
69
|
|
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
}
|
|
4
4
|
|
|
5
5
|
-keepclassmembers class com.facebook.react.devsupport.ReleaseDevSupportManager {
|
|
6
|
-
private final com.facebook.react.bridge.DefaultJSExceptionHandler
|
|
6
|
+
private final com.facebook.react.bridge.DefaultJSExceptionHandler defaultJSExceptionHandler;
|
|
7
7
|
}
|
|
@@ -2,7 +2,7 @@ package expo.modules.updates
|
|
|
2
2
|
|
|
3
3
|
import android.content.Context
|
|
4
4
|
import com.facebook.react.ReactApplication
|
|
5
|
-
import expo.modules.
|
|
5
|
+
import expo.modules.updates.events.IUpdatesEventManagerObserver
|
|
6
6
|
import expo.modules.updates.loader.LoaderTask
|
|
7
7
|
import expo.modules.updates.logging.UpdatesErrorCode
|
|
8
8
|
import expo.modules.updates.logging.UpdatesLogger
|
|
@@ -151,13 +151,13 @@ class UpdatesController {
|
|
|
151
151
|
}
|
|
152
152
|
}
|
|
153
153
|
|
|
154
|
-
internal fun
|
|
155
|
-
singletonInstance?.eventManager?.
|
|
154
|
+
internal fun setUpdatesEventManagerObserver(observer: WeakReference<IUpdatesEventManagerObserver>) {
|
|
155
|
+
singletonInstance?.eventManager?.observer = observer
|
|
156
156
|
singletonInstance?.onEventListenerStartObserving()
|
|
157
157
|
}
|
|
158
158
|
|
|
159
|
-
internal fun
|
|
160
|
-
singletonInstance?.eventManager?.
|
|
159
|
+
internal fun removeUpdatesEventManagerObserver() {
|
|
160
|
+
singletonInstance?.eventManager?.observer = null
|
|
161
161
|
}
|
|
162
162
|
}
|
|
163
163
|
}
|
|
@@ -8,19 +8,26 @@ import expo.modules.kotlin.exception.CodedException
|
|
|
8
8
|
import expo.modules.kotlin.exception.Exceptions
|
|
9
9
|
import expo.modules.kotlin.modules.Module
|
|
10
10
|
import expo.modules.kotlin.modules.ModuleDefinition
|
|
11
|
-
import expo.modules.
|
|
11
|
+
import expo.modules.kotlin.types.Enumerable
|
|
12
|
+
import expo.modules.updates.events.IUpdatesEventManagerObserver
|
|
12
13
|
import expo.modules.updates.logging.UpdatesErrorCode
|
|
13
14
|
import expo.modules.updates.logging.UpdatesLogEntry
|
|
14
15
|
import expo.modules.updates.logging.UpdatesLogReader
|
|
15
16
|
import expo.modules.updates.logging.UpdatesLogger
|
|
17
|
+
import expo.modules.updates.statemachine.UpdatesStateContext
|
|
18
|
+
import java.lang.ref.WeakReference
|
|
16
19
|
import java.util.Date
|
|
17
20
|
|
|
21
|
+
enum class UpdatesJSEvent(val eventName: String) : Enumerable {
|
|
22
|
+
StateChange("Expo.nativeUpdatesStateChangeEvent")
|
|
23
|
+
}
|
|
24
|
+
|
|
18
25
|
/**
|
|
19
26
|
* Exported module which provides to the JS runtime information about the currently running update
|
|
20
27
|
* and updates state, along with methods to check for and download new updates, reload with the
|
|
21
28
|
* newest downloaded update applied, and read/clear native log entries.
|
|
22
29
|
*/
|
|
23
|
-
class UpdatesModule : Module() {
|
|
30
|
+
class UpdatesModule : Module(), IUpdatesEventManagerObserver {
|
|
24
31
|
private val logger: UpdatesLogger
|
|
25
32
|
get() = UpdatesLogger(context)
|
|
26
33
|
|
|
@@ -30,21 +37,23 @@ class UpdatesModule : Module() {
|
|
|
30
37
|
override fun definition() = ModuleDefinition {
|
|
31
38
|
Name("ExpoUpdates")
|
|
32
39
|
|
|
33
|
-
Events(
|
|
34
|
-
UpdatesJSEvent.StateChange.eventName
|
|
35
|
-
)
|
|
40
|
+
Events<UpdatesJSEvent>()
|
|
36
41
|
|
|
37
42
|
Constants {
|
|
38
43
|
UpdatesLogger(context).info("UpdatesModule: getConstants called", UpdatesErrorCode.None)
|
|
39
44
|
UpdatesController.instance.getConstantsForModule().toModuleConstantsMap()
|
|
40
45
|
}
|
|
41
46
|
|
|
42
|
-
OnStartObserving {
|
|
43
|
-
UpdatesController.
|
|
47
|
+
OnStartObserving(UpdatesJSEvent.StateChange) {
|
|
48
|
+
UpdatesController.setUpdatesEventManagerObserver(WeakReference(this@UpdatesModule))
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
OnStopObserving(UpdatesJSEvent.StateChange) {
|
|
52
|
+
UpdatesController.removeUpdatesEventManagerObserver()
|
|
44
53
|
}
|
|
45
54
|
|
|
46
|
-
|
|
47
|
-
UpdatesController.
|
|
55
|
+
OnDestroy {
|
|
56
|
+
UpdatesController.removeUpdatesEventManagerObserver()
|
|
48
57
|
}
|
|
49
58
|
|
|
50
59
|
AsyncFunction("reload") { promise: Promise ->
|
|
@@ -240,4 +249,8 @@ class UpdatesModule : Module() {
|
|
|
240
249
|
)
|
|
241
250
|
}
|
|
242
251
|
}
|
|
252
|
+
|
|
253
|
+
override fun onStateMachineContextEvent(context: UpdatesStateContext) {
|
|
254
|
+
sendEvent(UpdatesJSEvent.StateChange, Bundle().apply { putBundle("context", context.bundle) })
|
|
255
|
+
}
|
|
243
256
|
}
|
|
@@ -6,9 +6,9 @@ import com.facebook.react.bridge.DefaultJSExceptionHandler
|
|
|
6
6
|
import com.facebook.react.bridge.ReactMarker
|
|
7
7
|
import com.facebook.react.bridge.ReactMarker.MarkerListener
|
|
8
8
|
import com.facebook.react.bridge.ReactMarkerConstants
|
|
9
|
-
import com.facebook.react.config.ReactFeatureFlags
|
|
10
9
|
import com.facebook.react.devsupport.ReleaseDevSupportManager
|
|
11
10
|
import com.facebook.react.devsupport.interfaces.DevSupportManager
|
|
11
|
+
import expo.modules.rncompatibility.ReactNativeFeatureFlags
|
|
12
12
|
import expo.modules.updates.logging.UpdatesErrorCode
|
|
13
13
|
import expo.modules.updates.logging.UpdatesLogger
|
|
14
14
|
import java.lang.ref.WeakReference
|
|
@@ -97,7 +97,7 @@ class ErrorRecovery(
|
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
private fun registerErrorHandler(devSupportManager: DevSupportManager) {
|
|
100
|
-
if (
|
|
100
|
+
if (ReactNativeFeatureFlags.enableBridgelessArchitecture) {
|
|
101
101
|
registerErrorHandlerImplBridgeless()
|
|
102
102
|
} else {
|
|
103
103
|
registerErrorHandlerImplBridge(devSupportManager)
|
|
@@ -120,7 +120,7 @@ class ErrorRecovery(
|
|
|
120
120
|
}
|
|
121
121
|
}
|
|
122
122
|
val devSupportManagerClass = devSupportManager.javaClass
|
|
123
|
-
previousExceptionHandler = devSupportManagerClass.getDeclaredField("
|
|
123
|
+
previousExceptionHandler = devSupportManagerClass.getDeclaredField("defaultJSExceptionHandler").let { field ->
|
|
124
124
|
field.isAccessible = true
|
|
125
125
|
val previousValue = field[devSupportManager]
|
|
126
126
|
field[devSupportManager] = defaultJSExceptionHandler
|
|
@@ -130,7 +130,7 @@ class ErrorRecovery(
|
|
|
130
130
|
}
|
|
131
131
|
|
|
132
132
|
private fun unregisterErrorHandler() {
|
|
133
|
-
if (
|
|
133
|
+
if (ReactNativeFeatureFlags.enableBridgelessArchitecture) {
|
|
134
134
|
unregisterErrorHandlerImplBridgeless()
|
|
135
135
|
} else {
|
|
136
136
|
unregisterErrorHandlerImplBridge()
|
|
@@ -152,7 +152,7 @@ class ErrorRecovery(
|
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
val devSupportManagerClass = devSupportManager.javaClass
|
|
155
|
-
devSupportManagerClass.getDeclaredField("
|
|
155
|
+
devSupportManagerClass.getDeclaredField("defaultJSExceptionHandler").let { field ->
|
|
156
156
|
field.isAccessible = true
|
|
157
157
|
field[devSupportManager] = previousExceptionHandler
|
|
158
158
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
package expo.modules.updates.events
|
|
2
2
|
|
|
3
|
-
import expo.modules.kotlin.events.EventEmitter
|
|
4
3
|
import expo.modules.updates.statemachine.UpdatesStateContext
|
|
4
|
+
import java.lang.ref.WeakReference
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
interface IUpdatesEventManagerObserver {
|
|
7
|
+
fun onStateMachineContextEvent(context: UpdatesStateContext)
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
interface IUpdatesEventManager {
|
|
11
|
-
var
|
|
11
|
+
var observer: WeakReference<IUpdatesEventManagerObserver>?
|
|
12
12
|
fun sendStateMachineContextEvent(context: UpdatesStateContext)
|
|
13
13
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
package expo.modules.updates.events
|
|
2
2
|
|
|
3
|
-
import expo.modules.kotlin.events.EventEmitter
|
|
4
3
|
import expo.modules.updates.statemachine.UpdatesStateContext
|
|
4
|
+
import java.lang.ref.WeakReference
|
|
5
5
|
|
|
6
6
|
class NoOpUpdatesEventManager : IUpdatesEventManager {
|
|
7
|
-
override var
|
|
7
|
+
override var observer: WeakReference<IUpdatesEventManagerObserver>? = null
|
|
8
8
|
override fun sendStateMachineContextEvent(context: UpdatesStateContext) {}
|
|
9
9
|
}
|
|
@@ -1,31 +1,27 @@
|
|
|
1
1
|
package expo.modules.updates.events
|
|
2
2
|
|
|
3
|
-
import expo.modules.kotlin.events.EventEmitter
|
|
4
3
|
import expo.modules.updates.logging.UpdatesErrorCode
|
|
5
4
|
import expo.modules.updates.logging.UpdatesLogger
|
|
6
5
|
import expo.modules.updates.statemachine.UpdatesStateContext
|
|
6
|
+
import java.lang.ref.WeakReference
|
|
7
7
|
|
|
8
8
|
class UpdatesEventManager(private val logger: UpdatesLogger) : IUpdatesEventManager {
|
|
9
|
-
override var
|
|
9
|
+
override var observer: WeakReference<IUpdatesEventManagerObserver>? = null
|
|
10
10
|
|
|
11
11
|
override fun sendStateMachineContextEvent(context: UpdatesStateContext) {
|
|
12
|
-
|
|
12
|
+
logger.debug("Sending state machine context to observer")
|
|
13
13
|
|
|
14
|
-
val
|
|
15
|
-
|
|
16
|
-
logger.info(
|
|
17
|
-
"Could not emit $eventName event; no event emitter was found.",
|
|
18
|
-
UpdatesErrorCode.JSRuntimeError
|
|
19
|
-
)
|
|
14
|
+
val observer = observer?.get() ?: run {
|
|
15
|
+
logger.debug("Unable to send state machine context to observer, no observer", UpdatesErrorCode.JSRuntimeError)
|
|
20
16
|
return
|
|
21
17
|
}
|
|
22
18
|
|
|
23
19
|
try {
|
|
24
|
-
|
|
25
|
-
logger.
|
|
20
|
+
observer.onStateMachineContextEvent(context)
|
|
21
|
+
logger.debug("Sent state machine context to observer")
|
|
26
22
|
} catch (e: Exception) {
|
|
27
23
|
logger.error(
|
|
28
|
-
"Could not
|
|
24
|
+
"Could not send state machine context to observer",
|
|
29
25
|
e,
|
|
30
26
|
UpdatesErrorCode.JSRuntimeError
|
|
31
27
|
)
|
|
@@ -141,7 +141,7 @@ class FileDownloader(
|
|
|
141
141
|
|
|
142
142
|
val isMultipart = responseBody.contentType()?.type == "multipart"
|
|
143
143
|
if (isMultipart) {
|
|
144
|
-
parseMultipartRemoteUpdateResponse(responseBody, responseHeaderData, callback)
|
|
144
|
+
parseMultipartRemoteUpdateResponse(response, responseBody, responseHeaderData, callback)
|
|
145
145
|
} else {
|
|
146
146
|
val manifestResponseInfo = ResponsePartInfo(
|
|
147
147
|
responseHeaderData = responseHeaderData,
|
|
@@ -174,38 +174,39 @@ class FileDownloader(
|
|
|
174
174
|
}
|
|
175
175
|
}
|
|
176
176
|
|
|
177
|
-
private fun parseMultipartRemoteUpdateResponse(responseBody: ResponseBody, responseHeaderData: ResponseHeaderData, callback: RemoteUpdateDownloadCallback) {
|
|
177
|
+
private fun parseMultipartRemoteUpdateResponse(response: Response, responseBody: ResponseBody, responseHeaderData: ResponseHeaderData, callback: RemoteUpdateDownloadCallback) {
|
|
178
178
|
var manifestPartBodyAndHeaders: Pair<String, Headers>? = null
|
|
179
179
|
var extensionsBody: String? = null
|
|
180
180
|
var certificateChainString: String? = null
|
|
181
181
|
var directivePartBodyAndHeaders: Pair<String, Headers>? = null
|
|
182
182
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
val
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
val
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
183
|
+
val isEmpty = response.peekBody(1).bytes().isEmpty()
|
|
184
|
+
if (!isEmpty) {
|
|
185
|
+
try {
|
|
186
|
+
MultipartReader(responseBody).use { reader ->
|
|
187
|
+
while (true) {
|
|
188
|
+
val nextPart = reader.nextPart() ?: break
|
|
189
|
+
nextPart.use { part ->
|
|
190
|
+
val headers = part.headers
|
|
191
|
+
val body = part.body
|
|
192
|
+
val contentDispositionValue = headers["content-disposition"]
|
|
193
|
+
if (contentDispositionValue != null) {
|
|
194
|
+
val contentDispositionName =
|
|
195
|
+
contentDispositionValue.parseContentDispositionNameParameter()
|
|
196
|
+
if (contentDispositionName != null) {
|
|
197
|
+
when (contentDispositionName) {
|
|
198
|
+
"manifest" -> manifestPartBodyAndHeaders = Pair(body.readUtf8(), headers)
|
|
199
|
+
"extensions" -> extensionsBody = body.readUtf8()
|
|
200
|
+
"certificate_chain" -> certificateChainString = body.readUtf8()
|
|
201
|
+
"directive" -> directivePartBodyAndHeaders = Pair(body.readUtf8(), headers)
|
|
202
|
+
}
|
|
200
203
|
}
|
|
201
204
|
}
|
|
202
205
|
}
|
|
203
206
|
}
|
|
204
207
|
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
// okhttp multipart reader doesn't support empty multipart bodies, but our spec does
|
|
208
|
-
if (responseBody.bytes().isNotEmpty()) {
|
|
208
|
+
} catch (e: Exception) {
|
|
209
|
+
// okhttp multipart reader doesn't support empty multipart bodies, but our spec does
|
|
209
210
|
val message = "Error while reading multipart remote update response"
|
|
210
211
|
logger.error(message, e, UpdatesErrorCode.UpdateFailedToLoad)
|
|
211
212
|
callback.onFailure(IOException(message, e))
|
|
@@ -575,7 +576,7 @@ class FileDownloader(
|
|
|
575
576
|
|
|
576
577
|
val update = UpdateFactory.getUpdate(preManifest, responseHeaderData, extensions, configuration)
|
|
577
578
|
if (!SelectionPolicies.matchesFilters(update.updateEntity!!, responseHeaderData.manifestFilters)) {
|
|
578
|
-
callback.onFailure(Exception("Manifest filters
|
|
579
|
+
callback.onFailure(Exception("Manifest filters do not match manifest content for downloaded manifest"))
|
|
579
580
|
} else {
|
|
580
581
|
callback.onSuccess(UpdateResponsePart.ManifestUpdateResponsePart(update))
|
|
581
582
|
}
|
|
@@ -294,56 +294,66 @@ class LoaderTask(
|
|
|
294
294
|
}
|
|
295
295
|
|
|
296
296
|
private fun launchFallbackUpdateFromDisk(diskUpdateCallback: LaunchUpdateCallback) {
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
297
|
+
AsyncTask.execute {
|
|
298
|
+
val database = databaseHolder.database
|
|
299
|
+
val launcher =
|
|
300
|
+
DatabaseLauncher(context, configuration, directory, fileDownloader, selectionPolicy, logger)
|
|
301
|
+
candidateLauncher = launcher
|
|
302
|
+
val launcherCallback: LauncherCallback = object : LauncherCallback {
|
|
303
|
+
override fun onFailure(e: Exception) {
|
|
304
|
+
databaseHolder.releaseDatabase()
|
|
305
|
+
diskUpdateCallback.onFailure(e)
|
|
306
|
+
}
|
|
305
307
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
308
|
+
override fun onSuccess() {
|
|
309
|
+
databaseHolder.releaseDatabase()
|
|
310
|
+
diskUpdateCallback.onSuccess()
|
|
311
|
+
}
|
|
309
312
|
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
313
|
+
if (configuration.hasEmbeddedUpdate) {
|
|
314
|
+
// if the embedded update should be launched (e.g. if it's newer than any other update we have
|
|
315
|
+
// in the database, which can happen if the app binary is updated), load it into the database
|
|
316
|
+
// so we can launch it
|
|
317
|
+
val embeddedUpdate =
|
|
318
|
+
EmbeddedManifestUtils.getEmbeddedUpdate(context, configuration)!!.updateEntity
|
|
319
|
+
val launchableUpdate = launcher.getLaunchableUpdate(database)
|
|
320
|
+
val manifestFilters = ManifestMetadata.getManifestFilters(database, configuration)
|
|
321
|
+
if (selectionPolicy.shouldLoadNewUpdate(
|
|
322
|
+
embeddedUpdate,
|
|
323
|
+
launchableUpdate,
|
|
324
|
+
manifestFilters
|
|
325
|
+
)
|
|
326
|
+
) {
|
|
327
|
+
EmbeddedLoader(context, configuration, logger, database, directory).start(object :
|
|
328
|
+
LoaderCallback {
|
|
329
|
+
override fun onFailure(e: Exception) {
|
|
330
|
+
logger.error("Unexpected error copying embedded update", e, UpdatesErrorCode.Unknown)
|
|
331
|
+
launcher.launch(database, launcherCallback)
|
|
332
|
+
}
|
|
324
333
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
334
|
+
override fun onSuccess(loaderResult: Loader.LoaderResult) {
|
|
335
|
+
launcher.launch(database, launcherCallback)
|
|
336
|
+
}
|
|
328
337
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
338
|
+
override fun onAssetLoaded(
|
|
339
|
+
asset: AssetEntity,
|
|
340
|
+
successfulAssetCount: Int,
|
|
341
|
+
failedAssetCount: Int,
|
|
342
|
+
totalAssetCount: Int
|
|
343
|
+
) {
|
|
344
|
+
// do nothing
|
|
345
|
+
}
|
|
337
346
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
347
|
+
override fun onUpdateResponseLoaded(updateResponse: UpdateResponse): Loader.OnUpdateResponseLoadedResult {
|
|
348
|
+
return Loader.OnUpdateResponseLoadedResult(shouldDownloadManifestIfPresentInResponse = true)
|
|
349
|
+
}
|
|
350
|
+
})
|
|
351
|
+
} else {
|
|
352
|
+
launcher.launch(database, launcherCallback)
|
|
353
|
+
}
|
|
342
354
|
} else {
|
|
343
355
|
launcher.launch(database, launcherCallback)
|
|
344
356
|
}
|
|
345
|
-
} else {
|
|
346
|
-
launcher.launch(database, launcherCallback)
|
|
347
357
|
}
|
|
348
358
|
}
|
|
349
359
|
|
|
@@ -439,33 +449,35 @@ class LoaderTask(
|
|
|
439
449
|
object : LauncherCallback {
|
|
440
450
|
override fun onFailure(e: Exception) {
|
|
441
451
|
databaseHolder.releaseDatabase()
|
|
452
|
+
callback.onRemoteUpdateFinished(
|
|
453
|
+
RemoteUpdateStatus.ERROR,
|
|
454
|
+
null,
|
|
455
|
+
e
|
|
456
|
+
)
|
|
442
457
|
remoteUpdateCallback.onFailure(e)
|
|
443
458
|
logger.error("Loaded new update but it failed to launch", e, UpdatesErrorCode.UpdateFailedToLoad)
|
|
444
459
|
}
|
|
445
460
|
|
|
446
461
|
override fun onSuccess() {
|
|
447
462
|
databaseHolder.releaseDatabase()
|
|
448
|
-
|
|
463
|
+
synchronized(this@LoaderTask) {
|
|
449
464
|
if (!hasLaunched) {
|
|
450
465
|
candidateLauncher = newLauncher
|
|
451
466
|
isUpToDate = true
|
|
452
467
|
}
|
|
453
|
-
hasLaunched
|
|
454
468
|
}
|
|
455
|
-
if (
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
)
|
|
468
|
-
}
|
|
469
|
+
if (availableUpdate == null) {
|
|
470
|
+
callback.onRemoteUpdateFinished(
|
|
471
|
+
RemoteUpdateStatus.NO_UPDATE_AVAILABLE,
|
|
472
|
+
null,
|
|
473
|
+
null
|
|
474
|
+
)
|
|
475
|
+
} else {
|
|
476
|
+
callback.onRemoteUpdateFinished(
|
|
477
|
+
RemoteUpdateStatus.UPDATE_AVAILABLE,
|
|
478
|
+
availableUpdate,
|
|
479
|
+
null
|
|
480
|
+
)
|
|
469
481
|
}
|
|
470
482
|
remoteUpdateCallback.onSuccess()
|
|
471
483
|
}
|
package/android/src/main/java/expo/modules/updates/procedures/RecreateReactContextProcedure.kt
CHANGED
|
@@ -27,7 +27,7 @@ class RecreateReactContextProcedure(
|
|
|
27
27
|
Handler(Looper.getMainLooper()).post {
|
|
28
28
|
reactApplication.restart(weakActivity?.get(), "Restart from RecreateReactContextProcedure")
|
|
29
29
|
}
|
|
30
|
-
procedureContext.
|
|
30
|
+
procedureContext.resetStateAfterRestart()
|
|
31
31
|
procedureContext.onComplete()
|
|
32
32
|
}
|
|
33
33
|
}
|
|
@@ -7,8 +7,8 @@ import android.os.Handler
|
|
|
7
7
|
import android.os.Looper
|
|
8
8
|
import com.facebook.react.ReactApplication
|
|
9
9
|
import com.facebook.react.bridge.JSBundleLoader
|
|
10
|
-
import com.facebook.react.config.ReactFeatureFlags
|
|
11
10
|
import expo.modules.core.interfaces.ReactNativeHostHandler
|
|
11
|
+
import expo.modules.rncompatibility.ReactNativeFeatureFlags
|
|
12
12
|
import expo.modules.updates.UpdatesConfiguration
|
|
13
13
|
import expo.modules.updates.db.DatabaseHolder
|
|
14
14
|
import expo.modules.updates.db.Reaper
|
|
@@ -83,7 +83,7 @@ class RelaunchProcedure(
|
|
|
83
83
|
if (shouldRunReaper) {
|
|
84
84
|
runReaper()
|
|
85
85
|
}
|
|
86
|
-
procedureContext.
|
|
86
|
+
procedureContext.resetStateAfterRestart()
|
|
87
87
|
procedureContext.onComplete()
|
|
88
88
|
}
|
|
89
89
|
}
|
|
@@ -118,7 +118,7 @@ class RelaunchProcedure(
|
|
|
118
118
|
reactApplication: ReactApplication,
|
|
119
119
|
launchAssetFile: String
|
|
120
120
|
) {
|
|
121
|
-
if (
|
|
121
|
+
if (ReactNativeFeatureFlags.enableBridgelessArchitecture) {
|
|
122
122
|
return
|
|
123
123
|
}
|
|
124
124
|
|
|
@@ -3,7 +3,7 @@ package expo.modules.updates.procedures
|
|
|
3
3
|
import android.app.Activity
|
|
4
4
|
import com.facebook.react.ReactApplication
|
|
5
5
|
import com.facebook.react.common.LifecycleState
|
|
6
|
-
import
|
|
6
|
+
import expo.modules.rncompatibility.ReactNativeFeatureFlags
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* An extension for [ReactApplication] to restart the app
|
|
@@ -12,7 +12,7 @@ import com.facebook.react.config.ReactFeatureFlags
|
|
|
12
12
|
* @param reason The restart reason. Only used on bridgeless mode.
|
|
13
13
|
*/
|
|
14
14
|
internal fun ReactApplication.restart(activity: Activity?, reason: String) {
|
|
15
|
-
if (
|
|
15
|
+
if (ReactNativeFeatureFlags.enableBridgelessArchitecture) {
|
|
16
16
|
val reactHost = this.reactHost
|
|
17
17
|
check(reactHost != null)
|
|
18
18
|
if (reactHost.lifecycleState != LifecycleState.RESUMED && activity != null) {
|
|
@@ -102,6 +102,7 @@ class StartupProcedure(
|
|
|
102
102
|
}
|
|
103
103
|
|
|
104
104
|
override fun onFinishedAllLoading() {
|
|
105
|
+
procedureContext.processStateEvent(UpdatesStateEvent.EndStartup())
|
|
105
106
|
procedureContext.onComplete()
|
|
106
107
|
}
|
|
107
108
|
|
|
@@ -208,6 +209,7 @@ class StartupProcedure(
|
|
|
208
209
|
|
|
209
210
|
override fun run(procedureContext: ProcedureContext) {
|
|
210
211
|
this.procedureContext = procedureContext
|
|
212
|
+
procedureContext.processStateEvent(UpdatesStateEvent.StartStartup())
|
|
211
213
|
initializeDatabaseHandler()
|
|
212
214
|
initializeErrorRecovery()
|
|
213
215
|
loaderTask.start()
|