@capawesome/capacitor-live-update 7.2.2 → 7.4.0-dev.f18299f8.1767510052
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 +289 -28
- package/android/build.gradle +2 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/LiveUpdate.java +623 -220
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/LiveUpdateConfig.java +23 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/LiveUpdateHttpClient.java +42 -5
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/LiveUpdatePlugin.java +185 -15
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/LiveUpdatePreferences.java +42 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/classes/api/GetLatestBundleResponse.java +2 -2
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/classes/events/NextBundleSetEvent.java +26 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/classes/options/SetConfigOptions.java +19 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/classes/options/SyncOptions.java +4 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/classes/results/GetBlockedBundlesResult.java +27 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/classes/results/GetConfigResult.java +40 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/classes/results/GetDownloadedBundlesResult.java +27 -0
- package/android/src/main/java/io/capawesome/capacitorjs/plugins/liveupdate/classes/results/IsSyncingResult.java +26 -0
- package/dist/docs.json +428 -1
- package/dist/esm/definitions.d.ts +230 -2
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web.d.ts +8 -1
- package/dist/esm/web.js +21 -0
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +21 -0
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +21 -0
- package/dist/plugin.js.map +1 -1
- package/ios/Plugin/Classes/Events/NextBundleSetEvent.swift +16 -0
- package/ios/Plugin/Classes/Options/SetConfigOptions.swift +14 -0
- package/ios/Plugin/Classes/Options/SyncOptions.swift +4 -0
- package/ios/Plugin/Classes/Results/GetBlockedBundlesResult.swift +16 -0
- package/ios/Plugin/Classes/Results/GetConfigResult.swift +19 -0
- package/ios/Plugin/Classes/Results/GetDownloadedBundlesResult.swift +16 -0
- package/ios/Plugin/Classes/Results/IsSyncingResult.swift +16 -0
- package/ios/Plugin/LiveUpdate.swift +178 -4
- package/ios/Plugin/LiveUpdateConfig.swift +2 -0
- package/ios/Plugin/LiveUpdateHttpClient.swift +4 -2
- package/ios/Plugin/LiveUpdatePlugin.swift +106 -11
- package/ios/Plugin/LiveUpdatePreferences.swift +56 -0
- package/package.json +1 -1
package/dist/plugin.js
CHANGED
|
@@ -6,6 +6,9 @@ var capacitorLiveUpdate = (function (exports, core) {
|
|
|
6
6
|
});
|
|
7
7
|
|
|
8
8
|
class LiveUpdateWeb extends core.WebPlugin {
|
|
9
|
+
async clearBlockedBundles() {
|
|
10
|
+
this.throwUnimplementedError();
|
|
11
|
+
}
|
|
9
12
|
async deleteBundle(_options) {
|
|
10
13
|
this.throwUnimplementedError();
|
|
11
14
|
}
|
|
@@ -15,15 +18,24 @@ var capacitorLiveUpdate = (function (exports, core) {
|
|
|
15
18
|
async fetchLatestBundle() {
|
|
16
19
|
this.throwUnimplementedError();
|
|
17
20
|
}
|
|
21
|
+
async getBlockedBundles() {
|
|
22
|
+
this.throwUnimplementedError();
|
|
23
|
+
}
|
|
18
24
|
async getBundle() {
|
|
19
25
|
this.throwUnimplementedError();
|
|
20
26
|
}
|
|
21
27
|
async getBundles() {
|
|
22
28
|
this.throwUnimplementedError();
|
|
23
29
|
}
|
|
30
|
+
async getDownloadedBundles() {
|
|
31
|
+
this.throwUnimplementedError();
|
|
32
|
+
}
|
|
24
33
|
async getChannel() {
|
|
25
34
|
this.throwUnimplementedError();
|
|
26
35
|
}
|
|
36
|
+
async getConfig() {
|
|
37
|
+
this.throwUnimplementedError();
|
|
38
|
+
}
|
|
27
39
|
async getCurrentBundle() {
|
|
28
40
|
this.throwUnimplementedError();
|
|
29
41
|
}
|
|
@@ -42,6 +54,9 @@ var capacitorLiveUpdate = (function (exports, core) {
|
|
|
42
54
|
async getVersionName() {
|
|
43
55
|
this.throwUnimplementedError();
|
|
44
56
|
}
|
|
57
|
+
async isSyncing() {
|
|
58
|
+
this.throwUnimplementedError();
|
|
59
|
+
}
|
|
45
60
|
async ready() {
|
|
46
61
|
this.throwUnimplementedError();
|
|
47
62
|
}
|
|
@@ -51,12 +66,18 @@ var capacitorLiveUpdate = (function (exports, core) {
|
|
|
51
66
|
async reset() {
|
|
52
67
|
this.throwUnimplementedError();
|
|
53
68
|
}
|
|
69
|
+
async resetConfig() {
|
|
70
|
+
this.throwUnimplementedError();
|
|
71
|
+
}
|
|
54
72
|
async setBundle(_options) {
|
|
55
73
|
this.throwUnimplementedError();
|
|
56
74
|
}
|
|
57
75
|
async setChannel(_options) {
|
|
58
76
|
this.throwUnimplementedError();
|
|
59
77
|
}
|
|
78
|
+
async setConfig(_options) {
|
|
79
|
+
this.throwUnimplementedError();
|
|
80
|
+
}
|
|
60
81
|
async setCustomId(_options) {
|
|
61
82
|
this.throwUnimplementedError();
|
|
62
83
|
}
|
package/dist/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst LiveUpdate = registerPlugin('LiveUpdate', {\n web: () => import('./web').then(m => new m.LiveUpdateWeb()),\n});\nexport * from './definitions';\nexport { LiveUpdate };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class LiveUpdateWeb extends WebPlugin {\n async deleteBundle(_options) {\n this.throwUnimplementedError();\n }\n async downloadBundle(_options) {\n this.throwUnimplementedError();\n }\n async fetchLatestBundle() {\n this.throwUnimplementedError();\n }\n async getBundle() {\n this.throwUnimplementedError();\n }\n async getBundles() {\n this.throwUnimplementedError();\n }\n async getChannel() {\n this.throwUnimplementedError();\n }\n async getCurrentBundle() {\n this.throwUnimplementedError();\n }\n async getCustomId() {\n this.throwUnimplementedError();\n }\n async getDeviceId() {\n this.throwUnimplementedError();\n }\n async getNextBundle() {\n this.throwUnimplementedError();\n }\n async getVersionCode() {\n this.throwUnimplementedError();\n }\n async getVersionName() {\n this.throwUnimplementedError();\n }\n async ready() {\n this.throwUnimplementedError();\n }\n async reload() {\n this.throwUnimplementedError();\n }\n async reset() {\n this.throwUnimplementedError();\n }\n async setBundle(_options) {\n this.throwUnimplementedError();\n }\n async setChannel(_options) {\n this.throwUnimplementedError();\n }\n async setCustomId(_options) {\n this.throwUnimplementedError();\n }\n async setNextBundle(_options) {\n this.throwUnimplementedError();\n }\n async sync() {\n this.throwUnimplementedError();\n }\n throwUnimplementedError() {\n throw this.unimplemented('Not implemented on web.');\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;AACK,UAAC,UAAU,GAAGA,mBAAc,CAAC,YAAY,EAAE;IAChD,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,aAAa,EAAE,CAAC;IAC/D,CAAC;;ICFM,MAAM,aAAa,SAASC,cAAS,CAAC;IAC7C,IAAI,MAAM,YAAY,CAAC,QAAQ,EAAE;IACjC,QAAQ,IAAI,CAAC,uBAAuB,EAAE;IACtC;IACA,IAAI,MAAM,cAAc,CAAC,QAAQ,EAAE;IACnC,QAAQ,IAAI,CAAC,uBAAuB,EAAE;IACtC;IACA,IAAI,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,IAAI,CAAC,uBAAuB,EAAE;IACtC;IACA,IAAI,MAAM,SAAS,GAAG;IACtB,QAAQ,IAAI,CAAC,uBAAuB,EAAE;IACtC;IACA,IAAI,MAAM,UAAU,GAAG;IACvB,QAAQ,IAAI,CAAC,uBAAuB,EAAE;IACtC;IACA,IAAI,MAAM,UAAU,GAAG;IACvB,QAAQ,IAAI,CAAC,uBAAuB,EAAE;IACtC;IACA,IAAI,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,IAAI,CAAC,uBAAuB,EAAE;IACtC;IACA,IAAI,MAAM,WAAW,GAAG;IACxB,QAAQ,IAAI,CAAC,uBAAuB,EAAE;IACtC;IACA,IAAI,MAAM,WAAW,GAAG;IACxB,QAAQ,IAAI,CAAC,uBAAuB,EAAE;IACtC;IACA,IAAI,MAAM,aAAa,GAAG;IAC1B,QAAQ,IAAI,CAAC,uBAAuB,EAAE;IACtC;IACA,IAAI,MAAM,cAAc,GAAG;IAC3B,QAAQ,IAAI,CAAC,uBAAuB,EAAE;IACtC;IACA,IAAI,MAAM,cAAc,GAAG;IAC3B,QAAQ,IAAI,CAAC,uBAAuB,EAAE;IACtC;IACA,IAAI,MAAM,KAAK,GAAG;IAClB,QAAQ,IAAI,CAAC,uBAAuB,EAAE;IACtC;IACA,IAAI,MAAM,MAAM,GAAG;IACnB,QAAQ,IAAI,CAAC,uBAAuB,EAAE;IACtC;IACA,IAAI,MAAM,KAAK,GAAG;IAClB,QAAQ,IAAI,CAAC,uBAAuB,EAAE;IACtC;IACA,IAAI,MAAM,SAAS,CAAC,QAAQ,EAAE;IAC9B,QAAQ,IAAI,CAAC,uBAAuB,EAAE;IACtC;IACA,IAAI,MAAM,UAAU,CAAC,QAAQ,EAAE;IAC/B,QAAQ,IAAI,CAAC,uBAAuB,EAAE;IACtC;IACA,IAAI,MAAM,WAAW,CAAC,QAAQ,EAAE;IAChC,QAAQ,IAAI,CAAC,uBAAuB,EAAE;IACtC;IACA,IAAI,MAAM,aAAa,CAAC,QAAQ,EAAE;IAClC,QAAQ,IAAI,CAAC,uBAAuB,EAAE;IACtC;IACA,IAAI,MAAM,IAAI,GAAG;IACjB,QAAQ,IAAI,CAAC,uBAAuB,EAAE;IACtC;IACA,IAAI,uBAAuB,GAAG;IAC9B,QAAQ,MAAM,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC;IAC3D;IACA;;;;;;;;;;;;;;;"}
|
|
1
|
+
{"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst LiveUpdate = registerPlugin('LiveUpdate', {\n web: () => import('./web').then(m => new m.LiveUpdateWeb()),\n});\nexport * from './definitions';\nexport { LiveUpdate };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class LiveUpdateWeb extends WebPlugin {\n async clearBlockedBundles() {\n this.throwUnimplementedError();\n }\n async deleteBundle(_options) {\n this.throwUnimplementedError();\n }\n async downloadBundle(_options) {\n this.throwUnimplementedError();\n }\n async fetchLatestBundle() {\n this.throwUnimplementedError();\n }\n async getBlockedBundles() {\n this.throwUnimplementedError();\n }\n async getBundle() {\n this.throwUnimplementedError();\n }\n async getBundles() {\n this.throwUnimplementedError();\n }\n async getDownloadedBundles() {\n this.throwUnimplementedError();\n }\n async getChannel() {\n this.throwUnimplementedError();\n }\n async getConfig() {\n this.throwUnimplementedError();\n }\n async getCurrentBundle() {\n this.throwUnimplementedError();\n }\n async getCustomId() {\n this.throwUnimplementedError();\n }\n async getDeviceId() {\n this.throwUnimplementedError();\n }\n async getNextBundle() {\n this.throwUnimplementedError();\n }\n async getVersionCode() {\n this.throwUnimplementedError();\n }\n async getVersionName() {\n this.throwUnimplementedError();\n }\n async isSyncing() {\n this.throwUnimplementedError();\n }\n async ready() {\n this.throwUnimplementedError();\n }\n async reload() {\n this.throwUnimplementedError();\n }\n async reset() {\n this.throwUnimplementedError();\n }\n async resetConfig() {\n this.throwUnimplementedError();\n }\n async setBundle(_options) {\n this.throwUnimplementedError();\n }\n async setChannel(_options) {\n this.throwUnimplementedError();\n }\n async setConfig(_options) {\n this.throwUnimplementedError();\n }\n async setCustomId(_options) {\n this.throwUnimplementedError();\n }\n async setNextBundle(_options) {\n this.throwUnimplementedError();\n }\n async sync() {\n this.throwUnimplementedError();\n }\n throwUnimplementedError() {\n throw this.unimplemented('Not implemented on web.');\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Capacitor
|
|
3
|
+
|
|
4
|
+
@objc public class NextBundleSetEvent: NSObject {
|
|
5
|
+
let bundleId: String?
|
|
6
|
+
|
|
7
|
+
init(bundleId: String?) {
|
|
8
|
+
self.bundleId = bundleId
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
public func toJSObject() -> JSObject {
|
|
12
|
+
var result = JSObject()
|
|
13
|
+
result["bundleId"] = bundleId == nil ? NSNull() : bundleId
|
|
14
|
+
return result
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Capacitor
|
|
3
|
+
|
|
4
|
+
@objc public class SetConfigOptions: NSObject {
|
|
5
|
+
let appId: String?
|
|
6
|
+
|
|
7
|
+
init(_ call: CAPPluginCall) {
|
|
8
|
+
self.appId = call.getString("appId")
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
public func getAppId() -> String? {
|
|
12
|
+
return appId
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Capacitor
|
|
3
|
+
|
|
4
|
+
@objc public class GetBlockedBundlesResult: NSObject, Result {
|
|
5
|
+
let bundleIds: [String]
|
|
6
|
+
|
|
7
|
+
init(bundleIds: [String]) {
|
|
8
|
+
self.bundleIds = bundleIds
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
public func toJSObject() -> AnyObject {
|
|
12
|
+
var result = JSObject()
|
|
13
|
+
result["bundleIds"] = bundleIds
|
|
14
|
+
return result as AnyObject
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Capacitor
|
|
3
|
+
|
|
4
|
+
@objc public class GetConfigResult: NSObject, Result {
|
|
5
|
+
let appId: String?
|
|
6
|
+
let autoUpdateStrategy: String
|
|
7
|
+
|
|
8
|
+
init(appId: String?, autoUpdateStrategy: String) {
|
|
9
|
+
self.appId = appId
|
|
10
|
+
self.autoUpdateStrategy = autoUpdateStrategy
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
public func toJSObject() -> AnyObject {
|
|
14
|
+
var result = JSObject()
|
|
15
|
+
result["appId"] = appId == nil ? NSNull() : appId
|
|
16
|
+
result["autoUpdateStrategy"] = autoUpdateStrategy
|
|
17
|
+
return result as AnyObject
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Capacitor
|
|
3
|
+
|
|
4
|
+
@objc public class GetDownloadedBundlesResult: NSObject, Result {
|
|
5
|
+
let bundleIds: [String]
|
|
6
|
+
|
|
7
|
+
init(bundleIds: [String]) {
|
|
8
|
+
self.bundleIds = bundleIds
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
public func toJSObject() -> AnyObject {
|
|
12
|
+
var result = JSObject()
|
|
13
|
+
result["bundleIds"] = bundleIds
|
|
14
|
+
return result as AnyObject
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Capacitor
|
|
3
|
+
|
|
4
|
+
@objc public class IsSyncingResult: NSObject, Result {
|
|
5
|
+
let syncing: Bool
|
|
6
|
+
|
|
7
|
+
init(syncing: Bool) {
|
|
8
|
+
self.syncing = syncing
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
@objc public func toJSObject() -> AnyObject {
|
|
12
|
+
var result = JSObject()
|
|
13
|
+
result["syncing"] = syncing
|
|
14
|
+
return result as AnyObject
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -11,6 +11,7 @@ import CommonCrypto
|
|
|
11
11
|
|
|
12
12
|
// swiftlint:disable type_body_length
|
|
13
13
|
@objc public class LiveUpdate: NSObject {
|
|
14
|
+
private let autoUpdateIntervalMs: Int64 = 15 * 60 * 1000 // 15 minutes
|
|
14
15
|
private let bundlesDirectory = "NoCloud/ionic_built_snapshots" // DO NOT CHANGE! (See https://dub.sh/BLluidt)
|
|
15
16
|
private let cachesDirectoryUrl = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
|
|
16
17
|
private let config: LiveUpdateConfig
|
|
@@ -24,6 +25,8 @@ import CommonCrypto
|
|
|
24
25
|
|
|
25
26
|
private var rollbackDispatchWorkItem: DispatchWorkItem?
|
|
26
27
|
private var rollbackPerformed = false
|
|
28
|
+
private var lastAutoUpdateCheckTimestamp: Int64 = 0
|
|
29
|
+
private var syncInProgress = false
|
|
27
30
|
|
|
28
31
|
init(config: LiveUpdateConfig, plugin: LiveUpdatePlugin) {
|
|
29
32
|
self.config = config
|
|
@@ -32,11 +35,18 @@ import CommonCrypto
|
|
|
32
35
|
self.preferences = LiveUpdatePreferences()
|
|
33
36
|
super.init()
|
|
34
37
|
|
|
38
|
+
// Check version and reset config if version changed
|
|
39
|
+
checkAndResetConfigIfVersionChanged()
|
|
40
|
+
|
|
35
41
|
// Start the rollback timer to rollback to the default bundle
|
|
36
42
|
// if the app is not ready after a certain time
|
|
37
43
|
startRollbackTimer()
|
|
38
44
|
}
|
|
39
45
|
|
|
46
|
+
@objc public func clearBlockedBundles() {
|
|
47
|
+
preferences.setBlockedBundleIds(nil)
|
|
48
|
+
}
|
|
49
|
+
|
|
40
50
|
@objc public func deleteBundle(_ options: DeleteBundleOptions, completion: @escaping (Error?) -> Void) {
|
|
41
51
|
let bundleId = options.getBundleId()
|
|
42
52
|
|
|
@@ -79,18 +89,40 @@ import CommonCrypto
|
|
|
79
89
|
return FetchLatestBundleResult(artifactType: response?.artifactType, bundleId: response?.bundleId, checksum: response?.checksum, customProperties: response?.customProperties, downloadUrl: response?.url, signature: response?.signature)
|
|
80
90
|
}
|
|
81
91
|
|
|
92
|
+
@objc public func getBlockedBundles(completion: @escaping (Result?, Error?) -> Void) {
|
|
93
|
+
var bundleIds: [String] = []
|
|
94
|
+
if let blockedIds = preferences.getBlockedBundleIds(), !blockedIds.isEmpty {
|
|
95
|
+
bundleIds = blockedIds.split(separator: ",").map(String.init)
|
|
96
|
+
}
|
|
97
|
+
let result = GetBlockedBundlesResult(bundleIds: bundleIds)
|
|
98
|
+
completion(result, nil)
|
|
99
|
+
}
|
|
100
|
+
|
|
82
101
|
@objc public func getBundles(completion: @escaping (Result?, Error?) -> Void) {
|
|
83
|
-
let bundleIds =
|
|
102
|
+
let bundleIds = getDownloadedBundleIds()
|
|
84
103
|
let result = GetBundlesResult(bundleIds: bundleIds)
|
|
85
104
|
completion(result, nil)
|
|
86
105
|
}
|
|
87
106
|
|
|
107
|
+
@objc public func getDownloadedBundles(completion: @escaping (Result?, Error?) -> Void) {
|
|
108
|
+
let bundleIds = getDownloadedBundleIds()
|
|
109
|
+
let result = GetDownloadedBundlesResult(bundleIds: bundleIds)
|
|
110
|
+
completion(result, nil)
|
|
111
|
+
}
|
|
112
|
+
|
|
88
113
|
@objc public func getChannel(completion: @escaping (Result?, Error?) -> Void) {
|
|
89
114
|
let channel = getChannel()
|
|
90
115
|
let result = GetChannelResult(channel: channel)
|
|
91
116
|
completion(result, nil)
|
|
92
117
|
}
|
|
93
118
|
|
|
119
|
+
@objc public func getConfig(completion: @escaping (Result?, Error?) -> Void) {
|
|
120
|
+
let appId = getAppId()
|
|
121
|
+
let autoUpdateStrategy = config.autoUpdateStrategy
|
|
122
|
+
let result = GetConfigResult(appId: appId, autoUpdateStrategy: autoUpdateStrategy)
|
|
123
|
+
completion(result, nil)
|
|
124
|
+
}
|
|
125
|
+
|
|
94
126
|
@objc public func getCurrentBundle(completion: @escaping (Result?, Error?) -> Void) {
|
|
95
127
|
let bundleId = getCurrentBundleId()
|
|
96
128
|
let result = GetCurrentBundleResult(bundleId: bundleId)
|
|
@@ -128,6 +160,23 @@ import CommonCrypto
|
|
|
128
160
|
completion(result, nil)
|
|
129
161
|
}
|
|
130
162
|
|
|
163
|
+
@objc public func isSyncing(completion: @escaping (Result?, Error?) -> Void) {
|
|
164
|
+
let result = IsSyncingResult(syncing: syncInProgress)
|
|
165
|
+
completion(result, nil)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
@objc public func handleLoad() {
|
|
169
|
+
if config.autoUpdateStrategy == "background" {
|
|
170
|
+
performAutoUpdate()
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
@objc public func handleAppWillEnterForeground() {
|
|
175
|
+
if config.autoUpdateStrategy == "background" {
|
|
176
|
+
performAutoUpdate()
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
131
180
|
@objc public func ready(completion: @escaping (Result?, Error?) -> Void) {
|
|
132
181
|
CAPLog.print("[", LiveUpdatePlugin.tag, "] ", "App is ready.")
|
|
133
182
|
if config.readyTimeout <= 0 {
|
|
@@ -142,6 +191,10 @@ import CommonCrypto
|
|
|
142
191
|
// Get the current and previous bundle IDs
|
|
143
192
|
let currentBundleId = getCurrentBundleId()
|
|
144
193
|
let previousBundleId = getPreviousBundleId()
|
|
194
|
+
// Block the rolled back bundle if enabled
|
|
195
|
+
if config.autoBlockRolledBackBundles && rollbackPerformed, let previousBundleId = previousBundleId {
|
|
196
|
+
addBlockedBundleId(previousBundleId)
|
|
197
|
+
}
|
|
145
198
|
// Return the result
|
|
146
199
|
let result = ReadyResult(currentBundleId: currentBundleId, previousBundleId: previousBundleId, rollback: rollbackPerformed)
|
|
147
200
|
completion(result, nil)
|
|
@@ -161,6 +214,10 @@ import CommonCrypto
|
|
|
161
214
|
self.setNextBundleById(nil)
|
|
162
215
|
}
|
|
163
216
|
|
|
217
|
+
@objc public func resetConfig() {
|
|
218
|
+
preferences.setAppId(nil)
|
|
219
|
+
}
|
|
220
|
+
|
|
164
221
|
@objc public func setChannel(_ options: SetChannelOptions, completion: @escaping (Error?) -> Void) {
|
|
165
222
|
let channel = options.getChannel()
|
|
166
223
|
|
|
@@ -168,6 +225,11 @@ import CommonCrypto
|
|
|
168
225
|
completion(nil)
|
|
169
226
|
}
|
|
170
227
|
|
|
228
|
+
@objc public func setConfig(_ options: SetConfigOptions) {
|
|
229
|
+
let appId = options.getAppId()
|
|
230
|
+
preferences.setAppId(appId)
|
|
231
|
+
}
|
|
232
|
+
|
|
171
233
|
@objc public func setCustomId(_ options: SetCustomIdOptions, completion: @escaping (Error?) -> Void) {
|
|
172
234
|
let customId = options.getCustomId()
|
|
173
235
|
|
|
@@ -194,6 +256,14 @@ import CommonCrypto
|
|
|
194
256
|
}
|
|
195
257
|
|
|
196
258
|
@objc public func sync(_ options: SyncOptions) async throws -> SyncResult {
|
|
259
|
+
if syncInProgress {
|
|
260
|
+
throw CustomError.syncInProgress
|
|
261
|
+
}
|
|
262
|
+
syncInProgress = true
|
|
263
|
+
defer {
|
|
264
|
+
syncInProgress = false
|
|
265
|
+
}
|
|
266
|
+
|
|
197
267
|
let channel = options.getChannel()
|
|
198
268
|
// Fetch the latest bundle
|
|
199
269
|
let fetchLatestBundleOptions = FetchLatestBundleOptions(channel: channel)
|
|
@@ -206,6 +276,11 @@ import CommonCrypto
|
|
|
206
276
|
let checksum = response.checksum
|
|
207
277
|
let signature = response.signature
|
|
208
278
|
let downloadUrl = response.url
|
|
279
|
+
// Check if the bundle is blocked
|
|
280
|
+
if isBlockedBundleId(latestBundleId) {
|
|
281
|
+
CAPLog.print("[", LiveUpdatePlugin.tag, "] ", "Bundle is blocked and will not be downloaded.")
|
|
282
|
+
return SyncResult(nextBundleId: nil)
|
|
283
|
+
}
|
|
209
284
|
// Check if bundle already exists
|
|
210
285
|
if hasBundleById(latestBundleId) {
|
|
211
286
|
var nextBundleId: String?
|
|
@@ -339,7 +414,7 @@ import CommonCrypto
|
|
|
339
414
|
}
|
|
340
415
|
|
|
341
416
|
private func deleteUnusedBundles() {
|
|
342
|
-
let bundleIds =
|
|
417
|
+
let bundleIds = getDownloadedBundleIds()
|
|
343
418
|
let currentBundleId = getCurrentBundleId()
|
|
344
419
|
let nextBundleId = getNextBundleId()
|
|
345
420
|
|
|
@@ -484,7 +559,7 @@ import CommonCrypto
|
|
|
484
559
|
parameters["osVersion"] = await UIDevice.current.systemVersion
|
|
485
560
|
parameters["platform"] = "1"
|
|
486
561
|
parameters["pluginVersion"] = LiveUpdatePlugin.version
|
|
487
|
-
var urlComponents = URLComponents(string: "https://\(config.serverDomain)/v1/apps/\(
|
|
562
|
+
var urlComponents = URLComponents(string: "https://\(config.serverDomain)/v1/apps/\(getAppId() ?? "")/bundles/latest")!
|
|
488
563
|
urlComponents.queryItems = parameters.map { URLQueryItem(name: $0.key, value: $0.value) }
|
|
489
564
|
let url = try urlComponents.asURL()
|
|
490
565
|
CAPLog.print("[", LiveUpdatePlugin.tag, "] Fetching latest bundle: ", url)
|
|
@@ -507,7 +582,7 @@ import CommonCrypto
|
|
|
507
582
|
}
|
|
508
583
|
}
|
|
509
584
|
|
|
510
|
-
private func
|
|
585
|
+
private func getDownloadedBundleIds() -> [String] {
|
|
511
586
|
let url = libraryDirectoryUrl.appendingPathComponent(bundlesDirectory)
|
|
512
587
|
do {
|
|
513
588
|
let pathExists = FileManager.default.fileExists(atPath: url.path)
|
|
@@ -521,6 +596,13 @@ import CommonCrypto
|
|
|
521
596
|
}
|
|
522
597
|
}
|
|
523
598
|
|
|
599
|
+
private func getAppId() -> String? {
|
|
600
|
+
if let appId = preferences.getAppId() {
|
|
601
|
+
return appId
|
|
602
|
+
}
|
|
603
|
+
return config.appId
|
|
604
|
+
}
|
|
605
|
+
|
|
524
606
|
private func getChannel() -> String? {
|
|
525
607
|
var channel: String?
|
|
526
608
|
if let _ = config.defaultChannel {
|
|
@@ -645,6 +727,30 @@ import CommonCrypto
|
|
|
645
727
|
plugin.notifyDownloadBundleProgressListeners(event)
|
|
646
728
|
}
|
|
647
729
|
|
|
730
|
+
private func performAutoUpdate() {
|
|
731
|
+
// Check if enough time has passed since the last check
|
|
732
|
+
let now = Int64(Date().timeIntervalSince1970 * 1000)
|
|
733
|
+
if lastAutoUpdateCheckTimestamp > 0 && (now - lastAutoUpdateCheckTimestamp) < autoUpdateIntervalMs {
|
|
734
|
+
CAPLog.print("[", LiveUpdatePlugin.tag, "] ", "Auto-update skipped. Last check was less than 15 minutes ago.")
|
|
735
|
+
return
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
// Update the timestamp
|
|
739
|
+
lastAutoUpdateCheckTimestamp = now
|
|
740
|
+
|
|
741
|
+
// Run sync in background task
|
|
742
|
+
Task {
|
|
743
|
+
do {
|
|
744
|
+
CAPLog.print("[", LiveUpdatePlugin.tag, "] ", "Auto-update started.")
|
|
745
|
+
let options = SyncOptions(channel: nil)
|
|
746
|
+
_ = try await sync(options)
|
|
747
|
+
CAPLog.print("[", LiveUpdatePlugin.tag, "] ", "Auto-update completed successfully.")
|
|
748
|
+
} catch {
|
|
749
|
+
CAPLog.print("[", LiveUpdatePlugin.tag, "] ", "Auto-update failed: ", error.localizedDescription)
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
|
|
648
754
|
private func rollback() {
|
|
649
755
|
// Set the rollback flag
|
|
650
756
|
rollbackPerformed = true
|
|
@@ -699,12 +805,63 @@ import CommonCrypto
|
|
|
699
805
|
return
|
|
700
806
|
}
|
|
701
807
|
viewController.setServerBasePath(path: path)
|
|
808
|
+
// Notify listeners
|
|
809
|
+
notifyReloadedListeners()
|
|
702
810
|
}
|
|
703
811
|
|
|
704
812
|
/// - Parameter bundleId: The bundle ID to set as the next bundle. If `nil`, the default bundle will be used.
|
|
705
813
|
private func setNextBundleById(_ bundleId: String?) {
|
|
706
814
|
let path = buildCapacitorServerPathFor(bundleId: bundleId)
|
|
707
815
|
setNextCapacitorServerPath(path: path)
|
|
816
|
+
|
|
817
|
+
// Notify listeners
|
|
818
|
+
notifyNextBundleSetListeners(bundleId)
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
private func notifyNextBundleSetListeners(_ bundleId: String?) {
|
|
822
|
+
let event = NextBundleSetEvent(bundleId: bundleId)
|
|
823
|
+
plugin.notifyNextBundleSetListeners(event)
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
private func notifyReloadedListeners() {
|
|
827
|
+
plugin.notifyReloadedListeners()
|
|
828
|
+
}
|
|
829
|
+
|
|
830
|
+
private func addBlockedBundleId(_ bundleId: String) {
|
|
831
|
+
var blockedList: [String] = []
|
|
832
|
+
|
|
833
|
+
// Parse existing blocked IDs
|
|
834
|
+
if let blockedIds = preferences.getBlockedBundleIds(), !blockedIds.isEmpty {
|
|
835
|
+
blockedList = blockedIds.split(separator: ",").map(String.init)
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
// Skip if already blocked
|
|
839
|
+
if blockedList.contains(bundleId) {
|
|
840
|
+
return
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
// Remove oldest if limit reached
|
|
844
|
+
if blockedList.count >= 100 {
|
|
845
|
+
blockedList.removeFirst()
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
// Add new bundle
|
|
849
|
+
blockedList.append(bundleId)
|
|
850
|
+
|
|
851
|
+
// Save back to preferences
|
|
852
|
+
let newBlockedIds = blockedList.joined(separator: ",")
|
|
853
|
+
preferences.setBlockedBundleIds(newBlockedIds)
|
|
854
|
+
|
|
855
|
+
CAPLog.print("[", LiveUpdatePlugin.tag, "] ", "Bundle blocked: ", bundleId)
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
private func isBlockedBundleId(_ bundleId: String) -> Bool {
|
|
859
|
+
guard let blockedIds = preferences.getBlockedBundleIds(), !blockedIds.isEmpty else {
|
|
860
|
+
return false
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
let blockedList = blockedIds.split(separator: ",").map(String.init)
|
|
864
|
+
return blockedList.contains(bundleId)
|
|
708
865
|
}
|
|
709
866
|
|
|
710
867
|
private func setNextCapacitorServerPath(path: String) {
|
|
@@ -717,6 +874,23 @@ import CommonCrypto
|
|
|
717
874
|
}
|
|
718
875
|
}
|
|
719
876
|
|
|
877
|
+
private func checkAndResetConfigIfVersionChanged() {
|
|
878
|
+
let currentVersionCode = getVersionCode()
|
|
879
|
+
let currentVersionName = getVersionName()
|
|
880
|
+
let lastVersionCode = preferences.getLastVersionCode()
|
|
881
|
+
let lastVersionName = preferences.getLastVersionName()
|
|
882
|
+
|
|
883
|
+
if lastVersionCode == nil || lastVersionName == nil || lastVersionCode != currentVersionCode || lastVersionName != currentVersionName {
|
|
884
|
+
CAPLog.print(
|
|
885
|
+
"[", LiveUpdatePlugin.tag, "] ",
|
|
886
|
+
"App version changed (last: \(lastVersionName ?? "nil")/\(lastVersionCode ?? "nil"), current: \(currentVersionName)/\(currentVersionCode)), resetting config."
|
|
887
|
+
)
|
|
888
|
+
resetConfig()
|
|
889
|
+
preferences.setLastVersionCode(currentVersionCode)
|
|
890
|
+
preferences.setLastVersionName(currentVersionName)
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
|
|
720
894
|
/// - Parameter bundleId: The bundle ID to save as the previous bundle ID. If `nil`, the value will be removed.
|
|
721
895
|
private func setPreviousBundleId(bundleId: String?) {
|
|
722
896
|
preferences.setPreviousBundleId(bundleId)
|
|
@@ -7,11 +7,13 @@ public class LiveUpdateHttpClient: NSObject {
|
|
|
7
7
|
private let config: LiveUpdateConfig
|
|
8
8
|
|
|
9
9
|
public static func getChecksumFromResponse(response: HTTPURLResponse) -> String? {
|
|
10
|
-
|
|
10
|
+
guard let headers = response.allHeaderFields as? [String: String] else { return nil }
|
|
11
|
+
return headers.first(where: { $0.key.lowercased() == "x-checksum" })?.value
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
public static func getSignatureFromResponse(response: HTTPURLResponse) -> String? {
|
|
14
|
-
|
|
15
|
+
guard let headers = response.allHeaderFields as? [String: String] else { return nil }
|
|
16
|
+
return headers.first(where: { $0.key.lowercased() == "x-signature" })?.value
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
init(config: LiveUpdateConfig) {
|