feat: Resolving concurrency warnings

This commit is contained in:
2024-06-11 10:34:19 -04:00
parent e07df0e426
commit bf2e65fb8f
15 changed files with 156 additions and 130 deletions

View File

@@ -2,6 +2,10 @@
import PackageDescription import PackageDescription
let settings: [SwiftSetting] = [
.enableExperimentalFeature("StrictConcurrency")
]
let package = Package( let package = Package(
name: "swift-estimated-pressures-core", name: "swift-estimated-pressures-core",
platforms: [ platforms: [
@@ -100,7 +104,3 @@ let package = Package(
), ),
] ]
) )
let settings: [SwiftSetting] = [
.enableExperimentalFeature("StrictConcurrency")
]

View File

@@ -26,6 +26,7 @@ public struct FlaggedEquipmentMeasurementView: View {
} }
} }
@MainActor
public protocol FlaggedEquipmentMeasurementStyle { public protocol FlaggedEquipmentMeasurementStyle {
associatedtype Body: View associatedtype Body: View
typealias Configuration = FlaggedEquipmentMeasurementStyleConfiguration typealias Configuration = FlaggedEquipmentMeasurementStyleConfiguration
@@ -39,6 +40,8 @@ public struct FlaggedEquipmentMeasurementStyleConfiguration {
public let ignoreIfZero: [EquipmentMeasurement.FlaggedMeasurement.FieldKey] public let ignoreIfZero: [EquipmentMeasurement.FlaggedMeasurement.FieldKey]
} }
@MainActor
@preconcurrency
public struct AnyFlaggedEquipmentMeasurementStyle: FlaggedEquipmentMeasurementStyle { public struct AnyFlaggedEquipmentMeasurementStyle: FlaggedEquipmentMeasurementStyle {
private var _makeBody: (Configuration) -> AnyView private var _makeBody: (Configuration) -> AnyView
@@ -46,6 +49,7 @@ public struct AnyFlaggedEquipmentMeasurementStyle: FlaggedEquipmentMeasurementSt
self._makeBody = makeBody self._makeBody = makeBody
} }
@MainActor
public init<S: FlaggedEquipmentMeasurementStyle>(_ style: S) { public init<S: FlaggedEquipmentMeasurementStyle>(_ style: S) {
self.init { configuration in self.init { configuration in
AnyView(style.makeBody(configuration: configuration)) AnyView(style.makeBody(configuration: configuration))
@@ -57,6 +61,7 @@ public struct AnyFlaggedEquipmentMeasurementStyle: FlaggedEquipmentMeasurementSt
} }
} }
@MainActor
public struct GridFlaggedEquipmentMeasurementStyle: FlaggedEquipmentMeasurementStyle { public struct GridFlaggedEquipmentMeasurementStyle: FlaggedEquipmentMeasurementStyle {
public func makeBody(configuration: Configuration) -> some View { public func makeBody(configuration: Configuration) -> some View {
@@ -82,15 +87,13 @@ extension FlaggedEquipmentMeasurementStyle where Self == GridFlaggedEquipmentMea
public static var grid: Self { .init() } public static var grid: Self { .init() }
} }
private struct FlaggedEquipmentMeasurementStyleKey: EnvironmentKey { //fileprivate struct FlaggedEquipmentMeasurementStyleKey: @preconcurrency EnvironmentKey {
static let defaultValue = AnyFlaggedEquipmentMeasurementStyle(GridFlaggedEquipmentMeasurementStyle()) //
} // static let defaultValue = AnyFlaggedEquipmentMeasurementStyle(.grid)
//}
extension EnvironmentValues { extension EnvironmentValues {
public var flaggedEquipmentMeasurementStyle: AnyFlaggedEquipmentMeasurementStyle { @Entry var flaggedEquipmentMeasurementStyle = AnyFlaggedEquipmentMeasurementStyle(.grid)
get { self[FlaggedEquipmentMeasurementStyleKey.self] }
set { self[FlaggedEquipmentMeasurementStyleKey.self] = newValue }
}
} }
extension View { extension View {

View File

@@ -23,7 +23,7 @@ public struct FlaggedMessageLabel: View {
} }
private struct FlaggedMessageLabelStyleKey: EnvironmentKey { private struct FlaggedMessageLabelStyleKey: EnvironmentKey {
static var defaultValue = AnyTextLabelStyle(style: .font(.caption)) static let defaultValue = AnyTextLabelStyle(style: .font(.caption))
} }
extension EnvironmentValues { extension EnvironmentValues {

View File

@@ -27,6 +27,8 @@ extension FlaggedMessageView {
} }
} }
@MainActor
@preconcurrency
public protocol FlaggedMessageViewStyle { public protocol FlaggedMessageViewStyle {
associatedtype Body: View associatedtype Body: View
typealias Configuration = FlaggedMessageViewStyleConfiguration typealias Configuration = FlaggedMessageViewStyleConfiguration
@@ -117,8 +119,10 @@ extension FlaggedMessageViewStyle where Self == AutomaticFlaggedMessageViewStyle
} }
} }
private struct FlaggedMessageViewStyleKey: EnvironmentKey { @MainActor
static var defaultValue = AnyFlaggedMessageViewStyle( private struct FlaggedMessageViewStyleKey: @preconcurrency EnvironmentKey {
static let defaultValue = AnyFlaggedMessageViewStyle(
AutomaticFlaggedMessageViewStyle(horizontalSizeClass: nil) AutomaticFlaggedMessageViewStyle(horizontalSizeClass: nil)
) )
} }

View File

@@ -23,22 +23,24 @@ public struct FlaggedStatusLabel: View {
} }
} }
@MainActor
public protocol FlaggedStatusLabelStyle { @preconcurrency
public protocol FlaggedStatusLabelStyle: Sendable {
associatedtype Body: View associatedtype Body: View
typealias Configuration = FlaggedStatusLabelStyleConfiguration typealias Configuration = FlaggedStatusLabelStyleConfiguration
func makeBody(configuration: Self.Configuration) -> Self.Body func makeBody(configuration: Self.Configuration) -> Self.Body
} }
public struct FlaggedStatusLabelStyleConfiguration { public struct FlaggedStatusLabelStyleConfiguration : Sendable{
public let status: Flagged.CheckResult.Status public let status: Flagged.CheckResult.Status
} }
public struct AnyFlaggedStatusLabelStyle: FlaggedStatusLabelStyle { @MainActor
private let _makeBody: (Configuration) -> AnyView public struct AnyFlaggedStatusLabelStyle: FlaggedStatusLabelStyle, Sendable {
private let _makeBody: @Sendable (Configuration) -> AnyView
internal init(makeBody: @escaping (Configuration) -> AnyView) { internal init(makeBody: @escaping @Sendable (Configuration) -> AnyView) {
self._makeBody = makeBody self._makeBody = makeBody
} }
@@ -57,7 +59,7 @@ public struct FlaggedStatusTextLabelStyle: FlaggedStatusLabelStyle {
let textLabelStyle: AnyTextLabelStyle? let textLabelStyle: AnyTextLabelStyle?
public func makeBody(configuration: Configuration) -> some View { @MainActor public func makeBody(configuration: Configuration) -> some View {
TextLabel(configuration.status.title) TextLabel(configuration.status.title)
.textLabelStyle( .textLabelStyle(
textLabelStyle textLabelStyle
@@ -68,8 +70,8 @@ public struct FlaggedStatusTextLabelStyle: FlaggedStatusLabelStyle {
} }
} }
private struct FlaggedStatusLabelStyleKey: EnvironmentKey { private struct FlaggedStatusLabelStyleKey: @preconcurrency EnvironmentKey {
static var defaultValue = AnyFlaggedStatusLabelStyle( @MainActor static let defaultValue = AnyFlaggedStatusLabelStyle(
FlaggedStatusTextLabelStyle( FlaggedStatusTextLabelStyle(
textLabelStyle: AnyTextLabelStyle( textLabelStyle: AnyTextLabelStyle(
style: .font(.callout, fontWeight: .bold) style: .font(.callout, fontWeight: .bold)

View File

@@ -42,6 +42,7 @@ extension FlaggedView where Label == EmptyView {
} }
} }
@MainActor
public protocol FlaggedViewStyle { public protocol FlaggedViewStyle {
associatedtype Body: View associatedtype Body: View
typealias Configuration = FlaggedViewStyleConfiguration typealias Configuration = FlaggedViewStyleConfiguration
@@ -50,6 +51,7 @@ public protocol FlaggedViewStyle {
func makeBody(configuration: Self.Configuration) -> Self.Body func makeBody(configuration: Self.Configuration) -> Self.Body
} }
@MainActor
public struct FlaggedViewStyleConfiguration { public struct FlaggedViewStyleConfiguration {
public let flagged: Flagged public let flagged: Flagged
public let label: Label public let label: Label
@@ -82,6 +84,7 @@ public struct AnyFlaggedViewStyle: FlaggedViewStyle {
} }
} }
@MainActor
public struct DefaultFlagViewStyle: FlaggedViewStyle { public struct DefaultFlagViewStyle: FlaggedViewStyle {
let alignment: HorizontalAlignment let alignment: HorizontalAlignment
@@ -202,6 +205,7 @@ extension Flagged {
.foregroundStyle(statusColor) .foregroundStyle(statusColor)
} }
@MainActor
public var messageView: some View { public var messageView: some View {
FlaggedMessageView(flagged: self) FlaggedMessageView(flagged: self)
} }

View File

@@ -9,7 +9,7 @@ public struct EstimationForm {
public init() { } public init() { }
@ObservableState @ObservableState
public struct State: Equatable { public struct State: Equatable, Sendable {
public var cfmPerTon: Int public var cfmPerTon: Int
public var coolingCapacity: EquipmentMetadata.CoolingCapacity public var coolingCapacity: EquipmentMetadata.CoolingCapacity
public var filterPressureDrop: Double? public var filterPressureDrop: Double?

View File

@@ -7,9 +7,8 @@ import Styleguide
import SwiftUI import SwiftUI
import TCAExtras import TCAExtras
@Reducer @Reducer
public struct FlaggedMeasurementsList { public struct FlaggedMeasurementsList: Sendable {
@Reducer(state: .equatable) @Reducer(state: .equatable)
public enum Destination { public enum Destination {
@@ -17,20 +16,18 @@ public struct FlaggedMeasurementsList {
} }
@ObservableState @ObservableState
@dynamicMemberLookup
public struct State: Equatable { public struct State: Equatable {
@Presents public var destination: Destination.State? @Presents public var destination: Destination.State?
@Shared var sharedSettings: SharedPressureEstimationSettings @Shared var sharedSettings: SharedPressureEstimationSettings
public var estimatedMeasurements: IdentifiedArrayOf<FlaggedMeasurementContainer>
init( public init(
destination: Destination.State? = nil, destination: Destination.State? = nil,
sharedSettings: Shared<SharedPressureEstimationSettings>, sharedSettings: Shared<SharedPressureEstimationSettings>
estimatedMeasurements: IdentifiedArrayOf<FlaggedMeasurementContainer> = []
) { ) {
self.destination = destination self.destination = destination
self._sharedSettings = sharedSettings self._sharedSettings = sharedSettings
self.estimatedMeasurements = estimatedMeasurements
} }
var ignoreIfZeroFields: [EquipmentMeasurement.FlaggedMeasurement.FieldKey] { var ignoreIfZeroFields: [EquipmentMeasurement.FlaggedMeasurement.FieldKey] {
@@ -39,21 +36,9 @@ public struct FlaggedMeasurementsList {
return [.coilDrop, .filterDrop] return [.coilDrop, .filterDrop]
} }
#warning("Move to shared settings.") public subscript<T>(dynamicMember keyPath: WritableKeyPath<SharedPressureEstimationSettings, T>) -> T {
public struct FlaggedMeasurementContainer: Equatable, Identifiable { get { sharedSettings[keyPath: keyPath] }
public let id: UUID set { sharedSettings[keyPath: keyPath] = newValue }
public var flaggedMeasurement: EquipmentMeasurement.FlaggedMeasurement
public var name: String
public init(
id: UUID,
name: String,
flaggedMeasurement: EquipmentMeasurement.FlaggedMeasurement
) {
self.id = id
self.name = name
self.flaggedMeasurement = flaggedMeasurement
}
} }
} }
@@ -64,7 +49,7 @@ public struct FlaggedMeasurementsList {
case view(View) case view(View)
@CasePathable @CasePathable
public enum ReceiveAction { public enum ReceiveAction: Sendable {
case existingFlaggedMeasurement(EquipmentMeasurement.FlaggedMeasurement) case existingFlaggedMeasurement(EquipmentMeasurement.FlaggedMeasurement)
case estimatedFlaggedMeasurement(name: String, measurement: EquipmentMeasurement.FlaggedMeasurement) case estimatedFlaggedMeasurement(name: String, measurement: EquipmentMeasurement.FlaggedMeasurement)
} }
@@ -73,7 +58,7 @@ public struct FlaggedMeasurementsList {
public enum View { public enum View {
case addButtonTapped case addButtonTapped
case destination(DestinationAction) case destination(DestinationAction)
case editButtonTapped(id: State.FlaggedMeasurementContainer.ID) case editButtonTapped(id: SharedPressureEstimationSettings.FlaggedMeasurementContainer.ID)
case onAppear case onAppear
@CasePathable @CasePathable
@@ -96,7 +81,7 @@ public struct FlaggedMeasurementsList {
return .none return .none
case let .estimatedFlaggedMeasurement(name: name, measurement: measurement): case let .estimatedFlaggedMeasurement(name: name, measurement: measurement):
state.estimatedMeasurements.append( state.flaggedEstimations.append(
.init( .init(
id: uuid(), id: uuid(),
name: name, name: name,
@@ -242,7 +227,7 @@ public struct FlaggedMeasurementListView: View {
} }
} }
} }
ForEach(store.estimatedMeasurements) { measurement in ForEach(store.flaggedEstimations) { measurement in
Section { Section {
FlaggedEquipmentMeasurementView( FlaggedEquipmentMeasurementView(
measurement.flaggedMeasurement, measurement.flaggedMeasurement,
@@ -295,34 +280,36 @@ public struct FlaggedMeasurementListView: View {
} }
#if DEBUG #if DEBUG
private let sharedPressureEstimationSettings = SharedPressureEstimationSettings(
budgets: .init(equipmentType: .airHandler, fanType: .constantSpeed),
equipmentMeasurement: .mock(type: .airHandler),
flaggedEquipmentMeasurement: nil
)
private let flaggedMeasurements = IdentifiedArrayOf<FlaggedMeasurementsList.State.FlaggedMeasurementContainer>( private let budgets = BudgetedPercentEnvelope(equipmentType: .airHandler, fanType: .constantSpeed)
private let flaggedMeasurements = IdentifiedArrayOf<SharedPressureEstimationSettings.FlaggedMeasurementContainer>(
uniqueElements: [ uniqueElements: [
.init( .init(
id: UUID(0), id: UUID(0),
name: "Existing", name: "Existing",
flaggedMeasurement: .init( flaggedMeasurement: .init(
budgets: sharedPressureEstimationSettings.budgets!, budgets: budgets,
measurement: sharedPressureEstimationSettings.equipmentMeasurement!, measurement: .mock(type: .airHandler),
ratedPressures: sharedPressureEstimationSettings.equipmentMetadata.ratedStaticPressures, ratedPressures: .init(),
tons: sharedPressureEstimationSettings.equipmentMetadata.coolingCapacity tons: .default
) )
), ),
] ]
) )
#Preview { #Preview {
NavigationStack { NavigationStack {
FlaggedMeasurementListView( FlaggedMeasurementListView(
store: Store( store: Store(
initialState: FlaggedMeasurementsList.State( initialState: FlaggedMeasurementsList.State(
sharedSettings: Shared(sharedPressureEstimationSettings) sharedSettings: Shared(
SharedPressureEstimationSettings(
budgets: budgets,
equipmentMeasurement: .mock(type: .airHandler),
flaggedEquipmentMeasurement: nil,
flaggedEstimations: flaggedMeasurements
)
)
) )
) { ) {
FlaggedMeasurementsList() FlaggedMeasurementsList()
@@ -331,18 +318,4 @@ private let flaggedMeasurements = IdentifiedArrayOf<FlaggedMeasurementsList.Stat
} }
} }
#Preview("Landscape", traits: .landscapeLeft) {
NavigationStack {
FlaggedMeasurementListView(
store: Store(
initialState: FlaggedMeasurementsList.State(
sharedSettings: Shared(sharedPressureEstimationSettings)
)
) {
FlaggedMeasurementsList()
}
)
}
}
#endif #endif

View File

@@ -1,13 +1,15 @@
import ComposableArchitecture import ComposableArchitecture
import Foundation
import SharedModels import SharedModels
/// Holds onto shared values for several of the views in this feature. /// Holds onto shared values for several of the views in this feature.
@dynamicMemberLookup @dynamicMemberLookup
public struct SharedPressureEstimationSettings: Equatable { public struct SharedPressureEstimationSettings: Equatable, Sendable {
public var budgets: BudgetedPercentEnvelope? public var budgets: BudgetedPercentEnvelope?
public var equipmentMeasurement: EquipmentMeasurement? public var equipmentMeasurement: EquipmentMeasurement?
public var equipmentMetadata: EquipmentMetadata public var equipmentMetadata: EquipmentMetadata
public var flaggedEquipmentMeasurement: EquipmentMeasurement.FlaggedMeasurement? public var flaggedEquipmentMeasurement: EquipmentMeasurement.FlaggedMeasurement?
public var flaggedEstimations: IdentifiedArrayOf<FlaggedMeasurementContainer>
public var heatingCapacity: Double? public var heatingCapacity: Double?
public var manufacturersIncludedFilterPressureDrop: Double? public var manufacturersIncludedFilterPressureDrop: Double?
@@ -16,6 +18,7 @@ public struct SharedPressureEstimationSettings: Equatable {
equipmentMeasurement: EquipmentMeasurement? = nil, equipmentMeasurement: EquipmentMeasurement? = nil,
equipmentMetadata: EquipmentMetadata = .init(), equipmentMetadata: EquipmentMetadata = .init(),
flaggedEquipmentMeasurement: EquipmentMeasurement.FlaggedMeasurement? = nil, flaggedEquipmentMeasurement: EquipmentMeasurement.FlaggedMeasurement? = nil,
flaggedEstimations: IdentifiedArrayOf<FlaggedMeasurementContainer> = [],
heatingCapacity: Double? = nil, heatingCapacity: Double? = nil,
manufacturersIncludedFilterPressureDrop: Double? = nil manufacturersIncludedFilterPressureDrop: Double? = nil
) { ) {
@@ -23,6 +26,7 @@ public struct SharedPressureEstimationSettings: Equatable {
self.equipmentMeasurement = equipmentMeasurement self.equipmentMeasurement = equipmentMeasurement
self.equipmentMetadata = equipmentMetadata self.equipmentMetadata = equipmentMetadata
self.flaggedEquipmentMeasurement = flaggedEquipmentMeasurement self.flaggedEquipmentMeasurement = flaggedEquipmentMeasurement
self.flaggedEstimations = flaggedEstimations
self.heatingCapacity = heatingCapacity self.heatingCapacity = heatingCapacity
self.manufacturersIncludedFilterPressureDrop = manufacturersIncludedFilterPressureDrop self.manufacturersIncludedFilterPressureDrop = manufacturersIncludedFilterPressureDrop
} }
@@ -31,6 +35,22 @@ public struct SharedPressureEstimationSettings: Equatable {
get { equipmentMetadata[keyPath: keyPath] } get { equipmentMetadata[keyPath: keyPath] }
set { equipmentMetadata[keyPath: keyPath] = newValue } set { equipmentMetadata[keyPath: keyPath] = newValue }
} }
public struct FlaggedMeasurementContainer: Equatable, Identifiable, Sendable {
public let id: UUID
public var flaggedMeasurement: EquipmentMeasurement.FlaggedMeasurement
public var name: String
public init(
id: UUID,
name: String,
flaggedMeasurement: EquipmentMeasurement.FlaggedMeasurement
) {
self.id = id
self.name = name
self.flaggedMeasurement = flaggedMeasurement
}
}
} }
extension PersistenceReaderKey where Self == InMemoryKey<SharedPressureEstimationSettings> { extension PersistenceReaderKey where Self == InMemoryKey<SharedPressureEstimationSettings> {

View File

@@ -19,7 +19,7 @@ public struct Flagged: Equatable, Sendable {
public init( public init(
wrappedValue: Double, wrappedValue: Double,
_ checkValue: @escaping (Double) -> CheckResult _ checkValue: @escaping @Sendable (Double) -> CheckResult
) { ) {
self.checkValue = .init(checkValue) self.checkValue = .init(checkValue)
self.wrappedValue = wrappedValue self.wrappedValue = wrappedValue
@@ -35,10 +35,10 @@ public struct Flagged: Equatable, Sendable {
checkValue(wrappedValue) checkValue(wrappedValue)
} }
public struct GoodMessageHandler { public struct GoodMessageHandler: Sendable {
let message: (Double) -> String? let message: @Sendable (Double) -> String?
public init(message: @escaping (Double) -> String?) { public init(message: @escaping @Sendable (Double) -> String?) {
self.message = message self.message = message
} }

View File

@@ -1,6 +1,6 @@
import Foundation import Foundation
extension Optional: ExpressibleByIntegerLiteral where Wrapped: ExpressibleByIntegerLiteral { extension Optional: @retroactive ExpressibleByIntegerLiteral where Wrapped: ExpressibleByIntegerLiteral {
public typealias IntegerLiteralType = Wrapped.IntegerLiteralType public typealias IntegerLiteralType = Wrapped.IntegerLiteralType
@@ -9,7 +9,7 @@ extension Optional: ExpressibleByIntegerLiteral where Wrapped: ExpressibleByInte
} }
} }
extension Optional: ExpressibleByFloatLiteral where Wrapped: ExpressibleByFloatLiteral { extension Optional: @retroactive ExpressibleByFloatLiteral where Wrapped: ExpressibleByFloatLiteral {
public typealias FloatLiteralType = Wrapped.FloatLiteralType public typealias FloatLiteralType = Wrapped.FloatLiteralType
public init(floatLiteral value: Wrapped.FloatLiteralType) { public init(floatLiteral value: Wrapped.FloatLiteralType) {
@@ -17,7 +17,7 @@ extension Optional: ExpressibleByFloatLiteral where Wrapped: ExpressibleByFloatL
} }
} }
extension Optional: AdditiveArithmetic where Wrapped: AdditiveArithmetic { extension Optional: @retroactive AdditiveArithmetic where Wrapped: AdditiveArithmetic {
public static func - (lhs: Optional<Wrapped>, rhs: Optional<Wrapped>) -> Optional<Wrapped> { public static func - (lhs: Optional<Wrapped>, rhs: Optional<Wrapped>) -> Optional<Wrapped> {
switch (lhs, rhs) { switch (lhs, rhs) {
@@ -58,7 +58,7 @@ extension Optional: AdditiveArithmetic where Wrapped: AdditiveArithmetic {
} }
extension Optional: Numeric where Wrapped: Numeric { extension Optional: @retroactive Numeric where Wrapped: Numeric {
public static func *= (lhs: inout Optional<Wrapped>, rhs: Optional<Wrapped>) { public static func *= (lhs: inout Optional<Wrapped>, rhs: Optional<Wrapped>) {
switch (lhs, rhs) { switch (lhs, rhs) {
@@ -107,7 +107,7 @@ extension Optional: Numeric where Wrapped: Numeric {
public typealias Magnitude = Wrapped.Magnitude public typealias Magnitude = Wrapped.Magnitude
} }
extension Optional: Comparable where Wrapped: Comparable { extension Optional: @retroactive Comparable where Wrapped: Comparable {
public static func < (lhs: Optional<Wrapped>, rhs: Optional<Wrapped>) -> Bool { public static func < (lhs: Optional<Wrapped>, rhs: Optional<Wrapped>) -> Bool {
switch (lhs, rhs) { switch (lhs, rhs) {
case let (.some(lhs), .some(rhs)): case let (.some(lhs), .some(rhs)):

View File

@@ -72,7 +72,7 @@ extension Percentage: Comparable {
extension Percentage: CustomStringConvertible { extension Percentage: CustomStringConvertible {
static var formatter: NumberFormatter = { static let formatter: NumberFormatter = {
let formatter = NumberFormatter() let formatter = NumberFormatter()
formatter.numberStyle = .percent formatter.numberStyle = .percent
return formatter return formatter

View File

@@ -2,7 +2,7 @@ import ComposableArchitecture
import SwiftUI import SwiftUI
@Reducer @Reducer
public struct InfoViewFeature { public struct InfoViewFeature: Sendable {
public init() { } public init() { }

View File

@@ -10,21 +10,23 @@ public enum NextButtonType { }
public enum ResetButtonType { } public enum ResetButtonType { }
/// A type erased button style, used to style buttons in a namespace. /// A type erased button style, used to style buttons in a namespace.
public struct AnyButtonStyle<ButtonType>: ButtonStyle { //@MainActor
private let _makeBody: (Configuration) -> AnyView //public struct AnyButtonStyle<ButtonType>: ButtonStyle, Sendable {
// private let _makeBody: @Sendable (Configuration) -> AnyView
public init<S: ButtonStyle>(_ style: S) { //
self._makeBody = { configuration in // public init<S: ButtonStyle>(_ style: S) where S: Sendable, S.Body: Sendable {
AnyView(style.makeBody(configuration: configuration)) // self._makeBody = { configuration in
} // AnyView(style.makeBody(configuration: configuration))
} // }
// }
public func makeBody(configuration: Configuration) -> some View { //
self._makeBody(configuration) // public func makeBody(configuration: Configuration) -> some View {
} // self._makeBody(configuration)
} // }
//}
/// A type erased primitive button style, used to style buttons in a namespace. /// A type erased primitive button style, used to style buttons in a namespace.
@MainActor
public struct AnyPrimitiveButtonStyle<ButtonType>: PrimitiveButtonStyle { public struct AnyPrimitiveButtonStyle<ButtonType>: PrimitiveButtonStyle {
private let _makeBody: (Configuration) -> AnyView private let _makeBody: (Configuration) -> AnyView
@@ -40,7 +42,8 @@ public struct AnyPrimitiveButtonStyle<ButtonType>: PrimitiveButtonStyle {
} }
/// The default info button style. /// The default info button style.
public struct DefaultInfoButtonStyle<Style: LabelStyle>: ButtonStyle { @MainActor
public struct DefaultInfoButtonStyle<Style: LabelStyle>: PrimitiveButtonStyle {
let color: Color let color: Color
let font: Font let font: Font
let labelStyle: Style let labelStyle: Style
@@ -56,11 +59,17 @@ public struct DefaultInfoButtonStyle<Style: LabelStyle>: ButtonStyle {
} }
public func makeBody(configuration: Configuration) -> some View { public func makeBody(configuration: Configuration) -> some View {
Button(role: configuration.role, action: configuration.trigger) {
configuration.label configuration.label
.font(font) .font(font)
.foregroundStyle(color.opacity(configuration.isPressed ? 0.5 : 1)) .foregroundStyle(color)
.labelStyle(labelStyle) .labelStyle(labelStyle)
.scaleEffect(configuration.isPressed ? 0.8 : 1) }
// configuration.label
// .font(font)
// .foregroundStyle(color.opacity(configuration.isPressed ? 0.5 : 1))
// .labelStyle(labelStyle)
// .scaleEffect(configuration.isPressed ? 0.8 : 1)
} }
} }
@@ -104,32 +113,40 @@ extension AnyPrimitiveButtonStyle<NextButtonType> {
public static var toolbar: Self { .init(ToolbarNextButtonStyle()) } public static var toolbar: Self { .init(ToolbarNextButtonStyle()) }
} }
extension AnyButtonStyle where ButtonType == InfoButtonType { //extension AnyButtonStyle where ButtonType == InfoButtonType {
public static var `default`: Self { // public static var `default`: Self {
.init(DefaultInfoButtonStyle<IconOnlyLabelStyle>(labelStyle: .iconOnly)) // .init(DefaultInfoButtonStyle<IconOnlyLabelStyle>(labelStyle: .iconOnly))
} // }
//
// public static func `default`<S: LabelStyle>(color: Color, font: Font, labelStyle: S) -> Self {
// .init(DefaultInfoButtonStyle<S>(color: color, font: font, labelStyle: labelStyle))
// }
//}
public static func `default`<S: LabelStyle>(color: Color, font: Font, labelStyle: S) -> Self { private struct InfoButtonStyleKey: @preconcurrency EnvironmentKey {
.init(DefaultInfoButtonStyle<S>(color: color, font: font, labelStyle: labelStyle)) @MainActor
static var defaultValue: AnyPrimitiveButtonStyle<InfoButtonType> {
AnyPrimitiveButtonStyle<InfoButtonType>(DefaultInfoButtonStyle(labelStyle: .iconOnly))
} }
} }
private struct InfoButtonStyleKey: EnvironmentKey {
static var defaultValue = AnyButtonStyle<InfoButtonType>.default
}
private struct NextButtonStyleKey: EnvironmentKey { private struct NextButtonStyleKey: EnvironmentKey {
static var defaultValue = AnyPrimitiveButtonStyle<NextButtonType>( @MainActor
static var defaultValue: AnyPrimitiveButtonStyle<NextButtonType> {
AnyPrimitiveButtonStyle<NextButtonType>(
DefaultNextButtonStyle<BorderedProminentButtonStyle, NextLabelStyle>() DefaultNextButtonStyle<BorderedProminentButtonStyle, NextLabelStyle>()
) )
} }
}
private struct ResetButtonStyleKey: EnvironmentKey { private struct ResetButtonStyleKey: EnvironmentKey {
static var defaultValue = AnyPrimitiveButtonStyle<ResetButtonType>(.borderedProminent) static let defaultValue = AnyPrimitiveButtonStyle<ResetButtonType>(.borderedProminent)
} }
extension EnvironmentValues { extension EnvironmentValues {
var infoButtonStyle: AnyButtonStyle<InfoButtonType> { // @Entry var infoButtonStyle: AnyButtonStyle<InfoButtonType> = AnyButtonStyle.default
var infoButtonStyle: AnyPrimitiveButtonStyle<InfoButtonType> {
get { self[InfoButtonStyleKey.self] } get { self[InfoButtonStyleKey.self] }
set { self[InfoButtonStyleKey.self] = newValue } set { self[InfoButtonStyleKey.self] = newValue }
} }
@@ -148,13 +165,13 @@ extension EnvironmentValues {
extension View { extension View {
/// Sets the button style for the ``InfoButton`` type. /// Sets the button style for the ``InfoButton`` type.
public func infoButtonStyle(_ style: AnyButtonStyle<InfoButtonType>) -> some View { public func infoButtonStyle(_ style: AnyPrimitiveButtonStyle<InfoButtonType>) -> some View {
environment(\.infoButtonStyle, style) environment(\.infoButtonStyle, style)
} }
/// Sets the button style for the ``InfoButton`` type. /// Sets the button style for the ``InfoButton`` type.
public func infoButtonStyle<S: ButtonStyle>(_ style: S) -> some View { public func infoButtonStyle<S: PrimitiveButtonStyle>(_ style: S) -> some View {
infoButtonStyle(AnyButtonStyle(style)) infoButtonStyle(AnyPrimitiveButtonStyle(style))
} }
/// Sets the button style for the ``NextButton`` type. /// Sets the button style for the ``NextButton`` type.

View File

@@ -1,5 +1,6 @@
import SwiftUI import SwiftUI
@MainActor
public protocol TextLabelStyle { public protocol TextLabelStyle {
associatedtype Body: View associatedtype Body: View
@@ -28,6 +29,7 @@ public struct TextLabelConfiguration {
public let label: TextLabelConfiguration.Label public let label: TextLabelConfiguration.Label
} }
@MainActor
public struct AnyTextLabelStyle: TextLabelStyle { public struct AnyTextLabelStyle: TextLabelStyle {
private var _makeBody: (Configuration) -> AnyView private var _makeBody: (Configuration) -> AnyView
@@ -57,6 +59,7 @@ public struct AnyTextLabelStyle: TextLabelStyle {
} }
} }
@MainActor
public struct AutomaticTextLabelStyle: TextLabelStyle { public struct AutomaticTextLabelStyle: TextLabelStyle {
public func makeBody(configuration: Configuration) -> some View { public func makeBody(configuration: Configuration) -> some View {
configuration.label configuration.label