@capgo/capacitor-updater 8.44.0 → 8.45.1

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.
@@ -72,7 +72,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
72
72
  CAPPluginMethod(name: "completeFlexibleUpdate", returnType: CAPPluginReturnPromise)
73
73
  ]
74
74
  public var implementation = CapgoUpdater()
75
- private let pluginVersion: String = "8.44.0"
75
+ private let pluginVersion: String = "8.45.1"
76
76
  static let updateUrlDefault = "https://plugin.capgo.app/updates"
77
77
  static let statsUrlDefault = "https://plugin.capgo.app/stats"
78
78
  static let channelUrlDefault = "https://plugin.capgo.app/channel_self"
@@ -102,7 +102,11 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
102
102
  private var autoSplashscreenTimeoutWorkItem: DispatchWorkItem?
103
103
  private var splashscreenLoaderView: UIActivityIndicatorView?
104
104
  private var splashscreenLoaderContainer: UIView?
105
+ private let splashscreenPluginName = "SplashScreen"
106
+ private let splashscreenRetryDelayMilliseconds = 100
107
+ private let splashscreenMaxRetries = 20
105
108
  private var autoSplashscreenTimedOut = false
109
+ private var splashscreenInvocationToken = 0
106
110
  private var autoDeleteFailed = false
107
111
  private var autoDeletePrevious = false
108
112
  var allowSetDefaultChannel = true
@@ -111,6 +115,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
111
115
  private var taskRunning = false
112
116
  private var periodCheckDelay = 0
113
117
  private let downloadLock = NSLock()
118
+ private let onLaunchDirectUpdateStateLock = NSLock()
114
119
  private var downloadInProgress = false
115
120
  private var downloadStartTime: Date?
116
121
  private let downloadTimeout: TimeInterval = 3600 // 1 hour timeout
@@ -742,8 +747,11 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
742
747
  if !res {
743
748
  logger.info("Bundle successfully set to: \(id) ")
744
749
  call.reject("Update failed, id \(id) doesn't exist")
750
+ } else if !self._reload() {
751
+ call.reject("Reload failed after setting bundle \(id)")
745
752
  } else {
746
- self.reload(call)
753
+ self.notifyBundleSet(self.implementation.getBundleInfo(id: id))
754
+ call.resolve()
747
755
  }
748
756
  }
749
757
 
@@ -938,7 +946,11 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
938
946
  // the built-in bundle, set it as the bundle to use and reload.
939
947
  if toLastSuccessful && !fallback.isBuiltin() {
940
948
  logger.info("Resetting to: \(fallback.toString())")
941
- return self.implementation.set(bundle: fallback) && self._reload()
949
+ if self.implementation.set(bundle: fallback) && self._reload() {
950
+ self.notifyBundleSet(fallback)
951
+ return true
952
+ }
953
+ return false
942
954
  }
943
955
 
944
956
  logger.info("Resetting to builtin version")
@@ -1097,6 +1109,10 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
1097
1109
  self.backgroundTaskID = UIBackgroundTaskIdentifier.invalid
1098
1110
  }
1099
1111
 
1112
+ private func notifyBundleSet(_ bundle: BundleInfo) {
1113
+ self.notifyListeners("set", data: ["bundle": bundle.toJSON()], retainUntilConsumed: true)
1114
+ }
1115
+
1100
1116
  func sendReadyToJs(current: BundleInfo, msg: String) {
1101
1117
  logger.info("sendReadyToJs")
1102
1118
  DispatchQueue.global().async {
@@ -1124,32 +1140,14 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
1124
1140
  private func performHideSplashscreen() {
1125
1141
  self.cancelSplashscreenTimeout()
1126
1142
  self.removeSplashscreenLoader()
1127
-
1128
- guard let bridge = self.bridge else {
1129
- self.logger.warn("Bridge not available for hiding splashscreen with autoSplashscreen")
1130
- return
1131
- }
1132
-
1133
- // Create a plugin call for the hide method
1134
- let call = CAPPluginCall(callbackId: "autoHideSplashscreen", options: [:], success: { (_, _) in
1135
- self.logger.info("Splashscreen hidden automatically")
1136
- }, error: { (_) in
1137
- self.logger.error("Failed to auto-hide splashscreen")
1138
- })
1139
-
1140
- // Try to call the SplashScreen hide method directly through the bridge
1141
- if let splashScreenPlugin = bridge.plugin(withName: "SplashScreen") {
1142
- // Use runtime method invocation to call hide method
1143
- let selector = NSSelectorFromString("hide:")
1144
- if splashScreenPlugin.responds(to: selector) {
1145
- _ = splashScreenPlugin.perform(selector, with: call)
1146
- self.logger.info("Called SplashScreen hide method")
1147
- } else {
1148
- self.logger.warn("autoSplashscreen: SplashScreen plugin does not respond to hide: method. Make sure @capacitor/splash-screen plugin is properly installed.")
1149
- }
1150
- } else {
1151
- self.logger.warn("autoSplashscreen: SplashScreen plugin not found. Install @capacitor/splash-screen plugin.")
1152
- }
1143
+ self.splashscreenInvocationToken += 1
1144
+ self.invokeSplashscreenMethod(
1145
+ methodName: "hide",
1146
+ callbackId: "autoHideSplashscreen",
1147
+ options: self.splashscreenOptions(methodName: "hide"),
1148
+ retriesRemaining: self.splashscreenMaxRetries,
1149
+ requestToken: self.splashscreenInvocationToken
1150
+ )
1153
1151
  }
1154
1152
 
1155
1153
  private func showSplashscreen() {
@@ -1165,35 +1163,132 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
1165
1163
  private func performShowSplashscreen() {
1166
1164
  self.cancelSplashscreenTimeout()
1167
1165
  self.autoSplashscreenTimedOut = false
1166
+ self.splashscreenInvocationToken += 1
1167
+ self.invokeSplashscreenMethod(
1168
+ methodName: "show",
1169
+ callbackId: "autoShowSplashscreen",
1170
+ options: self.splashscreenOptions(methodName: "show"),
1171
+ retriesRemaining: self.splashscreenMaxRetries,
1172
+ requestToken: self.splashscreenInvocationToken
1173
+ )
1174
+
1175
+ self.addSplashscreenLoaderIfNeeded()
1176
+ self.scheduleSplashscreenTimeout()
1177
+ }
1178
+
1179
+ private func splashscreenOptions(methodName: String) -> [String: Any] {
1180
+ methodName == "show" ? ["autoHide": false] : [:]
1181
+ }
1182
+
1183
+ private func splashscreenCompletedMessage(methodName: String) -> String {
1184
+ methodName == "show" ? "Splashscreen shown automatically" : "Splashscreen hidden automatically"
1185
+ }
1186
+
1187
+ func splashscreenOptionsForTesting(methodName: String) -> [String: Any] {
1188
+ self.splashscreenOptions(methodName: methodName)
1189
+ }
1190
+
1191
+ func isCurrentSplashscreenInvocationTokenForTesting(_ requestToken: Int) -> Bool {
1192
+ requestToken == self.splashscreenInvocationToken
1193
+ }
1194
+
1195
+ func advanceSplashscreenInvocationTokenForTesting() {
1196
+ self.splashscreenInvocationToken += 1
1197
+ }
1198
+
1199
+ private func makeSplashscreenCall(callbackId: String, options: [String: Any], methodName: String) -> CAPPluginCall {
1200
+ CAPPluginCall(callbackId: callbackId, options: options, success: { [weak self] (_, _) in
1201
+ guard let self = self else { return }
1202
+ self.logger.info(self.splashscreenCompletedMessage(methodName: methodName))
1203
+ }, error: { [weak self] (_) in
1204
+ guard let self = self else { return }
1205
+ self.logger.error("Failed to auto-\(methodName) splashscreen")
1206
+ })
1207
+ }
1208
+
1209
+ private func invokeSplashscreenMethod(
1210
+ methodName: String,
1211
+ callbackId: String,
1212
+ options: [String: Any],
1213
+ retriesRemaining: Int,
1214
+ requestToken: Int
1215
+ ) {
1216
+ guard requestToken == self.splashscreenInvocationToken else {
1217
+ return
1218
+ }
1168
1219
 
1169
1220
  guard let bridge = self.bridge else {
1170
- self.logger.warn("Bridge not available for showing splashscreen with autoSplashscreen")
1221
+ self.retrySplashscreenMethod(
1222
+ methodName: methodName,
1223
+ callbackId: callbackId,
1224
+ options: options,
1225
+ retriesRemaining: retriesRemaining,
1226
+ requestToken: requestToken,
1227
+ message: "Bridge not available for \(methodName == "show" ? "showing" : "hiding") splashscreen with autoSplashscreen"
1228
+ )
1171
1229
  return
1172
1230
  }
1173
1231
 
1174
- // Create a plugin call for the show method
1175
- let call = CAPPluginCall(callbackId: "autoShowSplashscreen", options: [:], success: { (_, _) in
1176
- self.logger.info("Splashscreen shown automatically")
1177
- }, error: { (_) in
1178
- self.logger.error("Failed to auto-show splashscreen")
1179
- })
1232
+ guard let splashScreenPlugin = bridge.plugin(withName: self.splashscreenPluginName) else {
1233
+ self.retrySplashscreenMethod(
1234
+ methodName: methodName,
1235
+ callbackId: callbackId,
1236
+ options: options,
1237
+ retriesRemaining: retriesRemaining,
1238
+ requestToken: requestToken,
1239
+ message: "autoSplashscreen: SplashScreen plugin not found. Install @capacitor/splash-screen plugin."
1240
+ )
1241
+ return
1242
+ }
1243
+
1244
+ let selector = NSSelectorFromString("\(methodName):")
1245
+ guard splashScreenPlugin.responds(to: selector) else {
1246
+ self.retrySplashscreenMethod(
1247
+ methodName: methodName,
1248
+ callbackId: callbackId,
1249
+ options: options,
1250
+ retriesRemaining: retriesRemaining,
1251
+ requestToken: requestToken,
1252
+ message: "autoSplashscreen: SplashScreen plugin does not respond to \(methodName): method. Make sure @capacitor/splash-screen plugin is properly installed."
1253
+ )
1254
+ return
1255
+ }
1256
+
1257
+ let call = self.makeSplashscreenCall(callbackId: callbackId, options: options, methodName: methodName)
1258
+ _ = splashScreenPlugin.perform(selector, with: call)
1259
+ self.logger.info("Called SplashScreen \(methodName) method")
1260
+ }
1180
1261
 
1181
- // Try to call the SplashScreen show method directly through the bridge
1182
- if let splashScreenPlugin = bridge.plugin(withName: "SplashScreen") {
1183
- // Use runtime method invocation to call show method
1184
- let selector = NSSelectorFromString("show:")
1185
- if splashScreenPlugin.responds(to: selector) {
1186
- _ = splashScreenPlugin.perform(selector, with: call)
1187
- self.logger.info("Called SplashScreen show method")
1262
+ private func retrySplashscreenMethod(
1263
+ methodName: String,
1264
+ callbackId: String,
1265
+ options: [String: Any],
1266
+ retriesRemaining: Int,
1267
+ requestToken: Int,
1268
+ message: String
1269
+ ) {
1270
+ guard retriesRemaining > 0 else {
1271
+ if methodName == "show" {
1272
+ self.logger.warn(message)
1188
1273
  } else {
1189
- self.logger.warn("autoSplashscreen: SplashScreen plugin does not respond to show: method. Make sure @capacitor/splash-screen plugin is properly installed.")
1274
+ self.logger.error(message)
1190
1275
  }
1191
- } else {
1192
- self.logger.warn("autoSplashscreen: SplashScreen plugin not found. Install @capacitor/splash-screen plugin.")
1276
+ return
1193
1277
  }
1194
1278
 
1195
- self.addSplashscreenLoaderIfNeeded()
1196
- self.scheduleSplashscreenTimeout()
1279
+ self.logger.info("\(message). Retrying.")
1280
+ DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(self.splashscreenRetryDelayMilliseconds)) { [weak self] in
1281
+ guard let self = self, requestToken == self.splashscreenInvocationToken else {
1282
+ return
1283
+ }
1284
+ self.invokeSplashscreenMethod(
1285
+ methodName: methodName,
1286
+ callbackId: callbackId,
1287
+ options: options,
1288
+ retriesRemaining: retriesRemaining - 1,
1289
+ requestToken: requestToken
1290
+ )
1291
+ }
1197
1292
  }
1198
1293
 
1199
1294
  private func addSplashscreenLoaderIfNeeded() {
@@ -1347,7 +1442,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
1347
1442
  }
1348
1443
  return false
1349
1444
  case "onLaunch":
1350
- if !self.onLaunchDirectUpdateUsed {
1445
+ if !self.getOnLaunchDirectUpdateUsed() {
1351
1446
  return true
1352
1447
  }
1353
1448
  return false
@@ -1357,6 +1452,47 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
1357
1452
  }
1358
1453
  }
1359
1454
 
1455
+ static func shouldConsumeOnLaunchDirectUpdate(directUpdateMode: String, plannedDirectUpdate: Bool) -> Bool {
1456
+ plannedDirectUpdate && directUpdateMode == "onLaunch"
1457
+ }
1458
+
1459
+ private func getOnLaunchDirectUpdateUsed() -> Bool {
1460
+ self.onLaunchDirectUpdateStateLock.lock()
1461
+ defer { self.onLaunchDirectUpdateStateLock.unlock() }
1462
+ return self.onLaunchDirectUpdateUsed
1463
+ }
1464
+
1465
+ private func setOnLaunchDirectUpdateUsed(_ used: Bool) {
1466
+ self.onLaunchDirectUpdateStateLock.lock()
1467
+ self.onLaunchDirectUpdateUsed = used
1468
+ self.onLaunchDirectUpdateStateLock.unlock()
1469
+ }
1470
+
1471
+ private func consumeOnLaunchDirectUpdateAttempt(plannedDirectUpdate: Bool) {
1472
+ guard Self.shouldConsumeOnLaunchDirectUpdate(directUpdateMode: self.directUpdateMode, plannedDirectUpdate: plannedDirectUpdate) else {
1473
+ return
1474
+ }
1475
+
1476
+ self.setOnLaunchDirectUpdateUsed(true)
1477
+ }
1478
+
1479
+ func configureDirectUpdateModeForTesting(_ directUpdateMode: String, onLaunchDirectUpdateUsed: Bool = false) {
1480
+ self.directUpdateMode = directUpdateMode
1481
+ self.setOnLaunchDirectUpdateUsed(onLaunchDirectUpdateUsed)
1482
+ }
1483
+
1484
+ func setUpdateUrlForTesting(_ updateUrl: String) {
1485
+ self.updateUrl = updateUrl
1486
+ }
1487
+
1488
+ func shouldUseDirectUpdateForTesting() -> Bool {
1489
+ self.shouldUseDirectUpdate()
1490
+ }
1491
+
1492
+ var hasConsumedOnLaunchDirectUpdateForTesting: Bool {
1493
+ self.getOnLaunchDirectUpdateUsed()
1494
+ }
1495
+
1360
1496
  private func notifyBreakingEvents(version: String) {
1361
1497
  guard !version.isEmpty else {
1362
1498
  return
@@ -1371,6 +1507,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
1371
1507
  latestVersionName: String,
1372
1508
  current: BundleInfo,
1373
1509
  error: Bool = true,
1510
+ plannedDirectUpdate: Bool = false,
1374
1511
  failureAction: String = "download_fail",
1375
1512
  failureEvent: String = "downloadFailed",
1376
1513
  sendStats: Bool = true
@@ -1382,6 +1519,8 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
1382
1519
  downloadInProgress = false
1383
1520
  downloadStartTime = nil
1384
1521
 
1522
+ self.consumeOnLaunchDirectUpdateAttempt(plannedDirectUpdate: plannedDirectUpdate)
1523
+
1385
1524
  if error {
1386
1525
  if sendStats {
1387
1526
  self.implementation.sendStats(action: failureAction, versionName: current.getVersionName())
@@ -1416,6 +1555,10 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
1416
1555
  return true
1417
1556
  }
1418
1557
 
1558
+ func runBackgroundDownloadWork(_ work: @escaping () -> Void) {
1559
+ DispatchQueue.global(qos: .background).async(execute: work)
1560
+ }
1561
+
1419
1562
  func backgroundDownload() {
1420
1563
  // Set download in progress flag (thread-safe)
1421
1564
  downloadLock.lock()
@@ -1435,7 +1578,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
1435
1578
  return
1436
1579
  }
1437
1580
 
1438
- DispatchQueue.global(qos: .background).async {
1581
+ self.runBackgroundDownloadWork {
1439
1582
  // Wait for cleanup to complete before starting download
1440
1583
  self.waitForCleanupIfNeeded()
1441
1584
  self.backgroundTaskID = UIApplication.shared.beginBackgroundTask(withName: "Finish Download Tasks") {
@@ -1456,6 +1599,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
1456
1599
  latestVersionName: res.version,
1457
1600
  current: current,
1458
1601
  error: true,
1602
+ plannedDirectUpdate: plannedDirectUpdate,
1459
1603
  sendStats: !responseIsOk
1460
1604
  )
1461
1605
  return
@@ -1465,26 +1609,39 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
1465
1609
  let directUpdateAllowed = plannedDirectUpdate && !self.autoSplashscreenTimedOut
1466
1610
  if directUpdateAllowed {
1467
1611
  self.logger.info("Direct update to builtin version")
1468
- if self.directUpdateMode == "onLaunch" {
1469
- self.onLaunchDirectUpdateUsed = true
1470
- self.directUpdate = false
1471
- }
1472
1612
  _ = self._reset(toLastSuccessful: false)
1473
- self.endBackGroundTaskWithNotif(msg: "Updated to builtin version", latestVersionName: res.version, current: self.implementation.getCurrentBundle(), error: false)
1613
+ self.endBackGroundTaskWithNotif(
1614
+ msg: "Updated to builtin version",
1615
+ latestVersionName: res.version,
1616
+ current: self.implementation.getCurrentBundle(),
1617
+ error: false,
1618
+ plannedDirectUpdate: plannedDirectUpdate
1619
+ )
1474
1620
  } else {
1475
1621
  if plannedDirectUpdate && !directUpdateAllowed {
1476
1622
  self.logger.info("Direct update skipped because splashscreen timeout occurred. Update will apply later.")
1477
1623
  }
1478
1624
  self.logger.info("Setting next bundle to builtin")
1479
1625
  _ = self.implementation.setNextBundle(next: BundleInfo.ID_BUILTIN)
1480
- self.endBackGroundTaskWithNotif(msg: "Next update will be to builtin version", latestVersionName: res.version, current: current, error: false)
1626
+ self.endBackGroundTaskWithNotif(
1627
+ msg: "Next update will be to builtin version",
1628
+ latestVersionName: res.version,
1629
+ current: current,
1630
+ error: false,
1631
+ plannedDirectUpdate: plannedDirectUpdate
1632
+ )
1481
1633
  }
1482
1634
  return
1483
1635
  }
1484
1636
  let sessionKey = res.sessionKey ?? ""
1485
1637
  guard let downloadUrl = URL(string: res.url) else {
1486
1638
  self.logger.error("Error no url or wrong format")
1487
- self.endBackGroundTaskWithNotif(msg: "Error no url or wrong format", latestVersionName: res.version, current: current)
1639
+ self.endBackGroundTaskWithNotif(
1640
+ msg: "Error no url or wrong format",
1641
+ latestVersionName: res.version,
1642
+ current: current,
1643
+ plannedDirectUpdate: plannedDirectUpdate
1644
+ )
1488
1645
  return
1489
1646
  }
1490
1647
  let latestVersionName = res.version
@@ -1502,6 +1659,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
1502
1659
  self.logger.error("Failed to delete failed bundle: \(nextImpl!.toString())")
1503
1660
  }
1504
1661
  }
1662
+ self.consumeOnLaunchDirectUpdateAttempt(plannedDirectUpdate: plannedDirectUpdate)
1505
1663
  if res.manifest != nil {
1506
1664
  nextImpl = try self.implementation.downloadManifest(manifest: res.manifest!, version: latestVersionName, sessionKey: sessionKey, link: res.link, comment: res.comment)
1507
1665
  } else {
@@ -1510,12 +1668,22 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
1510
1668
  }
1511
1669
  guard let next = nextImpl else {
1512
1670
  self.logger.error("Error downloading file")
1513
- self.endBackGroundTaskWithNotif(msg: "Error downloading file", latestVersionName: latestVersionName, current: current)
1671
+ self.endBackGroundTaskWithNotif(
1672
+ msg: "Error downloading file",
1673
+ latestVersionName: latestVersionName,
1674
+ current: current,
1675
+ plannedDirectUpdate: plannedDirectUpdate
1676
+ )
1514
1677
  return
1515
1678
  }
1516
1679
  if next.isErrorStatus() {
1517
1680
  self.logger.error("Latest bundle already exists and is in error state. Aborting update.")
1518
- self.endBackGroundTaskWithNotif(msg: "Latest version is in error state. Aborting update.", latestVersionName: latestVersionName, current: current)
1681
+ self.endBackGroundTaskWithNotif(
1682
+ msg: "Latest version is in error state. Aborting update.",
1683
+ latestVersionName: latestVersionName,
1684
+ current: current,
1685
+ plannedDirectUpdate: plannedDirectUpdate
1686
+ )
1519
1687
  return
1520
1688
  }
1521
1689
  res.checksum = try CryptoCipher.decryptChecksum(checksum: res.checksum, publicKey: self.implementation.publicKey)
@@ -1529,7 +1697,12 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
1529
1697
  if !resDel {
1530
1698
  self.logger.error("Delete failed, id \(id) doesn't exist")
1531
1699
  }
1532
- self.endBackGroundTaskWithNotif(msg: "Error checksum", latestVersionName: latestVersionName, current: current)
1700
+ self.endBackGroundTaskWithNotif(
1701
+ msg: "Error checksum",
1702
+ latestVersionName: latestVersionName,
1703
+ current: current,
1704
+ plannedDirectUpdate: plannedDirectUpdate
1705
+ )
1533
1706
  return
1534
1707
  }
1535
1708
  let directUpdateAllowed = plannedDirectUpdate && !self.autoSplashscreenTimedOut
@@ -1542,34 +1715,67 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
1542
1715
  }
1543
1716
  if !delayConditionList.isEmpty {
1544
1717
  self.logger.info("Update delayed until delay conditions met")
1545
- self.endBackGroundTaskWithNotif(msg: "Update delayed until delay conditions met", latestVersionName: latestVersionName, current: next, error: false)
1718
+ self.endBackGroundTaskWithNotif(
1719
+ msg: "Update delayed until delay conditions met",
1720
+ latestVersionName: latestVersionName,
1721
+ current: next,
1722
+ error: false,
1723
+ plannedDirectUpdate: plannedDirectUpdate
1724
+ )
1546
1725
  return
1547
1726
  }
1548
- if self.directUpdateMode == "onLaunch" {
1549
- self.onLaunchDirectUpdateUsed = true
1550
- self.directUpdate = false
1727
+ if self.implementation.set(bundle: next) && self._reload() {
1728
+ self.notifyBundleSet(next)
1729
+ self.endBackGroundTaskWithNotif(
1730
+ msg: "update installed",
1731
+ latestVersionName: latestVersionName,
1732
+ current: next,
1733
+ error: false,
1734
+ plannedDirectUpdate: plannedDirectUpdate
1735
+ )
1736
+ } else {
1737
+ self.endBackGroundTaskWithNotif(
1738
+ msg: "Update install failed",
1739
+ latestVersionName: latestVersionName,
1740
+ current: next,
1741
+ plannedDirectUpdate: plannedDirectUpdate
1742
+ )
1551
1743
  }
1552
- _ = self.implementation.set(bundle: next)
1553
- _ = self._reload()
1554
- self.endBackGroundTaskWithNotif(msg: "update installed", latestVersionName: latestVersionName, current: next, error: false)
1555
1744
  } else {
1556
1745
  if plannedDirectUpdate && !directUpdateAllowed {
1557
1746
  self.logger.info("Direct update skipped because splashscreen timeout occurred. Update will install on next app background.")
1558
1747
  }
1559
1748
  self.notifyListeners("updateAvailable", data: ["bundle": next.toJSON()])
1560
1749
  _ = self.implementation.setNextBundle(next: next.getId())
1561
- self.endBackGroundTaskWithNotif(msg: "update downloaded, will install next background", latestVersionName: latestVersionName, current: current, error: false)
1750
+ self.endBackGroundTaskWithNotif(
1751
+ msg: "update downloaded, will install next background",
1752
+ latestVersionName: latestVersionName,
1753
+ current: current,
1754
+ error: false,
1755
+ plannedDirectUpdate: plannedDirectUpdate
1756
+ )
1562
1757
  }
1563
1758
  return
1564
1759
  } catch {
1565
1760
  self.logger.error("Error downloading file \(error.localizedDescription)")
1566
1761
  let current: BundleInfo = self.implementation.getCurrentBundle()
1567
- self.endBackGroundTaskWithNotif(msg: "Error downloading file", latestVersionName: latestVersionName, current: current)
1762
+ self.endBackGroundTaskWithNotif(
1763
+ msg: "Error downloading file",
1764
+ latestVersionName: latestVersionName,
1765
+ current: current,
1766
+ plannedDirectUpdate: plannedDirectUpdate
1767
+ )
1568
1768
  return
1569
1769
  }
1570
1770
  } else {
1571
1771
  self.logger.info("No need to update, \(current.getId()) is the latest bundle.")
1572
- self.endBackGroundTaskWithNotif(msg: "No need to update, \(current.getId()) is the latest bundle.", latestVersionName: latestVersionName, current: current, error: false)
1772
+ self.endBackGroundTaskWithNotif(
1773
+ msg: "No need to update, \(current.getId()) is the latest bundle.",
1774
+ latestVersionName: latestVersionName,
1775
+ current: current,
1776
+ error: false,
1777
+ plannedDirectUpdate: plannedDirectUpdate
1778
+ )
1573
1779
  return
1574
1780
  }
1575
1781
  }
@@ -1593,6 +1799,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
1593
1799
  logger.info("Next bundle is: \(next!.toString())")
1594
1800
  if self.implementation.set(bundle: next!) && self._reload() {
1595
1801
  logger.info("Updated to bundle: \(next!.toString())")
1802
+ self.notifyBundleSet(next!)
1596
1803
  _ = self.implementation.setNextBundle(next: Optional<String>.none)
1597
1804
  } else {
1598
1805
  logger.error("Update to bundle: \(next!.toString()) Failed!")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/capacitor-updater",
3
- "version": "8.44.0",
3
+ "version": "8.45.1",
4
4
  "license": "MPL-2.0",
5
5
  "description": "Live update for capacitor apps",
6
6
  "main": "dist/plugin.cjs.js",