Introduce TankDefinition/TankCatalog loaded from Tanks.json, bundle the Drachengas USDZ tank models, add tank selection and preview views, and update the AR experience, editor and project views to use the catalog. Includes tests for catalog loading and model selection. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
102 lines
3.3 KiB
Swift
102 lines
3.3 KiB
Swift
//
|
|
// ProjectListView.swift
|
|
// GasTankAR
|
|
//
|
|
// Created by Dennis Nemec on 25.08.26.
|
|
//
|
|
|
|
import SwiftUI
|
|
import SwiftData
|
|
|
|
struct ProjectListView: View {
|
|
@Environment(\.modelContext) private var modelContext
|
|
@Query(sort: \Project.creationDate, order: .reverse) private var projects: [Project]
|
|
|
|
@State private var selectedProject: Project?
|
|
@State private var isCreatingProject = false
|
|
@State private var isShowingSettings = false
|
|
|
|
var body: some View {
|
|
NavigationSplitView {
|
|
List(selection: $selectedProject) {
|
|
ForEach(projects) { project in
|
|
ProjectListItem(project: project)
|
|
.tag(project)
|
|
}
|
|
.onDelete(perform: deleteProjects)
|
|
}
|
|
.overlay {
|
|
if projects.isEmpty {
|
|
ContentUnavailableView(
|
|
"Keine Projekte",
|
|
systemImage: "tray",
|
|
description: Text("Tippe auf +, um dein erstes Projekt zu erstellen.")
|
|
)
|
|
}
|
|
}
|
|
.navigationTitle(Text("Projekte"))
|
|
.toolbar {
|
|
ToolbarItem(placement: .topBarTrailing) {
|
|
Button("Einstellungen", systemImage: "gearshape") {
|
|
isShowingSettings = true
|
|
}
|
|
}
|
|
}
|
|
.sheet(isPresented: $isShowingSettings) {
|
|
SettingsView()
|
|
}
|
|
.overlay(alignment: .bottomTrailing) {
|
|
GlassEffectContainer {
|
|
Button {
|
|
isCreatingProject = true
|
|
} label: {
|
|
Image(systemName: "plus")
|
|
.font(.title2.weight(.semibold))
|
|
.frame(width: 56, height: 56)
|
|
.contentShape(.circle)
|
|
}
|
|
.buttonStyle(.plain)
|
|
.glassEffect(.regular.interactive(), in: .circle)
|
|
}
|
|
.padding()
|
|
.accessibilityLabel("Projekt erstellen")
|
|
}
|
|
.sheet(isPresented: $isCreatingProject) {
|
|
ProjectCreateView { project in
|
|
selectedProject = project
|
|
}
|
|
}
|
|
} detail: {
|
|
NavigationStack {
|
|
if let selectedProject {
|
|
ProjectDetailView(project: selectedProject)
|
|
} else {
|
|
ContentUnavailableView(
|
|
"Kein Projekt ausgewählt",
|
|
systemImage: "hand.point.up.left",
|
|
description: Text("Wähle links ein Projekt aus, um die Details zu sehen.")
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private func deleteProjects(at offsets: IndexSet) {
|
|
for index in offsets {
|
|
let project = projects[index]
|
|
if project == selectedProject { selectedProject = nil }
|
|
modelContext.delete(project)
|
|
}
|
|
}
|
|
}
|
|
|
|
#Preview("Gefüllt") {
|
|
ProjectListView()
|
|
.modelContainer(PreviewSupport.container)
|
|
}
|
|
|
|
#Preview("Leer") {
|
|
ProjectListView()
|
|
.modelContainer(PreviewSupport.makeEmptyContainer())
|
|
}
|