@capgo/capacitor-updater 6.0.0 → 6.0.2
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 +530 -210
- package/android/build.gradle +3 -3
- package/android/proguard-rules.pro +28 -0
- package/android/src/main/java/ee/forgr/capacitor_updater/Callback.java +13 -0
- package/android/src/main/java/ee/forgr/capacitor_updater/CapacitorUpdater.java +315 -259
- package/android/src/main/java/ee/forgr/capacitor_updater/CapacitorUpdaterPlugin.java +716 -411
- package/android/src/main/java/ee/forgr/capacitor_updater/CryptoCipher.java +4 -12
- package/android/src/main/java/ee/forgr/capacitor_updater/DelayCondition.java +3 -2
- package/android/src/main/java/ee/forgr/capacitor_updater/DownloadService.java +31 -22
- package/android/src/main/java/ee/forgr/capacitor_updater/InternalUtils.java +41 -0
- package/dist/docs.json +884 -329
- package/dist/esm/definitions.d.ts +402 -242
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/web.d.ts +21 -40
- package/dist/esm/web.js +21 -1
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +21 -1
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +21 -1
- package/dist/plugin.js.map +1 -1
- package/ios/Plugin/CapacitorUpdater.swift +226 -69
- package/ios/Plugin/CapacitorUpdaterPlugin.m +4 -1
- package/ios/Plugin/CapacitorUpdaterPlugin.swift +227 -59
- package/ios/Plugin/CryptoCipher.swift +9 -3
- package/package.json +21 -24
|
@@ -14,8 +14,8 @@ import Version
|
|
|
14
14
|
*/
|
|
15
15
|
@objc(CapacitorUpdaterPlugin)
|
|
16
16
|
public class CapacitorUpdaterPlugin: CAPPlugin {
|
|
17
|
-
|
|
18
|
-
private let PLUGIN_VERSION: String = "6.0.
|
|
17
|
+
public var implementation = CapacitorUpdater()
|
|
18
|
+
private let PLUGIN_VERSION: String = "6.0.2"
|
|
19
19
|
static let updateUrlDefault = "https://api.capgo.app/updates"
|
|
20
20
|
static let statsUrlDefault = "https://api.capgo.app/stats"
|
|
21
21
|
static let channelUrlDefault = "https://api.capgo.app/channel_self"
|
|
@@ -29,36 +29,59 @@ public class CapacitorUpdaterPlugin: CAPPlugin {
|
|
|
29
29
|
private var appReadyTimeout = 10000
|
|
30
30
|
private var appReadyCheck: DispatchWorkItem?
|
|
31
31
|
private var resetWhenUpdate = true
|
|
32
|
+
private var directUpdate = false
|
|
32
33
|
private var autoDeleteFailed = false
|
|
33
34
|
private var autoDeletePrevious = false
|
|
34
35
|
private var backgroundWork: DispatchWorkItem?
|
|
35
36
|
private var taskRunning = false
|
|
37
|
+
private var periodCheckDelay = 0
|
|
38
|
+
let semaphoreReady = DispatchSemaphore(value: 0)
|
|
36
39
|
|
|
37
40
|
override public func load() {
|
|
41
|
+
self.semaphoreUp()
|
|
38
42
|
print("\(self.implementation.TAG) init for device \(self.implementation.deviceID)")
|
|
43
|
+
guard let versionName = getConfig().getString("version", Bundle.main.versionName) else {
|
|
44
|
+
print("\(self.implementation.TAG) Cannot get version name")
|
|
45
|
+
// crash the app
|
|
46
|
+
fatalError("Cannot get version name")
|
|
47
|
+
}
|
|
39
48
|
do {
|
|
40
|
-
currentVersionNative = try Version(
|
|
49
|
+
currentVersionNative = try Version(versionName)
|
|
41
50
|
} catch {
|
|
42
|
-
print("\(self.implementation.TAG) Cannot
|
|
51
|
+
print("\(self.implementation.TAG) Cannot parse versionName \(versionName)")
|
|
43
52
|
}
|
|
44
53
|
print("\(self.implementation.TAG) version native \(self.currentVersionNative.description)")
|
|
45
|
-
implementation.
|
|
54
|
+
implementation.versionBuild = getConfig().getString("version", Bundle.main.versionName)!
|
|
46
55
|
autoDeleteFailed = getConfig().getBoolean("autoDeleteFailed", true)
|
|
47
56
|
autoDeletePrevious = getConfig().getBoolean("autoDeletePrevious", true)
|
|
57
|
+
directUpdate = getConfig().getBoolean("directUpdate", false)
|
|
48
58
|
updateUrl = getConfig().getString("updateUrl", CapacitorUpdaterPlugin.updateUrlDefault)!
|
|
49
59
|
autoUpdate = getConfig().getBoolean("autoUpdate", true)
|
|
50
60
|
appReadyTimeout = getConfig().getInt("appReadyTimeout", 10000)
|
|
61
|
+
implementation.timeout = Double(getConfig().getInt("responseTimeout", 20))
|
|
51
62
|
resetWhenUpdate = getConfig().getBoolean("resetWhenUpdate", true)
|
|
63
|
+
let periodCheckDelayValue = getConfig().getInt("periodCheckDelay", 0)
|
|
64
|
+
if periodCheckDelayValue >= 0 && periodCheckDelayValue > 600 {
|
|
65
|
+
periodCheckDelay = 600
|
|
66
|
+
} else {
|
|
67
|
+
periodCheckDelay = periodCheckDelayValue
|
|
68
|
+
}
|
|
52
69
|
|
|
53
70
|
implementation.privateKey = getConfig().getString("privateKey", self.defaultPrivateKey)!
|
|
54
71
|
implementation.notifyDownload = notifyDownload
|
|
55
72
|
implementation.PLUGIN_VERSION = self.PLUGIN_VERSION
|
|
56
73
|
let config = (self.bridge?.viewController as? CAPBridgeViewController)?.instanceDescriptor().legacyConfig
|
|
57
|
-
|
|
58
|
-
|
|
74
|
+
implementation.appId = Bundle.main.infoDictionary?["CFBundleIdentifier"] as? String ?? ""
|
|
75
|
+
implementation.appId = config?["appId"] as? String ?? implementation.appId
|
|
76
|
+
implementation.appId = getConfig().getString("appId", implementation.appId)!
|
|
77
|
+
if implementation.appId == "" {
|
|
78
|
+
fatalError("appId is missing in capacitor.config.json or plugin config, and cannot be retrieved from the native app, please add it globally or in the plugin config")
|
|
59
79
|
}
|
|
80
|
+
print("\(self.implementation.TAG) appId \(implementation.appId)")
|
|
60
81
|
implementation.statsUrl = getConfig().getString("statsUrl", CapacitorUpdaterPlugin.statsUrlDefault)!
|
|
61
82
|
implementation.channelUrl = getConfig().getString("channelUrl", CapacitorUpdaterPlugin.channelUrlDefault)!
|
|
83
|
+
implementation.defaultChannel = getConfig().getString("defaultChannel", "")!
|
|
84
|
+
self.implementation.autoReset()
|
|
62
85
|
if resetWhenUpdate {
|
|
63
86
|
self.cleanupObsoleteVersions()
|
|
64
87
|
}
|
|
@@ -67,6 +90,24 @@ public class CapacitorUpdaterPlugin: CAPPlugin {
|
|
|
67
90
|
nc.addObserver(self, selector: #selector(appMovedToForeground), name: UIApplication.willEnterForegroundNotification, object: nil)
|
|
68
91
|
nc.addObserver(self, selector: #selector(appKilled), name: UIApplication.willTerminateNotification, object: nil)
|
|
69
92
|
self.appMovedToForeground()
|
|
93
|
+
self.checkForUpdateAfterDelay()
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
private func semaphoreWait(waitTime: Int) {
|
|
97
|
+
print("\(self.implementation.TAG) semaphoreWait \(waitTime)")
|
|
98
|
+
_ = semaphoreReady.wait(timeout: .now() + .milliseconds(waitTime))
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
private func semaphoreUp() {
|
|
102
|
+
print("\(self.implementation.TAG) semaphoreUp")
|
|
103
|
+
DispatchQueue.global().async {
|
|
104
|
+
self.semaphoreWait(waitTime: 0)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
private func semaphoreDown() {
|
|
109
|
+
print("\(self.implementation.TAG) semaphoreDown")
|
|
110
|
+
semaphoreReady.signal()
|
|
70
111
|
}
|
|
71
112
|
|
|
72
113
|
private func cleanupObsoleteVersions() {
|
|
@@ -102,6 +143,55 @@ public class CapacitorUpdaterPlugin: CAPPlugin {
|
|
|
102
143
|
}
|
|
103
144
|
}
|
|
104
145
|
|
|
146
|
+
@objc func setUpdateUrl(_ call: CAPPluginCall) {
|
|
147
|
+
if !getConfig().getBoolean("allowModifyUrl", false) {
|
|
148
|
+
print("\(self.implementation.TAG) setUpdateUrl called without allowModifyUrl")
|
|
149
|
+
call.reject("setUpdateUrl called without allowModifyUrl set allowModifyUrl in your config to true to allow it")
|
|
150
|
+
return
|
|
151
|
+
}
|
|
152
|
+
guard let url = call.getString("url") else {
|
|
153
|
+
print("\(self.implementation.TAG) setUpdateUrl called without url")
|
|
154
|
+
call.reject("setUpdateUrl called without url")
|
|
155
|
+
return
|
|
156
|
+
}
|
|
157
|
+
self.updateUrl = url
|
|
158
|
+
call.resolve()
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
@objc func setStatsUrl(_ call: CAPPluginCall) {
|
|
162
|
+
if !getConfig().getBoolean("allowModifyUrl", false) {
|
|
163
|
+
print("\(self.implementation.TAG) setStatsUrl called without allowModifyUrl")
|
|
164
|
+
call.reject("setStatsUrl called without allowModifyUrl set allowModifyUrl in your config to true to allow it")
|
|
165
|
+
return
|
|
166
|
+
}
|
|
167
|
+
guard let url = call.getString("url") else {
|
|
168
|
+
print("\(self.implementation.TAG) setStatsUrl called without url")
|
|
169
|
+
call.reject("setStatsUrl called without url")
|
|
170
|
+
return
|
|
171
|
+
}
|
|
172
|
+
self.statsUrl = url
|
|
173
|
+
call.resolve()
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
@objc func setChannelUrl(_ call: CAPPluginCall) {
|
|
177
|
+
if !getConfig().getBoolean("allowModifyUrl", false) {
|
|
178
|
+
print("\(self.implementation.TAG) setChannelUrl called without allowModifyUrl")
|
|
179
|
+
call.reject("setChannelUrl called without allowModifyUrl set allowModifyUrl in your config to true to allow it")
|
|
180
|
+
return
|
|
181
|
+
}
|
|
182
|
+
guard let url = call.getString("url") else {
|
|
183
|
+
print("\(self.implementation.TAG) setChannelUrl called without url")
|
|
184
|
+
call.reject("setChannelUrl called without url")
|
|
185
|
+
return
|
|
186
|
+
}
|
|
187
|
+
self.implementation.channelUrl = url
|
|
188
|
+
call.resolve()
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
@objc func getBuiltinVersion(_ call: CAPPluginCall) {
|
|
192
|
+
call.resolve(["version": implementation.versionBuild])
|
|
193
|
+
}
|
|
194
|
+
|
|
105
195
|
@objc func getDeviceId(_ call: CAPPluginCall) {
|
|
106
196
|
call.resolve(["deviceId": implementation.deviceID])
|
|
107
197
|
}
|
|
@@ -143,20 +233,25 @@ public class CapacitorUpdaterPlugin: CAPPlugin {
|
|
|
143
233
|
} catch {
|
|
144
234
|
print("\(self.implementation.TAG) Failed to download from: \(String(describing: url)) \(error.localizedDescription)")
|
|
145
235
|
self.notifyListeners("downloadFailed", data: ["version": version])
|
|
146
|
-
|
|
147
|
-
self.implementation.sendStats(action: "download_fail", versionName: current.getVersionName())
|
|
236
|
+
self.implementation.sendStats(action: "download_fail")
|
|
148
237
|
call.reject("Failed to download from: \(url!)", error.localizedDescription)
|
|
149
238
|
}
|
|
150
239
|
}
|
|
151
240
|
}
|
|
152
241
|
|
|
153
|
-
|
|
242
|
+
public func _reload() -> Bool {
|
|
154
243
|
guard let bridge = self.bridge else { return false }
|
|
244
|
+
self.semaphoreUp()
|
|
155
245
|
let id = self.implementation.getCurrentBundleId()
|
|
156
|
-
let
|
|
246
|
+
let dest: URL
|
|
247
|
+
if BundleInfo.ID_BUILTIN == id {
|
|
248
|
+
dest = Bundle.main.resourceURL!.appendingPathComponent("public")
|
|
249
|
+
} else {
|
|
250
|
+
dest = self.implementation.getBundleDirectory(id: id)
|
|
251
|
+
}
|
|
157
252
|
print("\(self.implementation.TAG) Reloading \(id)")
|
|
158
253
|
if let vc = bridge.viewController as? CAPBridgeViewController {
|
|
159
|
-
vc.setServerBasePath(path:
|
|
254
|
+
vc.setServerBasePath(path: dest.path)
|
|
160
255
|
self.checkAppReady()
|
|
161
256
|
self.notifyListeners("appReloaded", data: [:])
|
|
162
257
|
return true
|
|
@@ -235,23 +330,46 @@ public class CapacitorUpdaterPlugin: CAPPlugin {
|
|
|
235
330
|
let res = self.implementation.getLatest(url: URL(string: self.updateUrl)!)
|
|
236
331
|
if res.error != nil {
|
|
237
332
|
call.reject( res.error!)
|
|
333
|
+
} else if res.message != nil {
|
|
334
|
+
call.reject( res.message!)
|
|
238
335
|
} else {
|
|
239
336
|
call.resolve(res.toDict())
|
|
240
337
|
}
|
|
241
338
|
}
|
|
242
339
|
}
|
|
243
340
|
|
|
341
|
+
@objc func unsetChannel(_ call: CAPPluginCall) {
|
|
342
|
+
let triggerAutoUpdate = call.getBool("triggerAutoUpdate", false)
|
|
343
|
+
DispatchQueue.global(qos: .background).async {
|
|
344
|
+
let res = self.implementation.unsetChannel()
|
|
345
|
+
if res.error != "" {
|
|
346
|
+
call.reject(res.error)
|
|
347
|
+
} else {
|
|
348
|
+
if self._isAutoUpdateEnabled() && triggerAutoUpdate {
|
|
349
|
+
print("\(self.implementation.TAG) Calling autoupdater after channel change!")
|
|
350
|
+
self.backgroundDownload()
|
|
351
|
+
}
|
|
352
|
+
call.resolve(res.toDict())
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
244
357
|
@objc func setChannel(_ call: CAPPluginCall) {
|
|
245
358
|
guard let channel = call.getString("channel") else {
|
|
246
359
|
print("\(self.implementation.TAG) setChannel called without channel")
|
|
247
360
|
call.reject("setChannel called without channel")
|
|
248
361
|
return
|
|
249
362
|
}
|
|
363
|
+
let triggerAutoUpdate = call.getBool("triggerAutoUpdate") ?? false
|
|
250
364
|
DispatchQueue.global(qos: .background).async {
|
|
251
365
|
let res = self.implementation.setChannel(channel: channel)
|
|
252
366
|
if res.error != "" {
|
|
253
367
|
call.reject(res.error)
|
|
254
368
|
} else {
|
|
369
|
+
if self._isAutoUpdateEnabled() && triggerAutoUpdate {
|
|
370
|
+
print("\(self.implementation.TAG) Calling autoupdater after channel change!")
|
|
371
|
+
self.backgroundDownload()
|
|
372
|
+
}
|
|
255
373
|
call.resolve(res.toDict())
|
|
256
374
|
}
|
|
257
375
|
}
|
|
@@ -318,10 +436,11 @@ public class CapacitorUpdaterPlugin: CAPPlugin {
|
|
|
318
436
|
}
|
|
319
437
|
|
|
320
438
|
@objc func notifyAppReady(_ call: CAPPluginCall) {
|
|
321
|
-
|
|
322
|
-
self.implementation.
|
|
323
|
-
|
|
324
|
-
|
|
439
|
+
self.semaphoreDown()
|
|
440
|
+
let bundle = self.implementation.getCurrentBundle()
|
|
441
|
+
self.implementation.setSuccess(bundle: bundle, autoDeletePrevious: self.autoDeletePrevious)
|
|
442
|
+
print("\(self.implementation.TAG) Current bundle loaded successfully. ['notifyAppReady()' was called] \(bundle.toString())")
|
|
443
|
+
call.resolve(["bundle": bundle.toJSON()])
|
|
325
444
|
}
|
|
326
445
|
|
|
327
446
|
@objc func setMultiDelay(_ call: CAPPluginCall) {
|
|
@@ -490,64 +609,81 @@ public class CapacitorUpdaterPlugin: CAPPlugin {
|
|
|
490
609
|
self.backgroundTaskID = UIBackgroundTaskIdentifier.invalid
|
|
491
610
|
}
|
|
492
611
|
|
|
612
|
+
func sendReadyToJs(current: BundleInfo, msg: String) {
|
|
613
|
+
print("\(self.implementation.TAG) sendReadyToJs")
|
|
614
|
+
DispatchQueue.global().async {
|
|
615
|
+
self.semaphoreWait(waitTime: self.appReadyTimeout)
|
|
616
|
+
self.notifyListeners("appReady", data: ["bundle": current.toJSON(), "status": msg])
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
func endBackGroundTaskWithNotif(msg: String, latestVersionName: String, current: BundleInfo, error: Bool = true) {
|
|
621
|
+
if error {
|
|
622
|
+
self.implementation.sendStats(action: "download_fail", versionName: current.getVersionName())
|
|
623
|
+
self.notifyListeners("downloadFailed", data: ["version": latestVersionName])
|
|
624
|
+
}
|
|
625
|
+
self.notifyListeners("noNeedUpdate", data: ["bundle": current.toJSON()])
|
|
626
|
+
self.sendReadyToJs(current: current, msg: msg)
|
|
627
|
+
print("\(self.implementation.TAG) endBackGroundTaskWithNotif \(msg)")
|
|
628
|
+
self.endBackGroundTask()
|
|
629
|
+
}
|
|
630
|
+
|
|
493
631
|
func backgroundDownload() {
|
|
632
|
+
let messageUpdate = self.directUpdate ? "Update will occur now." : "Update will occur next time app moves to background."
|
|
633
|
+
guard let url = URL(string: self.updateUrl) else {
|
|
634
|
+
print("\(self.implementation.TAG) Error no url or wrong format")
|
|
635
|
+
return
|
|
636
|
+
}
|
|
494
637
|
DispatchQueue.global(qos: .background).async {
|
|
495
638
|
self.backgroundTaskID = UIApplication.shared.beginBackgroundTask(withName: "Finish Download Tasks") {
|
|
496
639
|
// End the task if time expires.
|
|
497
640
|
self.endBackGroundTask()
|
|
498
641
|
}
|
|
499
642
|
print("\(self.implementation.TAG) Check for update via \(self.updateUrl)")
|
|
500
|
-
let url = URL(string: self.updateUrl)!
|
|
501
643
|
let res = self.implementation.getLatest(url: url)
|
|
502
644
|
let current = self.implementation.getCurrentBundle()
|
|
503
645
|
|
|
504
646
|
if (res.message) != nil {
|
|
505
|
-
print("\(self.implementation.TAG) message \(res.message ?? "")")
|
|
647
|
+
print("\(self.implementation.TAG) API message: \(res.message ?? "")")
|
|
506
648
|
if res.major == true {
|
|
507
649
|
self.notifyListeners("majorAvailable", data: ["version": res.version])
|
|
508
650
|
}
|
|
509
|
-
self.
|
|
510
|
-
self.endBackGroundTask()
|
|
651
|
+
self.endBackGroundTaskWithNotif(msg: res.message ?? "", latestVersionName: res.version, current: current, error: false)
|
|
511
652
|
return
|
|
512
653
|
}
|
|
513
654
|
let sessionKey = res.sessionKey ?? ""
|
|
514
655
|
guard let downloadUrl = URL(string: res.url) else {
|
|
515
656
|
print("\(self.implementation.TAG) Error no url or wrong format")
|
|
516
|
-
self.
|
|
517
|
-
self.endBackGroundTask()
|
|
657
|
+
self.endBackGroundTaskWithNotif(msg: "Error no url or wrong format", latestVersionName: res.version, current: current)
|
|
518
658
|
return
|
|
519
659
|
}
|
|
520
660
|
let latestVersionName = res.version
|
|
521
661
|
if latestVersionName != "" && current.getVersionName() != latestVersionName {
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
662
|
+
do {
|
|
663
|
+
print("\(self.implementation.TAG) New bundle: \(latestVersionName) found. Current is: \(current.getVersionName()). \(messageUpdate)")
|
|
664
|
+
var nextImpl = self.implementation.getBundleInfoByVersionName(version: latestVersionName)
|
|
665
|
+
if nextImpl == nil || ((nextImpl?.isDeleted()) != nil) {
|
|
666
|
+
if (nextImpl?.isDeleted()) != nil {
|
|
667
|
+
print("\(self.implementation.TAG) Latest bundle already exists and will be deleted, download will overwrite it.")
|
|
668
|
+
let res = self.implementation.delete(id: nextImpl!.getId(), removeInfo: true)
|
|
669
|
+
if res {
|
|
670
|
+
print("\(self.implementation.TAG) Delete version deleted: \(nextImpl!.toString())")
|
|
671
|
+
} else {
|
|
672
|
+
print("\(self.implementation.TAG) Failed to delete failed bundle: \(nextImpl!.toString())")
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
nextImpl = try self.implementation.download(url: downloadUrl, version: latestVersionName, sessionKey: sessionKey)
|
|
529
676
|
}
|
|
530
|
-
|
|
531
|
-
print("\(self.implementation.TAG)
|
|
532
|
-
self.
|
|
533
|
-
_ = self.implementation.setNextBundle(next: latest!.getId())
|
|
534
|
-
self.endBackGroundTask()
|
|
677
|
+
guard let next = nextImpl else {
|
|
678
|
+
print("\(self.implementation.TAG) Error downloading file")
|
|
679
|
+
self.endBackGroundTaskWithNotif(msg: "Error downloading file", latestVersionName: latestVersionName, current: current)
|
|
535
680
|
return
|
|
536
681
|
}
|
|
537
|
-
if
|
|
538
|
-
print("\(self.implementation.TAG) Latest
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
print("\(self.implementation.TAG) Delete version deleted: \(latest!.toString())")
|
|
542
|
-
} else {
|
|
543
|
-
print("\(self.implementation.TAG) Failed to delete failed bundle: \(latest!.toString())")
|
|
544
|
-
}
|
|
682
|
+
if next.isErrorStatus() {
|
|
683
|
+
print("\(self.implementation.TAG) Latest version is in error state. Aborting update.")
|
|
684
|
+
self.endBackGroundTaskWithNotif(msg: "Latest version is in error state. Aborting update.", latestVersionName: latestVersionName, current: current)
|
|
685
|
+
return
|
|
545
686
|
}
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
do {
|
|
549
|
-
print("\(self.implementation.TAG) New bundle: \(latestVersionName) found. Current is: \(current.getVersionName()). Update will occur next time app moves to background.")
|
|
550
|
-
let next = try self.implementation.download(url: downloadUrl, version: latestVersionName, sessionKey: sessionKey)
|
|
551
687
|
if res.checksum != "" && next.getChecksum() != res.checksum {
|
|
552
688
|
print("\(self.implementation.TAG) Error checksum", next.getChecksum(), res.checksum)
|
|
553
689
|
self.implementation.sendStats(action: "checksum_fail", versionName: next.getVersionName())
|
|
@@ -556,23 +692,31 @@ public class CapacitorUpdaterPlugin: CAPPlugin {
|
|
|
556
692
|
if !resDel {
|
|
557
693
|
print("\(self.implementation.TAG) Delete failed, id \(id) doesn't exist")
|
|
558
694
|
}
|
|
559
|
-
self.
|
|
560
|
-
|
|
695
|
+
self.endBackGroundTaskWithNotif(msg: "Error checksum", latestVersionName: latestVersionName, current: current)
|
|
696
|
+
return
|
|
561
697
|
}
|
|
562
|
-
self.
|
|
563
|
-
|
|
698
|
+
if self.directUpdate {
|
|
699
|
+
_ = self.implementation.set(bundle: next)
|
|
700
|
+
_ = self._reload()
|
|
701
|
+
self.directUpdate = false
|
|
702
|
+
self.endBackGroundTaskWithNotif(msg: "update installed", latestVersionName: latestVersionName, current: current, error: false)
|
|
703
|
+
} else {
|
|
704
|
+
self.notifyListeners("updateAvailable", data: ["bundle": next.toJSON()])
|
|
705
|
+
_ = self.implementation.setNextBundle(next: next.getId())
|
|
706
|
+
self.endBackGroundTaskWithNotif(msg: "update downloaded, will install next background", latestVersionName: latestVersionName, current: current, error: false)
|
|
707
|
+
}
|
|
708
|
+
return
|
|
564
709
|
} catch {
|
|
565
710
|
print("\(self.implementation.TAG) Error downloading file", error.localizedDescription)
|
|
566
711
|
let current: BundleInfo = self.implementation.getCurrentBundle()
|
|
567
|
-
self.
|
|
568
|
-
|
|
569
|
-
self.notifyListeners("noNeedUpdate", data: ["bundle": current.toJSON()])
|
|
712
|
+
self.endBackGroundTaskWithNotif(msg: "Error downloading file", latestVersionName: latestVersionName, current: current)
|
|
713
|
+
return
|
|
570
714
|
}
|
|
571
715
|
} else {
|
|
572
716
|
print("\(self.implementation.TAG) No need to update, \(current.getId()) is the latest bundle.")
|
|
573
|
-
self.
|
|
717
|
+
self.endBackGroundTaskWithNotif(msg: "No need to update, \(current.getId()) is the latest bundle.", latestVersionName: latestVersionName, current: current, error: false)
|
|
718
|
+
return
|
|
574
719
|
}
|
|
575
|
-
self.endBackGroundTask()
|
|
576
720
|
}
|
|
577
721
|
}
|
|
578
722
|
|
|
@@ -614,7 +758,9 @@ public class CapacitorUpdaterPlugin: CAPPlugin {
|
|
|
614
758
|
}
|
|
615
759
|
|
|
616
760
|
@objc private func fromJsonArr(json: String) -> [NSObject] {
|
|
617
|
-
let jsonData = json.data(using: .utf8)
|
|
761
|
+
guard let jsonData = json.data(using: .utf8) else {
|
|
762
|
+
return []
|
|
763
|
+
}
|
|
618
764
|
let object = try? JSONSerialization.jsonObject(
|
|
619
765
|
with: jsonData,
|
|
620
766
|
options: .mutableContainers
|
|
@@ -633,13 +779,35 @@ public class CapacitorUpdaterPlugin: CAPPlugin {
|
|
|
633
779
|
self.backgroundDownload()
|
|
634
780
|
} else {
|
|
635
781
|
print("\(self.implementation.TAG) Auto update is disabled")
|
|
782
|
+
self.sendReadyToJs(current: current, msg: "disabled")
|
|
636
783
|
}
|
|
637
784
|
self.checkAppReady()
|
|
638
785
|
}
|
|
639
786
|
|
|
787
|
+
@objc func checkForUpdateAfterDelay() {
|
|
788
|
+
if periodCheckDelay == 0 || !self._isAutoUpdateEnabled() {
|
|
789
|
+
return
|
|
790
|
+
}
|
|
791
|
+
guard let url = URL(string: self.updateUrl) else {
|
|
792
|
+
print("\(self.implementation.TAG) Error no url or wrong format")
|
|
793
|
+
return
|
|
794
|
+
}
|
|
795
|
+
let timer = Timer.scheduledTimer(withTimeInterval: TimeInterval(periodCheckDelay), repeats: true) { _ in
|
|
796
|
+
DispatchQueue.global(qos: .background).async {
|
|
797
|
+
let res = self.implementation.getLatest(url: url)
|
|
798
|
+
let current = self.implementation.getCurrentBundle()
|
|
799
|
+
|
|
800
|
+
if res.version != current.getVersionName() {
|
|
801
|
+
print("\(self.implementation.TAG) New version found: \(res.version)")
|
|
802
|
+
self.backgroundDownload()
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
RunLoop.current.add(timer, forMode: .default)
|
|
807
|
+
}
|
|
808
|
+
|
|
640
809
|
@objc func appMovedToBackground() {
|
|
641
|
-
|
|
642
|
-
self.implementation.sendStats(action: "app_moved_to_background", versionName: current.getVersionName())
|
|
810
|
+
self.implementation.sendStats(action: "app_moved_to_background")
|
|
643
811
|
print("\(self.implementation.TAG) Check for pending update")
|
|
644
812
|
let delayUpdatePreferences = UserDefaults.standard.string(forKey: DELAY_CONDITION_PREFERENCES) ?? "[]"
|
|
645
813
|
|
|
@@ -199,10 +199,16 @@ public struct RSAPrivateKey {
|
|
|
199
199
|
privKey = privKey.replacingOccurrences(of: "-----END RSA PRIVATE KEY-----", with: "")
|
|
200
200
|
privKey = privKey.replacingOccurrences(of: "\\n+", with: "", options: .regularExpression)
|
|
201
201
|
privKey = privKey.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
202
|
-
|
|
203
|
-
|
|
202
|
+
do {
|
|
203
|
+
guard let rsaPrivateKeyData: Data = Data(base64Encoded: privKey) else {
|
|
204
|
+
throw CustomError.cannotDecode
|
|
205
|
+
}
|
|
206
|
+
guard let privateKey: SecKey = .loadPrivateFromData(rsaPrivateKeyData) else {
|
|
207
|
+
throw CustomError.cannotDecode
|
|
208
|
+
}
|
|
204
209
|
return RSAPrivateKey(privateKey: privateKey)
|
|
205
|
-
}
|
|
210
|
+
} catch {
|
|
211
|
+
print("Error load RSA: \(error)")
|
|
206
212
|
return nil
|
|
207
213
|
}
|
|
208
214
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@capgo/capacitor-updater",
|
|
3
|
-
"version": "6.0.
|
|
4
|
-
"packageManager": "pnpm@8.
|
|
3
|
+
"version": "6.0.2",
|
|
4
|
+
"packageManager": "pnpm@8.15.7",
|
|
5
5
|
"license": "MPL-2.0",
|
|
6
6
|
"description": "Live update for capacitor apps",
|
|
7
7
|
"main": "dist/plugin.cjs.js",
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
"unpkg": "dist/plugin.js",
|
|
11
11
|
"files": [
|
|
12
12
|
"android/src/main/",
|
|
13
|
+
"android/proguard-rules.pro",
|
|
13
14
|
"android/build.gradle",
|
|
14
15
|
"dist/",
|
|
15
16
|
"ios/Plugin/",
|
|
@@ -42,7 +43,7 @@
|
|
|
42
43
|
"verify:web": "npm run build",
|
|
43
44
|
"lint": "npm run eslint && npm run prettier -- --check && npm run swiftlint -- lint",
|
|
44
45
|
"fmt": "npm run eslint -- --fix && npm run prettier -- --write && npm run swiftlint -- --autocorrect --format",
|
|
45
|
-
"eslint": "eslint .
|
|
46
|
+
"eslint": "eslint .",
|
|
46
47
|
"prettier": "prettier --config .prettierrc.js \"**/*.{css,html,ts,js,java}\"",
|
|
47
48
|
"swiftlint": "node-swiftlint",
|
|
48
49
|
"docgen": "docgen --api CapacitorUpdaterPlugin --output-readme README.md --output-json dist/docs.json",
|
|
@@ -53,34 +54,30 @@
|
|
|
53
54
|
"prepublishOnly": "npm run build"
|
|
54
55
|
},
|
|
55
56
|
"devDependencies": {
|
|
56
|
-
"@capacitor/android": "^
|
|
57
|
-
"@capacitor/cli": "^
|
|
58
|
-
"@capacitor/core": "^
|
|
59
|
-
"@capacitor/docgen": "^0.2.
|
|
60
|
-
"@capacitor/ios": "^
|
|
57
|
+
"@capacitor/android": "^6.0.0",
|
|
58
|
+
"@capacitor/cli": "^6.0.0",
|
|
59
|
+
"@capacitor/core": "^6.0.0",
|
|
60
|
+
"@capacitor/docgen": "^0.2.2",
|
|
61
|
+
"@capacitor/ios": "^6.0.0",
|
|
61
62
|
"@ionic/eslint-config": "^0.3.0",
|
|
62
|
-
"@ionic/prettier-config": "^
|
|
63
|
+
"@ionic/prettier-config": "^4.0.0",
|
|
63
64
|
"@ionic/swiftlint-config": "^1.1.2",
|
|
64
|
-
"@types/node": "^20.
|
|
65
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
66
|
-
"@typescript-eslint/parser": "^
|
|
67
|
-
"eslint": "^
|
|
68
|
-
"eslint-plugin-import": "^2.
|
|
69
|
-
"prettier": "^2.
|
|
70
|
-
"prettier-plugin-java": "^2.
|
|
71
|
-
"rimraf": "^5.0.
|
|
72
|
-
"rollup": "^
|
|
65
|
+
"@types/node": "^20.12.7",
|
|
66
|
+
"@typescript-eslint/eslint-plugin": "^7.8.0",
|
|
67
|
+
"@typescript-eslint/parser": "^7.8.0",
|
|
68
|
+
"eslint": "^9.1.1",
|
|
69
|
+
"eslint-plugin-import": "^2.29.1",
|
|
70
|
+
"prettier": "^3.2.5",
|
|
71
|
+
"prettier-plugin-java": "^2.6.0",
|
|
72
|
+
"rimraf": "^5.0.5",
|
|
73
|
+
"rollup": "^4.17.1",
|
|
73
74
|
"swiftlint": "^1.0.2",
|
|
74
|
-
"typescript": "^5.
|
|
75
|
+
"typescript": "^5.4.5"
|
|
75
76
|
},
|
|
76
77
|
"peerDependencies": {
|
|
77
|
-
"@capacitor/core": "^
|
|
78
|
+
"@capacitor/core": "^6.0.0"
|
|
78
79
|
},
|
|
79
80
|
"prettier": "@ionic/prettier-config",
|
|
80
|
-
"swiftlint": "@ionic/swiftlint-config",
|
|
81
|
-
"eslintConfig": {
|
|
82
|
-
"extends": "@ionic/eslint-config/recommended"
|
|
83
|
-
},
|
|
84
81
|
"capacitor": {
|
|
85
82
|
"ios": {
|
|
86
83
|
"src": "ios"
|