162 lines
4.8 KiB
Swift
162 lines
4.8 KiB
Swift
//
|
|
// Alert.swift
|
|
// MacBackend
|
|
//
|
|
// Created by david-swift on 01.12.2024.
|
|
//
|
|
|
|
import SwiftUI
|
|
|
|
/// The alert view.
|
|
public struct Alert: SwiftUIWidget {
|
|
|
|
/// The alert's title.
|
|
var title: String
|
|
/// The alert's description.
|
|
var description: String
|
|
/// Whether the alert is presented.
|
|
var isPresented: Meta.Binding<Bool>
|
|
/// The alert's actions.
|
|
var actions: [Action] = []
|
|
/// The wrapped view.
|
|
var child: Meta.AnyView
|
|
|
|
/// The wrapped views.
|
|
public var wrappedViews: [String: Meta.AnyView] {
|
|
[.mainContent: child]
|
|
}
|
|
|
|
/// Initialize the alert.
|
|
/// - Parameters:
|
|
/// - title: The alert's title.
|
|
/// - description: The alert's description.
|
|
/// - isPresented: Whether the alert is presented.
|
|
/// - child: The wrapped view.
|
|
public init(title: String, description: String, isPresented: Meta.Binding<Bool>, child: Meta.AnyView) {
|
|
self.title = title
|
|
self.description = description
|
|
self.isPresented = isPresented
|
|
self.child = child
|
|
}
|
|
|
|
/// An alert action.
|
|
enum Action {
|
|
|
|
/// A regular button.
|
|
case button(button: Button)
|
|
/// A cancel button.
|
|
case cancel(button: Button)
|
|
/// A destructive button.
|
|
case destructive(button: Button)
|
|
|
|
/// Get the SwiftUI button.
|
|
@SwiftUI.ViewBuilder var button: some SwiftUI.View {
|
|
switch self {
|
|
case let .button(button):
|
|
button.button()
|
|
case let .cancel(button):
|
|
button.button(cancel: true)
|
|
case let .destructive(button):
|
|
button.button(destructive: true)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/// The button.
|
|
struct Button {
|
|
|
|
/// The button's label.
|
|
var label: String
|
|
/// The button's action.
|
|
var action: () -> Void
|
|
/// Whether it is the default action.
|
|
var defaultAction: Bool
|
|
|
|
/// Get the SwiftUI button.
|
|
/// - Parameters:
|
|
/// - cancel: Whether it is the cancel action.
|
|
/// - destructive: Whether it is a destructive action.
|
|
/// - Returns: The SwiftUI view.
|
|
@SwiftUI.ViewBuilder
|
|
func button(cancel: Bool = false, destructive: Bool = false) -> some SwiftUI.View {
|
|
let button = SwiftUI.Button(
|
|
label,
|
|
role: cancel ? .cancel : (destructive ? .destructive : nil),
|
|
action: action
|
|
)
|
|
if defaultAction {
|
|
button
|
|
.keyboardShortcut(.defaultAction)
|
|
} else {
|
|
button
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/// Get the SwiftUI view.
|
|
/// - Parameter properties: The widget data.
|
|
/// - Returns: The SwiftUI view.
|
|
public static func view(properties: Self) -> some SwiftUI.View {
|
|
MacBackendView(.mainContent)
|
|
.alert(properties.title, isPresented: properties.isPresented.swiftUI) {
|
|
SwiftUI.ForEach(Array(properties.actions.enumerated()), id: \.offset) { action in
|
|
action.element.button
|
|
}
|
|
} message: {
|
|
SwiftUI.Text(properties.description)
|
|
}
|
|
}
|
|
|
|
/// Add a button to the alert.
|
|
/// - Parameters:
|
|
/// - label: The button's label.
|
|
/// - defaultAction: Whether it is a default action.
|
|
/// - action: The handler.
|
|
/// - Returns: The alert.
|
|
public func button(
|
|
_ label: String,
|
|
default defaultAction: Bool = false,
|
|
action: @escaping () -> Void
|
|
) -> Self {
|
|
modify { alert in
|
|
alert.actions.append(.button(button: .init(label: label, action: action, defaultAction: defaultAction)))
|
|
}
|
|
}
|
|
|
|
/// Add a cancel button to the alert.
|
|
/// - Parameters:
|
|
/// - label: The button's label.
|
|
/// - defaultAction: Whether it is a default action.
|
|
/// - action: The handler.
|
|
/// - Returns: The alert.
|
|
public func cancelButton(
|
|
_ label: String,
|
|
default defaultAction: Bool = false,
|
|
action: @escaping () -> Void
|
|
) -> Self {
|
|
modify { alert in
|
|
alert.actions.append(.cancel(button: .init(label: label, action: action, defaultAction: defaultAction)))
|
|
}
|
|
}
|
|
|
|
/// Add a destructive button to the alert.
|
|
/// - Parameters:
|
|
/// - label: The button's label.
|
|
/// - defaultAction: Whether it is a default action.
|
|
/// - action: The handler.
|
|
/// - Returns: The alert.
|
|
public func destructiveButton(
|
|
_ label: String,
|
|
default defaultAction: Bool = false,
|
|
action: @escaping () -> Void
|
|
) -> Self {
|
|
modify { alert in
|
|
alert.actions
|
|
.append(.destructive(button: .init(label: label, action: action, defaultAction: defaultAction)))
|
|
}
|
|
}
|
|
|
|
}
|