feat: Moves flagged views into their own module.
This commit is contained in:
@@ -13,6 +13,7 @@ let package = Package(
|
||||
products: [
|
||||
.library(name: "CalculateAtFeature", targets: ["CalculateAtFeature"]),
|
||||
.library(name: "EstimatedPressureDependency", targets: ["EstimatedPressureDependency"]),
|
||||
.library(name: "FlaggedViews", targets: ["FlaggedViews"]),
|
||||
.library(name: "PressureEstimationsFeature", targets: ["PressureEstimationsFeature"]),
|
||||
.library(name: "SharedModels", targets: ["SharedModels"]),
|
||||
.library(name: "Styleguide", targets: ["Styleguide"]),
|
||||
@@ -55,6 +56,13 @@ let package = Package(
|
||||
.product(name: "DependenciesMacros", package: "swift-dependencies")
|
||||
]
|
||||
),
|
||||
.target(
|
||||
name: "FlaggedViews",
|
||||
dependencies: [
|
||||
"SharedModels",
|
||||
"Styleguide"
|
||||
]
|
||||
),
|
||||
.target(name: "SharedModels"),
|
||||
.target(
|
||||
name: "Styleguide",
|
||||
@@ -74,6 +82,7 @@ let package = Package(
|
||||
name: "PressureEstimationsFeature",
|
||||
dependencies: [
|
||||
"EstimatedPressureDependency",
|
||||
"FlaggedViews",
|
||||
"SharedModels",
|
||||
"Styleguide",
|
||||
.product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
|
||||
|
||||
32
Sources/FlaggedViews/FlaggedMessageView.swift
Normal file
32
Sources/FlaggedViews/FlaggedMessageView.swift
Normal file
@@ -0,0 +1,32 @@
|
||||
import SharedModels
|
||||
import SwiftUI
|
||||
|
||||
public struct FlaggedMessageView: View {
|
||||
|
||||
@Environment(\.flaggedMessageViewStyle) private var style
|
||||
|
||||
let message: String?
|
||||
let status: Flagged.CheckResult.Status
|
||||
|
||||
public init(message: String?, status: Flagged.CheckResult.Status) {
|
||||
self.message = message
|
||||
self.status = status
|
||||
}
|
||||
|
||||
public var body: some View {
|
||||
style.makeBody(
|
||||
configuration: .init(message: message, status: status)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
extension FlaggedMessageView {
|
||||
|
||||
public init(flagged: Flagged) {
|
||||
self.init(message: flagged.message, status: flagged.status)
|
||||
}
|
||||
}
|
||||
|
||||
//#Preview {
|
||||
// SwiftUIView()
|
||||
//}
|
||||
115
Sources/FlaggedViews/Styles/FlaggedMessageViewStyle.swift
Normal file
115
Sources/FlaggedViews/Styles/FlaggedMessageViewStyle.swift
Normal file
@@ -0,0 +1,115 @@
|
||||
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<S: FlaggedMessageViewStyle>(_ 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<S: 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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -68,7 +68,7 @@ public struct DefaultFlagViewStyle: FlaggedViewStyle {
|
||||
)
|
||||
configuration.flagged.flagImage
|
||||
}
|
||||
flaggedMessageView(flagged: configuration.flagged)
|
||||
FlaggedMessageView(flagged: configuration.flagged)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -87,13 +87,13 @@ public struct FlagAndMessageOnlyStyle: FlaggedViewStyle {
|
||||
switch stackStyle {
|
||||
case .horizontal:
|
||||
HStack {
|
||||
flaggedMessageView(flagged: configuration.flagged)
|
||||
FlaggedMessageView(flagged: configuration.flagged)
|
||||
configuration.flagged.flagImage
|
||||
}
|
||||
case .vertical:
|
||||
VStack {
|
||||
configuration.flagged.flagImage
|
||||
flaggedMessageView(flagged: configuration.flagged)
|
||||
FlaggedMessageView(flagged: configuration.flagged)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -114,7 +114,7 @@ public struct FlaggedGridRowStyle: FlaggedViewStyle {
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
configuration.label
|
||||
.foregroundStyle(Color.secondary)
|
||||
flaggedMessageView(flagged: configuration.flagged)
|
||||
FlaggedMessageView(flagged: configuration.flagged)
|
||||
}
|
||||
Text(
|
||||
configuration.flagged.wrappedValue,
|
||||
@@ -149,23 +149,9 @@ extension FlaggedViewStyle where Self == DefaultFlagViewStyle {
|
||||
}
|
||||
}
|
||||
|
||||
fileprivate extension Flagged.CheckResult.Key {
|
||||
|
||||
var flagColor: Color {
|
||||
switch self {
|
||||
case .good:
|
||||
return .green
|
||||
case .warning:
|
||||
return .yellow
|
||||
case .error:
|
||||
return .red
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
extension Flagged {
|
||||
var flagColor: Color { projectedValue.key.flagColor }
|
||||
var flagColor: Color { self.status.flagColor }
|
||||
|
||||
public var flagImage: some View {
|
||||
Image(systemName: "flag.fill")
|
||||
@@ -173,20 +159,7 @@ extension Flagged {
|
||||
}
|
||||
|
||||
public var messageView: some View {
|
||||
flaggedMessageView(flagged: self)
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
fileprivate func flaggedMessageView(flagged: Flagged) -> some View {
|
||||
if let message = flagged.message {
|
||||
HStack {
|
||||
Text(flagged.projectedValue.key.title)
|
||||
.bold()
|
||||
.foregroundStyle(flagged.projectedValue.key.flagColor)
|
||||
TextLabel(message)
|
||||
}
|
||||
.font(.caption)
|
||||
FlaggedMessageView(flagged: self)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import ComposableArchitecture
|
||||
import FlaggedViews
|
||||
import SharedModels
|
||||
import Styleguide
|
||||
import SwiftUI
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import ComposableArchitecture
|
||||
import DependenciesAdditions
|
||||
import EstimatedPressureDependency
|
||||
import FlaggedViews
|
||||
import SharedModels
|
||||
import Styleguide
|
||||
import SwiftUI
|
||||
@@ -205,6 +206,7 @@ public struct FlaggedMeasurementsList {
|
||||
|
||||
@ViewAction(for: FlaggedMeasurementsList.self)
|
||||
public struct FlaggedMeasurementListView: View {
|
||||
@Environment(\.horizontalSizeClass) var horizontalSizeClass
|
||||
@Bindable public var store: StoreOf<FlaggedMeasurementsList>
|
||||
|
||||
public init(store: StoreOf<FlaggedMeasurementsList>) {
|
||||
@@ -265,6 +267,11 @@ public struct FlaggedMeasurementListView: View {
|
||||
}
|
||||
}
|
||||
.onAppear { send(.onAppear) }
|
||||
.flaggedMessageViewStyle(
|
||||
horizontalSizeClass == .compact
|
||||
? AnyFlaggedMessageViewStyle(.vertical)
|
||||
: AnyFlaggedMessageViewStyle(.horizontal)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -70,7 +70,7 @@ public struct Flagged: Equatable {
|
||||
case good(String? = nil)
|
||||
case error(String)
|
||||
|
||||
public var key: Key {
|
||||
public var status: Status {
|
||||
switch self {
|
||||
case .aboveMaximum(_):
|
||||
return .error
|
||||
@@ -110,7 +110,7 @@ public struct Flagged: Equatable {
|
||||
}
|
||||
}
|
||||
|
||||
public enum Key: String, Equatable, CaseIterable {
|
||||
public enum Status: String, Equatable, CaseIterable {
|
||||
case good, warning, error
|
||||
|
||||
public var title: String {
|
||||
|
||||
Reference in New Issue
Block a user