@capgo/capacitor-updater 4.2.7 → 4.3.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/README.md +57 -5
- package/android/build.gradle +3 -3
- package/android/src/main/java/ee/forgr/capacitor_updater/CapacitorUpdater.java +10 -9
- package/android/src/main/java/ee/forgr/capacitor_updater/CapacitorUpdaterPlugin.java +159 -58
- package/android/src/main/java/ee/forgr/capacitor_updater/DelayCondition.java +48 -0
- package/android/src/main/java/ee/forgr/capacitor_updater/DelayUntilNext.java +8 -0
- package/dist/docs.json +175 -10
- package/dist/esm/definitions.d.ts +44 -8
- package/dist/esm/web.d.ts +4 -4
- package/dist/esm/web.js +6 -2
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +6 -2
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +6 -2
- package/dist/plugin.js.map +1 -1
- package/ios/Plugin/CapacitorUpdater.swift +1 -1
- package/ios/Plugin/CapacitorUpdaterPlugin.m +1 -0
- package/ios/Plugin/CapacitorUpdaterPlugin.swift +154 -47
- package/ios/Plugin/DelayCondition.swift +68 -0
- package/ios/Plugin/DelayUntilNext.swift +24 -0
- package/package.json +1 -1
|
@@ -11,8 +11,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin {
|
|
|
11
11
|
private var implementation = CapacitorUpdater()
|
|
12
12
|
static let updateUrlDefault = "https://api.capgo.app/updates"
|
|
13
13
|
static let statsUrlDefault = "https://api.capgo.app/stats"
|
|
14
|
-
let
|
|
15
|
-
let DELAY_UPDATE_VAL = "delayUpdateVal"
|
|
14
|
+
let DELAY_CONDITION_PREFERENCES = ""
|
|
16
15
|
private var updateUrl = ""
|
|
17
16
|
private var statsUrl = ""
|
|
18
17
|
private var currentVersionNative: Version = "0.0.0"
|
|
@@ -22,6 +21,8 @@ public class CapacitorUpdaterPlugin: CAPPlugin {
|
|
|
22
21
|
private var resetWhenUpdate = true
|
|
23
22
|
private var autoDeleteFailed = false
|
|
24
23
|
private var autoDeletePrevious = false
|
|
24
|
+
private var backgroundWork: DispatchWorkItem?
|
|
25
|
+
private var taskRunning = false
|
|
25
26
|
|
|
26
27
|
override public func load() {
|
|
27
28
|
print("\(self.implementation.TAG) init for device \(self.implementation.deviceID)")
|
|
@@ -120,6 +121,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin {
|
|
|
120
121
|
if let vc = bridge.viewController as? CAPBridgeViewController {
|
|
121
122
|
vc.setServerBasePath(path: destHot.path)
|
|
122
123
|
self.checkAppReady()
|
|
124
|
+
self.notifyListeners("appReloaded", data: [:])
|
|
123
125
|
return true
|
|
124
126
|
}
|
|
125
127
|
return false
|
|
@@ -241,24 +243,47 @@ public class CapacitorUpdaterPlugin: CAPPlugin {
|
|
|
241
243
|
call.resolve()
|
|
242
244
|
}
|
|
243
245
|
|
|
244
|
-
@objc func
|
|
245
|
-
guard let
|
|
246
|
-
print("\(self.implementation.TAG)
|
|
247
|
-
call.reject("
|
|
246
|
+
@objc func setMultiDelay(_ call: CAPPluginCall) {
|
|
247
|
+
guard let delayConditionList = call.getValue("delayConditions") else {
|
|
248
|
+
print("\(self.implementation.TAG) setMultiDelay called without delayCondition")
|
|
249
|
+
call.reject("setMultiDelay called without delayCondition")
|
|
248
250
|
return
|
|
249
251
|
}
|
|
250
|
-
let
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
252
|
+
let delayConditions: String = toJson(object: delayConditionList)
|
|
253
|
+
if _setMultiDelay(delayConditions: delayConditions) {
|
|
254
|
+
call.resolve()
|
|
255
|
+
} else {
|
|
256
|
+
call.reject("Failed to delay update")
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
@available(*, deprecated, message: "use SetMultiDelay instead")
|
|
261
|
+
@objc func setDelay(_ call: CAPPluginCall) {
|
|
262
|
+
let kind: String = call.getString("kind", "")
|
|
263
|
+
let value: String? = call.getString("value", "")
|
|
264
|
+
let delayConditions: String = "[{\"kind\":\"\(kind)\", \"value\":\"\(value ?? "")\"}]"
|
|
265
|
+
if _setMultiDelay(delayConditions: delayConditions) {
|
|
266
|
+
call.resolve()
|
|
267
|
+
} else {
|
|
268
|
+
call.reject("Failed to delay update")
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
private func _setMultiDelay(delayConditions: String?) -> Bool {
|
|
273
|
+
if delayConditions != nil && "" != delayConditions {
|
|
274
|
+
UserDefaults.standard.set(delayConditions, forKey: DELAY_CONDITION_PREFERENCES)
|
|
275
|
+
UserDefaults.standard.synchronize()
|
|
276
|
+
print("\(self.implementation.TAG) Delay update saved.")
|
|
277
|
+
return true
|
|
278
|
+
} else {
|
|
279
|
+
print("\(self.implementation.TAG) Failed to delay update, [Error calling '_setMultiDelay()']")
|
|
280
|
+
return false
|
|
281
|
+
}
|
|
256
282
|
}
|
|
257
283
|
|
|
258
284
|
private func _cancelDelay(source: String) {
|
|
259
285
|
print("\(self.implementation.TAG) delay Canceled from \(source)")
|
|
260
|
-
UserDefaults.standard.removeObject(forKey:
|
|
261
|
-
UserDefaults.standard.removeObject(forKey: DELAY_UPDATE_VAL)
|
|
286
|
+
UserDefaults.standard.removeObject(forKey: DELAY_CONDITION_PREFERENCES)
|
|
262
287
|
UserDefaults.standard.synchronize()
|
|
263
288
|
}
|
|
264
289
|
|
|
@@ -268,39 +293,65 @@ public class CapacitorUpdaterPlugin: CAPPlugin {
|
|
|
268
293
|
}
|
|
269
294
|
|
|
270
295
|
private func _checkCancelDelay(killed: Bool) {
|
|
271
|
-
let
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
do {
|
|
293
|
-
let versionLimit = try Version(delayVal)
|
|
294
|
-
if self.currentVersionNative >= versionLimit {
|
|
295
|
-
self._cancelDelay(source: "nativeVersion above limit")
|
|
296
|
+
let delayUpdatePreferences = UserDefaults.standard.string(forKey: DELAY_CONDITION_PREFERENCES) ?? "[]"
|
|
297
|
+
let delayConditionList: [DelayCondition] = fromJsonArr(json: delayUpdatePreferences).map { obj -> DelayCondition in
|
|
298
|
+
let kind: String = obj.value(forKey: "kind") as! String
|
|
299
|
+
let value: String? = obj.value(forKey: "value") as? String
|
|
300
|
+
return DelayCondition(kind: kind, value: value)
|
|
301
|
+
}
|
|
302
|
+
for condition in delayConditionList {
|
|
303
|
+
let kind: String? = condition.getKind()
|
|
304
|
+
let value: String? = condition.getValue()
|
|
305
|
+
if kind != nil {
|
|
306
|
+
switch kind {
|
|
307
|
+
case "background":
|
|
308
|
+
if !killed {
|
|
309
|
+
self._cancelDelay(source: "background check")
|
|
310
|
+
}
|
|
311
|
+
break
|
|
312
|
+
case "kill":
|
|
313
|
+
if killed {
|
|
314
|
+
self._cancelDelay(source: "kill check")
|
|
315
|
+
// instant install for kill action
|
|
316
|
+
self.installNext()
|
|
296
317
|
}
|
|
297
|
-
|
|
298
|
-
|
|
318
|
+
break
|
|
319
|
+
case "date":
|
|
320
|
+
if value != nil && value != "" {
|
|
321
|
+
let dateFormatter = ISO8601DateFormatter()
|
|
322
|
+
guard let ExpireDate = dateFormatter.date(from: value!) else {
|
|
323
|
+
self._cancelDelay(source: "date parsing issue")
|
|
324
|
+
return
|
|
325
|
+
}
|
|
326
|
+
if ExpireDate < Date() {
|
|
327
|
+
self._cancelDelay(source: "date expired")
|
|
328
|
+
}
|
|
329
|
+
} else {
|
|
330
|
+
self._cancelDelay(source: "delayVal absent")
|
|
331
|
+
}
|
|
332
|
+
break
|
|
333
|
+
case "nativeVersion":
|
|
334
|
+
if value != nil && value != "" {
|
|
335
|
+
do {
|
|
336
|
+
let versionLimit = try Version(value!)
|
|
337
|
+
if self.currentVersionNative >= versionLimit {
|
|
338
|
+
self._cancelDelay(source: "nativeVersion above limit")
|
|
339
|
+
}
|
|
340
|
+
} catch {
|
|
341
|
+
self._cancelDelay(source: "nativeVersion parsing issue")
|
|
342
|
+
}
|
|
343
|
+
} else {
|
|
344
|
+
self._cancelDelay(source: "delayVal absent")
|
|
345
|
+
}
|
|
346
|
+
break
|
|
347
|
+
case .none:
|
|
348
|
+
print("\(self.implementation.TAG) _checkCancelDelay switch case none error")
|
|
349
|
+
case .some:
|
|
350
|
+
print("\(self.implementation.TAG) _checkCancelDelay switch case some error")
|
|
299
351
|
}
|
|
300
352
|
}
|
|
301
353
|
}
|
|
302
|
-
|
|
303
|
-
self.checkAppReady()
|
|
354
|
+
// self.checkAppReady() why this here?
|
|
304
355
|
}
|
|
305
356
|
|
|
306
357
|
private func _isAutoUpdateEnabled() -> Bool {
|
|
@@ -361,6 +412,10 @@ public class CapacitorUpdaterPlugin: CAPPlugin {
|
|
|
361
412
|
}
|
|
362
413
|
|
|
363
414
|
@objc func appMovedToForeground() {
|
|
415
|
+
if backgroundWork != nil && taskRunning {
|
|
416
|
+
backgroundWork!.cancel()
|
|
417
|
+
print("\(self.implementation.TAG) Background Timer Task canceled, Activity resumed before timer completes")
|
|
418
|
+
}
|
|
364
419
|
if self._isAutoUpdateEnabled() {
|
|
365
420
|
DispatchQueue.global(qos: .background).async {
|
|
366
421
|
print("\(self.implementation.TAG) Check for update via \(self.updateUrl)")
|
|
@@ -420,13 +475,49 @@ public class CapacitorUpdaterPlugin: CAPPlugin {
|
|
|
420
475
|
|
|
421
476
|
@objc func appMovedToBackground() {
|
|
422
477
|
print("\(self.implementation.TAG) Check for pending update")
|
|
423
|
-
let
|
|
424
|
-
|
|
425
|
-
|
|
478
|
+
let delayUpdatePreferences = UserDefaults.standard.string(forKey: DELAY_CONDITION_PREFERENCES) ?? "[]"
|
|
479
|
+
|
|
480
|
+
let delayConditionList: [DelayCondition] = fromJsonArr(json: delayUpdatePreferences).map { obj -> DelayCondition in
|
|
481
|
+
let kind: String = obj.value(forKey: "kind") as! String
|
|
482
|
+
let value: String? = obj.value(forKey: "value") as? String
|
|
483
|
+
return DelayCondition(kind: kind, value: value)
|
|
484
|
+
}
|
|
485
|
+
var backgroundValue: String?
|
|
486
|
+
for delayCondition in delayConditionList {
|
|
487
|
+
if delayCondition.getKind() == "background" {
|
|
488
|
+
let value: String? = delayCondition.getValue()
|
|
489
|
+
backgroundValue = (value != nil && value != "") ? value! : "0"
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
if backgroundValue != nil {
|
|
493
|
+
self.taskRunning = true
|
|
494
|
+
let interval: Double = (Double(backgroundValue!) ?? 0.0) / 1000
|
|
495
|
+
self.backgroundWork?.cancel()
|
|
496
|
+
self.backgroundWork = DispatchWorkItem(block: {
|
|
497
|
+
// IOS never executes this task in background
|
|
498
|
+
self.taskRunning = false
|
|
499
|
+
self._checkCancelDelay(killed: false)
|
|
500
|
+
self.installNext()
|
|
501
|
+
})
|
|
502
|
+
DispatchQueue.global(qos: .background).asyncAfter(deadline: .now() + interval, execute: self.backgroundWork!)
|
|
503
|
+
} else {
|
|
504
|
+
self._checkCancelDelay(killed: false)
|
|
505
|
+
self.installNext()
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
private func installNext() {
|
|
511
|
+
let delayUpdatePreferences = UserDefaults.standard.string(forKey: DELAY_CONDITION_PREFERENCES) ?? "[]"
|
|
512
|
+
let delayConditionList: [DelayCondition]? = fromJsonArr(json: delayUpdatePreferences).map { obj -> DelayCondition in
|
|
513
|
+
let kind: String = obj.value(forKey: "kind") as! String
|
|
514
|
+
let value: String? = obj.value(forKey: "value") as? String
|
|
515
|
+
return DelayCondition(kind: kind, value: value)
|
|
516
|
+
}
|
|
517
|
+
if delayConditionList != nil && delayConditionList?.capacity != 0 {
|
|
426
518
|
print("\(self.implementation.TAG) Update delayed to next backgrounding")
|
|
427
519
|
return
|
|
428
520
|
}
|
|
429
|
-
|
|
430
521
|
let current: BundleInfo = self.implementation.getCurrentBundle()
|
|
431
522
|
let next: BundleInfo? = self.implementation.getNextBundle()
|
|
432
523
|
|
|
@@ -440,4 +531,20 @@ public class CapacitorUpdaterPlugin: CAPPlugin {
|
|
|
440
531
|
}
|
|
441
532
|
}
|
|
442
533
|
}
|
|
534
|
+
|
|
535
|
+
@objc private func toJson(object: Any) -> String {
|
|
536
|
+
guard let data = try? JSONSerialization.data(withJSONObject: object, options: []) else {
|
|
537
|
+
return ""
|
|
538
|
+
}
|
|
539
|
+
return String(data: data, encoding: String.Encoding.utf8) ?? ""
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
@objc private func fromJsonArr(json: String) -> [NSObject] {
|
|
543
|
+
let jsonData = json.data(using: .utf8)!
|
|
544
|
+
let object = try? JSONSerialization.jsonObject(
|
|
545
|
+
with: jsonData,
|
|
546
|
+
options: .mutableContainers
|
|
547
|
+
) as? [NSObject]
|
|
548
|
+
return object ?? []
|
|
549
|
+
}
|
|
443
550
|
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
//
|
|
2
|
+
// DelayCondition.swift
|
|
3
|
+
// Plugin
|
|
4
|
+
//
|
|
5
|
+
// Created by Luca Peruzzo on 12/09/22.
|
|
6
|
+
// Copyright © 2022 Capgo. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
import Foundation
|
|
10
|
+
|
|
11
|
+
private func delayUntilNextValue(value: String) -> DelayUntilNext {
|
|
12
|
+
switch value {
|
|
13
|
+
case "background": return .background
|
|
14
|
+
case "kill": return .kill
|
|
15
|
+
case "nativeVersion": return .nativeVersion
|
|
16
|
+
case "date": return .date
|
|
17
|
+
default:
|
|
18
|
+
return .background
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@objc public class DelayCondition: NSObject, Decodable, Encodable {
|
|
23
|
+
private let kind: DelayUntilNext
|
|
24
|
+
private let value: String?
|
|
25
|
+
|
|
26
|
+
convenience init(kind: String, value: String?) {
|
|
27
|
+
self.init(kind: delayUntilNextValue(value: kind), value: value)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
init(kind: DelayUntilNext, value: String?) {
|
|
31
|
+
self.kind = kind
|
|
32
|
+
self.value = value
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public required init(from decoder: Decoder) throws {
|
|
36
|
+
let values = try decoder.container(keyedBy: CodingKeys.self)
|
|
37
|
+
kind = try values.decode(DelayUntilNext.self, forKey: .kind)
|
|
38
|
+
value = try values.decode(String.self, forKey: .value)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
enum CodingKeys: String, CodingKey {
|
|
42
|
+
case kind, value
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
public func getKind() -> String {
|
|
46
|
+
return self.kind.description
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public func getValue() -> String? {
|
|
50
|
+
return self.value
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
public func toJSON() -> [String: String] {
|
|
54
|
+
return [
|
|
55
|
+
"kind": self.getKind(),
|
|
56
|
+
"value": self.getValue() ?? ""
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
public static func == (lhs: DelayCondition, rhs: DelayCondition) -> Bool {
|
|
61
|
+
return lhs.getKind() == rhs.getKind() && lhs.getValue() == rhs.getValue()
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
public func toString() -> String {
|
|
65
|
+
return "{ \"kind\": \"\(self.getKind())\", \"value\": \"\(self.getValue() ?? "")\"}"
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
//
|
|
2
|
+
// DelayUntilNext.swift
|
|
3
|
+
// Plugin
|
|
4
|
+
//
|
|
5
|
+
// Created by Luca Peruzzo on 12/09/22.
|
|
6
|
+
// Copyright © 2022 Capgo. All rights reserved.
|
|
7
|
+
//
|
|
8
|
+
|
|
9
|
+
import Foundation
|
|
10
|
+
enum DelayUntilNext: Decodable, Encodable, CustomStringConvertible {
|
|
11
|
+
case background
|
|
12
|
+
case kill
|
|
13
|
+
case nativeVersion
|
|
14
|
+
case date
|
|
15
|
+
|
|
16
|
+
var description: String {
|
|
17
|
+
switch self {
|
|
18
|
+
case .background: return "background"
|
|
19
|
+
case .kill: return "kill"
|
|
20
|
+
case .nativeVersion: return "nativeVersion"
|
|
21
|
+
case .date: return "date"
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|