@capgo/capacitor-updater 8.47.6 → 8.47.7
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 +13 -20
- package/android/src/main/java/ee/forgr/capacitor_updater/CapacitorUpdaterPlugin.java +175 -53
- package/android/src/main/java/ee/forgr/capacitor_updater/CapgoUpdater.java +48 -46
- package/android/src/main/java/ee/forgr/capacitor_updater/ShakeMenu.java +95 -39
- package/dist/docs.json +5 -5
- package/dist/esm/definitions.d.ts +16 -24
- package/dist/esm/definitions.js.map +1 -1
- package/ios/Sources/CapacitorUpdaterPlugin/CapacitorUpdaterPlugin.swift +182 -36
- package/ios/Sources/CapacitorUpdaterPlugin/CapgoUpdater.swift +1 -1
- package/ios/Sources/CapacitorUpdaterPlugin/InternalUtils.swift +1 -1
- package/ios/Sources/CapacitorUpdaterPlugin/ShakeMenu.swift +25 -8
- package/package.json +1 -1
|
@@ -79,7 +79,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
79
79
|
CAPPluginMethod(name: "completeFlexibleUpdate", returnType: CAPPluginReturnPromise)
|
|
80
80
|
]
|
|
81
81
|
public var implementation = CapgoUpdater()
|
|
82
|
-
private let pluginVersion: String = "8.47.
|
|
82
|
+
private let pluginVersion: String = "8.47.7"
|
|
83
83
|
static let updateUrlDefault = "https://plugin.capgo.app/updates"
|
|
84
84
|
static let statsUrlDefault = "https://plugin.capgo.app/stats"
|
|
85
85
|
static let channelUrlDefault = "https://plugin.capgo.app/channel_self"
|
|
@@ -89,6 +89,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
89
89
|
static let autoUpdateModeLaunch = "onLaunch"
|
|
90
90
|
static let autoUpdateModeAlways = "always"
|
|
91
91
|
static let autoUpdateModeOnlyDownload = "onlyDownload"
|
|
92
|
+
private static let previewLoaderTimeoutMs = 60000
|
|
92
93
|
private let keepUrlPathFlagKey = "__capgo_keep_url_path_after_reload"
|
|
93
94
|
private let customIdDefaultsKey = "CapacitorUpdater.customId"
|
|
94
95
|
private let updateUrlDefaultsKey = "CapacitorUpdater.updateUrl"
|
|
@@ -131,6 +132,10 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
131
132
|
private var autoSplashscreenTimeoutWorkItem: DispatchWorkItem?
|
|
132
133
|
private var splashscreenLoaderView: UIActivityIndicatorView?
|
|
133
134
|
private var splashscreenLoaderContainer: UIView?
|
|
135
|
+
private var previewTransitionLoaderView: UIActivityIndicatorView?
|
|
136
|
+
private var previewTransitionLoaderContainer: UIView?
|
|
137
|
+
private var previewTransitionLoaderTimeoutWorkItem: DispatchWorkItem?
|
|
138
|
+
private var previewTransitionLoaderRequested = false
|
|
134
139
|
private let splashscreenPluginName = "SplashScreen"
|
|
135
140
|
private let splashscreenRetryDelayMilliseconds = 100
|
|
136
141
|
private let splashscreenMaxRetries = 20
|
|
@@ -243,7 +248,8 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
243
248
|
if previewSessionEnabled {
|
|
244
249
|
previewSessionAlertPending = UserDefaults.standard.object(forKey: previewSessionAlertPendingDefaultsKey) as? Bool ?? true
|
|
245
250
|
shakeMenuEnabled = true
|
|
246
|
-
shakeChannelSelectorEnabled =
|
|
251
|
+
shakeChannelSelectorEnabled = UserDefaults.standard.object(forKey: previewPreviousShakeChannelSelectorDefaultsKey) as? Bool
|
|
252
|
+
?? shakeChannelSelectorEnabled
|
|
247
253
|
}
|
|
248
254
|
periodCheckDelay = Self.normalizedPeriodCheckDelaySeconds(getConfig().getInt("periodCheckDelay", 0))
|
|
249
255
|
|
|
@@ -1119,6 +1125,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1119
1125
|
|
|
1120
1126
|
@objc func startPreviewSession(_ call: CAPPluginCall) {
|
|
1121
1127
|
guard self.allowPreview else {
|
|
1128
|
+
self.hidePreviewTransitionLoader(reason: "preview-session-not-allowed")
|
|
1122
1129
|
logger.error("startPreviewSession called without allowPreview")
|
|
1123
1130
|
call.reject("startPreviewSession not allowed. Set allowPreview to true in your config to enable it.")
|
|
1124
1131
|
return
|
|
@@ -1127,6 +1134,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1127
1134
|
let rawPayloadUrl = call.getString("payloadUrl")
|
|
1128
1135
|
let previewPayloadUrl = self.normalizedPreviewPayloadUrl(rawPayloadUrl)
|
|
1129
1136
|
if let rawPayloadUrl = rawPayloadUrl, !rawPayloadUrl.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty, previewPayloadUrl == nil {
|
|
1137
|
+
self.hidePreviewTransitionLoader(reason: "preview-session-invalid-payload")
|
|
1130
1138
|
logger.error("startPreviewSession called with invalid payloadUrl")
|
|
1131
1139
|
call.reject("Invalid preview payloadUrl")
|
|
1132
1140
|
return
|
|
@@ -1135,6 +1143,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1135
1143
|
if !self.previewSessionEnabled {
|
|
1136
1144
|
let current = self.implementation.getCurrentBundle()
|
|
1137
1145
|
guard self.implementation.setPreviewFallbackBundle(fallback: current.getId()) else {
|
|
1146
|
+
self.hidePreviewTransitionLoader(reason: "preview-session-fallback-failed")
|
|
1138
1147
|
logger.error("Could not save current bundle as preview fallback")
|
|
1139
1148
|
call.reject("Could not save current bundle as preview fallback")
|
|
1140
1149
|
return
|
|
@@ -1175,11 +1184,11 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1175
1184
|
}
|
|
1176
1185
|
|
|
1177
1186
|
self.clearIncomingPreviewTransition()
|
|
1187
|
+
self.hidePreviewTransitionLoader(reason: "preview-session-started")
|
|
1178
1188
|
self.previewSessionEnabled = true
|
|
1179
1189
|
self.previewSessionAlertPending = true
|
|
1180
1190
|
self.implementation.previewSession = true
|
|
1181
1191
|
self.shakeMenuEnabled = true
|
|
1182
|
-
self.shakeChannelSelectorEnabled = false
|
|
1183
1192
|
UserDefaults.standard.set(true, forKey: self.previewSessionDefaultsKey)
|
|
1184
1193
|
UserDefaults.standard.set(true, forKey: self.previewSessionAlertPendingDefaultsKey)
|
|
1185
1194
|
UserDefaults.standard.synchronize()
|
|
@@ -1189,8 +1198,10 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1189
1198
|
func leavePreviewSessionFromShakeMenu() -> Bool {
|
|
1190
1199
|
let previewBundle = self.implementation.getCurrentBundle()
|
|
1191
1200
|
|
|
1201
|
+
self.showPreviewTransitionLoader(reason: "leave-preview-session")
|
|
1192
1202
|
let didReset = self.resetToPreviewFallbackBundle()
|
|
1193
1203
|
guard didReset else {
|
|
1204
|
+
self.hidePreviewTransitionLoader(reason: "leave-preview-session-failed")
|
|
1194
1205
|
return false
|
|
1195
1206
|
}
|
|
1196
1207
|
|
|
@@ -1210,10 +1221,12 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1210
1221
|
}
|
|
1211
1222
|
|
|
1212
1223
|
self.isLeavingPreviewForIncomingLink = true
|
|
1224
|
+
self.showPreviewTransitionLoader(reason: "preview-launch-deeplink")
|
|
1213
1225
|
logger.info("Preview deeplink launch detected while preview session is active; restoring fallback before initial load")
|
|
1214
1226
|
if !self.leavePreviewSessionWithoutReload() {
|
|
1215
1227
|
logger.error("Could not leave preview session before initial preview deeplink routing")
|
|
1216
1228
|
self.isLeavingPreviewForIncomingLink = false
|
|
1229
|
+
self.hidePreviewTransitionLoader(reason: "preview-launch-deeplink-failed")
|
|
1217
1230
|
}
|
|
1218
1231
|
}
|
|
1219
1232
|
|
|
@@ -1239,15 +1252,18 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1239
1252
|
}
|
|
1240
1253
|
|
|
1241
1254
|
private func leavePreviewSessionForIncomingPreviewLink() -> Bool {
|
|
1255
|
+
self.showPreviewTransitionLoader(reason: "incoming-preview-deeplink")
|
|
1242
1256
|
let previewBundle = self.implementation.getCurrentBundle()
|
|
1243
1257
|
guard let previewFallbackBundle = self.implementation.getPreviewFallbackBundle(), !previewFallbackBundle.isErrorStatus() else {
|
|
1244
1258
|
logger.error("No preview fallback bundle available")
|
|
1245
1259
|
self.clearIncomingPreviewTransition()
|
|
1260
|
+
self.hidePreviewTransitionLoader(reason: "incoming-preview-deeplink-failed")
|
|
1246
1261
|
return false
|
|
1247
1262
|
}
|
|
1248
1263
|
guard self.implementation.canSet(bundle: previewFallbackBundle) else {
|
|
1249
1264
|
logger.error("Preview fallback bundle is not installable")
|
|
1250
1265
|
self.clearIncomingPreviewTransition()
|
|
1266
|
+
self.hidePreviewTransitionLoader(reason: "incoming-preview-deeplink-failed")
|
|
1251
1267
|
return false
|
|
1252
1268
|
}
|
|
1253
1269
|
|
|
@@ -1255,6 +1271,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1255
1271
|
guard self.implementation.stagePreviewFallbackReload(bundle: previewFallbackBundle) else {
|
|
1256
1272
|
logger.error("Could not stage preview fallback bundle")
|
|
1257
1273
|
self.clearIncomingPreviewTransition()
|
|
1274
|
+
self.hidePreviewTransitionLoader(reason: "incoming-preview-deeplink-failed")
|
|
1258
1275
|
return false
|
|
1259
1276
|
}
|
|
1260
1277
|
|
|
@@ -1272,6 +1289,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1272
1289
|
self.implementation.restoreResetState(previousState)
|
|
1273
1290
|
self.restoreLiveBundleStateAfterFailedReload()
|
|
1274
1291
|
self.clearIncomingPreviewTransition()
|
|
1292
|
+
self.hidePreviewTransitionLoader(reason: "incoming-preview-deeplink-reload-failed")
|
|
1275
1293
|
}
|
|
1276
1294
|
return didReload
|
|
1277
1295
|
}
|
|
@@ -1289,11 +1307,18 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1289
1307
|
}
|
|
1290
1308
|
|
|
1291
1309
|
func reloadPreviewSessionFromShakeMenu() -> Bool {
|
|
1310
|
+
self.showPreviewTransitionLoader(reason: "reload-preview-session")
|
|
1311
|
+
let didReload: Bool
|
|
1292
1312
|
if let payloadUrl = self.storedPreviewPayloadUrl() {
|
|
1293
|
-
|
|
1313
|
+
didReload = self.refreshPreviewSessionFromPayloadUrl(payloadUrl)
|
|
1314
|
+
} else {
|
|
1315
|
+
didReload = self._reload()
|
|
1294
1316
|
}
|
|
1295
1317
|
|
|
1296
|
-
|
|
1318
|
+
if !didReload {
|
|
1319
|
+
self.hidePreviewTransitionLoader(reason: "reload-preview-session-failed")
|
|
1320
|
+
}
|
|
1321
|
+
return didReload
|
|
1297
1322
|
}
|
|
1298
1323
|
|
|
1299
1324
|
func hasActivePreviewSession() -> Bool {
|
|
@@ -1370,6 +1395,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1370
1395
|
self.previewSessionAlertPending = false
|
|
1371
1396
|
self.isLeavingPreviewForIncomingLink = false
|
|
1372
1397
|
self.implementation.previewSession = false
|
|
1398
|
+
self.hidePreviewTransitionLoader(reason: "preview-session-disabled")
|
|
1373
1399
|
self.shakeMenuEnabled = getConfig().getBoolean("shakeMenu", false)
|
|
1374
1400
|
self.shakeChannelSelectorEnabled = getConfig().getBoolean("allowShakeChannelSelector", false)
|
|
1375
1401
|
self.clearPreviewSessionPreferences()
|
|
@@ -1492,12 +1518,14 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
1492
1518
|
}
|
|
1493
1519
|
|
|
1494
1520
|
self.isLeavingPreviewForIncomingLink = true
|
|
1521
|
+
self.showPreviewTransitionLoader(reason: "incoming-preview-deeplink")
|
|
1495
1522
|
logger.info("Preview deeplink received while preview session is active; restoring fallback before routing")
|
|
1496
1523
|
DispatchQueue.global(qos: .userInitiated).async {
|
|
1497
1524
|
let didLeave = self.leavePreviewSessionForIncomingPreviewLink()
|
|
1498
1525
|
if !didLeave {
|
|
1499
1526
|
self.logger.error("Could not leave preview session before routing incoming preview deeplink")
|
|
1500
1527
|
self.isLeavingPreviewForIncomingLink = false
|
|
1528
|
+
self.hidePreviewTransitionLoader(reason: "incoming-preview-deeplink-failed")
|
|
1501
1529
|
}
|
|
1502
1530
|
}
|
|
1503
1531
|
}
|
|
@@ -2040,6 +2068,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
2040
2068
|
self.implementation.setSuccess(bundle: bundle, autoDeletePrevious: self.autoDeletePrevious)
|
|
2041
2069
|
logger.info("Current bundle loaded successfully. [notifyAppReady was called] \(bundle.toString())")
|
|
2042
2070
|
self.clearIncomingPreviewTransition()
|
|
2071
|
+
self.hidePreviewTransitionLoader(reason: "notify-app-ready")
|
|
2043
2072
|
|
|
2044
2073
|
call.resolve(["bundle": bundle.toJSON()])
|
|
2045
2074
|
}
|
|
@@ -2186,6 +2215,7 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
2186
2215
|
if self.autoSplashscreen {
|
|
2187
2216
|
self.hideSplashscreen()
|
|
2188
2217
|
}
|
|
2218
|
+
self.hidePreviewTransitionLoader(reason: "app-ready")
|
|
2189
2219
|
}
|
|
2190
2220
|
}
|
|
2191
2221
|
|
|
@@ -2353,6 +2383,51 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
2353
2383
|
}
|
|
2354
2384
|
}
|
|
2355
2385
|
|
|
2386
|
+
private func createLoaderOverlay(
|
|
2387
|
+
backgroundColor: UIColor,
|
|
2388
|
+
isUserInteractionEnabled: Bool,
|
|
2389
|
+
indicatorColor: UIColor?
|
|
2390
|
+
) -> (container: UIView, indicator: UIActivityIndicatorView) {
|
|
2391
|
+
let container = UIView()
|
|
2392
|
+
container.translatesAutoresizingMaskIntoConstraints = false
|
|
2393
|
+
container.backgroundColor = backgroundColor
|
|
2394
|
+
container.isUserInteractionEnabled = isUserInteractionEnabled
|
|
2395
|
+
|
|
2396
|
+
let indicatorStyle: UIActivityIndicatorView.Style
|
|
2397
|
+
if #available(iOS 13.0, *) {
|
|
2398
|
+
indicatorStyle = .large
|
|
2399
|
+
} else {
|
|
2400
|
+
indicatorStyle = .whiteLarge
|
|
2401
|
+
}
|
|
2402
|
+
|
|
2403
|
+
let indicator = UIActivityIndicatorView(style: indicatorStyle)
|
|
2404
|
+
indicator.translatesAutoresizingMaskIntoConstraints = false
|
|
2405
|
+
indicator.hidesWhenStopped = false
|
|
2406
|
+
if let indicatorColor = indicatorColor {
|
|
2407
|
+
indicator.color = indicatorColor
|
|
2408
|
+
}
|
|
2409
|
+
indicator.startAnimating()
|
|
2410
|
+
|
|
2411
|
+
return (container, indicator)
|
|
2412
|
+
}
|
|
2413
|
+
|
|
2414
|
+
private func attachLoaderOverlay(
|
|
2415
|
+
_ overlay: (container: UIView, indicator: UIActivityIndicatorView),
|
|
2416
|
+
to rootView: UIView
|
|
2417
|
+
) {
|
|
2418
|
+
overlay.container.addSubview(overlay.indicator)
|
|
2419
|
+
rootView.addSubview(overlay.container)
|
|
2420
|
+
|
|
2421
|
+
NSLayoutConstraint.activate([
|
|
2422
|
+
overlay.container.leadingAnchor.constraint(equalTo: rootView.leadingAnchor),
|
|
2423
|
+
overlay.container.trailingAnchor.constraint(equalTo: rootView.trailingAnchor),
|
|
2424
|
+
overlay.container.topAnchor.constraint(equalTo: rootView.topAnchor),
|
|
2425
|
+
overlay.container.bottomAnchor.constraint(equalTo: rootView.bottomAnchor),
|
|
2426
|
+
overlay.indicator.centerXAnchor.constraint(equalTo: overlay.container.centerXAnchor),
|
|
2427
|
+
overlay.indicator.centerYAnchor.constraint(equalTo: overlay.container.centerYAnchor)
|
|
2428
|
+
])
|
|
2429
|
+
}
|
|
2430
|
+
|
|
2356
2431
|
private func addSplashscreenLoaderIfNeeded() {
|
|
2357
2432
|
guard self.autoSplashscreenLoader else {
|
|
2358
2433
|
return
|
|
@@ -2367,40 +2442,20 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
2367
2442
|
return
|
|
2368
2443
|
}
|
|
2369
2444
|
|
|
2370
|
-
let
|
|
2371
|
-
container.translatesAutoresizingMaskIntoConstraints = false
|
|
2372
|
-
container.backgroundColor = UIColor.clear
|
|
2373
|
-
container.isUserInteractionEnabled = false
|
|
2374
|
-
|
|
2375
|
-
let indicatorStyle: UIActivityIndicatorView.Style
|
|
2445
|
+
let indicatorColor: UIColor?
|
|
2376
2446
|
if #available(iOS 13.0, *) {
|
|
2377
|
-
|
|
2447
|
+
indicatorColor = UIColor.label
|
|
2378
2448
|
} else {
|
|
2379
|
-
|
|
2380
|
-
}
|
|
2381
|
-
|
|
2382
|
-
let indicator = UIActivityIndicatorView(style: indicatorStyle)
|
|
2383
|
-
indicator.translatesAutoresizingMaskIntoConstraints = false
|
|
2384
|
-
indicator.hidesWhenStopped = false
|
|
2385
|
-
if #available(iOS 13.0, *) {
|
|
2386
|
-
indicator.color = UIColor.label
|
|
2449
|
+
indicatorColor = nil
|
|
2387
2450
|
}
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
container.topAnchor.constraint(equalTo: rootView.topAnchor),
|
|
2397
|
-
container.bottomAnchor.constraint(equalTo: rootView.bottomAnchor),
|
|
2398
|
-
indicator.centerXAnchor.constraint(equalTo: container.centerXAnchor),
|
|
2399
|
-
indicator.centerYAnchor.constraint(equalTo: container.centerYAnchor)
|
|
2400
|
-
])
|
|
2401
|
-
|
|
2402
|
-
self.splashscreenLoaderContainer = container
|
|
2403
|
-
self.splashscreenLoaderView = indicator
|
|
2451
|
+
let overlay = self.createLoaderOverlay(
|
|
2452
|
+
backgroundColor: UIColor.clear,
|
|
2453
|
+
isUserInteractionEnabled: false,
|
|
2454
|
+
indicatorColor: indicatorColor
|
|
2455
|
+
)
|
|
2456
|
+
self.attachLoaderOverlay(overlay, to: rootView)
|
|
2457
|
+
self.splashscreenLoaderContainer = overlay.container
|
|
2458
|
+
self.splashscreenLoaderView = overlay.indicator
|
|
2404
2459
|
}
|
|
2405
2460
|
|
|
2406
2461
|
if Thread.isMainThread {
|
|
@@ -2429,6 +2484,97 @@ public class CapacitorUpdaterPlugin: CAPPlugin, CAPBridgedPlugin {
|
|
|
2429
2484
|
}
|
|
2430
2485
|
}
|
|
2431
2486
|
|
|
2487
|
+
private func showPreviewTransitionLoader(reason: String) {
|
|
2488
|
+
self.previewTransitionLoaderRequested = true
|
|
2489
|
+
let showLoader = {
|
|
2490
|
+
guard self.previewTransitionLoaderRequested else {
|
|
2491
|
+
return
|
|
2492
|
+
}
|
|
2493
|
+
|
|
2494
|
+
if let container = self.previewTransitionLoaderContainer {
|
|
2495
|
+
self.previewTransitionLoaderTimeoutWorkItem?.cancel()
|
|
2496
|
+
self.schedulePreviewTransitionLoaderTimeout()
|
|
2497
|
+
container.superview?.bringSubviewToFront(container)
|
|
2498
|
+
return
|
|
2499
|
+
}
|
|
2500
|
+
|
|
2501
|
+
guard let rootView = self.bridge?.viewController?.view else {
|
|
2502
|
+
self.logger.warn("Preview transition loader unavailable: root view missing for \(reason)")
|
|
2503
|
+
self.previewTransitionLoaderRequested = false
|
|
2504
|
+
return
|
|
2505
|
+
}
|
|
2506
|
+
|
|
2507
|
+
self.previewTransitionLoaderTimeoutWorkItem?.cancel()
|
|
2508
|
+
self.schedulePreviewTransitionLoaderTimeout()
|
|
2509
|
+
|
|
2510
|
+
let indicatorColor: UIColor?
|
|
2511
|
+
if #available(iOS 13.0, *) {
|
|
2512
|
+
indicatorColor = UIColor.white
|
|
2513
|
+
} else {
|
|
2514
|
+
indicatorColor = nil
|
|
2515
|
+
}
|
|
2516
|
+
let overlay = self.createLoaderOverlay(
|
|
2517
|
+
backgroundColor: UIColor.black.withAlphaComponent(0.18),
|
|
2518
|
+
isUserInteractionEnabled: true,
|
|
2519
|
+
indicatorColor: indicatorColor
|
|
2520
|
+
)
|
|
2521
|
+
self.attachLoaderOverlay(overlay, to: rootView)
|
|
2522
|
+
self.previewTransitionLoaderContainer = overlay.container
|
|
2523
|
+
self.previewTransitionLoaderView = overlay.indicator
|
|
2524
|
+
self.logger.info("Preview transition loader shown: \(reason)")
|
|
2525
|
+
}
|
|
2526
|
+
|
|
2527
|
+
if Thread.isMainThread {
|
|
2528
|
+
showLoader()
|
|
2529
|
+
} else {
|
|
2530
|
+
DispatchQueue.main.async {
|
|
2531
|
+
showLoader()
|
|
2532
|
+
}
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
|
|
2536
|
+
private func hidePreviewTransitionLoader(reason: String) {
|
|
2537
|
+
if !self.previewTransitionLoaderRequested &&
|
|
2538
|
+
self.previewTransitionLoaderContainer == nil &&
|
|
2539
|
+
self.previewTransitionLoaderTimeoutWorkItem == nil {
|
|
2540
|
+
return
|
|
2541
|
+
}
|
|
2542
|
+
|
|
2543
|
+
let hideLoader = {
|
|
2544
|
+
self.previewTransitionLoaderRequested = false
|
|
2545
|
+
self.previewTransitionLoaderTimeoutWorkItem?.cancel()
|
|
2546
|
+
self.previewTransitionLoaderTimeoutWorkItem = nil
|
|
2547
|
+
guard self.previewTransitionLoaderContainer != nil else {
|
|
2548
|
+
return
|
|
2549
|
+
}
|
|
2550
|
+
self.previewTransitionLoaderView?.stopAnimating()
|
|
2551
|
+
self.previewTransitionLoaderContainer?.removeFromSuperview()
|
|
2552
|
+
self.previewTransitionLoaderView = nil
|
|
2553
|
+
self.previewTransitionLoaderContainer = nil
|
|
2554
|
+
self.logger.info("Preview transition loader hidden: \(reason)")
|
|
2555
|
+
}
|
|
2556
|
+
|
|
2557
|
+
if Thread.isMainThread {
|
|
2558
|
+
hideLoader()
|
|
2559
|
+
} else {
|
|
2560
|
+
DispatchQueue.main.async {
|
|
2561
|
+
hideLoader()
|
|
2562
|
+
}
|
|
2563
|
+
}
|
|
2564
|
+
}
|
|
2565
|
+
|
|
2566
|
+
private func schedulePreviewTransitionLoaderTimeout() {
|
|
2567
|
+
self.previewTransitionLoaderTimeoutWorkItem?.cancel()
|
|
2568
|
+
let workItem = DispatchWorkItem { [weak self] in
|
|
2569
|
+
self?.hidePreviewTransitionLoader(reason: "preview-transition-timeout")
|
|
2570
|
+
}
|
|
2571
|
+
self.previewTransitionLoaderTimeoutWorkItem = workItem
|
|
2572
|
+
DispatchQueue.main.asyncAfter(
|
|
2573
|
+
deadline: .now() + .milliseconds(Self.previewLoaderTimeoutMs),
|
|
2574
|
+
execute: workItem
|
|
2575
|
+
)
|
|
2576
|
+
}
|
|
2577
|
+
|
|
2432
2578
|
private func scheduleSplashscreenTimeout() {
|
|
2433
2579
|
guard self.autoSplashscreenTimeout > 0 else {
|
|
2434
2580
|
return
|
|
@@ -2431,7 +2431,7 @@ import UIKit
|
|
|
2431
2431
|
if let channels = responseValue.channels {
|
|
2432
2432
|
listChannels.channels = channels.map { channel in
|
|
2433
2433
|
var channelDict: [String: Any] = [:]
|
|
2434
|
-
channelDict["id"] = channel.id
|
|
2434
|
+
channelDict["id"] = channel.id
|
|
2435
2435
|
channelDict["name"] = channel.name ?? ""
|
|
2436
2436
|
channelDict["public"] = channel.public ?? false
|
|
2437
2437
|
channelDict["allow_self_set"] = channel.allow_self_set ?? false
|
|
@@ -33,17 +33,20 @@ extension UIWindow {
|
|
|
33
33
|
return
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
let canShowPreviewMenu = plugin.shakeMenuEnabled && plugin.hasActivePreviewSession()
|
|
37
|
+
let canShowChannelSelector = plugin.shakeChannelSelectorEnabled
|
|
38
|
+
|
|
39
|
+
if !canShowPreviewMenu && !canShowChannelSelector {
|
|
40
|
+
if plugin.shakeMenuEnabled {
|
|
41
|
+
plugin.logger.info("Shake preview menu ignored because no preview session is active")
|
|
42
|
+
}
|
|
38
43
|
return
|
|
39
44
|
}
|
|
40
45
|
|
|
41
|
-
if
|
|
46
|
+
if canShowPreviewMenu {
|
|
42
47
|
showDefaultMenu(plugin: plugin, bridge: bridge)
|
|
43
|
-
} else if plugin.shakeChannelSelectorEnabled {
|
|
44
|
-
showChannelSelector(plugin: plugin, bridge: bridge)
|
|
45
48
|
} else {
|
|
46
|
-
|
|
49
|
+
showChannelSelector(plugin: plugin, bridge: bridge)
|
|
47
50
|
}
|
|
48
51
|
}
|
|
49
52
|
}
|
|
@@ -56,8 +59,8 @@ extension UIWindow {
|
|
|
56
59
|
return
|
|
57
60
|
}
|
|
58
61
|
|
|
59
|
-
|
|
60
|
-
|
|
62
|
+
guard plugin.hasActivePreviewSession() else {
|
|
63
|
+
plugin.logger.info("Shake preview menu ignored because no preview session is active")
|
|
61
64
|
return
|
|
62
65
|
}
|
|
63
66
|
|
|
@@ -90,6 +93,20 @@ extension UIWindow {
|
|
|
90
93
|
}
|
|
91
94
|
})
|
|
92
95
|
|
|
96
|
+
if plugin.shakeChannelSelectorEnabled {
|
|
97
|
+
alertShake.addAction(UIAlertAction(title: "Switch channel", style: .default) { _ in
|
|
98
|
+
let showSelector = {
|
|
99
|
+
self.showChannelSelector(plugin: plugin, bridge: bridge)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if let presenter = alertShake.presentingViewController {
|
|
103
|
+
presenter.dismiss(animated: true, completion: showSelector)
|
|
104
|
+
} else {
|
|
105
|
+
DispatchQueue.main.async(execute: showSelector)
|
|
106
|
+
}
|
|
107
|
+
})
|
|
108
|
+
}
|
|
109
|
+
|
|
93
110
|
alertShake.addAction(UIAlertAction(title: cancelButtonTitle, style: .default))
|
|
94
111
|
|
|
95
112
|
DispatchQueue.main.async {
|