Implemented the (first version of the) Recording Live Activity in the Attendi widget target.
This commit is contained in:
@@ -0,0 +1,115 @@
|
||||
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
|
||||
)
|
||||
.padding(Constant.Padding.icon)
|
||||
.foregroundStyle(.windowBackground)
|
||||
.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)
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user