Compare commits
138 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b9f02d317e | |||
| 29d3fe128e | |||
| 0463bb7a8e | |||
| 12f8e2bc0d | |||
| 578b3dbb41 | |||
| 223ec2d2c0 | |||
| a0ca7e9e2a | |||
| f0a1914145 | |||
| 4355f5eb09 | |||
| 6b080f503d | |||
| c23ed83bf0 | |||
| 8b1c77d743 | |||
| 915ef85cff | |||
| dc1050be2a | |||
| 99ba8bf657 | |||
| 2b7e4198cf | |||
| 0969cceac8 | |||
| f349dea851 | |||
| b8e8f8d0ce | |||
| ee5f9ee9de | |||
| 8348cd6396 | |||
| 9f4c1be56d | |||
| de779aebef | |||
| 1785822242 | |||
| 1514ea5481 | |||
| ec81b9f5dd | |||
| 7381066b36 | |||
| bc998622eb | |||
| 47fd132451 | |||
| f0c45211b2 | |||
| 2952d5d559 | |||
| a6a5995402 | |||
| 8e476c702f | |||
| 5f7cc4c7b3 | |||
| d8d4e1e339 | |||
| 97c8e8aa32 | |||
| 7be93d548e | |||
| 0f78641fdb | |||
| fd909a3ad6 | |||
| 2bb0c190b3 | |||
| 1ecc16c953 | |||
| 4698fbbe99 | |||
| 03df02d214 | |||
| cbc46d4db4 | |||
| 552f722a88 | |||
| 19caee5ccc | |||
| 2b5d20f26d | |||
| a6913a46a2 | |||
| fab0c7a274 | |||
| d04463f251 | |||
| d37aace4ec | |||
| 33d9b98d7d | |||
| 0363923e1b | |||
| 877108b08b | |||
| 7b25a6b878 | |||
| b69ae3ff7e | |||
| 4eac2276d4 | |||
| 38a6a10280 | |||
| aae897fc68 | |||
| 438811dbe5 | |||
| 7ea761b26e | |||
| 5c5457a09b | |||
| cdccba8929 | |||
| 196beb7592 | |||
| 91fe62e899 | |||
| bab71b560d | |||
| bb11bcd528 | |||
| d1f25b147f | |||
| 3eb459eab5 | |||
| 9060761733 | |||
| d7c5bd193c | |||
| 43a03de8d9 | |||
| 621bdb3e05 | |||
| d50ba88425 | |||
| 08b8422c26 | |||
| 9d13d508c6 | |||
| 6ae45f0568 | |||
| e5dbab65e1 | |||
| 07827b28a9 | |||
| 1dbd0ad54b | |||
| 49f2429633 | |||
| ef0a87e777 | |||
| b23a0b14e3 | |||
| a05b878af4 | |||
| 912c2d3903 | |||
| 3716912bc5 | |||
| ec9e174e14 | |||
| 6b98bf40c2 | |||
| 1167ca0a0d | |||
| c8c565d4ec | |||
| be0be7585b | |||
| c241629ea6 | |||
| 46afa63dbd | |||
| 682ab6127f | |||
| 4d70e9ca26 | |||
| 7091a625f3 | |||
| 5a83c3d1f3 | |||
| ad0c6eaf62 | |||
| 1f96f32980 | |||
| 03b38dfa0e | |||
| 2c35358336 | |||
| 18626df942 | |||
| 1a716980c0 | |||
| b5cf71046f | |||
| 328d3739d6 | |||
| 2a858aa309 | |||
| f2937f6830 | |||
| c274892031 | |||
| 745968a053 | |||
| 4c90c708b7 | |||
| 871e96c1b9 | |||
| ad26638886 | |||
| 0306b46949 | |||
| 0f038463ed | |||
| ae01552b84 | |||
| 272bff5584 | |||
| 2adb5b4c88 | |||
| f930141a04 | |||
| 615fb4fcbc | |||
| 10dafb3853 | |||
| 7505c48033 | |||
| 35770b7362 | |||
| d478decba7 | |||
| 51bb03327c | |||
| f23eacf2ad | |||
| 04c9b77c75 | |||
| e7e83b5ad2 | |||
| 5911771ec9 | |||
| 6c1070848f | |||
| c18e8b8faf | |||
| 1d03424ab4 | |||
| 66556da572 | |||
| 6ebcfa59e9 | |||
| f6a2c31e2f | |||
| be3eb3f3a7 | |||
| a821389fee | |||
| e057aadaf1 | |||
| 4c95e0ed3f |
@@ -0,0 +1,8 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||
patreon: ivanvorobei
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
||||
custom: # https://xcode-shop.com
|
||||
@@ -33,6 +33,7 @@ playground.xcworkspace
|
||||
|
||||
# Swift Package Manager
|
||||
.build/
|
||||
.swiftpm/
|
||||
|
||||
# Carthage
|
||||
Carthage/Build
|
||||
@@ -7,12 +7,14 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
F437B75122D62D7700E6074C /* SPStorkControllerConfirmDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F437B75022D62D7700E6074C /* SPStorkControllerConfirmDelegate.swift */; };
|
||||
F445CA8721AED92600184254 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F445CA8621AED92600184254 /* AppDelegate.swift */; };
|
||||
F445CA8921AED92600184254 /* Controller.swift in Sources */ = {isa = PBXBuildFile; fileRef = F445CA8821AED92600184254 /* Controller.swift */; };
|
||||
F445CA8E21AED92700184254 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = F445CA8D21AED92700184254 /* Assets.xcassets */; };
|
||||
F445CA9121AED92700184254 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = F445CA8F21AED92700184254 /* LaunchScreen.storyboard */; };
|
||||
F459D75B21C3AB9A00798524 /* ModalViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F459D75A21C3AB9A00798524 /* ModalViewController.swift */; };
|
||||
F459D75D21C3ABBD00798524 /* ModalTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F459D75C21C3ABBD00798524 /* ModalTableViewController.swift */; };
|
||||
F4803BF523082FDA0092C9BC /* SPStorkArrowMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4803BF423082FDA0092C9BC /* SPStorkArrowMode.swift */; };
|
||||
F4DB849622609C05005082AA /* SPVibration.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4DB83F522609C03005082AA /* SPVibration.swift */; };
|
||||
F4DB849722609C05005082AA /* SPPromoTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4DB83F922609C03005082AA /* SPPromoTableViewCell.swift */; };
|
||||
F4DB849822609C05005082AA /* SPFormButtonTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4DB83FB22609C03005082AA /* SPFormButtonTableViewCell.swift */; };
|
||||
@@ -133,23 +135,25 @@
|
||||
F4DB850B22609C05005082AA /* SPRandom.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4DB849122609C04005082AA /* SPRandom.swift */; };
|
||||
F4DB850C22609C05005082AA /* SPDelay.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4DB849322609C04005082AA /* SPDelay.swift */; };
|
||||
F4DB850D22609C05005082AA /* SPShare.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4DB849522609C04005082AA /* SPShare.swift */; };
|
||||
F4F33BD822802AA100199EBE /* SPStorkHaptic.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4F33BC722802AA100199EBE /* SPStorkHaptic.swift */; };
|
||||
F4F33BD922802AA100199EBE /* SPStorkCodeDraw.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4F33BC922802AA100199EBE /* SPStorkCodeDraw.swift */; };
|
||||
F4F33BDA22802AA100199EBE /* SPStorkController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4F33BCA22802AA100199EBE /* SPStorkController.swift */; };
|
||||
F4F33BDB22802AA100199EBE /* SPStorkTransitioningDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4F33BCC22802AA100199EBE /* SPStorkTransitioningDelegate.swift */; };
|
||||
F4F33BDC22802AA100199EBE /* SPStorkPresentingAnimationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4F33BCD22802AA100199EBE /* SPStorkPresentingAnimationController.swift */; };
|
||||
F4F33BDD22802AA100199EBE /* SPStorkPresentationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4F33BCE22802AA100199EBE /* SPStorkPresentationController.swift */; };
|
||||
F4F33BDE22802AA100199EBE /* SPStorkDismissingAnimationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4F33BCF22802AA100199EBE /* SPStorkDismissingAnimationController.swift */; };
|
||||
F4F33BDF22802AA100199EBE /* SPStorkViewControllerExtenshion.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4F33BD122802AA100199EBE /* SPStorkViewControllerExtenshion.swift */; };
|
||||
F4F33BE022802AA100199EBE /* SPStorkCloseButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4F33BD322802AA100199EBE /* SPStorkCloseButton.swift */; };
|
||||
F4F33BE122802AA100199EBE /* SPStorkIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4F33BD422802AA100199EBE /* SPStorkIndicatorView.swift */; };
|
||||
F4F33BE222802AA100199EBE /* SPStorkCloseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4F33BD522802AA100199EBE /* SPStorkCloseView.swift */; };
|
||||
F4F33BE322802AA100199EBE /* SPStorkControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4F33BD722802AA100199EBE /* SPStorkControllerDelegate.swift */; };
|
||||
F4E0E39022CF6B940020D754 /* SPStorkHaptic.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4E0E37E22CF6B940020D754 /* SPStorkHaptic.swift */; };
|
||||
F4E0E39122CF6B940020D754 /* SPStorkSeque.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4E0E37F22CF6B940020D754 /* SPStorkSeque.swift */; };
|
||||
F4E0E39222CF6B940020D754 /* SPStorkCodeDraw.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4E0E38122CF6B940020D754 /* SPStorkCodeDraw.swift */; };
|
||||
F4E0E39322CF6B940020D754 /* SPStorkController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4E0E38222CF6B940020D754 /* SPStorkController.swift */; };
|
||||
F4E0E39422CF6B940020D754 /* SPStorkTransitioningDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4E0E38422CF6B940020D754 /* SPStorkTransitioningDelegate.swift */; };
|
||||
F4E0E39522CF6B940020D754 /* SPStorkPresentingAnimationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4E0E38522CF6B940020D754 /* SPStorkPresentingAnimationController.swift */; };
|
||||
F4E0E39622CF6B940020D754 /* SPStorkPresentationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4E0E38622CF6B940020D754 /* SPStorkPresentationController.swift */; };
|
||||
F4E0E39722CF6B940020D754 /* SPStorkDismissingAnimationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4E0E38722CF6B940020D754 /* SPStorkDismissingAnimationController.swift */; };
|
||||
F4E0E39822CF6B940020D754 /* SPStorkViewControllerExtenshion.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4E0E38922CF6B940020D754 /* SPStorkViewControllerExtenshion.swift */; };
|
||||
F4E0E39922CF6B940020D754 /* SPStorkCloseButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4E0E38B22CF6B940020D754 /* SPStorkCloseButton.swift */; };
|
||||
F4E0E39A22CF6B940020D754 /* SPStorkIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4E0E38C22CF6B940020D754 /* SPStorkIndicatorView.swift */; };
|
||||
F4E0E39B22CF6B940020D754 /* SPStorkCloseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4E0E38D22CF6B940020D754 /* SPStorkCloseView.swift */; };
|
||||
F4E0E39C22CF6B940020D754 /* SPStorkControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4E0E38F22CF6B940020D754 /* SPStorkControllerDelegate.swift */; };
|
||||
F4F33BE722802AB000199EBE /* SPFakeBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4F33BE522802AB000199EBE /* SPFakeBarView.swift */; };
|
||||
F4F33BE822802AB000199EBE /* SPFakeBarNavigationStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4F33BE622802AB000199EBE /* SPFakeBarNavigationStyle.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
F437B75022D62D7700E6074C /* SPStorkControllerConfirmDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPStorkControllerConfirmDelegate.swift; sourceTree = "<group>"; };
|
||||
F445CA8321AED92600184254 /* stork-controller.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "stork-controller.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
F445CA8621AED92600184254 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
F445CA8821AED92600184254 /* Controller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Controller.swift; sourceTree = "<group>"; };
|
||||
@@ -158,6 +162,7 @@
|
||||
F445CA9221AED92700184254 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
F459D75A21C3AB9A00798524 /* ModalViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalViewController.swift; sourceTree = "<group>"; };
|
||||
F459D75C21C3ABBD00798524 /* ModalTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ModalTableViewController.swift; sourceTree = "<group>"; };
|
||||
F4803BF423082FDA0092C9BC /* SPStorkArrowMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPStorkArrowMode.swift; sourceTree = "<group>"; };
|
||||
F4DB83F522609C03005082AA /* SPVibration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPVibration.swift; sourceTree = "<group>"; };
|
||||
F4DB83F922609C03005082AA /* SPPromoTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPPromoTableViewCell.swift; sourceTree = "<group>"; };
|
||||
F4DB83FB22609C03005082AA /* SPFormButtonTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPFormButtonTableViewCell.swift; sourceTree = "<group>"; };
|
||||
@@ -278,18 +283,19 @@
|
||||
F4DB849122609C04005082AA /* SPRandom.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPRandom.swift; sourceTree = "<group>"; };
|
||||
F4DB849322609C04005082AA /* SPDelay.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPDelay.swift; sourceTree = "<group>"; };
|
||||
F4DB849522609C04005082AA /* SPShare.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPShare.swift; sourceTree = "<group>"; };
|
||||
F4F33BC722802AA100199EBE /* SPStorkHaptic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkHaptic.swift; sourceTree = "<group>"; };
|
||||
F4F33BC922802AA100199EBE /* SPStorkCodeDraw.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkCodeDraw.swift; sourceTree = "<group>"; };
|
||||
F4F33BCA22802AA100199EBE /* SPStorkController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkController.swift; sourceTree = "<group>"; };
|
||||
F4F33BCC22802AA100199EBE /* SPStorkTransitioningDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkTransitioningDelegate.swift; sourceTree = "<group>"; };
|
||||
F4F33BCD22802AA100199EBE /* SPStorkPresentingAnimationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkPresentingAnimationController.swift; sourceTree = "<group>"; };
|
||||
F4F33BCE22802AA100199EBE /* SPStorkPresentationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkPresentationController.swift; sourceTree = "<group>"; };
|
||||
F4F33BCF22802AA100199EBE /* SPStorkDismissingAnimationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkDismissingAnimationController.swift; sourceTree = "<group>"; };
|
||||
F4F33BD122802AA100199EBE /* SPStorkViewControllerExtenshion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkViewControllerExtenshion.swift; sourceTree = "<group>"; };
|
||||
F4F33BD322802AA100199EBE /* SPStorkCloseButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkCloseButton.swift; sourceTree = "<group>"; };
|
||||
F4F33BD422802AA100199EBE /* SPStorkIndicatorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkIndicatorView.swift; sourceTree = "<group>"; };
|
||||
F4F33BD522802AA100199EBE /* SPStorkCloseView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkCloseView.swift; sourceTree = "<group>"; };
|
||||
F4F33BD722802AA100199EBE /* SPStorkControllerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkControllerDelegate.swift; sourceTree = "<group>"; };
|
||||
F4E0E37E22CF6B940020D754 /* SPStorkHaptic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkHaptic.swift; sourceTree = "<group>"; };
|
||||
F4E0E37F22CF6B940020D754 /* SPStorkSeque.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkSeque.swift; sourceTree = "<group>"; };
|
||||
F4E0E38122CF6B940020D754 /* SPStorkCodeDraw.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkCodeDraw.swift; sourceTree = "<group>"; };
|
||||
F4E0E38222CF6B940020D754 /* SPStorkController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkController.swift; sourceTree = "<group>"; };
|
||||
F4E0E38422CF6B940020D754 /* SPStorkTransitioningDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkTransitioningDelegate.swift; sourceTree = "<group>"; };
|
||||
F4E0E38522CF6B940020D754 /* SPStorkPresentingAnimationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkPresentingAnimationController.swift; sourceTree = "<group>"; };
|
||||
F4E0E38622CF6B940020D754 /* SPStorkPresentationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkPresentationController.swift; sourceTree = "<group>"; };
|
||||
F4E0E38722CF6B940020D754 /* SPStorkDismissingAnimationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkDismissingAnimationController.swift; sourceTree = "<group>"; };
|
||||
F4E0E38922CF6B940020D754 /* SPStorkViewControllerExtenshion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkViewControllerExtenshion.swift; sourceTree = "<group>"; };
|
||||
F4E0E38B22CF6B940020D754 /* SPStorkCloseButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkCloseButton.swift; sourceTree = "<group>"; };
|
||||
F4E0E38C22CF6B940020D754 /* SPStorkIndicatorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkIndicatorView.swift; sourceTree = "<group>"; };
|
||||
F4E0E38D22CF6B940020D754 /* SPStorkCloseView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkCloseView.swift; sourceTree = "<group>"; };
|
||||
F4E0E38F22CF6B940020D754 /* SPStorkControllerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkControllerDelegate.swift; sourceTree = "<group>"; };
|
||||
F4F33BE522802AB000199EBE /* SPFakeBarView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPFakeBarView.swift; sourceTree = "<group>"; };
|
||||
F4F33BE622802AB000199EBE /* SPFakeBarNavigationStyle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPFakeBarNavigationStyle.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
@@ -340,8 +346,8 @@
|
||||
F445CA9821AED98500184254 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F4E0E37C22CF6B940020D754 /* SPStorkController */,
|
||||
F4F33BE422802AB000199EBE /* SPFakeBar */,
|
||||
F4F33BC522802AA100199EBE /* SPStorkController */,
|
||||
F4DB83F322609C03005082AA /* SparrowKit */,
|
||||
);
|
||||
path = Frameworks;
|
||||
@@ -810,69 +816,72 @@
|
||||
path = Share;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F4F33BC522802AA100199EBE /* SPStorkController */ = {
|
||||
F4E0E37C22CF6B940020D754 /* SPStorkController */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F4F33BC622802AA100199EBE /* Models */,
|
||||
F4F33BC822802AA100199EBE /* CodeDraw */,
|
||||
F4F33BCA22802AA100199EBE /* SPStorkController.swift */,
|
||||
F4F33BCB22802AA100199EBE /* TransitioningDelegate */,
|
||||
F4F33BD022802AA100199EBE /* Extenshion */,
|
||||
F4F33BD222802AA100199EBE /* Views */,
|
||||
F4F33BD622802AA100199EBE /* Protocols */,
|
||||
F4E0E37D22CF6B940020D754 /* Models */,
|
||||
F4E0E37F22CF6B940020D754 /* SPStorkSeque.swift */,
|
||||
F4E0E38022CF6B940020D754 /* CodeDraw */,
|
||||
F4E0E38222CF6B940020D754 /* SPStorkController.swift */,
|
||||
F4E0E38322CF6B940020D754 /* TransitioningDelegate */,
|
||||
F4E0E38822CF6B940020D754 /* Extenshion */,
|
||||
F4E0E38A22CF6B940020D754 /* Views */,
|
||||
F4E0E38E22CF6B940020D754 /* Protocols */,
|
||||
);
|
||||
path = SPStorkController;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F4F33BC622802AA100199EBE /* Models */ = {
|
||||
F4E0E37D22CF6B940020D754 /* Models */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F4F33BC722802AA100199EBE /* SPStorkHaptic.swift */,
|
||||
F4E0E37E22CF6B940020D754 /* SPStorkHaptic.swift */,
|
||||
F4803BF423082FDA0092C9BC /* SPStorkArrowMode.swift */,
|
||||
);
|
||||
path = Models;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F4F33BC822802AA100199EBE /* CodeDraw */ = {
|
||||
F4E0E38022CF6B940020D754 /* CodeDraw */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F4F33BC922802AA100199EBE /* SPStorkCodeDraw.swift */,
|
||||
F4E0E38122CF6B940020D754 /* SPStorkCodeDraw.swift */,
|
||||
);
|
||||
path = CodeDraw;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F4F33BCB22802AA100199EBE /* TransitioningDelegate */ = {
|
||||
F4E0E38322CF6B940020D754 /* TransitioningDelegate */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F4F33BCC22802AA100199EBE /* SPStorkTransitioningDelegate.swift */,
|
||||
F4F33BCD22802AA100199EBE /* SPStorkPresentingAnimationController.swift */,
|
||||
F4F33BCE22802AA100199EBE /* SPStorkPresentationController.swift */,
|
||||
F4F33BCF22802AA100199EBE /* SPStorkDismissingAnimationController.swift */,
|
||||
F4E0E38422CF6B940020D754 /* SPStorkTransitioningDelegate.swift */,
|
||||
F4E0E38522CF6B940020D754 /* SPStorkPresentingAnimationController.swift */,
|
||||
F4E0E38622CF6B940020D754 /* SPStorkPresentationController.swift */,
|
||||
F4E0E38722CF6B940020D754 /* SPStorkDismissingAnimationController.swift */,
|
||||
);
|
||||
path = TransitioningDelegate;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F4F33BD022802AA100199EBE /* Extenshion */ = {
|
||||
F4E0E38822CF6B940020D754 /* Extenshion */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F4F33BD122802AA100199EBE /* SPStorkViewControllerExtenshion.swift */,
|
||||
F4E0E38922CF6B940020D754 /* SPStorkViewControllerExtenshion.swift */,
|
||||
);
|
||||
path = Extenshion;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F4F33BD222802AA100199EBE /* Views */ = {
|
||||
F4E0E38A22CF6B940020D754 /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F4F33BD322802AA100199EBE /* SPStorkCloseButton.swift */,
|
||||
F4F33BD422802AA100199EBE /* SPStorkIndicatorView.swift */,
|
||||
F4F33BD522802AA100199EBE /* SPStorkCloseView.swift */,
|
||||
F4E0E38B22CF6B940020D754 /* SPStorkCloseButton.swift */,
|
||||
F4E0E38C22CF6B940020D754 /* SPStorkIndicatorView.swift */,
|
||||
F4E0E38D22CF6B940020D754 /* SPStorkCloseView.swift */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F4F33BD622802AA100199EBE /* Protocols */ = {
|
||||
F4E0E38E22CF6B940020D754 /* Protocols */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F4F33BD722802AA100199EBE /* SPStorkControllerDelegate.swift */,
|
||||
F4E0E38F22CF6B940020D754 /* SPStorkControllerDelegate.swift */,
|
||||
F437B75022D62D7700E6074C /* SPStorkControllerConfirmDelegate.swift */,
|
||||
);
|
||||
path = Protocols;
|
||||
sourceTree = "<group>";
|
||||
@@ -960,7 +969,6 @@
|
||||
F4DB84D722609C05005082AA /* SPUIImageExtension.swift in Sources */,
|
||||
F4DB84FF22609C05005082AA /* SPViber.swift in Sources */,
|
||||
F4DB84D122609C05005082AA /* SPTypes.swift in Sources */,
|
||||
F4F33BE122802AA100199EBE /* SPStorkIndicatorView.swift in Sources */,
|
||||
F4DB84FA22609C05005082AA /* SPAnimationAlpha.swift in Sources */,
|
||||
F4DB84C822609C05005082AA /* SPController.swift in Sources */,
|
||||
F4DB849B22609C05005082AA /* SPFormTextFiledTableViewCell.swift in Sources */,
|
||||
@@ -972,43 +980,48 @@
|
||||
F4DB849622609C05005082AA /* SPVibration.swift in Sources */,
|
||||
F4DB850522609C05005082AA /* SPCodeAudioIconPack.swift in Sources */,
|
||||
F4DB849922609C05005082AA /* SPFormMailTableViewCell.swift in Sources */,
|
||||
F4E0E39522CF6B940020D754 /* SPStorkPresentingAnimationController.swift in Sources */,
|
||||
F4DB850822609C05005082AA /* SPCodeDraw.swift in Sources */,
|
||||
F4DB84D622609C05005082AA /* SPUIFontExtenshion.swift in Sources */,
|
||||
F4DB84A722609C05005082AA /* SPAppleMusicSectionButtonsView.swift in Sources */,
|
||||
F4DB84FC22609C05005082AA /* SPDownloader.swift in Sources */,
|
||||
F4F33BE822802AB000199EBE /* SPFakeBarNavigationStyle.swift in Sources */,
|
||||
F4DB84CF22609C05005082AA /* SPImagesCollectionView.swift in Sources */,
|
||||
F4E0E39322CF6B940020D754 /* SPStorkController.swift in Sources */,
|
||||
F4DB84A622609C05005082AA /* SPSocialButton.swift in Sources */,
|
||||
F4DB84E022609C05005082AA /* SPUICollectionViewExtenshion.swift in Sources */,
|
||||
F4E0E39222CF6B940020D754 /* SPStorkCodeDraw.swift in Sources */,
|
||||
F4803BF523082FDA0092C9BC /* SPStorkArrowMode.swift in Sources */,
|
||||
F4DB84E222609C05005082AA /* SPUITabBarControllerExtenshion.swift in Sources */,
|
||||
F4DB84A122609C05005082AA /* SPProposeTableViewCell.swift in Sources */,
|
||||
F4E0E39922CF6B940020D754 /* SPStorkCloseButton.swift in Sources */,
|
||||
F4DB849D22609C05005082AA /* SPFormTextInputTableViewCell.swift in Sources */,
|
||||
F4DB84A222609C05005082AA /* SPBaseContentTableViewCell.swift in Sources */,
|
||||
F4DB84FD22609C05005082AA /* SPBufer.swift in Sources */,
|
||||
F4DB850622609C05005082AA /* SPCodeSocialIconPack.swift in Sources */,
|
||||
F4DB84D222609C05005082AA /* SPLocale.swift in Sources */,
|
||||
F4DB84B922609C05005082AA /* SPSeparatorView.swift in Sources */,
|
||||
F4E0E39422CF6B940020D754 /* SPStorkTransitioningDelegate.swift in Sources */,
|
||||
F4DB84A822609C05005082AA /* SPDotsButton.swift in Sources */,
|
||||
F4DB84FB22609C05005082AA /* SPAnimation.swift in Sources */,
|
||||
F4E0E39622CF6B940020D754 /* SPStorkPresentationController.swift in Sources */,
|
||||
F4DB84F722609C05005082AA /* SPShadowDeep.swift in Sources */,
|
||||
F4DB84BF22609C05005082AA /* SPCenterLabelsView.swift in Sources */,
|
||||
F4DB84C522609C05005082AA /* SPNativeTableController.swift in Sources */,
|
||||
F445CA8921AED92600184254 /* Controller.swift in Sources */,
|
||||
F4DB84AA22609C05005082AA /* SPNativeLargeButton.swift in Sources */,
|
||||
F4DB84E522609C05005082AA /* SPUILabelExtenshion.swift in Sources */,
|
||||
F4E0E39122CF6B940020D754 /* SPStorkSeque.swift in Sources */,
|
||||
F4DB84CC22609C05005082AA /* SPCollectionViewLayout.swift in Sources */,
|
||||
F4DB850022609C05005082AA /* SPTelegram.swift in Sources */,
|
||||
F4DB84A922609C05005082AA /* SPSystemIconButton.swift in Sources */,
|
||||
F4DB84DA22609C05005082AA /* SPArrayExtension.swift in Sources */,
|
||||
F4DB84BC22609C05005082AA /* SPEmptyLabelsView.swift in Sources */,
|
||||
F4F33BDE22802AA100199EBE /* SPStorkDismissingAnimationController.swift in Sources */,
|
||||
F4DB84B122609C05005082AA /* SPScrollView.swift in Sources */,
|
||||
F4DB84CB22609C05005082AA /* SPImageCollectionViewCell.swift in Sources */,
|
||||
F4DB84F322609C05005082AA /* SPLocalNotification.swift in Sources */,
|
||||
F4DB84BD22609C05005082AA /* SPSectionLabelsView.swift in Sources */,
|
||||
F4F33BD922802AA100199EBE /* SPStorkCodeDraw.swift in Sources */,
|
||||
F4DB84C222609C05005082AA /* SPSystemIconView.swift in Sources */,
|
||||
F4F33BE322802AA100199EBE /* SPStorkControllerDelegate.swift in Sources */,
|
||||
F4DB84C922609C05005082AA /* SPCollectionViewCell.swift in Sources */,
|
||||
F4DB84E322609C05005082AA /* SPUINavigationControllerExtenshion.swift in Sources */,
|
||||
F4DB84B822609C05005082AA /* SPGradientView.swift in Sources */,
|
||||
@@ -1021,6 +1034,7 @@
|
||||
F4DB84E122609C05005082AA /* SPTextFieldExtenshion.swift in Sources */,
|
||||
F4DB84B622609C05005082AA /* SPDownloadingUIImageView.swift in Sources */,
|
||||
F4DB849E22609C05005082AA /* SPFormTextTableViewCell.swift in Sources */,
|
||||
F4E0E39A22CF6B940020D754 /* SPStorkIndicatorView.swift in Sources */,
|
||||
F4DB84C622609C05005082AA /* SPTableController.swift in Sources */,
|
||||
F4DB84C122609C05005082AA /* SPSocialIconView.swift in Sources */,
|
||||
F4DB84C022609C05005082AA /* SPAudioIconView.swift in Sources */,
|
||||
@@ -1034,31 +1048,30 @@
|
||||
F4DB84D822609C05005082AA /* SPUITableView.swift in Sources */,
|
||||
F4DB84EA22609C05005082AA /* SPUIButtonExtenshion.swift in Sources */,
|
||||
F459D75D21C3ABBD00798524 /* ModalTableViewController.swift in Sources */,
|
||||
F4F33BE022802AA100199EBE /* SPStorkCloseButton.swift in Sources */,
|
||||
F4DB850922609C05005082AA /* SPGolubevGolubevIconPack.swift in Sources */,
|
||||
F4DB84BA22609C05005082AA /* SPVideoPlayer.swift in Sources */,
|
||||
F4DB84A322609C05005082AA /* SPTableViewCell.swift in Sources */,
|
||||
F4DB849F22609C05005082AA /* SPMengTransformTableViewCell.swift in Sources */,
|
||||
F4DB849C22609C05005082AA /* SPFormFeaturedTitleTableViewCell.swift in Sources */,
|
||||
F4DB84ED22609C05005082AA /* SPAppBadge.swift in Sources */,
|
||||
F4E0E39722CF6B940020D754 /* SPStorkDismissingAnimationController.swift in Sources */,
|
||||
F4DB84F422609C05005082AA /* SPMail.swift in Sources */,
|
||||
F4DB84EF22609C05005082AA /* SPNativeColors.swift in Sources */,
|
||||
F4DB850B22609C05005082AA /* SPRandom.swift in Sources */,
|
||||
F4DB84B422609C05005082AA /* SPTextView.swift in Sources */,
|
||||
F4DB84F022609C05005082AA /* SPConstraints.swift in Sources */,
|
||||
F4F33BDC22802AA100199EBE /* SPStorkPresentingAnimationController.swift in Sources */,
|
||||
F4DB84B022609C05005082AA /* SPImageView.swift in Sources */,
|
||||
F4DB84D922609C05005082AA /* SPUIViewExtenshion.swift in Sources */,
|
||||
F4F33BDA22802AA100199EBE /* SPStorkController.swift in Sources */,
|
||||
F4DB850122609C05005082AA /* SPInstagram.swift in Sources */,
|
||||
F4DB84E922609C05005082AA /* SPUIColorExtension.swift in Sources */,
|
||||
F4DB84D022609C05005082AA /* SPPageCollectionView.swift in Sources */,
|
||||
F4DB84D522609C05005082AA /* SPUITextFieldExtenshion.swift in Sources */,
|
||||
F4DB849822609C05005082AA /* SPFormButtonTableViewCell.swift in Sources */,
|
||||
F4F33BD822802AA100199EBE /* SPStorkHaptic.swift in Sources */,
|
||||
F4E0E39022CF6B940020D754 /* SPStorkHaptic.swift in Sources */,
|
||||
F4DB84CD22609C05005082AA /* SPMengTransformCollectionView.swift in Sources */,
|
||||
F445CA8721AED92600184254 /* AppDelegate.swift in Sources */,
|
||||
F4DB84A422609C05005082AA /* SPTableView.swift in Sources */,
|
||||
F4E0E39822CF6B940020D754 /* SPStorkViewControllerExtenshion.swift in Sources */,
|
||||
F4DB850D22609C05005082AA /* SPShare.swift in Sources */,
|
||||
F459D75B21C3AB9A00798524 /* ModalViewController.swift in Sources */,
|
||||
F4DB84C722609C05005082AA /* SPStatusBarManagerController.swift in Sources */,
|
||||
@@ -1070,25 +1083,24 @@
|
||||
F4DB84BE22609C05005082AA /* SPLabel.swift in Sources */,
|
||||
F4DB84E822609C05005082AA /* SPUIImageViewExtenshion.swift in Sources */,
|
||||
F4DB84D422609C05005082AA /* SPUITableViewCellExtenshion.swift in Sources */,
|
||||
F4E0E39B22CF6B940020D754 /* SPStorkCloseView.swift in Sources */,
|
||||
F4DB84AB22609C05005082AA /* SPDownloadingButton.swift in Sources */,
|
||||
F4F33BDB22802AA100199EBE /* SPStorkTransitioningDelegate.swift in Sources */,
|
||||
F4F33BE722802AB000199EBE /* SPFakeBarView.swift in Sources */,
|
||||
F4DB84B522609C05005082AA /* SPGradeBlurView.swift in Sources */,
|
||||
F4DB84DD22609C05005082AA /* SPStringExtenshion.swift in Sources */,
|
||||
F4DB84A522609C05005082AA /* SPPlayCircleButton.swift in Sources */,
|
||||
F4DB84FE22609C05005082AA /* SPTwitter.swift in Sources */,
|
||||
F4F33BDD22802AA100199EBE /* SPStorkPresentationController.swift in Sources */,
|
||||
F4DB84DB22609C05005082AA /* SPUserDefaultsExtenshion.swift in Sources */,
|
||||
F4DB849A22609C05005082AA /* SPFormLabelTableViewCell.swift in Sources */,
|
||||
F4DB84AD22609C05005082AA /* SPCircleCloseButton.swift in Sources */,
|
||||
F437B75122D62D7700E6074C /* SPStorkControllerConfirmDelegate.swift in Sources */,
|
||||
F4DB84AE22609C05005082AA /* SPAppStoreActionButton.swift in Sources */,
|
||||
F4F33BDF22802AA100199EBE /* SPStorkViewControllerExtenshion.swift in Sources */,
|
||||
F4E0E39C22CF6B940020D754 /* SPStorkControllerDelegate.swift in Sources */,
|
||||
F4DB84BB22609C05005082AA /* SPBlurView.swift in Sources */,
|
||||
F4DB850A22609C05005082AA /* SPDevice.swift in Sources */,
|
||||
F4DB84B322609C05005082AA /* SPTextField.swift in Sources */,
|
||||
F4DB84F122609C05005082AA /* SPLocalAuthentication.swift in Sources */,
|
||||
F4DB84DE22609C05005082AA /* SPStrideableExtension.swift in Sources */,
|
||||
F4F33BE222802AA100199EBE /* SPStorkCloseView.swift in Sources */,
|
||||
F4DB84F922609C05005082AA /* SPAnimationSpring.swift in Sources */,
|
||||
F4DB84E722609C05005082AA /* SPCGSizeExtenshion.swift in Sources */,
|
||||
F4DB84F522609C05005082AA /* SPLayout.swift in Sources */,
|
||||
|
||||
@@ -14,28 +14,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
return true
|
||||
}
|
||||
|
||||
func applicationWillResignActive(_ application: UIApplication) {
|
||||
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
|
||||
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
|
||||
}
|
||||
|
||||
func applicationDidEnterBackground(_ application: UIApplication) {
|
||||
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
|
||||
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
|
||||
}
|
||||
|
||||
func applicationWillEnterForeground(_ application: UIApplication) {
|
||||
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
|
||||
}
|
||||
|
||||
func applicationDidBecomeActive(_ application: UIApplication) {
|
||||
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
|
||||
}
|
||||
|
||||
func applicationWillTerminate(_ application: UIApplication) {
|
||||
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
|
||||
}
|
||||
|
||||
func launch(rootViewController: UIViewController) {
|
||||
let frame = UIScreen.main.bounds
|
||||
self.window = UIWindow(frame: frame)
|
||||
|
||||
@@ -1,93 +1,111 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "20x20",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon_20pt@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "20x20",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon_20pt@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon_29pt@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "29x29",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon_29pt@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon_40pt@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "40x40",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon_40pt@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon_60pt@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "iphone",
|
||||
"size" : "60x60",
|
||||
"idiom" : "iphone",
|
||||
"filename" : "icon_60pt@3x.png",
|
||||
"scale" : "3x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "20x20",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon_20pt.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "20x20",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon_20pt@2x-1.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "29x29",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon_29pt.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "29x29",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon_29pt@2x-1.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "40x40",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon_40pt.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "40x40",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon_40pt@2x-1.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon_76pt.png",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "76x76",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon_76pt@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ipad",
|
||||
"size" : "83.5x83.5",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "icon_83.5@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "ios-marketing",
|
||||
"size" : "1024x1024",
|
||||
"idiom" : "ios-marketing",
|
||||
"filename" : "Icon.png",
|
||||
"scale" : "1x"
|
||||
}
|
||||
],
|
||||
|
||||
|
After Width: | Height: | Size: 483 KiB |
|
After Width: | Height: | Size: 685 B |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 4.8 KiB |
|
After Width: | Height: | Size: 9.3 KiB |
|
After Width: | Height: | Size: 9.3 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 4.3 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 16 KiB |
@@ -28,6 +28,8 @@ class Controller: UIViewController {
|
||||
@objc func presentModalViewController() {
|
||||
let modal = ModalViewController()
|
||||
let transitionDelegate = SPStorkTransitioningDelegate()
|
||||
transitionDelegate.storkDelegate = self
|
||||
transitionDelegate.confirmDelegate = modal
|
||||
modal.transitioningDelegate = transitionDelegate
|
||||
modal.modalPresentationStyle = .custom
|
||||
self.present(modal, animated: true, completion: nil)
|
||||
@@ -36,8 +38,21 @@ class Controller: UIViewController {
|
||||
@objc func presentModalTableViewController() {
|
||||
let modal = ModalTableViewController()
|
||||
let transitionDelegate = SPStorkTransitioningDelegate()
|
||||
transitionDelegate.storkDelegate = self
|
||||
transitionDelegate.confirmDelegate = modal
|
||||
modal.transitioningDelegate = transitionDelegate
|
||||
modal.modalPresentationStyle = .custom
|
||||
self.present(modal, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
extension Controller: SPStorkControllerDelegate {
|
||||
|
||||
func didDismissStorkByTap() {
|
||||
print("SPStorkControllerDelegate - didDismissStorkByTap")
|
||||
}
|
||||
|
||||
func didDismissStorkBySwipe() {
|
||||
print("SPStorkControllerDelegate - didDismissStorkBySwipe")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,12 +38,11 @@ extension UIViewController {
|
||||
self.present(controller, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
public func presentAsStork(_ controller: UIViewController, height: CGFloat?, showIndicator: Bool, hideIndicatorWhenScroll: Bool, showCloseButton: Bool, complection: (() -> Void)?) {
|
||||
public func presentAsStork(_ controller: UIViewController, height: CGFloat?, showIndicator: Bool, showCloseButton: Bool, complection: (() -> Void)? = nil) {
|
||||
let transitionDelegate = SPStorkTransitioningDelegate()
|
||||
transitionDelegate.customHeight = height
|
||||
transitionDelegate.showCloseButton = showCloseButton
|
||||
transitionDelegate.showIndicator = showIndicator
|
||||
transitionDelegate.hideIndicatorWhenScroll = hideIndicatorWhenScroll
|
||||
controller.transitioningDelegate = transitionDelegate
|
||||
controller.modalPresentationStyle = .custom
|
||||
controller.modalPresentationCapturesStatusBarAppearance = true
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// The MIT License (MIT)
|
||||
// Copyright © 2017 Ivan Vorobei (hello@ivanvorobei.by)
|
||||
//
|
||||
// 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.
|
||||
|
||||
import UIKit
|
||||
|
||||
public enum SPStorkArrowMode {
|
||||
|
||||
case auto
|
||||
case alwaysArrow
|
||||
case alwaysLine
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// The MIT License (MIT)
|
||||
// Copyright © 2017 Ivan Vorobei (hello@ivanvorobei.by)
|
||||
//
|
||||
// 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.
|
||||
|
||||
import UIKit
|
||||
|
||||
@objc public protocol SPStorkControllerConfirmDelegate: class {
|
||||
|
||||
var needConfirm: Bool { get }
|
||||
|
||||
func confirm(_ completion: @escaping (_ isConfirmed: Bool)->())
|
||||
}
|
||||
@@ -21,11 +21,11 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
public struct SPStorkController {
|
||||
public enum SPStorkController {
|
||||
|
||||
static public func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||
if let controller = self.controller(for: scrollView) {
|
||||
if let presentationController = controller.presentationController as? SPStorkPresentationController {
|
||||
if let presentationController = self.presentationController(for: controller) {
|
||||
let translation = -(scrollView.contentOffset.y + scrollView.contentInset.top)
|
||||
if translation >= 0 {
|
||||
if controller.isBeingPresented { return }
|
||||
@@ -35,7 +35,7 @@ public struct SPStorkController {
|
||||
presentationController.setIndicator(style: scrollView.isTracking ? .line : .arrow)
|
||||
if translation >= presentationController.translateForDismiss * 0.4 {
|
||||
if !scrollView.isTracking && !scrollView.isDragging {
|
||||
presentationController.presentedViewController.dismiss(animated: true, completion: {
|
||||
self.dismissWithConfirmation(controller: controller, completion: {
|
||||
presentationController.storkDelegate?.didDismissStorkBySwipe?()
|
||||
})
|
||||
return
|
||||
@@ -58,6 +58,14 @@ public struct SPStorkController {
|
||||
}
|
||||
}
|
||||
|
||||
static public func dismissWithConfirmation(controller: UIViewController, completion: (()->())?) {
|
||||
if let controller = self.presentationController(for: controller) {
|
||||
controller.dismissWithConfirmation(prepare: nil, completion: {
|
||||
completion?()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
static public var topScrollIndicatorInset: CGFloat {
|
||||
return 6
|
||||
}
|
||||
@@ -74,6 +82,19 @@ public struct SPStorkController {
|
||||
}
|
||||
}
|
||||
|
||||
static private func presentationController(for controller: UIViewController) -> SPStorkPresentationController? {
|
||||
guard controller.modalPresentationStyle == .custom else { return nil }
|
||||
|
||||
if let presentationController = controller.presentationController as? SPStorkPresentationController {
|
||||
return presentationController
|
||||
}
|
||||
|
||||
if let presentationController = controller.parent?.presentationController as? SPStorkPresentationController {
|
||||
return presentationController
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
static private func controller(for view: UIView) -> UIViewController? {
|
||||
var nextResponder = view.next
|
||||
while nextResponder != nil && !(nextResponder! is UIViewController) {
|
||||
@@ -81,6 +102,4 @@ public struct SPStorkController {
|
||||
}
|
||||
return nextResponder as? UIViewController
|
||||
}
|
||||
|
||||
private init() {}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
// The MIT License (MIT)
|
||||
// Copyright © 2017 Ivan Vorobei (hello@ivanvorobei.by)
|
||||
//
|
||||
// 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.
|
||||
|
||||
import UIKit
|
||||
|
||||
public class SPStorkSegue: UIStoryboardSegue {
|
||||
|
||||
public var transitioningDelegate: SPStorkTransitioningDelegate?
|
||||
|
||||
override public func perform() {
|
||||
transitioningDelegate = transitioningDelegate ?? SPStorkTransitioningDelegate()
|
||||
destination.transitioningDelegate = transitioningDelegate
|
||||
destination.modalPresentationStyle = .custom
|
||||
super.perform()
|
||||
}
|
||||
}
|
||||
@@ -29,12 +29,14 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
|
||||
var showIndicator: Bool = true
|
||||
var indicatorColor: UIColor = UIColor.init(red: 202/255, green: 201/255, blue: 207/255, alpha: 1)
|
||||
var hideIndicatorWhenScroll: Bool = false
|
||||
var indicatorMode: SPStorkArrowMode = .auto
|
||||
var customHeight: CGFloat? = nil
|
||||
var translateForDismiss: CGFloat = 200
|
||||
var hapticMoments: [SPStorkHapticMoments] = [.willDismissIfRelease]
|
||||
|
||||
var transitioningDelegate: SPStorkTransitioningDelegate?
|
||||
weak var storkDelegate: SPStorkControllerDelegate?
|
||||
weak var confirmDelegate: SPStorkControllerConfirmDelegate?
|
||||
|
||||
var pan: UIPanGestureRecognizer?
|
||||
var tap: UITapGestureRecognizer?
|
||||
@@ -50,6 +52,7 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
|
||||
private var snapshotViewWidthConstraint: NSLayoutConstraint?
|
||||
private var snapshotViewAspectRatioConstraint: NSLayoutConstraint?
|
||||
|
||||
var workConfirmation: Bool = false
|
||||
private var workGester: Bool = false
|
||||
private var startDismissing: Bool = false
|
||||
private var afterReleaseDismissing: Bool = false
|
||||
@@ -64,11 +67,19 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
|
||||
|
||||
private var scaleForPresentingView: CGFloat {
|
||||
guard let containerView = containerView else { return 0 }
|
||||
let factor = 1 - ((self.cornerRadius + 2) * 2 / containerView.frame.width)
|
||||
let factor = 1 - ((self.cornerRadius + 3) * 2 / containerView.frame.width)
|
||||
return factor
|
||||
}
|
||||
|
||||
private var feedbackGenerator: UIImpactFeedbackGenerator = UIImpactFeedbackGenerator(style: .light)
|
||||
private var feedbackGenerator = UIImpactFeedbackGenerator(style: .light)
|
||||
|
||||
override var presentedView: UIView? {
|
||||
let view = self.presentedViewController.view
|
||||
if view?.frame.origin == CGPoint.zero {
|
||||
view?.frame = self.frameOfPresentedViewInContainerView
|
||||
}
|
||||
return view
|
||||
}
|
||||
|
||||
override var frameOfPresentedViewInContainerView: CGRect {
|
||||
guard let containerView = containerView else { return .zero }
|
||||
@@ -95,19 +106,43 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
|
||||
|
||||
guard let containerView = self.containerView, let presentedView = self.presentedView, let window = containerView.window else { return }
|
||||
|
||||
let closeTitle = NSLocalizedString("Close", comment: "Close")
|
||||
|
||||
if self.showIndicator {
|
||||
self.indicatorView.color = self.indicatorColor
|
||||
let tap = UITapGestureRecognizer.init(target: self, action: #selector(self.dismissAction))
|
||||
let tap = UITapGestureRecognizer.init(target: self, action: #selector(self.tapIndicator))
|
||||
tap.cancelsTouchesInView = false
|
||||
self.indicatorView.addGestureRecognizer(tap)
|
||||
self.indicatorView.accessibilityLabel = closeTitle
|
||||
presentedView.addSubview(self.indicatorView)
|
||||
self.indicatorView.translatesAutoresizingMaskIntoConstraints = false
|
||||
self.indicatorView.widthAnchor.constraint(equalToConstant: 36).isActive = true
|
||||
self.indicatorView.heightAnchor.constraint(equalToConstant: 13).isActive = true
|
||||
self.indicatorView.centerXAnchor.constraint(equalTo: presentedView.centerXAnchor).isActive = true
|
||||
self.indicatorView.topAnchor.constraint(equalTo: presentedView.topAnchor, constant: 12).isActive = true
|
||||
self.indicatorView.mode = self.indicatorMode
|
||||
|
||||
if UIAccessibility.isVoiceOverRunning {
|
||||
let accessibleIndicatorOverlayButton = UIButton(type: .custom)
|
||||
accessibleIndicatorOverlayButton.addTarget(self, action: #selector(self.tapIndicator), for: .touchUpInside)
|
||||
accessibleIndicatorOverlayButton.accessibilityLabel = closeTitle
|
||||
presentedView.addSubview(accessibleIndicatorOverlayButton)
|
||||
accessibleIndicatorOverlayButton.translatesAutoresizingMaskIntoConstraints = false
|
||||
NSLayoutConstraint.activate([
|
||||
accessibleIndicatorOverlayButton.leadingAnchor.constraint(equalTo: presentedView.leadingAnchor),
|
||||
accessibleIndicatorOverlayButton.trailingAnchor.constraint(equalTo: presentedView.trailingAnchor),
|
||||
accessibleIndicatorOverlayButton.topAnchor.constraint(equalTo: presentedView.topAnchor),
|
||||
accessibleIndicatorOverlayButton.bottomAnchor.constraint(equalTo: self.indicatorView.bottomAnchor),
|
||||
])
|
||||
}
|
||||
}
|
||||
self.updateLayoutIndicator()
|
||||
self.indicatorView.style = .arrow
|
||||
self.gradeView.alpha = 0
|
||||
|
||||
|
||||
self.closeButton.accessibilityLabel = closeTitle
|
||||
if self.showCloseButton {
|
||||
self.closeButton.addTarget(self, action: #selector(self.dismissAction), for: .touchUpInside)
|
||||
self.closeButton.addTarget(self, action: #selector(self.tapCloseButton), for: .touchUpInside)
|
||||
presentedView.addSubview(self.closeButton)
|
||||
}
|
||||
self.updateLayoutCloseButton()
|
||||
@@ -194,7 +229,7 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
|
||||
self.updateSnapshotAspectRatio()
|
||||
|
||||
if self.tapAroundToDismissEnabled {
|
||||
self.tap = UITapGestureRecognizer.init(target: self, action: #selector(self.dismissAction))
|
||||
self.tap = UITapGestureRecognizer.init(target: self, action: #selector(self.tapArround))
|
||||
self.tap?.cancelsTouchesInView = false
|
||||
self.snapshotViewContainer.addGestureRecognizer(self.tap!)
|
||||
}
|
||||
@@ -208,21 +243,13 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
|
||||
}
|
||||
}
|
||||
|
||||
@objc func dismissAction() {
|
||||
self.presentingViewController.view.endEditing(true)
|
||||
self.presentedViewController.view.endEditing(true)
|
||||
self.presentedViewController.dismiss(animated: true, completion: {
|
||||
self.storkDelegate?.didDismissStorkByTap?()
|
||||
})
|
||||
}
|
||||
|
||||
override func dismissalTransitionWillBegin() {
|
||||
super.dismissalTransitionWillBegin()
|
||||
guard let containerView = containerView else { return }
|
||||
self.startDismissing = true
|
||||
|
||||
let initialFrame: CGRect = presentingViewController.isPresentedAsStork ? presentingViewController.view.frame : containerView.bounds
|
||||
|
||||
|
||||
let initialTransform = CGAffineTransform.identity
|
||||
.translatedBy(x: 0, y: -initialFrame.origin.y)
|
||||
.translatedBy(x: 0, y: self.topSpace)
|
||||
@@ -299,6 +326,56 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
|
||||
|
||||
extension SPStorkPresentationController {
|
||||
|
||||
@objc func tapIndicator() {
|
||||
self.dismissWithConfirmation(prepare: nil, completion: {
|
||||
self.storkDelegate?.didDismissStorkByTap?()
|
||||
})
|
||||
}
|
||||
|
||||
@objc func tapArround() {
|
||||
self.dismissWithConfirmation(prepare: nil, completion: {
|
||||
self.storkDelegate?.didDismissStorkByTap?()
|
||||
})
|
||||
}
|
||||
|
||||
@objc func tapCloseButton() {
|
||||
self.dismissWithConfirmation(prepare: nil, completion: {
|
||||
self.storkDelegate?.didDismissStorkByTap?()
|
||||
})
|
||||
}
|
||||
|
||||
public func dismissWithConfirmation(prepare: (()->())?, completion: (()->())?) {
|
||||
|
||||
let dismiss = {
|
||||
self.presentingViewController.view.endEditing(true)
|
||||
self.presentedViewController.view.endEditing(true)
|
||||
self.presentedViewController.dismiss(animated: true, completion: {
|
||||
completion?()
|
||||
})
|
||||
}
|
||||
|
||||
guard let confirmDelegate = self.confirmDelegate else {
|
||||
dismiss()
|
||||
return
|
||||
}
|
||||
|
||||
if self.workConfirmation { return }
|
||||
|
||||
if confirmDelegate.needConfirm {
|
||||
prepare?()
|
||||
self.workConfirmation = true
|
||||
confirmDelegate.confirm({ (isConfirmed) in
|
||||
self.workConfirmation = false
|
||||
self.afterReleaseDismissing = false
|
||||
if isConfirmed {
|
||||
dismiss()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
@objc func handlePan(gestureRecognizer: UIPanGestureRecognizer) {
|
||||
guard gestureRecognizer.isEqual(self.pan), self.swipeToDismissEnabled else { return }
|
||||
|
||||
@@ -321,11 +398,8 @@ extension SPStorkPresentationController {
|
||||
case .ended:
|
||||
self.workGester = false
|
||||
let translation = gestureRecognizer.translation(in: presentedView).y
|
||||
if translation >= self.translateForDismiss {
|
||||
self.presentedViewController.dismiss(animated: true, completion: {
|
||||
self.storkDelegate?.didDismissStorkBySwipe?()
|
||||
})
|
||||
} else {
|
||||
|
||||
let toDefault = {
|
||||
self.indicatorView.style = .arrow
|
||||
UIView.animate(
|
||||
withDuration: 0.6,
|
||||
@@ -339,6 +413,14 @@ extension SPStorkPresentationController {
|
||||
self.gradeView.alpha = self.alpha
|
||||
})
|
||||
}
|
||||
|
||||
if translation >= self.translateForDismiss {
|
||||
self.dismissWithConfirmation(prepare: toDefault, completion: {
|
||||
self.storkDelegate?.didDismissStorkBySwipe?()
|
||||
})
|
||||
} else {
|
||||
toDefault()
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
@@ -388,7 +470,7 @@ extension SPStorkPresentationController {
|
||||
|
||||
let elasticThreshold: CGFloat = 120
|
||||
let translationFactor: CGFloat = 1 / 2
|
||||
|
||||
|
||||
if translation >= 0 {
|
||||
let translationForModal: CGFloat = {
|
||||
if translation >= elasticThreshold {
|
||||
@@ -414,8 +496,10 @@ extension SPStorkPresentationController {
|
||||
let afterRealseDismissing = (translation >= self.translateForDismiss)
|
||||
if afterRealseDismissing != self.afterReleaseDismissing {
|
||||
self.afterReleaseDismissing = afterRealseDismissing
|
||||
if self.hapticMoments.contains(.willDismissIfRelease) {
|
||||
self.feedbackGenerator.impactOccurred()
|
||||
if !self.workConfirmation {
|
||||
if self.hapticMoments.contains(.willDismissIfRelease) {
|
||||
self.feedbackGenerator.impactOccurred()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -429,10 +513,7 @@ extension SPStorkPresentationController {
|
||||
guard let containerView = containerView else { return }
|
||||
self.updateSnapshotAspectRatio()
|
||||
if presentedViewController.view.isDescendant(of: containerView) {
|
||||
UIView.animate(withDuration: 0.1) { [weak self] in
|
||||
guard let `self` = self else { return }
|
||||
self.presentedViewController.view.frame = self.frameOfPresentedViewInContainerView
|
||||
}
|
||||
self.presentedViewController.view.frame = self.frameOfPresentedViewInContainerView
|
||||
}
|
||||
}
|
||||
|
||||
@@ -448,11 +529,9 @@ extension SPStorkPresentationController {
|
||||
}
|
||||
|
||||
private func updateLayoutIndicator() {
|
||||
guard let presentedView = self.presentedView else { return }
|
||||
self.indicatorView.style = .line
|
||||
self.indicatorView.sizeToFit()
|
||||
self.indicatorView.frame.origin.y = 12
|
||||
self.indicatorView.center.x = presentedView.frame.width / 2
|
||||
self.indicatorView.style = .arrow
|
||||
}
|
||||
|
||||
private func updateLayoutCloseButton() {
|
||||
|
||||
@@ -29,11 +29,13 @@ public final class SPStorkTransitioningDelegate: NSObject, UIViewControllerTrans
|
||||
public var showIndicator: Bool = true
|
||||
public var indicatorColor: UIColor = UIColor.init(red: 202/255, green: 201/255, blue: 207/255, alpha: 1)
|
||||
public var hideIndicatorWhenScroll: Bool = false
|
||||
public var indicatorMode: SPStorkArrowMode = .auto
|
||||
public var customHeight: CGFloat? = nil
|
||||
public var translateForDismiss: CGFloat = 200
|
||||
public var cornerRadius: CGFloat = 10
|
||||
public var hapticMoments: [SPStorkHapticMoments] = [.willDismissIfRelease]
|
||||
public weak var storkDelegate: SPStorkControllerDelegate? = nil
|
||||
public weak var confirmDelegate: SPStorkControllerConfirmDelegate? = nil
|
||||
|
||||
public func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
|
||||
let controller = SPStorkPresentationController(presentedViewController: presented, presenting: presenting)
|
||||
@@ -43,12 +45,14 @@ public final class SPStorkTransitioningDelegate: NSObject, UIViewControllerTrans
|
||||
controller.showIndicator = self.showIndicator
|
||||
controller.indicatorColor = self.indicatorColor
|
||||
controller.hideIndicatorWhenScroll = self.hideIndicatorWhenScroll
|
||||
controller.indicatorMode = self.indicatorMode
|
||||
controller.customHeight = self.customHeight
|
||||
controller.translateForDismiss = self.translateForDismiss
|
||||
controller.cornerRadius = self.cornerRadius
|
||||
controller.hapticMoments = self.hapticMoments
|
||||
controller.transitioningDelegate = self
|
||||
controller.storkDelegate = self.storkDelegate
|
||||
controller.confirmDelegate = self.confirmDelegate
|
||||
return controller
|
||||
}
|
||||
|
||||
|
||||
@@ -25,23 +25,41 @@ open class SPStorkIndicatorView: UIView {
|
||||
|
||||
var style: Style = .line {
|
||||
didSet {
|
||||
switch self.style {
|
||||
case .line:
|
||||
self.animate {
|
||||
self.leftView.transform = .identity
|
||||
self.rightView.transform = .identity
|
||||
}
|
||||
case .arrow:
|
||||
self.animate {
|
||||
let angle = CGFloat(20 * Float.pi / 180)
|
||||
self.leftView.transform = CGAffineTransform.init(rotationAngle: angle)
|
||||
self.rightView.transform = CGAffineTransform.init(rotationAngle: -angle)
|
||||
if self.mode == .auto {
|
||||
switch self.style {
|
||||
case .line:
|
||||
self.animate {
|
||||
self.leftView.transform = .identity
|
||||
self.rightView.transform = .identity
|
||||
}
|
||||
case .arrow:
|
||||
self.animate {
|
||||
let angle = CGFloat(20 * Float.pi / 180)
|
||||
self.leftView.transform = CGAffineTransform.init(rotationAngle: angle)
|
||||
self.rightView.transform = CGAffineTransform.init(rotationAngle: -angle)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if self.mode == .alwaysArrow {
|
||||
self.leftView.layer.removeAllAnimations()
|
||||
self.rightView.layer.removeAllAnimations()
|
||||
self.leftView.transform = .identity
|
||||
self.rightView.transform = .identity
|
||||
let angle = CGFloat(20 * Float.pi / 180)
|
||||
self.leftView.transform = CGAffineTransform.init(rotationAngle: angle)
|
||||
self.rightView.transform = CGAffineTransform.init(rotationAngle: -angle)
|
||||
}
|
||||
|
||||
if self.mode == .alwaysLine {
|
||||
self.leftView.transform = .identity
|
||||
self.rightView.transform = .identity
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var mode: SPStorkArrowMode = .auto
|
||||
|
||||
var color: UIColor = UIColor.init(red: 202/255, green: 201/255, blue: 207/255, alpha: 1) {
|
||||
didSet {
|
||||
self.leftView.backgroundColor = self.color
|
||||
@@ -66,6 +84,10 @@ open class SPStorkIndicatorView: UIView {
|
||||
|
||||
override open func sizeToFit() {
|
||||
super.sizeToFit()
|
||||
|
||||
self.leftView.transform = .identity
|
||||
self.rightView.transform = .identity
|
||||
|
||||
self.frame = CGRect.init(x: self.frame.origin.x, y: self.frame.origin.y, width: 36, height: 13)
|
||||
|
||||
let height: CGFloat = 5
|
||||
|
||||
@@ -20,9 +20,8 @@
|
||||
// SOFTWARE.
|
||||
|
||||
import UIKit
|
||||
import StoreKit
|
||||
|
||||
struct SPApp {
|
||||
enum SPApp {
|
||||
|
||||
static var udid: String? {
|
||||
return UIDevice.current.identifierForVendor?.uuidString
|
||||
@@ -71,6 +70,4 @@ struct SPApp {
|
||||
UITabBarController.elementsColor = elementsColor
|
||||
UITabBar.appearance().tintColor = elementsColor
|
||||
}
|
||||
|
||||
private init() {}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ import UIKit
|
||||
|
||||
extension SPApp {
|
||||
|
||||
struct Launch {
|
||||
enum Launch {
|
||||
|
||||
static func run() {
|
||||
self.count += 1
|
||||
@@ -44,7 +44,5 @@ extension SPApp {
|
||||
static var dateFirstLaunch: Date {
|
||||
return ((UserDefaults.standard.object(forKey: "SPDateFirstLaunch") as? Date) ?? Date())
|
||||
}
|
||||
|
||||
private init() {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,21 +63,23 @@ extension SPApp {
|
||||
}
|
||||
}
|
||||
|
||||
static func open(link: String, redirect: Bool) {
|
||||
static func open(link: String) {
|
||||
|
||||
guard let url = URL(string: link) else {
|
||||
print("SPOpener - can not create URL")
|
||||
return
|
||||
}
|
||||
|
||||
if redirect {
|
||||
UIApplication.shared.open(url, options: convertToUIApplicationOpenExternalURLOptionsKeyDictionary([:]), completionHandler: nil)
|
||||
} else {
|
||||
if let rootController = SPApp.rootController {
|
||||
let safariController = SFSafariViewController.init(url: url)
|
||||
rootController.present(safariController, animated: true, completion: nil)
|
||||
}
|
||||
UIApplication.shared.open(url, options: convertToUIApplicationOpenExternalURLOptionsKeyDictionary([:]), completionHandler: nil)
|
||||
}
|
||||
|
||||
static func open(link: String, on controller: UIViewController) {
|
||||
guard let url = URL(string: link) else {
|
||||
print("SPOpener - can not create URL")
|
||||
return
|
||||
}
|
||||
let safariController = SFSafariViewController.init(url: url)
|
||||
controller.present(safariController, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ import StoreKit
|
||||
struct SPAppStore {
|
||||
|
||||
static func link(appID: String) -> String {
|
||||
return "https://itunes.apple.com/by/app/id" + appID
|
||||
return "https://itunes.apple.com/app/id" + appID
|
||||
}
|
||||
|
||||
static func open(app id: String) {
|
||||
|
||||
@@ -27,7 +27,7 @@ class SPAudioPlayer: NSObject, AVAudioPlayerDelegate {
|
||||
fileprivate var player: AVAudioPlayer = AVAudioPlayer()
|
||||
fileprivate var endPlayingComplection: (()->())? = nil
|
||||
|
||||
func play(fileName: String, complection: (()->())? = nil) {
|
||||
func play(fileName: String, complection: (()->())? = nil, volume: Float = 1) {
|
||||
self.endPlayingComplection?()
|
||||
self.player = AVAudioPlayer()
|
||||
let url = Bundle.main.url(forResource: fileName, withExtension: nil)
|
||||
@@ -37,7 +37,7 @@ class SPAudioPlayer: NSObject, AVAudioPlayerDelegate {
|
||||
}
|
||||
do {
|
||||
self.player = try AVAudioPlayer(contentsOf: url!)
|
||||
player.volume = 1
|
||||
player.volume = volume
|
||||
player.delegate = self
|
||||
player.prepareToPlay()
|
||||
player.play()
|
||||
|
||||
@@ -29,9 +29,9 @@ extension Date {
|
||||
return dateFormatter.string(from: self)
|
||||
}
|
||||
|
||||
static func create(from value: String) -> Date? {
|
||||
static func create(from value: String, mask: String = "dd.MM.yyyy HH:mm") -> Date? {
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateFormat = "dd.MM.yyyy HH:mm"
|
||||
formatter.dateFormat = mask
|
||||
let date = formatter.date(from: value)
|
||||
return date
|
||||
}
|
||||
|
||||
@@ -32,19 +32,21 @@ extension UIAlertController {
|
||||
}
|
||||
}
|
||||
|
||||
static func show(title: String, message: String, buttonTitle: String, cancelButtonTitle: String? = nil, complection: @escaping ()->() = {}, on viewController: UIViewController) {
|
||||
|
||||
static func show(title: String? = nil, message: String? = nil, buttonTitle: String, cancelButtonTitle: String? = nil, complection: @escaping ()->() = {}, on viewController: UIViewController) {
|
||||
let ac = UIAlertController(
|
||||
title: title,
|
||||
message: message,
|
||||
preferredStyle: .alert
|
||||
)
|
||||
|
||||
guard cancelButtonTitle != nil else { return }
|
||||
ac.addAction(UIAlertAction.init(
|
||||
title: cancelButtonTitle!,
|
||||
style: UIAlertAction.Style.cancel,
|
||||
handler: nil)
|
||||
)
|
||||
if let cancelTitle = cancelButtonTitle {
|
||||
ac.addAction(UIAlertAction.init(
|
||||
title: cancelTitle,
|
||||
style: UIAlertAction.Style.cancel,
|
||||
handler: nil)
|
||||
)
|
||||
}
|
||||
|
||||
ac.addAction(UIAlertAction.init(
|
||||
title: buttonTitle,
|
||||
@@ -56,7 +58,7 @@ extension UIAlertController {
|
||||
viewController.present(ac, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
static func сonfirm(title: String? = nil, message: String, buttonTitle: String, cancelButtonTitle: String, isDestructive: Bool = false, complection: @escaping (Bool)->(), on viewController: UIViewController) {
|
||||
static func сonfirm(title: String? = nil, message: String? = nil, buttonTitle: String, cancelButtonTitle: String, isDestructive: Bool = false, complection: @escaping (Bool)->(), on viewController: UIViewController) {
|
||||
let ac = UIAlertController(
|
||||
title: title,
|
||||
message: message,
|
||||
|
||||
@@ -62,7 +62,7 @@ extension UILabel {
|
||||
paragraphStyle.lineSpacing = lineSpacing
|
||||
paragraphStyle.lineHeightMultiple = lineHeightMultiple
|
||||
|
||||
let attributedString:NSMutableAttributedString
|
||||
let attributedString: NSMutableAttributedString
|
||||
if let labelattributedText = self.attributedText {
|
||||
attributedString = NSMutableAttributedString(attributedString: labelattributedText)
|
||||
} else {
|
||||
@@ -74,15 +74,16 @@ extension UILabel {
|
||||
self.attributedText = attributedString
|
||||
}
|
||||
|
||||
func setFormat(text: String, positions: [(start: Int, length: Int)], hithiglightFont: UIFont, higlightColor: UIColor) {
|
||||
func setFormat(text: String, positions: [FormatPosition], font: UIFont, textColor: UIColor, backgroundColor: UIColor = .clear) {
|
||||
|
||||
let title = NSMutableAttributedString.init(string: text)
|
||||
|
||||
for position in positions {
|
||||
title.addAttributes(
|
||||
[
|
||||
NSAttributedString.Key.foregroundColor : higlightColor,
|
||||
NSAttributedString.Key.font : hithiglightFont
|
||||
NSAttributedString.Key.backgroundColor : backgroundColor,
|
||||
NSAttributedString.Key.foregroundColor : textColor,
|
||||
NSAttributedString.Key.font : font
|
||||
],
|
||||
range: NSRange.init(location: position.start, length: position.length)
|
||||
)
|
||||
@@ -90,4 +91,10 @@ extension UILabel {
|
||||
|
||||
self.attributedText = title
|
||||
}
|
||||
|
||||
struct FormatPosition {
|
||||
|
||||
var start: Int
|
||||
var length: Int
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// The MIT License (MIT)
|
||||
// Copyright © 2017 Ivan Vorobei (hello@ivanvorobei.by)
|
||||
//
|
||||
// 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.
|
||||
|
||||
import UIKit
|
||||
|
||||
extension UIScrollView {
|
||||
|
||||
func stopScrolling() {
|
||||
self.setContentOffset(self.contentOffset, animated: false)
|
||||
}
|
||||
}
|
||||
@@ -23,10 +23,25 @@ import UIKit
|
||||
|
||||
extension UIView {
|
||||
|
||||
var controller: UIViewController? {
|
||||
var isDarkMode: Bool {
|
||||
if #available(iOS 12.0, *) {
|
||||
if self.traitCollection.userInterfaceStyle == .dark {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension UIView {
|
||||
|
||||
var viewController: UIViewController? {
|
||||
get {
|
||||
if let nextResponder = self.next as? UIViewController { return nextResponder }
|
||||
else if let nextResponder = self.next as? UIView { return nextResponder.controller }
|
||||
else if let nextResponder = self.next as? UIView { return nextResponder.viewController }
|
||||
else { return nil }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,32 +27,13 @@ struct SPLocalAuthentication {
|
||||
static var isEnable: Bool {
|
||||
let context = LAContext()
|
||||
var error: NSError?
|
||||
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
|
||||
return true
|
||||
} else {
|
||||
if context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error)
|
||||
}
|
||||
|
||||
static func request(reason: String, complecton: @escaping (Bool)->()) {
|
||||
let context = LAContext()
|
||||
var error: NSError?
|
||||
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
|
||||
context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: reason) { success, error in
|
||||
DispatchQueue.main.async { complecton(success) }
|
||||
}
|
||||
} else {
|
||||
if context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) {
|
||||
context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: reason) { success, error in
|
||||
DispatchQueue.main.async { complecton(success) }
|
||||
}
|
||||
} else {
|
||||
complecton(false)
|
||||
}
|
||||
context.evaluatePolicy(.deviceOwnerAuthentication, localizedReason: reason) { success, error in
|
||||
DispatchQueue.main.async { complecton(success) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ struct SPLocalNotification {
|
||||
|
||||
if let category = self.category {
|
||||
if #available(iOS 12.0, *) {
|
||||
let notificationCategory = UNNotificationCategory(identifier: category.identifier, actions: [], intentIdentifiers: [], hiddenPreviewsBodyPlaceholder: nil, categorySummaryFormat: category.summary, options: [])
|
||||
let notificationCategory = UNNotificationCategory(identifier: category.identifier, actions: category.actions, intentIdentifiers: [], hiddenPreviewsBodyPlaceholder: nil, categorySummaryFormat: category.summary, options: [])
|
||||
UNUserNotificationCenter.current().setNotificationCategories([notificationCategory])
|
||||
content.categoryIdentifier = notificationCategory.identifier
|
||||
}
|
||||
@@ -81,8 +81,9 @@ struct SPLocalNotificationCategory {
|
||||
|
||||
var identifier: String
|
||||
var summary: String
|
||||
var actions: [UNNotificationAction] = []
|
||||
|
||||
var countSymbol: String {
|
||||
static var countSymbol: String {
|
||||
return "%u"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ class SPInstagram {
|
||||
if UIApplication.shared.canOpenURL(instagramUrl!) {
|
||||
UIApplication.shared.open(instagramUrl!, options: convertToUIApplicationOpenExternalURLOptionsKeyDictionary([:]), completionHandler: nil)
|
||||
} else {
|
||||
SPApp.open(link: safariURL.absoluteString, redirect: true)
|
||||
SPApp.open(link: safariURL.absoluteString)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ class SPInstagram {
|
||||
if UIApplication.shared.canOpenURL(instagramUrl!) {
|
||||
UIApplication.shared.open(instagramUrl!, options: convertToUIApplicationOpenExternalURLOptionsKeyDictionary([:]), completionHandler: nil)
|
||||
} else {
|
||||
SPApp.open(link: safariURL.absoluteString, redirect: true)
|
||||
SPApp.open(link: safariURL.absoluteString)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,31 +43,12 @@ class SPTelegram {
|
||||
|
||||
static func joinChannel(id: String) {
|
||||
let url = "https://t.me/joinchat/\(id)"
|
||||
SPApp.open(link: url, redirect: true)
|
||||
SPApp.open(link: url)
|
||||
}
|
||||
|
||||
static func joinChat(id: String) {
|
||||
|
||||
let openInBrowser = {
|
||||
let url = "https://t.me/joinchat/\(id)"
|
||||
SPApp.open(link: url, redirect: true)
|
||||
}
|
||||
|
||||
if SPTelegram.isSetApp {
|
||||
let urlStringEncoded = id.addingPercentEncoding( withAllowedCharacters: .urlHostAllowed)
|
||||
let urlOptional = URL(string: "tg://join?invite=\(urlStringEncoded ?? "")")
|
||||
if let url = urlOptional {
|
||||
if UIApplication.shared.canOpenURL(url) {
|
||||
UIApplication.shared.open(url, options: convertToUIApplicationOpenExternalURLOptionsKeyDictionary([:]), completionHandler: nil)
|
||||
} else {
|
||||
openInBrowser()
|
||||
}
|
||||
} else {
|
||||
openInBrowser()
|
||||
}
|
||||
} else {
|
||||
openInBrowser()
|
||||
}
|
||||
let url = "https://t.me/joinchat/\(id)"
|
||||
SPApp.open(link: url)
|
||||
}
|
||||
|
||||
static func openBot(username: String) {
|
||||
@@ -76,7 +57,12 @@ class SPTelegram {
|
||||
username.removeFirst()
|
||||
}
|
||||
let url = "https://telegram.me/\(username)"
|
||||
SPApp.open(link: url, redirect: true)
|
||||
SPApp.open(link: url)
|
||||
}
|
||||
|
||||
static func openDialog(username: String) {
|
||||
let url = "https://t.me/\(username)"
|
||||
SPApp.open(link: url)
|
||||
}
|
||||
|
||||
private init() {}
|
||||
|
||||
@@ -23,17 +23,6 @@ import UIKit
|
||||
|
||||
class SPButton: UIButton {
|
||||
|
||||
override func imageRect(forContentRect contentRect: CGRect) -> CGRect {
|
||||
if self.title(for: .normal) != nil {
|
||||
let inset: CGFloat = 6
|
||||
let sideSize = self.frame.height - inset * 2
|
||||
let titleFrame = self.titleRect(forContentRect: contentRect)
|
||||
return CGRect.init(x: titleFrame.origin.x - sideSize - 6, y: 0, width: sideSize, height: self.frame.height)
|
||||
} else {
|
||||
return super.imageRect(forContentRect: contentRect)
|
||||
}
|
||||
}
|
||||
|
||||
override var isHighlighted: Bool {
|
||||
didSet {
|
||||
if self.isHighlighted {
|
||||
|
||||
@@ -197,7 +197,7 @@ class SPProposeController: SPController {
|
||||
self.layer.masksToBounds = true
|
||||
self.layer.cornerRadius = 34
|
||||
|
||||
self.titleLabel.font = UIFont.system(weight: .regular, size: 28)
|
||||
self.titleLabel.font = UIFont.system(weight: .regular, size: 31)
|
||||
self.titleLabel.textColor = UIColor.init(hex: "939393")
|
||||
self.titleLabel.numberOfLines = 1
|
||||
self.titleLabel.adjustsFontSizeToFitWidth = true
|
||||
@@ -205,7 +205,7 @@ class SPProposeController: SPController {
|
||||
self.titleLabel.setCenterAlignment()
|
||||
self.addSubview(self.titleLabel)
|
||||
|
||||
self.subtitleLabel.font = UIFont.system(weight: .regular, size: 16)
|
||||
self.subtitleLabel.font = UIFont.system(weight: .regular, size: 17)
|
||||
self.subtitleLabel.textColor = SPNativeColors.black
|
||||
self.subtitleLabel.numberOfLines = 0
|
||||
self.subtitleLabel.setCenterAlignment()
|
||||
@@ -243,23 +243,23 @@ class SPProposeController: SPController {
|
||||
|
||||
self.subtitleLabel.sizeToFit()
|
||||
self.subtitleLabel.frame.origin.y = self.titleLabel.frame.bottomY + 8
|
||||
self.subtitleLabel.frame.set(width: self.frame.width - self.space * 2)
|
||||
self.subtitleLabel.frame.set(width: self.frame.width - self.space * 2 + 10)
|
||||
self.subtitleLabel.setXCenter()
|
||||
|
||||
self.imageView.frame = CGRect.init(
|
||||
x: 0, y: self.subtitleLabel.frame.bottomY + self.space / 2,
|
||||
x: 0, y: self.subtitleLabel.frame.bottomY + self.space / 1.4,
|
||||
width: self.imageSideSize,
|
||||
height: self.imageSideSize
|
||||
)
|
||||
self.imageView.setXCenter()
|
||||
|
||||
self.button.sizeToFit()
|
||||
self.button.frame.set(height: 52)
|
||||
self.button.frame.set(height: 55)
|
||||
self.button.frame.set(width: self.frame.width - self.space * 2)
|
||||
self.button.frame.origin.y = self.imageView.frame.bottomY + self.space / 1.8
|
||||
self.button.frame.origin.y = self.imageView.frame.bottomY + self.space / 1.2
|
||||
self.button.setXCenter()
|
||||
|
||||
self.closeButton.frame = CGRect.init(x: 0, y: 0, width: 24, height: 24)
|
||||
self.closeButton.frame = CGRect.init(x: 0, y: 0, width: 28, height: 28)
|
||||
self.closeButton.frame.origin.x = self.frame.width - self.closeButton.frame.width - 20
|
||||
self.closeButton.frame.origin.y = 20
|
||||
self.closeButton.round()
|
||||
|
||||
@@ -64,10 +64,12 @@ class SPSectionLabelsView: SPView {
|
||||
|
||||
self.titleLabel.frame.set(width: self.frame.width)
|
||||
self.titleLabel.sizeToFit()
|
||||
self.titleLabel.frame.set(width: self.frame.width)
|
||||
self.titleLabel.frame.origin = CGPoint.zero
|
||||
|
||||
self.subtitleLabel.frame.set(width: self.frame.width)
|
||||
self.subtitleLabel.sizeToFit()
|
||||
self.subtitleLabel.frame.set(width: self.frame.width)
|
||||
self.subtitleLabel.frame.origin.x = 0
|
||||
self.subtitleLabel.frame.origin.y = self.titleLabel.frame.bottomY + self.titlesInset
|
||||
|
||||
|
||||
@@ -24,8 +24,9 @@ import UIKit
|
||||
class SPFooterActionsView: SPView {
|
||||
|
||||
var sectionLabels = SPSectionLabelsView()
|
||||
private var buttons: [SPFooterActionButton] = []
|
||||
private var separators: [SPSeparatorView] = []
|
||||
|
||||
var buttons: [SPFooterActionButton] = []
|
||||
var separators: [SPSeparatorView] = []
|
||||
|
||||
override func commonInit() {
|
||||
super.commonInit()
|
||||
|
||||
@@ -53,7 +53,8 @@ class SPFormLabelTableViewCell: SPTableViewCell {
|
||||
self.commonInit()
|
||||
}
|
||||
|
||||
private func commonInit() {
|
||||
override func commonInit() {
|
||||
super.commonInit()
|
||||
self.backgroundColor = UIColor.white
|
||||
self.label.textAlignment = .left
|
||||
self.label.text = "Title"
|
||||
|
||||
@@ -57,7 +57,8 @@ class SPFormTextInputTableViewCell: SPTableViewCell {
|
||||
self.commonInit()
|
||||
}
|
||||
|
||||
private func commonInit() {
|
||||
override func commonInit() {
|
||||
super.commonInit()
|
||||
self.backgroundColor = UIColor.white
|
||||
self.textInputView.textAlignment = .left
|
||||
self.textInputView.text = ""
|
||||
|
||||
@@ -189,7 +189,8 @@ class SPBaseContentTableViewCell: SPTableViewCell {
|
||||
fatalError("init(coder:) has not been implemented")
|
||||
}
|
||||
|
||||
private func commonInit() {
|
||||
override func commonInit() {
|
||||
super.commonInit()
|
||||
let marginGuide = contentView.layoutMarginsGuide
|
||||
|
||||
//iconImageView
|
||||
|
||||
@@ -56,8 +56,8 @@ class SPImageTableViewCell: SPTableViewCell {
|
||||
self.commonInit()
|
||||
}
|
||||
|
||||
private func commonInit() {
|
||||
|
||||
override func commonInit() {
|
||||
super.commonInit()
|
||||
self.layer.masksToBounds = true
|
||||
|
||||
let marginGuide = contentView.layoutMarginsGuide
|
||||
|
||||
@@ -38,7 +38,8 @@ class SPPromoTableViewCell: SPBaseContentTableViewCell {
|
||||
self.commonInit()
|
||||
}
|
||||
|
||||
private func commonInit() {
|
||||
override func commonInit() {
|
||||
super.commonInit()
|
||||
self.withImage = false
|
||||
self.withButton = true
|
||||
self.withSubtitle = false
|
||||
|
||||
@@ -57,7 +57,7 @@ class SPTableViewCell: UITableViewCell {
|
||||
self.commonInit()
|
||||
}
|
||||
|
||||
private func commonInit() {
|
||||
func commonInit() {
|
||||
|
||||
self.contentView.addSubview(self.processActivityIndicatorView)
|
||||
self.processActivityIndicatorView.style = .gray
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>StorkController</string>
|
||||
<string>SPStork</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
@@ -41,5 +41,7 @@
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
</array>
|
||||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -4,7 +4,10 @@ class ModalTableViewController: UIViewController {
|
||||
|
||||
let navBar = SPFakeBarView(style: .stork)
|
||||
let tableView = UITableView()
|
||||
override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent }
|
||||
var lightStatusBar: Bool = false
|
||||
override var preferredStatusBarStyle: UIStatusBarStyle {
|
||||
return self.lightStatusBar ? .lightContent : .default
|
||||
}
|
||||
|
||||
private var data = ["Assembly", "C", "C++", "Java", "JavaScript", "Php", "Python", "Swift", "Kotlin", "Assembly", "C", "C++", "Java", "JavaScript", "Php", "Python", "Objective-C", "Swift", "Kotlin", "Assembly", "C", "C++", "Java", "JavaScript", "Php", "Python", "Objective-C"]
|
||||
|
||||
@@ -28,6 +31,14 @@ class ModalTableViewController: UIViewController {
|
||||
self.updateLayout(with: self.view.frame.size)
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
self.lightStatusBar = true
|
||||
UIView.animate(withDuration: 0.3) { () -> Void in
|
||||
self.setNeedsStatusBarAppearanceUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
override func viewWillLayoutSubviews() {
|
||||
super.viewWillLayoutSubviews()
|
||||
self.updateLayout(with: self.view.frame.size)
|
||||
@@ -38,7 +49,7 @@ class ModalTableViewController: UIViewController {
|
||||
}
|
||||
|
||||
@objc func dismissAction() {
|
||||
self.dismiss()
|
||||
SPStorkController.dismissWithConfirmation(controller: self, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,3 +79,20 @@ extension ModalTableViewController: UITableViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
extension ModalTableViewController: SPStorkControllerConfirmDelegate {
|
||||
|
||||
var needConfirm: Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func confirm(_ completion: @escaping (Bool) -> ()) {
|
||||
let alertController = UIAlertController(title: "Need dismiss?", message: "It test confirm option for SPStorkController", preferredStyle: .actionSheet)
|
||||
alertController.addDestructiveAction(title: "Confirm", complection: {
|
||||
completion(true)
|
||||
})
|
||||
alertController.addCancelAction(title: "Cancel") {
|
||||
completion(false)
|
||||
}
|
||||
self.present(alertController)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,10 @@ import UIKit
|
||||
class ModalViewController: UIViewController {
|
||||
|
||||
let navBar = SPFakeBarView(style: .stork)
|
||||
override var preferredStatusBarStyle: UIStatusBarStyle { return .lightContent }
|
||||
var lightStatusBar: Bool = false
|
||||
override var preferredStatusBarStyle: UIStatusBarStyle {
|
||||
return self.lightStatusBar ? .lightContent : .default
|
||||
}
|
||||
|
||||
override func viewDidLoad() {
|
||||
super.viewDidLoad()
|
||||
@@ -17,7 +20,32 @@ class ModalViewController: UIViewController {
|
||||
}
|
||||
|
||||
@objc func dismissAction() {
|
||||
self.dismiss()
|
||||
SPStorkController.dismissWithConfirmation(controller: self, completion: nil)
|
||||
}
|
||||
|
||||
override func viewWillAppear(_ animated: Bool) {
|
||||
super.viewWillAppear(animated)
|
||||
self.lightStatusBar = true
|
||||
UIView.animate(withDuration: 0.3) { () -> Void in
|
||||
self.setNeedsStatusBarAppearanceUpdate()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension ModalViewController: SPStorkControllerConfirmDelegate {
|
||||
|
||||
var needConfirm: Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func confirm(_ completion: @escaping (Bool) -> ()) {
|
||||
let alertController = UIAlertController(title: "Need dismiss?", message: "It test confirm option for SPStorkController", preferredStyle: .actionSheet)
|
||||
alertController.addDestructiveAction(title: "Confirm", complection: {
|
||||
completion(true)
|
||||
})
|
||||
alertController.addCancelAction(title: "Cancel") {
|
||||
completion(false)
|
||||
}
|
||||
self.present(alertController)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
// swift-tools-version:5.1
|
||||
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "SPStorkController",
|
||||
platforms: [
|
||||
.iOS(.v10)
|
||||
],
|
||||
products: [
|
||||
.library(name: "SPStorkController", targets: ["SPStorkController"])
|
||||
],
|
||||
targets: [
|
||||
.target(name: "SPStorkController", dependencies: [], path: "Source/SPStorkController")
|
||||
]
|
||||
)
|
||||
@@ -1,43 +1,54 @@
|
||||
# SPStorkController
|
||||
|
||||
Very similar to the modal **controller displayed in Apple Music, Podcasts and Mail** apps. Customizable height of view. Check scroll's bounce for more interactive. Simple adding close button and centering arrow indicator. You can download example [Debts - Spending tracker](https://itunes.apple.com/app/id1446635818) or [Code - Learn Swift & Design](https://itunes.apple.com/app/id1453325619) apps from AppStore. If you like the project, do not forget to **put star ★**
|
||||
<a href="https://itunes.apple.com/app/id1446635818" target="_blank"><img align="left" src="https://github.com/ivanvorobei/SPStorkController/blob/master/Resources/Preview.gif" width="400"/></a>
|
||||
|
||||
### Preview
|
||||
### About
|
||||
Controller **as in Apple Music, Podcasts and Mail** apps. Simple adding close button and centering arrow indicator. Customizable height. Using custom `TransitionDelegate`. Alert you can find in [SPAlert](https://github.com/IvanVorobei/SPAlert) project.
|
||||
|
||||
<img src="https://github.com/IvanVorobei/SPStorkController/blob/master/Resources/Preview.gif" width="440">
|
||||
You can download example [Debts - Spending tracker](https://itunes.apple.com/app/id1446635818) app from AppStore. For **buy source code** of app in preview, go to:
|
||||
|
||||
If you want to **buy source code** of this apps, please, go to [xcode-shop.com](https://xcode-shop.com).
|
||||
[](https://xcode-shop.com)
|
||||
|
||||
If you like the project, do not forget to `put star ★` and follow me on GitHub:
|
||||
|
||||
[](https://github.com/ivanvorobei)
|
||||
|
||||
## Navigate
|
||||
|
||||
- [Requirements](#requirements)
|
||||
- [Installation](#installation)
|
||||
- [CocoaPods](#cocoapods)
|
||||
- [Carthage](#carthage)
|
||||
- [Swift Package Manager](#swift-package-manager)
|
||||
- [Manually](#manually)
|
||||
- [Quick Start](#quick-start)
|
||||
- [Usage](#usage)
|
||||
- [Light StatusBar](#light-statusbar)
|
||||
- [Custom Height](#custom-height)
|
||||
- [Close Button](#close-button)
|
||||
- [Indicator](#indicator)
|
||||
- [Arrow Indicator](#arrow-indicator)
|
||||
- [Dismissing](#dismissing)
|
||||
- [Corner Radius](#corner-radius)
|
||||
- [Haptic](#haptic)
|
||||
- [Snapshots](#snapshots)
|
||||
- [Add Navigation Bar](#add-navigation-bar)
|
||||
- [Navigation Bar](#navigation-bar)
|
||||
- [Working with UIScrollView](#working-with-uiscrollview)
|
||||
- [UITableView & UICollectionView](#working-with-uitableview--uicollectionview)
|
||||
- [Confirm before dismiss](#confirm-before-dismiss)
|
||||
- [Delegate](#delegate)
|
||||
- [Video Tutorial](#video-tutorial)
|
||||
- [Other Projects (+gif)](#my-projects)
|
||||
- [Storyboard](#storyboard)
|
||||
- [Sheets in iOS 13](#sheets-in-ios-13)
|
||||
- [Sponsors](#sponsors)
|
||||
- [Other Projects +gif](#my-projects)
|
||||
- [SPAlert](#spalert)
|
||||
- [SPLarkController](#splarkcontroller)
|
||||
- [SPPermission](#sppermission)
|
||||
- [Xcode Shop](#xcode-shop)
|
||||
- [Awesome iOS UI](https://github.com/ivanvorobei/awesome-ios-ui)
|
||||
- [License](#license)
|
||||
- [Contact or Order Develop](#contact)
|
||||
|
||||
## Requirements
|
||||
|
||||
Swift 4.2 & **5.0**. Ready for use on iOS 10+
|
||||
Swift `4.2` & `5.0`. Ready for use on iOS 10+
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -54,7 +65,17 @@ pod 'SPStorkController'
|
||||
[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. To integrate `SPStorkController` into your Xcode project using Carthage, specify it in your `Cartfile`:
|
||||
|
||||
```ogdl
|
||||
github "IvanVorobei/SPStorkController"
|
||||
github "ivanvorobei/SPStorkController"
|
||||
```
|
||||
|
||||
### Swift Package Manager
|
||||
|
||||
The [Swift Package Manager](https://swift.org/package-manager/) is a tool for managing the distribution of Swift code. It’s integrated with the Swift build system to automate the process of downloading, compiling, and linking dependencies.
|
||||
|
||||
To integrate `SPStorkController` into your Xcode project using Xcode 11, specify it in `Project > Swift Packages`:
|
||||
|
||||
```ogdl
|
||||
https://github.com/ivanvorobei/SPStorkController
|
||||
```
|
||||
|
||||
### Manually
|
||||
@@ -131,7 +152,7 @@ Property `showCloseButton` added circle button with dismiss action. Default is `
|
||||
transitionDelegate.showCloseButton = false
|
||||
```
|
||||
|
||||
### Indicator
|
||||
### Arrow Indicator
|
||||
|
||||
On the top of controller you can add arrow indicator with animatable states. It simple configure.
|
||||
Property `showIndicator` shows or hides top arrow indicator. Default is `true`:
|
||||
@@ -152,6 +173,12 @@ Property `hideIndicatorWhenScroll` shows or hides indicator when scrolling. Defa
|
||||
transitionDelegate.hideIndicatorWhenScroll = true
|
||||
```
|
||||
|
||||
You can set always line or arrow indicator. Set `indicatorMode`:
|
||||
|
||||
```swift
|
||||
transitionDelegate.indicatorMode = .alwaysLine
|
||||
```
|
||||
|
||||
### Dismissing
|
||||
|
||||
You can also configure events that will dimiss the controller.
|
||||
@@ -199,7 +226,13 @@ SPStorkController.updatePresentingController(modal: controller)
|
||||
|
||||
and pass the controller, which is modal and uses `SPStorkTransitioningDelegate`.
|
||||
|
||||
### Add Navigation Bar
|
||||
If the parent controller scrollings and you try to show `SPStorkController`, you will see how it froze, and in a second its final position is updated. I recommend before present `SPStorkController` stop scrolling force:
|
||||
|
||||
```swift
|
||||
scrollView.setContentOffset(self.contentOffset, animated: false)
|
||||
```
|
||||
|
||||
### Navigation Bar
|
||||
|
||||
You may want to add a navigation bar to your modal controller. Since it became impossible to change or customize the native controller in swift 4 (I couldn’t even find a way to change the height of the bar), I had to recreate navigation bar from the ground up. Visually it looks real, but it doesn’t execute the necessary functions:
|
||||
|
||||
@@ -227,9 +260,9 @@ class ModalController: UIViewController {
|
||||
|
||||
You only need to add a navigation bar to the main view, it will automatically layout. Use style `.stork` in init of `SPFakeBarView`. Here is visual preview with Navigation Bar and without it:
|
||||
|
||||
<img src="https://github.com/IvanVorobei/SPStorkController/blob/master/Resources/Navigation%20Bar.jpg"/>
|
||||
<img src="https://github.com/ivanvorobei/SPStorkController/blob/master/Resources/Navigation%20Bar.jpg"/>
|
||||
|
||||
To use it, you need to install [SPFakeBar](https://github.com/IvanVorobei/SPFakeBar) pod:
|
||||
To use it, you need to install [SPFakeBar](https://github.com/ivanvorobei/SPFakeBar) pod:
|
||||
|
||||
```ruby
|
||||
pod 'SPFakeBar'
|
||||
@@ -258,6 +291,29 @@ tableView.scrollIndicatorInsets.top = self.navBar.height
|
||||
|
||||
Please, also use `SPStorkController.scrollViewDidScroll` function in scroll delegate for more interactiveness with your collection or table view.
|
||||
|
||||
### Confirm before dismiss
|
||||
|
||||
For confirm closing by swipe, tap around, close button and indicator use `SPStorkControllerConfirmDelegate`. Implenet protocol:
|
||||
|
||||
```swift
|
||||
@objc public protocol SPStorkControllerConfirmDelegate: class {
|
||||
|
||||
var needConfirm: Bool { get }
|
||||
|
||||
func confirm(_ completion: @escaping (_ isConfirmed: Bool)->())
|
||||
}
|
||||
```
|
||||
|
||||
and set `confirmDelegate` property to object, which protocol impleneted. Function `confirm` call if `needConfirm` return true. Pass `isConfirmed` with result. Best options use `UIAlertController` with `.actionSheet` style for confirmation.
|
||||
|
||||
If you use custom buttons, in the target use this code:
|
||||
|
||||
```swift
|
||||
SPStorkController.dismissWithConfirmation(controller: self, completion: nil)
|
||||
```
|
||||
|
||||
It call `confirm` func and check result of confirmation. See example project for more details.
|
||||
|
||||
### Delegate
|
||||
|
||||
You can check events by implement `SPStorkControllerDelegate` and set delegate for `transitionDelegate`:
|
||||
@@ -277,9 +333,31 @@ protocol SPStorkControllerDelegate: class {
|
||||
}
|
||||
```
|
||||
|
||||
### Storyboard
|
||||
|
||||
If need using `SPStorkController` with storyboard, set class `SPStorkSegue` for transition setting in storyboard file. I will give the class code so that you understand what it does:
|
||||
|
||||
```swift
|
||||
import UIKit
|
||||
|
||||
class SPStorkSegue: UIStoryboardSegue {
|
||||
|
||||
public var transitioningDelegate: SPStorkTransitioningDelegate?
|
||||
|
||||
override func perform() {
|
||||
transitioningDelegate = transitioningDelegate ?? SPStorkTransitioningDelegate()
|
||||
destination.transitioningDelegate = transitioningDelegate
|
||||
destination.modalPresentationStyle = .custom
|
||||
super.perform()
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Open your storyboard, choose transition and open right menu. Open `Attributes Inspector` and in Class section insert `SPStorkSegue`.
|
||||
|
||||
### Modal presentation of other controller
|
||||
|
||||
If you want to present modal controller on SPStorkController, please set:
|
||||
If you want to present modal controller on `SPStorkController`, please set:
|
||||
|
||||
```swift
|
||||
controller.modalPresentationStyle = .custom
|
||||
@@ -287,46 +365,52 @@ controller.modalPresentationStyle = .custom
|
||||
|
||||
It’s needed for correct presentation and dismissal of all modal controllers.
|
||||
|
||||
## Video Tutorial
|
||||
## Sheets in iOS 13
|
||||
|
||||
You can see how to use `SPStorkController` and how to customize it [in this video](https://youtu.be/wOTNGswT2-0). For English speakers I’ve added subtitles, don’t forget to turn them on:
|
||||
Apple present in `WWDC 2019` new modal presentation style - `Sheets`. It ready use Support interactive dismiss and work with navigations bars. Available since iOS 13. I will add more information when I study this in more detail. You can see presentation [here](https://developer.apple.com/videos/play/wwdc2019/224/).
|
||||
|
||||
[](https://youtu.be/wOTNGswT2-0)
|
||||
<a href="https://developer.apple.com/videos/play/wwdc2019/224/" target="_blank"><img align="center" src="https://github.com/ivanvorobei/SPStorkController/blob/master/Resources/Sheets.png"/></a>
|
||||
|
||||
## Sponsors
|
||||
|
||||
Support me with a monthly donation and help me continue activities. After payment I add you to list of sponsor **in my all projects** with link to your profile. [Become a sponsors](https://www.patreon.com/ivanvorobei)
|
||||
|
||||
<a href="https://github.com/zubara21/" target="_blank"><img src="https://github.api.ivanvorobei.by/sponsors/zubara21.jpg" width="100"></a>
|
||||
<a href="https://github.com/sparrowganz/" target="_blank"><img src="https://github.api.ivanvorobei.by/sponsors/sparrowganz.jpg" width="100"></a>
|
||||
<a href="https://github.com/shatk0vskiy/" target="_blank"><img src="https://github.api.ivanvorobei.by/sponsors/shatk0vskiy.jpg" width="100"></a>
|
||||
<a href="https://www.patreon.com/ivanvorobei" target="_blank"><img src="https://github.api.ivanvorobei.by/sponsors/add.jpg" width="100"></a>
|
||||
|
||||
## My projects
|
||||
|
||||
<img align="left" src="https://github.com/ivanvorobei/SPAlert/blob/master/Resources/Preview-Done.gif" width="220"/>
|
||||
|
||||
### SPAlert
|
||||
|
||||
Native popup [SPAlert](https://github.com/IvanVorobei/SPAlert) is **similar to Apple Music or Feedback in AppStore** app. Support animations. I tried to repeat Apple alert as much as possible.
|
||||
[SPAlert](https://github.com/ivanvorobei/SPAlert) is **popup from Apple Music & Feedback in AppStore**. Contains `Done` & `Heart` presets. `Done` present with draw path animation. I clone Apple's alerts as much as possible.
|
||||
You can find this alerts in AppStore after feedback, after added song to library in Apple Music. I am also add alert without icon, as simple message.
|
||||
|
||||
<p float="left">
|
||||
<img src="https://github.com/IvanVorobei/SPAlert/blob/master/Resources/Preview-Done.gif" width="250">
|
||||
<img src="https://github.com/IvanVorobei/SPAlert/blob/master/Resources/Preview-Heart.gif" width="250">
|
||||
<img src="https://github.com/IvanVorobei/SPAlert/blob/master/Resources/Preview-Message.gif" width="250">
|
||||
</p>
|
||||
You can download example [Debts - Spending tracker](https://itunes.apple.com/app/id1446635818) app from AppStore. If you want to **buy source code** of app in preview, please, go to [xcode-shop.com](https://xcode-shop.com).
|
||||
|
||||
You can download example app [Debts - Spending tracker](https://itunes.apple.com/app/id1446635818) from AppStore. If you want to **buy source code** of example apps, please, go to [xcode-shop.com](https://xcode-shop.com).
|
||||
---
|
||||
|
||||
<img align="left" src="https://github.com/ivanvorobei/SPLarkController/blob/master/Resources/Preview.gif" width="220"/>
|
||||
|
||||
### SPLarkController
|
||||
|
||||
[SPLarkController](https://github.com/IvanVorobei/SPLarkController) make **settings screen** for your application. You can add **buttons and switches**. The amount cells is not limited. You can start using project with just two lines of code and easy customisation.
|
||||
[SPLarkController](https://github.com/ivanvorobei/SPLarkController) transition between controllers. Translate to top. Make **settings screen** for application. You can add **buttons and switches**. The amount cells is not limited. You can start using project with just two lines of code and easy customisation. For implement settings as in preiew, see section [Settings Controller](https://github.com/ivanvorobei/SPLarkController#settings-controller).
|
||||
|
||||
<img src="https://github.com/IvanVorobei/SPLarkController/blob/master/Resources/Preview.gif" width="440">
|
||||
You can download example app [Code - Learn Swift & Design](https://itunes.apple.com/app/id1453325619) from AppStore. If you want to **buy source code** of app this app, please, go to [xcode-shop.com](https://xcode-shop.com).
|
||||
|
||||
You can download [Code - Learn Swift & Design](https://itunes.apple.com/app/id1453325619) app, which uses `SPLarkController`. Also you can **buy source code** of this app on [xcode-shop.com](https://xcode-shop.com).
|
||||
---
|
||||
|
||||
<img align="left" src="https://github.com/ivanvorobei/SPPermission/blob/master/Resources/Preview.gif" width="220"/>
|
||||
|
||||
### SPPermission
|
||||
|
||||
[SPPermission](https://github.com/IvanVorobei/SPPermission) allow request permissions **with native dialog** UI and interactive animations. Also you can request permissions without dialog. Check state any permission. You can start using this project with just two lines of code and easy customisation.
|
||||
[SPPermission](https://github.com/ivanvorobei/SPPermission) allow request permissions **with native dialog** UI and interactive animations. Also you can request permissions without dialog. Check state any permission. You can start using this project with just two lines of code and easy customisation.
|
||||
|
||||
<img src="https://github.com/IvanVorobei/SPPermission/blob/master/Resources/Preview.gif" width="500">
|
||||
|
||||
### Xcode Shop
|
||||
|
||||
If you want **buy apps with source code**, you can visit my [xcode-shop.com](https://xcode-shop.com). Here I am sale apps, modules, 3D elements and other. In applications you can find many cool UI that will be useful for your projects. Also by buying, **you support me** and my free GitHub development.
|
||||
You can buy example Dialog & Dinamic animations in [xcode-shop.com](https://xcode-shop.com/ui-elements), see [preview](https://xcode-shop.com/assets/preview/dinamic-alert.mov).
|
||||
|
||||
## License
|
||||
`SPStorkController` is released under the MIT license. Check `LICENSE.md` for details.
|
||||
|
||||
## Contact
|
||||
If you need any application or UI to be developed, message me at hello@ivanvorobei.by or via [telegram](https://t.me/ivanvorobei). I develop iOS apps and designs. I use `swift` for development. To request more functionality, you should create a new issue. You can see my [apps in AppStore](https://itunes.apple.com/developer/id1446635817).
|
||||
`SPStorkController` is released under the MIT license. Check `LICENSE.md` for details.
|
||||
|
||||
|
Before Width: | Height: | Size: 2.6 MiB After Width: | Height: | Size: 2.4 MiB |
|
After Width: | Height: | Size: 2.7 MiB |
@@ -1,7 +1,7 @@
|
||||
Pod::Spec.new do |s|
|
||||
|
||||
s.name = "SPStorkController"
|
||||
s.version = "1.6.2"
|
||||
s.version = "1.7.9"
|
||||
s.summary = "Very similar to the controllers displayed in Apple Music, Podcasts and Mail Apple's applications."
|
||||
s.homepage = "https://github.com/IvanVorobei/SPStorkController"
|
||||
s.source = { :git => "https://github.com/IvanVorobei/SPStorkController.git", :tag => s.version }
|
||||
|
||||
@@ -7,37 +7,43 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
F4803C0C230836F40092C9BC /* SPStorkHaptic.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4803BF8230836F40092C9BC /* SPStorkHaptic.swift */; };
|
||||
F4803C0D230836F50092C9BC /* SPStorkArrowMode.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4803BF9230836F40092C9BC /* SPStorkArrowMode.swift */; };
|
||||
F4803C0E230836F50092C9BC /* SPStorkSeque.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4803BFA230836F40092C9BC /* SPStorkSeque.swift */; };
|
||||
F4803C0F230836F50092C9BC /* SPStorkCodeDraw.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4803BFC230836F40092C9BC /* SPStorkCodeDraw.swift */; };
|
||||
F4803C10230836F50092C9BC /* SPStorkController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4803BFD230836F40092C9BC /* SPStorkController.swift */; };
|
||||
F4803C11230836F50092C9BC /* SPStorkTransitioningDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4803BFF230836F40092C9BC /* SPStorkTransitioningDelegate.swift */; };
|
||||
F4803C12230836F50092C9BC /* SPStorkPresentingAnimationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4803C00230836F40092C9BC /* SPStorkPresentingAnimationController.swift */; };
|
||||
F4803C13230836F50092C9BC /* SPStorkPresentationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4803C01230836F40092C9BC /* SPStorkPresentationController.swift */; };
|
||||
F4803C14230836F50092C9BC /* SPStorkDismissingAnimationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4803C02230836F40092C9BC /* SPStorkDismissingAnimationController.swift */; };
|
||||
F4803C15230836F50092C9BC /* SPStorkViewControllerExtenshion.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4803C04230836F40092C9BC /* SPStorkViewControllerExtenshion.swift */; };
|
||||
F4803C16230836F50092C9BC /* SPStorkCloseButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4803C06230836F40092C9BC /* SPStorkCloseButton.swift */; };
|
||||
F4803C17230836F50092C9BC /* SPStorkIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4803C07230836F40092C9BC /* SPStorkIndicatorView.swift */; };
|
||||
F4803C18230836F50092C9BC /* SPStorkCloseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4803C08230836F40092C9BC /* SPStorkCloseView.swift */; };
|
||||
F4803C19230836F50092C9BC /* SPStorkControllerConfirmDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4803C0A230836F40092C9BC /* SPStorkControllerConfirmDelegate.swift */; };
|
||||
F4803C1A230836F50092C9BC /* SPStorkControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4803C0B230836F40092C9BC /* SPStorkControllerDelegate.swift */; };
|
||||
F4DB85222260A4FD005082AA /* SPStorkController.h in Headers */ = {isa = PBXBuildFile; fileRef = F4DB85202260A4FD005082AA /* SPStorkController.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
F4DB853B2260A582005082AA /* SPStorkHaptic.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4DB852A2260A582005082AA /* SPStorkHaptic.swift */; };
|
||||
F4DB853C2260A582005082AA /* SPStorkCodeDraw.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4DB852C2260A582005082AA /* SPStorkCodeDraw.swift */; };
|
||||
F4DB853D2260A582005082AA /* SPStorkController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4DB852D2260A582005082AA /* SPStorkController.swift */; };
|
||||
F4DB853E2260A582005082AA /* SPStorkTransitioningDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4DB852F2260A582005082AA /* SPStorkTransitioningDelegate.swift */; };
|
||||
F4DB853F2260A582005082AA /* SPStorkPresentingAnimationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4DB85302260A582005082AA /* SPStorkPresentingAnimationController.swift */; };
|
||||
F4DB85402260A582005082AA /* SPStorkPresentationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4DB85312260A582005082AA /* SPStorkPresentationController.swift */; };
|
||||
F4DB85412260A582005082AA /* SPStorkDismissingAnimationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4DB85322260A582005082AA /* SPStorkDismissingAnimationController.swift */; };
|
||||
F4DB85422260A582005082AA /* SPStorkViewControllerExtenshion.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4DB85342260A582005082AA /* SPStorkViewControllerExtenshion.swift */; };
|
||||
F4DB85432260A582005082AA /* SPStorkCloseButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4DB85362260A582005082AA /* SPStorkCloseButton.swift */; };
|
||||
F4DB85442260A582005082AA /* SPStorkIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4DB85372260A582005082AA /* SPStorkIndicatorView.swift */; };
|
||||
F4DB85452260A582005082AA /* SPStorkCloseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4DB85382260A582005082AA /* SPStorkCloseView.swift */; };
|
||||
F4DB85462260A582005082AA /* SPStorkControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4DB853A2260A582005082AA /* SPStorkControllerDelegate.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
F4803BF8230836F40092C9BC /* SPStorkHaptic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkHaptic.swift; sourceTree = "<group>"; };
|
||||
F4803BF9230836F40092C9BC /* SPStorkArrowMode.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkArrowMode.swift; sourceTree = "<group>"; };
|
||||
F4803BFA230836F40092C9BC /* SPStorkSeque.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkSeque.swift; sourceTree = "<group>"; };
|
||||
F4803BFC230836F40092C9BC /* SPStorkCodeDraw.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkCodeDraw.swift; sourceTree = "<group>"; };
|
||||
F4803BFD230836F40092C9BC /* SPStorkController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkController.swift; sourceTree = "<group>"; };
|
||||
F4803BFF230836F40092C9BC /* SPStorkTransitioningDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkTransitioningDelegate.swift; sourceTree = "<group>"; };
|
||||
F4803C00230836F40092C9BC /* SPStorkPresentingAnimationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkPresentingAnimationController.swift; sourceTree = "<group>"; };
|
||||
F4803C01230836F40092C9BC /* SPStorkPresentationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkPresentationController.swift; sourceTree = "<group>"; };
|
||||
F4803C02230836F40092C9BC /* SPStorkDismissingAnimationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkDismissingAnimationController.swift; sourceTree = "<group>"; };
|
||||
F4803C04230836F40092C9BC /* SPStorkViewControllerExtenshion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkViewControllerExtenshion.swift; sourceTree = "<group>"; };
|
||||
F4803C06230836F40092C9BC /* SPStorkCloseButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkCloseButton.swift; sourceTree = "<group>"; };
|
||||
F4803C07230836F40092C9BC /* SPStorkIndicatorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkIndicatorView.swift; sourceTree = "<group>"; };
|
||||
F4803C08230836F40092C9BC /* SPStorkCloseView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkCloseView.swift; sourceTree = "<group>"; };
|
||||
F4803C0A230836F40092C9BC /* SPStorkControllerConfirmDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkControllerConfirmDelegate.swift; sourceTree = "<group>"; };
|
||||
F4803C0B230836F40092C9BC /* SPStorkControllerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkControllerDelegate.swift; sourceTree = "<group>"; };
|
||||
F4DB851D2260A4FD005082AA /* SPStorkController.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SPStorkController.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
F4DB85202260A4FD005082AA /* SPStorkController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SPStorkController.h; sourceTree = "<group>"; };
|
||||
F4DB85212260A4FD005082AA /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
F4DB852A2260A582005082AA /* SPStorkHaptic.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkHaptic.swift; sourceTree = "<group>"; };
|
||||
F4DB852C2260A582005082AA /* SPStorkCodeDraw.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkCodeDraw.swift; sourceTree = "<group>"; };
|
||||
F4DB852D2260A582005082AA /* SPStorkController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkController.swift; sourceTree = "<group>"; };
|
||||
F4DB852F2260A582005082AA /* SPStorkTransitioningDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkTransitioningDelegate.swift; sourceTree = "<group>"; };
|
||||
F4DB85302260A582005082AA /* SPStorkPresentingAnimationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkPresentingAnimationController.swift; sourceTree = "<group>"; };
|
||||
F4DB85312260A582005082AA /* SPStorkPresentationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkPresentationController.swift; sourceTree = "<group>"; };
|
||||
F4DB85322260A582005082AA /* SPStorkDismissingAnimationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkDismissingAnimationController.swift; sourceTree = "<group>"; };
|
||||
F4DB85342260A582005082AA /* SPStorkViewControllerExtenshion.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkViewControllerExtenshion.swift; sourceTree = "<group>"; };
|
||||
F4DB85362260A582005082AA /* SPStorkCloseButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkCloseButton.swift; sourceTree = "<group>"; };
|
||||
F4DB85372260A582005082AA /* SPStorkIndicatorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkIndicatorView.swift; sourceTree = "<group>"; };
|
||||
F4DB85382260A582005082AA /* SPStorkCloseView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkCloseView.swift; sourceTree = "<group>"; };
|
||||
F4DB853A2260A582005082AA /* SPStorkControllerDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPStorkControllerDelegate.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@@ -51,6 +57,85 @@
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
F4437E4F22B50918006E6498 /* Supporting Files */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F4DB85202260A4FD005082AA /* SPStorkController.h */,
|
||||
F4DB85212260A4FD005082AA /* Info.plist */,
|
||||
);
|
||||
path = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F4803BF6230836F40092C9BC /* SPStorkController */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F4803BF7230836F40092C9BC /* Models */,
|
||||
F4803BFA230836F40092C9BC /* SPStorkSeque.swift */,
|
||||
F4803BFB230836F40092C9BC /* CodeDraw */,
|
||||
F4803BFD230836F40092C9BC /* SPStorkController.swift */,
|
||||
F4803BFE230836F40092C9BC /* TransitioningDelegate */,
|
||||
F4803C03230836F40092C9BC /* Extenshion */,
|
||||
F4803C05230836F40092C9BC /* Views */,
|
||||
F4803C09230836F40092C9BC /* Protocols */,
|
||||
);
|
||||
path = SPStorkController;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F4803BF7230836F40092C9BC /* Models */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F4803BF8230836F40092C9BC /* SPStorkHaptic.swift */,
|
||||
F4803BF9230836F40092C9BC /* SPStorkArrowMode.swift */,
|
||||
);
|
||||
path = Models;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F4803BFB230836F40092C9BC /* CodeDraw */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F4803BFC230836F40092C9BC /* SPStorkCodeDraw.swift */,
|
||||
);
|
||||
path = CodeDraw;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F4803BFE230836F40092C9BC /* TransitioningDelegate */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F4803BFF230836F40092C9BC /* SPStorkTransitioningDelegate.swift */,
|
||||
F4803C00230836F40092C9BC /* SPStorkPresentingAnimationController.swift */,
|
||||
F4803C01230836F40092C9BC /* SPStorkPresentationController.swift */,
|
||||
F4803C02230836F40092C9BC /* SPStorkDismissingAnimationController.swift */,
|
||||
);
|
||||
path = TransitioningDelegate;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F4803C03230836F40092C9BC /* Extenshion */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F4803C04230836F40092C9BC /* SPStorkViewControllerExtenshion.swift */,
|
||||
);
|
||||
path = Extenshion;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F4803C05230836F40092C9BC /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F4803C06230836F40092C9BC /* SPStorkCloseButton.swift */,
|
||||
F4803C07230836F40092C9BC /* SPStorkIndicatorView.swift */,
|
||||
F4803C08230836F40092C9BC /* SPStorkCloseView.swift */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F4803C09230836F40092C9BC /* Protocols */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F4803C0A230836F40092C9BC /* SPStorkControllerConfirmDelegate.swift */,
|
||||
F4803C0B230836F40092C9BC /* SPStorkControllerDelegate.swift */,
|
||||
);
|
||||
path = Protocols;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F4DB85132260A4FD005082AA = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -70,80 +155,12 @@
|
||||
F4DB851F2260A4FD005082AA /* Source */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F4DB85282260A582005082AA /* SPStorkController */,
|
||||
F4DB85202260A4FD005082AA /* SPStorkController.h */,
|
||||
F4DB85212260A4FD005082AA /* Info.plist */,
|
||||
F4803BF6230836F40092C9BC /* SPStorkController */,
|
||||
F4437E4F22B50918006E6498 /* Supporting Files */,
|
||||
);
|
||||
path = Source;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F4DB85282260A582005082AA /* SPStorkController */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F4DB85292260A582005082AA /* Models */,
|
||||
F4DB852B2260A582005082AA /* CodeDraw */,
|
||||
F4DB852D2260A582005082AA /* SPStorkController.swift */,
|
||||
F4DB852E2260A582005082AA /* TransitioningDelegate */,
|
||||
F4DB85332260A582005082AA /* Extenshion */,
|
||||
F4DB85352260A582005082AA /* Views */,
|
||||
F4DB85392260A582005082AA /* Protocols */,
|
||||
);
|
||||
path = SPStorkController;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F4DB85292260A582005082AA /* Models */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F4DB852A2260A582005082AA /* SPStorkHaptic.swift */,
|
||||
);
|
||||
path = Models;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F4DB852B2260A582005082AA /* CodeDraw */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F4DB852C2260A582005082AA /* SPStorkCodeDraw.swift */,
|
||||
);
|
||||
path = CodeDraw;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F4DB852E2260A582005082AA /* TransitioningDelegate */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F4DB852F2260A582005082AA /* SPStorkTransitioningDelegate.swift */,
|
||||
F4DB85302260A582005082AA /* SPStorkPresentingAnimationController.swift */,
|
||||
F4DB85312260A582005082AA /* SPStorkPresentationController.swift */,
|
||||
F4DB85322260A582005082AA /* SPStorkDismissingAnimationController.swift */,
|
||||
);
|
||||
path = TransitioningDelegate;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F4DB85332260A582005082AA /* Extenshion */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F4DB85342260A582005082AA /* SPStorkViewControllerExtenshion.swift */,
|
||||
);
|
||||
path = Extenshion;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F4DB85352260A582005082AA /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F4DB85362260A582005082AA /* SPStorkCloseButton.swift */,
|
||||
F4DB85372260A582005082AA /* SPStorkIndicatorView.swift */,
|
||||
F4DB85382260A582005082AA /* SPStorkCloseView.swift */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
F4DB85392260A582005082AA /* Protocols */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
F4DB853A2260A582005082AA /* SPStorkControllerDelegate.swift */,
|
||||
);
|
||||
path = Protocols;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXHeadersBuildPhase section */
|
||||
@@ -222,18 +239,21 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
F4DB853D2260A582005082AA /* SPStorkController.swift in Sources */,
|
||||
F4DB85412260A582005082AA /* SPStorkDismissingAnimationController.swift in Sources */,
|
||||
F4DB85422260A582005082AA /* SPStorkViewControllerExtenshion.swift in Sources */,
|
||||
F4DB85462260A582005082AA /* SPStorkControllerDelegate.swift in Sources */,
|
||||
F4DB85452260A582005082AA /* SPStorkCloseView.swift in Sources */,
|
||||
F4DB85432260A582005082AA /* SPStorkCloseButton.swift in Sources */,
|
||||
F4DB853B2260A582005082AA /* SPStorkHaptic.swift in Sources */,
|
||||
F4DB85402260A582005082AA /* SPStorkPresentationController.swift in Sources */,
|
||||
F4DB853F2260A582005082AA /* SPStorkPresentingAnimationController.swift in Sources */,
|
||||
F4DB853C2260A582005082AA /* SPStorkCodeDraw.swift in Sources */,
|
||||
F4DB853E2260A582005082AA /* SPStorkTransitioningDelegate.swift in Sources */,
|
||||
F4DB85442260A582005082AA /* SPStorkIndicatorView.swift in Sources */,
|
||||
F4803C10230836F50092C9BC /* SPStorkController.swift in Sources */,
|
||||
F4803C11230836F50092C9BC /* SPStorkTransitioningDelegate.swift in Sources */,
|
||||
F4803C19230836F50092C9BC /* SPStorkControllerConfirmDelegate.swift in Sources */,
|
||||
F4803C1A230836F50092C9BC /* SPStorkControllerDelegate.swift in Sources */,
|
||||
F4803C15230836F50092C9BC /* SPStorkViewControllerExtenshion.swift in Sources */,
|
||||
F4803C17230836F50092C9BC /* SPStorkIndicatorView.swift in Sources */,
|
||||
F4803C0C230836F40092C9BC /* SPStorkHaptic.swift in Sources */,
|
||||
F4803C12230836F50092C9BC /* SPStorkPresentingAnimationController.swift in Sources */,
|
||||
F4803C18230836F50092C9BC /* SPStorkCloseView.swift in Sources */,
|
||||
F4803C13230836F50092C9BC /* SPStorkPresentationController.swift in Sources */,
|
||||
F4803C0E230836F50092C9BC /* SPStorkSeque.swift in Sources */,
|
||||
F4803C14230836F50092C9BC /* SPStorkDismissingAnimationController.swift in Sources */,
|
||||
F4803C0D230836F50092C9BC /* SPStorkArrowMode.swift in Sources */,
|
||||
F4803C0F230836F50092C9BC /* SPStorkCodeDraw.swift in Sources */,
|
||||
F4803C16230836F50092C9BC /* SPStorkCloseButton.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -371,7 +391,7 @@
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist";
|
||||
INFOPLIST_FILE = "$(SRCROOT)/Source/Supporting Files/Info.plist";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
@@ -396,7 +416,7 @@
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
DYLIB_CURRENT_VERSION = 1;
|
||||
DYLIB_INSTALL_NAME_BASE = "@rpath";
|
||||
INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist";
|
||||
INFOPLIST_FILE = "$(SRCROOT)/Source/Supporting Files/Info.plist";
|
||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 10.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
|
||||
@@ -38,12 +38,11 @@ extension UIViewController {
|
||||
self.present(controller, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
public func presentAsStork(_ controller: UIViewController, height: CGFloat?, showIndicator: Bool, hideIndicatorWhenScroll: Bool, showCloseButton: Bool, complection: (() -> Void)?) {
|
||||
public func presentAsStork(_ controller: UIViewController, height: CGFloat?, showIndicator: Bool, showCloseButton: Bool, complection: (() -> Void)? = nil) {
|
||||
let transitionDelegate = SPStorkTransitioningDelegate()
|
||||
transitionDelegate.customHeight = height
|
||||
transitionDelegate.showCloseButton = showCloseButton
|
||||
transitionDelegate.showIndicator = showIndicator
|
||||
transitionDelegate.hideIndicatorWhenScroll = hideIndicatorWhenScroll
|
||||
controller.transitioningDelegate = transitionDelegate
|
||||
controller.modalPresentationStyle = .custom
|
||||
controller.modalPresentationCapturesStatusBarAppearance = true
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
// The MIT License (MIT)
|
||||
// Copyright © 2017 Ivan Vorobei (hello@ivanvorobei.by)
|
||||
//
|
||||
// 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.
|
||||
|
||||
import UIKit
|
||||
|
||||
public enum SPStorkArrowMode {
|
||||
|
||||
case auto
|
||||
case alwaysArrow
|
||||
case alwaysLine
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// The MIT License (MIT)
|
||||
// Copyright © 2017 Ivan Vorobei (hello@ivanvorobei.by)
|
||||
//
|
||||
// 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.
|
||||
|
||||
import UIKit
|
||||
|
||||
@objc public protocol SPStorkControllerConfirmDelegate: class {
|
||||
|
||||
var needConfirm: Bool { get }
|
||||
|
||||
func confirm(_ completion: @escaping (_ isConfirmed: Bool)->())
|
||||
}
|
||||
@@ -21,11 +21,11 @@
|
||||
|
||||
import UIKit
|
||||
|
||||
public struct SPStorkController {
|
||||
public enum SPStorkController {
|
||||
|
||||
static public func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||
if let controller = self.controller(for: scrollView) {
|
||||
if let presentationController = controller.presentationController as? SPStorkPresentationController {
|
||||
if let presentationController = self.presentationController(for: controller) {
|
||||
let translation = -(scrollView.contentOffset.y + scrollView.contentInset.top)
|
||||
if translation >= 0 {
|
||||
if controller.isBeingPresented { return }
|
||||
@@ -35,7 +35,7 @@ public struct SPStorkController {
|
||||
presentationController.setIndicator(style: scrollView.isTracking ? .line : .arrow)
|
||||
if translation >= presentationController.translateForDismiss * 0.4 {
|
||||
if !scrollView.isTracking && !scrollView.isDragging {
|
||||
presentationController.presentedViewController.dismiss(animated: true, completion: {
|
||||
self.dismissWithConfirmation(controller: controller, completion: {
|
||||
presentationController.storkDelegate?.didDismissStorkBySwipe?()
|
||||
})
|
||||
return
|
||||
@@ -58,6 +58,14 @@ public struct SPStorkController {
|
||||
}
|
||||
}
|
||||
|
||||
static public func dismissWithConfirmation(controller: UIViewController, completion: (()->())?) {
|
||||
if let controller = self.presentationController(for: controller) {
|
||||
controller.dismissWithConfirmation(prepare: nil, completion: {
|
||||
completion?()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
static public var topScrollIndicatorInset: CGFloat {
|
||||
return 6
|
||||
}
|
||||
@@ -74,6 +82,19 @@ public struct SPStorkController {
|
||||
}
|
||||
}
|
||||
|
||||
static private func presentationController(for controller: UIViewController) -> SPStorkPresentationController? {
|
||||
guard controller.modalPresentationStyle == .custom else { return nil }
|
||||
|
||||
if let presentationController = controller.presentationController as? SPStorkPresentationController {
|
||||
return presentationController
|
||||
}
|
||||
|
||||
if let presentationController = controller.parent?.presentationController as? SPStorkPresentationController {
|
||||
return presentationController
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
static private func controller(for view: UIView) -> UIViewController? {
|
||||
var nextResponder = view.next
|
||||
while nextResponder != nil && !(nextResponder! is UIViewController) {
|
||||
@@ -81,6 +102,4 @@ public struct SPStorkController {
|
||||
}
|
||||
return nextResponder as? UIViewController
|
||||
}
|
||||
|
||||
private init() {}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
// The MIT License (MIT)
|
||||
// Copyright © 2017 Ivan Vorobei (hello@ivanvorobei.by)
|
||||
//
|
||||
// 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.
|
||||
|
||||
import UIKit
|
||||
|
||||
public class SPStorkSegue: UIStoryboardSegue {
|
||||
|
||||
public var transitioningDelegate: SPStorkTransitioningDelegate?
|
||||
|
||||
override public func perform() {
|
||||
transitioningDelegate = transitioningDelegate ?? SPStorkTransitioningDelegate()
|
||||
destination.transitioningDelegate = transitioningDelegate
|
||||
destination.modalPresentationStyle = .custom
|
||||
super.perform()
|
||||
}
|
||||
}
|
||||
@@ -29,12 +29,14 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
|
||||
var showIndicator: Bool = true
|
||||
var indicatorColor: UIColor = UIColor.init(red: 202/255, green: 201/255, blue: 207/255, alpha: 1)
|
||||
var hideIndicatorWhenScroll: Bool = false
|
||||
var indicatorMode: SPStorkArrowMode = .auto
|
||||
var customHeight: CGFloat? = nil
|
||||
var translateForDismiss: CGFloat = 200
|
||||
var hapticMoments: [SPStorkHapticMoments] = [.willDismissIfRelease]
|
||||
|
||||
var transitioningDelegate: SPStorkTransitioningDelegate?
|
||||
weak var storkDelegate: SPStorkControllerDelegate?
|
||||
weak var confirmDelegate: SPStorkControllerConfirmDelegate?
|
||||
|
||||
var pan: UIPanGestureRecognizer?
|
||||
var tap: UITapGestureRecognizer?
|
||||
@@ -50,6 +52,7 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
|
||||
private var snapshotViewWidthConstraint: NSLayoutConstraint?
|
||||
private var snapshotViewAspectRatioConstraint: NSLayoutConstraint?
|
||||
|
||||
var workConfirmation: Bool = false
|
||||
private var workGester: Bool = false
|
||||
private var startDismissing: Bool = false
|
||||
private var afterReleaseDismissing: Bool = false
|
||||
@@ -64,11 +67,19 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
|
||||
|
||||
private var scaleForPresentingView: CGFloat {
|
||||
guard let containerView = containerView else { return 0 }
|
||||
let factor = 1 - ((self.cornerRadius + 2) * 2 / containerView.frame.width)
|
||||
let factor = 1 - ((self.cornerRadius + 3) * 2 / containerView.frame.width)
|
||||
return factor
|
||||
}
|
||||
|
||||
private var feedbackGenerator: UIImpactFeedbackGenerator = UIImpactFeedbackGenerator(style: .light)
|
||||
private var feedbackGenerator = UIImpactFeedbackGenerator(style: .light)
|
||||
|
||||
override var presentedView: UIView? {
|
||||
let view = self.presentedViewController.view
|
||||
if view?.frame.origin == CGPoint.zero {
|
||||
view?.frame = self.frameOfPresentedViewInContainerView
|
||||
}
|
||||
return view
|
||||
}
|
||||
|
||||
override var frameOfPresentedViewInContainerView: CGRect {
|
||||
guard let containerView = containerView else { return .zero }
|
||||
@@ -95,19 +106,43 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
|
||||
|
||||
guard let containerView = self.containerView, let presentedView = self.presentedView, let window = containerView.window else { return }
|
||||
|
||||
let closeTitle = NSLocalizedString("Close", comment: "Close")
|
||||
|
||||
if self.showIndicator {
|
||||
self.indicatorView.color = self.indicatorColor
|
||||
let tap = UITapGestureRecognizer.init(target: self, action: #selector(self.dismissAction))
|
||||
let tap = UITapGestureRecognizer.init(target: self, action: #selector(self.tapIndicator))
|
||||
tap.cancelsTouchesInView = false
|
||||
self.indicatorView.addGestureRecognizer(tap)
|
||||
self.indicatorView.accessibilityLabel = closeTitle
|
||||
presentedView.addSubview(self.indicatorView)
|
||||
self.indicatorView.translatesAutoresizingMaskIntoConstraints = false
|
||||
self.indicatorView.widthAnchor.constraint(equalToConstant: 36).isActive = true
|
||||
self.indicatorView.heightAnchor.constraint(equalToConstant: 13).isActive = true
|
||||
self.indicatorView.centerXAnchor.constraint(equalTo: presentedView.centerXAnchor).isActive = true
|
||||
self.indicatorView.topAnchor.constraint(equalTo: presentedView.topAnchor, constant: 12).isActive = true
|
||||
self.indicatorView.mode = self.indicatorMode
|
||||
|
||||
if UIAccessibility.isVoiceOverRunning {
|
||||
let accessibleIndicatorOverlayButton = UIButton(type: .custom)
|
||||
accessibleIndicatorOverlayButton.addTarget(self, action: #selector(self.tapIndicator), for: .touchUpInside)
|
||||
accessibleIndicatorOverlayButton.accessibilityLabel = closeTitle
|
||||
presentedView.addSubview(accessibleIndicatorOverlayButton)
|
||||
accessibleIndicatorOverlayButton.translatesAutoresizingMaskIntoConstraints = false
|
||||
NSLayoutConstraint.activate([
|
||||
accessibleIndicatorOverlayButton.leadingAnchor.constraint(equalTo: presentedView.leadingAnchor),
|
||||
accessibleIndicatorOverlayButton.trailingAnchor.constraint(equalTo: presentedView.trailingAnchor),
|
||||
accessibleIndicatorOverlayButton.topAnchor.constraint(equalTo: presentedView.topAnchor),
|
||||
accessibleIndicatorOverlayButton.bottomAnchor.constraint(equalTo: self.indicatorView.bottomAnchor),
|
||||
])
|
||||
}
|
||||
}
|
||||
self.updateLayoutIndicator()
|
||||
self.indicatorView.style = .arrow
|
||||
self.gradeView.alpha = 0
|
||||
|
||||
|
||||
self.closeButton.accessibilityLabel = closeTitle
|
||||
if self.showCloseButton {
|
||||
self.closeButton.addTarget(self, action: #selector(self.dismissAction), for: .touchUpInside)
|
||||
self.closeButton.addTarget(self, action: #selector(self.tapCloseButton), for: .touchUpInside)
|
||||
presentedView.addSubview(self.closeButton)
|
||||
}
|
||||
self.updateLayoutCloseButton()
|
||||
@@ -194,7 +229,7 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
|
||||
self.updateSnapshotAspectRatio()
|
||||
|
||||
if self.tapAroundToDismissEnabled {
|
||||
self.tap = UITapGestureRecognizer.init(target: self, action: #selector(self.dismissAction))
|
||||
self.tap = UITapGestureRecognizer.init(target: self, action: #selector(self.tapArround))
|
||||
self.tap?.cancelsTouchesInView = false
|
||||
self.snapshotViewContainer.addGestureRecognizer(self.tap!)
|
||||
}
|
||||
@@ -208,21 +243,13 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
|
||||
}
|
||||
}
|
||||
|
||||
@objc func dismissAction() {
|
||||
self.presentingViewController.view.endEditing(true)
|
||||
self.presentedViewController.view.endEditing(true)
|
||||
self.presentedViewController.dismiss(animated: true, completion: {
|
||||
self.storkDelegate?.didDismissStorkByTap?()
|
||||
})
|
||||
}
|
||||
|
||||
override func dismissalTransitionWillBegin() {
|
||||
super.dismissalTransitionWillBegin()
|
||||
guard let containerView = containerView else { return }
|
||||
self.startDismissing = true
|
||||
|
||||
let initialFrame: CGRect = presentingViewController.isPresentedAsStork ? presentingViewController.view.frame : containerView.bounds
|
||||
|
||||
|
||||
let initialTransform = CGAffineTransform.identity
|
||||
.translatedBy(x: 0, y: -initialFrame.origin.y)
|
||||
.translatedBy(x: 0, y: self.topSpace)
|
||||
@@ -299,6 +326,56 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
|
||||
|
||||
extension SPStorkPresentationController {
|
||||
|
||||
@objc func tapIndicator() {
|
||||
self.dismissWithConfirmation(prepare: nil, completion: {
|
||||
self.storkDelegate?.didDismissStorkByTap?()
|
||||
})
|
||||
}
|
||||
|
||||
@objc func tapArround() {
|
||||
self.dismissWithConfirmation(prepare: nil, completion: {
|
||||
self.storkDelegate?.didDismissStorkByTap?()
|
||||
})
|
||||
}
|
||||
|
||||
@objc func tapCloseButton() {
|
||||
self.dismissWithConfirmation(prepare: nil, completion: {
|
||||
self.storkDelegate?.didDismissStorkByTap?()
|
||||
})
|
||||
}
|
||||
|
||||
public func dismissWithConfirmation(prepare: (()->())?, completion: (()->())?) {
|
||||
|
||||
let dismiss = {
|
||||
self.presentingViewController.view.endEditing(true)
|
||||
self.presentedViewController.view.endEditing(true)
|
||||
self.presentedViewController.dismiss(animated: true, completion: {
|
||||
completion?()
|
||||
})
|
||||
}
|
||||
|
||||
guard let confirmDelegate = self.confirmDelegate else {
|
||||
dismiss()
|
||||
return
|
||||
}
|
||||
|
||||
if self.workConfirmation { return }
|
||||
|
||||
if confirmDelegate.needConfirm {
|
||||
prepare?()
|
||||
self.workConfirmation = true
|
||||
confirmDelegate.confirm({ (isConfirmed) in
|
||||
self.workConfirmation = false
|
||||
self.afterReleaseDismissing = false
|
||||
if isConfirmed {
|
||||
dismiss()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
|
||||
@objc func handlePan(gestureRecognizer: UIPanGestureRecognizer) {
|
||||
guard gestureRecognizer.isEqual(self.pan), self.swipeToDismissEnabled else { return }
|
||||
|
||||
@@ -321,11 +398,8 @@ extension SPStorkPresentationController {
|
||||
case .ended:
|
||||
self.workGester = false
|
||||
let translation = gestureRecognizer.translation(in: presentedView).y
|
||||
if translation >= self.translateForDismiss {
|
||||
self.presentedViewController.dismiss(animated: true, completion: {
|
||||
self.storkDelegate?.didDismissStorkBySwipe?()
|
||||
})
|
||||
} else {
|
||||
|
||||
let toDefault = {
|
||||
self.indicatorView.style = .arrow
|
||||
UIView.animate(
|
||||
withDuration: 0.6,
|
||||
@@ -339,6 +413,14 @@ extension SPStorkPresentationController {
|
||||
self.gradeView.alpha = self.alpha
|
||||
})
|
||||
}
|
||||
|
||||
if translation >= self.translateForDismiss {
|
||||
self.dismissWithConfirmation(prepare: toDefault, completion: {
|
||||
self.storkDelegate?.didDismissStorkBySwipe?()
|
||||
})
|
||||
} else {
|
||||
toDefault()
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
@@ -388,7 +470,7 @@ extension SPStorkPresentationController {
|
||||
|
||||
let elasticThreshold: CGFloat = 120
|
||||
let translationFactor: CGFloat = 1 / 2
|
||||
|
||||
|
||||
if translation >= 0 {
|
||||
let translationForModal: CGFloat = {
|
||||
if translation >= elasticThreshold {
|
||||
@@ -414,8 +496,10 @@ extension SPStorkPresentationController {
|
||||
let afterRealseDismissing = (translation >= self.translateForDismiss)
|
||||
if afterRealseDismissing != self.afterReleaseDismissing {
|
||||
self.afterReleaseDismissing = afterRealseDismissing
|
||||
if self.hapticMoments.contains(.willDismissIfRelease) {
|
||||
self.feedbackGenerator.impactOccurred()
|
||||
if !self.workConfirmation {
|
||||
if self.hapticMoments.contains(.willDismissIfRelease) {
|
||||
self.feedbackGenerator.impactOccurred()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -429,10 +513,7 @@ extension SPStorkPresentationController {
|
||||
guard let containerView = containerView else { return }
|
||||
self.updateSnapshotAspectRatio()
|
||||
if presentedViewController.view.isDescendant(of: containerView) {
|
||||
UIView.animate(withDuration: 0.1) { [weak self] in
|
||||
guard let `self` = self else { return }
|
||||
self.presentedViewController.view.frame = self.frameOfPresentedViewInContainerView
|
||||
}
|
||||
self.presentedViewController.view.frame = self.frameOfPresentedViewInContainerView
|
||||
}
|
||||
}
|
||||
|
||||
@@ -448,11 +529,9 @@ extension SPStorkPresentationController {
|
||||
}
|
||||
|
||||
private func updateLayoutIndicator() {
|
||||
guard let presentedView = self.presentedView else { return }
|
||||
self.indicatorView.style = .line
|
||||
self.indicatorView.sizeToFit()
|
||||
self.indicatorView.frame.origin.y = 12
|
||||
self.indicatorView.center.x = presentedView.frame.width / 2
|
||||
self.indicatorView.style = .arrow
|
||||
}
|
||||
|
||||
private func updateLayoutCloseButton() {
|
||||
|
||||
@@ -29,11 +29,13 @@ public final class SPStorkTransitioningDelegate: NSObject, UIViewControllerTrans
|
||||
public var showIndicator: Bool = true
|
||||
public var indicatorColor: UIColor = UIColor.init(red: 202/255, green: 201/255, blue: 207/255, alpha: 1)
|
||||
public var hideIndicatorWhenScroll: Bool = false
|
||||
public var indicatorMode: SPStorkArrowMode = .auto
|
||||
public var customHeight: CGFloat? = nil
|
||||
public var translateForDismiss: CGFloat = 200
|
||||
public var cornerRadius: CGFloat = 10
|
||||
public var hapticMoments: [SPStorkHapticMoments] = [.willDismissIfRelease]
|
||||
public weak var storkDelegate: SPStorkControllerDelegate? = nil
|
||||
public weak var confirmDelegate: SPStorkControllerConfirmDelegate? = nil
|
||||
|
||||
public func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
|
||||
let controller = SPStorkPresentationController(presentedViewController: presented, presenting: presenting)
|
||||
@@ -43,12 +45,14 @@ public final class SPStorkTransitioningDelegate: NSObject, UIViewControllerTrans
|
||||
controller.showIndicator = self.showIndicator
|
||||
controller.indicatorColor = self.indicatorColor
|
||||
controller.hideIndicatorWhenScroll = self.hideIndicatorWhenScroll
|
||||
controller.indicatorMode = self.indicatorMode
|
||||
controller.customHeight = self.customHeight
|
||||
controller.translateForDismiss = self.translateForDismiss
|
||||
controller.cornerRadius = self.cornerRadius
|
||||
controller.hapticMoments = self.hapticMoments
|
||||
controller.transitioningDelegate = self
|
||||
controller.storkDelegate = self.storkDelegate
|
||||
controller.confirmDelegate = self.confirmDelegate
|
||||
return controller
|
||||
}
|
||||
|
||||
|
||||
@@ -25,23 +25,41 @@ open class SPStorkIndicatorView: UIView {
|
||||
|
||||
var style: Style = .line {
|
||||
didSet {
|
||||
switch self.style {
|
||||
case .line:
|
||||
self.animate {
|
||||
self.leftView.transform = .identity
|
||||
self.rightView.transform = .identity
|
||||
}
|
||||
case .arrow:
|
||||
self.animate {
|
||||
let angle = CGFloat(20 * Float.pi / 180)
|
||||
self.leftView.transform = CGAffineTransform.init(rotationAngle: angle)
|
||||
self.rightView.transform = CGAffineTransform.init(rotationAngle: -angle)
|
||||
if self.mode == .auto {
|
||||
switch self.style {
|
||||
case .line:
|
||||
self.animate {
|
||||
self.leftView.transform = .identity
|
||||
self.rightView.transform = .identity
|
||||
}
|
||||
case .arrow:
|
||||
self.animate {
|
||||
let angle = CGFloat(20 * Float.pi / 180)
|
||||
self.leftView.transform = CGAffineTransform.init(rotationAngle: angle)
|
||||
self.rightView.transform = CGAffineTransform.init(rotationAngle: -angle)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if self.mode == .alwaysArrow {
|
||||
self.leftView.layer.removeAllAnimations()
|
||||
self.rightView.layer.removeAllAnimations()
|
||||
self.leftView.transform = .identity
|
||||
self.rightView.transform = .identity
|
||||
let angle = CGFloat(20 * Float.pi / 180)
|
||||
self.leftView.transform = CGAffineTransform.init(rotationAngle: angle)
|
||||
self.rightView.transform = CGAffineTransform.init(rotationAngle: -angle)
|
||||
}
|
||||
|
||||
if self.mode == .alwaysLine {
|
||||
self.leftView.transform = .identity
|
||||
self.rightView.transform = .identity
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var mode: SPStorkArrowMode = .auto
|
||||
|
||||
var color: UIColor = UIColor.init(red: 202/255, green: 201/255, blue: 207/255, alpha: 1) {
|
||||
didSet {
|
||||
self.leftView.backgroundColor = self.color
|
||||
@@ -66,6 +84,10 @@ open class SPStorkIndicatorView: UIView {
|
||||
|
||||
override open func sizeToFit() {
|
||||
super.sizeToFit()
|
||||
|
||||
self.leftView.transform = .identity
|
||||
self.rightView.transform = .identity
|
||||
|
||||
self.frame = CGRect.init(x: self.frame.origin.x, y: self.frame.origin.y, width: 36, height: 13)
|
||||
|
||||
let height: CGFloat = 5
|
||||
|
||||