fix: code review notes + added custom modifier for alerts
This commit is contained in:
parent
cfbf53faf8
commit
9a427adab7
|
|
@ -3,16 +3,26 @@
|
|||
Core UI elements: protocols, views and helpers.
|
||||
|
||||
## SwiftUI alerts
|
||||
> SwiftUI views should conform to protocol `SwiftUIAlertContext` to present alert
|
||||
> SwiftUI views should conform to protocol `SwiftUIAlertContext` to present alerts. This means that the view must implement the presentingViewController property. This controller is a context from which the alert will be shown.
|
||||
|
||||
```swift
|
||||
var body: some View {
|
||||
Button("Show custom alert with binding property") {
|
||||
alertDescription = factory.okAlert(title: "Title", message: "Message")
|
||||
isPresentedCustomAlert = true
|
||||
struct ContentView: View, SwiftUIAlertContext {
|
||||
|
||||
private let factory = AlertFactory()
|
||||
|
||||
@State private var alertDescription: AlertDescriptor
|
||||
@State private var isAlertPresented = false
|
||||
|
||||
var presentingViewController: UIViewController
|
||||
|
||||
var body: some View {
|
||||
Button("Show custom alert with binding property") {
|
||||
alertDescription = factory.okAlert(title: "Title", message: "Message")
|
||||
isAlertPresented = true
|
||||
}
|
||||
}
|
||||
.alert(isPresented: $isAlertPresented, on: self, alert: alertDescription)
|
||||
}
|
||||
.alert(isPresented: $isPresentedAlert, on: self, alert: alertDescription)
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
//
|
||||
// Copyright (c) 2022 Touch Instinct
|
||||
//
|
||||
// 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 SwiftUI
|
||||
import TISwiftUtils
|
||||
import TIUIKitCore
|
||||
|
||||
@available(iOS 13, *)
|
||||
struct AlertModifier: ViewModifier {
|
||||
|
||||
@Binding var isPresented: Bool
|
||||
|
||||
let context: AlertPresentationContext
|
||||
let alertDescriptor: AlertDescriptor
|
||||
let alertPresentable: AlertPresentable?
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
if isPresented {
|
||||
let completion: VoidClosure = {
|
||||
isPresented = false
|
||||
}
|
||||
|
||||
if let alertPresentable = alertPresentable {
|
||||
alertPresentable.present(on: context, completion: completion)
|
||||
} else {
|
||||
alertDescriptor.present(on: context, completion: completion)
|
||||
}
|
||||
}
|
||||
|
||||
return content
|
||||
}
|
||||
}
|
||||
|
|
@ -36,13 +36,10 @@ public extension View {
|
|||
on context: AlertPresentationContext,
|
||||
alert: AlertDescriptor) -> some View {
|
||||
|
||||
if isPresented.wrappedValue {
|
||||
alert.present(on: context) {
|
||||
isPresented.wrappedValue = false
|
||||
}
|
||||
}
|
||||
|
||||
return self
|
||||
modifier(AlertModifier(isPresented: isPresented,
|
||||
context: context,
|
||||
alertDescriptor: alert,
|
||||
alertPresentable: nil))
|
||||
}
|
||||
|
||||
/// Presents an alert with a description on a context with custom configuration of the alert when a given condition is true.
|
||||
|
|
@ -56,12 +53,9 @@ public extension View {
|
|||
alertDescriptor descriptor: AlertDescriptor,
|
||||
alertViewFactory: Closure<AlertDescriptor, AlertPresentable>) -> some View {
|
||||
|
||||
if isPresented.wrappedValue {
|
||||
alertViewFactory(descriptor).present(on: context) {
|
||||
isPresented.wrappedValue = false
|
||||
}
|
||||
}
|
||||
|
||||
return self
|
||||
modifier(AlertModifier(isPresented: isPresented,
|
||||
context: context,
|
||||
alertDescriptor: descriptor,
|
||||
alertPresentable: alertViewFactory(descriptor)))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,8 +27,32 @@ Core UI elements: protocols, views and helpers.
|
|||
Use to present alerts in a few lines of code. Can be used for UIKit and SwiftUI
|
||||
> You can initialize `AlertsFactory` with your own *LocalizationProvider* or use `DefaultAlertLocalizationProvider`
|
||||
|
||||
### Your view or view controller must implement PresentationContext protocol
|
||||
There are `UIKitAlertContext` protocol that are designed to make it easier to work with `AlertPresentationContext` protocol. By default, no changes need to be made for UIKit view controllers to make them conform to `UIKitAlertContext`.
|
||||
### Your view or view controller must implement AlertPresentationContext protocol
|
||||
The implementation of the protocol says that an alert can be shown from this object. Also there is a `UIKitAlertContext` protocol designed to make it easier to work with `AlertPresentationContext` protocol. By default, no changes need to be made for UIKit view controllers to make them conform to `UIKitAlertContext`.
|
||||
|
||||
### Your alert controller must implement AlertPresentable protocol
|
||||
The implementation of this protocol says that an alert can be shown from the context. By default, the standard `UIAlertController` conforms to the protocol. Accordingly, when using a custom alert, it must also conform to the protocol:
|
||||
|
||||
```swift
|
||||
import PopupDialog
|
||||
|
||||
extension PopupDialog: AlertPresentable {
|
||||
@discardableResult
|
||||
public func configured(with configuration: AlertDescriptor) -> Self {
|
||||
title = configuration.title
|
||||
|
||||
for action in configuration.actions {
|
||||
addButton(DefaultButton(title: action.title, action: action.action))
|
||||
}
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
public func present(on context: AlertPresentationContext, completion: VoidClosure?) {
|
||||
context.present(self, animated: true, completion: completion)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Custom alerts
|
||||
```swift
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ open class AlertFactory {
|
|||
/// - message: A text string used as the message of the alert.
|
||||
/// - tint: A color used as a tint color of the alert. Default color is UIColor.systemBlue.
|
||||
/// - actions: An array of actions of the alert.
|
||||
/// - Returns: Alert descriptor, which can be used to present alert view.
|
||||
/// - Returns: Alert descriptor which can be used to present alert view.
|
||||
open func alert(title: String? = nil,
|
||||
message: String? = nil,
|
||||
tint: UIColor = .systemBlue,
|
||||
|
|
@ -54,7 +54,7 @@ open class AlertFactory {
|
|||
/// - message: A text string used as the message of the sheet alert.
|
||||
/// - tint: A color used as a tint color of the sheet alert. Default color is UIColor.systemBlue.
|
||||
/// - actions: An array of actions of the sheet alert.
|
||||
/// - Returns: Alert descriptor, which can be used to present sheet alert view.
|
||||
/// - Returns: Alert descriptor which can be used to present sheet alert view.
|
||||
open func sheetAlert(title: String? = nil,
|
||||
message: String? = nil,
|
||||
tint: UIColor = .systemBlue,
|
||||
|
|
@ -72,7 +72,7 @@ open class AlertFactory {
|
|||
/// - title: A text string used as the title of the alert.
|
||||
/// - message: A text string used as the message of the alert.
|
||||
/// - tint: A color used as a tint color of the alert. Default color is UIColor.systemBlue.
|
||||
/// - Returns: Alert descriptor, which can be used to present alert view.
|
||||
/// - Returns: Alert descriptor which can be used to present alert view.
|
||||
open func okAlert(title: String? = nil,
|
||||
message: String? = nil,
|
||||
tint: UIColor = .systemBlue) -> AlertDescriptor {
|
||||
|
|
@ -89,7 +89,7 @@ open class AlertFactory {
|
|||
/// - message: A text string used as the message of the alert.
|
||||
/// - tint: A color used as a tint color of the alert. Default color is UIColor.systemBlue.
|
||||
/// - retryAction: A closure called by tapping on the retry button of the alert.
|
||||
/// - Returns: Alert descriptor, which can be used to present alert view.
|
||||
/// - Returns: Alert descriptor which can be used to present alert view.
|
||||
open func retryAlert(title: String? = nil,
|
||||
message: String? = nil,
|
||||
tint: UIColor = .systemBlue,
|
||||
|
|
@ -111,7 +111,7 @@ open class AlertFactory {
|
|||
/// - tint: A color used as a tint color of the alert. Default color is UIColor.systemBlue.
|
||||
/// - yesAction: A closure called by tapping on the yes button of the alert.
|
||||
/// - noAction: A closure called by tapping on the no button of the alert.
|
||||
/// - Returns: Alert descriptor, which can be used to present alert view.
|
||||
/// - Returns: Alert descriptor which can be used to present alert view.
|
||||
open func dialogueAlert(title: String? = nil,
|
||||
message: String? = nil,
|
||||
tint: UIColor = .systemBlue,
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
import TISwiftUtils
|
||||
import UIKit
|
||||
|
||||
// struct describe alert button information
|
||||
/// A struct describes an alert button information
|
||||
public struct AlertAction {
|
||||
|
||||
public let id = UUID()
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
import UIKit
|
||||
|
||||
/// Struct describes alert data
|
||||
/// A struct describes alert data
|
||||
public struct AlertDescriptor {
|
||||
|
||||
/// Alert title
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
import TISwiftUtils
|
||||
|
||||
/// A protocol represents an alert which can be presented on the given context
|
||||
public protocol AlertPresentable {
|
||||
func present(on context: AlertPresentationContext, completion: VoidClosure?)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@
|
|||
import TISwiftUtils
|
||||
import UIKit
|
||||
|
||||
/// A context from where the alert can be presented
|
||||
public protocol AlertPresentationContext {
|
||||
func present(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: VoidClosure?)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,4 @@
|
|||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
public protocol UIKitAlertContext: AlertPresentationContext { }
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
import Foundation
|
||||
|
||||
/// Provide default localization for alerts' buttons
|
||||
/// Provides default localization for alerts' buttons
|
||||
open class DefaultAlertLocalizationProvider: AlertLocalizationProvider {
|
||||
|
||||
public var bundle: Bundle
|
||||
|
|
|
|||
Loading…
Reference in New Issue