expo-updates 0.18.10 → 0.19.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/CHANGELOG.md +32 -5
- package/android/build.gradle +30 -5
- package/android/src/main/java/expo/modules/updates/UpdatesModule.kt +152 -73
- package/android/src/main/java/expo/modules/updates/db/dao/UpdateDao.kt +22 -9
- package/android/src/main/java/expo/modules/updates/loader/LoaderTask.kt +10 -73
- package/android/src/main/java/expo/modules/updates/loader/RemoteLoader.kt +92 -0
- package/android/src/main/java/expo/modules/updates/statemachine/UpdatesStateContext.kt +54 -25
- package/android/src/main/java/expo/modules/updates/statemachine/UpdatesStateMachine.kt +9 -4
- package/build/Updates.d.ts +3 -12
- package/build/Updates.d.ts.map +1 -1
- package/build/Updates.js +19 -34
- package/build/Updates.js.map +1 -1
- package/build/Updates.types.d.ts +22 -0
- package/build/Updates.types.d.ts.map +1 -1
- package/build/Updates.types.js.map +1 -1
- package/build/UpdatesEmitter.d.ts +22 -0
- package/build/UpdatesEmitter.d.ts.map +1 -0
- package/build/UpdatesEmitter.js +80 -0
- package/build/UpdatesEmitter.js.map +1 -0
- package/build/UpdatesHooks.d.ts.map +1 -1
- package/build/UpdatesHooks.js +2 -2
- package/build/UpdatesHooks.js.map +1 -1
- package/build/UseUpdates.d.ts +52 -0
- package/build/UseUpdates.d.ts.map +1 -0
- package/build/UseUpdates.js +77 -0
- package/build/UseUpdates.js.map +1 -0
- package/build/UseUpdates.types.d.ts +149 -0
- package/build/UseUpdates.types.d.ts.map +1 -0
- package/build/UseUpdates.types.js +14 -0
- package/build/UseUpdates.types.js.map +1 -0
- package/build/UseUpdatesUtils.d.ts +19 -0
- package/build/UseUpdatesUtils.d.ts.map +1 -0
- package/build/UseUpdatesUtils.js +56 -0
- package/build/UseUpdatesUtils.js.map +1 -0
- package/build/index.d.ts +4 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +4 -0
- package/build/index.js.map +1 -1
- package/e2e/fixtures/App-apitest.tsx +97 -75
- package/e2e/fixtures/App.tsx +83 -28
- package/e2e/fixtures/Updates.e2e.ts +82 -51
- package/e2e/fixtures/project_files/e2e/tests/utils/update.ts +6 -2
- package/e2e/fixtures/project_files/eas-hooks/eas-build-pre-install.sh +3 -0
- package/e2e/fixtures/project_files/xcode.env.local +4 -0
- package/e2e/setup/project.js +1 -10
- package/ios/EXUpdates/AppController.swift +32 -18
- package/ios/EXUpdates/AppLoader/AppLoaderTask.swift +60 -78
- package/ios/EXUpdates/AppLoader/FileDownloader.swift +1 -4
- package/ios/EXUpdates/AppLoader/RemoteAppLoader.swift +105 -0
- package/ios/EXUpdates/Database/UpdatesDatabase.swift +1 -1
- package/ios/EXUpdates/DevLauncherController.swift +2 -2
- package/ios/EXUpdates/Exceptions.swift +0 -6
- package/ios/EXUpdates/SelectionPolicy/SelectionPolicies.swift +1 -2
- package/ios/EXUpdates/Update/BareUpdate.swift +1 -1
- package/ios/EXUpdates/Update/Update.swift +2 -2
- package/ios/EXUpdates/UpdatesModule.swift +23 -1
- package/ios/EXUpdates/UpdatesStateMachine.swift +41 -20
- package/ios/EXUpdates/UpdatesUtils.swift +91 -39
- package/ios/Tests/FileDownloaderManifestParsingSpec.swift +5 -5
- package/package.json +7 -7
- package/src/Updates.ts +20 -45
- package/src/Updates.types.ts +27 -0
- package/src/UpdatesEmitter.ts +97 -0
- package/src/UpdatesHooks.ts +2 -2
- package/src/UseUpdates.ts +86 -0
- package/src/UseUpdates.types.ts +152 -0
- package/src/UseUpdatesUtils.ts +79 -0
- package/src/index.ts +4 -0
package/CHANGELOG.md
CHANGED
|
@@ -10,24 +10,50 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
-
## 0.
|
|
13
|
+
## 0.19.0 — 2023-07-28
|
|
14
|
+
|
|
15
|
+
### 🎉 New features
|
|
16
|
+
|
|
17
|
+
- New useUpdates() JS API. ([#23532](https://github.com/expo/expo/pull/23532) by [@douglowder](https://github.com/douglowder))
|
|
18
|
+
|
|
19
|
+
### 🐛 Bug fixes
|
|
20
|
+
|
|
21
|
+
- [Android] Fix rollback embedded update logic. ([#23244](https://github.com/expo/expo/pull/23244) by [@wschurman](https://github.com/wschurman))
|
|
22
|
+
- Correctly handle roll backs in JS module methods. ([#23356](https://github.com/expo/expo/pull/23356), [#23377](https://github.com/expo/expo/pull/23377) by [@wschurman](https://github.com/wschurman))
|
|
23
|
+
- [iOS] Fix unmatched selection policy. ([#23535](https://github.com/expo/expo/pull/23535) by [@chochihim](https://github.com/chochihim))
|
|
24
|
+
- Handle initialization errors in useUpdates(). ([#23640](https://github.com/expo/expo/pull/23640) by [@douglowder](https://github.com/douglowder))
|
|
25
|
+
- [iOS] Fix error handling on iOS during startup check for updates. ([#23663](https://github.com/expo/expo/pull/23663) by [@douglowder](https://github.com/douglowder))
|
|
26
|
+
- Last check dateTime should come from native. ([#23692](https://github.com/expo/expo/pull/23692) by [@douglowder](https://github.com/douglowder))
|
|
27
|
+
|
|
28
|
+
### 💡 Others
|
|
29
|
+
|
|
30
|
+
- Native getter for state machine context. ([#23428](https://github.com/expo/expo/pull/23428) by [@douglowder](https://github.com/douglowder))
|
|
31
|
+
- [iOS] Fix template for EX_UPDATES_NATIVE_DEBUG. ([#23602](https://github.com/expo/expo/pull/23602) by [@douglowder](https://github.com/douglowder))
|
|
32
|
+
|
|
33
|
+
## 0.18.11 - 2023-07-23
|
|
34
|
+
|
|
35
|
+
### 💡 Others
|
|
36
|
+
|
|
37
|
+
- [Android] EX_UPDATES_ANDROID_DELAY_LOAD_APP settable by env. ([#23479](https://github.com/expo/expo/pull/23479) by [@douglowder](https://github.com/douglowder))
|
|
38
|
+
|
|
39
|
+
## 0.18.10 - 2023-07-12
|
|
14
40
|
|
|
15
41
|
### 🐛 Bug fixes
|
|
16
42
|
|
|
17
43
|
- [CLI] Add missing chalk dependency for the `expo-updates` cli. ([#23429](https://github.com/expo/expo/pull/23429) by [@byCedric](https://github.com/byCedric))
|
|
18
44
|
- [CLI] Drop `fs-extra` in favor of `fs`. ([#23431](https://github.com/expo/expo/pull/23431) by [@byCedric](https://github.com/byCedric))
|
|
19
45
|
|
|
20
|
-
## 0.18.9
|
|
46
|
+
## 0.18.9 - 2023-07-10
|
|
21
47
|
|
|
22
48
|
### 🐛 Bug fixes
|
|
23
49
|
|
|
24
50
|
- [ios] Allow nil scopeKey for bare/embedded updates. ([#23385](https://github.com/expo/expo/pull/23385) by [@wschurman](https://github.com/wschurman))
|
|
25
51
|
|
|
26
|
-
## 0.18.8
|
|
52
|
+
## 0.18.8 - 2023-07-04
|
|
27
53
|
|
|
28
54
|
_This version does not introduce any user-facing changes._
|
|
29
55
|
|
|
30
|
-
## 0.18.7
|
|
56
|
+
## 0.18.7 - 2023-06-30
|
|
31
57
|
|
|
32
58
|
### 🐛 Bug fixes
|
|
33
59
|
|
|
@@ -35,7 +61,7 @@ _This version does not introduce any user-facing changes._
|
|
|
35
61
|
- [iOS] Fix response header casing bug. ([#23234](https://github.com/expo/expo/pull/23234) by [@wschurman](https://github.com/wschurman))
|
|
36
62
|
- Fix tsconfig paths and other SDK 49 Metro features. ([#23276](https://github.com/expo/expo/pull/23276) by [@EvanBacon](https://github.com/EvanBacon))
|
|
37
63
|
|
|
38
|
-
## 0.18.6
|
|
64
|
+
## 0.18.6 - 2023-06-29
|
|
39
65
|
|
|
40
66
|
### 🐛 Bug fixes
|
|
41
67
|
|
|
@@ -53,6 +79,7 @@ _This version does not introduce any user-facing changes._
|
|
|
53
79
|
|
|
54
80
|
- [iOS] Use weak delegate for state machine. ([#23060](https://github.com/expo/expo/pull/23060) by [@wschurman](https://github.com/wschurman))
|
|
55
81
|
- [Android] Convert LoaderTask.RemoteCheckResult to sealed class. ([#23061](https://github.com/expo/expo/pull/23061) by [@wschurman](https://github.com/wschurman))
|
|
82
|
+
- [iOS] Use swift enum for AppLoaderTask delegate. ([#23064](https://github.com/expo/expo/pull/23064) by [@wschurman](https://github.com/wschurman))
|
|
56
83
|
|
|
57
84
|
## 0.18.3 — 2023-06-24
|
|
58
85
|
|
package/android/build.gradle
CHANGED
|
@@ -4,9 +4,34 @@ apply plugin: 'kotlin-kapt'
|
|
|
4
4
|
apply plugin: 'maven-publish'
|
|
5
5
|
|
|
6
6
|
group = 'host.exp.exponent'
|
|
7
|
-
version = '0.
|
|
7
|
+
version = '0.19.0'
|
|
8
|
+
|
|
9
|
+
// Utility method to derive boolean values from the environment or from Java properties,
|
|
10
|
+
// and return them as strings to be used in BuildConfig fields
|
|
11
|
+
def getBoolStringFromPropOrEnv(String name, Boolean defaultValue) {
|
|
12
|
+
def env_value = System.getenv(name)
|
|
13
|
+
def prop_value = findProperty(name)
|
|
14
|
+
def value = defaultValue.toString()
|
|
15
|
+
// If present, property value in gradle.properties overrides default
|
|
16
|
+
if (prop_value != null) {
|
|
17
|
+
value = boolish(prop_value).toString()
|
|
18
|
+
println("expo-updates: Value of ${name} was overridden by property, new value = ${value}")
|
|
19
|
+
}
|
|
20
|
+
// If present, env value overrides default and gradle.properties
|
|
21
|
+
if (env_value != null) {
|
|
22
|
+
value = boolish(env_value).toString()
|
|
23
|
+
println("expo-updates: Value of ${name} was overridden by environment, new value = ${value}")
|
|
24
|
+
}
|
|
25
|
+
return value
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// If true, app will use bundled manifest and updates will be enabled, even for
|
|
29
|
+
// debug builds. (default false)
|
|
30
|
+
def exUpdatesNativeDebug = getBoolStringFromPropOrEnv("EX_UPDATES_NATIVE_DEBUG", false)
|
|
8
31
|
|
|
9
|
-
|
|
32
|
+
// If true, code will run that delays app loading until updates is initialized, to prevent ANR issues.
|
|
33
|
+
// (default true)
|
|
34
|
+
def exUpdatesAndroidDelayLoadApp = getBoolStringFromPropOrEnv("EX_UPDATES_ANDROID_DELAY_LOAD_APP", true)
|
|
10
35
|
|
|
11
36
|
buildscript {
|
|
12
37
|
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
|
|
@@ -70,12 +95,12 @@ android {
|
|
|
70
95
|
minSdkVersion safeExtGet("minSdkVersion", 21)
|
|
71
96
|
targetSdkVersion safeExtGet("targetSdkVersion", 33)
|
|
72
97
|
versionCode 31
|
|
73
|
-
versionName '0.
|
|
98
|
+
versionName '0.19.0'
|
|
74
99
|
consumerProguardFiles("proguard-rules.pro")
|
|
75
100
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
76
101
|
|
|
77
|
-
buildConfigField("boolean", "EX_UPDATES_NATIVE_DEBUG",
|
|
78
|
-
buildConfigField("boolean", "EX_UPDATES_ANDROID_DELAY_LOAD_APP",
|
|
102
|
+
buildConfigField("boolean", "EX_UPDATES_NATIVE_DEBUG", exUpdatesNativeDebug)
|
|
103
|
+
buildConfigField("boolean", "EX_UPDATES_ANDROID_DELAY_LOAD_APP", exUpdatesAndroidDelayLoadApp)
|
|
79
104
|
|
|
80
105
|
// uncomment below to export the database schema when making changes
|
|
81
106
|
/* javaCompileOptions {
|
|
@@ -19,12 +19,16 @@ import expo.modules.updates.logging.UpdatesLogEntry
|
|
|
19
19
|
import expo.modules.updates.logging.UpdatesLogReader
|
|
20
20
|
import expo.modules.updates.logging.UpdatesLogger
|
|
21
21
|
import expo.modules.updates.manifest.ManifestMetadata
|
|
22
|
+
import expo.modules.updates.statemachine.UpdatesStateContext
|
|
22
23
|
import expo.modules.updates.statemachine.UpdatesStateEvent
|
|
23
24
|
import java.util.Date
|
|
25
|
+
import expo.modules.updates.manifest.EmbeddedManifest
|
|
26
|
+
import expo.modules.updates.manifest.UpdateManifest
|
|
24
27
|
|
|
25
28
|
// these unused imports must stay because of versioning
|
|
26
29
|
/* ktlint-disable no-unused-imports */
|
|
27
30
|
import expo.modules.updates.UpdatesConfiguration
|
|
31
|
+
|
|
28
32
|
/* ktlint-enable no-unused-imports */
|
|
29
33
|
|
|
30
34
|
/**
|
|
@@ -134,6 +138,28 @@ class UpdatesModule(
|
|
|
134
138
|
}
|
|
135
139
|
}
|
|
136
140
|
|
|
141
|
+
// Used internally by @expo/use-updates useUpdates() to get its initial state
|
|
142
|
+
@ExpoMethod
|
|
143
|
+
fun getNativeStateMachineContextAsync(promise: Promise) {
|
|
144
|
+
try {
|
|
145
|
+
val updatesServiceLocal = updatesService
|
|
146
|
+
if (!updatesServiceLocal!!.configuration.isEnabled) {
|
|
147
|
+
promise.reject(
|
|
148
|
+
"ERR_UPDATES_DISABLED",
|
|
149
|
+
"You cannot check for updates when expo-updates is not enabled."
|
|
150
|
+
)
|
|
151
|
+
return
|
|
152
|
+
}
|
|
153
|
+
val context = updatesServiceLocal.stateMachine?.context ?: UpdatesStateContext()
|
|
154
|
+
promise.resolve(context.bundle)
|
|
155
|
+
} catch (e: IllegalStateException) {
|
|
156
|
+
promise.reject(
|
|
157
|
+
"ERR_UPDATES_CHECK",
|
|
158
|
+
"The updates module controller has not been properly initialized. If you're using a development client, you cannot check for updates. Otherwise, make sure you have called the native method UpdatesController.initialize()."
|
|
159
|
+
)
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
137
163
|
@ExpoMethod
|
|
138
164
|
fun checkForUpdateAsync(promise: Promise) {
|
|
139
165
|
try {
|
|
@@ -169,42 +195,46 @@ class UpdatesModule(
|
|
|
169
195
|
val updateDirective = updateResponse.directiveUpdateResponsePart?.updateDirective
|
|
170
196
|
val updateManifest = updateResponse.manifestUpdateResponsePart?.updateManifest
|
|
171
197
|
|
|
172
|
-
val
|
|
198
|
+
val launchedUpdate = updatesServiceLocal.launchedUpdate
|
|
199
|
+
|
|
173
200
|
if (updateDirective != null) {
|
|
174
201
|
if (updateDirective is UpdateDirective.RollBackToEmbeddedUpdateDirective) {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
)
|
|
202
|
+
if (!updatesServiceLocal.configuration.hasEmbeddedUpdate) {
|
|
203
|
+
promise.resolveWithCheckForUpdateAsyncResult(CheckForUpdateAsyncResult.NoUpdateAvailable(), updatesServiceLocal)
|
|
204
|
+
return
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
val embeddedUpdate = EmbeddedManifest.get(context, updatesServiceLocal.configuration)!!.updateEntity
|
|
208
|
+
if (embeddedUpdate == null) {
|
|
209
|
+
promise.resolveWithCheckForUpdateAsyncResult(CheckForUpdateAsyncResult.NoUpdateAvailable(), updatesServiceLocal)
|
|
210
|
+
return
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if (!updatesServiceLocal.selectionPolicy.shouldLoadRollBackToEmbeddedDirective(
|
|
214
|
+
updateDirective,
|
|
215
|
+
embeddedUpdate,
|
|
216
|
+
launchedUpdate,
|
|
217
|
+
updateResponse.responseHeaderData?.manifestFilters
|
|
218
|
+
)
|
|
219
|
+
) {
|
|
220
|
+
promise.resolveWithCheckForUpdateAsyncResult(CheckForUpdateAsyncResult.NoUpdateAvailable(), updatesServiceLocal)
|
|
221
|
+
return
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
promise.resolveWithCheckForUpdateAsyncResult(CheckForUpdateAsyncResult.RollBackToEmbedded(), updatesServiceLocal)
|
|
181
225
|
return
|
|
182
226
|
}
|
|
183
227
|
}
|
|
184
228
|
|
|
185
229
|
if (updateManifest == null) {
|
|
186
|
-
|
|
187
|
-
updateInfo.putBoolean("isAvailable", false)
|
|
188
|
-
promise.resolve(updateInfo)
|
|
189
|
-
updatesServiceLocal.stateMachine?.processEvent(
|
|
190
|
-
UpdatesStateEvent.CheckCompleteUnavailable()
|
|
191
|
-
)
|
|
230
|
+
promise.resolveWithCheckForUpdateAsyncResult(CheckForUpdateAsyncResult.NoUpdateAvailable(), updatesServiceLocal)
|
|
192
231
|
return
|
|
193
232
|
}
|
|
194
233
|
|
|
195
|
-
val launchedUpdate = updatesServiceLocal.launchedUpdate
|
|
196
234
|
if (launchedUpdate == null) {
|
|
197
235
|
// this shouldn't ever happen, but if we don't have anything to compare
|
|
198
236
|
// the new manifest to, let the user know an update is available
|
|
199
|
-
|
|
200
|
-
updateInfo.putBoolean("isAvailable", true)
|
|
201
|
-
updateInfo.putString("manifestString", updateManifest.manifest.toString())
|
|
202
|
-
promise.resolve(updateInfo)
|
|
203
|
-
updatesServiceLocal.stateMachine?.processEvent(
|
|
204
|
-
UpdatesStateEvent.CheckCompleteWithUpdate(
|
|
205
|
-
updateManifest.manifest.getRawJson()
|
|
206
|
-
)
|
|
207
|
-
)
|
|
237
|
+
promise.resolveWithCheckForUpdateAsyncResult(CheckForUpdateAsyncResult.UpdateAvailable(updateManifest), updatesServiceLocal)
|
|
208
238
|
return
|
|
209
239
|
}
|
|
210
240
|
|
|
@@ -214,22 +244,9 @@ class UpdatesModule(
|
|
|
214
244
|
updateResponse.responseHeaderData?.manifestFilters
|
|
215
245
|
)
|
|
216
246
|
) {
|
|
217
|
-
|
|
218
|
-
updateInfo.putBoolean("isAvailable", true)
|
|
219
|
-
updateInfo.putString("manifestString", updateManifest.manifest.toString())
|
|
220
|
-
promise.resolve(updateInfo)
|
|
221
|
-
updatesServiceLocal.stateMachine?.processEvent(
|
|
222
|
-
UpdatesStateEvent.CheckCompleteWithUpdate(
|
|
223
|
-
updateManifest.manifest.getRawJson()
|
|
224
|
-
)
|
|
225
|
-
)
|
|
247
|
+
promise.resolveWithCheckForUpdateAsyncResult(CheckForUpdateAsyncResult.UpdateAvailable(updateManifest), updatesServiceLocal)
|
|
226
248
|
} else {
|
|
227
|
-
|
|
228
|
-
updateInfo.putBoolean("isAvailable", false)
|
|
229
|
-
promise.resolve(updateInfo)
|
|
230
|
-
updatesServiceLocal.stateMachine?.processEvent(
|
|
231
|
-
UpdatesStateEvent.CheckCompleteUnavailable()
|
|
232
|
-
)
|
|
249
|
+
promise.resolveWithCheckForUpdateAsyncResult(CheckForUpdateAsyncResult.NoUpdateAvailable(), updatesServiceLocal)
|
|
233
250
|
}
|
|
234
251
|
}
|
|
235
252
|
}
|
|
@@ -243,6 +260,51 @@ class UpdatesModule(
|
|
|
243
260
|
}
|
|
244
261
|
}
|
|
245
262
|
|
|
263
|
+
private sealed class CheckForUpdateAsyncResult(private val status: Status) {
|
|
264
|
+
private enum class Status {
|
|
265
|
+
NO_UPDATE_AVAILABLE,
|
|
266
|
+
UPDATE_AVAILABLE,
|
|
267
|
+
ROLL_BACK_TO_EMBEDDED
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
class NoUpdateAvailable : CheckForUpdateAsyncResult(Status.NO_UPDATE_AVAILABLE)
|
|
271
|
+
class UpdateAvailable(val updateManifest: UpdateManifest) : CheckForUpdateAsyncResult(Status.UPDATE_AVAILABLE)
|
|
272
|
+
class RollBackToEmbedded : CheckForUpdateAsyncResult(Status.ROLL_BACK_TO_EMBEDDED)
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
private fun Promise.resolveWithCheckForUpdateAsyncResult(checkForUpdateAsyncResult: CheckForUpdateAsyncResult, updatesServiceLocal: UpdatesInterface) {
|
|
276
|
+
resolve(
|
|
277
|
+
Bundle().apply {
|
|
278
|
+
when (checkForUpdateAsyncResult) {
|
|
279
|
+
is CheckForUpdateAsyncResult.NoUpdateAvailable -> {
|
|
280
|
+
putBoolean("isRollBackToEmbedded", false)
|
|
281
|
+
putBoolean("isAvailable", false)
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
is CheckForUpdateAsyncResult.RollBackToEmbedded -> {
|
|
285
|
+
putBoolean("isRollBackToEmbedded", true)
|
|
286
|
+
putBoolean("isAvailable", false)
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
is CheckForUpdateAsyncResult.UpdateAvailable -> {
|
|
290
|
+
putBoolean("isRollBackToEmbedded", false)
|
|
291
|
+
putBoolean("isAvailable", true)
|
|
292
|
+
putString("manifestString", checkForUpdateAsyncResult.updateManifest.manifest.toString())
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
)
|
|
297
|
+
updatesServiceLocal.stateMachine?.processEvent(
|
|
298
|
+
when (checkForUpdateAsyncResult) {
|
|
299
|
+
is CheckForUpdateAsyncResult.NoUpdateAvailable -> UpdatesStateEvent.CheckCompleteUnavailable()
|
|
300
|
+
is CheckForUpdateAsyncResult.RollBackToEmbedded -> UpdatesStateEvent.CheckCompleteWithRollback()
|
|
301
|
+
is CheckForUpdateAsyncResult.UpdateAvailable -> UpdatesStateEvent.CheckCompleteWithUpdate(
|
|
302
|
+
checkForUpdateAsyncResult.updateManifest.manifest.getRawJson()
|
|
303
|
+
)
|
|
304
|
+
}
|
|
305
|
+
)
|
|
306
|
+
}
|
|
307
|
+
|
|
246
308
|
@ExpoMethod
|
|
247
309
|
fun fetchUpdateAsync(promise: Promise) {
|
|
248
310
|
try {
|
|
@@ -257,10 +319,11 @@ class UpdatesModule(
|
|
|
257
319
|
updatesServiceLocal.stateMachine?.processEvent(UpdatesStateEvent.Download())
|
|
258
320
|
AsyncTask.execute {
|
|
259
321
|
val databaseHolder = updatesServiceLocal.databaseHolder
|
|
322
|
+
val database = databaseHolder.database
|
|
260
323
|
RemoteLoader(
|
|
261
324
|
context,
|
|
262
325
|
updatesServiceLocal.configuration,
|
|
263
|
-
|
|
326
|
+
database,
|
|
264
327
|
updatesServiceLocal.fileDownloader,
|
|
265
328
|
updatesServiceLocal.directory,
|
|
266
329
|
updatesServiceLocal.launchedUpdate
|
|
@@ -294,7 +357,8 @@ class UpdatesModule(
|
|
|
294
357
|
)
|
|
295
358
|
}
|
|
296
359
|
|
|
297
|
-
val updateManifest = updateResponse.manifestUpdateResponsePart?.updateManifest
|
|
360
|
+
val updateManifest = updateResponse.manifestUpdateResponsePart?.updateManifest
|
|
361
|
+
?: return Loader.OnUpdateResponseLoadedResult(shouldDownloadManifestIfPresentInResponse = false)
|
|
298
362
|
|
|
299
363
|
return Loader.OnUpdateResponseLoadedResult(
|
|
300
364
|
shouldDownloadManifestIfPresentInResponse = updatesServiceLocal.selectionPolicy.shouldLoadNewUpdate(
|
|
@@ -306,44 +370,59 @@ class UpdatesModule(
|
|
|
306
370
|
}
|
|
307
371
|
|
|
308
372
|
override fun onSuccess(loaderResult: Loader.LoaderResult) {
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
)
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
)
|
|
327
|
-
} else {
|
|
328
|
-
updatesServiceLocal.resetSelectionPolicy()
|
|
329
|
-
updateInfo.putBoolean("isNew", true)
|
|
330
|
-
|
|
331
|
-
// We need the explicit casting here because when in versioned expo-updates,
|
|
332
|
-
// the UpdateEntity and UpdatesModule are in different package namespace,
|
|
333
|
-
// Kotlin cannot do the smart casting for that case.
|
|
334
|
-
val updateEntity = loaderResult.updateEntity as UpdateEntity
|
|
335
|
-
|
|
336
|
-
updateInfo.putString(
|
|
337
|
-
"manifestString",
|
|
338
|
-
updateEntity.manifest.toString()
|
|
373
|
+
RemoteLoader.processSuccessLoaderResult(
|
|
374
|
+
context,
|
|
375
|
+
updatesServiceLocal.configuration,
|
|
376
|
+
database,
|
|
377
|
+
updatesServiceLocal.selectionPolicy,
|
|
378
|
+
updatesServiceLocal.directory,
|
|
379
|
+
updatesServiceLocal.launchedUpdate,
|
|
380
|
+
loaderResult
|
|
381
|
+
) { availableUpdate, didRollBackToEmbedded ->
|
|
382
|
+
databaseHolder.releaseDatabase()
|
|
383
|
+
|
|
384
|
+
if (didRollBackToEmbedded) {
|
|
385
|
+
promise.resolve(
|
|
386
|
+
Bundle().apply {
|
|
387
|
+
putBoolean("isRollBackToEmbedded", true)
|
|
388
|
+
putBoolean("isNew", false)
|
|
389
|
+
}
|
|
339
390
|
)
|
|
340
391
|
updatesServiceLocal.stateMachine?.processEvent(
|
|
341
|
-
UpdatesStateEvent.
|
|
392
|
+
UpdatesStateEvent.DownloadCompleteWithRollback()
|
|
342
393
|
)
|
|
394
|
+
} else {
|
|
395
|
+
if (availableUpdate == null) {
|
|
396
|
+
promise.resolve(
|
|
397
|
+
Bundle().apply {
|
|
398
|
+
putBoolean("isRollBackToEmbedded", false)
|
|
399
|
+
putBoolean("isNew", false)
|
|
400
|
+
}
|
|
401
|
+
)
|
|
402
|
+
updatesServiceLocal.stateMachine?.processEvent(
|
|
403
|
+
UpdatesStateEvent.DownloadComplete()
|
|
404
|
+
)
|
|
405
|
+
} else {
|
|
406
|
+
updatesServiceLocal.resetSelectionPolicy()
|
|
407
|
+
|
|
408
|
+
// We need the explicit casting here because when in versioned expo-updates,
|
|
409
|
+
// the UpdateEntity and UpdatesModule are in different package namespace,
|
|
410
|
+
// Kotlin cannot do the smart casting for that case.
|
|
411
|
+
val updateEntity = loaderResult.updateEntity as UpdateEntity
|
|
412
|
+
|
|
413
|
+
promise.resolve(
|
|
414
|
+
Bundle().apply {
|
|
415
|
+
putBoolean("isRollBackToEmbedded", false)
|
|
416
|
+
putBoolean("isNew", true)
|
|
417
|
+
putString("manifestString", updateEntity.manifest.toString())
|
|
418
|
+
}
|
|
419
|
+
)
|
|
420
|
+
updatesServiceLocal.stateMachine?.processEvent(
|
|
421
|
+
UpdatesStateEvent.DownloadCompleteWithUpdate(updateEntity.manifest!!)
|
|
422
|
+
)
|
|
423
|
+
}
|
|
343
424
|
}
|
|
344
425
|
}
|
|
345
|
-
|
|
346
|
-
promise.resolve(updateInfo)
|
|
347
426
|
}
|
|
348
427
|
}
|
|
349
428
|
)
|
|
@@ -34,9 +34,6 @@ abstract class UpdateDao {
|
|
|
34
34
|
@Query("UPDATE updates SET status = :status WHERE id = :id;")
|
|
35
35
|
abstract fun _markUpdateWithStatus(status: UpdateStatus, id: UUID)
|
|
36
36
|
|
|
37
|
-
@Update
|
|
38
|
-
abstract fun _updateUpdate(update: UpdateEntity)
|
|
39
|
-
|
|
40
37
|
@Query(
|
|
41
38
|
"UPDATE updates SET status = :status WHERE id IN (" +
|
|
42
39
|
"SELECT DISTINCT update_id FROM updates_assets WHERE asset_id IN (:missingAssetIds));"
|
|
@@ -78,14 +75,20 @@ abstract class UpdateDao {
|
|
|
78
75
|
|
|
79
76
|
fun setUpdateScopeKey(update: UpdateEntity, newScopeKey: String) {
|
|
80
77
|
update.scopeKey = newScopeKey
|
|
81
|
-
|
|
78
|
+
_setUpdateScopeKeyInternal(update.id, newScopeKey)
|
|
82
79
|
}
|
|
83
80
|
|
|
81
|
+
@Query("UPDATE updates SET scope_key = :newScopeKey WHERE id = :id;")
|
|
82
|
+
abstract fun _setUpdateScopeKeyInternal(id: UUID, newScopeKey: String)
|
|
83
|
+
|
|
84
84
|
fun setUpdateCommitTime(update: UpdateEntity, commitTime: Date) {
|
|
85
85
|
update.commitTime = commitTime
|
|
86
|
-
|
|
86
|
+
_setUpdateCommitTime(update.id, commitTime)
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
+
@Query("UPDATE updates SET commit_time = :commitTime WHERE id = :id;")
|
|
90
|
+
abstract fun _setUpdateCommitTime(id: UUID, commitTime: Date)
|
|
91
|
+
|
|
89
92
|
@Transaction
|
|
90
93
|
open fun markUpdateFinished(update: UpdateEntity, hasSkippedEmbeddedAssets: Boolean) {
|
|
91
94
|
var statusToMark = UpdateStatus.READY
|
|
@@ -103,20 +106,30 @@ abstract class UpdateDao {
|
|
|
103
106
|
}
|
|
104
107
|
|
|
105
108
|
fun markUpdateAccessed(update: UpdateEntity) {
|
|
106
|
-
|
|
107
|
-
|
|
109
|
+
val newLastAccessed = Date()
|
|
110
|
+
update.lastAccessed = newLastAccessed
|
|
111
|
+
_markUpdateAccessed(update.id, newLastAccessed)
|
|
108
112
|
}
|
|
109
113
|
|
|
114
|
+
@Query("UPDATE updates SET last_accessed = :lastAccessed WHERE id = :id;")
|
|
115
|
+
abstract fun _markUpdateAccessed(id: UUID, lastAccessed: Date)
|
|
116
|
+
|
|
110
117
|
fun incrementSuccessfulLaunchCount(update: UpdateEntity) {
|
|
111
118
|
update.successfulLaunchCount++
|
|
112
|
-
|
|
119
|
+
_incrementSuccessfulLaunchCount(update.id)
|
|
113
120
|
}
|
|
114
121
|
|
|
122
|
+
@Query("UPDATE updates SET successful_launch_count = successful_launch_count + 1 WHERE id = :id;")
|
|
123
|
+
abstract fun _incrementSuccessfulLaunchCount(id: UUID)
|
|
124
|
+
|
|
115
125
|
fun incrementFailedLaunchCount(update: UpdateEntity) {
|
|
116
126
|
update.failedLaunchCount++
|
|
117
|
-
|
|
127
|
+
_incrementFailedLaunchCount(update.id)
|
|
118
128
|
}
|
|
119
129
|
|
|
130
|
+
@Query("UPDATE updates SET failed_launch_count = failed_launch_count + 1 WHERE id = :id;")
|
|
131
|
+
abstract fun _incrementFailedLaunchCount(id: UUID)
|
|
132
|
+
|
|
120
133
|
fun markUpdatesWithMissingAssets(missingAssets: List<AssetEntity>) {
|
|
121
134
|
val missingAssetIds = mutableListOf<Long>()
|
|
122
135
|
for (asset in missingAssets) {
|
|
@@ -372,80 +372,17 @@ class LoaderTask(
|
|
|
372
372
|
}
|
|
373
373
|
|
|
374
374
|
override fun onSuccess(loaderResult: Loader.LoaderResult) {
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
/**
|
|
386
|
-
* If directive is to roll-back to the embedded update and there is an embedded update,
|
|
387
|
-
* we need to update embedded update in the DB with the newer commitTime from the directive
|
|
388
|
-
* so that the selection policy will choose it. That way future updates can continue to be applied
|
|
389
|
-
* over this roll back, but older ones won't.
|
|
390
|
-
*/
|
|
391
|
-
private fun processRollBackToEmbeddedDirective(updateDirective: UpdateDirective.RollBackToEmbeddedUpdateDirective) {
|
|
392
|
-
if (!configuration.hasEmbeddedUpdate) {
|
|
393
|
-
launchUpdate(null)
|
|
394
|
-
return
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
val embeddedUpdate = EmbeddedManifest.get(context, configuration)!!.updateEntity
|
|
398
|
-
if (embeddedUpdate == null) {
|
|
399
|
-
launchUpdate(null)
|
|
400
|
-
return
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
val launcher = DatabaseLauncher(configuration, directory, fileDownloader, selectionPolicy)
|
|
404
|
-
val launchableUpdate = launcher.getLaunchableUpdate(database, context)
|
|
405
|
-
val manifestFilters = ManifestMetadata.getManifestFilters(database, configuration)
|
|
406
|
-
|
|
407
|
-
if (!selectionPolicy.shouldLoadRollBackToEmbeddedDirective(updateDirective, embeddedUpdate, launchableUpdate, manifestFilters)) {
|
|
408
|
-
launchUpdate(null)
|
|
409
|
-
return
|
|
375
|
+
RemoteLoader.processSuccessLoaderResult(
|
|
376
|
+
context,
|
|
377
|
+
configuration,
|
|
378
|
+
database,
|
|
379
|
+
selectionPolicy,
|
|
380
|
+
directory,
|
|
381
|
+
candidateLauncher?.launchedUpdate,
|
|
382
|
+
loaderResult
|
|
383
|
+
) { availableUpdate, _ ->
|
|
384
|
+
launchUpdate(availableUpdate)
|
|
410
385
|
}
|
|
411
|
-
|
|
412
|
-
// update the embedded update commit time in the in-memory embedded update since it is a singleton
|
|
413
|
-
embeddedUpdate.commitTime = updateDirective.commitTime
|
|
414
|
-
|
|
415
|
-
// update the embedded update commit time in the database (requires loading and then updating)
|
|
416
|
-
EmbeddedLoader(context, configuration, database, directory).start(object : LoaderCallback {
|
|
417
|
-
/**
|
|
418
|
-
* This should never happen since we check for the embedded update above
|
|
419
|
-
*/
|
|
420
|
-
override fun onFailure(e: Exception) {
|
|
421
|
-
Log.e(
|
|
422
|
-
TAG,
|
|
423
|
-
"Embedded update erroneously null when applying roll back to embedded directive",
|
|
424
|
-
e
|
|
425
|
-
)
|
|
426
|
-
launchUpdate(null)
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
override fun onSuccess(loaderResult: Loader.LoaderResult) {
|
|
430
|
-
val embeddedUpdateToLoad = loaderResult.updateEntity
|
|
431
|
-
database.updateDao().setUpdateCommitTime(embeddedUpdateToLoad!!, updateDirective.commitTime)
|
|
432
|
-
launchUpdate(null)
|
|
433
|
-
}
|
|
434
|
-
|
|
435
|
-
override fun onAssetLoaded(
|
|
436
|
-
asset: AssetEntity,
|
|
437
|
-
successfulAssetCount: Int,
|
|
438
|
-
failedAssetCount: Int,
|
|
439
|
-
totalAssetCount: Int
|
|
440
|
-
) {
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
override fun onUpdateResponseLoaded(updateResponse: UpdateResponse): Loader.OnUpdateResponseLoadedResult {
|
|
444
|
-
return Loader.OnUpdateResponseLoadedResult(
|
|
445
|
-
shouldDownloadManifestIfPresentInResponse = true
|
|
446
|
-
)
|
|
447
|
-
}
|
|
448
|
-
})
|
|
449
386
|
}
|
|
450
387
|
|
|
451
388
|
private fun launchUpdate(availableUpdate: UpdateEntity?) {
|