Add lead workflows, PDF signing, AR projects and photo gallery integration
This commit is contained in:
@ -60,8 +60,8 @@ struct GalleryView: View {
|
||||
PhotoViewer(
|
||||
photo: photo,
|
||||
photos: project.photos.sorted { $0.creationDate > $1.creationDate }
|
||||
) {
|
||||
delete(photo)
|
||||
) { selected in
|
||||
delete(selected)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -158,9 +158,10 @@ private struct DrawingStroke {
|
||||
var isEraser: Bool
|
||||
}
|
||||
|
||||
private struct PhotoViewer: View {
|
||||
struct PhotoViewer: View {
|
||||
let photos: [ProjectPhoto]
|
||||
let onDelete: () -> Void
|
||||
let onDelete: (ProjectPhoto) throws -> Void
|
||||
let usesNavigationStack: Bool
|
||||
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
@Environment(\.modelContext) private var modelContext
|
||||
@ -172,19 +173,36 @@ private struct PhotoViewer: View {
|
||||
@State private var drawingColor = Color.red
|
||||
@State private var drawingWidth: Double = 0.012
|
||||
@State private var imageRevision = 0
|
||||
@State private var deletionError: String?
|
||||
|
||||
private var currentPhoto: ProjectPhoto {
|
||||
photos[currentIndex]
|
||||
}
|
||||
|
||||
init(photo: ProjectPhoto, photos: [ProjectPhoto], onDelete: @escaping () -> Void) {
|
||||
init(photo: ProjectPhoto, photos: [ProjectPhoto], usesNavigationStack: Bool = true,
|
||||
onDelete: @escaping (ProjectPhoto) throws -> Void) {
|
||||
self.photos = photos
|
||||
self.onDelete = onDelete
|
||||
self.usesNavigationStack = usesNavigationStack
|
||||
_currentIndex = State(initialValue: photos.firstIndex(of: photo) ?? 0)
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
Group {
|
||||
if usesNavigationStack {
|
||||
NavigationStack { content }
|
||||
} else {
|
||||
content
|
||||
}
|
||||
}
|
||||
.alert("Foto konnte nicht gelöscht werden", isPresented: Binding(
|
||||
get: { deletionError != nil }, set: { if !$0 { deletionError = nil } }
|
||||
)) {
|
||||
Button("OK", role: .cancel) { deletionError = nil }
|
||||
} message: { Text(deletionError ?? "") }
|
||||
}
|
||||
|
||||
private var content: some View {
|
||||
TabView(selection: $currentIndex) {
|
||||
ForEach(photos.indices, id: \.self) { index in
|
||||
photoLayout(for: photos[index])
|
||||
@ -197,7 +215,7 @@ private struct PhotoViewer: View {
|
||||
ToolbarItem(placement: .topBarLeading) {
|
||||
if isDrawing {
|
||||
EmptyView()
|
||||
} else {
|
||||
} else if usesNavigationStack {
|
||||
Button("Fertig") { dismiss() }
|
||||
}
|
||||
}
|
||||
@ -213,8 +231,10 @@ private struct PhotoViewer: View {
|
||||
.accessibilityLabel("Zeichnung speichern")
|
||||
} else {
|
||||
Button("Löschen", systemImage: "trash", role: .destructive) {
|
||||
onDelete()
|
||||
dismiss()
|
||||
do {
|
||||
try onDelete(currentPhoto)
|
||||
dismiss()
|
||||
} catch { deletionError = error.localizedDescription }
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -250,7 +270,6 @@ private struct PhotoViewer: View {
|
||||
}
|
||||
}
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
}
|
||||
|
||||
private func photoLayout(for photo: ProjectPhoto) -> some View {
|
||||
@ -619,6 +638,6 @@ private struct PhotoLocationCard: View {
|
||||
|
||||
#Preview("Foto-Detail") {
|
||||
let photo = PreviewSupport.samplePhoto()
|
||||
PhotoViewer(photo: photo, photos: [photo]) {}
|
||||
PhotoViewer(photo: photo, photos: [photo]) { _ in }
|
||||
}
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user