@capgo/capacitor-updater 8.47.10 → 8.47.11
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 +33 -15
- package/android/src/main/java/ee/forgr/capacitor_updater/CapacitorUpdaterPlugin.java +65 -4
- package/android/src/main/java/ee/forgr/capacitor_updater/ShakeMenu.java +24 -6
- package/android/src/main/java/ee/forgr/capacitor_updater/ThreeFingerPinchDetector.java +169 -0
- package/dist/docs.json +67 -6
- package/dist/esm/definitions.d.ts +47 -10
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web.js +1 -1
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +1 -1
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +1 -1
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/CapacitorUpdaterPlugin/CapacitorUpdaterPlugin.swift +49 -2
- package/ios/Sources/CapacitorUpdaterPlugin/ShakeMenu.swift +105 -22
- package/package.json +1 -1
|
@@ -89,6 +89,8 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
89
89
|
static let autoUpdateModeLaunch = "onLaunch"
|
|
90
90
|
static let autoUpdateModeAlways = "always"
|
|
91
91
|
static let autoUpdateModeOnlyDownload = "onlyDownload"
|
|
92
|
+
static let shakeMenuGestureShake = "shake"
|
|
93
|
+
static let shakeMenuGestureThreeFingerPinch = "threeFingerPinch"
|
|
92
94
|
private static let previewLoaderTimeoutMs = 60000
|
|
93
95
|
private let keepUrlPathFlagKey = "__capgo_keep_url_path_after_reload"
|
|
94
96
|
private let customIdDefaultsKey = "CapacitorUpdater.customId"
|
|
@@ -167,6 +169,9 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
167
169
|
private var webViewStatsReporter: WebViewStatsReporter?
|
|
168
170
|
public var shakeMenuEnabled = false
|
|
169
171
|
public var shakeChannelSelectorEnabled = false
|
|
172
|
+
public var shakeMenuGesture = CapacitorUpdaterPlugin.shakeMenuGestureShake
|
|
173
|
+
var shakeMenuPinchGestureRecognizer: UIPinchGestureRecognizer?
|
|
174
|
+
var shakeMenuPinchGestureTriggered = false
|
|
170
175
|
public var previewSessionEnabled = false
|
|
171
176
|
private var previewSessionAlertPending = false
|
|
172
177
|
private var isLeavingPreviewForIncomingLink = false
|
|
@@ -241,6 +246,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
241
246
|
resetWhenUpdate = getConfig().getBoolean("resetWhenUpdate", true)
|
|
242
247
|
shakeMenuEnabled = getConfig().getBoolean("shakeMenu", false)
|
|
243
248
|
shakeChannelSelectorEnabled = getConfig().getBoolean("allowShakeChannelSelector", false)
|
|
249
|
+
shakeMenuGesture = Self.normalizedShakeMenuGesture(getConfig().getString("shakeMenuGesture", Self.shakeMenuGestureShake))
|
|
244
250
|
let storedPreviewSessionEnabled = UserDefaults.standard.bool(forKey: previewSessionDefaultsKey)
|
|
245
251
|
let shouldClearPreviewSessionBecauseDisabled = !allowPreview && storedPreviewSessionEnabled
|
|
246
252
|
previewSessionEnabled = allowPreview && storedPreviewSessionEnabled
|
|
@@ -251,6 +257,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
251
257
|
shakeChannelSelectorEnabled = UserDefaults.standard.object(forKey: previewPreviousShakeChannelSelectorDefaultsKey) as? Bool
|
|
252
258
|
?? shakeChannelSelectorEnabled
|
|
253
259
|
}
|
|
260
|
+
syncShakeMenuGestureRecognizer()
|
|
254
261
|
periodCheckDelay = Self.normalizedPeriodCheckDelaySeconds(getConfig().getInt("periodCheckDelay", 0))
|
|
255
262
|
|
|
256
263
|
implementation.setPublicKey(getConfig().getString("publicKey") ?? "")
|
|
@@ -1212,6 +1219,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1212
1219
|
self.previewSessionAlertPending = true
|
|
1213
1220
|
self.implementation.previewSession = true
|
|
1214
1221
|
self.shakeMenuEnabled = true
|
|
1222
|
+
self.syncShakeMenuGestureRecognizer()
|
|
1215
1223
|
UserDefaults.standard.set(true, forKey: self.previewSessionDefaultsKey)
|
|
1216
1224
|
UserDefaults.standard.set(true, forKey: self.previewSessionAlertPendingDefaultsKey)
|
|
1217
1225
|
UserDefaults.standard.synchronize()
|
|
@@ -1398,6 +1406,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1398
1406
|
}
|
|
1399
1407
|
self.shakeMenuEnabled = previousShakeMenuEnabled
|
|
1400
1408
|
self.shakeChannelSelectorEnabled = previousShakeChannelSelectorEnabled
|
|
1409
|
+
self.syncShakeMenuGestureRecognizer()
|
|
1401
1410
|
_ = self.implementation.setPreviewFallbackBundle(fallback: nil)
|
|
1402
1411
|
self.clearPreviewSessionPreferences()
|
|
1403
1412
|
logger.info("Preview session ended")
|
|
@@ -1421,6 +1430,8 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1421
1430
|
self.hidePreviewTransitionLoader(reason: "preview-session-disabled")
|
|
1422
1431
|
self.shakeMenuEnabled = self.getBooleanConfig("shakeMenu", defaultValue: false)
|
|
1423
1432
|
self.shakeChannelSelectorEnabled = self.getBooleanConfig("allowShakeChannelSelector", defaultValue: false)
|
|
1433
|
+
self.shakeMenuGesture = Self.normalizedShakeMenuGesture(self.getStringConfig("shakeMenuGesture", defaultValue: Self.shakeMenuGestureShake))
|
|
1434
|
+
self.syncShakeMenuGestureRecognizer()
|
|
1424
1435
|
self.clearPreviewSessionPreferences()
|
|
1425
1436
|
}
|
|
1426
1437
|
|
|
@@ -1652,6 +1663,8 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1652
1663
|
self.implementation.previewSession = false
|
|
1653
1664
|
self.shakeMenuEnabled = self.getBooleanConfig("shakeMenu", defaultValue: false)
|
|
1654
1665
|
self.shakeChannelSelectorEnabled = self.getBooleanConfig("allowShakeChannelSelector", defaultValue: false)
|
|
1666
|
+
self.shakeMenuGesture = Self.normalizedShakeMenuGesture(self.getStringConfig("shakeMenuGesture", defaultValue: Self.shakeMenuGestureShake))
|
|
1667
|
+
self.syncShakeMenuGestureRecognizer()
|
|
1655
1668
|
self.restorePreviewPreviousAppId()
|
|
1656
1669
|
self.restorePreviewPreviousDefaultChannel()
|
|
1657
1670
|
_ = self.implementation.setPreviewFallbackBundle(fallback: nil)
|
|
@@ -2765,6 +2778,28 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
2765
2778
|
}
|
|
2766
2779
|
}
|
|
2767
2780
|
|
|
2781
|
+
static func normalizedShakeMenuGesture(_ value: String?) -> String {
|
|
2782
|
+
guard let value, !value.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else {
|
|
2783
|
+
return shakeMenuGestureShake
|
|
2784
|
+
}
|
|
2785
|
+
let normalized = value.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
2786
|
+
if normalized == shakeMenuGestureThreeFingerPinch {
|
|
2787
|
+
return shakeMenuGestureThreeFingerPinch
|
|
2788
|
+
}
|
|
2789
|
+
return shakeMenuGestureShake
|
|
2790
|
+
}
|
|
2791
|
+
|
|
2792
|
+
static func isSupportedShakeMenuGesture(_ value: String?) -> Bool {
|
|
2793
|
+
guard let value else {
|
|
2794
|
+
return true
|
|
2795
|
+
}
|
|
2796
|
+
let normalized = value.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
2797
|
+
if normalized.isEmpty {
|
|
2798
|
+
return false
|
|
2799
|
+
}
|
|
2800
|
+
return normalized == shakeMenuGestureShake || normalized == shakeMenuGestureThreeFingerPinch
|
|
2801
|
+
}
|
|
2802
|
+
|
|
2768
2803
|
static func autoUpdateModeForLegacyDirectUpdateMode(_ directUpdateMode: String) -> String {
|
|
2769
2804
|
switch directUpdateMode {
|
|
2770
2805
|
case autoUpdateModeInstall, autoUpdateModeLaunch, autoUpdateModeAlways:
|
|
@@ -3485,14 +3520,25 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
3485
3520
|
return
|
|
3486
3521
|
}
|
|
3487
3522
|
|
|
3523
|
+
if let gesture = call.getString("gesture") {
|
|
3524
|
+
guard Self.isSupportedShakeMenuGesture(gesture) else {
|
|
3525
|
+
logger.error("Unsupported shake menu gesture: \(gesture)")
|
|
3526
|
+
call.reject("Unsupported shake menu gesture. Use \"shake\" or \"threeFingerPinch\".")
|
|
3527
|
+
return
|
|
3528
|
+
}
|
|
3529
|
+
self.shakeMenuGesture = Self.normalizedShakeMenuGesture(gesture)
|
|
3530
|
+
}
|
|
3531
|
+
|
|
3488
3532
|
self.shakeMenuEnabled = enabled
|
|
3489
|
-
|
|
3533
|
+
self.syncShakeMenuGestureRecognizer()
|
|
3534
|
+
logger.info("Shake menu \(enabled ? "enabled" : "disabled") with \(self.shakeMenuGesture) gesture")
|
|
3490
3535
|
call.resolve()
|
|
3491
3536
|
}
|
|
3492
3537
|
|
|
3493
3538
|
@objc func isShakeMenuEnabled(_ call: CAPPluginCall) {
|
|
3494
3539
|
call.resolve([
|
|
3495
|
-
"enabled": self.shakeMenuEnabled
|
|
3540
|
+
"enabled": self.shakeMenuEnabled,
|
|
3541
|
+
"gesture": self.shakeMenuGesture
|
|
3496
3542
|
])
|
|
3497
3543
|
}
|
|
3498
3544
|
|
|
@@ -3504,6 +3550,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
3504
3550
|
}
|
|
3505
3551
|
|
|
3506
3552
|
self.shakeChannelSelectorEnabled = enabled
|
|
3553
|
+
self.syncShakeMenuGestureRecognizer()
|
|
3507
3554
|
logger.info("Shake channel selector \(enabled ? "enabled" : "disabled")")
|
|
3508
3555
|
call.resolve()
|
|
3509
3556
|
}
|
|
@@ -9,6 +9,7 @@ import Capacitor
|
|
|
9
9
|
|
|
10
10
|
private var lastShakeMenuShownAt: TimeInterval = 0
|
|
11
11
|
private let shakeMenuCooldownSeconds: TimeInterval = 1.2
|
|
12
|
+
private let threeFingerPinchScaleDelta: CGFloat = 0.30
|
|
12
13
|
|
|
13
14
|
extension UIApplication {
|
|
14
15
|
// swiftlint:disable:next line_length
|
|
@@ -26,42 +27,124 @@ extension UIApplication {
|
|
|
26
27
|
}
|
|
27
28
|
}
|
|
28
29
|
|
|
30
|
+
extension CapacitorUpdaterPlugin: UIGestureRecognizerDelegate {
|
|
31
|
+
func syncShakeMenuGestureRecognizer() {
|
|
32
|
+
DispatchQueue.main.async { [weak self] in
|
|
33
|
+
guard let self else { return }
|
|
34
|
+
|
|
35
|
+
let shouldInstall = self.shakeMenuGesture == Self.shakeMenuGestureThreeFingerPinch &&
|
|
36
|
+
(self.shakeMenuEnabled || self.shakeChannelSelectorEnabled)
|
|
37
|
+
|
|
38
|
+
guard shouldInstall, let targetView = self.bridge?.webView ?? self.bridge?.viewController?.view else {
|
|
39
|
+
self.removeShakeMenuGestureRecognizer()
|
|
40
|
+
return
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if self.shakeMenuPinchGestureRecognizer?.view === targetView {
|
|
44
|
+
return
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
self.removeShakeMenuGestureRecognizer()
|
|
48
|
+
|
|
49
|
+
let recognizer = UIPinchGestureRecognizer(target: self, action: #selector(self.handleShakeMenuPinch(_:)))
|
|
50
|
+
recognizer.cancelsTouchesInView = false
|
|
51
|
+
recognizer.delaysTouchesBegan = false
|
|
52
|
+
recognizer.delaysTouchesEnded = false
|
|
53
|
+
recognizer.delegate = self
|
|
54
|
+
targetView.addGestureRecognizer(recognizer)
|
|
55
|
+
self.shakeMenuPinchGestureRecognizer = recognizer
|
|
56
|
+
self.logger.info("Three finger pinch menu gesture initialized")
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
func removeShakeMenuGestureRecognizer() {
|
|
61
|
+
if let recognizer = self.shakeMenuPinchGestureRecognizer {
|
|
62
|
+
recognizer.view?.removeGestureRecognizer(recognizer)
|
|
63
|
+
self.shakeMenuPinchGestureRecognizer = nil
|
|
64
|
+
self.shakeMenuPinchGestureTriggered = false
|
|
65
|
+
self.logger.info("Three finger pinch menu gesture stopped")
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
@objc func handleShakeMenuPinch(_ recognizer: UIPinchGestureRecognizer) {
|
|
70
|
+
if recognizer.state == .ended || recognizer.state == .cancelled || recognizer.state == .failed {
|
|
71
|
+
self.shakeMenuPinchGestureTriggered = false
|
|
72
|
+
return
|
|
73
|
+
}
|
|
74
|
+
guard recognizer.state == .changed, !self.shakeMenuPinchGestureTriggered, recognizer.numberOfTouches == 3 else {
|
|
75
|
+
return
|
|
76
|
+
}
|
|
77
|
+
guard abs(recognizer.scale - 1) >= threeFingerPinchScaleDelta else {
|
|
78
|
+
return
|
|
79
|
+
}
|
|
80
|
+
guard self.shakeMenuGesture == Self.shakeMenuGestureThreeFingerPinch, let bridge = self.bridge else {
|
|
81
|
+
return
|
|
82
|
+
}
|
|
83
|
+
guard let window = recognizer.view?.window ?? bridge.viewController?.view.window else {
|
|
84
|
+
return
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
self.shakeMenuPinchGestureTriggered = true
|
|
88
|
+
_ = window.showCapacitorUpdaterMenu(plugin: self, bridge: bridge, gestureName: "Three finger pinch")
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
public func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool {
|
|
92
|
+
if gestureRecognizer === self.shakeMenuPinchGestureRecognizer {
|
|
93
|
+
self.shakeMenuPinchGestureTriggered = false
|
|
94
|
+
}
|
|
95
|
+
return true
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
public func gestureRecognizer(
|
|
99
|
+
_: UIGestureRecognizer,
|
|
100
|
+
shouldRecognizeSimultaneouslyWith _: UIGestureRecognizer
|
|
101
|
+
) -> Bool {
|
|
102
|
+
true
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
29
106
|
extension UIWindow {
|
|
30
107
|
override open func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
|
|
31
108
|
if motion == .motionShake {
|
|
32
|
-
// Find the CapacitorUpdaterPlugin instance
|
|
33
109
|
guard let bridgeViewController = rootViewController as? CAPBridgeViewController,
|
|
34
110
|
let bridge = bridgeViewController.bridge,
|
|
35
111
|
let plugin = bridge.plugin(withName: "CapacitorUpdater") as? CapacitorUpdaterPlugin else {
|
|
36
112
|
return
|
|
37
113
|
}
|
|
38
|
-
|
|
39
|
-
let canShowPreviewMenu = plugin.shakeMenuEnabled && plugin.hasActivePreviewSession()
|
|
40
|
-
let canShowChannelSelector = plugin.shakeChannelSelectorEnabled
|
|
41
|
-
|
|
42
|
-
if !canShowPreviewMenu && !canShowChannelSelector {
|
|
43
|
-
if plugin.shakeMenuEnabled {
|
|
44
|
-
plugin.logger.info("Shake preview menu ignored because no preview session is active")
|
|
45
|
-
}
|
|
114
|
+
guard plugin.shakeMenuGesture == CapacitorUpdaterPlugin.shakeMenuGestureShake else {
|
|
46
115
|
return
|
|
47
116
|
}
|
|
48
117
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
return
|
|
53
|
-
}
|
|
118
|
+
_ = showCapacitorUpdaterMenu(plugin: plugin, bridge: bridge, gestureName: "Shake")
|
|
119
|
+
}
|
|
120
|
+
}
|
|
54
121
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
122
|
+
@discardableResult
|
|
123
|
+
fileprivate func showCapacitorUpdaterMenu(plugin: CapacitorUpdaterPlugin, bridge: CAPBridgeProtocol, gestureName: String) -> Bool {
|
|
124
|
+
let canShowPreviewMenu = plugin.shakeMenuEnabled && plugin.hasActivePreviewSession()
|
|
125
|
+
let canShowChannelSelector = plugin.shakeChannelSelectorEnabled
|
|
126
|
+
|
|
127
|
+
if !canShowPreviewMenu && !canShowChannelSelector {
|
|
128
|
+
if plugin.shakeMenuEnabled {
|
|
129
|
+
plugin.logger.info("\(gestureName) preview menu ignored because no preview session is active")
|
|
63
130
|
}
|
|
131
|
+
return false
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
let now = Date().timeIntervalSince1970
|
|
135
|
+
guard now - lastShakeMenuShownAt >= shakeMenuCooldownSeconds else {
|
|
136
|
+
plugin.logger.info("\(gestureName) menu ignored because cooldown is active")
|
|
137
|
+
return false
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
let didShow = canShowPreviewMenu
|
|
141
|
+
? showDefaultMenu(plugin: plugin, bridge: bridge)
|
|
142
|
+
: showChannelSelector(plugin: plugin, bridge: bridge)
|
|
143
|
+
|
|
144
|
+
if didShow {
|
|
145
|
+
lastShakeMenuShownAt = now
|
|
64
146
|
}
|
|
147
|
+
return didShow
|
|
65
148
|
}
|
|
66
149
|
|
|
67
150
|
@discardableResult
|