116 lines
3.2 KiB
Swift
116 lines
3.2 KiB
Swift
import Commanding
|
|
import SwiftUI
|
|
import WidgetKit
|
|
|
|
/// The style of the action buttons of the recording Live Activity: it renders a button's label as a fixed-size icon on a circle
|
|
/// colored by the ``ActionType`` given at initialization.
|
|
struct ActionButtonStyle: PrimitiveButtonStyle {
|
|
|
|
// MARK: Properties
|
|
|
|
/// The type of the action behind the styled button, deciding the color of the circular background.
|
|
private let action: ActionType
|
|
|
|
// MARK: Initializers
|
|
|
|
/// Creates a style for a button behind the given type of action.
|
|
///
|
|
/// - Parameter action: The type of the action behind the styled button.
|
|
fileprivate init(
|
|
_ action: ActionType
|
|
) {
|
|
self.action = action
|
|
}
|
|
|
|
// MARK: Methods
|
|
|
|
/// Builds the styled button: its label as a fixed-size, padded icon on a circle colored by the type of the action.
|
|
///
|
|
/// - Parameter configuration: The properties of the button to style.
|
|
/// - Returns: The styled button.
|
|
func makeBody(
|
|
configuration: Configuration
|
|
) -> some View {
|
|
configuration.label
|
|
.scaledToFit()
|
|
.frame(
|
|
width: Constant.Size.icon.width,
|
|
height: Constant.Size.icon.height
|
|
)
|
|
.foregroundStyle(.primary)
|
|
.padding(Constant.Padding.icon)
|
|
.background {
|
|
Circle()
|
|
.foregroundStyle(backgroundColor)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// MARK: - Helpers
|
|
|
|
private extension ActionButtonStyle {
|
|
|
|
/// The color of the circular background, matching the type of the action behind the button.
|
|
var backgroundColor: Color {
|
|
switch action {
|
|
case .confirmative: .green
|
|
case let .custom(color): color
|
|
case .default: .yellow
|
|
case .destructive: .red
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// MARK: - Enumerations
|
|
|
|
extension ActionButtonStyle {
|
|
/// The types of action a styled button can stand behind, each coloring the button's background differently.
|
|
enum ActionType {
|
|
/// An action that confirms or submits, colored green.
|
|
case confirmative
|
|
/// An action colored by the given custom color.
|
|
case custom(_ color: Color)
|
|
/// A regular action, colored yellow.
|
|
case `default`
|
|
/// An action that throws something away, colored red.
|
|
case destructive
|
|
}
|
|
}
|
|
|
|
// MARK: - Constants
|
|
|
|
/// The constant values used across the action button style.
|
|
private enum Constant {
|
|
/// The padding constants.
|
|
enum Padding {
|
|
/// The padding around the button's icon.
|
|
static let icon: CGFloat = 16
|
|
}
|
|
/// The size constants.
|
|
enum Size {
|
|
/// The size of the button's icon.
|
|
static let icon: CGSize = .init(
|
|
width: 24,
|
|
height: 24
|
|
)
|
|
}
|
|
}
|
|
|
|
// MARK: - Styles
|
|
|
|
extension PrimitiveButtonStyle where Self == ActionButtonStyle {
|
|
|
|
/// An action button style for a button behind the given type of action.
|
|
///
|
|
/// - Parameter actionType: The type of the action behind the styled button.
|
|
/// - Returns: The action button style colored for the given type.
|
|
static func action(
|
|
type actionType: ActionButtonStyle.ActionType
|
|
) -> ActionButtonStyle {
|
|
.init(actionType)
|
|
}
|
|
|
|
}
|