@capgo/capacitor-updater 3.3.11 → 4.0.0-alpha.10

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.
@@ -10,6 +10,11 @@ extension URL {
10
10
  return FileManager().fileExists(atPath: self.path)
11
11
  }
12
12
  }
13
+ extension Date {
14
+ func adding(minutes: Int) -> Date {
15
+ return Calendar.current.date(byAdding: .minute, value: minutes, to: self)!
16
+ }
17
+ }
13
18
  struct AppVersionDec: Decodable {
14
19
  let version: String?
15
20
  let url: String?
@@ -22,6 +27,20 @@ public class AppVersion: NSObject {
22
27
  var message: String?
23
28
  var major: Bool?
24
29
  }
30
+
31
+ extension AppVersion {
32
+ func toDict() -> [String:Any] {
33
+ var dict = [String:Any]()
34
+ let otherSelf = Mirror(reflecting: self)
35
+ for child in otherSelf.children {
36
+ if let key = child.label {
37
+ dict[key] = child.value
38
+ }
39
+ }
40
+ return dict
41
+ }
42
+ }
43
+
25
44
  extension OperatingSystemVersion {
26
45
  func getFullVersion(separator: String = ".") -> String {
27
46
  return "\(majorVersion)\(separator)\(minorVersion)\(separator)\(patchVersion)"
@@ -36,9 +55,43 @@ extension Bundle {
36
55
  }
37
56
  }
38
57
 
58
+ extension ISO8601DateFormatter {
59
+ convenience init(_ formatOptions: Options) {
60
+ self.init()
61
+ self.formatOptions = formatOptions
62
+ }
63
+ }
64
+ extension Formatter {
65
+ static let iso8601withFractionalSeconds = ISO8601DateFormatter([.withInternetDateTime, .withFractionalSeconds])
66
+ }
67
+ extension Date {
68
+ var iso8601withFractionalSeconds: String { return Formatter.iso8601withFractionalSeconds.string(from: self) }
69
+ }
70
+ extension String {
71
+
72
+ var fileURL: URL {
73
+ return URL(fileURLWithPath: self)
74
+ }
75
+
76
+ var lastPathComponent:String {
77
+ get {
78
+ return fileURL.lastPathComponent
79
+ }
80
+ }
81
+ var iso8601withFractionalSeconds: Date? {
82
+ return Formatter.iso8601withFractionalSeconds.date(from: self)
83
+ }
84
+ func trim(using characterSet: CharacterSet = .whitespacesAndNewlines) -> String {
85
+ return trimmingCharacters(in: characterSet)
86
+ }
87
+ }
88
+
39
89
  enum CustomError: Error {
40
90
  // Throw when an unzip fail
41
91
  case cannotUnzip
92
+ case cannotUnflat
93
+ case cannotCreateDirectory
94
+ case cannotDeleteDirectory
42
95
 
43
96
  // Throw in all other cases
44
97
  case unexpected(code: Int)
@@ -52,6 +105,21 @@ extension CustomError: LocalizedError {
52
105
  "The file cannot be unzip",
53
106
  comment: "Invalid zip"
54
107
  )
108
+ case .cannotCreateDirectory:
109
+ return NSLocalizedString(
110
+ "The folder cannot be created",
111
+ comment: "Invalid folder"
112
+ )
113
+ case .cannotDeleteDirectory:
114
+ return NSLocalizedString(
115
+ "The folder cannot be deleted",
116
+ comment: "Invalid folder"
117
+ )
118
+ case .cannotUnflat:
119
+ return NSLocalizedString(
120
+ "The file cannot be unflat",
121
+ comment: "Invalid folder"
122
+ )
55
123
  case .unexpected(_):
56
124
  return NSLocalizedString(
57
125
  "An unexpected error occurred.",
@@ -63,21 +131,29 @@ extension CustomError: LocalizedError {
63
131
 
64
132
  @objc public class CapacitorUpdater: NSObject {
65
133
 
66
- private var versionBuild = Bundle.main.releaseVersionNumber ?? ""
67
- private var versionCode = Bundle.main.buildVersionNumber ?? ""
68
- private var versionOs = ProcessInfo().operatingSystemVersion.getFullVersion()
134
+ private let versionBuild = Bundle.main.releaseVersionNumber ?? ""
135
+ private let versionCode = Bundle.main.buildVersionNumber ?? ""
136
+ private let versionOs = ProcessInfo().operatingSystemVersion.getFullVersion()
137
+ private let documentsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
138
+ private let libraryDir = FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask).first!
139
+ private let bundleDirectoryHot = "versions"
140
+ private let DEFAULT_FOLDER = ""
141
+ private let bundleDirectory = "NoCloud/ionic_built_snapshots"
142
+ private let INFO_SUFFIX = "_info"
143
+ private let FALLBACK_VERSION = "pastVersion"
144
+ private let NEXT_VERSION = "nextVersion"
145
+
69
146
  private var lastPathHot = ""
70
147
  private var lastPathPersist = ""
71
- private let basePathHot = "versions"
72
- private let basePathPersist = "NoCloud/ionic_built_snapshots"
73
- private let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
74
- private let libraryUrl = FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask).first!
75
148
 
149
+ public let TAG = "✨ Capacitor-updater:";
150
+ public let CAP_SERVER_PATH = "serverBasePath"
151
+ public let pluginVersion = "4.0.0-alpha.10"
76
152
  public var statsUrl = ""
77
153
  public var appId = ""
78
154
  public var deviceID = UIDevice.current.identifierForVendor?.uuidString ?? ""
79
- public var notifyDownload: (Int) -> Void = { _ in }
80
- public var pluginVersion = "3.2.0"
155
+
156
+ public var notifyDownload: (String, Int) -> Void = { _,_ in }
81
157
 
82
158
  private func calcTotalPercent(percent: Int, min: Int, max: Int) -> Int {
83
159
  return (percent * (max - min)) / 100 + min;
@@ -92,25 +168,27 @@ extension CustomError: LocalizedError {
92
168
  // Hot Reload path /var/mobile/Containers/Data/Application/8C0C07BE-0FD3-4FD4-B7DF-90A88E12B8C3/Documents/FOLDER
93
169
  // Normal /private/var/containers/Bundle/Application/8C0C07BE-0FD3-4FD4-B7DF-90A88E12B8C3/App.app/public
94
170
 
95
- private func prepareFolder(source: URL) {
171
+ private func prepareFolder(source: URL) throws {
96
172
  if (!FileManager.default.fileExists(atPath: source.path)) {
97
173
  do {
98
174
  try FileManager.default.createDirectory(atPath: source.path, withIntermediateDirectories: true, attributes: nil)
99
175
  } catch {
100
- print("✨ Capacitor-updater: Cannot createDirectory \(source.path)")
176
+ print("\(self.TAG) Cannot createDirectory \(source.path)")
177
+ throw CustomError.cannotCreateDirectory
101
178
  }
102
179
  }
103
180
  }
104
181
 
105
- private func deleteFolder(source: URL) {
182
+ private func deleteFolder(source: URL) throws {
106
183
  do {
107
184
  try FileManager.default.removeItem(atPath: source.path)
108
185
  } catch {
109
- print("✨ Capacitor-updater: File not removed. \(source.path)")
186
+ print("\(self.TAG) File not removed. \(source.path)")
187
+ throw CustomError.cannotDeleteDirectory
110
188
  }
111
189
  }
112
190
 
113
- private func unflatFolder(source: URL, dest: URL) -> Bool {
191
+ private func unflatFolder(source: URL, dest: URL) throws -> Bool {
114
192
  let index = source.appendingPathComponent("index.html")
115
193
  do {
116
194
  let files = try FileManager.default.contentsOfDirectory(atPath: source.path)
@@ -122,37 +200,37 @@ extension CustomError: LocalizedError {
122
200
  return false
123
201
  }
124
202
  } catch {
125
- print("✨ Capacitor-updater: File not moved. source: \(source.path) dest: \(dest.path)")
126
- return true
203
+ print("\(self.TAG) File not moved. source: \(source.path) dest: \(dest.path)")
204
+ throw CustomError.cannotUnflat
127
205
  }
128
206
  }
129
207
 
130
- private func saveDownloaded(sourceZip: URL, version: String, base: URL) throws {
131
- prepareFolder(source: base)
132
- let destHot = base.appendingPathComponent(version)
133
- let destUnZip = documentsUrl.appendingPathComponent(randomString(length: 10))
208
+ private func saveDownloaded(sourceZip: URL, id: String, base: URL) throws {
209
+ try prepareFolder(source: base)
210
+ let destHot = base.appendingPathComponent(id)
211
+ let destUnZip = documentsDir.appendingPathComponent(randomString(length: 10))
134
212
  if (!SSZipArchive.unzipFile(atPath: sourceZip.path, toDestination: destUnZip.path)) {
135
213
  throw CustomError.cannotUnzip
136
214
  }
137
- if (unflatFolder(source: destUnZip, dest: destHot)) {
138
- deleteFolder(source: destUnZip)
215
+ if (try unflatFolder(source: destUnZip, dest: destHot)) {
216
+ try deleteFolder(source: destUnZip)
139
217
  }
140
218
  }
141
219
 
142
220
  public func getLatest(url: URL) -> AppVersion? {
143
221
  let semaphore = DispatchSemaphore(value: 0)
144
222
  let latest = AppVersion()
145
- let headers: HTTPHeaders = [
146
- "cap_platform": "ios",
147
- "cap_device_id": self.deviceID,
148
- "cap_app_id": self.appId,
149
- "cap_version_build": self.versionBuild,
150
- "cap_version_code": self.versionCode,
151
- "cap_version_os": self.versionOs,
152
- "cap_plugin_version": self.pluginVersion,
153
- "cap_version_name": UserDefaults.standard.string(forKey: "versionName") ?? "builtin"
223
+ let parameters: [String: String] = [
224
+ "platform": "ios",
225
+ "device_id": self.deviceID,
226
+ "app_id": self.appId,
227
+ "version_build": self.versionBuild,
228
+ "version_code": self.versionCode,
229
+ "version_os": self.versionOs,
230
+ "plugin_version": self.pluginVersion,
231
+ "version_name": self.getCurrentBundle().getVersionName()
154
232
  ]
155
- let request = AF.request(url, headers: headers)
233
+ let request = AF.request(url, method: .post,parameters: parameters, encoder: JSONParameterEncoder.default)
156
234
 
157
235
  request.validate().responseDecodable(of: AppVersionDec.self) { response in
158
236
  switch response.result {
@@ -168,9 +246,10 @@ extension CustomError: LocalizedError {
168
246
  }
169
247
  if let message = response.value?.message {
170
248
  latest.message = message
249
+ print("\(self.TAG) Auto-update message: \(message)")
171
250
  }
172
251
  case let .failure(error):
173
- print("✨ Capacitor-updater: Error getting Latest", error )
252
+ print("\(self.TAG) Error getting Latest", error )
174
253
  }
175
254
  semaphore.signal()
176
255
  }
@@ -178,9 +257,15 @@ extension CustomError: LocalizedError {
178
257
  return latest.url != "" ? latest : nil
179
258
  }
180
259
 
181
- public func download(url: URL) throws -> String {
260
+ private func setCurrentBundle(bundle: String) {
261
+ UserDefaults.standard.set(bundle, forKey: self.CAP_SERVER_PATH)
262
+ print("\(self.TAG) Current bundle set to: \(bundle)")
263
+ UserDefaults.standard.synchronize()
264
+ }
265
+
266
+ public func download(url: URL, version: String) throws -> BundleInfo {
182
267
  let semaphore = DispatchSemaphore(value: 0)
183
- var version: String = ""
268
+ let id: String = self.randomString(length: 10)
184
269
  var mainError: NSError? = nil
185
270
  let destination: DownloadRequest.Destination = { _, _ in
186
271
  let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
@@ -192,112 +277,150 @@ extension CustomError: LocalizedError {
192
277
 
193
278
  request.downloadProgress { progress in
194
279
  let percent = self.calcTotalPercent(percent: Int(progress.fractionCompleted * 100), min: 10, max: 70)
195
- self.notifyDownload(percent)
280
+ self.notifyDownload(id, percent)
196
281
  }
197
282
  request.responseURL { (response) in
198
283
  if let fileURL = response.fileURL {
199
284
  switch response.result {
200
285
  case .success:
201
- self.notifyDownload(71);
202
- version = self.randomString(length: 10)
286
+ self.notifyDownload(id, 71)
203
287
  do {
204
- try self.saveDownloaded(sourceZip: fileURL, version: version, base: self.documentsUrl.appendingPathComponent(self.basePathHot))
205
- self.notifyDownload(85);
206
- try self.saveDownloaded(sourceZip: fileURL, version: version, base: self.libraryUrl.appendingPathComponent(self.basePathPersist))
207
- self.notifyDownload(100);
208
- self.deleteFolder(source: fileURL)
288
+ try self.saveDownloaded(sourceZip: fileURL, id: id, base: self.documentsDir.appendingPathComponent(self.bundleDirectoryHot))
289
+ self.notifyDownload(id, 85)
290
+ try self.saveDownloaded(sourceZip: fileURL, id: id, base: self.libraryDir.appendingPathComponent(self.bundleDirectory))
291
+ self.notifyDownload(id, 100)
292
+ try self.deleteFolder(source: fileURL)
209
293
  } catch {
210
- print("✨ Capacitor-updater: download unzip error", error)
294
+ print("\(self.TAG) download unzip error", error)
211
295
  mainError = error as NSError
212
296
  }
213
297
  case let .failure(error):
214
- print("✨ Capacitor-updater: download error", error)
298
+ print("\(self.TAG) download error", error)
215
299
  mainError = error as NSError
216
300
  }
217
301
  }
218
302
  semaphore.signal()
219
303
  }
220
- self.notifyDownload(0);
304
+ self.saveBundleInfo(id: id, bundle: BundleInfo(id: id, version: version, status: BundleStatus.DOWNLOADING, downloaded: Date()))
305
+ self.notifyDownload(id, 0)
221
306
  semaphore.wait()
222
307
  if (mainError != nil) {
223
308
  throw mainError!
224
309
  }
225
- return version
310
+ let info: BundleInfo = BundleInfo(id: id, version: version, status: BundleStatus.PENDING, downloaded: Date())
311
+ self.saveBundleInfo(id: id, bundle: info)
312
+ return info
226
313
  }
227
314
 
228
- public func list() -> [String] {
229
- let dest = documentsUrl.appendingPathComponent(basePathHot)
315
+ public func list() -> [BundleInfo] {
316
+ let dest = documentsDir.appendingPathComponent(bundleDirectoryHot)
230
317
  do {
231
318
  let files = try FileManager.default.contentsOfDirectory(atPath: dest.path)
232
- return files
319
+ var res: [BundleInfo] = []
320
+ print("\(self.TAG) list File : \(dest.path)")
321
+ if (dest.exist) {
322
+ for id in files {
323
+ res.append(self.getBundleInfo(id: id));
324
+ }
325
+ }
326
+ return res
233
327
  } catch {
234
- print("✨ Capacitor-updater: No version available \(dest.path)")
328
+ print("\(self.TAG) No version available \(dest.path)")
235
329
  return []
236
330
  }
237
331
  }
238
332
 
239
- public func delete(version: String, versionName: String) -> Bool {
240
- let destHot = documentsUrl.appendingPathComponent(basePathHot).appendingPathComponent(version)
241
- let destPersist = libraryUrl.appendingPathComponent(basePathPersist).appendingPathComponent(version)
333
+ public func delete(id: String) -> Bool {
334
+ let deleted: BundleInfo = self.getBundleInfo(id: id)
335
+ let destHot = documentsDir.appendingPathComponent(bundleDirectoryHot).appendingPathComponent(id)
336
+ let destPersist = libraryDir.appendingPathComponent(bundleDirectory).appendingPathComponent(id)
242
337
  do {
243
338
  try FileManager.default.removeItem(atPath: destHot.path)
244
339
  } catch {
245
- print("✨ Capacitor-updater: Hot Folder \(destHot.path), not removed.")
340
+ print("\(self.TAG) Hot Folder \(destHot.path), not removed.")
246
341
  }
247
342
  do {
248
343
  try FileManager.default.removeItem(atPath: destPersist.path)
249
344
  } catch {
250
- print("✨ Capacitor-updater: Folder \(destPersist.path), not removed.")
345
+ print("\(self.TAG) Folder \(destPersist.path), not removed.")
251
346
  return false
252
347
  }
253
- sendStats(action: "delete", version: versionName)
348
+ self.removeBundleInfo(id: id)
349
+ self.sendStats(action: "delete", versionName: deleted.getVersionName())
254
350
  return true
255
351
  }
256
352
 
257
- public func set(version: String, versionName: String) -> Bool {
258
- let destHot = documentsUrl.appendingPathComponent(basePathHot).appendingPathComponent(version)
353
+ public func getBundleDirectory(id: String) -> URL {
354
+ return libraryDir.appendingPathComponent(self.bundleDirectory).appendingPathComponent(id)
355
+ }
356
+
357
+ public func set(bundle: BundleInfo) -> Bool {
358
+ return self.set(id: bundle.getId());
359
+ }
360
+
361
+ private func bundleExists(id: String) -> Bool {
362
+ let destHot = self.getPathHot(id: id)
363
+ let destHotPersist = self.getPathPersist(id: id)
259
364
  let indexHot = destHot.appendingPathComponent("index.html")
260
- let destHotPersist = libraryUrl.appendingPathComponent(basePathPersist).appendingPathComponent(version)
261
365
  let indexPersist = destHotPersist.appendingPathComponent("index.html")
262
- if (destHot.isDirectory && destHotPersist.isDirectory && indexHot.exist && indexPersist.exist) {
263
- UserDefaults.standard.set(destHot.path, forKey: "lastPathHot")
264
- UserDefaults.standard.set(destHotPersist.path, forKey: "lastPathPersist")
265
- UserDefaults.standard.set(versionName, forKey: "versionName")
266
- sendStats(action: "set", version: versionName)
366
+ let url: URL = self.getBundleDirectory(id: id)
367
+ if(url.isDirectory && destHotPersist.isDirectory && indexHot.exist && indexPersist.exist) {
368
+ return true;
369
+ }
370
+ return false;
371
+ }
372
+
373
+ public func set(id: String) -> Bool {
374
+ let newBundle: BundleInfo = self.getBundleInfo(id: id)
375
+ if (bundleExists(id: id)) {
376
+ let url: URL = self.getBundleDirectory(id: id)
377
+ self.setCurrentBundle(bundle: String(url.path.suffix(10)))
378
+ self.setBundleStatus(id: id, status: BundleStatus.PENDING)
379
+ sendStats(action: "set", versionName: newBundle.getVersionName())
267
380
  return true
268
381
  }
269
- sendStats(action: "set_fail", version: versionName)
382
+ sendStats(action: "set_fail", versionName: newBundle.getVersionName())
270
383
  return false
271
384
  }
272
385
 
273
- public func getLastPathHot() -> String {
274
- return UserDefaults.standard.string(forKey: "lastPathHot") ?? ""
386
+ public func getPathHot(id: String) -> URL {
387
+ return documentsDir.appendingPathComponent(self.bundleDirectoryHot).appendingPathComponent(id)
275
388
  }
276
389
 
277
- public func getVersionName() -> String {
278
- return UserDefaults.standard.string(forKey: "versionName") ?? ""
390
+ public func getPathPersist(id: String) -> URL {
391
+ return libraryDir.appendingPathComponent(self.bundleDirectory).appendingPathComponent(id)
279
392
  }
280
393
 
281
- public func getLastPathPersist() -> String {
282
- return UserDefaults.standard.string(forKey: "lastPathPersist") ?? ""
394
+ public func reset() {
395
+ self.reset(isInternal: false)
283
396
  }
284
397
 
285
- public func reset() {
286
- let version = UserDefaults.standard.string(forKey: "versionName") ?? ""
287
- sendStats(action: "reset", version: version)
288
- UserDefaults.standard.set("", forKey: "lastPathHot")
289
- UserDefaults.standard.set("", forKey: "lastPathPersist")
290
- UserDefaults.standard.set("", forKey: "versionName")
398
+ public func reset(isInternal: Bool) {
399
+ self.setCurrentBundle(bundle: "")
400
+ self.setFallbackVersion(fallback: Optional<BundleInfo>.none)
401
+ let _ = self.setNextVersion(next: Optional<String>.none)
291
402
  UserDefaults.standard.synchronize()
403
+ if(!isInternal) {
404
+ sendStats(action: "reset", versionName: self.getCurrentBundle().getVersionName())
405
+ }
406
+ }
407
+
408
+ public func commit(bundle: BundleInfo) {
409
+ self.setBundleStatus(id: bundle.getId(), status: BundleStatus.SUCCESS)
410
+ self.setFallbackVersion(fallback: bundle)
411
+ }
412
+
413
+ public func rollback(bundle: BundleInfo) {
414
+ self.setBundleStatus(id: bundle.getId(), status: BundleStatus.ERROR);
292
415
  }
293
416
 
294
- func sendStats(action: String, version: String) {
417
+ func sendStats(action: String, versionName: String) {
295
418
  if (statsUrl == "") { return }
296
419
  let parameters: [String: String] = [
297
420
  "platform": "ios",
298
421
  "action": action,
299
422
  "device_id": self.deviceID,
300
- "version_name": version,
423
+ "version_name": versionName,
301
424
  "version_build": self.versionBuild,
302
425
  "version_code": self.versionCode,
303
426
  "version_os": self.versionOs,
@@ -307,8 +430,122 @@ extension CustomError: LocalizedError {
307
430
 
308
431
  DispatchQueue.global(qos: .background).async {
309
432
  let _ = AF.request(self.statsUrl, method: .post,parameters: parameters, encoder: JSONParameterEncoder.default)
310
- print("✨ Capacitor-updater: Stats send for \(action), version \(version)")
433
+ print("\(self.TAG) Stats send for \(action), version \(versionName)")
311
434
  }
312
435
  }
313
-
436
+
437
+ public func getBundleInfo(id: String = BundleInfo.ID_BUILTIN) -> BundleInfo {
438
+ print("\(self.TAG) Getting info for bundle [\(id)]")
439
+ if(BundleInfo.ID_BUILTIN == id) {
440
+ return BundleInfo(id: id, version: "", status: BundleStatus.SUCCESS)
441
+ }
442
+ do {
443
+ let result: BundleInfo = try UserDefaults.standard.getObj(forKey: "\(id)\(self.INFO_SUFFIX)", castTo: BundleInfo.self)
444
+ print("\(self.TAG) Returning info bundle [\(id)]", result.toString())
445
+ return result
446
+ } catch {
447
+ print("\(self.TAG) Failed to parse info for bundle [\(id)]", error.localizedDescription)
448
+ return BundleInfo(id: id, version: "", status: BundleStatus.PENDING)
449
+ }
450
+ }
451
+
452
+ public func getBundleInfoByVersionName(version: String) -> BundleInfo? {
453
+ let installed : Array<BundleInfo> = self.list()
454
+ for i in installed {
455
+ if(i.getVersionName() == version) {
456
+ return i
457
+ }
458
+ }
459
+ return nil
460
+ }
461
+
462
+ private func removeBundleInfo(id: String) {
463
+ self.saveBundleInfo(id: id, bundle: nil)
464
+ }
465
+
466
+ private func saveBundleInfo(id: String, bundle: BundleInfo?) {
467
+ if (bundle != nil && (bundle!.isBuiltin() || bundle!.isUnknown())) {
468
+ print("\(self.TAG) Not saving info for bundle [\(id)]", bundle!.toString())
469
+ return
470
+ }
471
+ if(bundle == nil) {
472
+ print("\(self.TAG) Removing info for bundle [\(id)]")
473
+ UserDefaults.standard.removeObject(forKey: "\(id)\(self.INFO_SUFFIX)")
474
+ } else {
475
+ let update = bundle!.setId(id: id)
476
+ print("\(self.TAG) Storing info for bundle [\(id)]", update.toString())
477
+ do {
478
+ try UserDefaults.standard.setObj(update, forKey: "\(id)\(self.INFO_SUFFIX)")
479
+ } catch {
480
+ print("\(self.TAG) Failed to save info for bundle [\(id)]", error.localizedDescription)
481
+ }
482
+ }
483
+ UserDefaults.standard.synchronize()
484
+ }
485
+
486
+ public func setVersionName(id: String, version: String) {
487
+ print("\(self.TAG) Setting version for folder [\(id)] to \(version)")
488
+ let info = self.getBundleInfo(id: id)
489
+ self.saveBundleInfo(id: id, bundle: info.setVersionName(version: version))
490
+ }
491
+
492
+ private func setBundleStatus(id: String, status: BundleStatus) {
493
+ print("\(self.TAG) Setting status for bundle [\(id)] to \(status)")
494
+ let info = self.getBundleInfo(id: id)
495
+ self.saveBundleInfo(id: id, bundle: info.setStatus(status: status.localizedString))
496
+ }
497
+
498
+ private func getCurrentBundleVersion() -> String {
499
+ if(self.isUsingBuiltin()) {
500
+ return BundleInfo.ID_BUILTIN
501
+ } else {
502
+ let path: String = self.getCurrentBundleId()
503
+ return path.lastPathComponent
504
+ }
505
+ }
506
+
507
+ public func getCurrentBundle() -> BundleInfo {
508
+ return self.getBundleInfo(id: self.getCurrentBundleId());
509
+ }
510
+
511
+ public func getCurrentBundleId() -> String {
512
+ return UserDefaults.standard.string(forKey: self.CAP_SERVER_PATH) ?? self.DEFAULT_FOLDER
513
+ }
514
+
515
+ public func isUsingBuiltin() -> Bool {
516
+ return self.getCurrentBundleId() == self.DEFAULT_FOLDER
517
+ }
518
+
519
+ public func getFallbackVersion() -> BundleInfo {
520
+ let id: String = UserDefaults.standard.string(forKey: self.FALLBACK_VERSION) ?? BundleInfo.ID_BUILTIN
521
+ return self.getBundleInfo(id: id)
522
+ }
523
+
524
+ private func setFallbackVersion(fallback: BundleInfo?) {
525
+ UserDefaults.standard.set(fallback == nil ? BundleInfo.ID_BUILTIN : fallback!.getId(), forKey: self.FALLBACK_VERSION)
526
+ }
527
+
528
+ public func getNextVersion() -> BundleInfo? {
529
+ let id: String = UserDefaults.standard.string(forKey: self.NEXT_VERSION) ?? ""
530
+ if(id != "") {
531
+ return self.getBundleInfo(id: id)
532
+ } else {
533
+ return nil
534
+ }
535
+ }
536
+
537
+ public func setNextVersion(next: String?) -> Bool {
538
+ if (next == nil) {
539
+ UserDefaults.standard.removeObject(forKey: self.NEXT_VERSION)
540
+ } else {
541
+ let bundle: URL = self.getBundleDirectory(id: next!)
542
+ if (!bundle.exist) {
543
+ return false
544
+ }
545
+ UserDefaults.standard.set(next, forKey: self.NEXT_VERSION)
546
+ self.setBundleStatus(id: next!, status: BundleStatus.PENDING);
547
+ }
548
+ UserDefaults.standard.synchronize()
549
+ return true
550
+ }
314
551
  }
@@ -11,9 +11,11 @@ CAP_PLUGIN(CapacitorUpdaterPlugin, "CapacitorUpdater",
11
11
  CAP_PLUGIN_METHOD(reset, CAPPluginReturnPromise);
12
12
  CAP_PLUGIN_METHOD(current, CAPPluginReturnPromise);
13
13
  CAP_PLUGIN_METHOD(reload, CAPPluginReturnPromise);
14
- CAP_PLUGIN_METHOD(versionName, CAPPluginReturnPromise);
15
14
  CAP_PLUGIN_METHOD(notifyAppReady, CAPPluginReturnPromise);
16
- CAP_PLUGIN_METHOD(delayUpdate, CAPPluginReturnPromise);
15
+ CAP_PLUGIN_METHOD(setDelay, CAPPluginReturnPromise);
16
+ CAP_PLUGIN_METHOD(getLatest, CAPPluginReturnPromise);
17
17
  CAP_PLUGIN_METHOD(getId, CAPPluginReturnPromise);
18
18
  CAP_PLUGIN_METHOD(getPluginVersion, CAPPluginReturnPromise);
19
+ CAP_PLUGIN_METHOD(next, CAPPluginReturnPromise);
20
+ CAP_PLUGIN_METHOD(isAutoUpdateEnabled, CAPPluginReturnPromise);
19
21
  )