Explorar el Código

增加SVProgressHUD

100Years hace 1 mes
padre
commit
448019e030
Se han modificado 30 ficheros con 2578 adiciones y 0 borrados
  1. 21 0
      Example/Pods/SVProgressHUD/LICENSE
  2. 221 0
      Example/Pods/SVProgressHUD/README.md
  3. 14 0
      Example/Pods/SVProgressHUD/SVProgressHUD/PrivacyInfo.xcprivacy
  4. 17 0
      Example/Pods/SVProgressHUD/SVProgressHUD/SVIndefiniteAnimatedView.h
  5. 142 0
      Example/Pods/SVProgressHUD/SVProgressHUD/SVIndefiniteAnimatedView.m
  6. 17 0
      Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressAnimatedView.h
  7. 96 0
      Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressAnimatedView.m
  8. BIN
      Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/angle-mask.png
  9. BIN
      Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/angle-mask@2x.png
  10. BIN
      Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/angle-mask@3x.png
  11. BIN
      Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/error.png
  12. BIN
      Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/error@2x.png
  13. BIN
      Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/error@3x.png
  14. BIN
      Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/info.png
  15. BIN
      Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/info@2x.png
  16. BIN
      Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/info@3x.png
  17. BIN
      Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/success.png
  18. BIN
      Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/success@2x.png
  19. BIN
      Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/success@3x.png
  20. 392 0
      Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.h
  21. 1524 0
      Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.m
  22. 14 0
      Example/Pods/SVProgressHUD/SVProgressHUD/SVRadialGradientLayer.h
  23. 25 0
      Example/Pods/SVProgressHUD/SVProgressHUD/SVRadialGradientLayer.m
  24. 26 0
      Example/Pods/Target Support Files/SVProgressHUD/SVProgressHUD-Info.plist
  25. 5 0
      Example/Pods/Target Support Files/SVProgressHUD/SVProgressHUD-dummy.m
  26. 12 0
      Example/Pods/Target Support Files/SVProgressHUD/SVProgressHUD-prefix.pch
  27. 20 0
      Example/Pods/Target Support Files/SVProgressHUD/SVProgressHUD-umbrella.h
  28. 13 0
      Example/Pods/Target Support Files/SVProgressHUD/SVProgressHUD.debug.xcconfig
  29. 6 0
      Example/Pods/Target Support Files/SVProgressHUD/SVProgressHUD.modulemap
  30. 13 0
      Example/Pods/Target Support Files/SVProgressHUD/SVProgressHUD.release.xcconfig

+ 21 - 0
Example/Pods/SVProgressHUD/LICENSE

@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2011-2023 Sam Vermette, Tobias Totzek and contributors.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 221 - 0
Example/Pods/SVProgressHUD/README.md

@@ -0,0 +1,221 @@
+# SVProgressHUD
+
+![Pod Version](https://img.shields.io/cocoapods/v/SVProgressHUD.svg?style=flat)
+![Pod Platform](https://img.shields.io/cocoapods/p/SVProgressHUD.svg?style=flat)
+![Pod License](https://img.shields.io/cocoapods/l/SVProgressHUD.svg?style=flat)
+[![SwiftPM compatible](https://img.shields.io/badge/SwiftPM-compatible-brightgreen.svg)](https://swift.org/package-manager/)
+[![CocoaPods compatible](https://img.shields.io/badge/CocoaPods-compatible-green.svg?style=flat)](https://cocoapods.org)
+[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-green.svg?style=flat)](https://github.com/Carthage/Carthage)
+
+`SVProgressHUD` is a clean and easy-to-use HUD meant to display the progress of an ongoing task on iOS and tvOS.
+
+![SVProgressHUD](https://raw.githubusercontent.com/SVProgressHUD/SVProgressHUD/master/Images/SVProgressHUD.png)
+
+## Installation
+
+### Swift Package Manager
+
+[Swift Package Manager](https://swift.org/package-manager/) (SwiftPM) is a tool for managing the distribution of Swift code. It simplifies the process of managing Swift package dependencies.
+
+To integrate `SVProgressHUD` into your project using SwiftPM:
+
+1. In Xcode, select **File > Add Package Dependency**.
+2. Enter the following package repository URL: https://github.com/SVProgressHUD/SVProgressHUD.git
+3. Choose the appropriate version (e.g. a specific version, branch, or commit).
+4. Add `SVProgressHUD` to your target dependencies.
+
+`SVProgressHUD` requires at least Swift tools version 5.3.
+
+### From CocoaPods
+
+[CocoaPods](http://cocoapods.org) is a dependency manager for Objective-C, which automates and simplifies the process of using 3rd-party libraries like `SVProgressHUD` in your projects. First, add the following line to your [Podfile](http://guides.cocoapods.org/using/using-cocoapods.html):
+
+```ruby
+pod 'SVProgressHUD'
+```
+
+If you want to use the latest features of `SVProgressHUD` use normal external source dependencies.
+
+```ruby
+pod 'SVProgressHUD', :git => 'https://github.com/SVProgressHUD/SVProgressHUD.git'
+```
+
+This pulls from the `master` branch directly.
+
+Second, install `SVProgressHUD` into your project:
+
+```ruby
+pod install
+```
+
+### Carthage
+
+[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. To integrate `SVProgressHUD` into your Xcode project using Carthage, specify it in your `Cartfile`:
+
+```ogdl
+github "SVProgressHUD/SVProgressHUD"
+```
+
+Run `carthage bootstrap` to build the framework in your repository's Carthage directory. You can then include it in your target's `carthage copy-frameworks` build phase. For more information on this, please see [Carthage's documentation](https://github.com/carthage/carthage#if-youre-building-for-ios-tvos-or-watchos).
+
+### Manually
+
+* Drag the `SVProgressHUD/SVProgressHUD` folder into your project.
+* Take care that `SVProgressHUD.bundle` is added to `Targets->Build Phases->Copy Bundle Resources`.
+* Add the **QuartzCore** framework to your project.
+
+## Swift
+
+Even though `SVProgressHUD` is written in Objective-C, it can be used in Swift with no hassle.
+
+If you use [CocoaPods](http://cocoapods.org) add the following line to your [Podfile](http://guides.cocoapods.org/using/using-cocoapods.html):
+
+```ruby
+use_frameworks!
+```
+
+If you added `SVProgressHUD` manually, just add a [bridging header](https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html) file to your project with the `SVProgressHUD` header included.
+
+## Usage
+
+(see sample Xcode project in `/Demo`)
+
+`SVProgressHUD` is created as a singleton (i.e. it doesn't need to be explicitly allocated and instantiated; you directly call `[SVProgressHUD method]` / `SVProgressHUD.method()`).
+
+**Use `SVProgressHUD` wisely! Only use it if you absolutely need to perform a task before taking the user forward. Bad use case examples: pull to refresh, infinite scrolling, sending message.**
+
+Using `SVProgressHUD` in your app will usually look as simple as this.
+
+**Objective-C:**
+
+```objective-c
+[SVProgressHUD show];
+dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+    // time-consuming task
+    dispatch_async(dispatch_get_main_queue(), ^{
+        [SVProgressHUD dismiss];
+    });
+});
+```
+
+**Swift:**
+
+```swift
+SVProgressHUD.show()
+DispatchQueue.global(qos: .default).async {
+    // time-consuming task
+    DispatchQueue.main.async {
+        SVProgressHUD.dismiss()
+    }
+}
+```
+
+### Showing the HUD
+
+You can show the status of indeterminate tasks using one of the following:
+
+```objective-c
++ (void)show;
++ (void)showWithStatus:(NSString*)string;
+```
+
+If you'd like the HUD to reflect the progress of a task, use one of these:
+
+```objective-c
++ (void)showProgress:(CGFloat)progress;
++ (void)showProgress:(CGFloat)progress status:(NSString*)status;
+```
+
+### Dismissing the HUD
+
+The HUD can be dismissed using:
+
+```objective-c
++ (void)dismiss;
++ (void)dismissWithDelay:(NSTimeInterval)delay;
+```
+
+If you'd like to stack HUDs, you can balance out every show call using:
+
+```
++ (void)popActivity;
+```
+
+The HUD will get dismissed once the `popActivity` calls will match the number of show calls.
+
+Or show an image with status before getting dismissed a little bit later. The display time depends on `minimumDismissTimeInterval` and the length of the given string.
+
+```objective-c
++ (void)showInfoWithStatus:(NSString*)string;
++ (void)showSuccessWithStatus:(NSString*)string;
++ (void)showErrorWithStatus:(NSString*)string;
++ (void)showImage:(UIImage*)image status:(NSString*)string;
+```
+
+## Customization
+
+`SVProgressHUD` is designed with flexibility in mind, providing a myriad of customization options to fit the look and feel of your application seamlessly.
+
+* Appearance: Make use of the `UI_APPEARANCE_SELECTOR` to adjust styles, colors, fonts, size, and images app-wide.
+* Behavior: Control visibility durations, display delays, and animation speeds.
+* Feedback: Enhance the user experience with options for haptic feedback and motion effects.
+
+For a comprehensive list of properties and detailed explanations, refer to the `SVProgressHUD.h` file in the API documentation.
+
+### Hint
+
+As standard `SVProgressHUD` offers three preconfigured styles:
+
+* `SVProgressHUDStyleAutomatic`: Automatically switch between the light and dark style
+* `SVProgressHUDStyleLight`: White background with black spinner and text
+* `SVProgressHUDStyleDark`: Black background with white spinner and text
+
+If you want to use custom colors use `setForegroundColor:` and/or `setBackgroundColor:`. These implicitly set the HUD's style to `SVProgressHUDStyleCustom`.
+
+## Haptic Feedback
+
+Available on iPhone 7 and newer, `SVProgressHUD` can automatically trigger haptic feedback depending on which HUD is being displayed. The feedback maps as follows:
+
+* `showSuccessWithStatus:` <-> `UINotificationFeedbackTypeSuccess`
+* `showInfoWithStatus:` <-> `UINotificationFeedbackTypeWarning`
+* `showErrorWithStatus:` <-> `UINotificationFeedbackTypeError`
+
+To enable this functionality, use `setHapticsEnabled:`.
+
+## Notifications
+
+`SVProgressHUD` posts four notifications via `NSNotificationCenter` in response to being shown/dismissed:
+
+* `SVProgressHUDWillAppearNotification` when the show animation starts
+* `SVProgressHUDDidAppearNotification` when the show animation completes
+* `SVProgressHUDWillDisappearNotification` when the dismiss animation starts
+* `SVProgressHUDDidDisappearNotification` when the dismiss animation completes
+
+Each notification passes a `userInfo` dictionary holding the HUD's status string (if any), retrievable via `SVProgressHUDStatusUserInfoKey`.
+
+`SVProgressHUD` also posts `SVProgressHUDDidReceiveTouchEventNotification` when users touch on the overall screen or `SVProgressHUDDidTouchDownInsideNotification` when a user touches on the HUD directly. For these notifications `userInfo` is not passed but the object parameter contains the `UIEvent` that related to the touch.
+
+## App Extensions
+
+When using `SVProgressHUD` in an App Extension, `#define SV_APP_EXTENSIONS` to avoid using unavailable APIs. This will be done automatically when using the `AppExtension` CocoaPods subspec. Additionally, call `setViewForExtension:` from your extensions view controller with `self.view`.
+
+## Contributing to this project
+
+If you have feature requests or bug reports, feel free to help out by sending pull requests or by [creating new issues](https://github.com/SVProgressHUD/SVProgressHUD/issues/new). Please take a moment to
+review the guidelines written by [Nicolas Gallagher](https://github.com/necolas):
+
+* [Bug reports](https://github.com/necolas/issue-guidelines/blob/master/CONTRIBUTING.md#bugs)
+* [Feature requests](https://github.com/necolas/issue-guidelines/blob/master/CONTRIBUTING.md#features)
+* [Pull requests](https://github.com/necolas/issue-guidelines/blob/master/CONTRIBUTING.md#pull-requests)
+
+## License
+
+`SVProgressHUD` is distributed under the terms and conditions of the [MIT license](https://github.com/SVProgressHUD/SVProgressHUD/blob/master/LICENSE). The success, error and info icons used on iOS 12 are made by [Freepik](http://www.freepik.com) from [Flaticon](https://www.flaticon.com) and are licensed under [Creative Commons BY 3.0](https://creativecommons.org/licenses/by/3.0/).
+
+## Privacy
+
+`SVProgressHUD` does not collect any data. A [privacy manifest file](https://developer.apple.com/documentation/bundleresources/privacy_manifest_files) is [provided](SVProgressHUD/PrivacyInfo.xcprivacy).
+
+## Credits
+
+`SVProgressHUD` is brought to you by Sam Vermette, [Tobias Totzek](https://totzek.me) and [contributors to the project](https://github.com/SVProgressHUD/SVProgressHUD/contributors). If you're using `SVProgressHUD` in your project, attribution would be very appreciated.

+ 14 - 0
Example/Pods/SVProgressHUD/SVProgressHUD/PrivacyInfo.xcprivacy

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>NSPrivacyTracking</key>
+	<false/>
+	<key>NSPrivacyCollectedDataTypes</key>
+	<array/>
+	<key>NSPrivacyTrackingDomains</key>
+	<array/>
+	<key>NSPrivacyAccessedAPITypes</key>
+	<array/>
+</dict>
+</plist>

+ 17 - 0
Example/Pods/SVProgressHUD/SVProgressHUD/SVIndefiniteAnimatedView.h

@@ -0,0 +1,17 @@
+//
+//  SVIndefiniteAnimatedView.h
+//  SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD
+//
+//  Copyright (c) 2014-2023 Guillaume Campagna and contributors. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface SVIndefiniteAnimatedView : UIView
+
+@property (nonatomic, assign) CGFloat strokeThickness;
+@property (nonatomic, assign) CGFloat radius;
+@property (nonatomic, strong) UIColor *strokeColor;
+
+@end
+

+ 142 - 0
Example/Pods/SVProgressHUD/SVProgressHUD/SVIndefiniteAnimatedView.m

@@ -0,0 +1,142 @@
+//
+//  SVIndefiniteAnimatedView.m
+//  SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD
+//
+//  Copyright (c) 2014-2023 Guillaume Campagna and contributors. All rights reserved.
+//
+
+#import "SVIndefiniteAnimatedView.h"
+#import "SVProgressHUD.h"
+
+@interface SVIndefiniteAnimatedView ()
+
+@property (nonatomic, strong) CAShapeLayer *indefiniteAnimatedLayer;
+
+@end
+
+@implementation SVIndefiniteAnimatedView
+
+- (void)willMoveToSuperview:(UIView*)newSuperview {
+    if (newSuperview) {
+        [self layoutAnimatedLayer];
+    } else {
+        [_indefiniteAnimatedLayer removeFromSuperlayer];
+        _indefiniteAnimatedLayer = nil;
+    }
+}
+
+- (void)layoutSubviews {
+    [super layoutSubviews];
+
+    [self layoutAnimatedLayer];
+}
+
+- (void)layoutAnimatedLayer {
+    CALayer *layer = self.indefiniteAnimatedLayer;
+
+    if (!layer.superlayer) {
+        [self.layer addSublayer:layer];
+    }
+    
+    CGFloat widthDiff = CGRectGetWidth(self.bounds) - CGRectGetWidth(layer.bounds);
+    CGFloat heightDiff = CGRectGetHeight(self.bounds) - CGRectGetHeight(layer.bounds);
+    layer.position = CGPointMake(CGRectGetWidth(self.bounds) - CGRectGetWidth(layer.bounds) / 2 - widthDiff / 2, CGRectGetHeight(self.bounds) - CGRectGetHeight(layer.bounds) / 2 - heightDiff / 2);
+}
+
+- (CAShapeLayer*)indefiniteAnimatedLayer {
+    if(!_indefiniteAnimatedLayer) {
+        CGPoint arcCenter = CGPointMake(self.radius+self.strokeThickness/2+5, self.radius+self.strokeThickness/2+5);
+        UIBezierPath* smoothedPath = [UIBezierPath bezierPathWithArcCenter:arcCenter radius:self.radius startAngle:(CGFloat) (M_PI*3/2) endAngle:(CGFloat) (M_PI/2+M_PI*5) clockwise:YES];
+        
+        _indefiniteAnimatedLayer = [CAShapeLayer layer];
+        _indefiniteAnimatedLayer.contentsScale = [[UIScreen mainScreen] scale];
+        _indefiniteAnimatedLayer.frame = CGRectMake(0.0f, 0.0f, arcCenter.x*2, arcCenter.y*2);
+        _indefiniteAnimatedLayer.fillColor = [UIColor clearColor].CGColor;
+        _indefiniteAnimatedLayer.strokeColor = self.strokeColor.CGColor;
+        _indefiniteAnimatedLayer.lineWidth = self.strokeThickness;
+        _indefiniteAnimatedLayer.lineCap = kCALineCapRound;
+        _indefiniteAnimatedLayer.lineJoin = kCALineJoinBevel;
+        _indefiniteAnimatedLayer.path = smoothedPath.CGPath;
+        
+        CALayer *maskLayer = [CALayer layer];
+        
+        NSBundle *imageBundle = [SVProgressHUD imageBundle];
+        
+        maskLayer.contents = (__bridge id)[[UIImage imageNamed:@"angle-mask.png" inBundle:imageBundle compatibleWithTraitCollection:nil] CGImage];
+        maskLayer.frame = _indefiniteAnimatedLayer.bounds;
+        _indefiniteAnimatedLayer.mask = maskLayer;
+        
+        NSTimeInterval animationDuration = 1;
+        CAMediaTimingFunction *linearCurve = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
+        
+        CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
+        animation.fromValue = (id) 0;
+        animation.toValue = @(M_PI*2);
+        animation.duration = animationDuration;
+        animation.timingFunction = linearCurve;
+        animation.removedOnCompletion = NO;
+        animation.repeatCount = INFINITY;
+        animation.fillMode = kCAFillModeForwards;
+        animation.autoreverses = NO;
+        [_indefiniteAnimatedLayer.mask addAnimation:animation forKey:@"rotate"];
+        
+        CAAnimationGroup *animationGroup = [CAAnimationGroup animation];
+        animationGroup.duration = animationDuration;
+        animationGroup.repeatCount = INFINITY;
+        animationGroup.removedOnCompletion = NO;
+        animationGroup.timingFunction = linearCurve;
+        
+        CABasicAnimation *strokeStartAnimation = [CABasicAnimation animationWithKeyPath:@"strokeStart"];
+        strokeStartAnimation.fromValue = @0.015;
+        strokeStartAnimation.toValue = @0.515;
+        
+        CABasicAnimation *strokeEndAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
+        strokeEndAnimation.fromValue = @0.485;
+        strokeEndAnimation.toValue = @0.985;
+        
+        animationGroup.animations = @[strokeStartAnimation, strokeEndAnimation];
+        [_indefiniteAnimatedLayer addAnimation:animationGroup forKey:@"progress"];
+        
+    }
+    return _indefiniteAnimatedLayer;
+}
+
+- (void)setFrame:(CGRect)frame {
+    if(!CGRectEqualToRect(frame, super.frame)) {
+        [super setFrame:frame];
+        
+        if(self.superview) {
+            [self layoutAnimatedLayer];
+        }
+    }
+    
+}
+
+- (void)setRadius:(CGFloat)radius {
+    if(radius != _radius) {
+        _radius = radius;
+        
+        [_indefiniteAnimatedLayer removeFromSuperlayer];
+        _indefiniteAnimatedLayer = nil;
+        
+        if(self.superview) {
+            [self layoutAnimatedLayer];
+        }
+    }
+}
+
+- (void)setStrokeColor:(UIColor*)strokeColor {
+    _strokeColor = strokeColor;
+    _indefiniteAnimatedLayer.strokeColor = strokeColor.CGColor;
+}
+
+- (void)setStrokeThickness:(CGFloat)strokeThickness {
+    _strokeThickness = strokeThickness;
+    _indefiniteAnimatedLayer.lineWidth = _strokeThickness;
+}
+
+- (CGSize)sizeThatFits:(CGSize)size {
+    return CGSizeMake((self.radius+self.strokeThickness/2+5)*2, (self.radius+self.strokeThickness/2+5)*2);
+}
+
+@end

+ 17 - 0
Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressAnimatedView.h

@@ -0,0 +1,17 @@
+//
+//  SVProgressAnimatedView.h
+//  SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD
+//
+//  Copyright (c) 2017-2023 Tobias Totzek and contributors. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface SVProgressAnimatedView : UIView
+
+@property (nonatomic, assign) CGFloat radius;
+@property (nonatomic, assign) CGFloat strokeThickness;
+@property (nonatomic, strong) UIColor *strokeColor;
+@property (nonatomic, assign) CGFloat strokeEnd;
+
+@end

+ 96 - 0
Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressAnimatedView.m

@@ -0,0 +1,96 @@
+//
+//  SVProgressAnimatedView.m
+//  SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD
+//
+//  Copyright (c) 2017-2023 Tobias Totzek and contributors. All rights reserved.
+//
+
+#import "SVProgressAnimatedView.h"
+
+@interface SVProgressAnimatedView ()
+
+@property (nonatomic, strong) CAShapeLayer *ringAnimatedLayer;
+
+@end
+
+@implementation SVProgressAnimatedView
+
+- (void)willMoveToSuperview:(UIView*)newSuperview {
+    if (newSuperview) {
+        [self layoutAnimatedLayer];
+    } else {
+        [_ringAnimatedLayer removeFromSuperlayer];
+        _ringAnimatedLayer = nil;
+    }
+}
+
+- (void)layoutAnimatedLayer {
+    CALayer *layer = self.ringAnimatedLayer;
+    [self.layer addSublayer:layer];
+    
+    CGFloat widthDiff = CGRectGetWidth(self.bounds) - CGRectGetWidth(layer.bounds);
+    CGFloat heightDiff = CGRectGetHeight(self.bounds) - CGRectGetHeight(layer.bounds);
+    layer.position = CGPointMake(CGRectGetWidth(self.bounds) - CGRectGetWidth(layer.bounds) / 2 - widthDiff / 2, CGRectGetHeight(self.bounds) - CGRectGetHeight(layer.bounds) / 2 - heightDiff / 2);
+}
+
+- (CAShapeLayer*)ringAnimatedLayer {
+    if(!_ringAnimatedLayer) {
+        CGPoint arcCenter = CGPointMake(self.radius+self.strokeThickness/2+5, self.radius+self.strokeThickness/2+5);
+        UIBezierPath* smoothedPath = [UIBezierPath bezierPathWithArcCenter:arcCenter radius:self.radius startAngle:(CGFloat)-M_PI_2 endAngle:(CGFloat) (M_PI + M_PI_2) clockwise:YES];
+        
+        _ringAnimatedLayer = [CAShapeLayer layer];
+        _ringAnimatedLayer.contentsScale = [[UIScreen mainScreen] scale];
+        _ringAnimatedLayer.frame = CGRectMake(0.0f, 0.0f, arcCenter.x*2, arcCenter.y*2);
+        _ringAnimatedLayer.fillColor = [UIColor clearColor].CGColor;
+        _ringAnimatedLayer.strokeColor = self.strokeColor.CGColor;
+        _ringAnimatedLayer.lineWidth = self.strokeThickness;
+        _ringAnimatedLayer.lineCap = kCALineCapRound;
+        _ringAnimatedLayer.lineJoin = kCALineJoinBevel;
+        _ringAnimatedLayer.path = smoothedPath.CGPath;
+    }
+    return _ringAnimatedLayer;
+}
+
+- (void)setFrame:(CGRect)frame {
+    if(!CGRectEqualToRect(frame, super.frame)) {
+        [super setFrame:frame];
+        
+        if(self.superview) {
+            [self layoutAnimatedLayer];
+        }
+    }
+}
+
+- (void)setRadius:(CGFloat)radius {
+    if(radius != _radius) {
+        _radius = radius;
+        
+        [_ringAnimatedLayer removeFromSuperlayer];
+        _ringAnimatedLayer = nil;
+        
+        if(self.superview) {
+            [self layoutAnimatedLayer];
+        }
+    }
+}
+
+- (void)setStrokeColor:(UIColor*)strokeColor {
+    _strokeColor = strokeColor;
+    _ringAnimatedLayer.strokeColor = strokeColor.CGColor;
+}
+
+- (void)setStrokeThickness:(CGFloat)strokeThickness {
+    _strokeThickness = strokeThickness;
+    _ringAnimatedLayer.lineWidth = _strokeThickness;
+}
+
+- (void)setStrokeEnd:(CGFloat)strokeEnd {
+    _strokeEnd = strokeEnd;
+    _ringAnimatedLayer.strokeEnd = _strokeEnd;
+}
+
+- (CGSize)sizeThatFits:(CGSize)size {
+    return CGSizeMake((self.radius+self.strokeThickness/2+5)*2, (self.radius+self.strokeThickness/2+5)*2);
+}
+
+@end

BIN
Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/angle-mask.png


BIN
Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/angle-mask@2x.png


BIN
Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/angle-mask@3x.png


BIN
Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/error.png


BIN
Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/error@2x.png


BIN
Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/error@3x.png


BIN
Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/info.png


BIN
Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/info@2x.png


BIN
Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/info@3x.png


BIN
Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/success.png


BIN
Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/success@2x.png


BIN
Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.bundle/success@3x.png


+ 392 - 0
Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.h

@@ -0,0 +1,392 @@
+//
+//  SVProgressHUD.h
+//  SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD
+//
+//  Copyright (c) 2011-2023 Sam Vermette and contributors. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+#import <AvailabilityMacros.h>
+
+extern NSString * _Nonnull const SVProgressHUDDidReceiveTouchEventNotification;
+extern NSString * _Nonnull const SVProgressHUDDidTouchDownInsideNotification;
+extern NSString * _Nonnull const SVProgressHUDWillDisappearNotification;
+extern NSString * _Nonnull const SVProgressHUDDidDisappearNotification;
+extern NSString * _Nonnull const SVProgressHUDWillAppearNotification;
+extern NSString * _Nonnull const SVProgressHUDDidAppearNotification;
+
+extern NSString * _Nonnull const SVProgressHUDStatusUserInfoKey;
+
+/// Represents the appearance style of the HUD.
+typedef NS_ENUM(NSInteger, SVProgressHUDStyle) {
+    /// White HUD with black text. HUD background will be blurred.
+    SVProgressHUDStyleLight NS_SWIFT_NAME(light),
+    
+    /// Black HUD with white text. HUD background will be blurred.
+    SVProgressHUDStyleDark NS_SWIFT_NAME(dark),
+    
+    /// Uses the fore- and background color properties.
+    SVProgressHUDStyleCustom NS_SWIFT_NAME(custom),
+    
+    /// Automatically switch between light or dark mode appearance.
+    SVProgressHUDStyleAutomatic NS_SWIFT_NAME(automatic)
+};
+
+/// Represents the type of mask to be applied when the HUD is displayed.
+typedef NS_ENUM(NSUInteger, SVProgressHUDMaskType) {
+    /// Allow user interactions while HUD is displayed.
+    SVProgressHUDMaskTypeNone NS_SWIFT_NAME(none) = 1,
+    
+    /// Don't allow user interactions with background objects.
+    SVProgressHUDMaskTypeClear NS_SWIFT_NAME(clear),
+    
+    /// Don't allow user interactions and dim the UI behind the HUD (as in iOS 7+).
+    SVProgressHUDMaskTypeBlack NS_SWIFT_NAME(black),
+    
+    /// Don't allow user interactions and dim the UI with an UIAlertView-like background gradient (as in iOS 6).
+    SVProgressHUDMaskTypeGradient NS_SWIFT_NAME(gradient),
+    
+    /// Don't allow user interactions and dim the UI behind the HUD with a custom color.
+    SVProgressHUDMaskTypeCustom NS_SWIFT_NAME(custom)
+};
+
+/// Represents the animation type of the HUD when it's shown or hidden.
+typedef NS_ENUM(NSUInteger, SVProgressHUDAnimationType) {
+    /// Custom flat animation (indefinite animated ring).
+    SVProgressHUDAnimationTypeFlat NS_SWIFT_NAME(flat),
+    
+    /// iOS native UIActivityIndicatorView.
+    SVProgressHUDAnimationTypeNative NS_SWIFT_NAME(native)
+};
+
+typedef void (^SVProgressHUDShowCompletion)(void);
+typedef void (^SVProgressHUDDismissCompletion)(void);
+
+@interface SVProgressHUD : UIView
+
+#pragma mark - Customization
+
+/// Represents the default style for the HUD.
+/// @discussion Default: SVProgressHUDStyleAutomatic.
+@property (assign, nonatomic) SVProgressHUDStyle defaultStyle UI_APPEARANCE_SELECTOR;
+
+/// Represents the type of mask applied when the HUD is displayed.
+/// @discussion Default: SVProgressHUDMaskTypeNone.
+@property (assign, nonatomic) SVProgressHUDMaskType defaultMaskType UI_APPEARANCE_SELECTOR;
+
+/// Defines the animation type used when the HUD is displayed.
+/// @discussion Default: SVProgressHUDAnimationTypeFlat.
+@property (assign, nonatomic) SVProgressHUDAnimationType defaultAnimationType UI_APPEARANCE_SELECTOR;
+
+/// The container view used for displaying the HUD. If nil, the default window level is used.
+@property (strong, nonatomic, nullable) UIView *containerView;
+
+/// The minimum size for the HUD. Useful for maintaining a consistent size when the message might cause resizing.
+/// @discussion Default: CGSizeZero.
+@property (assign, nonatomic) CGSize minimumSize UI_APPEARANCE_SELECTOR;
+
+/// Thickness of the ring shown in the HUD.
+/// @discussion Default: 2 pt.
+@property (assign, nonatomic) CGFloat ringThickness UI_APPEARANCE_SELECTOR;
+
+/// Radius of the ring shown in the HUD when there's associated text.
+/// @discussion Default: 18 pt.
+@property (assign, nonatomic) CGFloat ringRadius UI_APPEARANCE_SELECTOR;
+
+/// Radius of the ring shown in the HUD when there's no associated text.
+/// @discussion Default: 24 pt.
+@property (assign, nonatomic) CGFloat ringNoTextRadius UI_APPEARANCE_SELECTOR;
+
+/// Corner radius of the HUD view.
+/// @discussion Default: 14 pt.
+@property (assign, nonatomic) CGFloat cornerRadius UI_APPEARANCE_SELECTOR;
+
+/// Font used for text within the HUD.
+/// @discussion Default: [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline].
+@property (strong, nonatomic, nonnull) UIFont *font UI_APPEARANCE_SELECTOR;
+
+/// Background color of the HUD.
+/// @discussion Default: [UIColor whiteColor].
+@property (strong, nonatomic, nonnull) UIColor *backgroundColor UI_APPEARANCE_SELECTOR;
+
+/// Foreground color used for content in the HUD.
+/// @discussion Default: [UIColor blackColor].
+@property (strong, nonatomic, nonnull) UIColor *foregroundColor UI_APPEARANCE_SELECTOR;
+
+/// Color for any foreground images in the HUD.
+/// @discussion Default: same as foregroundColor.
+@property (strong, nonatomic, nullable) UIColor *foregroundImageColor UI_APPEARANCE_SELECTOR;
+
+/// Color for the background layer behind the HUD.
+/// @discussion Default: [UIColor colorWithWhite:0 alpha:0.4].
+@property (strong, nonatomic, nonnull) UIColor *backgroundLayerColor UI_APPEARANCE_SELECTOR;
+
+/// Size of any images displayed within the HUD.
+/// @discussion Default: 28x28 pt.
+@property (assign, nonatomic) CGSize imageViewSize UI_APPEARANCE_SELECTOR;
+
+/// Indicates whether images within the HUD should be tinted.
+/// @discussion Default: YES.
+@property (assign, nonatomic) BOOL shouldTintImages UI_APPEARANCE_SELECTOR;
+
+/// The image displayed when showing informational messages.
+/// @discussion Default: info.circle from SF Symbols (iOS 13+) or the bundled info image provided by Freepik.
+@property (strong, nonatomic, nonnull) UIImage *infoImage UI_APPEARANCE_SELECTOR;
+
+/// The image displayed when showing success messages.
+/// @discussion Default: checkmark from SF Symbols (iOS 13+) or the bundled success image provided by Freepik.
+@property (strong, nonatomic, nonnull) UIImage *successImage UI_APPEARANCE_SELECTOR;
+
+/// The image displayed when showing error messages.
+/// @discussion Default: xmark from SF Symbols (iOS 13+) or the bundled error image provided by Freepik.
+@property (strong, nonatomic, nonnull) UIImage *errorImage UI_APPEARANCE_SELECTOR;
+
+/// A specific view for extensions. This property is only used if #define SV_APP_EXTENSIONS is set.
+/// @discussion Default: nil.
+@property (strong, nonatomic, nonnull) UIView *viewForExtension UI_APPEARANCE_SELECTOR;
+
+/// The interval in seconds to wait before displaying the HUD. If the HUD is displayed before this time elapses, this timer is reset.
+/// @discussion Default: 0 seconds.
+@property (assign, nonatomic) NSTimeInterval graceTimeInterval;
+
+/// The minimum amount of time in seconds the HUD will display.
+/// @discussion Default: 5.0 seconds.
+@property (assign, nonatomic) NSTimeInterval minimumDismissTimeInterval;
+
+/// The maximum amount of time in seconds the HUD will display.
+/// @discussion Default: CGFLOAT_MAX.
+@property (assign, nonatomic) NSTimeInterval maximumDismissTimeInterval;
+
+/// Offset from the center position, can be used to adjust the HUD position.
+/// @discussion Default: 0, 0.
+@property (assign, nonatomic) UIOffset offsetFromCenter UI_APPEARANCE_SELECTOR;
+
+/// Duration of the fade-in animation when showing the HUD.
+/// @discussion Default: 0.15.
+@property (assign, nonatomic) NSTimeInterval fadeInAnimationDuration UI_APPEARANCE_SELECTOR;
+
+/// Duration of the fade-out animation when hiding the HUD.
+/// @discussion Default: 0.15.
+@property (assign, nonatomic) NSTimeInterval fadeOutAnimationDuration UI_APPEARANCE_SELECTOR;
+
+/// The maximum window level on which the HUD can be displayed.
+/// @discussion Default: UIWindowLevelNormal.
+@property (assign, nonatomic) UIWindowLevel maxSupportedWindowLevel;
+
+/// Indicates if haptic feedback should be used.
+/// @discussion Default: NO.
+@property (assign, nonatomic) BOOL hapticsEnabled;
+
+/// Indicates if motion effects should be applied to the HUD.
+/// @discussion Default: YES.
+@property (assign, nonatomic) BOOL motionEffectEnabled;
+
+@property (class, strong, nonatomic, readonly, nonnull) NSBundle *imageBundle;
+
+/// Sets the default style for the HUD.
+/// @param style The desired style for the HUD.
++ (void)setDefaultStyle:(SVProgressHUDStyle)style;
+
+/// Sets the default mask type for the HUD.
+/// @param maskType The mask type to apply.
++ (void)setDefaultMaskType:(SVProgressHUDMaskType)maskType;
+
+/// Sets the default animation type for the HUD.
+/// @param type The desired animation type.
++ (void)setDefaultAnimationType:(SVProgressHUDAnimationType)type;
+
+/// Sets the container view for the HUD.
+/// @param containerView The view to contain the HUD.
++ (void)setContainerView:(nullable UIView*)containerView;
+
+/// Sets the minimum size for the HUD.
+/// @param minimumSize The minimum size for the HUD.
++ (void)setMinimumSize:(CGSize)minimumSize;
+
+/// Sets the ring thickness for the HUD.
+/// @param ringThickness Thickness of the ring.
++ (void)setRingThickness:(CGFloat)ringThickness;
+
+/// Sets the ring radius for the HUD.
+/// @param radius Radius of the ring.
++ (void)setRingRadius:(CGFloat)radius;
+
+/// Sets the no text ring radius for the HUD.
+/// @param radius Radius of the ring when no text is displayed.
++ (void)setRingNoTextRadius:(CGFloat)radius;
+
+/// Sets the corner radius for the HUD.
+/// @param cornerRadius Desired corner radius.
++ (void)setCornerRadius:(CGFloat)cornerRadius;
+
+/// Sets the border color for the HUD.
+/// @param color Desired border color.
++ (void)setBorderColor:(nonnull UIColor*)color;
+
+/// Sets the border width for the HUD.
+/// @param width Desired border width.
++ (void)setBorderWidth:(CGFloat)width;
+
+/// Sets the font for the HUD's text.
+/// @param font Desired font for the text.
++ (void)setFont:(nonnull UIFont*)font;
+
+/// Sets the foreground color for the HUD.
+/// @param color Desired foreground color.
+/// @discussion These implicitly set the HUD's style to `SVProgressHUDStyleCustom`.
++ (void)setForegroundColor:(nonnull UIColor*)color;
+
+/// Sets the foreground image color for the HUD.
+/// @param color Desired color for the image.
+/// @discussion These implicitly set the HUD's style to `SVProgressHUDStyleCustom`.
++ (void)setForegroundImageColor:(nullable UIColor*)color;
+
+/// Sets the background color for the HUD.
+/// @param color Desired background color.
+/// @discussion These implicitly set the HUD's style to `SVProgressHUDStyleCustom`.
++ (void)setBackgroundColor:(nonnull UIColor*)color;
+
+/// Sets a custom blur effect for the HUD view.
+/// @param blurEffect Desired blur effect.
+/// @discussion These implicitly set the HUD's style to `SVProgressHUDStyleCustom`.
++ (void)setHudViewCustomBlurEffect:(nullable UIBlurEffect*)blurEffect;
+
+/// Sets the background layer color for the HUD.
+/// @param color Desired color for the background layer.
++ (void)setBackgroundLayerColor:(nonnull UIColor*)color;
+
+/// Sets the size for the HUD's image view.
+/// @param size Desired size for the image view.
++ (void)setImageViewSize:(CGSize)size;
+
+/// Determines if images should be tinted in the HUD.
+/// @param shouldTintImages Whether images should be tinted.
++ (void)setShouldTintImages:(BOOL)shouldTintImages;
+
+/// Sets the info image for the HUD.
+/// @param image The desired info image.
++ (void)setInfoImage:(nonnull UIImage*)image;
+
+/// Sets the success image for the HUD.
+/// @param image The desired success image.
++ (void)setSuccessImage:(nonnull UIImage*)image;
+
+/// Sets the error image for the HUD.
+/// @param image The desired error image.
++ (void)setErrorImage:(nonnull UIImage*)image;
+
+/// Sets the view for extensions.
+/// @param view The desired view for extensions.
++ (void)setViewForExtension:(nonnull UIView*)view;
+
+/// Sets the grace time interval for the HUD.
+/// @param interval Desired grace time interval.
++ (void)setGraceTimeInterval:(NSTimeInterval)interval;
+
+/// Sets the minimum dismiss time interval.
+/// @param interval The minimum time interval, in seconds, that the HUD should be displayed.
++ (void)setMinimumDismissTimeInterval:(NSTimeInterval)interval;
+
+/// Sets the maximum dismiss time interval.
+/// @param interval The maximum time interval, in seconds, that the HUD should be displayed.
++ (void)setMaximumDismissTimeInterval:(NSTimeInterval)interval;
+
+/// Sets the fade-in animation duration.
+/// @param duration The duration, in seconds, for the fade-in animation.
++ (void)setFadeInAnimationDuration:(NSTimeInterval)duration;
+
+/// Sets the fade-out animation duration.
+/// @param duration The duration, in seconds, for the fade-out animation.
++ (void)setFadeOutAnimationDuration:(NSTimeInterval)duration;
+
+/// Sets the max supported window level.
+/// @param windowLevel The UIWindowLevel to which the HUD should be displayed.
++ (void)setMaxSupportedWindowLevel:(UIWindowLevel)windowLevel;
+
+/// Determines if haptics are enabled.
+/// @param hapticsEnabled A boolean that determines if haptic feedback is enabled.
++ (void)setHapticsEnabled:(BOOL)hapticsEnabled;
+
+/// Determines if motion effect is enabled.
+/// @param motionEffectEnabled A boolean that determines if motion effects are enabled.
++ (void)setMotionEffectEnabled:(BOOL)motionEffectEnabled;
+
+
+#pragma mark - Show Methods
+
+/// Shows the HUD without any additional status message.
++ (void)show;
+
+/// Shows the HUD with a provided status message.
+/// @param status The message to be displayed alongside the HUD.
++ (void)showWithStatus:(nullable NSString*)status;
+
+/// Display methods to show progress on the HUD.
+
+/// Shows the HUD with a progress indicator.
+/// @param progress A float value between 0.0 and 1.0 indicating the progress.
++ (void)showProgress:(float)progress;
+
+/// Shows the HUD with a progress indicator and a provided status message.
+/// @param progress A float value between 0.0 and 1.0 indicating the progress.
+/// @param status The message to be displayed alongside the progress indicator.
++ (void)showProgress:(float)progress status:(nullable NSString*)status;
+
+/// Updates the current status of the loading HUD.
+/// @param status The new status message to update the HUD with.
++ (void)setStatus:(nullable NSString*)status;
+
+/// Shows an info status with the provided message.
+/// @param status The info message to be displayed.
++ (void)showInfoWithStatus:(nullable NSString*)status;
+
+/// Shows a success status with the provided message.
+/// @param status The success message to be displayed.
++ (void)showSuccessWithStatus:(nullable NSString*)status;
+
+/// Shows an error status with the provided message.
+/// @param status The error message to be displayed.
++ (void)showErrorWithStatus:(nullable NSString*)status;
+
+/// Shows a custom image with the provided status message.
+/// @param image The custom image to be displayed.
+/// @param status The message to accompany the custom image.
++ (void)showImage:(nonnull UIImage*)image status:(nullable NSString*)status;
+
+/// Sets the offset from the center for the HUD.
+/// @param offset The UIOffset value indicating how much the HUD should be offset from its center position.
++ (void)setOffsetFromCenter:(UIOffset)offset;
+
+/// Resets the offset to center the HUD.
++ (void)resetOffsetFromCenter;
+
+/// Decreases the activity count, dismissing the HUD if count reaches 0.
++ (void)popActivity;
+
+/// Dismisses the HUD immediately.
++ (void)dismiss;
+
+/// Dismisses the HUD and triggers a completion block.
+/// @param completion A block that gets executed after the HUD is dismissed.
++ (void)dismissWithCompletion:(nullable SVProgressHUDDismissCompletion)completion;
+
+/// Dismisses the HUD after a specified delay.
+/// @param delay The time in seconds after which the HUD should be dismissed.
++ (void)dismissWithDelay:(NSTimeInterval)delay;
+
+/// Dismisses the HUD after a specified delay and triggers a completion block.
+/// @param delay The time in seconds after which the HUD should be dismissed.
+/// @param completion A block that gets executed after the HUD is dismissed.
++ (void)dismissWithDelay:(NSTimeInterval)delay completion:(nullable SVProgressHUDDismissCompletion)completion;
+
+/// Checks if the HUD is currently visible.
+/// @return A boolean value indicating whether the HUD is visible.
++ (BOOL)isVisible;
+
+/// Calculates the display duration based on a given string's length.
+/// @param string The string whose length determines the display duration.
+/// @return A time interval representing the display duration.
++ (NSTimeInterval)displayDurationForString:(nullable NSString*)string;
+
+@end
+

+ 1524 - 0
Example/Pods/SVProgressHUD/SVProgressHUD/SVProgressHUD.m

@@ -0,0 +1,1524 @@
+//
+//  SVProgressHUD.h
+//  SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD
+//
+//  Copyright (c) 2011-2023 Sam Vermette and contributors. All rights reserved.
+//
+
+#if !__has_feature(objc_arc)
+#error SVProgressHUD is ARC only. Either turn on ARC for the project or use -fobjc-arc flag
+#endif
+
+#import "SVProgressHUD.h"
+#import "SVIndefiniteAnimatedView.h"
+#import "SVProgressAnimatedView.h"
+#import "SVRadialGradientLayer.h"
+
+NSString * const SVProgressHUDDidReceiveTouchEventNotification = @"SVProgressHUDDidReceiveTouchEventNotification";
+NSString * const SVProgressHUDDidTouchDownInsideNotification = @"SVProgressHUDDidTouchDownInsideNotification";
+NSString * const SVProgressHUDWillDisappearNotification = @"SVProgressHUDWillDisappearNotification";
+NSString * const SVProgressHUDDidDisappearNotification = @"SVProgressHUDDidDisappearNotification";
+NSString * const SVProgressHUDWillAppearNotification = @"SVProgressHUDWillAppearNotification";
+NSString * const SVProgressHUDDidAppearNotification = @"SVProgressHUDDidAppearNotification";
+
+NSString * const SVProgressHUDStatusUserInfoKey = @"SVProgressHUDStatusUserInfoKey";
+
+static const CGFloat SVProgressHUDParallaxDepthPoints = 10.0f;
+static const CGFloat SVProgressHUDUndefinedProgress = -1;
+static const CGFloat SVProgressHUDDefaultAnimationDuration = 0.15f;
+static const CGFloat SVProgressHUDVerticalSpacing = 12.0f;
+static const CGFloat SVProgressHUDHorizontalSpacing = 12.0f;
+static const CGFloat SVProgressHUDLabelSpacing = 8.0f;
+
+
+@interface SVProgressHUD ()
+
+@property (nonatomic, strong) NSTimer *graceTimer;
+@property (nonatomic, strong) NSTimer *fadeOutTimer;
+
+@property (nonatomic, strong) UIControl *controlView;
+@property (nonatomic, strong) UIView *backgroundView;
+@property (nonatomic, strong) SVRadialGradientLayer *backgroundRadialGradientLayer;
+@property (nonatomic, strong) UIVisualEffectView *hudView;
+@property (nonatomic, strong) UIBlurEffect *hudViewCustomBlurEffect;
+@property (nonatomic, strong) UILabel *statusLabel;
+@property (nonatomic, strong) UIImageView *imageView;
+
+@property (nonatomic, strong) UIView *indefiniteAnimatedView;
+@property (nonatomic, strong) SVProgressAnimatedView *ringView;
+@property (nonatomic, strong) SVProgressAnimatedView *backgroundRingView;
+
+@property (nonatomic, readwrite) CGFloat progress;
+@property (nonatomic, readwrite) NSUInteger activityCount;
+
+@property (nonatomic, readonly) CGFloat visibleKeyboardHeight;
+@property (nonatomic, readonly) UIWindow *frontWindow;
+
+#if TARGET_OS_IOS
+@property (nonatomic, strong) UINotificationFeedbackGenerator *hapticGenerator;
+#endif
+
+@end
+
+@implementation SVProgressHUD {
+    BOOL _isInitializing;
+}
+
++ (SVProgressHUD*)sharedView {
+    static dispatch_once_t once;
+    
+    static SVProgressHUD *sharedView;
+#if !defined(SV_APP_EXTENSIONS)
+     dispatch_once(&once, ^{ sharedView = [[self alloc] initWithFrame:[SVProgressHUD mainWindow].bounds]; });
+#else
+    dispatch_once(&once, ^{ sharedView = [[self alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; });
+#endif
+    return sharedView;
+}
+
++ (UIWindow *)mainWindow {
+    if (@available(iOS 13.0, *)) {
+        for (UIWindowScene* windowScene in [UIApplication sharedApplication].connectedScenes) {
+            if (windowScene.activationState == UISceneActivationStateForegroundActive) {
+                return windowScene.windows.firstObject;
+            }
+        }
+        // If a window has not been returned by now, the first scene's window is returned (regardless of activationState).
+        UIWindowScene *windowScene = (UIWindowScene *)[[UIApplication sharedApplication].connectedScenes allObjects].firstObject;
+        return windowScene.windows.firstObject;
+    } else {
+#if TARGET_OS_IOS
+        return [[[UIApplication sharedApplication] delegate] window];
+#else
+        return [UIApplication sharedApplication].keyWindow;
+#endif
+    }
+}
+
++ (NSBundle *)imageBundle {
+#if defined(SWIFTPM_MODULE_BUNDLE)
+     NSBundle *bundle = SWIFTPM_MODULE_BUNDLE;
+#else
+     NSBundle *bundle = [NSBundle bundleForClass:[SVProgressHUD class]];
+#endif
+     NSURL *url = [bundle URLForResource:@"SVProgressHUD" withExtension:@"bundle"];
+     return [NSBundle bundleWithURL:url];
+ }
+
+#pragma mark - Setters
+
++ (void)setStatus:(NSString*)status {
+    [[self sharedView] setStatus:status];
+}
+
++ (void)setDefaultStyle:(SVProgressHUDStyle)style {
+    [self sharedView].defaultStyle = style;
+}
+
++ (void)setDefaultMaskType:(SVProgressHUDMaskType)maskType {
+    [self sharedView].defaultMaskType = maskType;
+}
+
++ (void)setDefaultAnimationType:(SVProgressHUDAnimationType)type {
+    [self sharedView].defaultAnimationType = type;
+}
+
++ (void)setContainerView:(nullable UIView*)containerView {
+    [self sharedView].containerView = containerView;
+}
+
++ (void)setMinimumSize:(CGSize)minimumSize {
+    [self sharedView].minimumSize = minimumSize;
+}
+
++ (void)setRingThickness:(CGFloat)ringThickness {
+    [self sharedView].ringThickness = ringThickness;
+}
+
++ (void)setRingRadius:(CGFloat)radius {
+    [self sharedView].ringRadius = radius;
+}
+
++ (void)setRingNoTextRadius:(CGFloat)radius {
+    [self sharedView].ringNoTextRadius = radius;
+}
+
++ (void)setCornerRadius:(CGFloat)cornerRadius {
+    [self sharedView].cornerRadius = cornerRadius;
+}
+
++ (void)setBorderColor:(nonnull UIColor*)color {
+    [self sharedView].hudView.layer.borderColor = color.CGColor;
+}
+
++ (void)setBorderWidth:(CGFloat)width {
+    [self sharedView].hudView.layer.borderWidth = width;
+}
+
++ (void)setFont:(UIFont*)font {
+    [self sharedView].font = font;
+}
+
++ (void)setForegroundColor:(UIColor*)color {
+    [self sharedView].foregroundColor = color;
+    [self setDefaultStyle:SVProgressHUDStyleCustom];
+}
+
++ (void)setForegroundImageColor:(UIColor *)color {
+    [self sharedView].foregroundImageColor = color;
+    [self setDefaultStyle:SVProgressHUDStyleCustom];
+}
+
++ (void)setBackgroundColor:(UIColor*)color {
+    [self sharedView].backgroundColor = color;
+    [self setDefaultStyle:SVProgressHUDStyleCustom];
+}
+
++ (void)setHudViewCustomBlurEffect:(UIBlurEffect*)blurEffect {
+    [self sharedView].hudViewCustomBlurEffect = blurEffect;
+    [self setDefaultStyle:SVProgressHUDStyleCustom];
+}
+
++ (void)setBackgroundLayerColor:(UIColor*)color {
+    [self sharedView].backgroundLayerColor = color;
+}
+
++ (void)setImageViewSize:(CGSize)size {
+    [self sharedView].imageViewSize = size;
+}
+
++ (void)setShouldTintImages:(BOOL)shouldTintImages {
+    [self sharedView].shouldTintImages = shouldTintImages;
+}
+
++ (void)setInfoImage:(UIImage*)image {
+    [self sharedView].infoImage = image;
+}
+
++ (void)setSuccessImage:(UIImage*)image {
+    [self sharedView].successImage = image;
+}
+
++ (void)setErrorImage:(UIImage*)image {
+    [self sharedView].errorImage = image;
+}
+
++ (void)setViewForExtension:(UIView*)view {
+    [self sharedView].viewForExtension = view;
+}
+
++ (void)setGraceTimeInterval:(NSTimeInterval)interval {
+    [self sharedView].graceTimeInterval = interval;
+}
+
++ (void)setMinimumDismissTimeInterval:(NSTimeInterval)interval {
+    [self sharedView].minimumDismissTimeInterval = interval;
+}
+
++ (void)setMaximumDismissTimeInterval:(NSTimeInterval)interval {
+    [self sharedView].maximumDismissTimeInterval = interval;
+}
+
++ (void)setFadeInAnimationDuration:(NSTimeInterval)duration {
+    [self sharedView].fadeInAnimationDuration = duration;
+}
+
++ (void)setFadeOutAnimationDuration:(NSTimeInterval)duration {
+    [self sharedView].fadeOutAnimationDuration = duration;
+}
+
++ (void)setMaxSupportedWindowLevel:(UIWindowLevel)windowLevel {
+    [self sharedView].maxSupportedWindowLevel = windowLevel;
+}
+
++ (void)setHapticsEnabled:(BOOL)hapticsEnabled {
+    [self sharedView].hapticsEnabled = hapticsEnabled;
+}
+
++ (void)setMotionEffectEnabled:(BOOL)motionEffectEnabled {
+    [self sharedView].motionEffectEnabled = motionEffectEnabled;
+}
+
+#pragma mark - Show Methods
+
++ (void)show {
+    [self showWithStatus:nil];
+}
+
++ (void)showWithStatus:(NSString*)status {
+    [self showProgress:SVProgressHUDUndefinedProgress status:status];
+}
+
++ (void)showProgress:(float)progress {
+    [self showProgress:progress status:nil];
+}
+
++ (void)showProgress:(float)progress status:(NSString*)status {
+    [[self sharedView] showProgress:progress status:status];
+}
+
+
+#pragma mark - Show, then automatically dismiss methods
+
++ (void)showInfoWithStatus:(NSString*)status {
+    [self showImage:[self sharedView].infoImage status:status];
+    
+#if TARGET_OS_IOS
+    dispatch_async(dispatch_get_main_queue(), ^{
+        [[self sharedView].hapticGenerator notificationOccurred:UINotificationFeedbackTypeWarning];
+    });
+#endif
+}
+
++ (void)showSuccessWithStatus:(NSString*)status {
+    [self showImage:[self sharedView].successImage status:status];
+
+#if TARGET_OS_IOS
+    dispatch_async(dispatch_get_main_queue(), ^{
+        [[self sharedView].hapticGenerator notificationOccurred:UINotificationFeedbackTypeSuccess];
+    });
+#endif
+}
+
++ (void)showErrorWithStatus:(NSString*)status {
+    [self showImage:[self sharedView].errorImage status:status];
+    
+#if TARGET_OS_IOS
+    dispatch_async(dispatch_get_main_queue(), ^{
+        [[self sharedView].hapticGenerator notificationOccurred:UINotificationFeedbackTypeError];
+    });
+#endif
+}
+
++ (void)showImage:(UIImage*)image status:(NSString*)status {
+    NSTimeInterval displayInterval = [self displayDurationForString:status];
+    [[self sharedView] showImage:image status:status duration:displayInterval];
+}
+
+
+#pragma mark - Dismiss Methods
+
++ (void)popActivity {
+    if([self sharedView].activityCount > 0) {
+        [self sharedView].activityCount--;
+    }
+    if([self sharedView].activityCount == 0) {
+        [[self sharedView] dismiss];
+    }
+}
+
++ (void)dismiss {
+    [self dismissWithDelay:0.0 completion:nil];
+}
+
++ (void)dismissWithCompletion:(SVProgressHUDDismissCompletion)completion {
+    [self dismissWithDelay:0.0 completion:completion];
+}
+
++ (void)dismissWithDelay:(NSTimeInterval)delay {
+    [self dismissWithDelay:delay completion:nil];
+}
+
++ (void)dismissWithDelay:(NSTimeInterval)delay completion:(SVProgressHUDDismissCompletion)completion {
+    [[self sharedView] dismissWithDelay:delay completion:completion];
+}
+
+
+#pragma mark - Offset
+
++ (void)setOffsetFromCenter:(UIOffset)offset {
+    [self sharedView].offsetFromCenter = offset;
+}
+
++ (void)resetOffsetFromCenter {
+    [self setOffsetFromCenter:UIOffsetZero];
+}
+
+
+#pragma mark - Instance Methods
+
+- (instancetype)initWithFrame:(CGRect)frame {
+    if((self = [super initWithFrame:frame])) {
+        _isInitializing = YES;
+        
+        self.userInteractionEnabled = NO;
+        self.activityCount = 0;
+        
+        self.backgroundView.alpha = 0.0f;
+        self.imageView.alpha = 0.0f;
+        self.statusLabel.alpha = 0.0f;
+        self.indefiniteAnimatedView.alpha = 0.0f;
+        self.ringView.alpha = self.backgroundRingView.alpha = 0.0f;
+        
+
+        _backgroundColor = [UIColor whiteColor];
+        _foregroundColor = [UIColor blackColor];
+        _backgroundLayerColor = [UIColor colorWithWhite:0 alpha:0.4];
+        
+        // Set default values
+        _defaultMaskType = SVProgressHUDMaskTypeNone;
+        _defaultStyle = SVProgressHUDStyleAutomatic;
+        _defaultAnimationType = SVProgressHUDAnimationTypeFlat;
+        _minimumSize = CGSizeZero;
+        _font = [UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline];
+        
+        _imageViewSize = CGSizeMake(28.0f, 28.0f);
+        _shouldTintImages = YES;
+        
+        NSBundle *imageBundle = [SVProgressHUD imageBundle];
+        
+        if (@available(iOS 13.0, *)) {
+            _infoImage = [UIImage systemImageNamed:@"info.circle"];
+            _successImage = [UIImage systemImageNamed:@"checkmark"];
+            _errorImage = [UIImage systemImageNamed:@"xmark"];
+        } else {
+            _infoImage = [UIImage imageWithContentsOfFile:[imageBundle pathForResource:@"info" ofType:@"png"]];
+            _successImage = [UIImage imageWithContentsOfFile:[imageBundle pathForResource:@"success" ofType:@"png"]];
+            _errorImage = [UIImage imageWithContentsOfFile:[imageBundle pathForResource:@"error" ofType:@"png"]];
+        }
+        
+        _ringThickness = 2.0f;
+        _ringRadius = 18.0f;
+        _ringNoTextRadius = 24.0f;
+        
+        _cornerRadius = 14.0f;
+		
+        _graceTimeInterval = 0.0f;
+        _minimumDismissTimeInterval = 5.0;
+        _maximumDismissTimeInterval = CGFLOAT_MAX;
+
+        _fadeInAnimationDuration = SVProgressHUDDefaultAnimationDuration;
+        _fadeOutAnimationDuration = SVProgressHUDDefaultAnimationDuration;
+        
+        _maxSupportedWindowLevel = UIWindowLevelNormal;
+        
+        _hapticsEnabled = NO;
+        _motionEffectEnabled = YES;
+        
+        // Accessibility support
+        self.accessibilityIdentifier = @"SVProgressHUD";
+        self.isAccessibilityElement = YES;
+        
+        _isInitializing = NO;
+    }
+    return self;
+}
+
+- (void)updateHUDFrame {
+    // Check if an image or progress ring is displayed
+    BOOL imageUsed = (self.imageView.image) && !(self.imageView.hidden) && (self.imageViewSize.height > 0 && self.imageViewSize.width > 0);
+    BOOL progressUsed = self.imageView.hidden;
+    
+    // Calculate size of string
+    CGRect labelRect = CGRectZero;
+    CGFloat labelHeight = 0.0f;
+    CGFloat labelWidth = 0.0f;
+    
+    if(self.statusLabel.text) {
+        CGSize constraintSize = CGSizeMake(200.0f, 300.0f);
+        labelRect = [self.statusLabel.text boundingRectWithSize:constraintSize
+                                                        options:(NSStringDrawingOptions)(NSStringDrawingUsesFontLeading | NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin)
+                                                     attributes:@{NSFontAttributeName: self.statusLabel.font}
+                                                        context:NULL];
+        labelHeight = ceilf(CGRectGetHeight(labelRect));
+        labelWidth = ceilf(CGRectGetWidth(labelRect));
+    }
+    
+    // Calculate hud size based on content
+    // For the beginning use default values, these
+    // might get update if string is too large etc.
+    CGFloat hudWidth;
+    CGFloat hudHeight;
+    
+    CGFloat contentWidth = 0.0f;
+    CGFloat contentHeight = 0.0f;
+    
+    if(imageUsed || progressUsed) {
+        contentWidth = CGRectGetWidth(imageUsed ? self.imageView.frame : self.indefiniteAnimatedView.frame);
+        contentHeight = CGRectGetHeight(imageUsed ? self.imageView.frame : self.indefiniteAnimatedView.frame);
+    }
+    
+    // |-spacing-content-spacing-|
+    hudWidth = SVProgressHUDHorizontalSpacing + MAX(labelWidth, contentWidth) + SVProgressHUDHorizontalSpacing;
+    
+    // |-spacing-content-(labelSpacing-label-)spacing-|
+    hudHeight = SVProgressHUDVerticalSpacing + labelHeight + contentHeight + SVProgressHUDVerticalSpacing;
+    if(self.statusLabel.text && (imageUsed || progressUsed)){
+        // Add spacing if both content and label are used
+        hudHeight += SVProgressHUDLabelSpacing;
+    }
+    
+    // Update values on subviews
+    self.hudView.bounds = CGRectMake(0.0f, 0.0f, MAX(self.minimumSize.width, hudWidth), MAX(self.minimumSize.height, hudHeight));
+    
+    // Animate value update
+    [CATransaction begin];
+    [CATransaction setDisableActions:YES];
+    
+    // Spinner and image view
+    CGFloat centerY;
+    if(self.statusLabel.text) {
+        CGFloat yOffset = MAX(SVProgressHUDVerticalSpacing, (self.minimumSize.height - contentHeight - SVProgressHUDLabelSpacing - labelHeight) / 2.0f);
+        centerY = yOffset + contentHeight / 2.0f;
+    } else {
+        centerY = CGRectGetMidY(self.hudView.bounds);
+    }
+    self.indefiniteAnimatedView.center = CGPointMake(CGRectGetMidX(self.hudView.bounds), centerY);
+    if(self.progress != SVProgressHUDUndefinedProgress) {
+        self.backgroundRingView.center = self.ringView.center = CGPointMake(CGRectGetMidX(self.hudView.bounds), centerY);
+    }
+    self.imageView.center = CGPointMake(CGRectGetMidX(self.hudView.bounds), centerY);
+
+    // Label
+    if(imageUsed || progressUsed) {
+        centerY = CGRectGetMaxY(imageUsed ? self.imageView.frame : self.indefiniteAnimatedView.frame) + SVProgressHUDLabelSpacing + labelHeight / 2.0f;
+    } else {
+        centerY = CGRectGetMidY(self.hudView.bounds);
+    }
+    self.statusLabel.frame = labelRect;
+    self.statusLabel.center = CGPointMake(CGRectGetMidX(self.hudView.bounds), centerY);
+    
+    [CATransaction commit];
+}
+
+#if TARGET_OS_IOS
+- (void)updateMotionEffectForOrientation:(UIInterfaceOrientation)orientation {
+    bool isPortrait = UIInterfaceOrientationIsPortrait(orientation);
+    UIInterpolatingMotionEffectType xMotionEffectType = isPortrait ? UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis : UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis;
+    UIInterpolatingMotionEffectType yMotionEffectType = isPortrait ? UIInterpolatingMotionEffectTypeTiltAlongVerticalAxis : UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis;
+    [self updateMotionEffectForXMotionEffectType:xMotionEffectType yMotionEffectType:yMotionEffectType];
+}
+#endif
+
+- (void)updateMotionEffectForXMotionEffectType:(UIInterpolatingMotionEffectType)xMotionEffectType yMotionEffectType:(UIInterpolatingMotionEffectType)yMotionEffectType {
+    UIInterpolatingMotionEffect *effectX = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" type:xMotionEffectType];
+    effectX.minimumRelativeValue = @(-SVProgressHUDParallaxDepthPoints);
+    effectX.maximumRelativeValue = @(SVProgressHUDParallaxDepthPoints);
+    
+    UIInterpolatingMotionEffect *effectY = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.y" type:yMotionEffectType];
+    effectY.minimumRelativeValue = @(-SVProgressHUDParallaxDepthPoints);
+    effectY.maximumRelativeValue = @(SVProgressHUDParallaxDepthPoints);
+    
+    UIMotionEffectGroup *effectGroup = [UIMotionEffectGroup new];
+    effectGroup.motionEffects = @[effectX, effectY];
+    
+    // Clear old motion effect, then add new motion effects
+    self.hudView.motionEffects = @[];
+    [self.hudView addMotionEffect:effectGroup];
+}
+
+- (void)updateViewHierarchy {
+    // Add the overlay to the application window if necessary
+    if(!self.controlView.superview) {
+        if(self.containerView){
+            [self.containerView addSubview:self.controlView];
+        } else {
+#if !defined(SV_APP_EXTENSIONS)
+            [self.frontWindow addSubview:self.controlView];
+#else
+            // If SVProgressHUD is used inside an app extension add it to the given view
+            if(self.viewForExtension) {
+                [self.viewForExtension addSubview:self.controlView];
+            }
+#endif
+        }
+    } else {
+        // The HUD is already on screen, but maybe not in front. Therefore
+        // ensure that overlay will be on top of rootViewController (which may
+        // be changed during runtime).
+        [self.controlView.superview bringSubviewToFront:self.controlView];
+    }
+    
+    // Add self to the overlay view
+    if(!self.superview) {
+        [self.controlView addSubview:self];
+    }
+}
+
+- (void)setStatus:(NSString*)status {
+    self.statusLabel.text = status;
+    self.statusLabel.hidden = status.length == 0;
+    [self updateHUDFrame];
+}
+
+- (void)setGraceTimer:(NSTimer*)timer {
+    if(_graceTimer) {
+        [_graceTimer invalidate];
+        _graceTimer = nil;
+    }
+    if(timer) {
+        _graceTimer = timer;
+    }
+}
+
+- (void)setFadeOutTimer:(NSTimer*)timer {
+    if(_fadeOutTimer) {
+        [_fadeOutTimer invalidate];
+        _fadeOutTimer = nil;
+    }
+    if(timer) {
+        _fadeOutTimer = timer;
+    }
+}
+
+
+#pragma mark - Notifications and their handling
+
+- (void)registerNotifications {
+#if TARGET_OS_IOS
+    [[NSNotificationCenter defaultCenter] addObserver:self
+                                             selector:@selector(positionHUD:)
+                                                 name:UIApplicationDidChangeStatusBarOrientationNotification
+                                               object:nil];
+    
+    [[NSNotificationCenter defaultCenter] addObserver:self
+                                             selector:@selector(positionHUD:)
+                                                 name:UIKeyboardWillHideNotification
+                                               object:nil];
+    
+    [[NSNotificationCenter defaultCenter] addObserver:self
+                                             selector:@selector(positionHUD:)
+                                                 name:UIKeyboardDidHideNotification
+                                               object:nil];
+    
+    [[NSNotificationCenter defaultCenter] addObserver:self
+                                             selector:@selector(positionHUD:)
+                                                 name:UIKeyboardWillShowNotification
+                                               object:nil];
+    
+    [[NSNotificationCenter defaultCenter] addObserver:self
+                                             selector:@selector(positionHUD:)
+                                                 name:UIKeyboardDidShowNotification
+                                               object:nil];
+#endif
+    [[NSNotificationCenter defaultCenter] addObserver:self
+                                             selector:@selector(positionHUD:)
+                                                 name:UIApplicationDidBecomeActiveNotification
+                                               object:nil];
+}
+
+- (NSDictionary*)notificationUserInfo {
+    return (self.statusLabel.text ? @{SVProgressHUDStatusUserInfoKey : self.statusLabel.text} : nil);
+}
+
+- (void)positionHUD:(NSNotification*)notification {
+    CGFloat keyboardHeight = 0.0f;
+    double animationDuration = 0.0;
+
+#if !defined(SV_APP_EXTENSIONS) && TARGET_OS_IOS
+    self.frame =  [SVProgressHUD mainWindow].bounds;
+    UIInterfaceOrientation orientation = UIApplication.sharedApplication.statusBarOrientation;
+#elif !defined(SV_APP_EXTENSIONS) && !TARGET_OS_IOS
+    self.frame = [SVProgressHUD mainWindow].bounds;
+#else
+    if (self.viewForExtension) {
+        self.frame = self.viewForExtension.frame;
+    } else {
+        self.frame = UIScreen.mainScreen.bounds;
+    }
+#if TARGET_OS_IOS
+    UIInterfaceOrientation orientation = CGRectGetWidth(self.frame) > CGRectGetHeight(self.frame) ? UIInterfaceOrientationLandscapeLeft : UIInterfaceOrientationPortrait;
+#endif
+#endif
+    
+#if TARGET_OS_IOS
+    // Get keyboardHeight in regard to current state
+    if(notification) {
+        NSDictionary* keyboardInfo = [notification userInfo];
+        CGRect keyboardFrame = [keyboardInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue];
+        animationDuration = [keyboardInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
+        
+        if(notification.name == UIKeyboardWillShowNotification || notification.name == UIKeyboardDidShowNotification) {
+            keyboardHeight = CGRectGetWidth(keyboardFrame);
+            
+            if(UIInterfaceOrientationIsPortrait(orientation)) {
+                keyboardHeight = CGRectGetHeight(keyboardFrame);
+            }
+        }
+    } else {
+        keyboardHeight = self.visibleKeyboardHeight;
+    }
+#endif
+    
+    // Get the currently active frame of the display (depends on orientation)
+    CGRect orientationFrame = self.bounds;
+
+#if !defined(SV_APP_EXTENSIONS) && TARGET_OS_IOS
+    CGRect statusBarFrame = UIApplication.sharedApplication.statusBarFrame;
+#else
+    CGRect statusBarFrame = CGRectZero;
+#endif
+    
+    if (_motionEffectEnabled) {
+#if TARGET_OS_IOS
+        // Update the motion effects in regard to orientation
+        [self updateMotionEffectForOrientation:orientation];
+#else
+        [self updateMotionEffectForXMotionEffectType:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis yMotionEffectType:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis];
+#endif
+    }
+    
+    // Calculate available height for display
+    CGFloat activeHeight = CGRectGetHeight(orientationFrame);
+    if(keyboardHeight > 0) {
+        activeHeight += CGRectGetHeight(statusBarFrame) * 2;
+    }
+    activeHeight -= keyboardHeight;
+    
+    CGFloat posX = CGRectGetMidX(orientationFrame);
+    CGFloat posY = floorf(activeHeight*0.45f);
+
+    CGFloat rotateAngle = 0.0;
+    CGPoint newCenter = CGPointMake(posX, posY);
+    
+    if(notification) {
+        // Animate update if notification was present
+        [UIView animateWithDuration:animationDuration
+                              delay:0
+                            options:(UIViewAnimationOptions) (UIViewAnimationOptionAllowUserInteraction | UIViewAnimationOptionBeginFromCurrentState)
+                         animations:^{
+                             [self moveToPoint:newCenter rotateAngle:rotateAngle];
+                             [self.hudView setNeedsDisplay];
+                         } completion:nil];
+    } else {
+        [self moveToPoint:newCenter rotateAngle:rotateAngle];
+    }
+}
+
+- (void)moveToPoint:(CGPoint)newCenter rotateAngle:(CGFloat)angle {
+    self.hudView.transform = CGAffineTransformMakeRotation(angle);
+    if (self.containerView) {
+        self.hudView.center = CGPointMake(self.containerView.center.x + self.offsetFromCenter.horizontal, self.containerView.center.y + self.offsetFromCenter.vertical);
+    } else {
+        self.hudView.center = CGPointMake(newCenter.x + self.offsetFromCenter.horizontal, newCenter.y + self.offsetFromCenter.vertical);
+    }
+}
+
+
+#pragma mark - Event handling
+
+- (void)controlViewDidReceiveTouchEvent:(id)sender forEvent:(UIEvent*)event {
+    [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDDidReceiveTouchEventNotification
+                                                        object:self
+                                                      userInfo:[self notificationUserInfo]];
+    
+    UITouch *touch = event.allTouches.anyObject;
+    CGPoint touchLocation = [touch locationInView:self];
+    
+    if(CGRectContainsPoint(self.hudView.frame, touchLocation)) {
+        [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDDidTouchDownInsideNotification
+                                                            object:self
+                                                          userInfo:[self notificationUserInfo]];
+    }
+}
+
+
+#pragma mark - Master show/dismiss methods
+
+- (void)showProgress:(float)progress status:(NSString*)status {
+    __weak SVProgressHUD *weakSelf = self;
+    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
+        __strong SVProgressHUD *strongSelf = weakSelf;
+        if(strongSelf){
+            if(strongSelf.fadeOutTimer) {
+                strongSelf.activityCount = 0;
+            }
+            
+            // Stop timer
+            strongSelf.fadeOutTimer = nil;
+            strongSelf.graceTimer = nil;
+            
+            // Update / Check view hierarchy to ensure the HUD is visible
+            [strongSelf updateViewHierarchy];
+            
+            // Reset imageView and fadeout timer if an image is currently displayed
+            strongSelf.imageView.hidden = YES;
+            strongSelf.imageView.image = nil;
+            
+            // Update text and set progress to the given value
+            strongSelf.statusLabel.hidden = status.length == 0;
+            strongSelf.statusLabel.text = status;
+            strongSelf.progress = progress;
+            
+            // Choose the "right" indicator depending on the progress
+            if(progress >= 0) {
+                // Cancel the indefiniteAnimatedView, then show the ringLayer
+                [strongSelf cancelIndefiniteAnimatedViewAnimation];
+                
+                // Add ring to HUD
+                if(!strongSelf.ringView.superview){
+                    [strongSelf.hudView.contentView addSubview:strongSelf.ringView];
+                }
+                if(!strongSelf.backgroundRingView.superview){
+                    [strongSelf.hudView.contentView addSubview:strongSelf.backgroundRingView];
+                }
+                
+                // Set progress animated
+                [CATransaction begin];
+                [CATransaction setDisableActions:YES];
+                strongSelf.ringView.strokeEnd = progress;
+                [CATransaction commit];
+                
+                // Update the activity count
+                if(progress == 0) {
+                    strongSelf.activityCount++;
+                }
+            } else {
+                // Cancel the ringLayer animation, then show the indefiniteAnimatedView
+                [strongSelf cancelRingLayerAnimation];
+                
+                // Add indefiniteAnimatedView to HUD
+                [strongSelf.hudView.contentView addSubview:strongSelf.indefiniteAnimatedView];
+                if([strongSelf.indefiniteAnimatedView respondsToSelector:@selector(startAnimating)]) {
+                    [(id)strongSelf.indefiniteAnimatedView startAnimating];
+                }
+                
+                // Update the activity count
+                strongSelf.activityCount++;
+            }
+            
+            // Fade in delayed if a grace time is set
+            if (self.graceTimeInterval > 0.0 && self.backgroundView.alpha == 0.0f) {
+                strongSelf.graceTimer = [NSTimer timerWithTimeInterval:self.graceTimeInterval target:strongSelf selector:@selector(fadeIn:) userInfo:nil repeats:NO];
+                [[NSRunLoop mainRunLoop] addTimer:strongSelf.graceTimer forMode:NSRunLoopCommonModes];
+            } else {
+                [strongSelf fadeIn:nil];
+            }
+            
+            // Tell the Haptics Generator to prepare for feedback, which may come soon
+#if TARGET_OS_IOS
+            [strongSelf.hapticGenerator prepare];
+#endif
+        }
+    }];
+}
+
+- (void)showImage:(UIImage*)image status:(NSString*)status duration:(NSTimeInterval)duration {
+    __weak SVProgressHUD *weakSelf = self;
+    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
+        __strong SVProgressHUD *strongSelf = weakSelf;
+        if(strongSelf){
+            // Stop timer
+            strongSelf.fadeOutTimer = nil;
+            strongSelf.graceTimer = nil;
+            
+            // Update / Check view hierarchy to ensure the HUD is visible
+            [strongSelf updateViewHierarchy];
+            
+            // Reset progress and cancel any running animation
+            strongSelf.progress = SVProgressHUDUndefinedProgress;
+            [strongSelf cancelRingLayerAnimation];
+            [strongSelf cancelIndefiniteAnimatedViewAnimation];
+            
+            // Update imageView
+            if (self.shouldTintImages) {
+                if (image.renderingMode != UIImageRenderingModeAlwaysTemplate) {
+                    strongSelf.imageView.image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
+                } else {
+                    strongSelf.imageView.image = image;
+                }
+                strongSelf.imageView.tintColor = strongSelf.foregroundImageColorForStyle;
+            } else {
+                strongSelf.imageView.image = image;
+            }
+            strongSelf.imageView.hidden = NO;
+            
+            // Update text
+            strongSelf.statusLabel.hidden = status.length == 0;
+            strongSelf.statusLabel.text = status;
+            
+            // Fade in delayed if a grace time is set
+            // An image will be dismissed automatically. Thus pass the duration as userInfo.
+            if (self.graceTimeInterval > 0.0 && self.backgroundView.alpha == 0.0f) {
+                strongSelf.graceTimer = [NSTimer timerWithTimeInterval:self.graceTimeInterval target:strongSelf selector:@selector(fadeIn:) userInfo:@(duration) repeats:NO];
+                [[NSRunLoop mainRunLoop] addTimer:strongSelf.graceTimer forMode:NSRunLoopCommonModes];
+            } else {
+                [strongSelf fadeIn:@(duration)];
+            }
+        }
+    }];
+}
+
+- (void)fadeIn:(id)data {
+    // Update the HUDs frame to the new content and position HUD
+    [self updateHUDFrame];
+    [self positionHUD:nil];
+    
+    // Update accessibility as well as user interaction
+    // \n cause to read text twice so remove "\n" new line character before setting up accessiblity label
+    NSString *accessibilityString = [[self.statusLabel.text componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]] componentsJoinedByString:@" "];
+    if(self.defaultMaskType != SVProgressHUDMaskTypeNone) {
+        self.controlView.userInteractionEnabled = YES;
+        self.accessibilityLabel =  accessibilityString ?: NSLocalizedString(@"Loading", nil);
+        self.isAccessibilityElement = YES;
+        self.controlView.accessibilityViewIsModal = YES;
+    } else {
+        self.controlView.userInteractionEnabled = NO;
+        self.hudView.accessibilityLabel = accessibilityString ?: NSLocalizedString(@"Loading", nil);
+        self.isAccessibilityElement = NO;
+        self.hudView.isAccessibilityElement = YES;
+        self.controlView.accessibilityViewIsModal = NO;
+    }
+    
+    // Get duration
+    id duration = [data isKindOfClass:[NSTimer class]] ? ((NSTimer *)data).userInfo : data;
+    
+    // Show if not already visible
+    if(self.backgroundView.alpha != 1.0f) {
+        // Post notification to inform user
+        [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDWillAppearNotification
+                                                            object:self
+                                                          userInfo:[self notificationUserInfo]];
+        
+        // Zoom HUD a little to to make a nice appear / pop up animation
+        self.hudView.transform = self.hudView.transform = CGAffineTransformScale(self.hudView.transform, 1.3f, 1.3f);
+        
+        __block void (^animationsBlock)(void) = ^{
+            // Zoom HUD a little to make a nice appear / pop up animation
+            self.hudView.transform = CGAffineTransformIdentity;
+            
+            // Fade in all effects (colors, blur, etc.)
+            [self fadeInEffects];
+        };
+        
+        __block void (^completionBlock)(void) = ^{
+            // Check if we really achieved to show the HUD (<=> alpha)
+            // and the change of these values has not been cancelled in between e.g. due to a dismissal
+            if(self.backgroundView.alpha == 1.0f){
+                // Register observer <=> we now have to handle orientation changes etc.
+                [self registerNotifications];
+                
+                // Post notification to inform user
+                [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDDidAppearNotification
+                                                                    object:self
+                                                                  userInfo:[self notificationUserInfo]];
+                
+                // Update accessibility
+                UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil);
+                UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, self.statusLabel.text);
+                
+                // Dismiss automatically if a duration was passed as userInfo. We start a timer
+                // which then will call dismiss after the predefined duration
+                if(duration){
+                    self.fadeOutTimer = [NSTimer timerWithTimeInterval:[(NSNumber *)duration doubleValue] target:self selector:@selector(dismiss) userInfo:nil repeats:NO];
+                    [[NSRunLoop mainRunLoop] addTimer:self.fadeOutTimer forMode:NSRunLoopCommonModes];
+                }
+            }
+        };
+        
+        // Animate appearance
+        if (self.fadeInAnimationDuration > 0) {
+            // Animate appearance
+            [UIView animateWithDuration:self.fadeInAnimationDuration
+                                  delay:0
+                                options:(UIViewAnimationOptions) (UIViewAnimationOptionAllowUserInteraction | UIViewAnimationCurveEaseIn | UIViewAnimationOptionBeginFromCurrentState)
+                             animations:^{
+                                 animationsBlock();
+                             } completion:^(BOOL finished) {
+                                 completionBlock();
+                             }];
+        } else {
+            animationsBlock();
+            completionBlock();
+        }
+        
+        // Inform iOS to redraw the view hierarchy
+        [self setNeedsDisplay];
+    } else {
+        // Update accessibility
+        UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, nil);
+        UIAccessibilityPostNotification(UIAccessibilityAnnouncementNotification, self.statusLabel.text);
+        
+        // Dismiss automatically if a duration was passed as userInfo. We start a timer
+        // which then will call dismiss after the predefined duration
+        if(duration){
+            self.fadeOutTimer = [NSTimer timerWithTimeInterval:[(NSNumber *)duration doubleValue] target:self selector:@selector(dismiss) userInfo:nil repeats:NO];
+            [[NSRunLoop mainRunLoop] addTimer:self.fadeOutTimer forMode:NSRunLoopCommonModes];
+        }
+    }
+}
+
+- (void)dismiss {
+    [self dismissWithDelay:0.0 completion:nil];
+}
+
+- (void)dismissWithDelay:(NSTimeInterval)delay completion:(SVProgressHUDDismissCompletion)completion {
+    __weak SVProgressHUD *weakSelf = self;
+    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
+        __strong SVProgressHUD *strongSelf = weakSelf;
+        if(strongSelf){
+            
+            // Post notification to inform user
+            [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDWillDisappearNotification
+                                                                object:nil
+                                                              userInfo:[strongSelf notificationUserInfo]];
+            
+            // Reset activity count
+            strongSelf.activityCount = 0;
+            
+            __block void (^animationsBlock)(void) = ^{
+                // Shrink HUD a little to make a nice disappear animation
+                strongSelf.hudView.transform = CGAffineTransformScale(strongSelf.hudView.transform, 1/1.3f, 1/1.3f);
+                
+                // Fade out all effects (colors, blur, etc.)
+                [strongSelf fadeOutEffects];
+            };
+            
+            __block void (^completionBlock)(void) = ^{
+                // Check if we really achieved to dismiss the HUD (<=> alpha values are applied)
+                // and the change of these values has not been cancelled in between e.g. due to a new show
+                if(self.backgroundView.alpha == 0.0f){
+                    // Clean up view hierarchy (overlays)
+                    [strongSelf.controlView removeFromSuperview];
+                    [strongSelf.backgroundView removeFromSuperview];
+                    [strongSelf.hudView removeFromSuperview];
+                    [strongSelf removeFromSuperview];
+                    
+                    // Reset progress and cancel any running animation
+                    strongSelf.progress = SVProgressHUDUndefinedProgress;
+                    [strongSelf cancelRingLayerAnimation];
+                    [strongSelf cancelIndefiniteAnimatedViewAnimation];
+                    
+                    // Remove observer <=> we do not have to handle orientation changes etc.
+                    [[NSNotificationCenter defaultCenter] removeObserver:strongSelf];
+                    
+                    // Post notification to inform user
+                    [[NSNotificationCenter defaultCenter] postNotificationName:SVProgressHUDDidDisappearNotification
+                                                                        object:strongSelf
+                                                                      userInfo:[strongSelf notificationUserInfo]];
+                    
+                    // Tell the rootViewController to update the StatusBar appearance
+#if !defined(SV_APP_EXTENSIONS) && TARGET_OS_IOS
+                    UIViewController *rootController = [SVProgressHUD mainWindow].rootViewController;
+                    [rootController setNeedsStatusBarAppearanceUpdate];
+#endif
+                    
+                    // Run an (optional) completionHandler
+                    if (completion) {
+                        completion();
+                    }
+                }
+            };
+            
+            // UIViewAnimationOptionBeginFromCurrentState AND a delay doesn't always work as expected
+            // When UIViewAnimationOptionBeginFromCurrentState is set, animateWithDuration: evaluates the current
+            // values to check if an animation is necessary. The evaluation happens at function call time and not
+            // after the delay => the animation is sometimes skipped. Therefore we delay using dispatch_after.
+            
+            dispatch_time_t dipatchTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC));
+            dispatch_after(dipatchTime, dispatch_get_main_queue(), ^{
+                
+                // Stop timer
+                strongSelf.graceTimer = nil;
+                
+                if (strongSelf.fadeOutAnimationDuration > 0) {
+                    // Animate appearance
+                    [UIView animateWithDuration:strongSelf.fadeOutAnimationDuration
+                                          delay:0
+                                        options:(UIViewAnimationOptions) (UIViewAnimationOptionAllowUserInteraction | UIViewAnimationCurveEaseOut | UIViewAnimationOptionBeginFromCurrentState)
+                                     animations:^{
+                                         animationsBlock();
+                                     } completion:^(BOOL finished) {
+                                         completionBlock();
+                                     }];
+                } else {
+                    animationsBlock();
+                    completionBlock();
+                }
+            });
+            
+            // Inform iOS to redraw the view hierarchy
+            [strongSelf setNeedsDisplay];
+        }
+    }];
+}
+
+
+#pragma mark - Ring progress animation
+
+- (UIView*)indefiniteAnimatedView {
+    // Get the correct spinner for defaultAnimationType
+    if(self.defaultAnimationType == SVProgressHUDAnimationTypeFlat){
+        // Check if spinner exists and is an object of different class
+        if(_indefiniteAnimatedView && ![_indefiniteAnimatedView isKindOfClass:[SVIndefiniteAnimatedView class]]){
+            [_indefiniteAnimatedView removeFromSuperview];
+            _indefiniteAnimatedView = nil;
+        }
+        
+        if(!_indefiniteAnimatedView){
+            _indefiniteAnimatedView = [[SVIndefiniteAnimatedView alloc] initWithFrame:CGRectZero];
+        }
+        
+        // Update styling
+        SVIndefiniteAnimatedView *indefiniteAnimatedView = (SVIndefiniteAnimatedView*)_indefiniteAnimatedView;
+        indefiniteAnimatedView.strokeColor = self.foregroundImageColorForStyle;
+        indefiniteAnimatedView.strokeThickness = self.ringThickness;
+        indefiniteAnimatedView.radius = self.statusLabel.text ? self.ringRadius : self.ringNoTextRadius;
+    } else {
+        // Check if spinner exists and is an object of different class
+        if(_indefiniteAnimatedView && ![_indefiniteAnimatedView isKindOfClass:[UIActivityIndicatorView class]]){
+            [_indefiniteAnimatedView removeFromSuperview];
+            _indefiniteAnimatedView = nil;
+        }
+        
+        if(!_indefiniteAnimatedView){
+            _indefiniteAnimatedView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
+        }
+        
+        // Update styling
+        UIActivityIndicatorView *activityIndicatorView = (UIActivityIndicatorView*)_indefiniteAnimatedView;
+        activityIndicatorView.color = self.foregroundImageColorForStyle;
+    }
+    [_indefiniteAnimatedView sizeToFit];
+    
+    return _indefiniteAnimatedView;
+}
+
+- (SVProgressAnimatedView*)ringView {
+    if(!_ringView) {
+        _ringView = [[SVProgressAnimatedView alloc] initWithFrame:CGRectZero];
+    }
+    
+    // Update styling
+    _ringView.strokeColor = self.foregroundImageColorForStyle;
+    _ringView.strokeThickness = self.ringThickness;
+    _ringView.radius = self.statusLabel.text ? self.ringRadius : self.ringNoTextRadius;
+    
+    return _ringView;
+}
+
+- (SVProgressAnimatedView*)backgroundRingView {
+    if(!_backgroundRingView) {
+        _backgroundRingView = [[SVProgressAnimatedView alloc] initWithFrame:CGRectZero];
+        _backgroundRingView.strokeEnd = 1.0f;
+    }
+    
+    // Update styling
+    _backgroundRingView.strokeColor = [self.foregroundImageColorForStyle colorWithAlphaComponent:0.1f];
+    _backgroundRingView.strokeThickness = self.ringThickness;
+    _backgroundRingView.radius = self.statusLabel.text ? self.ringRadius : self.ringNoTextRadius;
+    
+    return _backgroundRingView;
+}
+
+- (void)cancelRingLayerAnimation {
+    // Animate value update, stop animation
+    [CATransaction begin];
+    [CATransaction setDisableActions:YES];
+    
+    [self.hudView.layer removeAllAnimations];
+    self.ringView.strokeEnd = 0.0f;
+    
+    [CATransaction commit];
+    
+    // Remove from view
+    [self.ringView removeFromSuperview];
+    [self.backgroundRingView removeFromSuperview];
+}
+
+- (void)cancelIndefiniteAnimatedViewAnimation {
+    // Stop animation
+    if([self.indefiniteAnimatedView respondsToSelector:@selector(stopAnimating)]) {
+        [(id)self.indefiniteAnimatedView stopAnimating];
+    }
+    // Remove from view
+    [self.indefiniteAnimatedView removeFromSuperview];
+}
+
+
+#pragma mark - Utilities
+
++ (BOOL)isVisible {
+    // Checking one alpha value is sufficient as they are all the same
+    return [self sharedView].backgroundView.alpha > 0.0f;
+}
+
+
+#pragma mark - Getters
+
++ (NSTimeInterval)displayDurationForString:(NSString*)string {
+    CGFloat minimum = MAX((CGFloat)string.length * 0.06 + 0.5, [self sharedView].minimumDismissTimeInterval);
+    return MIN(minimum, [self sharedView].maximumDismissTimeInterval);
+}
+
+- (UIColor*)foregroundColorForStyle {
+    SVProgressHUDStyle style = [self defaultStyleResolvingAutomatic];
+    
+    if(style == SVProgressHUDStyleLight) {
+        return [UIColor blackColor];
+    } else if(style == SVProgressHUDStyleDark) {
+        return [UIColor whiteColor];
+    } else {
+        return self.foregroundColor;
+    }
+}
+
+- (UIColor*)foregroundImageColorForStyle {
+    if (self.foregroundImageColor) {
+        return self.foregroundImageColor;
+    } else {
+        return [self foregroundColorForStyle];
+    }
+}
+
+- (UIColor*)backgroundColorForStyle {
+    SVProgressHUDStyle style = [self defaultStyleResolvingAutomatic];
+
+    if(style == SVProgressHUDStyleLight) {
+        return [UIColor whiteColor];
+    } else if(style == SVProgressHUDStyleDark) {
+        return [UIColor blackColor];
+    } else {
+        return self.backgroundColor;
+    }
+}
+
+- (UIControl*)controlView {
+    if(!_controlView) {
+        _controlView = [UIControl new];
+        _controlView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+        _controlView.backgroundColor = [UIColor clearColor];
+        _controlView.userInteractionEnabled = YES;
+        [_controlView addTarget:self action:@selector(controlViewDidReceiveTouchEvent:forEvent:) forControlEvents:UIControlEventTouchDown];
+    }
+    
+    // Update frame
+#if !defined(SV_APP_EXTENSIONS)
+    _controlView.frame = [SVProgressHUD mainWindow].bounds;
+#else
+    _controlView.frame = [UIScreen mainScreen].bounds;
+#endif
+    
+    return _controlView;
+}
+
+-(UIView *)backgroundView {
+    if(!_backgroundView){
+        _backgroundView = [UIView new];
+        _backgroundView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+    }
+    if(!_backgroundView.superview){
+        [self insertSubview:_backgroundView belowSubview:self.hudView];
+    }
+    
+    // Update styling
+    if(self.defaultMaskType == SVProgressHUDMaskTypeGradient){
+        if(!_backgroundRadialGradientLayer){
+            _backgroundRadialGradientLayer = [SVRadialGradientLayer layer];
+        }
+        if(!_backgroundRadialGradientLayer.superlayer){
+            [_backgroundView.layer insertSublayer:_backgroundRadialGradientLayer atIndex:0];
+        }
+        _backgroundView.backgroundColor = [UIColor clearColor];
+    } else {
+        if(_backgroundRadialGradientLayer && _backgroundRadialGradientLayer.superlayer){
+            [_backgroundRadialGradientLayer removeFromSuperlayer];
+        }
+        if(self.defaultMaskType == SVProgressHUDMaskTypeBlack){
+            _backgroundView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.4];
+        } else if(self.defaultMaskType == SVProgressHUDMaskTypeCustom){
+            _backgroundView.backgroundColor = self.backgroundLayerColor;
+        } else {
+            _backgroundView.backgroundColor = [UIColor clearColor];
+        }
+    }
+
+    // Update frame
+    if(_backgroundView){
+        _backgroundView.frame = self.bounds;
+    }
+    if(_backgroundRadialGradientLayer){
+        _backgroundRadialGradientLayer.frame = self.bounds;
+        
+        // Calculate the new center of the gradient, it may change if keyboard is visible
+        CGPoint gradientCenter = self.center;
+        gradientCenter.y = (self.bounds.size.height - self.visibleKeyboardHeight)/2;
+        _backgroundRadialGradientLayer.gradientCenter = gradientCenter;
+        [_backgroundRadialGradientLayer setNeedsDisplay];
+    }
+    
+    return _backgroundView;
+}
+- (UIVisualEffectView*)hudView {
+    if(!_hudView) {
+        _hudView = [UIVisualEffectView new];
+        _hudView.layer.masksToBounds = YES;
+        _hudView.autoresizingMask = UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin;
+    }
+    if(!_hudView.superview) {
+        [self addSubview:_hudView];
+    }
+    
+    // Update styling
+    _hudView.layer.cornerRadius = self.cornerRadius;
+    
+    return _hudView;
+}
+
+- (UILabel*)statusLabel {
+    if(!_statusLabel) {
+        _statusLabel = [[UILabel alloc] initWithFrame:CGRectZero];
+        _statusLabel.backgroundColor = [UIColor clearColor];
+        _statusLabel.adjustsFontSizeToFitWidth = YES;
+        _statusLabel.adjustsFontForContentSizeCategory = YES;
+        _statusLabel.textAlignment = NSTextAlignmentCenter;
+        _statusLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
+        _statusLabel.numberOfLines = 0;
+    }
+    if(!_statusLabel.superview) {
+      [self.hudView.contentView addSubview:_statusLabel];
+    }
+    
+    // Update styling
+    _statusLabel.textColor = self.foregroundColorForStyle;
+    _statusLabel.font = self.font;
+
+    return _statusLabel;
+}
+
+- (UIImageView*)imageView {
+    if(_imageView && !CGSizeEqualToSize(_imageView.bounds.size, _imageViewSize)) {
+        [_imageView removeFromSuperview];
+        _imageView = nil;
+    }
+    
+    if(!_imageView) {
+        _imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, _imageViewSize.width, _imageViewSize.height)];
+    }
+    if(!_imageView.superview) {
+        [self.hudView.contentView addSubview:_imageView];
+    }
+    
+    return _imageView;
+}
+
+
+#pragma mark - Helper
+
+- (SVProgressHUDStyle) defaultStyleResolvingAutomatic {
+    if(self.defaultStyle == SVProgressHUDStyleAutomatic) {
+        return self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark ? SVProgressHUDStyleDark : SVProgressHUDStyleLight;
+    }
+    
+    return self.defaultStyle;
+}
+
+- (CGFloat)visibleKeyboardHeight {
+#if !defined(SV_APP_EXTENSIONS)
+    UIWindow *keyboardWindow = nil;
+    for (UIWindow *testWindow in UIApplication.sharedApplication.windows) {
+        if(![testWindow.class isEqual:UIWindow.class]) {
+            keyboardWindow = testWindow;
+            break;
+        }
+    }
+    
+    for (__strong UIView *possibleKeyboard in keyboardWindow.subviews) {
+        NSString *viewName = NSStringFromClass(possibleKeyboard.class);
+        if([viewName hasPrefix:@"UI"]){
+            if([viewName hasSuffix:@"PeripheralHostView"] || [viewName hasSuffix:@"Keyboard"]){
+                return CGRectGetHeight(possibleKeyboard.bounds);
+            } else if ([viewName hasSuffix:@"InputSetContainerView"]){
+                for (__strong UIView *possibleKeyboardSubview in possibleKeyboard.subviews) {
+                    viewName = NSStringFromClass(possibleKeyboardSubview.class);
+                    if([viewName hasPrefix:@"UI"] && [viewName hasSuffix:@"InputSetHostView"]) {
+                        CGRect convertedRect = [possibleKeyboard convertRect:possibleKeyboardSubview.frame toView:self];
+                        CGRect intersectedRect = CGRectIntersection(convertedRect, self.bounds);
+                        if (!CGRectIsNull(intersectedRect)) {
+                            return CGRectGetHeight(intersectedRect);
+                        }
+                    }
+                }
+            }
+        }
+    }
+#endif
+    return 0;
+}
+    
+- (UIWindow *)frontWindow {
+#if !defined(SV_APP_EXTENSIONS)
+    NSEnumerator *frontToBackWindows = [UIApplication.sharedApplication.windows reverseObjectEnumerator];
+    for (UIWindow *window in frontToBackWindows) {
+        BOOL windowOnMainScreen = window.screen == UIScreen.mainScreen;
+        BOOL windowIsVisible = !window.hidden && window.alpha > 0;
+        BOOL windowLevelSupported = (window.windowLevel >= UIWindowLevelNormal && window.windowLevel <= self.maxSupportedWindowLevel);
+        BOOL windowKeyWindow = window.isKeyWindow;
+			
+        if(windowOnMainScreen && windowIsVisible && windowLevelSupported && windowKeyWindow) {
+            return window;
+        }
+    }
+#endif
+    return nil;
+}
+    
+- (void)fadeInEffects {
+    if(self.defaultStyle != SVProgressHUDStyleCustom) {
+        // Add blur effect
+        UIBlurEffectStyle blurEffectStyle;
+#if TARGET_OS_IOS
+        if (@available(iOS 13.0, *)) {
+            blurEffectStyle = [self defaultStyleResolvingAutomatic] == SVProgressHUDStyleLight ? UIBlurEffectStyleSystemMaterial : UIBlurEffectStyleSystemMaterialDark;
+        } else {
+            blurEffectStyle = [self defaultStyleResolvingAutomatic] == SVProgressHUDStyleLight ? UIBlurEffectStyleLight : UIBlurEffectStyleDark;
+        }
+#else
+        blurEffectStyle = [self defaultStyleResolvingAutomatic] == SVProgressHUDStyleLight ? UIBlurEffectStyleLight : UIBlurEffectStyleDark;
+#endif
+        
+        UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:blurEffectStyle];
+        self.hudView.effect = blurEffect;
+        
+        // We omit UIVibrancy effect and use a suitable background color as an alternative.
+        // This will make everything more readable. See the following for details:
+        // https://www.omnigroup.com/developer/how-to-make-text-in-a-uivisualeffectview-readable-on-any-background
+        
+        self.hudView.backgroundColor = [self.backgroundColorForStyle colorWithAlphaComponent:0.6f];
+    } else {
+        self.hudView.effect = self.hudViewCustomBlurEffect;
+        self.hudView.backgroundColor =  self.backgroundColorForStyle;
+    }
+
+    // Fade in views
+    self.backgroundView.alpha = 1.0f;
+    
+    self.imageView.alpha = 1.0f;
+    self.statusLabel.alpha = 1.0f;
+    self.indefiniteAnimatedView.alpha = 1.0f;
+    self.ringView.alpha = self.backgroundRingView.alpha = 1.0f;
+}
+
+- (void)fadeOutEffects
+{
+    if(self.defaultStyle != SVProgressHUDStyleCustom) {
+        // Remove blur effect
+        self.hudView.effect = nil;
+    }
+
+    // Remove background color
+    self.hudView.backgroundColor = [UIColor clearColor];
+    
+    // Fade out views
+    self.backgroundView.alpha = 0.0f;
+    
+    self.imageView.alpha = 0.0f;
+    self.statusLabel.alpha = 0.0f;
+    self.indefiniteAnimatedView.alpha = 0.0f;
+    self.ringView.alpha = self.backgroundRingView.alpha = 0.0f;
+}
+
+#if TARGET_OS_IOS
+- (UINotificationFeedbackGenerator *)hapticGenerator {
+	// Only return if haptics are enabled
+	if(!self.hapticsEnabled) {
+		return nil;
+	}
+	
+	if(!_hapticGenerator) {
+		_hapticGenerator = [[UINotificationFeedbackGenerator alloc] init];
+	}
+	return _hapticGenerator;
+}
+#endif
+
+    
+#pragma mark - UIAppearance Setters
+
+- (void)setDefaultStyle:(SVProgressHUDStyle)style {
+    if (!_isInitializing) _defaultStyle = style;
+}
+
+- (void)setDefaultMaskType:(SVProgressHUDMaskType)maskType {
+    if (!_isInitializing) _defaultMaskType = maskType;
+}
+
+- (void)setDefaultAnimationType:(SVProgressHUDAnimationType)animationType {
+    if (!_isInitializing) _defaultAnimationType = animationType;
+}
+
+- (void)setContainerView:(UIView *)containerView {
+    if (!_isInitializing) _containerView = containerView;
+}
+
+- (void)setMinimumSize:(CGSize)minimumSize {
+    if (!_isInitializing) _minimumSize = minimumSize;
+}
+
+- (void)setRingThickness:(CGFloat)ringThickness {
+    if (!_isInitializing) _ringThickness = ringThickness;
+}
+
+- (void)setRingRadius:(CGFloat)ringRadius {
+    if (!_isInitializing) _ringRadius = ringRadius;
+}
+
+- (void)setRingNoTextRadius:(CGFloat)ringNoTextRadius {
+    if (!_isInitializing) _ringNoTextRadius = ringNoTextRadius;
+}
+
+- (void)setCornerRadius:(CGFloat)cornerRadius {
+    if (!_isInitializing) _cornerRadius = cornerRadius;
+}
+
+- (void)setFont:(UIFont*)font {
+    if (!_isInitializing) _font = font;
+}
+
+- (void)setForegroundColor:(UIColor*)color {
+    if (!_isInitializing) _foregroundColor = color;
+}
+
+- (void)setForegroundImageColor:(UIColor *)color {
+    if (!_isInitializing) _foregroundImageColor = color;
+}
+
+- (void)setBackgroundColor:(UIColor*)color {
+    if (!_isInitializing) _backgroundColor = color;
+}
+
+- (void)setBackgroundLayerColor:(UIColor*)color {
+    if (!_isInitializing) _backgroundLayerColor = color;
+}
+
+- (void)setShouldTintImages:(BOOL)shouldTintImages {
+    if (!_isInitializing) _shouldTintImages = shouldTintImages;
+}
+
+- (void)setInfoImage:(UIImage*)image {
+    if (!_isInitializing) _infoImage = image;
+}
+
+- (void)setSuccessImage:(UIImage*)image {
+    if (!_isInitializing) _successImage = image;
+}
+
+- (void)setErrorImage:(UIImage*)image {
+    if (!_isInitializing) _errorImage = image;
+}
+
+- (void)setViewForExtension:(UIView*)view {
+    if (!_isInitializing) _viewForExtension = view;
+}
+
+- (void)setOffsetFromCenter:(UIOffset)offset {
+    if (!_isInitializing) _offsetFromCenter = offset;
+}
+
+- (void)setMinimumDismissTimeInterval:(NSTimeInterval)minimumDismissTimeInterval {
+    if (!_isInitializing) _minimumDismissTimeInterval = minimumDismissTimeInterval;
+}
+
+- (void)setFadeInAnimationDuration:(NSTimeInterval)duration {
+    if (!_isInitializing) _fadeInAnimationDuration = duration;
+}
+
+- (void)setFadeOutAnimationDuration:(NSTimeInterval)duration {
+    if (!_isInitializing) _fadeOutAnimationDuration = duration;
+}
+
+- (void)setMaxSupportedWindowLevel:(UIWindowLevel)maxSupportedWindowLevel {
+    if (!_isInitializing) _maxSupportedWindowLevel = maxSupportedWindowLevel;
+}
+
+@end

+ 14 - 0
Example/Pods/SVProgressHUD/SVProgressHUD/SVRadialGradientLayer.h

@@ -0,0 +1,14 @@
+//
+//  SVRadialGradientLayer.h
+//  SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD
+//
+//  Copyright (c) 2014-2023 Tobias Totzek and contributors. All rights reserved.
+//
+
+#import <QuartzCore/QuartzCore.h>
+
+@interface SVRadialGradientLayer : CALayer
+
+@property (nonatomic) CGPoint gradientCenter;
+
+@end

+ 25 - 0
Example/Pods/SVProgressHUD/SVProgressHUD/SVRadialGradientLayer.m

@@ -0,0 +1,25 @@
+//
+//  SVRadialGradientLayer.m
+//  SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD
+//
+//  Copyright (c) 2014-2023 Tobias Totzek and contributors. All rights reserved.
+//
+
+#import "SVRadialGradientLayer.h"
+
+@implementation SVRadialGradientLayer
+
+- (void)drawInContext:(CGContextRef)context {
+    size_t locationsCount = 2;
+    CGFloat locations[2] = {0.0f, 1.0f};
+    CGFloat colors[8] = {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.75f};
+    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
+    CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, colors, locations, locationsCount);
+    CGColorSpaceRelease(colorSpace);
+
+    float radius = MIN(self.bounds.size.width , self.bounds.size.height);
+    CGContextDrawRadialGradient (context, gradient, self.gradientCenter, 0, self.gradientCenter, radius, kCGGradientDrawsAfterEndLocation);
+    CGGradientRelease(gradient);
+}
+
+@end

+ 26 - 0
Example/Pods/Target Support Files/SVProgressHUD/SVProgressHUD-Info.plist

@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+  <key>CFBundleDevelopmentRegion</key>
+  <string>${PODS_DEVELOPMENT_LANGUAGE}</string>
+  <key>CFBundleExecutable</key>
+  <string>${EXECUTABLE_NAME}</string>
+  <key>CFBundleIdentifier</key>
+  <string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
+  <key>CFBundleInfoDictionaryVersion</key>
+  <string>6.0</string>
+  <key>CFBundleName</key>
+  <string>${PRODUCT_NAME}</string>
+  <key>CFBundlePackageType</key>
+  <string>FMWK</string>
+  <key>CFBundleShortVersionString</key>
+  <string>2.3.1</string>
+  <key>CFBundleSignature</key>
+  <string>????</string>
+  <key>CFBundleVersion</key>
+  <string>${CURRENT_PROJECT_VERSION}</string>
+  <key>NSPrincipalClass</key>
+  <string></string>
+</dict>
+</plist>

+ 5 - 0
Example/Pods/Target Support Files/SVProgressHUD/SVProgressHUD-dummy.m

@@ -0,0 +1,5 @@
+#import <Foundation/Foundation.h>
+@interface PodsDummy_SVProgressHUD : NSObject
+@end
+@implementation PodsDummy_SVProgressHUD
+@end

+ 12 - 0
Example/Pods/Target Support Files/SVProgressHUD/SVProgressHUD-prefix.pch

@@ -0,0 +1,12 @@
+#ifdef __OBJC__
+#import <UIKit/UIKit.h>
+#else
+#ifndef FOUNDATION_EXPORT
+#if defined(__cplusplus)
+#define FOUNDATION_EXPORT extern "C"
+#else
+#define FOUNDATION_EXPORT extern
+#endif
+#endif
+#endif
+

+ 20 - 0
Example/Pods/Target Support Files/SVProgressHUD/SVProgressHUD-umbrella.h

@@ -0,0 +1,20 @@
+#ifdef __OBJC__
+#import <UIKit/UIKit.h>
+#else
+#ifndef FOUNDATION_EXPORT
+#if defined(__cplusplus)
+#define FOUNDATION_EXPORT extern "C"
+#else
+#define FOUNDATION_EXPORT extern
+#endif
+#endif
+#endif
+
+#import "SVIndefiniteAnimatedView.h"
+#import "SVProgressAnimatedView.h"
+#import "SVProgressHUD.h"
+#import "SVRadialGradientLayer.h"
+
+FOUNDATION_EXPORT double SVProgressHUDVersionNumber;
+FOUNDATION_EXPORT const unsigned char SVProgressHUDVersionString[];
+

+ 13 - 0
Example/Pods/Target Support Files/SVProgressHUD/SVProgressHUD.debug.xcconfig

@@ -0,0 +1,13 @@
+CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
+CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
+OTHER_LDFLAGS = $(inherited) -framework "QuartzCore"
+PODS_BUILD_DIR = ${BUILD_DIR}
+PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
+PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE}
+PODS_ROOT = ${SRCROOT}
+PODS_TARGET_SRCROOT = ${PODS_ROOT}/SVProgressHUD
+PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
+PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
+SKIP_INSTALL = YES
+USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES

+ 6 - 0
Example/Pods/Target Support Files/SVProgressHUD/SVProgressHUD.modulemap

@@ -0,0 +1,6 @@
+framework module SVProgressHUD {
+  umbrella header "SVProgressHUD-umbrella.h"
+
+  export *
+  module * { export * }
+}

+ 13 - 0
Example/Pods/Target Support Files/SVProgressHUD/SVProgressHUD.release.xcconfig

@@ -0,0 +1,13 @@
+CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
+CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SVProgressHUD
+GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
+OTHER_LDFLAGS = $(inherited) -framework "QuartzCore"
+PODS_BUILD_DIR = ${BUILD_DIR}
+PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
+PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE}
+PODS_ROOT = ${SRCROOT}
+PODS_TARGET_SRCROOT = ${PODS_ROOT}/SVProgressHUD
+PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
+PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
+SKIP_INSTALL = YES
+USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES