@capgo/capacitor-updater 7.51.19 → 7.51.21

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.
@@ -96,7 +96,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
96
96
  deinit {
97
97
  implementation.shutdown()
98
98
  }
99
- private let pluginVersion: String = "7.51.19"
99
+ private let pluginVersion: String = "7.51.21"
100
100
  private let launchStartedAtMs = Int64(Date().timeIntervalSince1970 * 1000)
101
101
  static let updateUrlDefault = "https://plugin.capgo.app/updates"
102
102
  static let statsUrlDefault = "https://plugin.capgo.app/stats"
@@ -3498,13 +3498,10 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
3498
3498
  }
3499
3499
 
3500
3500
  private func performHideSplashscreen() {
3501
- self.cancelSplashscreenTimeout()
3502
3501
  self.removeSplashscreenLoader()
3503
3502
  self.splashscreenInvocationToken += 1
3504
- self.invokeSplashscreenMethod(
3505
- methodName: "hide",
3506
- callbackId: "autoHideSplashscreen",
3507
- options: self.splashscreenOptions(methodName: "hide"),
3503
+ self.invokeSplashscreenAction(
3504
+ .hide,
3508
3505
  retriesRemaining: self.splashscreenMaxRetries,
3509
3506
  requestToken: self.splashscreenInvocationToken
3510
3507
  )
@@ -3524,10 +3521,8 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
3524
3521
  self.cancelSplashscreenTimeout()
3525
3522
  self.autoSplashscreenTimedOut = false
3526
3523
  self.splashscreenInvocationToken += 1
3527
- self.invokeSplashscreenMethod(
3528
- methodName: "show",
3529
- callbackId: "autoShowSplashscreen",
3530
- options: self.splashscreenOptions(methodName: "show"),
3524
+ self.invokeSplashscreenAction(
3525
+ .show,
3531
3526
  retriesRemaining: self.splashscreenMaxRetries,
3532
3527
  requestToken: self.splashscreenInvocationToken
3533
3528
  )
@@ -3537,7 +3532,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
3537
3532
  }
3538
3533
 
3539
3534
  private func splashscreenOptions(methodName: String) -> [String: Any] {
3540
- methodName == "show" ? ["autoHide": false] : [:]
3535
+ methodName == "show" ? ["autoHide": false, "fadeInDuration": 0] : [:]
3541
3536
  }
3542
3537
 
3543
3538
  private func splashscreenCompletedMessage(methodName: String) -> String {
@@ -3556,20 +3551,59 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
3556
3551
  self.splashscreenInvocationToken += 1
3557
3552
  }
3558
3553
 
3559
- private func makeSplashscreenCall(callbackId: String, options: [String: Any], methodName: String) -> CAPPluginCall {
3560
- CAPPluginCall(callbackId: callbackId, methodName: methodName, options: options, success: { [weak self] (_, _) in
3561
- guard let self = self else { return }
3562
- self.logger.info(self.splashscreenCompletedMessage(methodName: methodName))
3563
- }, error: { [weak self] (_) in
3564
- guard let self = self else { return }
3565
- self.logger.error("Failed to auto-\(methodName) splashscreen")
3566
- })
3554
+ private enum SplashscreenAction {
3555
+ case show
3556
+ case hide
3557
+
3558
+ var methodName: String {
3559
+ switch self {
3560
+ case .show:
3561
+ return "show"
3562
+ case .hide:
3563
+ return "hide"
3564
+ }
3565
+ }
3566
+
3567
+ var unavailableMessageVerb: String {
3568
+ switch self {
3569
+ case .show:
3570
+ return "showing"
3571
+ case .hide:
3572
+ return "hiding"
3573
+ }
3574
+ }
3575
+ }
3576
+
3577
+ private func splashscreenOptionsJSON(methodName: String) -> String {
3578
+ let options = self.splashscreenOptions(methodName: methodName)
3579
+ guard !options.isEmpty,
3580
+ let data = try? JSONSerialization.data(withJSONObject: options),
3581
+ let json = String(data: data, encoding: .utf8) else {
3582
+ return "{}"
3583
+ }
3584
+ return json
3585
+ }
3586
+
3587
+ private func splashscreenPluginExposesMethod(_ methodName: String, on plugin: CAPPlugin) -> Bool {
3588
+ guard let bridgedPlugin = plugin as? CAPBridgedPlugin else {
3589
+ return false
3590
+ }
3591
+ return bridgedPlugin.pluginMethods.contains { $0.name == methodName }
3592
+ }
3593
+
3594
+ private func splashscreenBridgeScript(for action: SplashscreenAction) -> String {
3595
+ let optionsJSON = self.splashscreenOptionsJSON(methodName: action.methodName)
3596
+ return """
3597
+ var cap = window.Capacitor;
3598
+ if (!cap || typeof cap.nativePromise !== 'function') {
3599
+ throw new Error('Capacitor bridge not ready');
3600
+ }
3601
+ return await cap.nativePromise('\(self.splashscreenPluginName)', '\(action.methodName)', \(optionsJSON));
3602
+ """
3567
3603
  }
3568
3604
 
3569
- private func invokeSplashscreenMethod(
3570
- methodName: String,
3571
- callbackId: String,
3572
- options: [String: Any],
3605
+ private func invokeSplashscreenAction(
3606
+ _ action: SplashscreenAction,
3573
3607
  retriesRemaining: Int,
3574
3608
  requestToken: Int
3575
3609
  ) {
@@ -3578,22 +3612,18 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
3578
3612
  }
3579
3613
 
3580
3614
  guard let bridge = self.bridge else {
3581
- self.retrySplashscreenMethod(
3582
- methodName: methodName,
3583
- callbackId: callbackId,
3584
- options: options,
3615
+ self.retrySplashscreenAction(
3616
+ action,
3585
3617
  retriesRemaining: retriesRemaining,
3586
3618
  requestToken: requestToken,
3587
- message: "Bridge not available for \(methodName == "show" ? "showing" : "hiding") splashscreen with autoSplashscreen"
3619
+ message: "Bridge not available for \(action.unavailableMessageVerb) splashscreen with autoSplashscreen"
3588
3620
  )
3589
3621
  return
3590
3622
  }
3591
3623
 
3592
3624
  guard let splashScreenPlugin = bridge.plugin(withName: self.splashscreenPluginName) else {
3593
- self.retrySplashscreenMethod(
3594
- methodName: methodName,
3595
- callbackId: callbackId,
3596
- options: options,
3625
+ self.retrySplashscreenAction(
3626
+ action,
3597
3627
  retriesRemaining: retriesRemaining,
3598
3628
  requestToken: requestToken,
3599
3629
  message: "autoSplashscreen: SplashScreen plugin not found. Install @capacitor/splash-screen plugin."
@@ -3601,37 +3631,86 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
3601
3631
  return
3602
3632
  }
3603
3633
 
3604
- let selector = NSSelectorFromString("\(methodName):")
3605
- guard splashScreenPlugin.responds(to: selector) else {
3606
- self.retrySplashscreenMethod(
3607
- methodName: methodName,
3608
- callbackId: callbackId,
3609
- options: options,
3634
+ guard self.splashscreenPluginExposesMethod(action.methodName, on: splashScreenPlugin) else {
3635
+ self.retrySplashscreenAction(
3636
+ action,
3637
+ retriesRemaining: retriesRemaining,
3638
+ requestToken: requestToken,
3639
+ message: "autoSplashscreen: SplashScreen plugin does not expose \(action.methodName)(). Make sure @capacitor/splash-screen plugin is properly installed."
3640
+ )
3641
+ return
3642
+ }
3643
+
3644
+ guard let webView = bridge.webView else {
3645
+ self.retrySplashscreenAction(
3646
+ action,
3610
3647
  retriesRemaining: retriesRemaining,
3611
3648
  requestToken: requestToken,
3612
- message: "autoSplashscreen: SplashScreen plugin does not respond to \(methodName): method. Make sure @capacitor/splash-screen plugin is properly installed."
3649
+ message: "WebView not available for \(action.unavailableMessageVerb) splashscreen with autoSplashscreen"
3613
3650
  )
3614
3651
  return
3615
3652
  }
3616
3653
 
3617
- let call = self.makeSplashscreenCall(callbackId: callbackId, options: options, methodName: methodName)
3618
- _ = splashScreenPlugin.perform(selector, with: call)
3619
- self.logger.info("Called SplashScreen \(methodName) method")
3654
+ let script = self.splashscreenBridgeScript(for: action)
3655
+ let runInvocation = { [weak self] in
3656
+ guard let self = self, requestToken == self.splashscreenInvocationToken else {
3657
+ return
3658
+ }
3659
+ webView.callAsyncJavaScript(
3660
+ script,
3661
+ arguments: [:],
3662
+ in: nil,
3663
+ in: .page
3664
+ ) { [weak self] (result: Result<Any, Error>) in
3665
+ guard let self = self, requestToken == self.splashscreenInvocationToken else {
3666
+ return
3667
+ }
3668
+ if case .failure(let error) = result {
3669
+ self.retrySplashscreenAction(
3670
+ action,
3671
+ retriesRemaining: retriesRemaining,
3672
+ requestToken: requestToken,
3673
+ message: "Failed to invoke SplashScreen \(action.methodName) via Capacitor bridge: \(error.localizedDescription)"
3674
+ )
3675
+ return
3676
+ }
3677
+ if action == .hide {
3678
+ self.cancelSplashscreenTimeout()
3679
+ }
3680
+ self.logger.info("Called SplashScreen \(action.methodName) method")
3681
+ self.logger.info(self.splashscreenCompletedMessage(methodName: action.methodName))
3682
+ }
3683
+ }
3684
+
3685
+ if Thread.isMainThread {
3686
+ runInvocation()
3687
+ } else {
3688
+ DispatchQueue.main.async(execute: runInvocation)
3689
+ }
3620
3690
  }
3621
3691
 
3622
- private func retrySplashscreenMethod(
3623
- methodName: String,
3624
- callbackId: String,
3625
- options: [String: Any],
3692
+ private func retrySplashscreenAction(
3693
+ _ action: SplashscreenAction,
3626
3694
  retriesRemaining: Int,
3627
3695
  requestToken: Int,
3628
3696
  message: String
3629
3697
  ) {
3630
3698
  guard retriesRemaining > 0 else {
3631
- if methodName == "show" {
3699
+ if action == .show {
3632
3700
  self.logger.warn(message)
3633
- } else {
3634
- self.logger.error(message)
3701
+ return
3702
+ }
3703
+
3704
+ self.logger.error("\(message). Scheduling another hide retry.")
3705
+ DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(self.splashscreenRetryDelayMilliseconds)) { [weak self] in
3706
+ guard let self = self, requestToken == self.splashscreenInvocationToken else {
3707
+ return
3708
+ }
3709
+ self.invokeSplashscreenAction(
3710
+ action,
3711
+ retriesRemaining: self.splashscreenMaxRetries,
3712
+ requestToken: requestToken
3713
+ )
3635
3714
  }
3636
3715
  return
3637
3716
  }
@@ -3641,10 +3720,8 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
3641
3720
  guard let self = self, requestToken == self.splashscreenInvocationToken else {
3642
3721
  return
3643
3722
  }
3644
- self.invokeSplashscreenMethod(
3645
- methodName: methodName,
3646
- callbackId: callbackId,
3647
- options: options,
3723
+ self.invokeSplashscreenAction(
3724
+ action,
3648
3725
  retriesRemaining: retriesRemaining - 1,
3649
3726
  requestToken: requestToken
3650
3727
  )
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/capacitor-updater",
3
- "version": "7.51.19",
3
+ "version": "7.51.21",
4
4
  "license": "MPL-2.0",
5
5
  "description": "Live update for capacitor apps",
6
6
  "main": "dist/plugin.cjs.js",
@@ -63,7 +63,7 @@
63
63
  "test:maestro:ios:smoke": "./scripts/test-maestro-ios.sh",
64
64
  "lint": "bun run eslint && bun run prettier -- --check && bun run swiftlint -- lint",
65
65
  "fmt": "bun run eslint -- --fix && bun run prettier -- --write && bun run swiftlint -- --fix --format",
66
- "eslint": "eslint . --ext .ts",
66
+ "eslint": "eslint .",
67
67
  "prettier": "prettier-pretty-check \"**/*.{css,html,ts,js,java}\" --plugin=prettier-plugin-java",
68
68
  "swiftlint": "node-swiftlint",
69
69
  "docgen": "node scripts/generate-docs.js",
@@ -87,12 +87,13 @@
87
87
  "@capacitor/core": "^7.0.0",
88
88
  "@capacitor/docgen": "^0.3.0",
89
89
  "@capacitor/ios": "^7.0.0",
90
- "@ionic/eslint-config": "^0.4.0",
90
+ "@ionic/eslint-config": "^0.5.0",
91
+ "@typescript-eslint/eslint-plugin": "^8.70.0",
92
+ "@typescript-eslint/parser": "^8.70.0",
91
93
  "@ionic/prettier-config": "^4.0.0",
92
94
  "@ionic/swiftlint-config": "^2.0.0",
93
95
  "@types/node": "^26.0.0",
94
- "eslint": "^8.57.0",
95
- "eslint-plugin-import": "^2.32.0",
96
+ "eslint": "^10.0.0",
96
97
  "husky": "^9.1.7",
97
98
  "prettier": "^3.6.2",
98
99
  "prettier-plugin-java": "^2.7.4",
@@ -107,9 +108,6 @@
107
108
  },
108
109
  "prettier": "@ionic/prettier-config",
109
110
  "swiftlint": "@ionic/swiftlint-config",
110
- "eslintConfig": {
111
- "extends": "@ionic/eslint-config/recommended"
112
- },
113
111
  "capacitor": {
114
112
  "ios": {
115
113
  "src": "ios"