diff --git a/Assets/Readme/Miniature - Add.svg b/Assets/Readme/Miniature - Add.svg new file mode 100644 index 0000000..0f4d962 --- /dev/null +++ b/Assets/Readme/Miniature - Add.svg @@ -0,0 +1,13 @@ + + + + Miniature - Add + Created with Sketch. + + + + + + + + \ No newline at end of file diff --git a/Assets/Sketch/Presets.sketch b/Assets/Sketch/Presets.sketch index 903f325..7f3bf9a 100644 Binary files a/Assets/Sketch/Presets.sketch and b/Assets/Sketch/Presets.sketch differ diff --git a/Example/Controllers/ViewController.swift b/Example/Controllers/ViewController.swift index 92a5e75..20e63be 100644 --- a/Example/Controllers/ViewController.swift +++ b/Example/Controllers/ViewController.swift @@ -8,6 +8,7 @@ class ViewController: UITableViewController { Alert(key: "Heart", preset: .heart, title: "Love", subtitle: "We'll recommend more like this for you"), Alert(key: "Doc", preset: .doc, title: "Document saved", subtitle: "See in folder new file"), Alert(key: "Bookmark", preset: .bookmark, title: "Added to bookmark", subtitle: "See bookmarks screen"), + Alert(key: "Add", preset: .add, title: "Added to Folder", subtitle: nil), Alert(key: "Error", preset: .error, title: "Oops", subtitle: "Please try again later"), Alert(key: "Message", preset: nil, title: nil, subtitle: "Email required") ] diff --git a/Readme.md b/Readme.md index 2906854..d7a39f4 100644 --- a/Readme.md +++ b/Readme.md @@ -76,6 +76,7 @@ For now supporting `Done`, `Heart`, `Doc`, `Error`, `Bookmark` & `Message` prese

+ diff --git a/SPAlert.podspec b/SPAlert.podspec index 7920d3f..79d044d 100644 --- a/SPAlert.podspec +++ b/SPAlert.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "SPAlert" - s.version = "2.0.4" + s.version = "2.0.5" s.summary = "Native alert from Apple Music & Feedback. Contains Done, Heart & Message presets." s.homepage = "https://github.com/IvanVorobei/SPAlert" s.source = { :git => "https://github.com/IvanVorobei/SPAlert.git", :tag => s.version } diff --git a/SPAlert.xcodeproj/project.pbxproj b/SPAlert.xcodeproj/project.pbxproj index cdb91c4..bc034d8 100644 --- a/SPAlert.xcodeproj/project.pbxproj +++ b/SPAlert.xcodeproj/project.pbxproj @@ -25,6 +25,7 @@ F412052B2382AF64009C2AC7 /* SPAlertLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = F41205222382AEFA009C2AC7 /* SPAlertLayout.swift */; }; F4A5A92C2388792F00B0DFE0 /* SPAlertIconBookmarkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4A5A92B2388792F00B0DFE0 /* SPAlertIconBookmarkView.swift */; }; F4A8361A2385588300EB32E0 /* SPAlertIconDocView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4A836192385588300EB32E0 /* SPAlertIconDocView.swift */; }; + F4CA67B5238ABD0100E72F79 /* SPAlertIconAddView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4CA67B4238ABD0100E72F79 /* SPAlertIconAddView.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -78,6 +79,7 @@ F41205262382AF29009C2AC7 /* SPAlertIconAnimatable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPAlertIconAnimatable.swift; sourceTree = ""; }; F4A5A92B2388792F00B0DFE0 /* SPAlertIconBookmarkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPAlertIconBookmarkView.swift; sourceTree = ""; }; F4A836192385588300EB32E0 /* SPAlertIconDocView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPAlertIconDocView.swift; sourceTree = ""; }; + F4CA67B4238ABD0100E72F79 /* SPAlertIconAddView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPAlertIconAddView.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -160,6 +162,7 @@ 706F89492383277500ECF5D1 /* SPAlertIconErrorView.swift */, F4A836192385588300EB32E0 /* SPAlertIconDocView.swift */, F4A5A92B2388792F00B0DFE0 /* SPAlertIconBookmarkView.swift */, + F4CA67B4238ABD0100E72F79 /* SPAlertIconAddView.swift */, ); path = Icons; sourceTree = ""; @@ -363,6 +366,7 @@ F41204E92382AC9B009C2AC7 /* SPAlertView.swift in Sources */, 706F894A2383277500ECF5D1 /* SPAlertIconErrorView.swift in Sources */, F41205292382AF5C009C2AC7 /* SPAlertIconAnimatable.swift in Sources */, + F4CA67B5238ABD0100E72F79 /* SPAlertIconAddView.swift in Sources */, F41204EB2382AC9B009C2AC7 /* SPAlertIconHeartView.swift in Sources */, F4A8361A2385588300EB32E0 /* SPAlertIconDocView.swift in Sources */, F412052B2382AF64009C2AC7 /* SPAlertLayout.swift in Sources */, diff --git a/Source/SPAlert/Models/SPAlertPreset.swift b/Source/SPAlert/Models/SPAlertPreset.swift index 51e8253..832c418 100644 --- a/Source/SPAlert/Models/SPAlertPreset.swift +++ b/Source/SPAlert/Models/SPAlertPreset.swift @@ -30,6 +30,7 @@ public enum SPAlertPreset { case heart case doc case bookmark + case add case error /** @@ -45,6 +46,8 @@ public enum SPAlertPreset { return SPAlertIconDocView() case .bookmark: return SPAlertIconBookmarkView() + case .add: + return SPAlertIconAddView() case .error: return SPAlertIconErrorView() } @@ -81,19 +84,27 @@ public enum SPAlertPreset { return layout case .bookmark: var layout = SPAlertLayout() - layout.topSpace = 51 + layout.topSpace = 57 layout.bottomSpace = 29 layout.iconWidth = 112 - layout.iconHeight = 77 - layout.bottomIconSpace = 35 + layout.iconHeight = 94 + layout.bottomIconSpace = 36 + return layout + case .add: + var layout = SPAlertLayout() + layout.topSpace = 63 + layout.bottomSpace = 29 + layout.iconWidth = 106 + layout.iconHeight = 106 + layout.bottomIconSpace = 39 return layout case .error: var layout = SPAlertLayout() layout.topSpace = 63 layout.bottomSpace = 29 - layout.iconWidth = 112 - layout.iconHeight = 112 - layout.bottomIconSpace = 35 + layout.iconWidth = 100 + layout.iconHeight = 100 + layout.bottomIconSpace = 37 return layout } } @@ -111,6 +122,8 @@ public enum SPAlertPreset { return .success case .bookmark: return .success + case .add: + return .success case .error: return .error } diff --git a/Source/SPAlert/Views/Icons/SPAlertIconAddView.swift b/Source/SPAlert/Views/Icons/SPAlertIconAddView.swift new file mode 100644 index 0000000..498691b --- /dev/null +++ b/Source/SPAlert/Views/Icons/SPAlertIconAddView.swift @@ -0,0 +1,84 @@ +// The MIT License (MIT) +// Copyright © 2019 Ivan Vorobei (ivanvorobei@icloud.com) +// +// 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 SPAlertIconAddView: UIView, SPAlertIconAnimatable { + + public func animate() { + animateLeftToRightLine() + animateBottomFromTopLine() + } + + private func animateLeftToRightLine() { + let length = frame.width + + let topToBottomLine = UIBezierPath() + topToBottomLine.move(to: CGPoint(x: length * 0, y: length * 0.5)) + topToBottomLine.addLine(to: CGPoint(x: length * 1, y: length * 0.5)) + + let animatableLayer = CAShapeLayer() + animatableLayer.path = topToBottomLine.cgPath + animatableLayer.fillColor = UIColor.clear.cgColor + animatableLayer.strokeColor = tintColor?.cgColor + animatableLayer.lineWidth = 9 + animatableLayer.lineCap = .round + animatableLayer.lineJoin = .round + animatableLayer.strokeEnd = 0 + self.layer.addSublayer(animatableLayer) + + let animation = CABasicAnimation(keyPath: "strokeEnd") + animation.duration = 0.3 + animation.fromValue = 0 + animation.toValue = 1 + animation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut) + + animatableLayer.strokeEnd = 1 + animatableLayer.add(animation, forKey: "animation") + } + + private func animateBottomFromTopLine() { + let length = frame.width + + let bottomToTopLine = UIBezierPath() + bottomToTopLine.move(to: CGPoint(x: length * 0.5, y: length * 1)) + bottomToTopLine.addLine(to: CGPoint(x: length * 0.5, y: length * 0)) + + let animatableLayer = CAShapeLayer() + animatableLayer.path = bottomToTopLine.cgPath + animatableLayer.fillColor = UIColor.clear.cgColor + animatableLayer.strokeColor = tintColor?.cgColor + animatableLayer.lineWidth = 9 + animatableLayer.lineCap = .round + animatableLayer.lineJoin = .round + animatableLayer.strokeEnd = 0 + self.layer.addSublayer(animatableLayer) + + let animation = CABasicAnimation(keyPath: "strokeEnd") + animation.duration = 0.3 + animation.fromValue = 0 + animation.toValue = 1 + animation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut) + + animatableLayer.strokeEnd = 1 + animatableLayer.add(animation, forKey: "animation") + } +} diff --git a/Source/SPAlert/Views/Icons/SPAlertIconErrorView.swift b/Source/SPAlert/Views/Icons/SPAlertIconErrorView.swift index 018d80c..203771b 100644 --- a/Source/SPAlert/Views/Icons/SPAlertIconErrorView.swift +++ b/Source/SPAlert/Views/Icons/SPAlertIconErrorView.swift @@ -32,8 +32,8 @@ public class SPAlertIconErrorView: UIView, SPAlertIconAnimatable { let length = frame.width let topToBottomLine = UIBezierPath() - topToBottomLine.move(to: CGPoint(x: length * 0.1, y: length * 0.1)) - topToBottomLine.addLine(to: CGPoint(x: length * 0.9, y: length * 0.9)) + topToBottomLine.move(to: CGPoint(x: length * 0, y: length * 0)) + topToBottomLine.addLine(to: CGPoint(x: length * 1, y: length * 1)) let animatableLayer = CAShapeLayer() animatableLayer.path = topToBottomLine.cgPath @@ -46,7 +46,7 @@ public class SPAlertIconErrorView: UIView, SPAlertIconAnimatable { self.layer.addSublayer(animatableLayer) let animation = CABasicAnimation(keyPath: "strokeEnd") - animation.duration = 0.3 + animation.duration = 0.22 animation.fromValue = 0 animation.toValue = 1 animation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut) @@ -59,8 +59,8 @@ public class SPAlertIconErrorView: UIView, SPAlertIconAnimatable { let length = frame.width let bottomToTopLine = UIBezierPath() - bottomToTopLine.move(to: CGPoint(x: length * 0.1, y: length * 0.9)) - bottomToTopLine.addLine(to: CGPoint(x: length * 0.9, y: length * 0.1)) + bottomToTopLine.move(to: CGPoint(x: length * 0, y: length * 1)) + bottomToTopLine.addLine(to: CGPoint(x: length * 1, y: length * 0)) let animatableLayer = CAShapeLayer() animatableLayer.path = bottomToTopLine.cgPath @@ -73,7 +73,7 @@ public class SPAlertIconErrorView: UIView, SPAlertIconAnimatable { self.layer.addSublayer(animatableLayer) let animation = CABasicAnimation(keyPath: "strokeEnd") - animation.duration = 0.3 + animation.duration = 0.22 animation.fromValue = 0 animation.toValue = 1 animation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)