diff --git a/Assets/Readme/Miniature - Cart.svg b/Assets/Readme/Miniature - Cart.svg new file mode 100644 index 0000000..09008ea --- /dev/null +++ b/Assets/Readme/Miniature - Cart.svg @@ -0,0 +1,10 @@ + + + + Miniature - Cart + Created with Sketch. + + + + + \ No newline at end of file diff --git a/Assets/Sketch/Presets.sketch b/Assets/Sketch/Presets.sketch index 0a764f2..c10a957 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 02b8502..94d424e 100644 --- a/Example/Controllers/ViewController.swift +++ b/Example/Controllers/ViewController.swift @@ -17,6 +17,7 @@ class ViewController: UITableViewController { Alert(key: "Bolt", preset: .bolt, title: "Power", subtitle: "Now turned on"), Alert(key: "Eject", preset: .eject, title: "Eject complete", subtitle: nil), Alert(key: "Card", preset: .card, title: "Payment sent", subtitle: "Thanks for donate"), + Alert(key: "Cart", preset: .cart, title: "Add to order", subtitle: "It wait in cart"), Alert(key: "Like", preset: .like, title: "Thanks for feedback", subtitle: "It helped us"), Alert(key: "Dislike", preset: .dislike, title: "Thanks for feedback", subtitle: "It helped us"), Alert(key: "Privacy", preset: .privacy, title: "Privacy accepted", subtitle: "You privacy it important"), diff --git a/Readme.md b/Readme.md index 4c473bb..fa91fe8 100644 --- a/Readme.md +++ b/Readme.md @@ -22,6 +22,7 @@ And other + diff --git a/SPAlert.podspec b/SPAlert.podspec index 6111a18..2dd341a 100644 --- a/SPAlert.podspec +++ b/SPAlert.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "SPAlert" - s.version = "2.0.25" + s.version = "2.0.26" s.summary = "Native alert from Apple Music & Feedback. Contains Done, Heart & Message and other 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 663e53d..cc9cddd 100644 --- a/SPAlert.xcodeproj/project.pbxproj +++ b/SPAlert.xcodeproj/project.pbxproj @@ -30,6 +30,7 @@ F42DE05623AD7D94007CCE29 /* SPAlertIconPrivacyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F42DE05523AD7D94007CCE29 /* SPAlertIconPrivacyView.swift */; }; F45970B423A578A50092CE7C /* SPAlertIconCardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F45970B323A578A50092CE7C /* SPAlertIconCardView.swift */; }; F459720223A841C00092CE7C /* SPAlertIconRotateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F459720123A841C00092CE7C /* SPAlertIconRotateView.swift */; }; + F45DDF2823AFFF3000CA3956 /* SPAlertIconCartView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F45DDF2723AFFF3000CA3956 /* SPAlertIconCartView.swift */; }; F46AAEFE2392E97200BE9131 /* SPAlertIconMessageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F46AAEFD2392E97200BE9131 /* SPAlertIconMessageView.swift */; }; F47D2FA6239D718400A346A5 /* SPAlertIconBoltView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F47D2FA5239D718400A346A5 /* SPAlertIconBoltView.swift */; }; F47EE19D23959ADB00B02DF2 /* SPAlertIconShuffleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F47EE19C23959ADB00B02DF2 /* SPAlertIconShuffleView.swift */; }; @@ -100,6 +101,7 @@ F42DE05523AD7D94007CCE29 /* SPAlertIconPrivacyView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPAlertIconPrivacyView.swift; sourceTree = ""; }; F45970B323A578A50092CE7C /* SPAlertIconCardView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPAlertIconCardView.swift; sourceTree = ""; }; F459720123A841C00092CE7C /* SPAlertIconRotateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPAlertIconRotateView.swift; sourceTree = ""; }; + F45DDF2723AFFF3000CA3956 /* SPAlertIconCartView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPAlertIconCartView.swift; sourceTree = ""; }; F46AAEFD2392E97200BE9131 /* SPAlertIconMessageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPAlertIconMessageView.swift; sourceTree = ""; }; F47D2FA5239D718400A346A5 /* SPAlertIconBoltView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPAlertIconBoltView.swift; sourceTree = ""; }; F47EE19C23959ADB00B02DF2 /* SPAlertIconShuffleView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPAlertIconShuffleView.swift; sourceTree = ""; }; @@ -211,6 +213,7 @@ F4146EB123AAA18100AE7658 /* SPAlertIconLikeView.swift */, F42DE05323AD7D8A007CCE29 /* SPAlertIconDislikeView.swift */, F42DE05523AD7D94007CCE29 /* SPAlertIconPrivacyView.swift */, + F45DDF2723AFFF3000CA3956 /* SPAlertIconCartView.swift */, ); path = Icons; sourceTree = ""; @@ -418,6 +421,7 @@ F41204EC2382AC9B009C2AC7 /* SPAlertIconDoneView.swift in Sources */, F41204E92382AC9B009C2AC7 /* SPAlertView.swift in Sources */, F421EFF12398684E000A566D /* SPAlertIconFlagView.swift in Sources */, + F45DDF2823AFFF3000CA3956 /* SPAlertIconCartView.swift in Sources */, F47EE19D23959ADB00B02DF2 /* SPAlertIconShuffleView.swift in Sources */, F4D3CD58238DA9FE006C3DE2 /* SPAlertIconMoonView.swift in Sources */, F4D3CD5A238DAA49006C3DE2 /* SPAlertIconStarView.swift in Sources */, diff --git a/Source/SPAlert/Models/SPAlertPreset.swift b/Source/SPAlert/Models/SPAlertPreset.swift index b32e1c4..49da2c0 100644 --- a/Source/SPAlert/Models/SPAlertPreset.swift +++ b/Source/SPAlert/Models/SPAlertPreset.swift @@ -48,6 +48,7 @@ public enum SPAlertPreset { case like case dislike case privacy + case cart /** View for preset. Wrap to `UIView`. @@ -98,6 +99,8 @@ public enum SPAlertPreset { return SPAlertIconDislikeView() case .privacy: return SPAlertIconPrivacyView() + case .cart: + return SPAlertIconCartView() } } @@ -179,6 +182,14 @@ public enum SPAlertPreset { layout.iconHeight = 108 layout.bottomIconSpace = 25 return layout + case .cart: + var layout = SPAlertLayout() + layout.topSpace = 45 + layout.bottomSpace = 31 + layout.iconWidth = 108 + layout.iconHeight = 108 + layout.bottomIconSpace = 25 + return layout case .flag: var layout = SPAlertLayout() layout.topSpace = 49 @@ -335,6 +346,8 @@ public enum SPAlertPreset { return .error case .privacy: return .success + case .cart: + return .success } } } diff --git a/Source/SPAlert/Views/Icons/SPAlertIconCartView.swift b/Source/SPAlert/Views/Icons/SPAlertIconCartView.swift new file mode 100644 index 0000000..2814bea --- /dev/null +++ b/Source/SPAlert/Views/Icons/SPAlertIconCartView.swift @@ -0,0 +1,128 @@ +// 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 SPAlertIconCartView: UIView { + + init() { + super.init(frame: .zero) + self.backgroundColor = .clear + } + + required init?(coder aDecoder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + public override func draw(_ rect: CGRect) { + super.draw(rect) + CartDraw.draw(frame: rect, resizing: .aspectFit, fillColor: self.tintColor) + } + + class CartDraw: NSObject { + + @objc dynamic public class func draw(frame targetFrame: CGRect = CGRect(x: 0, y: 0, width: 60, height: 56), resizing: ResizingBehavior = .aspectFit, fillColor: UIColor = UIColor(red: 0.349, green: 0.345, blue: 0.353, alpha: 1.000)) { + let context = UIGraphicsGetCurrentContext()! + context.saveGState() + let resizedFrame: CGRect = resizing.apply(rect: CGRect(x: 0, y: 0, width: 72, height: 62), target: targetFrame) + context.translateBy(x: resizedFrame.minX, y: resizedFrame.minY) + context.scaleBy(x: resizedFrame.width / 72, y: resizedFrame.height / 62) + let bezierPath = UIBezierPath() + bezierPath.move(to: CGPoint(x: 3, y: 6.12)) + bezierPath.addCurve(to: CGPoint(x: 5.09, y: 8.27), controlPoint1: CGPoint(x: 3, y: 7.28), controlPoint2: CGPoint(x: 3.96, y: 8.27)) + bezierPath.addLine(to: CGPoint(x: 14.65, y: 8.27)) + bezierPath.addLine(to: CGPoint(x: 19.18, y: 39.32)) + bezierPath.addCurve(to: CGPoint(x: 25.99, y: 45.85), controlPoint1: CGPoint(x: 19.77, y: 43.34), controlPoint2: CGPoint(x: 21.89, y: 45.85)) + bezierPath.addLine(to: CGPoint(x: 58.99, y: 45.85)) + bezierPath.addCurve(to: CGPoint(x: 61.06, y: 43.73), controlPoint1: CGPoint(x: 60.1, y: 45.85), controlPoint2: CGPoint(x: 61.06, y: 44.95)) + bezierPath.addCurve(to: CGPoint(x: 58.99, y: 41.61), controlPoint1: CGPoint(x: 61.06, y: 42.52), controlPoint2: CGPoint(x: 60.1, y: 41.61)) + bezierPath.addLine(to: CGPoint(x: 26.47, y: 41.61)) + bezierPath.addCurve(to: CGPoint(x: 23.62, y: 38.76), controlPoint1: CGPoint(x: 24.86, y: 41.61), controlPoint2: CGPoint(x: 23.87, y: 40.48)) + bezierPath.addLine(to: CGPoint(x: 23.16, y: 35.79)) + bezierPath.addLine(to: CGPoint(x: 59.05, y: 35.79)) + bezierPath.addCurve(to: CGPoint(x: 65.85, y: 29.46), controlPoint1: CGPoint(x: 63.09, y: 35.79), controlPoint2: CGPoint(x: 65.2, y: 33.35)) + bezierPath.addLine(to: CGPoint(x: 68.16, y: 14.24)) + bezierPath.addCurve(to: CGPoint(x: 68.27, y: 13.16), controlPoint1: CGPoint(x: 68.21, y: 13.87), controlPoint2: CGPoint(x: 68.27, y: 13.42)) + bezierPath.addCurve(to: CGPoint(x: 65.7, y: 10.87), controlPoint1: CGPoint(x: 68.27, y: 11.81), controlPoint2: CGPoint(x: 67.25, y: 10.87)) + bezierPath.addLine(to: CGPoint(x: 19.54, y: 10.87)) + bezierPath.addLine(to: CGPoint(x: 18.98, y: 7.28)) + bezierPath.addCurve(to: CGPoint(x: 15.02, y: 4), controlPoint1: CGPoint(x: 18.7, y: 5.1), controlPoint2: CGPoint(x: 17.9, y: 4)) + bezierPath.addLine(to: CGPoint(x: 5.09, y: 4)) + bezierPath.addCurve(to: CGPoint(x: 3, y: 6.12), controlPoint1: CGPoint(x: 3.96, y: 4), controlPoint2: CGPoint(x: 3, y: 4.99)) + bezierPath.close() + bezierPath.move(to: CGPoint(x: 23.62, y: 55.02)) + bezierPath.addCurve(to: CGPoint(x: 28.23, y: 59.6), controlPoint1: CGPoint(x: 23.62, y: 57.59), controlPoint2: CGPoint(x: 25.65, y: 59.6)) + bezierPath.addCurve(to: CGPoint(x: 32.81, y: 55.02), controlPoint1: CGPoint(x: 30.77, y: 59.6), controlPoint2: CGPoint(x: 32.81, y: 57.59)) + bezierPath.addCurve(to: CGPoint(x: 28.23, y: 50.44), controlPoint1: CGPoint(x: 32.81, y: 52.47), controlPoint2: CGPoint(x: 30.77, y: 50.44)) + bezierPath.addCurve(to: CGPoint(x: 23.62, y: 55.02), controlPoint1: CGPoint(x: 25.65, y: 50.44), controlPoint2: CGPoint(x: 23.62, y: 52.47)) + bezierPath.close() + bezierPath.move(to: CGPoint(x: 50.06, y: 55.02)) + bezierPath.addCurve(to: CGPoint(x: 54.67, y: 50.44), controlPoint1: CGPoint(x: 50.06, y: 52.47), controlPoint2: CGPoint(x: 52.12, y: 50.44)) + bezierPath.addCurve(to: CGPoint(x: 59.28, y: 55.02), controlPoint1: CGPoint(x: 57.24, y: 50.44), controlPoint2: CGPoint(x: 59.28, y: 52.47)) + bezierPath.addCurve(to: CGPoint(x: 54.67, y: 59.6), controlPoint1: CGPoint(x: 59.28, y: 57.59), controlPoint2: CGPoint(x: 57.24, y: 59.6)) + bezierPath.addCurve(to: CGPoint(x: 50.06, y: 55.02), controlPoint1: CGPoint(x: 52.12, y: 59.6), controlPoint2: CGPoint(x: 50.06, y: 57.59)) + bezierPath.close() + fillColor.setFill() + bezierPath.fill() + context.restoreGState() + } + + @objc(StyleKitNameResizingBehavior) + public enum ResizingBehavior: Int { + + case aspectFit + case aspectFill + case stretch + case center + + public func apply(rect: CGRect, target: CGRect) -> CGRect { + if rect == target || target == CGRect.zero { + return rect + } + + var scales = CGSize.zero + scales.width = abs(target.width / rect.width) + scales.height = abs(target.height / rect.height) + + switch self { + case .aspectFit: + scales.width = min(scales.width, scales.height) + scales.height = scales.width + case .aspectFill: + scales.width = max(scales.width, scales.height) + scales.height = scales.width + case .stretch: + break + case .center: + scales.width = 1 + scales.height = 1 + } + + var result = rect.standardized + result.size.width *= scales.width + result.size.height *= scales.height + result.origin.x = target.minX + (target.width - result.width) / 2 + result.origin.y = target.minY + (target.height - result.height) / 2 + return result + } + } + } +}