-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #24 from futuredapp/feature/v1.0.0
Release - v1.0.0
Showing
59 changed files
with
1,403 additions
and
330 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
87 changes: 87 additions & 0 deletions
87
Sources/FuturedArchitecture/Architecture/Alert/AlertModel.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
import SwiftUI | ||
|
||
/// A model representation of an alert, which is used by `defaultAlert(model: AlertModel)` SwiftUI View modifier | ||
/// | ||
/// ## Overview | ||
/// | ||
/// It wrappes the native `alert(_:isPresented:presenting:actions:message:)`, but you show an alert in different way by using the `defaultAlert(model:)` view modifier, | ||
/// which then appears whenever the bound `model` value is not `nil` value. | ||
/// Alert model contains two actions: `primaryAction` and `secondaryAction`, which are then represented as SwiftUI Button | ||
/// If both values are nil, system presents alert with standard "OK" button and given `title` and `message` | ||
/// If one of the actions contains `destructive` button role and there is no `cancel` button role, system will add standard button with "Cancel" title. | ||
/// If both `primaryAction` and `secondaryAction` actions have `destructive` button roles, system will still add standard "Cancel" button to the alert. | ||
/// | ||
/// In the following example, a button presents a simple alert when tapped, by updating a local `alertModel` property. | ||
/// Alert contains given `title` and `message` with standard "OK" button | ||
/// | ||
/// ```swift | ||
/// @State private var alertModel: AlertModel? | ||
/// var body: some View { | ||
/// Button("Tap to show alert") { | ||
/// alertModel = AlertModel( | ||
/// title: "Current Location Not Available", | ||
/// message: "Your current location can’t be determined at this time." | ||
/// ) | ||
/// } | ||
/// .defaultAlert(model: $alertModel) | ||
/// } | ||
/// ``` | ||
/// | ||
/// The following example adds primary “Delete” button with `destructive` button role and standard "Cancel" button which is added by system. | ||
/// | ||
/// ```swift | ||
/// @State private var alertModel: AlertModel? | ||
/// var body: some View { | ||
/// Button("Tap to show alert") { | ||
/// alertModel = AlertModel( | ||
/// title: "Unable to Save Workout Data", | ||
/// message: "The connection to the server was lost.", | ||
/// primaryAction: AlertModel.ButtonAction( | ||
/// title: "Delete, | ||
/// buttonRole: .destructive, | ||
/// action: deleteWorkoutData | ||
/// ) | ||
/// ) | ||
/// } | ||
/// .defaultAlert(model: $alertModel) | ||
/// } | ||
/// ``` | ||
/// | ||
/// The alert handles its own dismissal when the user taps one of the buttons in the alert, | ||
/// by setting the bound `model` value back to `nil`. | ||
public struct AlertModel: Identifiable { | ||
public struct ButtonAction { | ||
let title: String | ||
let buttonRole: ButtonRole? | ||
let action: () -> Void | ||
|
||
public init(title: String, buttonRole: ButtonRole? = nil, action: @escaping () -> Void) { | ||
self.title = title | ||
self.buttonRole = buttonRole | ||
self.action = action | ||
} | ||
} | ||
|
||
public var id: String? { | ||
title + (message ?? "") | ||
} | ||
|
||
let title: String | ||
let message: String? | ||
let primaryAction: ButtonAction? | ||
let secondaryAction: ButtonAction? | ||
|
||
/// Creates an alert model. | ||
/// - Parameters: | ||
/// - title: The title of the alert. | ||
/// - message: The message to display in the body of the alert. | ||
/// - primaryAction: The specification of the alert primary action. | ||
/// - secondaryAction: The specification of the alert secondary action. | ||
|
||
public init(title: String, message: String?, primaryAction: ButtonAction? = nil, secondaryAction: ButtonAction? = nil) { | ||
self.title = title | ||
self.message = message | ||
self.primaryAction = primaryAction | ||
self.secondaryAction = secondaryAction | ||
} | ||
} |
75 changes: 75 additions & 0 deletions
75
Sources/FuturedArchitecture/Architecture/Alert/AlertModifier.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import SwiftUI | ||
|
||
private struct AlertModifier: ViewModifier { | ||
@Binding var model: AlertModel? | ||
|
||
init(_ model: Binding<AlertModel?>) { | ||
self._model = model | ||
} | ||
|
||
func body(content: Content) -> some View { | ||
content.alert( | ||
model?.title ?? "", | ||
isPresented: .init( | ||
get: { model != nil }, | ||
set: { isPresented, _ in | ||
if !isPresented { | ||
model = nil | ||
} | ||
} | ||
), | ||
presenting: model, | ||
actions: { model in | ||
if let primaryAction = model.primaryAction { | ||
Button( | ||
primaryAction.title, | ||
role: primaryAction.buttonRole, | ||
action: primaryAction.action | ||
) | ||
|
||
if let secondaryAction = model.secondaryAction { | ||
Button( | ||
secondaryAction.title, | ||
role: secondaryAction.buttonRole, | ||
action: secondaryAction.action | ||
) | ||
} | ||
} | ||
}, | ||
message: { model in | ||
if let message = model.message { | ||
Text(message) | ||
} | ||
} | ||
) | ||
} | ||
} | ||
|
||
extension View { | ||
/// Presents an alert to the user. | ||
/// - Parameters: | ||
/// - model: A binding to a `AlertModel` value that determines whether to present the alert | ||
/// that you define by this model. | ||
/// | ||
/// ## Overview | ||
/// | ||
/// Use this method when you need to show simplified an alert to the user. | ||
/// In the following example, a button presents an alert when tapped, by updating a local `alertModel` property. | ||
/// Alert contains given `title` and `message` with standard "OK" button | ||
/// | ||
/// ```swift | ||
/// @State private var alertModel: AlertModel? | ||
/// var body: some View { | ||
/// Button("Tap to show alert") { | ||
/// alertModel = AlertModel( | ||
/// title: "Current Location Not Available", | ||
/// message: "Your current location can’t be determined at this time." | ||
/// ) | ||
/// } | ||
/// .defaultAlert(model: $alertModel) | ||
/// } | ||
/// ``` | ||
public func defaultAlert(model: Binding<AlertModel?>) -> some View { | ||
modifier(AlertModifier(model)) | ||
} | ||
} |
7 changes: 7 additions & 0 deletions
7
Sources/FuturedArchitecture/Architecture/ComponentModel.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import Foundation | ||
|
||
public protocol ComponentModel: ObservableObject { | ||
associatedtype Event | ||
|
||
var onEvent: (Event) -> Void { get } | ||
} |
Oops, something went wrong.