141 lines
5.0 KiB
Swift
141 lines
5.0 KiB
Swift
import SwiftUI
|
||
|
||
struct ARProjectCreateView: View {
|
||
let isEditing: Bool
|
||
let onCreate: (String, Tank, Bool) -> Void
|
||
@State private var name = ""
|
||
@State private var tank = Tank()
|
||
@Environment(\.tankCatalog) private var catalog
|
||
|
||
init(project: ARProject? = nil, onCreate: @escaping (String, Tank, Bool) -> Void) {
|
||
isEditing = project != nil
|
||
self.onCreate = onCreate
|
||
_name = State(initialValue: project?.name ?? "")
|
||
_tank = State(initialValue: project?.tank ?? Tank())
|
||
}
|
||
|
||
private var canCreate: Bool {
|
||
!name.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
|
||
&& catalog.definition(for: tank) != nil
|
||
}
|
||
|
||
var body: some View {
|
||
Form {
|
||
Section {
|
||
VStack(spacing: 8) {
|
||
ARProjectTankImage(tank: tank)
|
||
.frame(height: 150)
|
||
.frame(maxWidth: .infinity)
|
||
Text("\(tank.size.volumeTitle) · \(tank.placement.displayName) · \(catalog.displayName(for: tank.color))")
|
||
.font(.subheadline).foregroundStyle(.secondary)
|
||
}
|
||
.padding(.vertical, 8)
|
||
}
|
||
Section("Name") {
|
||
TextField("Projektname", text: $name)
|
||
.textInputAutocapitalization(.sentences)
|
||
}
|
||
Section("Tankkonfiguration") {
|
||
ARProjectConfigurationView(tank: $tank)
|
||
}
|
||
}
|
||
.navigationTitle(isEditing ? "Projekt bearbeiten" : "Neues Projekt")
|
||
.navigationBarTitleDisplayMode(.inline)
|
||
.toolbar {
|
||
ToolbarItem(placement: .confirmationAction) {
|
||
Button(isEditing ? "Speichern" : "Anlegen") { onCreate(name, tank, false) }
|
||
.disabled(!canCreate)
|
||
}
|
||
}
|
||
.safeAreaInset(edge: .bottom) {
|
||
Button { onCreate(name, tank, true) } label: {
|
||
Label(isEditing ? "Speichern und AR-Modus starten" : "Anlegen und AR-Modus starten", systemImage: "arkit")
|
||
.font(.headline).frame(maxWidth: .infinity).padding(.vertical, 10)
|
||
}
|
||
.buttonStyle(.borderedProminent)
|
||
.disabled(!canCreate)
|
||
.padding()
|
||
.background(.bar)
|
||
}
|
||
.onAppear { tank = catalog.normalized(tank) }
|
||
}
|
||
}
|
||
|
||
struct ARProjectConfigurationView: View {
|
||
@Binding var tank: Tank
|
||
@Environment(\.tankCatalog) private var catalog
|
||
|
||
var body: some View {
|
||
VStack(alignment: .leading, spacing: 10) {
|
||
Text("Volumen").font(.subheadline)
|
||
Picker("Volumen", selection: $tank.size) {
|
||
ForEach(catalog.sizes(for: tank.placement)) { size in
|
||
Text(size.volumeTitle).tag(size)
|
||
}
|
||
}
|
||
.pickerStyle(.segmented)
|
||
}
|
||
.padding(.vertical, 4)
|
||
|
||
VStack(alignment: .leading, spacing: 10) {
|
||
Text("Aufstellung").font(.subheadline)
|
||
Picker("Aufstellung", selection: $tank.placement) {
|
||
ForEach(catalog.placements) { placement in
|
||
Text(placement.displayName).tag(placement)
|
||
}
|
||
}
|
||
.pickerStyle(.segmented)
|
||
}
|
||
.padding(.vertical, 4)
|
||
|
||
HStack {
|
||
Text("Farbe")
|
||
Spacer()
|
||
ForEach(catalog.colors(for: tank.size, placement: tank.placement)) { color in
|
||
Button { tank.color = color } label: {
|
||
Circle().fill(swatch(color))
|
||
.frame(width: 28, height: 28)
|
||
.overlay { Circle().strokeBorder(.gray.opacity(0.5), lineWidth: 1) }
|
||
.padding(4)
|
||
.overlay { Circle().strokeBorder(tank.color == color ? Color.accentColor : .clear, lineWidth: 2) }
|
||
.frame(minWidth: 44, minHeight: 44)
|
||
}
|
||
.buttonStyle(.plain)
|
||
.accessibilityLabel(catalog.displayName(for: color))
|
||
.accessibilityAddTraits(tank.color == color ? .isSelected : [])
|
||
}
|
||
Text(catalog.displayName(for: tank.color)).foregroundStyle(.secondary).font(.subheadline)
|
||
}
|
||
.onChange(of: tank.placement) { _, _ in normalize() }
|
||
.onChange(of: tank.size) { _, _ in normalize() }
|
||
}
|
||
|
||
private func normalize() {
|
||
tank = catalog.normalized(tank)
|
||
tank.showLidOnly = false
|
||
}
|
||
|
||
private func swatch(_ color: TankColor) -> Color {
|
||
switch color {
|
||
case .white: .white
|
||
case .green: Color(red: 0.49, green: 0.65, blue: 0.42)
|
||
case .olive: Color(red: 0.37, green: 0.40, blue: 0.22)
|
||
}
|
||
}
|
||
}
|
||
|
||
#Preview("Projekt konfigurieren") {
|
||
NavigationStack {
|
||
ARProjectCreateView { _, _, _ in }
|
||
}
|
||
.frame(width: 600, height: 760)
|
||
}
|
||
|
||
#Preview("Projekt konfigurieren – Dunkel") {
|
||
NavigationStack {
|
||
ARProjectCreateView { _, _, _ in }
|
||
}
|
||
.frame(width: 600, height: 760)
|
||
.preferredColorScheme(.dark)
|
||
}
|