From ebc2d5c4d48daec53f7aee33528ae97cf1075ecd Mon Sep 17 00:00:00 2001 From: Ivan Vorobei Date: Sat, 14 Oct 2023 22:59:53 +0300 Subject: [PATCH] Allow customisation. Added support SwiftUI. --- README.md | 44 ++++++++++++++++--- SPAlert.podspec | 2 +- Sources/AlertKit/AlertKitAPI.swift | 5 +++ .../Extensions/SwiftUIExtension.swift | 19 ++++++++ .../AlertKit/Extensions/UIFontExtension.swift | 21 --------- .../AlertKit/Icons/AlertIconDoneView.swift | 1 - .../Views/AlertAppleMusic16View.swift | 33 +++++--------- .../Views/AlertAppleMusic17View.swift | 31 +++++-------- .../AlertKit/Views/AlertViewProtocol.swift | 13 ++++++ 9 files changed, 98 insertions(+), 71 deletions(-) create mode 100644 Sources/AlertKit/Extensions/SwiftUIExtension.swift create mode 100644 Sources/AlertKit/Views/AlertViewProtocol.swift diff --git a/README.md b/README.md index ba352f6..998f8cf 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ I tried to recreate Apple's alerts as much as possible. You can find these alert ![Alert Kit v5](https://cdn.sparrowcode.io/github/alertkit/v5/preview-v1_2.png) -For run alert just call this: +For UIKit & SwiftUI call this: ```swift AlertKitAPI.present( @@ -27,7 +27,7 @@ public enum AlertViewStyle { ``` ### Community - +

@@ -35,17 +35,23 @@ public enum AlertViewStyle { - - -

+## Navigate + +- [Installation](#installation) + - [Swift Package Manager](#swift-package-manager) + - [CocoaPods](#cocoapods) +- [SwiftUI](#swiftui) +- [Customisation](#customisation) +- [Apps Using](#apps-using) + ## Installation -Ready to use on iOS 13+. +Ready to use on iOS 13+. Supports iOS and visionOS. Working with `UIKit` and `SwiftUI`. ### Swift Package Manager @@ -59,7 +65,7 @@ or adding it to the `dependencies` of your `Package.swift`: ```swift dependencies: [ - .package(url: "https://github.com/sparrowcode/AlertKit", .upToNextMajor(from: "5.0.0")) + .package(url: "https://github.com/sparrowcode/AlertKit", .upToNextMajor(from: "5.1.0")) ] ``` @@ -80,11 +86,35 @@ pod 'SPAlert' If you prefer not to use any of dependency managers, you can integrate manually. Put `Sources/AlertKit` folder in your Xcode project. Make sure to enable `Copy items if needed` and `Create groups`. +## SwiftUI + +You can use basic way via AlertKitAPI or call via modifier: + +```swift +let alertView = AlertAppleMusic17View(title: "Hello", subtitle: nil, icon: .done) + +VStack {} + .alert(isPresent: $alertPresented, view: alertView) +``` + +## Customisation + +If you need customisation fonts, icon, colors or any other, make view: + +```swift +let alertView = AlertAppleMusic17View(title: "Added to Library", subtitle: nil, icon: .done) +// Change content color +alertView.contentColor = .systemBlue +// Change font +alertView.titleLabel.font = UIFont.systemFont(ofSize: 21) +``` + ## Apps Using

+ diff --git a/SPAlert.podspec b/SPAlert.podspec index 4eb75c0..75773ab 100644 --- a/SPAlert.podspec +++ b/SPAlert.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = 'SPAlert' - s.version = '5.0.1' + s.version = '5.1.0' s.summary = 'Native alert from Apple Music & Feedback. Contains Done, Heart & Message and other presets. Support SwiftUI.' s.homepage = 'https://github.com/sparrowcode/AlertKit' s.source = { :git => 'https://github.com/sparrowcode/AlertKit.git', :tag => s.version } diff --git a/Sources/AlertKit/AlertKitAPI.swift b/Sources/AlertKit/AlertKitAPI.swift index 6260262..1cd1653 100644 --- a/Sources/AlertKit/AlertKitAPI.swift +++ b/Sources/AlertKit/AlertKitAPI.swift @@ -2,6 +2,11 @@ import UIKit public enum AlertKitAPI { + public static func present(view: AlertViewProtocol, completion: @escaping ()->Void = {}) { + guard let window = UIApplication.shared.windows.filter({ $0.isKeyWindow }).first else { return } + view.present(on: window, completion: completion) + } + public static func present(title: String? = nil, subtitle: String? = nil, icon: AlertIcon? = nil, style: AlertViewStyle, haptic: AlertHaptic? = nil) { switch style { case .iOS16AppleMusic: diff --git a/Sources/AlertKit/Extensions/SwiftUIExtension.swift b/Sources/AlertKit/Extensions/SwiftUIExtension.swift new file mode 100644 index 0000000..c1a2bb5 --- /dev/null +++ b/Sources/AlertKit/Extensions/SwiftUIExtension.swift @@ -0,0 +1,19 @@ +import SwiftUI + +@available(iOS 13.0, *) +extension View { + + public func alert(isPresent: Binding, view: AlertViewProtocol) -> some View { + if isPresent.wrappedValue { + let alertCompletion = view.completion + let completion = { + isPresent.wrappedValue = false + alertCompletion?() + } + if let window = UIApplication.shared.windows.filter({ $0.isKeyWindow }).first { + view.present(on: window, completion: completion) + } + } + return self + } +} diff --git a/Sources/AlertKit/Extensions/UIFontExtension.swift b/Sources/AlertKit/Extensions/UIFontExtension.swift index 3848dba..221b5ff 100644 --- a/Sources/AlertKit/Extensions/UIFontExtension.swift +++ b/Sources/AlertKit/Extensions/UIFontExtension.swift @@ -1,24 +1,3 @@ -// The MIT License (MIT) -// Copyright © 2020 Ivan Vorobei (hello@ivanvorobei.io) -// -// 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 UIFont { diff --git a/Sources/AlertKit/Icons/AlertIconDoneView.swift b/Sources/AlertKit/Icons/AlertIconDoneView.swift index a8a6386..85ad855 100644 --- a/Sources/AlertKit/Icons/AlertIconDoneView.swift +++ b/Sources/AlertKit/Icons/AlertIconDoneView.swift @@ -24,7 +24,6 @@ public class AlertIconDoneView: UIView, AlertIconAnimatable { animatableLayer.path = animatablePath.cgPath animatableLayer.fillColor = UIColor.clear.cgColor animatableLayer.strokeColor = tintColor?.cgColor - //animatableLayer.lineWidth = 9 animatableLayer.lineWidth = lineThick animatableLayer.lineCap = .round animatableLayer.lineJoin = .round diff --git a/Sources/AlertKit/Views/AlertAppleMusic16View.swift b/Sources/AlertKit/Views/AlertAppleMusic16View.swift index 2e2d945..c5af32b 100644 --- a/Sources/AlertKit/Views/AlertAppleMusic16View.swift +++ b/Sources/AlertKit/Views/AlertAppleMusic16View.swift @@ -1,21 +1,28 @@ import UIKit -public class AlertAppleMusic16View: UIView { +public class AlertAppleMusic16View: UIView, AlertViewProtocol { open var dismissByTap: Bool = true open var dismissInTime: Bool = true open var duration: TimeInterval = 1.5 open var haptic: AlertHaptic? = nil - fileprivate let titleLabel: UILabel? - fileprivate let subtitleLabel: UILabel? - fileprivate let iconView: UIView? + public let titleLabel: UILabel? + public let subtitleLabel: UILabel? + public let iconView: UIView? + + public var contentColor = UIColor { trait in + switch trait.userInterfaceStyle { + case .dark: UIColor(red: 127 / 255, green: 127 / 255, blue: 129 / 255, alpha: 1) + default: UIColor(red: 88 / 255, green: 87 / 255, blue: 88 / 255, alpha: 1) + } + } fileprivate weak var viewForPresent: UIView? fileprivate var presentDismissDuration: TimeInterval = 0.2 fileprivate var presentDismissScale: CGFloat = 0.8 - var completion: (() -> Void)? = nil + open var completion: (() -> Void)? = nil private lazy var backgroundView: UIVisualEffectView = { let view: UIVisualEffectView = { @@ -114,22 +121,6 @@ public class AlertAppleMusic16View: UIView { open func present(on view: UIView, completion: @escaping ()->Void = {}) { - let contentColor = { - let darkColor = UIColor(red: 127 / 255, green: 127 / 255, blue: 129 / 255, alpha: 1) - let lightColor = UIColor(red: 88 / 255, green: 87 / 255, blue: 88 / 255, alpha: 1) - if #available(iOS 12.0, *) { - let interfaceStyle = view.traitCollection.userInterfaceStyle - switch interfaceStyle { - case .light: return lightColor - case .dark: return darkColor - case .unspecified: return lightColor - @unknown default: return lightColor - } - } else { - return lightColor - } - }() - self.titleLabel?.textColor = contentColor self.subtitleLabel?.textColor = contentColor self.iconView?.tintColor = contentColor diff --git a/Sources/AlertKit/Views/AlertAppleMusic17View.swift b/Sources/AlertKit/Views/AlertAppleMusic17View.swift index 0cda0f3..ddaeec8 100644 --- a/Sources/AlertKit/Views/AlertAppleMusic17View.swift +++ b/Sources/AlertKit/Views/AlertAppleMusic17View.swift @@ -1,15 +1,22 @@ import UIKit -public class AlertAppleMusic17View: UIView { +public class AlertAppleMusic17View: UIView, AlertViewProtocol { open var dismissByTap: Bool = true open var dismissInTime: Bool = true open var duration: TimeInterval = 1.5 open var haptic: AlertHaptic? = nil - fileprivate let titleLabel: UILabel? - fileprivate let subtitleLabel: UILabel? - fileprivate let iconView: UIView? + public let titleLabel: UILabel? + public let subtitleLabel: UILabel? + public let iconView: UIView? + + public var contentColor = UIColor { trait in + switch trait.userInterfaceStyle { + case .dark: UIColor(red: 127 / 255, green: 127 / 255, blue: 129 / 255, alpha: 1) + default: UIColor(red: 88 / 255, green: 87 / 255, blue: 88 / 255, alpha: 1) + } + } fileprivate weak var viewForPresent: UIView? fileprivate var presentDismissDuration: TimeInterval = 0.2 @@ -112,22 +119,6 @@ public class AlertAppleMusic17View: UIView { open func present(on view: UIView, completion: @escaping ()->Void = {}) { - let contentColor = { - let darkColor = UIColor(red: 127 / 255, green: 127 / 255, blue: 129 / 255, alpha: 1) - let lightColor = UIColor(red: 88 / 255, green: 87 / 255, blue: 88 / 255, alpha: 1) - if #available(iOS 12.0, *) { - let interfaceStyle = view.traitCollection.userInterfaceStyle - switch interfaceStyle { - case .light: return lightColor - case .dark: return darkColor - case .unspecified: return lightColor - @unknown default: return lightColor - } - } else { - return lightColor - } - }() - self.titleLabel?.textColor = contentColor self.subtitleLabel?.textColor = contentColor self.iconView?.tintColor = contentColor diff --git a/Sources/AlertKit/Views/AlertViewProtocol.swift b/Sources/AlertKit/Views/AlertViewProtocol.swift new file mode 100644 index 0000000..e0e0f1a --- /dev/null +++ b/Sources/AlertKit/Views/AlertViewProtocol.swift @@ -0,0 +1,13 @@ +import UIKit + +public protocol AlertViewProtocol { + + func present(on view: UIView, completion: @escaping ()->Void) + + var completion: (() -> Void)? { get set } +} + +extension AlertViewProtocol where Self: UIView { + + func present(on view: UIView, completion: @escaping ()->Void = {}) {} +}