06/11 Fix some errors: submission datetime incorrect; inspection & issue not linked, etc
This commit is contained in:
@@ -1823,6 +1823,7 @@ struct TemplatesListView: View {
|
||||
struct SettingsView: View {
|
||||
@EnvironmentObject private var auth: AuthManager
|
||||
@EnvironmentObject private var sync: SyncManager
|
||||
@EnvironmentObject private var appearance: AppearanceManager
|
||||
@Environment(\.modelContext) private var context
|
||||
|
||||
@State private var showClearCacheAlert = false
|
||||
@@ -1837,6 +1838,15 @@ struct SettingsView: View {
|
||||
LabeledContent("Username", value: auth.currentUsername)
|
||||
LabeledContent("Role", value: auth.currentUserRole.capitalized)
|
||||
}
|
||||
|
||||
Section("Appearance") {
|
||||
Picker("Theme", selection: $appearance.mode) {
|
||||
ForEach(AppearanceMode.allCases, id: \.self) { mode in
|
||||
Text(mode.displayName).tag(mode)
|
||||
}
|
||||
}
|
||||
.pickerStyle(.segmented)
|
||||
}
|
||||
|
||||
Section("Sync") {
|
||||
Button {
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
import SwiftUI
|
||||
import SwiftData
|
||||
import CoreLocation
|
||||
|
||||
struct ExecuteInspectionView: View {
|
||||
|
||||
@@ -28,6 +29,10 @@ struct ExecuteInspectionView: View {
|
||||
@State private var isSubmitting = false
|
||||
@State private var submitResult: SubmitResult?
|
||||
|
||||
// Location manager — created lazily when submit alert fires so the
|
||||
// permission prompt only appears at the point of actual submission.
|
||||
@State private var locationManager = InspectionLocationManager()
|
||||
|
||||
// Auto-save interval
|
||||
private let autoSaveInterval: TimeInterval = 30
|
||||
|
||||
@@ -98,6 +103,11 @@ struct ExecuteInspectionView: View {
|
||||
? "Once submitted the inspection cannot be edited. It will be sent to the server now."
|
||||
: "Once submitted the inspection cannot be edited. It will sync automatically when you're back online.")
|
||||
}
|
||||
.onChange(of: showSubmitAlert) { _, showing in
|
||||
// Begin acquiring a GPS fix the moment the confirm dialog appears
|
||||
// so a location is likely ready by the time the inspector taps Submit.
|
||||
if showing { locationManager.requestLocation() }
|
||||
}
|
||||
// Result overlay
|
||||
.overlay(alignment: .top) {
|
||||
if let result = submitResult {
|
||||
@@ -378,6 +388,16 @@ struct ExecuteInspectionView: View {
|
||||
inspection.completedAt = Date()
|
||||
inspection.syncStatus = "pending"
|
||||
|
||||
// ── GPS ───────────────────────────────────────────────────────────
|
||||
// Use whatever fix the location manager has at this moment.
|
||||
// lastLocation is nil if permission was denied or no fix arrived yet;
|
||||
// the fields stay nil and the server silently omits them — same as web
|
||||
// submissions where the user declined the browser location prompt.
|
||||
if let loc = locationManager.lastLocation {
|
||||
inspection.submitLatitude = loc.coordinate.latitude
|
||||
inspection.submitLongitude = loc.coordinate.longitude
|
||||
}
|
||||
|
||||
// ── Clear follow-up flag on parent immediately ────────────────────
|
||||
// Do this at submit time rather than relying solely on SyncManager,
|
||||
// so the badge disappears the moment the inspector taps Submit —
|
||||
@@ -1138,3 +1158,70 @@ struct ConnectivityBadge: View {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - InspectionLocationManager
|
||||
// Thin CLLocationManager wrapper used only by ExecuteInspectionView.
|
||||
// Requests a single best-accuracy fix when the Submit confirmation dialog
|
||||
// appears. The fix is stored in lastLocation and read synchronously at the
|
||||
// moment the inspector confirms submission.
|
||||
//
|
||||
// Design constraints:
|
||||
// - @Observable is unavailable before iOS 17 WWDC beta; use plain class +
|
||||
// manual @State on the call site (already done above).
|
||||
// - CLLocationManager delegate callbacks arrive on the main thread when the
|
||||
// manager is created on the main thread (which @State guarantees here).
|
||||
// - requestWhenInUseAuthorization() is a no-op if permission was already
|
||||
// granted or permanently denied; it only shows the system prompt once.
|
||||
// - NSLocationWhenInUseUsageDescription must be present in the app's
|
||||
// Info.plist / build settings (add via Xcode target → Info tab).
|
||||
|
||||
final class InspectionLocationManager: NSObject, CLLocationManagerDelegate {
|
||||
|
||||
private let manager = CLLocationManager()
|
||||
|
||||
/// Most recent location fix, or nil if unavailable.
|
||||
private(set) var lastLocation: CLLocation?
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
manager.delegate = self
|
||||
manager.desiredAccuracy = kCLLocationAccuracyBest
|
||||
manager.distanceFilter = kCLDistanceFilterNone
|
||||
}
|
||||
|
||||
/// Request permission (if needed) and start a single location update.
|
||||
/// Safe to call multiple times — CLLocationManager ignores duplicate requests.
|
||||
func requestLocation() {
|
||||
switch manager.authorizationStatus {
|
||||
case .notDetermined:
|
||||
manager.requestWhenInUseAuthorization()
|
||||
// Delegate callback didChangeAuthorization will call requestLocation()
|
||||
// again once the user responds.
|
||||
case .authorizedWhenInUse, .authorizedAlways:
|
||||
manager.requestLocation()
|
||||
default:
|
||||
// Denied / restricted — lastLocation stays nil; GPS fields stay nil.
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// CLLocationManagerDelegate
|
||||
|
||||
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
|
||||
// Keep the most accurate fix received.
|
||||
lastLocation = locations.last
|
||||
}
|
||||
|
||||
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
|
||||
// Non-fatal — GPS fields will be nil; submission still proceeds.
|
||||
print("[JQC] Location fix failed: \(error.localizedDescription)")
|
||||
}
|
||||
|
||||
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
|
||||
// If the user just granted permission, start the fix immediately.
|
||||
if manager.authorizationStatus == .authorizedWhenInUse ||
|
||||
manager.authorizationStatus == .authorizedAlways {
|
||||
manager.requestLocation()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user