import SharedModels import Styleguide import SwiftUI public protocol FlaggedMessageViewStyle { associatedtype Body: View typealias Configuration = FlaggedMessageViewStyleConfiguration @ViewBuilder func makeBody(configuration: Self.Configuration) -> Self.Body } public struct FlaggedMessageViewStyleConfiguration { public let message: String? public let status: Flagged.CheckResult.Status public init(message: String?, status: Flagged.CheckResult.Status) { self.message = message self.status = status } } public struct AnyFlaggedMessageViewStyle: FlaggedMessageViewStyle { private let _makeBody: (Configuration) -> AnyView internal init(makeBody: @escaping (Configuration) -> AnyView) { self._makeBody = makeBody } public init(_ style: S) { self.init { configuration in AnyView(style.makeBody(configuration: configuration)) } } public func makeBody(configuration: Configuration) -> some View { _makeBody(configuration) } } public struct DefaultFlaggedMessageViewStyle: FlaggedMessageViewStyle { @ViewBuilder public func makeBody(configuration: Configuration) -> some View { if let message = configuration.message { HStack { Text(configuration.status.title) .bold() .foregroundStyle(configuration.status.flagColor) TextLabel(message) } .font(.caption) } } } public struct VerticalFlaggedMessageViewStyle: FlaggedMessageViewStyle { @ViewBuilder public func makeBody(configuration: Configuration) -> some View { if let message = configuration.message { VStack(alignment: .leading) { Text(configuration.status.title) .bold() .foregroundStyle(configuration.status.flagColor) TextLabel(message) } .font(.caption) } } } extension FlaggedMessageViewStyle where Self == VerticalFlaggedMessageViewStyle { public static var vertical: Self { .init() } } extension FlaggedMessageViewStyle where Self == DefaultFlaggedMessageViewStyle { public static var horizontal: Self { .init() } public static var `default`: Self { .init() } } private struct FlaggedMessageViewStyleKey: EnvironmentKey { static var defaultValue = AnyFlaggedMessageViewStyle(DefaultFlaggedMessageViewStyle()) } extension EnvironmentValues { public var flaggedMessageViewStyle: AnyFlaggedMessageViewStyle { get { self[FlaggedMessageViewStyleKey.self] } set { self[FlaggedMessageViewStyleKey.self] = newValue } } } extension View { public func flaggedMessageViewStyle(_ style: AnyFlaggedMessageViewStyle) -> some View { environment(\.flaggedMessageViewStyle, style) } public func flaggedMessageViewStyle(_ style: S) -> some View { flaggedMessageViewStyle(AnyFlaggedMessageViewStyle(style)) } } extension Flagged.CheckResult.Status { var flagColor: Color { switch self { case .good: return .green case .warning: return .yellow case .error: return .red } } }