Fixing location manager. Rewriting add/edit locations in SwiftUI

This commit is contained in:
Selim Mustafaev 2024-07-28 22:06:16 +03:00
parent 44c28e912d
commit 350ee8042a
13 changed files with 405 additions and 52 deletions

View File

@ -8,6 +8,14 @@
/* Begin PBXBuildFile section */
6841A85D4B60DB71D1E68DA0 /* ImageGrid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6841AC687EA6293A0757678C /* ImageGrid.swift */; };
7A1022692C55197D00B84627 /* RealmSwift in Embed Frameworks */ = {isa = PBXBuildFile; productRef = 7ADF23052C25B5BF002624FF /* RealmSwift */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
7A10226C2C551EC500B84627 /* LocationEditScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A10226B2C551EC500B84627 /* LocationEditScreen.swift */; };
7A10226E2C551EE000B84627 /* LocationEditViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A10226D2C551EE000B84627 /* LocationEditViewModel.swift */; };
7A1022702C551EFD00B84627 /* LocationEditCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A10226F2C551EFD00B84627 /* LocationEditCoordinator.swift */; };
7A1022722C554A1300B84627 /* CustomHostingController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1022712C554A1300B84627 /* CustomHostingController.swift */; };
7A1022772C557EC400B84627 /* LocationPickerScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1022762C557EC400B84627 /* LocationPickerScreen.swift */; };
7A1022792C557ED600B84627 /* LocationPickerViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1022782C557ED600B84627 /* LocationPickerViewModel.swift */; };
7A10227B2C557EE900B84627 /* LocationPickerCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A10227A2C557EE900B84627 /* LocationPickerCoordinator.swift */; };
7A1090E824A394F100B4F0B2 /* AudioRecordCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1090E724A394F100B4F0B2 /* AudioRecordCell.swift */; };
7A1090EA24A3A26300B4F0B2 /* AudioPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1090E924A3A26300B4F0B2 /* AudioPlayer.swift */; };
7A1090EC24A4E3E100B4F0B2 /* CellProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1090EB24A4E3E100B4F0B2 /* CellProgressView.swift */; };
@ -80,6 +88,7 @@
7A64AE752469DFB600ABE48E /* MediaBrowserViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A64AE712469DFB600ABE48E /* MediaBrowserViewController.swift */; };
7A64AE762469DFB600ABE48E /* ContentTransformers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A64AE722469DFB600ABE48E /* ContentTransformers.swift */; };
7A659B5B24A3768A0043A0F2 /* Substrings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A659B5A24A3768A0043A0F2 /* Substrings.swift */; };
7A6C4D9E2C56BCA600982597 /* SwiftLocation in Frameworks */ = {isa = PBXBuildFile; productRef = 7A6C4D9D2C56BCA600982597 /* SwiftLocation */; };
7A6DD903242BF4A5009DE740 /* PlateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6DD902242BF4A5009DE740 /* PlateView.swift */; };
7A6DD90824329144009DE740 /* CenterTextLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A6DD90724329144009DE740 /* CenterTextLayer.swift */; };
7A6DD90A24329541009DE740 /* RoadNumbers2.0.otf in Resources */ = {isa = PBXBuildFile; fileRef = 7A6DD90924329541009DE740 /* RoadNumbers2.0.otf */; };
@ -99,7 +108,6 @@
7A761C08267E8EA20005F28F /* JWT.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A43F9F7246C8A6200BA5B49 /* JWT.swift */; };
7A761C09267E8EE40005F28F /* Base64FS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A96AE32246C095700297C33 /* Base64FS.swift */; };
7A761C0B267E8FF90005F28F /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A761C0A267E8FF90005F28F /* Error.swift */; };
7A813DBE2506A57100CC93B9 /* AuthenticationServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A813DBD2506A57100CC93B9 /* AuthenticationServices.framework */; };
7A813DC32508EE4F00CC93B9 /* EventCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A813DC22508EE4F00CC93B9 /* EventCell.swift */; };
7A813DC5250AAF3C00CC93B9 /* LocationEditController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A813DC4250AAF3C00CC93B9 /* LocationEditController.swift */; };
7A813DC9250B5C9700CC93B9 /* LocationRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A813DC8250B5C9700CC93B9 /* LocationRow.swift */; };
@ -108,7 +116,6 @@
7A8A220B248D67B60073DFD9 /* VehicleReportImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A8A220A248D67B60073DFD9 /* VehicleReportImage.swift */; };
7A8AB76525A0DB8F00ECF2C1 /* BundleVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A8AB76425A0DB8F00ECF2C1 /* BundleVersion.swift */; };
7A8AB76B25A1D95500ECF2C1 /* SourceStatusRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A8AB76A25A1D95500ECF2C1 /* SourceStatusRow.swift */; };
7A8C4A5B2C1C55680052DDF3 /* SwiftLocation in Frameworks */ = {isa = PBXBuildFile; productRef = 7A8C4A5A2C1C55680052DDF3 /* SwiftLocation */; };
7A91894F29A2BD8700519C74 /* GestureRecognizers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A91894E29A2BD8700519C74 /* GestureRecognizers.swift */; };
7A961C6C2C4C3C8600CE2211 /* TextRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A961C6B2C4C3C8600CE2211 /* TextRowView.swift */; };
7A961C6E2C4C3C9E00CE2211 /* LinkRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A961C6D2C4C3C9E00CE2211 /* LinkRowView.swift */; };
@ -116,7 +123,6 @@
7A96AE2F246B2BCD00297C33 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A96AE2E246B2BCD00297C33 /* WebKit.framework */; };
7A99406426E4BFAE002E9CB6 /* VehicleNoteCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A99406326E4BFAE002E9CB6 /* VehicleNoteCell.swift */; };
7A9FEEC82529AB23001CA50E /* RxRealmDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9FEEC72529AB23001CA50E /* RxRealmDataSource.swift */; };
7AA363362C25B64A00851D6D /* RealmSwift in Embed Frameworks */ = {isa = PBXBuildFile; productRef = 7A1CF80429A41C66007962DA /* RealmSwift */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
7AA7BC3325A5DFB80053A5D5 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 7AF58D332402A91C00CE01A0 /* Kingfisher */; };
7AA7BC3525A5DFB80053A5D5 /* ExceptionCatcher in Frameworks */ = {isa = PBXBuildFile; productRef = 7A813DC02508C4D900CC93B9 /* ExceptionCatcher */; };
7AA7BC3625A5DFB80053A5D5 /* PKHUD in Frameworks */ = {isa = PBXBuildFile; productRef = 7AABDE1C2532F3EB0041AFC6 /* PKHUD */; };
@ -211,7 +217,6 @@
dstPath = "";
dstSubfolderSpec = 10;
files = (
7AA363362C25B64A00851D6D /* RealmSwift in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
@ -222,6 +227,7 @@
dstPath = "";
dstSubfolderSpec = 10;
files = (
7A1022692C55197D00B84627 /* RealmSwift in Embed Frameworks */,
7AF6D2052677C03B0086EA64 /* AutoCatCore.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
@ -235,6 +241,13 @@
7A000AA124C2EEDE001F5B00 /* Location.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Location.swift; sourceTree = "<group>"; };
7A0420A925619AEC00034941 /* Osago.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Osago.swift; sourceTree = "<group>"; };
7A0516192414FF0900FC55AC /* DateSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateSection.swift; sourceTree = "<group>"; };
7A10226B2C551EC500B84627 /* LocationEditScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationEditScreen.swift; sourceTree = "<group>"; };
7A10226D2C551EE000B84627 /* LocationEditViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationEditViewModel.swift; sourceTree = "<group>"; };
7A10226F2C551EFD00B84627 /* LocationEditCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationEditCoordinator.swift; sourceTree = "<group>"; };
7A1022712C554A1300B84627 /* CustomHostingController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomHostingController.swift; sourceTree = "<group>"; };
7A1022762C557EC400B84627 /* LocationPickerScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationPickerScreen.swift; sourceTree = "<group>"; };
7A1022782C557ED600B84627 /* LocationPickerViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationPickerViewModel.swift; sourceTree = "<group>"; };
7A10227A2C557EE900B84627 /* LocationPickerCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationPickerCoordinator.swift; sourceTree = "<group>"; };
7A1090E724A394F100B4F0B2 /* AudioRecordCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioRecordCell.swift; sourceTree = "<group>"; };
7A1090E924A3A26300B4F0B2 /* AudioPlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioPlayer.swift; sourceTree = "<group>"; };
7A1090EB24A4E3E100B4F0B2 /* CellProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CellProgressView.swift; sourceTree = "<group>"; };
@ -415,7 +428,6 @@
files = (
7AA7BC3525A5DFB80053A5D5 /* ExceptionCatcher in Frameworks */,
7AA7BC3325A5DFB80053A5D5 /* Kingfisher in Frameworks */,
7A813DBE2506A57100CC93B9 /* AuthenticationServices.framework in Frameworks */,
7ADF23062C25B5BF002624FF /* RealmSwift in Frameworks */,
7AA7BC3625A5DFB80053A5D5 /* PKHUD in Frameworks */,
7AC3554A2969652F00889457 /* SwiftEntryKit in Frameworks */,
@ -449,7 +461,7 @@
7A1CF80529A41C66007962DA /* RealmSwift in Frameworks */,
7AABB1F2267E9CC800D7AB32 /* SwiftDate in Frameworks */,
7A176DB72C432F8800999D6B /* Mockable in Frameworks */,
7A8C4A5B2C1C55680052DDF3 /* SwiftLocation in Frameworks */,
7A6C4D9E2C56BCA600982597 /* SwiftLocation in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -465,6 +477,26 @@
path = eureka;
sourceTree = "<group>";
};
7A10226A2C551EA200B84627 /* LocationEditScreen */ = {
isa = PBXGroup;
children = (
7A10226B2C551EC500B84627 /* LocationEditScreen.swift */,
7A10226D2C551EE000B84627 /* LocationEditViewModel.swift */,
7A10226F2C551EFD00B84627 /* LocationEditCoordinator.swift */,
);
path = LocationEditScreen;
sourceTree = "<group>";
};
7A1022752C557E3F00B84627 /* LocationPickerScreen */ = {
isa = PBXGroup;
children = (
7A1022762C557EC400B84627 /* LocationPickerScreen.swift */,
7A1022782C557ED600B84627 /* LocationPickerViewModel.swift */,
7A10227A2C557EE900B84627 /* LocationPickerCoordinator.swift */,
);
path = LocationPickerScreen;
sourceTree = "<group>";
};
7A1146F423FDE7E500B424AF = {
isa = PBXGroup;
children = (
@ -593,6 +625,8 @@
7A1441632C297E9800E79018 /* Screens */ = {
isa = PBXGroup;
children = (
7A1022752C557E3F00B84627 /* LocationPickerScreen */,
7A10226A2C551EA200B84627 /* LocationEditScreen */,
7A71580A2C44451B00852088 /* AdsScreen */,
7A7158052C44083F00852088 /* OsagoScreen */,
7A7157FE2C43EA5200852088 /* OwnersScreen */,
@ -909,6 +943,7 @@
7A961C6B2C4C3C8600CE2211 /* TextRowView.swift */,
7A961C6D2C4C3C9E00CE2211 /* LinkRowView.swift */,
7AAAFAD92C4D1AFE0050410D /* Zoomable.swift */,
7A1022712C554A1300B84627 /* CustomHostingController.swift */,
);
path = SwiftUI;
sourceTree = "<group>";
@ -1031,8 +1066,8 @@
packageProductDependencies = (
7AABB1F1267E9CC800D7AB32 /* SwiftDate */,
7A1CF80429A41C66007962DA /* RealmSwift */,
7A8C4A5A2C1C55680052DDF3 /* SwiftLocation */,
7A176DB62C432F8800999D6B /* Mockable */,
7A6C4D9D2C56BCA600982597 /* SwiftLocation */,
);
productName = AutoCatCore;
productReference = 7AF6D1EF2677C03B0086EA64 /* AutoCatCore.framework */;
@ -1081,8 +1116,8 @@
7A35177927E23F8800DC538C /* XCRemoteSwiftPackageReference "Eureka" */,
7AC355482969652F00889457 /* XCRemoteSwiftPackageReference "SwiftEntryKit" */,
7A1CF7FD29A41C2F007962DA /* XCRemoteSwiftPackageReference "realm-swift" */,
7AF336F72C1C54EC002FB8A3 /* XCRemoteSwiftPackageReference "SwiftLocation" */,
7A176DB52C432F8800999D6B /* XCRemoteSwiftPackageReference "Mockable" */,
7A6C4D9C2C56BCA600982597 /* XCRemoteSwiftPackageReference "SwiftLocation" */,
);
productRefGroup = 7A1146FE23FDE7E500B424AF /* Products */;
projectDirPath = "";
@ -1142,6 +1177,7 @@
files = (
7A961C6C2C4C3C8600CE2211 /* TextRowView.swift in Sources */,
7AEFC3BE2529D3CC00BADFB2 /* ConfigurableCell.swift in Sources */,
7A1022772C557EC400B84627 /* LocationPickerScreen.swift in Sources */,
7A7158092C44087E00852088 /* OsagoCoordinator.swift in Sources */,
7A1441662C297EDE00E79018 /* NotesScreen.swift in Sources */,
7A11470123FDE7E500B424AF /* AppDelegate.swift in Sources */,
@ -1180,6 +1216,7 @@
7A71580E2C4445A200852088 /* AdsCoordinator.swift in Sources */,
7AFBE8CA2C3081C7003C491D /* ACProgressHud+Modifiers.swift in Sources */,
7A27ADF7249FEF690035F39E /* Recorder.swift in Sources */,
7A10226C2C551EC500B84627 /* LocationEditScreen.swift in Sources */,
7A7158072C44085600852088 /* OsagoScreen.swift in Sources */,
7AAAFAD32C4D0FD00050410D /* ACImageSliderView.swift in Sources */,
7A3F07AB24360DC800E59687 /* Dated.swift in Sources */,
@ -1195,14 +1232,18 @@
7A64AE742469DFB600ABE48E /* MediaContentView.swift in Sources */,
7A1090EC24A4E3E100B4F0B2 /* CellProgressView.swift in Sources */,
7A96AE2D246B2B7400297C33 /* GoogleSignInController.swift in Sources */,
7A10227B2C557EE900B84627 /* LocationPickerCoordinator.swift in Sources */,
7A176DB22C43071A00999D6B /* ApiServiceStub.swift in Sources */,
7A1090EA24A3A26300B4F0B2 /* AudioPlayer.swift in Sources */,
7A11471623FDEB2A00B424AF /* MainSplitController.swift in Sources */,
7A813DC5250AAF3C00CC93B9 /* LocationEditController.swift in Sources */,
7A6DD903242BF4A5009DE740 /* PlateView.swift in Sources */,
7A1022722C554A1300B84627 /* CustomHostingController.swift in Sources */,
7ADF6C9F251201D200F237B2 /* GlobalEventsController.swift in Sources */,
7A1022792C557ED600B84627 /* LocationPickerViewModel.swift in Sources */,
7A11470323FDE7E500B424AF /* SceneDelegate.swift in Sources */,
7A530B7E24017FEE00CBFE6E /* VehicleCell.swift in Sources */,
7A10226E2C551EE000B84627 /* LocationEditViewModel.swift in Sources */,
7AFBE8CE2C308B53003C491D /* ACMessageView.swift in Sources */,
7A14416C2C297F2100E79018 /* NotesCoordinator.swift in Sources */,
7A813DCB250B5DC900CC93B9 /* LocationPickerController.swift in Sources */,
@ -1229,6 +1270,7 @@
7A64AE752469DFB600ABE48E /* MediaBrowserViewController.swift in Sources */,
7A64AE732469DFB600ABE48E /* DismissAnimationController.swift in Sources */,
7ADF6C97250F41B000F237B2 /* PNKeyboard.swift in Sources */,
7A1022702C551EFD00B84627 /* LocationEditCoordinator.swift in Sources */,
7A7158042C43EAA200852088 /* OwnersCoordinator.swift in Sources */,
7A7547E024032CB6004E8406 /* VehiclePhotoCell.swift in Sources */,
7A17CE4C2A2E850200626A6E /* UISegmentedControl.swift in Sources */,
@ -1501,7 +1543,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 127;
CURRENT_PROJECT_VERSION = 129;
DEVELOPMENT_TEAM = 46DTTB8X4S;
INFOPLIST_FILE = AutoCat/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = AutoCat;
@ -1527,7 +1569,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 127;
CURRENT_PROJECT_VERSION = 129;
DEVELOPMENT_TEAM = 46DTTB8X4S;
INFOPLIST_FILE = AutoCat/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = AutoCat;
@ -1787,6 +1829,14 @@
minimumVersion = 5.0.0;
};
};
7A6C4D9C2C56BCA600982597 /* XCRemoteSwiftPackageReference "SwiftLocation" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/malcommac/SwiftLocation.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 6.0.0;
};
};
7A813DBF2508C4D900CC93B9 /* XCRemoteSwiftPackageReference "ExceptionCatcher" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/sindresorhus/ExceptionCatcher";
@ -1811,14 +1861,6 @@
minimumVersion = 2.0.0;
};
};
7AF336F72C1C54EC002FB8A3 /* XCRemoteSwiftPackageReference "SwiftLocation" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/malcommac/SwiftLocation.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 6.0.0;
};
};
7AF58D322402A91C00CE01A0 /* XCRemoteSwiftPackageReference "Kingfisher" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/onevcat/Kingfisher";
@ -1850,16 +1892,16 @@
package = 7A35177927E23F8800DC538C /* XCRemoteSwiftPackageReference "Eureka" */;
productName = Eureka;
};
7A6C4D9D2C56BCA600982597 /* SwiftLocation */ = {
isa = XCSwiftPackageProductDependency;
package = 7A6C4D9C2C56BCA600982597 /* XCRemoteSwiftPackageReference "SwiftLocation" */;
productName = SwiftLocation;
};
7A813DC02508C4D900CC93B9 /* ExceptionCatcher */ = {
isa = XCSwiftPackageProductDependency;
package = 7A813DBF2508C4D900CC93B9 /* XCRemoteSwiftPackageReference "ExceptionCatcher" */;
productName = ExceptionCatcher;
};
7A8C4A5A2C1C55680052DDF3 /* SwiftLocation */ = {
isa = XCSwiftPackageProductDependency;
package = 7AF336F72C1C54EC002FB8A3 /* XCRemoteSwiftPackageReference "SwiftLocation" */;
productName = SwiftLocation;
};
7AABB1F1267E9CC800D7AB32 /* SwiftDate */ = {
isa = XCSwiftPackageProductDependency;
package = 7A05160F241412CA00FC55AC /* XCRemoteSwiftPackageReference "SwiftDate" */;

View File

@ -253,27 +253,22 @@ class EventsController: UIViewController, UITableViewDataSource, UITableViewDele
}
func editEvent(event: VehicleEventDto) {
let sb = UIStoryboard(name: "Main", bundle: nil)
let controller = sb.instantiateViewController(identifier: "LocationEditController") as LocationEditController
controller.title = NSLocalizedString("Edit event", comment: "")
controller.date = Date(timeIntervalSince1970: event.date)
controller.placemark = Placemark(latitude: event.latitude, longitude: event.longitude, address: event.address)
controller.onDone = { newEvent in
var updatedEvent = newEvent
updatedEvent.id = event.id
self.navigationController?.popViewController(animated: true, completion: {
if let navigationController {
let coordinator = LocationEditCoordinator(navController: navigationController,
event: event)
Task {
if let event = try await coordinator.start() {
do {
HUD.show(.progress)
let vehicle = try await ApiService.shared.edit(event: updatedEvent)
let vehicle = try await ApiService.shared.edit(event: event)
self.update(vehicle: vehicle)
} catch {
HUD.show(error: error)
}
}
})
}
self.navigationController?.pushViewController(controller, animated: true)
}
}
func copyEvent(event: VehicleEventDto) {
@ -327,23 +322,21 @@ class EventsController: UIViewController, UITableViewDataSource, UITableViewDele
return
}
let sb = UIStoryboard(name: "Main", bundle: nil)
let controller = sb.instantiateViewController(identifier: "LocationEditController") as LocationEditController
controller.title = NSLocalizedString("Add new event", comment: "")
controller.onDone = { newEvent in
self.navigationController?.popViewController(animated: true, completion: {
if let navigationController {
let coordinator = LocationEditCoordinator(navController: navigationController)
Task {
if let event = try await coordinator.start() {
do {
HUD.show(.progress)
let vehicle = try await ApiService.shared.add(event: newEvent, to: vehicle.getNumber())
let vehicle = try await ApiService.shared.add(event: event, to: vehicle.getNumber())
self.update(vehicle: vehicle)
} catch {
HUD.show(error: error)
}
}
})
}
self.navigationController?.pushViewController(controller, animated: true)
}
}
@objc func pasteEvent(_ sender: UIBarButtonItem) {
@ -390,16 +383,16 @@ class EventsController: UIViewController, UITableViewDataSource, UITableViewDele
func update(vehicle: VehicleDto) -> Bool {
do {
let realm = try Realm()
if let realmVehicle = realm.object(ofType: Vehicle.self, forPrimaryKey: vehicle.getNumber()) {
if realm.object(ofType: Vehicle.self, forPrimaryKey: vehicle.getNumber()) != nil {
try ExceptionCatcher.catch {
try realm.write {
realm.add(Vehicle(dto: vehicle), update: .all)
}
}
} else {
self.vehicle?.events = vehicle.events
}
self.updateInterface()
self.vehicle?.events = vehicle.events.sorted { $0.date > $1.date }
HUD.hide()
return true
} catch {

View File

@ -114,9 +114,11 @@ class RecordsController: UIViewController, UITableViewDelegate {
let session = notification.object as? AVAudioSession else { return }
if reason == .categoryChange && session.category == .playAndRecord {
DispatchQueue.main.async {
alert = self.showRecordingAlert()
}
}
}
#endif
let date = Date()
let fileName = "recording-\(date.timeIntervalSince1970).m4a"

View File

@ -0,0 +1,42 @@
//
// LocationEditCoordinator.swift
// AutoCat
//
// Created by Selim Mustafaev on 27.07.2024.
// Copyright © 2024 Selim Mustafaev. All rights reserved.
//
import UIKit
import SwiftUI
import AutoCatCore
@MainActor
final class LocationEditCoordinator: Coordinator {
let viewController: UINavigationController?
let event: VehicleEventDto
init(navController: UINavigationController?, event: VehicleEventDto? = nil) {
self.viewController = navController
self.event = event ?? VehicleEventDto(lat: 0, lon: 0)
}
func start() async throws -> VehicleEventDto? {
let viewModel = LocationEditViewModel(event: event)
viewModel.coordinator = self
let screen = LocationEditScreen(viewModel: viewModel)
let controller = CustomHostingController(rootView: screen)
viewController?.pushViewController(controller, animated: true)
await controller.waitForDisappear()
return viewModel.result
}
func openLocationPicker(event: VehicleEventDto) async -> VehicleEventDto? {
let coordinator = LocationPickerCoordinator(navController: viewController,
event: event)
return try? await coordinator.start()
}
}

View File

@ -0,0 +1,45 @@
//
// LocationEditScreen.swift
// AutoCat
//
// Created by Selim Mustafaev on 27.07.2024.
// Copyright © 2024 Selim Mustafaev. All rights reserved.
//
import SwiftUI
import AutoCatCore
struct LocationEditScreen: View {
@Environment(\.dismiss) var dismiss
@StateObject var viewModel: LocationEditViewModel
var body: some View {
List {
DatePicker("Date", selection: $viewModel.date)
.datePickerStyle(.compact)
TextRowView(title: "Location", value: viewModel.event.location)
.onTapGesture {
Task { await viewModel.pickLocation() }
}
}
.navigationTitle("Edit event")
.toolbar {
ToolbarItem(placement: .primaryAction) {
Button("Done") {
viewModel.done()
dismiss()
}
}
}
}
}
#Preview {
var event = VehicleEventDto(lat: 25.54984, lon: 36.34857)
event.address = "Ул. Ленина, 123"
return LocationEditScreen(viewModel: .init(event: event))
}

View File

@ -0,0 +1,37 @@
//
// LocationEditViewModel.swift
// AutoCat
//
// Created by Selim Mustafaev on 27.07.2024.
// Copyright © 2024 Selim Mustafaev. All rights reserved.
//
import AutoCatCore
import SwiftUI
@MainActor
final class LocationEditViewModel: ObservableObject {
weak var coordinator: LocationEditCoordinator?
@Published var event: VehicleEventDto
@Published var date: Date
var result: VehicleEventDto?
init(event: VehicleEventDto) {
self.event = event
self.date = Date(timeIntervalSince1970: event.date)
}
func done() {
event.date = date.timeIntervalSince1970
result = event
}
func pickLocation() async {
if let newEvent = await coordinator?.openLocationPicker(event: event) {
event = newEvent
}
}
}

View File

@ -0,0 +1,33 @@
//
// LocationPickerCoordinator.swift
// AutoCat
//
// Created by Selim Mustafaev on 27.07.2024.
// Copyright © 2024 Selim Mustafaev. All rights reserved.
//
import UIKit
import SwiftUI
import AutoCatCore
@MainActor
final class LocationPickerCoordinator: Coordinator {
let viewController: UINavigationController?
let event: VehicleEventDto
init(navController: UINavigationController?, event: VehicleEventDto) {
self.viewController = navController
self.event = event
}
func start() async throws -> VehicleEventDto? {
let viewModel = LocationPickerViewModel(event: event)
let screen = LocationPickerScreen(viewModel: viewModel)
let controller = CustomHostingController(rootView: screen)
viewController?.pushViewController(controller, animated: true)
await controller.waitForDisappear()
return viewModel.result
}
}

View File

@ -0,0 +1,48 @@
//
// LocationPickerScreen.swift
// AutoCat
//
// Created by Selim Mustafaev on 27.07.2024.
// Copyright © 2024 Selim Mustafaev. All rights reserved.
//
import SwiftUI
import AutoCatCore
import MapKit
struct LocationPickerScreen: View {
@Environment(\.dismiss) var dismiss
@StateObject var viewModel: LocationPickerViewModel
var body: some View {
ZStack {
Map(coordinateRegion: $viewModel.region)
Image(systemName: "mappin.and.ellipse")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(height: 48)
.offset(.init(width: 0, height: -10))
.foregroundColor(.blue)
}
.ignoresSafeArea()
.navigationTitle(viewModel.event.location)
.toolbar {
ToolbarItem(placement: .primaryAction) {
Button("Done") {
viewModel.done()
dismiss()
}
}
}
}
}
#Preview {
var event = VehicleEventDto(lat: 47.250049, lon: 39.711821)
event.address = "Ул. Ленина, 123"
return LocationPickerScreen(viewModel: .init(event: event))
}

View File

@ -0,0 +1,74 @@
//
// LocationPickerViewModel.swift
// AutoCat
//
// Created by Selim Mustafaev on 27.07.2024.
// Copyright © 2024 Selim Mustafaev. All rights reserved.
//
import AutoCatCore
import Combine
import MapKit
import SwiftUI
@MainActor
final class LocationPickerViewModel: ObservableObject {
@Published var event: VehicleEventDto
@Published var region: MKCoordinateRegion {
didSet {
Task { await updateEvent(region: region) }
}
}
var result: VehicleEventDto?
var geocodingTask: Task<Void, Error>?
init(event: VehicleEventDto) {
self.event = event
let center = CLLocationCoordinate2D(latitude: event.latitude, longitude: event.longitude)
self.region = MKCoordinateRegion(center: center,
latitudinalMeters: 1000,
longitudinalMeters: 1000)
if event.latitude == 0 && event.longitude == 0 {
Task { await moveToCurrentLocation() }
}
}
func moveToCurrentLocation() async {
do {
let currentEvent = try await RxLocationManager.requestCurrentLocation()
let center = CLLocationCoordinate2D(latitude: currentEvent.latitude,
longitude: currentEvent.longitude)
self.region = MKCoordinateRegion(center: center,
latitudinalMeters: 1000,
longitudinalMeters: 1000)
event.latitude = currentEvent.latitude
event.longitude = currentEvent.longitude
event.address = try? await RxLocationManager.getAddressForLocation(latitude: region.center.latitude,
longitude: region.center.longitude)
} catch {
print(error)
}
}
func updateEvent(region: MKCoordinateRegion) async {
geocodingTask?.cancel()
geocodingTask = Task {
event.latitude = region.center.latitude
event.longitude = region.center.longitude
try await Task.sleep(nanoseconds: 500_000_000)
event.address = try? await RxLocationManager.getAddressForLocation(latitude: region.center.latitude,
longitude: region.center.longitude)
geocodingTask = nil
}
}
func done() {
result = event
}
}

View File

@ -0,0 +1,27 @@
//
// CustomHostingController.swift
// AutoCat
//
// Created by Selim Mustafaev on 27.07.2024.
// Copyright © 2024 Selim Mustafaev. All rights reserved.
//
import UIKit
import SwiftUI
final class CustomHostingController<T: View>: UIHostingController<T> {
var continuation: CheckedContinuation<Void, Never>?
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
if isMovingFromParent || isBeingDismissed {
continuation?.resume()
}
}
func waitForDisappear() async {
await withCheckedContinuation { continuation = $0 }
}
}

View File

@ -10,7 +10,7 @@ import SwiftUI
struct TextRowView: View {
let title: String
let title: LocalizedStringKey
let value: String?
var body: some View {
@ -36,7 +36,7 @@ struct TextRowView: View {
struct SimpleTextRowView: View {
let title: String
let title: LocalizedStringKey
let value: String?
var body: some View {

View File

@ -41,6 +41,14 @@ public struct VehicleEventDto: Codable, Sendable {
}
}
public var location: String {
if let address {
return address
} else {
return "\(latitude), \(longitude)"
}
}
public func findAddress() async throws {
guard address == nil else {
return

View File

@ -17,6 +17,7 @@ enum LocationError: LocalizedError {
}
}
@MainActor
public class RxLocationManager {
private let generalErrors: [CLError.Code] = [.locationUnknown, .denied, .network, .headingFailure, .rangingUnavailable, .rangingFailure]
@ -68,6 +69,7 @@ public class RxLocationManager {
if let eventTask {
return try await eventTask.value
} else {
try await checkPermissions()
let task = Task {
let location = try await requestLocation()
eventTask = nil