@capgo/capacitor-updater 8.47.9 → 8.47.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.
- package/android/src/main/java/ee/forgr/capacitor_updater/CapacitorUpdaterPlugin.java +1 -1
- package/android/src/main/java/ee/forgr/capacitor_updater/ShakeDetector.java +3 -3
- package/ios/Sources/CapacitorUpdaterPlugin/CapacitorUpdaterPlugin.swift +22 -8
- package/ios/Sources/CapacitorUpdaterPlugin/ShakeMenu.swift +47 -30
- package/package.json +1 -1
|
@@ -2519,7 +2519,7 @@ public class CapacitorUpdaterPlugin extends Plugin {
|
|
|
2519
2519
|
}
|
|
2520
2520
|
|
|
2521
2521
|
final BundleInfo previewFallbackBundle = this.implementation.getPreviewFallbackBundle();
|
|
2522
|
-
this.endPreviewSession();
|
|
2522
|
+
this.endPreviewSession(true);
|
|
2523
2523
|
final BundleInfo restoredNextBundle = this.implementation.getNextBundle();
|
|
2524
2524
|
this.deletePreviewBundleIfUnused(previewBundle, previewFallbackBundle, restoredNextBundle);
|
|
2525
2525
|
return true;
|
|
@@ -17,8 +17,8 @@ public class ShakeDetector implements SensorEventListener {
|
|
|
17
17
|
void onShakeDetected();
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
private static final float SHAKE_THRESHOLD =
|
|
21
|
-
private static final int SHAKE_TIMEOUT =
|
|
20
|
+
private static final float SHAKE_THRESHOLD = 16.0f; // Acceleration threshold for shake detection
|
|
21
|
+
private static final int SHAKE_TIMEOUT = 1000; // Minimum time between shake events (ms)
|
|
22
22
|
|
|
23
23
|
private Listener listener;
|
|
24
24
|
private SensorManager sensorManager;
|
|
@@ -34,7 +34,7 @@ public class ShakeDetector implements SensorEventListener {
|
|
|
34
34
|
this.accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
|
|
35
35
|
|
|
36
36
|
if (accelerometer != null) {
|
|
37
|
-
sensorManager.registerListener(this, accelerometer, SensorManager.
|
|
37
|
+
sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_UI);
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
40
|
|
|
@@ -1229,7 +1229,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1229
1229
|
}
|
|
1230
1230
|
|
|
1231
1231
|
let previewFallbackBundle = self.implementation.getPreviewFallbackBundle()
|
|
1232
|
-
self.endPreviewSession()
|
|
1232
|
+
self.endPreviewSession(keepPreviewGuard: true)
|
|
1233
1233
|
let restoredNextBundle = self.implementation.getNextBundle()
|
|
1234
1234
|
self.deletePreviewBundleIfUnused(previewBundle, previewFallbackBundle: previewFallbackBundle, restoredNextBundle: restoredNextBundle)
|
|
1235
1235
|
return true
|
|
@@ -1382,9 +1382,9 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1382
1382
|
|
|
1383
1383
|
private func endPreviewSession(keepPreviewGuard: Bool = false) {
|
|
1384
1384
|
let previousShakeMenuEnabled = UserDefaults.standard.object(forKey: self.previewPreviousShakeMenuDefaultsKey) as? Bool
|
|
1385
|
-
??
|
|
1385
|
+
?? self.getBooleanConfig("shakeMenu", defaultValue: false)
|
|
1386
1386
|
let previousShakeChannelSelectorEnabled = UserDefaults.standard.object(forKey: self.previewPreviousShakeChannelSelectorDefaultsKey) as? Bool
|
|
1387
|
-
??
|
|
1387
|
+
?? self.getBooleanConfig("allowShakeChannelSelector", defaultValue: false)
|
|
1388
1388
|
self.restorePreviewPreviousNextBundle()
|
|
1389
1389
|
self.restorePreviewPreviousAppId()
|
|
1390
1390
|
self.restorePreviewPreviousDefaultChannel()
|
|
@@ -1419,11 +1419,25 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1419
1419
|
self.isLeavingPreviewForIncomingLink = false
|
|
1420
1420
|
self.implementation.previewSession = false
|
|
1421
1421
|
self.hidePreviewTransitionLoader(reason: "preview-session-disabled")
|
|
1422
|
-
self.shakeMenuEnabled =
|
|
1423
|
-
self.shakeChannelSelectorEnabled =
|
|
1422
|
+
self.shakeMenuEnabled = self.getBooleanConfig("shakeMenu", defaultValue: false)
|
|
1423
|
+
self.shakeChannelSelectorEnabled = self.getBooleanConfig("allowShakeChannelSelector", defaultValue: false)
|
|
1424
1424
|
self.clearPreviewSessionPreferences()
|
|
1425
1425
|
}
|
|
1426
1426
|
|
|
1427
|
+
private func getBooleanConfig(_ key: String, defaultValue: Bool) -> Bool {
|
|
1428
|
+
guard self.bridge != nil else {
|
|
1429
|
+
return defaultValue
|
|
1430
|
+
}
|
|
1431
|
+
return getConfig().getBoolean(key, defaultValue)
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
private func getStringConfig(_ key: String, defaultValue: String) -> String {
|
|
1435
|
+
guard self.bridge != nil else {
|
|
1436
|
+
return defaultValue
|
|
1437
|
+
}
|
|
1438
|
+
return getConfig().getString(key, defaultValue) ?? defaultValue
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1427
1441
|
private func clearPreviewSessionPreferences() {
|
|
1428
1442
|
_ = self.implementation.setPreviewFallbackBundle(fallback: nil)
|
|
1429
1443
|
UserDefaults.standard.removeObject(forKey: self.previewSessionDefaultsKey)
|
|
@@ -1449,7 +1463,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1449
1463
|
}
|
|
1450
1464
|
|
|
1451
1465
|
private func restorePreviewPreviousDefaultChannel() {
|
|
1452
|
-
let configDefaultChannel = self.
|
|
1466
|
+
let configDefaultChannel = self.getStringConfig("defaultChannel", defaultValue: "")
|
|
1453
1467
|
let hadPreviousDefaultChannel = UserDefaults.standard.object(forKey: self.previewPreviousDefaultChannelWasSetDefaultsKey) as? Bool ?? false
|
|
1454
1468
|
|
|
1455
1469
|
guard hadPreviousDefaultChannel,
|
|
@@ -1636,8 +1650,8 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1636
1650
|
self.previewSessionAlertPending = false
|
|
1637
1651
|
self.isLeavingPreviewForIncomingLink = false
|
|
1638
1652
|
self.implementation.previewSession = false
|
|
1639
|
-
self.shakeMenuEnabled =
|
|
1640
|
-
self.shakeChannelSelectorEnabled =
|
|
1653
|
+
self.shakeMenuEnabled = self.getBooleanConfig("shakeMenu", defaultValue: false)
|
|
1654
|
+
self.shakeChannelSelectorEnabled = self.getBooleanConfig("allowShakeChannelSelector", defaultValue: false)
|
|
1641
1655
|
self.restorePreviewPreviousAppId()
|
|
1642
1656
|
self.restorePreviewPreviousDefaultChannel()
|
|
1643
1657
|
_ = self.implementation.setPreviewFallbackBundle(fallback: nil)
|
|
@@ -7,6 +7,9 @@
|
|
|
7
7
|
import UIKit
|
|
8
8
|
import Capacitor
|
|
9
9
|
|
|
10
|
+
private var lastShakeMenuShownAt: TimeInterval = 0
|
|
11
|
+
private let shakeMenuCooldownSeconds: TimeInterval = 1.2
|
|
12
|
+
|
|
10
13
|
extension UIApplication {
|
|
11
14
|
// swiftlint:disable:next line_length
|
|
12
15
|
public class func topViewController(_ base: UIViewController? = UIApplication.shared.windows.first?.rootViewController) -> UIViewController? {
|
|
@@ -43,25 +46,38 @@ extension UIWindow {
|
|
|
43
46
|
return
|
|
44
47
|
}
|
|
45
48
|
|
|
49
|
+
let now = Date().timeIntervalSince1970
|
|
50
|
+
guard now - lastShakeMenuShownAt >= shakeMenuCooldownSeconds else {
|
|
51
|
+
plugin.logger.info("Shake menu ignored because cooldown is active")
|
|
52
|
+
return
|
|
53
|
+
}
|
|
54
|
+
|
|
46
55
|
if canShowPreviewMenu {
|
|
47
|
-
showDefaultMenu(plugin: plugin, bridge: bridge)
|
|
56
|
+
if showDefaultMenu(plugin: plugin, bridge: bridge) {
|
|
57
|
+
lastShakeMenuShownAt = now
|
|
58
|
+
}
|
|
48
59
|
} else {
|
|
49
|
-
showChannelSelector(plugin: plugin, bridge: bridge)
|
|
60
|
+
if showChannelSelector(plugin: plugin, bridge: bridge) {
|
|
61
|
+
lastShakeMenuShownAt = now
|
|
62
|
+
}
|
|
50
63
|
}
|
|
51
64
|
}
|
|
52
65
|
}
|
|
53
66
|
|
|
54
|
-
|
|
67
|
+
@discardableResult
|
|
68
|
+
private func showDefaultMenu(plugin: CapacitorUpdaterPlugin, bridge: CAPBridgeProtocol) -> Bool {
|
|
55
69
|
// Prevent multiple alerts from showing
|
|
56
|
-
|
|
57
|
-
|
|
70
|
+
guard let topVC = UIApplication.topViewController() else {
|
|
71
|
+
return false
|
|
72
|
+
}
|
|
73
|
+
if topVC.isKind(of: UIAlertController.self) {
|
|
58
74
|
plugin.logger.info("UIAlertController is already presented")
|
|
59
|
-
return
|
|
75
|
+
return false
|
|
60
76
|
}
|
|
61
77
|
|
|
62
78
|
guard plugin.hasActivePreviewSession() else {
|
|
63
79
|
plugin.logger.info("Shake preview menu ignored because no preview session is active")
|
|
64
|
-
return
|
|
80
|
+
return false
|
|
65
81
|
}
|
|
66
82
|
|
|
67
83
|
let appName = Bundle.main.infoDictionary?["CFBundleDisplayName"] as? String ?? "App"
|
|
@@ -96,7 +112,7 @@ extension UIWindow {
|
|
|
96
112
|
if plugin.shakeChannelSelectorEnabled {
|
|
97
113
|
alertShake.addAction(UIAlertAction(title: "Switch channel", style: .default) { _ in
|
|
98
114
|
let showSelector = {
|
|
99
|
-
self.showChannelSelector(plugin: plugin, bridge: bridge)
|
|
115
|
+
_ = self.showChannelSelector(plugin: plugin, bridge: bridge)
|
|
100
116
|
}
|
|
101
117
|
|
|
102
118
|
if let presenter = alertShake.presentingViewController {
|
|
@@ -110,10 +126,9 @@ extension UIWindow {
|
|
|
110
126
|
alertShake.addAction(UIAlertAction(title: cancelButtonTitle, style: .default))
|
|
111
127
|
|
|
112
128
|
DispatchQueue.main.async {
|
|
113
|
-
|
|
114
|
-
topVC.present(alertShake, animated: true)
|
|
115
|
-
}
|
|
129
|
+
topVC.present(alertShake, animated: true)
|
|
116
130
|
}
|
|
131
|
+
return true
|
|
117
132
|
}
|
|
118
133
|
|
|
119
134
|
private func showConfiguredDefaultMenu(plugin: CapacitorUpdaterPlugin, bridge: CAPBridgeProtocol) {
|
|
@@ -179,12 +194,15 @@ extension UIWindow {
|
|
|
179
194
|
}
|
|
180
195
|
}
|
|
181
196
|
|
|
182
|
-
|
|
197
|
+
@discardableResult
|
|
198
|
+
private func showChannelSelector(plugin: CapacitorUpdaterPlugin, bridge: CAPBridgeProtocol) -> Bool {
|
|
183
199
|
// Prevent multiple alerts from showing
|
|
184
|
-
|
|
185
|
-
|
|
200
|
+
guard let topVC = UIApplication.topViewController() else {
|
|
201
|
+
return false
|
|
202
|
+
}
|
|
203
|
+
if topVC.isKind(of: UIAlertController.self) {
|
|
186
204
|
plugin.logger.info("UIAlertController is already presented")
|
|
187
|
-
return
|
|
205
|
+
return false
|
|
188
206
|
}
|
|
189
207
|
|
|
190
208
|
let updater = plugin.implementation
|
|
@@ -208,28 +226,27 @@ extension UIWindow {
|
|
|
208
226
|
})
|
|
209
227
|
|
|
210
228
|
DispatchQueue.main.async {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
let result = updater.listChannels()
|
|
229
|
+
topVC.present(loadingAlert, animated: true) {
|
|
230
|
+
// Fetch channels in background
|
|
231
|
+
DispatchQueue.global(qos: .userInitiated).async {
|
|
232
|
+
let result = updater.listChannels()
|
|
216
233
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
}
|
|
234
|
+
DispatchQueue.main.async {
|
|
235
|
+
loadingAlert.dismiss(animated: true) {
|
|
236
|
+
guard !didCancel else { return }
|
|
237
|
+
if !result.error.isEmpty {
|
|
238
|
+
self.showError(message: "Failed to load channels: \(result.error)", plugin: plugin)
|
|
239
|
+
} else if result.channels.isEmpty {
|
|
240
|
+
self.showError(message: "No channels available for self-assignment", plugin: plugin)
|
|
241
|
+
} else {
|
|
242
|
+
self.presentChannelPicker(channels: result.channels, plugin: plugin, bridge: bridge)
|
|
227
243
|
}
|
|
228
244
|
}
|
|
229
245
|
}
|
|
230
246
|
}
|
|
231
247
|
}
|
|
232
248
|
}
|
|
249
|
+
return true
|
|
233
250
|
}
|
|
234
251
|
|
|
235
252
|
private func presentChannelPicker(channels: [[String: Any]], plugin: CapacitorUpdaterPlugin, bridge: CAPBridgeProtocol) {
|