|
21 | 21 | // |
22 | 22 |
|
23 | 23 | import UIKit |
24 | | -import Lottie |
25 | 24 | import PIALibrary |
26 | 25 | /// Declares a generic, dismissable modal controller. |
27 | 26 | public protocol ModalController: AnyObject { |
@@ -72,9 +71,13 @@ open class AutolayoutViewController: UIViewController, ModalController, Restylab |
72 | 71 | open var status: ViewControllerStatus = .initial { |
73 | 72 | didSet { reloadFormElements() } |
74 | 73 | } |
75 | | - |
| 74 | + |
| 75 | + /// Loading view controller for showing animations |
| 76 | + private var loadingViewController: LoadingViewController? |
| 77 | + |
76 | 78 | deinit { |
77 | 79 | NotificationCenter.default.removeObserver(self) |
| 80 | + loadingViewController?.view.removeFromSuperview() |
78 | 81 | } |
79 | 82 |
|
80 | 83 | /// :nodoc: |
@@ -221,139 +224,55 @@ open class AutolayoutViewController: UIViewController, ModalController, Restylab |
221 | 224 | } |
222 | 225 |
|
223 | 226 | extension AutolayoutViewController: AnimatingLoadingDelegate { |
224 | | - |
225 | | - private struct LottieRepos { |
226 | | - static var graphLoad: AnimationView? |
227 | | - static var containerView: UIView? |
228 | | - } |
229 | | - |
230 | | - var graphLoad: AnimationView? { |
231 | | - get { |
232 | | - return objc_getAssociatedObject(self, &LottieRepos.graphLoad) as? AnimationView |
233 | | - } |
234 | | - set { |
235 | | - if let unwrappedValue = newValue { |
236 | | - objc_setAssociatedObject(self, &LottieRepos.graphLoad, unwrappedValue as AnimationView?, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) |
237 | | - } |
238 | | - } |
239 | | - } |
240 | | - |
241 | | - var containerView: UIView? { |
242 | | - get { |
243 | | - return LottieRepos.containerView |
244 | | - } |
245 | | - set { |
246 | | - if let unwrappedValue = newValue { |
247 | | - LottieRepos.containerView = unwrappedValue |
248 | | - } |
249 | | - } |
250 | | - } |
251 | 227 |
|
252 | 228 | @objc public func showLoadingAnimation() { |
253 | | - if graphLoad == nil { |
254 | | - containerView = UIView(frame: UIScreen.main.bounds) |
255 | | - containerView?.backgroundColor = Theme.current.palette.appearance == .dark ? |
256 | | - UIColor.black.withAlphaComponent(0.72) : |
257 | | - UIColor.piaGrey1.withAlphaComponent(0.75) |
258 | | - graphLoad = AnimationView(name: "pia-spinner") |
259 | | - } |
260 | | - addLoadingAnimation() |
261 | | - } |
262 | | - |
263 | | - private func addLoadingAnimation() { |
264 | | - graphLoad?.loopMode = .loop |
265 | | - if let graphLoad = graphLoad, |
266 | | - let containerView = containerView { |
267 | | - if let key = self.navigationController?.view { |
268 | | - key.addSubview(containerView) |
269 | | - key.addSubview(graphLoad) |
270 | | - } |
271 | | - setLoadingConstraints() |
272 | | - graphLoad.play() |
| 229 | + // If already showing, keep it |
| 230 | + guard loadingViewController == nil else { return } |
| 231 | + |
| 232 | + guard |
| 233 | + let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, |
| 234 | + let window = windowScene.windows.first |
| 235 | + else { |
| 236 | + return |
273 | 237 | } |
274 | | - } |
275 | | - |
276 | | - @objc public func hideLoadingAnimation() { |
277 | | - graphLoad?.stop() |
278 | | - graphLoad?.removeFromSuperview() |
279 | | - containerView?.removeFromSuperview() |
280 | | - } |
281 | | - |
282 | | - private func setLoadingConstraints() { |
283 | | - if let graphLoad = graphLoad, |
284 | | - let keyView = self.navigationController?.view, |
285 | | - let containerView = containerView { |
286 | | - |
287 | | - containerView.translatesAutoresizingMaskIntoConstraints = false |
288 | | - graphLoad.translatesAutoresizingMaskIntoConstraints = false |
289 | 238 |
|
290 | | - NSLayoutConstraint(item: containerView, |
291 | | - attribute: .left, |
292 | | - relatedBy: .equal, |
293 | | - toItem: keyView, |
294 | | - attribute: .left, |
295 | | - multiplier: 1.0, |
296 | | - constant: 0.0).isActive = true |
| 239 | + // Lock UI |
| 240 | + window.isUserInteractionEnabled = false |
297 | 241 |
|
298 | | - NSLayoutConstraint(item: containerView, |
299 | | - attribute: .right, |
300 | | - relatedBy: .equal, |
301 | | - toItem: keyView, |
302 | | - attribute: .right, |
303 | | - multiplier: 1.0, |
304 | | - constant: 0.0).isActive = true |
| 242 | + let loadingVC = LoadingViewController() |
| 243 | + loadingVC.view.translatesAutoresizingMaskIntoConstraints = false |
| 244 | + self.loadingViewController = loadingVC |
305 | 245 |
|
306 | | - NSLayoutConstraint(item: containerView, |
307 | | - attribute: .top, |
308 | | - relatedBy: .equal, |
309 | | - toItem: keyView, |
310 | | - attribute: .top, |
311 | | - multiplier: 1.0, |
312 | | - constant: 0.0).isActive = true |
| 246 | + window.addSubview(loadingVC.view) |
313 | 247 |
|
314 | | - NSLayoutConstraint(item: containerView, |
315 | | - attribute: .bottom, |
316 | | - relatedBy: .equal, |
317 | | - toItem: keyView, |
318 | | - attribute: .bottom, |
319 | | - multiplier: 1.0, |
320 | | - constant: 0.0).isActive = true |
| 248 | + setupLoadingConstraints( |
| 249 | + loadingView: loadingVC.view, |
| 250 | + in: window |
| 251 | + ) |
| 252 | + } |
321 | 253 |
|
322 | | - NSLayoutConstraint(item: graphLoad, |
323 | | - attribute: .centerX, |
324 | | - relatedBy: .equal, |
325 | | - toItem: containerView, |
326 | | - attribute: .centerX, |
327 | | - multiplier: 1.0, |
328 | | - constant: 0.0).isActive = true |
329 | | - |
330 | | - NSLayoutConstraint(item: graphLoad, |
331 | | - attribute: .centerY, |
332 | | - relatedBy: .equal, |
333 | | - toItem: containerView, |
334 | | - attribute: .centerY, |
335 | | - multiplier: 1.0, |
336 | | - constant: 0.0).isActive = true |
337 | | - |
338 | | - let lottieWidth = UIScreen.main.bounds.width/4 |
| 254 | + @objc public func hideLoadingAnimation() { |
| 255 | + // Unlock UI |
| 256 | + let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene |
| 257 | + let window = windowScene?.windows.first |
| 258 | + window?.isUserInteractionEnabled = true |
339 | 259 |
|
340 | | - NSLayoutConstraint(item: graphLoad, |
341 | | - attribute: .width, |
342 | | - relatedBy: .equal, |
343 | | - toItem: nil, |
344 | | - attribute: .width, |
345 | | - multiplier: 1.0, |
346 | | - constant: lottieWidth).isActive = true |
347 | | - |
348 | | - NSLayoutConstraint(item: graphLoad, |
349 | | - attribute: .height, |
350 | | - relatedBy: .equal, |
351 | | - toItem: nil, |
352 | | - attribute: .height, |
353 | | - multiplier: 1.0, |
354 | | - constant: lottieWidth).isActive = true |
| 260 | + loadingViewController?.view.removeFromSuperview() |
| 261 | + loadingViewController = nil |
| 262 | + } |
355 | 263 |
|
356 | | - } |
| 264 | + private func setupLoadingConstraints( |
| 265 | + loadingView: UIView, |
| 266 | + in parentView: UIView |
| 267 | + ) { |
| 268 | + // Loading view centered in parent with fixed size |
| 269 | + let loadingSize = UIScreen.main.bounds.width / 4 |
| 270 | + NSLayoutConstraint.activate([ |
| 271 | + loadingView.centerXAnchor.constraint(equalTo: parentView.centerXAnchor), |
| 272 | + loadingView.centerYAnchor.constraint(equalTo: parentView.centerYAnchor), |
| 273 | + loadingView.widthAnchor.constraint(equalToConstant: loadingSize), |
| 274 | + loadingView.heightAnchor.constraint(equalToConstant: loadingSize) |
| 275 | + ]) |
357 | 276 | } |
358 | 277 |
|
359 | 278 | } |
0 commit comments