PadXcode-iPad/Build/PreflightView.swift

80 lines
3.9 KiB
Swift
Raw Permalink Normal View History

2026-04-12 00:46:30 -07:00
import SwiftUI
struct PreflightView: View {
let report: PreflightReport
let action: String
let onProceed: () -> Void
let onCancel: () -> Void
var body: some View {
NavigationStack {
VStack(spacing: 0) {
summaryHeader.padding(.horizontal, 20).padding(.vertical, 16)
.background(headerBg)
Divider()
List(report.checks) { check in
HStack(spacing: 10) {
Image(systemName: check.icon).foregroundStyle(check.color).font(.system(size: 16)).frame(width: 20)
VStack(alignment: .leading, spacing: 2) {
Text(check.name).font(.subheadline)
Text(check.detail).font(.caption).foregroundStyle(.secondary).lineLimit(2)
}
}
.padding(.vertical, 6)
}
.listStyle(.plain)
Divider()
HStack(spacing: 12) {
Button("Cancel", action: onCancel).buttonStyle(.bordered).frame(maxWidth: .infinity)
if report.canProceed {
Button(action: onProceed) {
Label(action == "buildAndRun" ? "Build & Run" : "Build",
systemImage: action == "buildAndRun" ? "play.fill" : "hammer.fill")
.frame(maxWidth: .infinity)
}
.buttonStyle(.borderedProminent)
.tint(report.hasWarnings ? .orange : .green)
} else {
Button("Fix Issues", action: onCancel)
.buttonStyle(.borderedProminent).tint(.red).frame(maxWidth: .infinity)
}
}
.padding(.horizontal, 20).padding(.vertical, 14)
.background(Color(.secondarySystemBackground))
}
.navigationTitle("Pre-Build Checks")
.navigationBarTitleDisplayMode(.inline)
.toolbar { ToolbarItem(placement: .cancellationAction) { Button("Cancel", action: onCancel) } }
}
.presentationDetents([.medium, .large])
.presentationDragIndicator(.visible)
}
private var summaryHeader: some View {
HStack(spacing: 14) {
Image(systemName: summaryIcon).font(.system(size: 36, weight: .medium)).foregroundStyle(summaryColor)
VStack(alignment: .leading, spacing: 3) {
Text(summaryTitle).font(.headline)
Text(summarySubtitle).font(.subheadline).foregroundStyle(.secondary)
}
Spacer()
}
}
private var summaryIcon: String { !report.canProceed ? "xmark.circle.fill" : report.hasWarnings ? "exclamationmark.triangle.fill" : "checkmark.circle.fill" }
private var summaryColor: Color { !report.canProceed ? .red : report.hasWarnings ? .orange : .green }
private var summaryTitle: String { !report.canProceed ? "Build Blocked" : report.hasWarnings ? "Ready with Warnings" : "All Checks Passed" }
private var headerBg: Color { !report.canProceed ? Color.red.opacity(0.08) : report.hasWarnings ? Color.orange.opacity(0.08) : Color.green.opacity(0.08) }
private var summarySubtitle: String {
let f = report.checks.filter { if case .fail = $0.status { return true }; return false }.count
let w = report.checks.filter { if case .warning = $0.status { return true }; return false }.count
let p = report.checks.filter { if case .pass = $0.status { return true }; return false }.count
var parts: [String] = []
if f > 0 { parts.append("\(f) failure\(f == 1 ? "" : "s")") }
if w > 0 { parts.append("\(w) warning\(w == 1 ? "" : "s")") }
if p > 0 { parts.append("\(p) passed") }
return parts.joined(separator: " · ")
}
}