Add lead workflows, PDF signing, AR projects and photo gallery integration
This commit is contained in:
52
GasTankAR/Views/Leads/Shared/LeadDocumentPreview.swift
Normal file
52
GasTankAR/Views/Leads/Shared/LeadDocumentPreview.swift
Normal file
@ -0,0 +1,52 @@
|
||||
import SwiftUI
|
||||
import QuickLook
|
||||
|
||||
/// Native full-screen PDF reading, including zoom, page navigation and system open-in actions.
|
||||
struct LeadDocumentPreview: View {
|
||||
let url: URL
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
LeadQuickLookView(url: url)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .confirmationAction) {
|
||||
Button(role: .confirm) { dismiss() }
|
||||
.labelStyle(.iconOnly)
|
||||
.accessibilityLabel("Zurück zur Unterschrift")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private struct LeadQuickLookView: UIViewControllerRepresentable {
|
||||
let url: URL
|
||||
|
||||
func makeUIViewController(context: Context) -> QLPreviewController {
|
||||
let controller = QLPreviewController()
|
||||
controller.dataSource = context.coordinator
|
||||
return controller
|
||||
}
|
||||
|
||||
func updateUIViewController(_ controller: QLPreviewController, context: Context) {
|
||||
guard context.coordinator.url != url else { return }
|
||||
context.coordinator.url = url
|
||||
controller.reloadData()
|
||||
}
|
||||
|
||||
func makeCoordinator() -> Coordinator { Coordinator(url: url) }
|
||||
|
||||
final class Coordinator: NSObject, QLPreviewControllerDataSource {
|
||||
var url: URL
|
||||
|
||||
init(url: URL) { self.url = url }
|
||||
|
||||
func numberOfPreviewItems(in controller: QLPreviewController) -> Int { 1 }
|
||||
|
||||
func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> any QLPreviewItem {
|
||||
url as NSURL
|
||||
}
|
||||
}
|
||||
}
|
||||
72
GasTankAR/Views/Leads/Shared/LeadPDFView.swift
Normal file
72
GasTankAR/Views/Leads/Shared/LeadPDFView.swift
Normal file
@ -0,0 +1,72 @@
|
||||
import SwiftUI
|
||||
import PDFKit
|
||||
|
||||
struct LeadPDFView: UIViewRepresentable {
|
||||
let url: URL
|
||||
var signaturePlacement: PDFSignaturePlacement?
|
||||
var fitsWholePage = false
|
||||
var onPageChanged: ((Int, Int) -> Void)?
|
||||
|
||||
func makeUIView(context: Context) -> PDFView {
|
||||
let view = PDFView()
|
||||
view.displayMode = fitsWholePage ? .singlePage : .singlePageContinuous
|
||||
if fitsWholePage {
|
||||
view.displayDirection = .horizontal
|
||||
view.usePageViewController(true)
|
||||
}
|
||||
view.autoScales = true
|
||||
view.backgroundColor = .secondarySystemGroupedBackground
|
||||
context.coordinator.observe(view)
|
||||
return view
|
||||
}
|
||||
|
||||
func updateUIView(_ view: PDFView, context: Context) {
|
||||
context.coordinator.onPageChanged = onPageChanged
|
||||
guard view.document?.documentURL != url else { return }
|
||||
view.document = PDFDocument(url: url)
|
||||
view.autoScales = true
|
||||
if let signaturePlacement,
|
||||
let page = view.document?.page(at: signaturePlacement.pageIndex) {
|
||||
// The marker exists only in the preview; the signing service reads the original file.
|
||||
let marker = PDFAnnotation(bounds: signaturePlacement.bounds, forType: .square, withProperties: nil)
|
||||
marker.color = .systemOrange
|
||||
marker.interiorColor = UIColor.systemOrange.withAlphaComponent(0.08)
|
||||
marker.contents = "Unterschrift Kunde"
|
||||
let border = PDFBorder()
|
||||
border.lineWidth = 1
|
||||
border.style = .dashed
|
||||
border.dashPattern = [3, 2]
|
||||
marker.border = border
|
||||
page.addAnnotation(marker)
|
||||
view.go(to: page)
|
||||
}
|
||||
context.coordinator.report(view)
|
||||
}
|
||||
|
||||
func makeCoordinator() -> Coordinator { Coordinator() }
|
||||
|
||||
final class Coordinator: NSObject {
|
||||
var onPageChanged: ((Int, Int) -> Void)?
|
||||
|
||||
func observe(_ view: PDFView) {
|
||||
NotificationCenter.default.addObserver(
|
||||
self, selector: #selector(pageChanged(_:)), name: .PDFViewPageChanged, object: view
|
||||
)
|
||||
}
|
||||
|
||||
@objc private func pageChanged(_ notification: Notification) {
|
||||
guard let view = notification.object as? PDFView else { return }
|
||||
report(view)
|
||||
}
|
||||
|
||||
func report(_ view: PDFView) {
|
||||
guard let document = view.document, let page = view.currentPage else { return }
|
||||
let number = document.index(for: page) + 1
|
||||
let count = document.pageCount
|
||||
// Avoid changing SwiftUI state while the representable is updating.
|
||||
Task { @MainActor [weak self] in self?.onPageChanged?(number, count) }
|
||||
}
|
||||
|
||||
deinit { NotificationCenter.default.removeObserver(self) }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user