feat(app): add flow diagnostics and refine interface
Improve failure recovery visibility, strengthen account-session handling, and make the cross-platform interface more consistent.
This commit is contained in:
@@ -81,34 +81,134 @@ public struct SurfaceCardModifier: ViewModifier {
|
||||
@Environment(\.themePalette) private var palette
|
||||
|
||||
private let enabled: Bool
|
||||
private let elevated: Bool
|
||||
|
||||
public init(enabled: Bool = true) {
|
||||
public init(enabled: Bool = true, elevated: Bool = true) {
|
||||
self.enabled = enabled
|
||||
self.elevated = elevated
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
public func body(content: Content) -> some View {
|
||||
if enabled {
|
||||
let shape = RoundedRectangle(cornerRadius: Radius.xl, style: .continuous)
|
||||
content
|
||||
let card = content
|
||||
.background(
|
||||
palette.surface,
|
||||
elevated ? palette.surface : palette.formSurface,
|
||||
in: shape
|
||||
)
|
||||
// Clip child backgrounds as well as the card surface. Without
|
||||
// this, a full-width child can visually square off a corner.
|
||||
.clipShape(shape)
|
||||
if elevated {
|
||||
card.cardElevation()
|
||||
} else {
|
||||
card
|
||||
}
|
||||
} else {
|
||||
content
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct CardElevationModifier: ViewModifier {
|
||||
@Environment(\.colorScheme) private var colorScheme
|
||||
|
||||
let accented: Bool
|
||||
|
||||
@ViewBuilder
|
||||
func body(content: Content) -> some View {
|
||||
#if os(iOS)
|
||||
// Layered low-opacity shadows create direction and length without
|
||||
// turning the warm background gray.
|
||||
content
|
||||
.shadow(
|
||||
color: nearShadowColor,
|
||||
radius: 1,
|
||||
x: 2,
|
||||
y: 3
|
||||
)
|
||||
.shadow(
|
||||
color: midShadowColor,
|
||||
radius: 3,
|
||||
x: 6,
|
||||
y: 8
|
||||
)
|
||||
.shadow(
|
||||
color: farShadowColor,
|
||||
radius: 9,
|
||||
x: 12,
|
||||
y: 18
|
||||
)
|
||||
#else
|
||||
content
|
||||
#endif
|
||||
}
|
||||
|
||||
private var nearShadowColor: Color {
|
||||
guard accented else { return OSGColor.cardShadowNear }
|
||||
return colorScheme == .dark
|
||||
? OSGColor.selectedCardShadowNearDark
|
||||
: OSGColor.selectedCardShadowNearLight
|
||||
}
|
||||
|
||||
private var midShadowColor: Color {
|
||||
guard accented else { return OSGColor.cardShadowMid }
|
||||
return colorScheme == .dark
|
||||
? OSGColor.selectedCardShadowMidDark
|
||||
: OSGColor.selectedCardShadowMidLight
|
||||
}
|
||||
|
||||
private var farShadowColor: Color {
|
||||
guard accented else { return OSGColor.cardShadowFar }
|
||||
return colorScheme == .dark
|
||||
? OSGColor.selectedCardShadowFarDark
|
||||
: OSGColor.selectedCardShadowFarLight
|
||||
}
|
||||
}
|
||||
|
||||
private struct CardListRowModifier: ViewModifier {
|
||||
let bottomSpacing: CGFloat
|
||||
let elevated: Bool
|
||||
|
||||
func body(content: Content) -> some View {
|
||||
content
|
||||
.surfaceCard(elevated: elevated)
|
||||
.listRowInsets(
|
||||
EdgeInsets(
|
||||
top: 0,
|
||||
leading: 0,
|
||||
bottom: bottomSpacing,
|
||||
trailing: 0
|
||||
)
|
||||
)
|
||||
.listRowBackground(Color.clear)
|
||||
.listRowSeparator(.hidden)
|
||||
}
|
||||
}
|
||||
|
||||
public extension View {
|
||||
func cardSectionLabel() -> some View {
|
||||
modifier(CardSectionLabelModifier())
|
||||
}
|
||||
|
||||
func surfaceCard(enabled: Bool = true) -> some View {
|
||||
modifier(SurfaceCardModifier(enabled: enabled))
|
||||
func surfaceCard(
|
||||
enabled: Bool = true,
|
||||
elevated: Bool = true
|
||||
) -> some View {
|
||||
modifier(SurfaceCardModifier(enabled: enabled, elevated: elevated))
|
||||
}
|
||||
|
||||
func cardElevation(accented: Bool = false) -> some View {
|
||||
modifier(CardElevationModifier(accented: accented))
|
||||
}
|
||||
|
||||
/// Makes a native List/Form row render as an elevated app card while
|
||||
/// retaining system scrolling, swipe actions, refresh, and keyboard logic.
|
||||
func cardListRow(
|
||||
bottomSpacing: CGFloat = 0,
|
||||
elevated: Bool = true
|
||||
) -> some View {
|
||||
modifier(CardListRowModifier(bottomSpacing: bottomSpacing, elevated: elevated))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user