Removing Kingfisher package.
Adding License Plate view. Adding stub for new SwiftUI history screen.
This commit is contained in:
parent
57c222b937
commit
67977f1ebf
@ -30,6 +30,9 @@
|
|||||||
7A11470D23FDE7E600B424AF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7A11470B23FDE7E600B424AF /* LaunchScreen.storyboard */; };
|
7A11470D23FDE7E600B424AF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7A11470B23FDE7E600B424AF /* LaunchScreen.storyboard */; };
|
||||||
7A11471623FDEB2A00B424AF /* MainSplitController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11471523FDEB2A00B424AF /* MainSplitController.swift */; };
|
7A11471623FDEB2A00B424AF /* MainSplitController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11471523FDEB2A00B424AF /* MainSplitController.swift */; };
|
||||||
7A11471A23FE839000B424AF /* AuthController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11471923FE839000B424AF /* AuthController.swift */; };
|
7A11471A23FE839000B424AF /* AuthController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11471923FE839000B424AF /* AuthController.swift */; };
|
||||||
|
7A131FD32D37B75500DC7755 /* HistoryScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A131FD22D37B75500DC7755 /* HistoryScreen.swift */; };
|
||||||
|
7A131FD52D37B76A00DC7755 /* HistoryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A131FD42D37B76A00DC7755 /* HistoryViewModel.swift */; };
|
||||||
|
7A131FD72D37B77E00DC7755 /* HistoryCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A131FD62D37B77E00DC7755 /* HistoryCoordinator.swift */; };
|
||||||
7A1441662C297EDE00E79018 /* NotesScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1441652C297EDE00E79018 /* NotesScreen.swift */; };
|
7A1441662C297EDE00E79018 /* NotesScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1441652C297EDE00E79018 /* NotesScreen.swift */; };
|
||||||
7A1441682C297EFD00E79018 /* NotesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1441672C297EFD00E79018 /* NotesViewModel.swift */; };
|
7A1441682C297EFD00E79018 /* NotesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A1441672C297EFD00E79018 /* NotesViewModel.swift */; };
|
||||||
7A14416C2C297F2100E79018 /* NotesCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A14416B2C297F2100E79018 /* NotesCoordinator.swift */; };
|
7A14416C2C297F2100E79018 /* NotesCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A14416B2C297F2100E79018 /* NotesCoordinator.swift */; };
|
||||||
@ -115,7 +118,6 @@
|
|||||||
7A71580E2C4445A200852088 /* AdsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A71580D2C4445A200852088 /* AdsCoordinator.swift */; };
|
7A71580E2C4445A200852088 /* AdsCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A71580D2C4445A200852088 /* AdsCoordinator.swift */; };
|
||||||
7A7158122C444A6400852088 /* AdsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A7158112C444A6400852088 /* AdsViewModel.swift */; };
|
7A7158122C444A6400852088 /* AdsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A7158112C444A6400852088 /* AdsViewModel.swift */; };
|
||||||
7A71EF572D0A26B200943129 /* EventModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A71EF562D0A26B200943129 /* EventModel.swift */; };
|
7A71EF572D0A26B200943129 /* EventModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A71EF562D0A26B200943129 /* EventModel.swift */; };
|
||||||
7A7547E024032CB6004E8406 /* VehiclePhotoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A7547DF24032CB6004E8406 /* VehiclePhotoCell.swift */; };
|
|
||||||
7A761C042677F18E0005F28F /* ApiService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11474323FF06CA00B424AF /* ApiService.swift */; };
|
7A761C042677F18E0005F28F /* ApiService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11474323FF06CA00B424AF /* ApiService.swift */; };
|
||||||
7A761C052677F1BC0005F28F /* CocoaError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A27ADF824A09CAD0035F39E /* CocoaError.swift */; };
|
7A761C052677F1BC0005F28F /* CocoaError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A27ADF824A09CAD0035F39E /* CocoaError.swift */; };
|
||||||
7A761C07267E8E7F0005F28F /* AnyEncodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A15051124DB3E3000F39631 /* AnyEncodable.swift */; };
|
7A761C07267E8E7F0005F28F /* AnyEncodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A15051124DB3E3000F39631 /* AnyEncodable.swift */; };
|
||||||
@ -124,8 +126,8 @@
|
|||||||
7A761C0B267E8FF90005F28F /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A761C0A267E8FF90005F28F /* Error.swift */; };
|
7A761C0B267E8FF90005F28F /* Error.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A761C0A267E8FF90005F28F /* Error.swift */; };
|
||||||
7A813DC32508EE4F00CC93B9 /* EventCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A813DC22508EE4F00CC93B9 /* EventCell.swift */; };
|
7A813DC32508EE4F00CC93B9 /* EventCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A813DC22508EE4F00CC93B9 /* EventCell.swift */; };
|
||||||
7A8A2209248D10EC0073DFD9 /* ResizeImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A8A2208248D10EC0073DFD9 /* ResizeImage.swift */; };
|
7A8A2209248D10EC0073DFD9 /* ResizeImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A8A2208248D10EC0073DFD9 /* ResizeImage.swift */; };
|
||||||
7A8A220B248D67B60073DFD9 /* VehicleReportImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A8A220A248D67B60073DFD9 /* VehicleReportImage.swift */; };
|
|
||||||
7A8AB76525A0DB8F00ECF2C1 /* BundleVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A8AB76425A0DB8F00ECF2C1 /* BundleVersion.swift */; };
|
7A8AB76525A0DB8F00ECF2C1 /* BundleVersion.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A8AB76425A0DB8F00ECF2C1 /* BundleVersion.swift */; };
|
||||||
|
7A912F372D381B7400002938 /* LicensePlateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A912F362D381B7400002938 /* LicensePlateView.swift */; };
|
||||||
7A91894F29A2BD8700519C74 /* GestureRecognizers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A91894E29A2BD8700519C74 /* GestureRecognizers.swift */; };
|
7A91894F29A2BD8700519C74 /* GestureRecognizers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A91894E29A2BD8700519C74 /* GestureRecognizers.swift */; };
|
||||||
7A961C6C2C4C3C8600CE2211 /* TextRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A961C6B2C4C3C8600CE2211 /* TextRowView.swift */; };
|
7A961C6C2C4C3C8600CE2211 /* TextRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A961C6B2C4C3C8600CE2211 /* TextRowView.swift */; };
|
||||||
7A961C6E2C4C3C9E00CE2211 /* LinkRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A961C6D2C4C3C9E00CE2211 /* LinkRowView.swift */; };
|
7A961C6E2C4C3C9E00CE2211 /* LinkRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A961C6D2C4C3C9E00CE2211 /* LinkRowView.swift */; };
|
||||||
@ -134,7 +136,6 @@
|
|||||||
7A99406426E4BFAE002E9CB6 /* VehicleNoteCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A99406326E4BFAE002E9CB6 /* VehicleNoteCell.swift */; };
|
7A99406426E4BFAE002E9CB6 /* VehicleNoteCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A99406326E4BFAE002E9CB6 /* VehicleNoteCell.swift */; };
|
||||||
7A9FEEC82529AB23001CA50E /* RxRealmDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9FEEC72529AB23001CA50E /* RxRealmDataSource.swift */; };
|
7A9FEEC82529AB23001CA50E /* RxRealmDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9FEEC72529AB23001CA50E /* RxRealmDataSource.swift */; };
|
||||||
7AA514E02D0B75B3001CAC50 /* StorageService+Events.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AA514DF2D0B75B3001CAC50 /* StorageService+Events.swift */; };
|
7AA514E02D0B75B3001CAC50 /* StorageService+Events.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AA514DF2D0B75B3001CAC50 /* StorageService+Events.swift */; };
|
||||||
7AA7BC3325A5DFB80053A5D5 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 7AF58D332402A91C00CE01A0 /* Kingfisher */; };
|
|
||||||
7AA7BC3525A5DFB80053A5D5 /* ExceptionCatcher in Frameworks */ = {isa = PBXBuildFile; productRef = 7A813DC02508C4D900CC93B9 /* ExceptionCatcher */; };
|
7AA7BC3525A5DFB80053A5D5 /* ExceptionCatcher in Frameworks */ = {isa = PBXBuildFile; productRef = 7A813DC02508C4D900CC93B9 /* ExceptionCatcher */; };
|
||||||
7AA7BC3625A5DFB80053A5D5 /* PKHUD in Frameworks */ = {isa = PBXBuildFile; productRef = 7AABDE1C2532F3EB0041AFC6 /* PKHUD */; };
|
7AA7BC3625A5DFB80053A5D5 /* PKHUD in Frameworks */ = {isa = PBXBuildFile; productRef = 7AABDE1C2532F3EB0041AFC6 /* PKHUD */; };
|
||||||
7AAAFAD32C4D0FD00050410D /* ACImageSliderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AAAFAD22C4D0FD00050410D /* ACImageSliderView.swift */; };
|
7AAAFAD32C4D0FD00050410D /* ACImageSliderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AAAFAD22C4D0FD00050410D /* ACImageSliderView.swift */; };
|
||||||
@ -289,6 +290,9 @@
|
|||||||
7A11474623FF2AA500B424AF /* User.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = "<group>"; };
|
7A11474623FF2AA500B424AF /* User.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = "<group>"; };
|
||||||
7A11474823FF2B2D00B424AF /* Response.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Response.swift; sourceTree = "<group>"; };
|
7A11474823FF2B2D00B424AF /* Response.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Response.swift; sourceTree = "<group>"; };
|
||||||
7A11474D23FFEE8800B424AF /* SVProgressHUD.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SVProgressHUD.framework; path = Carthage/Build/iOS/SVProgressHUD.framework; sourceTree = "<group>"; };
|
7A11474D23FFEE8800B424AF /* SVProgressHUD.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SVProgressHUD.framework; path = Carthage/Build/iOS/SVProgressHUD.framework; sourceTree = "<group>"; };
|
||||||
|
7A131FD22D37B75500DC7755 /* HistoryScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryScreen.swift; sourceTree = "<group>"; };
|
||||||
|
7A131FD42D37B76A00DC7755 /* HistoryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryViewModel.swift; sourceTree = "<group>"; };
|
||||||
|
7A131FD62D37B77E00DC7755 /* HistoryCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryCoordinator.swift; sourceTree = "<group>"; };
|
||||||
7A1441652C297EDE00E79018 /* NotesScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotesScreen.swift; sourceTree = "<group>"; };
|
7A1441652C297EDE00E79018 /* NotesScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotesScreen.swift; sourceTree = "<group>"; };
|
||||||
7A1441672C297EFD00E79018 /* NotesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotesViewModel.swift; sourceTree = "<group>"; };
|
7A1441672C297EFD00E79018 /* NotesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotesViewModel.swift; sourceTree = "<group>"; };
|
||||||
7A14416B2C297F2100E79018 /* NotesCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotesCoordinator.swift; sourceTree = "<group>"; };
|
7A14416B2C297F2100E79018 /* NotesCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotesCoordinator.swift; sourceTree = "<group>"; };
|
||||||
@ -387,14 +391,13 @@
|
|||||||
7A71580D2C4445A200852088 /* AdsCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdsCoordinator.swift; sourceTree = "<group>"; };
|
7A71580D2C4445A200852088 /* AdsCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdsCoordinator.swift; sourceTree = "<group>"; };
|
||||||
7A7158112C444A6400852088 /* AdsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdsViewModel.swift; sourceTree = "<group>"; };
|
7A7158112C444A6400852088 /* AdsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdsViewModel.swift; sourceTree = "<group>"; };
|
||||||
7A71EF562D0A26B200943129 /* EventModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventModel.swift; sourceTree = "<group>"; };
|
7A71EF562D0A26B200943129 /* EventModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventModel.swift; sourceTree = "<group>"; };
|
||||||
7A7547DF24032CB6004E8406 /* VehiclePhotoCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehiclePhotoCell.swift; sourceTree = "<group>"; };
|
|
||||||
7A761C0A267E8FF90005F28F /* Error.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Error.swift; sourceTree = "<group>"; };
|
7A761C0A267E8FF90005F28F /* Error.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Error.swift; sourceTree = "<group>"; };
|
||||||
7A813DBD2506A57100CC93B9 /* AuthenticationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AuthenticationServices.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/AuthenticationServices.framework; sourceTree = DEVELOPER_DIR; };
|
7A813DBD2506A57100CC93B9 /* AuthenticationServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AuthenticationServices.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/AuthenticationServices.framework; sourceTree = DEVELOPER_DIR; };
|
||||||
7A813DC22508EE4F00CC93B9 /* EventCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventCell.swift; sourceTree = "<group>"; };
|
7A813DC22508EE4F00CC93B9 /* EventCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventCell.swift; sourceTree = "<group>"; };
|
||||||
7A8A2208248D10EC0073DFD9 /* ResizeImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResizeImage.swift; sourceTree = "<group>"; };
|
7A8A2208248D10EC0073DFD9 /* ResizeImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResizeImage.swift; sourceTree = "<group>"; };
|
||||||
7A8A220A248D67B60073DFD9 /* VehicleReportImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehicleReportImage.swift; sourceTree = "<group>"; };
|
|
||||||
7A8AB76425A0DB8F00ECF2C1 /* BundleVersion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BundleVersion.swift; sourceTree = "<group>"; };
|
7A8AB76425A0DB8F00ECF2C1 /* BundleVersion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BundleVersion.swift; sourceTree = "<group>"; };
|
||||||
7A8AB76725A0DC8200ECF2C1 /* DebugInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugInfo.swift; sourceTree = "<group>"; };
|
7A8AB76725A0DC8200ECF2C1 /* DebugInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugInfo.swift; sourceTree = "<group>"; };
|
||||||
|
7A912F362D381B7400002938 /* LicensePlateView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LicensePlateView.swift; sourceTree = "<group>"; };
|
||||||
7A91894E29A2BD8700519C74 /* GestureRecognizers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GestureRecognizers.swift; sourceTree = "<group>"; };
|
7A91894E29A2BD8700519C74 /* GestureRecognizers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GestureRecognizers.swift; sourceTree = "<group>"; };
|
||||||
7A92D0AB240425B100EF3B77 /* ATGMediaBrowser.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ATGMediaBrowser.framework; path = Carthage/Build/iOS/ATGMediaBrowser.framework; sourceTree = "<group>"; };
|
7A92D0AB240425B100EF3B77 /* ATGMediaBrowser.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ATGMediaBrowser.framework; path = Carthage/Build/iOS/ATGMediaBrowser.framework; sourceTree = "<group>"; };
|
||||||
7A961C6B2C4C3C8600CE2211 /* TextRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextRowView.swift; sourceTree = "<group>"; };
|
7A961C6B2C4C3C8600CE2211 /* TextRowView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TextRowView.swift; sourceTree = "<group>"; };
|
||||||
@ -468,7 +471,6 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
7AA7BC3525A5DFB80053A5D5 /* ExceptionCatcher in Frameworks */,
|
7AA7BC3525A5DFB80053A5D5 /* ExceptionCatcher in Frameworks */,
|
||||||
7AA7BC3325A5DFB80053A5D5 /* Kingfisher in Frameworks */,
|
|
||||||
7ADF23062C25B5BF002624FF /* RealmSwift in Frameworks */,
|
7ADF23062C25B5BF002624FF /* RealmSwift in Frameworks */,
|
||||||
7AA7BC3625A5DFB80053A5D5 /* PKHUD in Frameworks */,
|
7AA7BC3625A5DFB80053A5D5 /* PKHUD in Frameworks */,
|
||||||
7AC3554A2969652F00889457 /* SwiftEntryKit in Frameworks */,
|
7AC3554A2969652F00889457 /* SwiftEntryKit in Frameworks */,
|
||||||
@ -670,9 +672,20 @@
|
|||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
7A131FD12D37B74100DC7755 /* HistoryScreen */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
7A131FD22D37B75500DC7755 /* HistoryScreen.swift */,
|
||||||
|
7A131FD42D37B76A00DC7755 /* HistoryViewModel.swift */,
|
||||||
|
7A131FD62D37B77E00DC7755 /* HistoryCoordinator.swift */,
|
||||||
|
);
|
||||||
|
path = HistoryScreen;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
7A1441632C297E9800E79018 /* Screens */ = {
|
7A1441632C297E9800E79018 /* Screens */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
7A131FD12D37B74100DC7755 /* HistoryScreen */,
|
||||||
7AB9FE202D08C28E005DE374 /* EventsScreen */,
|
7AB9FE202D08C28E005DE374 /* EventsScreen */,
|
||||||
7ABD1B452D044A0900B43213 /* GalleryScreen */,
|
7ABD1B452D044A0900B43213 /* GalleryScreen */,
|
||||||
7A1E78F42CE9001A0004B740 /* ReportScreen */,
|
7A1E78F42CE9001A0004B740 /* ReportScreen */,
|
||||||
@ -729,7 +742,6 @@
|
|||||||
7A8A2208248D10EC0073DFD9 /* ResizeImage.swift */,
|
7A8A2208248D10EC0073DFD9 /* ResizeImage.swift */,
|
||||||
7A659B5A24A3768A0043A0F2 /* Substrings.swift */,
|
7A659B5A24A3768A0043A0F2 /* Substrings.swift */,
|
||||||
7AE26A3224EEF9EC00625033 /* UIViewControllerExt.swift */,
|
7AE26A3224EEF9EC00625033 /* UIViewControllerExt.swift */,
|
||||||
7A8A220A248D67B60073DFD9 /* VehicleReportImage.swift */,
|
|
||||||
7A761C0A267E8FF90005F28F /* Error.swift */,
|
7A761C0A267E8FF90005F28F /* Error.swift */,
|
||||||
7AC76D7A270083AE0084DB27 /* TextView.swift */,
|
7AC76D7A270083AE0084DB27 /* TextView.swift */,
|
||||||
);
|
);
|
||||||
@ -761,7 +773,6 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
7A530B7D24017FEE00CBFE6E /* VehicleCell.swift */,
|
7A530B7D24017FEE00CBFE6E /* VehicleCell.swift */,
|
||||||
7A7547DF24032CB6004E8406 /* VehiclePhotoCell.swift */,
|
|
||||||
7A1090E724A394F100B4F0B2 /* AudioRecordCell.swift */,
|
7A1090E724A394F100B4F0B2 /* AudioRecordCell.swift */,
|
||||||
7A813DC22508EE4F00CC93B9 /* EventCell.swift */,
|
7A813DC22508EE4F00CC93B9 /* EventCell.swift */,
|
||||||
7AEFC3BD2529D3CC00BADFB2 /* ConfigurableCell.swift */,
|
7AEFC3BD2529D3CC00BADFB2 /* ConfigurableCell.swift */,
|
||||||
@ -1070,6 +1081,7 @@
|
|||||||
7A2E11282CCE395300E5CA17 /* OptionalDatePicker.swift */,
|
7A2E11282CCE395300E5CA17 /* OptionalDatePicker.swift */,
|
||||||
7A4927D42CCE438600851C01 /* OptionalBinding.swift */,
|
7A4927D42CCE438600851C01 /* OptionalBinding.swift */,
|
||||||
7AABBE3A2CF9F85600346588 /* Binding+Map.swift */,
|
7AABBE3A2CF9F85600346588 /* Binding+Map.swift */,
|
||||||
|
7A912F362D381B7400002938 /* LicensePlateView.swift */,
|
||||||
);
|
);
|
||||||
path = SwiftUI;
|
path = SwiftUI;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -1115,7 +1127,6 @@
|
|||||||
);
|
);
|
||||||
name = AutoCat;
|
name = AutoCat;
|
||||||
packageProductDependencies = (
|
packageProductDependencies = (
|
||||||
7AF58D332402A91C00CE01A0 /* Kingfisher */,
|
|
||||||
7A813DC02508C4D900CC93B9 /* ExceptionCatcher */,
|
7A813DC02508C4D900CC93B9 /* ExceptionCatcher */,
|
||||||
7AABDE1C2532F3EB0041AFC6 /* PKHUD */,
|
7AABDE1C2532F3EB0041AFC6 /* PKHUD */,
|
||||||
7AC355492969652F00889457 /* SwiftEntryKit */,
|
7AC355492969652F00889457 /* SwiftEntryKit */,
|
||||||
@ -1236,7 +1247,6 @@
|
|||||||
);
|
);
|
||||||
mainGroup = 7A1146F423FDE7E500B424AF;
|
mainGroup = 7A1146F423FDE7E500B424AF;
|
||||||
packageReferences = (
|
packageReferences = (
|
||||||
7AF58D322402A91C00CE01A0 /* XCRemoteSwiftPackageReference "Kingfisher" */,
|
|
||||||
7A05160F241412CA00FC55AC /* XCRemoteSwiftPackageReference "SwiftDate" */,
|
7A05160F241412CA00FC55AC /* XCRemoteSwiftPackageReference "SwiftDate" */,
|
||||||
7A813DBF2508C4D900CC93B9 /* XCRemoteSwiftPackageReference "ExceptionCatcher" */,
|
7A813DBF2508C4D900CC93B9 /* XCRemoteSwiftPackageReference "ExceptionCatcher" */,
|
||||||
7AABDE1B2532F3EB0041AFC6 /* XCRemoteSwiftPackageReference "PKHUD" */,
|
7AABDE1B2532F3EB0041AFC6 /* XCRemoteSwiftPackageReference "PKHUD" */,
|
||||||
@ -1354,6 +1364,7 @@
|
|||||||
7A7158072C44085600852088 /* OsagoScreen.swift in Sources */,
|
7A7158072C44085600852088 /* OsagoScreen.swift in Sources */,
|
||||||
7ABD1B492D044A4700B43213 /* GalleryViewModel.swift in Sources */,
|
7ABD1B492D044A4700B43213 /* GalleryViewModel.swift in Sources */,
|
||||||
7AAAFAD32C4D0FD00050410D /* ACImageSliderView.swift in Sources */,
|
7AAAFAD32C4D0FD00050410D /* ACImageSliderView.swift in Sources */,
|
||||||
|
7A912F372D381B7400002938 /* LicensePlateView.swift in Sources */,
|
||||||
7A3F07AB24360DC800E59687 /* Dated.swift in Sources */,
|
7A3F07AB24360DC800E59687 /* Dated.swift in Sources */,
|
||||||
7AC76D7B270083AE0084DB27 /* TextView.swift in Sources */,
|
7AC76D7B270083AE0084DB27 /* TextView.swift in Sources */,
|
||||||
7A1090E824A394F100B4F0B2 /* AudioRecordCell.swift in Sources */,
|
7A1090E824A394F100B4F0B2 /* AudioRecordCell.swift in Sources */,
|
||||||
@ -1387,11 +1398,11 @@
|
|||||||
7AB67E8E2435D1A000258F61 /* CustomButton.swift in Sources */,
|
7AB67E8E2435D1A000258F61 /* CustomButton.swift in Sources */,
|
||||||
7AC35554296973E100889457 /* ACButton.swift in Sources */,
|
7AC35554296973E100889457 /* ACButton.swift in Sources */,
|
||||||
7AAAFADC2C4D1E130050410D /* ACImageSliderView+Modifier.swift in Sources */,
|
7AAAFADC2C4D1E130050410D /* ACImageSliderView+Modifier.swift in Sources */,
|
||||||
7A8A220B248D67B60073DFD9 /* VehicleReportImage.swift in Sources */,
|
|
||||||
7AFBE8C42C302561003C491D /* ACHudContainer.swift in Sources */,
|
7AFBE8C42C302561003C491D /* ACHudContainer.swift in Sources */,
|
||||||
7AC3555B296995B200889457 /* UIEdgeInsets.swift in Sources */,
|
7AC3555B296995B200889457 /* UIEdgeInsets.swift in Sources */,
|
||||||
7A06E0AC2C7065AC005731AC /* SettingsScreen.swift in Sources */,
|
7A06E0AC2C7065AC005731AC /* SettingsScreen.swift in Sources */,
|
||||||
7A4322952CB2CD0F00085CF6 /* FiltersCoordinator.swift in Sources */,
|
7A4322952CB2CD0F00085CF6 /* FiltersCoordinator.swift in Sources */,
|
||||||
|
7A131FD72D37B77E00DC7755 /* HistoryCoordinator.swift in Sources */,
|
||||||
7A7158002C43EA6900852088 /* OwnersScreen.swift in Sources */,
|
7A7158002C43EA6900852088 /* OwnersScreen.swift in Sources */,
|
||||||
7A1441702C2998B200E79018 /* Formatters.swift in Sources */,
|
7A1441702C2998B200E79018 /* Formatters.swift in Sources */,
|
||||||
7A4322912CB2CC8A00085CF6 /* FiltersScreen.swift in Sources */,
|
7A4322912CB2CC8A00085CF6 /* FiltersScreen.swift in Sources */,
|
||||||
@ -1401,6 +1412,7 @@
|
|||||||
7A06E0B02C7065D8005731AC /* SettingsCoordinator.swift in Sources */,
|
7A06E0B02C7065D8005731AC /* SettingsCoordinator.swift in Sources */,
|
||||||
7A91894F29A2BD8700519C74 /* GestureRecognizers.swift in Sources */,
|
7A91894F29A2BD8700519C74 /* GestureRecognizers.swift in Sources */,
|
||||||
7AFBE8CC2C3085C6003C491D /* ACProgressView.swift in Sources */,
|
7AFBE8CC2C3085C6003C491D /* ACProgressView.swift in Sources */,
|
||||||
|
7A131FD32D37B75500DC7755 /* HistoryScreen.swift in Sources */,
|
||||||
7AB9FE222D08C2A5005DE374 /* EventsScreen.swift in Sources */,
|
7AB9FE222D08C2A5005DE374 /* EventsScreen.swift in Sources */,
|
||||||
7ADF6C93250B954900F237B2 /* Navigation.swift in Sources */,
|
7ADF6C93250B954900F237B2 /* Navigation.swift in Sources */,
|
||||||
7A64AE752469DFB600ABE48E /* MediaBrowserViewController.swift in Sources */,
|
7A64AE752469DFB600ABE48E /* MediaBrowserViewController.swift in Sources */,
|
||||||
@ -1409,8 +1421,8 @@
|
|||||||
7ADF6C97250F41B000F237B2 /* PNKeyboard.swift in Sources */,
|
7ADF6C97250F41B000F237B2 /* PNKeyboard.swift in Sources */,
|
||||||
7A1022702C551EFD00B84627 /* LocationEditCoordinator.swift in Sources */,
|
7A1022702C551EFD00B84627 /* LocationEditCoordinator.swift in Sources */,
|
||||||
7A7158042C43EAA200852088 /* OwnersCoordinator.swift in Sources */,
|
7A7158042C43EAA200852088 /* OwnersCoordinator.swift in Sources */,
|
||||||
7A7547E024032CB6004E8406 /* VehiclePhotoCell.swift in Sources */,
|
|
||||||
7A17CE4C2A2E850200626A6E /* UISegmentedControl.swift in Sources */,
|
7A17CE4C2A2E850200626A6E /* UISegmentedControl.swift in Sources */,
|
||||||
|
7A131FD52D37B76A00DC7755 /* HistoryViewModel.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -2013,14 +2025,6 @@
|
|||||||
minimumVersion = 0.0.11;
|
minimumVersion = 0.0.11;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
7AF58D322402A91C00CE01A0 /* XCRemoteSwiftPackageReference "Kingfisher" */ = {
|
|
||||||
isa = XCRemoteSwiftPackageReference;
|
|
||||||
repositoryURL = "https://github.com/onevcat/Kingfisher";
|
|
||||||
requirement = {
|
|
||||||
branch = "8.0.0-alpha.1";
|
|
||||||
kind = branch;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
/* End XCRemoteSwiftPackageReference section */
|
/* End XCRemoteSwiftPackageReference section */
|
||||||
|
|
||||||
/* Begin XCSwiftPackageProductDependency section */
|
/* Begin XCSwiftPackageProductDependency section */
|
||||||
@ -2074,11 +2078,6 @@
|
|||||||
package = 7A1CF7FD29A41C2F007962DA /* XCRemoteSwiftPackageReference "realm-swift" */;
|
package = 7A1CF7FD29A41C2F007962DA /* XCRemoteSwiftPackageReference "realm-swift" */;
|
||||||
productName = RealmSwift;
|
productName = RealmSwift;
|
||||||
};
|
};
|
||||||
7AF58D332402A91C00CE01A0 /* Kingfisher */ = {
|
|
||||||
isa = XCSwiftPackageProductDependency;
|
|
||||||
package = 7AF58D322402A91C00CE01A0 /* XCRemoteSwiftPackageReference "Kingfisher" */;
|
|
||||||
productName = Kingfisher;
|
|
||||||
};
|
|
||||||
7AF8606B2CB9B20C00954D2F /* Mockable */ = {
|
7AF8606B2CB9B20C00954D2F /* Mockable */ = {
|
||||||
isa = XCSwiftPackageProductDependency;
|
isa = XCSwiftPackageProductDependency;
|
||||||
package = 7ACBB91C2CB9B155005A5168 /* XCRemoteSwiftPackageReference "Mockable" */;
|
package = 7ACBB91C2CB9B155005A5168 /* XCRemoteSwiftPackageReference "Mockable" */;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"originHash" : "d6bab97967371dd248cd5b3fdb49293879398c897bea34714c48fd3d4cb90fb1",
|
"originHash" : "6fccb9fdc0d29647d4f0b927aef60f375302d72b5b724992eab52ac0d8ec71c3",
|
||||||
"pins" : [
|
"pins" : [
|
||||||
{
|
{
|
||||||
"identity" : "exceptioncatcher",
|
"identity" : "exceptioncatcher",
|
||||||
@ -10,15 +10,6 @@
|
|||||||
"version" : "1.1.0"
|
"version" : "1.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"identity" : "kingfisher",
|
|
||||||
"kind" : "remoteSourceControl",
|
|
||||||
"location" : "https://github.com/onevcat/Kingfisher",
|
|
||||||
"state" : {
|
|
||||||
"branch" : "8.0.0-alpha.1",
|
|
||||||
"revision" : "bb4e6ecf6c7a221dfc51c8e69f04fd3757fc519a"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"identity" : "mockable",
|
"identity" : "mockable",
|
||||||
"kind" : "remoteSourceControl",
|
"kind" : "remoteSourceControl",
|
||||||
|
|||||||
@ -2,8 +2,6 @@ import UIKit
|
|||||||
import RealmSwift
|
import RealmSwift
|
||||||
import PKHUD
|
import PKHUD
|
||||||
import AutoCatCore
|
import AutoCatCore
|
||||||
import SwiftLocation
|
|
||||||
import CoreLocation
|
|
||||||
|
|
||||||
enum QuickAction {
|
enum QuickAction {
|
||||||
case none
|
case none
|
||||||
@ -72,11 +70,8 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||||||
HUD.dimsBackground = true
|
HUD.dimsBackground = true
|
||||||
HUD.allowsInteraction = false
|
HUD.allowsInteraction = false
|
||||||
|
|
||||||
registerServices()
|
|
||||||
setupAppearance()
|
setupAppearance()
|
||||||
|
|
||||||
//Logging.URLRequests = { _ in false };
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,29 +88,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
|||||||
UINavigationBar.appearance().scrollEdgeAppearance = navigationBarAppearance
|
UINavigationBar.appearance().scrollEdgeAppearance = navigationBarAppearance
|
||||||
}
|
}
|
||||||
|
|
||||||
func registerServices() {
|
|
||||||
|
|
||||||
let container = ServiceContainer.shared
|
|
||||||
|
|
||||||
let settingsService = SettingsService(defaults: .standard)
|
|
||||||
|
|
||||||
container.register(SettingsServiceProtocol.self, instance: settingsService)
|
|
||||||
container.register(ApiServiceProtocol.self, instance: ApiService())
|
|
||||||
|
|
||||||
let locationService = LocationService(
|
|
||||||
geocoder: CLGeocoder(),
|
|
||||||
locationManager: Location(),
|
|
||||||
settingsService: settingsService
|
|
||||||
)
|
|
||||||
|
|
||||||
container.register(LocationServiceProtocol.self, instance: locationService)
|
|
||||||
|
|
||||||
Task {
|
|
||||||
container.register(StorageServiceProtocol.self,
|
|
||||||
instance: try await StorageService(settingsService: settingsService))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: UISceneSession Lifecycle
|
// MARK: UISceneSession Lifecycle
|
||||||
|
|
||||||
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
|
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
|
||||||
|
|||||||
@ -1,38 +0,0 @@
|
|||||||
import UIKit
|
|
||||||
import Kingfisher
|
|
||||||
import AutoCatCore
|
|
||||||
|
|
||||||
@MainActor
|
|
||||||
class VehiclePhotoCell: UICollectionViewCell {
|
|
||||||
@IBOutlet weak var photo: UIImageView!
|
|
||||||
@IBOutlet weak var model: UILabel!
|
|
||||||
@IBOutlet weak var date: UILabel!
|
|
||||||
|
|
||||||
let formatter = DateFormatter()
|
|
||||||
|
|
||||||
override func awakeFromNib() {
|
|
||||||
super.awakeFromNib()
|
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
self.layer.cornerRadius = 8
|
|
||||||
self.formatter.timeStyle = .none
|
|
||||||
self.formatter.dateStyle = .medium
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override func prepareForReuse() {
|
|
||||||
super.prepareForReuse()
|
|
||||||
self.photo.kf.cancelDownloadTask()
|
|
||||||
}
|
|
||||||
|
|
||||||
func configure(with photoModel: VehiclePhoto) {
|
|
||||||
if let url = URL(string: photoModel.url) {
|
|
||||||
self.photo.kf.setImage(with: url)
|
|
||||||
}
|
|
||||||
|
|
||||||
self.model.text = "\(photoModel.brand ?? "") \(photoModel.model ?? "")"
|
|
||||||
|
|
||||||
let date = Date(timeIntervalSince1970: photoModel.date/1000)
|
|
||||||
self.date.text = formatter.string(from: date)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -23,9 +23,19 @@ class MainTabController: UITabBarController, UITabBarControllerDelegate {
|
|||||||
traitOverrides.horizontalSizeClass = .compact
|
traitOverrides.horizontalSizeClass = .compact
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setupHistoryTab()
|
||||||
Task { await addSettings() }
|
Task { await addSettings() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setupHistoryTab() {
|
||||||
|
|
||||||
|
let coordinator = HistoryCoordinator()
|
||||||
|
let controller = coordinator.start()
|
||||||
|
controller.tabBarItem = UITabBarItem(title: NSLocalizedString("History", comment: ""),
|
||||||
|
image: UIImage(systemName: "clock.arrow.circlepath"), tag: 0)
|
||||||
|
viewControllers?[0] = controller
|
||||||
|
}
|
||||||
|
|
||||||
func addSettings() async {
|
func addSettings() async {
|
||||||
|
|
||||||
let coordinator = SettingsCoordinator(tabController: self)
|
let coordinator = SettingsCoordinator(tabController: self)
|
||||||
|
|||||||
@ -1,280 +0,0 @@
|
|||||||
import UIKit
|
|
||||||
import Kingfisher
|
|
||||||
import AutoCatCore
|
|
||||||
|
|
||||||
extension VehicleDto {
|
|
||||||
|
|
||||||
@MainActor
|
|
||||||
func drawLine(y: CGFloat, width: CGFloat, margin: CGFloat = 15,context: CGContext) {
|
|
||||||
let lineWidth = 1/UIScreen.main.scale
|
|
||||||
context.move(to: CGPoint(x: margin, y: y + lineWidth/2))
|
|
||||||
context.addLine(to: CGPoint(x: width, y: y + lineWidth/2))
|
|
||||||
context.closePath()
|
|
||||||
context.setLineWidth(lineWidth)
|
|
||||||
context.setStrokeColor(UIColor.opaqueSeparator.cgColor)
|
|
||||||
context.strokePath()
|
|
||||||
}
|
|
||||||
|
|
||||||
@MainActor
|
|
||||||
func drawCell(y: CGFloat, width: CGFloat, height: CGFloat, title: String, value: String, lineMargin: CGFloat = 15, context: CGContext) {
|
|
||||||
let fontSize: CGFloat = 17
|
|
||||||
let font = UIFont.systemFont(ofSize: fontSize)
|
|
||||||
let offest = (height - fontSize)/2
|
|
||||||
let pStyle = NSMutableParagraphStyle()
|
|
||||||
pStyle.alignment = .right
|
|
||||||
let attributes: [NSAttributedString.Key: Any] = [.font: font, .foregroundColor: UIColor.label]
|
|
||||||
let valueAttributs: [NSAttributedString.Key: Any] = [.font: font, .foregroundColor: UIColor.secondaryLabel, .paragraphStyle: pStyle]
|
|
||||||
let rect = CGRect(x: 15, y: y + offest, width: width - 30, height: height)
|
|
||||||
UIColor.secondarySystemGroupedBackground.setFill()
|
|
||||||
UIRectFill(CGRect(x: 0, y: y, width: width, height: height))
|
|
||||||
title.draw(with: rect, options: .usesLineFragmentOrigin, attributes: attributes, context: nil)
|
|
||||||
value.draw(with: rect, options: .usesLineFragmentOrigin, attributes: valueAttributs, context: nil)
|
|
||||||
self.drawLine(y: y + height - 1/UIScreen.main.scale, width: width, margin: lineMargin, context: context)
|
|
||||||
}
|
|
||||||
|
|
||||||
@MainActor
|
|
||||||
func drawBigTextCell(y: CGFloat, width: CGFloat, title: String, value: String, lineMargin: CGFloat = 15, context: CGContext) -> CGFloat {
|
|
||||||
let pStyle = NSMutableParagraphStyle()
|
|
||||||
pStyle.alignment = .right
|
|
||||||
let attributes: [NSAttributedString.Key: Any] = [.font: UIFont.systemFont(ofSize: 17), .foregroundColor: UIColor.label]
|
|
||||||
let valueAttributs: [NSAttributedString.Key: Any] = [.font: UIFont.systemFont(ofSize: 15), .foregroundColor: UIColor.secondaryLabel, .paragraphStyle: pStyle]
|
|
||||||
UIColor.secondarySystemGroupedBackground.setFill()
|
|
||||||
|
|
||||||
let text = NSMutableAttributedString(string: title + " - " + value)
|
|
||||||
text.setAttributes(attributes, range: NSRange(location: 0, length: title.count))
|
|
||||||
text.setAttributes(valueAttributs, range: NSRange(location: title.count, length: value.count + 3))
|
|
||||||
let textRect = text.boundingRect(with: CGSize(width: width - 30, height: 1000), options: [.usesLineFragmentOrigin, .usesFontLeading], context: nil)
|
|
||||||
let height = textRect.size.height > 28 ? textRect.size.height + 16 : 44
|
|
||||||
let offset = (height - textRect.size.height)/2
|
|
||||||
let rect = CGRect(x: 15, y: y + offset, width: width - 30, height: height)
|
|
||||||
UIRectFill(CGRect(x: 0, y: y, width: width, height: height))
|
|
||||||
text.draw(with: rect, options: .usesLineFragmentOrigin, context: nil)
|
|
||||||
self.drawLine(y: y + height - 1/UIScreen.main.scale, width: width, margin: lineMargin, context: context)
|
|
||||||
|
|
||||||
return height
|
|
||||||
}
|
|
||||||
|
|
||||||
@MainActor
|
|
||||||
func reportImage(width: CGFloat) -> UIImage {
|
|
||||||
var realHeight: CGFloat = 0
|
|
||||||
let rect = CGRect(origin: .zero, size: CGSize(width: width, height: CGFloat(10000)))
|
|
||||||
let renderer = UIGraphicsImageRenderer(bounds: rect)
|
|
||||||
let image = renderer.image { rendererContext in
|
|
||||||
let cellHeight: CGFloat = 44
|
|
||||||
let ctx = rendererContext.cgContext
|
|
||||||
let centeredStyle = NSMutableParagraphStyle()
|
|
||||||
centeredStyle.alignment = .center
|
|
||||||
let titleAttributes: [NSAttributedString.Key: Any] = [.font: UIFont.systemFont(ofSize: 20), .paragraphStyle: centeredStyle, .foregroundColor: UIColor.label]
|
|
||||||
let headerAttributes: [NSAttributedString.Key: Any] = [.font: UIFont.systemFont(ofSize: 13), .foregroundColor: UIColor.secondaryLabel]
|
|
||||||
|
|
||||||
let w: CGFloat = width
|
|
||||||
var y: CGFloat = 0
|
|
||||||
|
|
||||||
UIColor.systemGroupedBackground.setFill()
|
|
||||||
UIRectFill(rect)
|
|
||||||
|
|
||||||
y += 12
|
|
||||||
"\(self.brand?.name?.original ?? "Unknown model") (\(self.getNumber()))".draw(with: CGRect(x: 0, y: y, width: w, height: 30), options: .usesLineFragmentOrigin, attributes: titleAttributes, context: nil)
|
|
||||||
y += 50
|
|
||||||
"GENERAL".draw(with: CGRect(x: 15, y: y, width: w - 15, height: 24), options: .usesLineFragmentOrigin, attributes: headerAttributes, context: nil)
|
|
||||||
y += 24
|
|
||||||
self.drawLine(y: y, width: w, margin: 0, context: ctx)
|
|
||||||
y += 1/UIScreen.main.scale
|
|
||||||
self.drawCell(y: y, width: w, height: cellHeight, title: "Year", value: String(self.year), context: ctx)
|
|
||||||
y += cellHeight
|
|
||||||
self.drawCell(y: y, width: w, height: cellHeight, title: "Color", value: self.color ?? "<unknown>", context: ctx)
|
|
||||||
y += cellHeight
|
|
||||||
self.drawCell(y: y, width: w, height: cellHeight, title: "Category", value: self.category ?? "<unknown>", context: ctx)
|
|
||||||
y += cellHeight
|
|
||||||
var position = "Unknown"
|
|
||||||
if let rightWheel = self.isRightWheel {
|
|
||||||
position = rightWheel ? "Right" : "Left"
|
|
||||||
}
|
|
||||||
self.drawCell(y: y, width: w, height: cellHeight, title: "Steering wheel position", value: position, context: ctx)
|
|
||||||
y += cellHeight
|
|
||||||
var japanese = "<Unknown>"
|
|
||||||
if let isJapanese = self.isJapanese {
|
|
||||||
japanese = isJapanese ? "Yes" : "No"
|
|
||||||
}
|
|
||||||
self.drawCell(y: y, width: w, height: cellHeight, title: "Japanese", value: japanese, lineMargin: 0, context: ctx)
|
|
||||||
y += cellHeight + 32
|
|
||||||
|
|
||||||
"IDENTIFIERS".draw(with: CGRect(x: 15, y: y, width: w - 15, height: 24), options: .usesLineFragmentOrigin, attributes: headerAttributes, context: nil)
|
|
||||||
y += 24
|
|
||||||
self.drawLine(y: y, width: w, margin: 0, context: ctx)
|
|
||||||
y += 1/UIScreen.main.scale
|
|
||||||
self.drawCell(y: y, width: w, height: cellHeight, title: "Plate number", value: self.getNumber(), context: ctx)
|
|
||||||
y += cellHeight
|
|
||||||
self.drawCell(y: y, width: w, height: cellHeight, title: "VIN", value: self.vin1 ?? "<unknown>", context: ctx)
|
|
||||||
y += cellHeight
|
|
||||||
self.drawCell(y: y, width: w, height: cellHeight, title: "STS", value: self.sts ?? "<unknown>", context: ctx)
|
|
||||||
y += cellHeight
|
|
||||||
self.drawCell(y: y, width: w, height: cellHeight, title: "PTS", value: self.pts ?? "<unknown>", context: ctx)
|
|
||||||
y += cellHeight + 32
|
|
||||||
|
|
||||||
"ENGINE".draw(with: CGRect(x: 15, y: y, width: w - 15, height: 24), options: .usesLineFragmentOrigin, attributes: headerAttributes, context: nil)
|
|
||||||
y += 24
|
|
||||||
self.drawLine(y: y, width: w, margin: 0, context: ctx)
|
|
||||||
y += 1/UIScreen.main.scale
|
|
||||||
self.drawCell(y: y, width: w, height: cellHeight, title: "Number", value: self.engine?.number ?? "<unknown>", context: ctx)
|
|
||||||
y += cellHeight
|
|
||||||
self.drawCell(y: y, width: w, height: cellHeight, title: "Fuel type", value: self.engine?.fuelType ?? "<unknown>", context: ctx)
|
|
||||||
y += cellHeight
|
|
||||||
self.drawCell(y: y, width: w, height: cellHeight, title: "Volume (cm³)", value: String(self.engine?.volume ?? 0), context: ctx)
|
|
||||||
y += cellHeight
|
|
||||||
self.drawCell(y: y, width: w, height: cellHeight, title: "Power (HP)", value: String(self.engine?.powerHp ?? 0), context: ctx)
|
|
||||||
y += cellHeight
|
|
||||||
self.drawCell(y: y, width: w, height: cellHeight, title: "Power (kw)", value: String(self.engine?.powerKw ?? 0), context: ctx)
|
|
||||||
y += cellHeight + 32
|
|
||||||
|
|
||||||
"OWNERSHIP PERIODS (\(self.ownershipPeriods.count))".draw(with: CGRect(x: 15, y: y, width: w - 15, height: 24), options: .usesLineFragmentOrigin, attributes: headerAttributes, context: nil)
|
|
||||||
y += 24
|
|
||||||
self.drawLine(y: y, width: w, margin: 0, context: ctx)
|
|
||||||
y += 1/UIScreen.main.scale
|
|
||||||
|
|
||||||
let formatter = DateFormatter()
|
|
||||||
formatter.dateStyle = .long
|
|
||||||
formatter.timeStyle = .none
|
|
||||||
for period in self.ownershipPeriods {
|
|
||||||
self.drawCell(y: y, width: w, height: cellHeight, title: "Owner type", value: period.ownerType, context: ctx)
|
|
||||||
y += cellHeight
|
|
||||||
|
|
||||||
let fromDate = Date(timeIntervalSince1970: TimeInterval(period.from/1000))
|
|
||||||
self.drawCell(y: y, width: w, height: cellHeight, title: "From", value: formatter.string(from: fromDate), context: ctx)
|
|
||||||
y += cellHeight
|
|
||||||
|
|
||||||
let toDate = Date(timeIntervalSince1970: TimeInterval(period.to/1000))
|
|
||||||
let toString = period.to == 0 ? "now" : formatter.string(from: toDate)
|
|
||||||
self.drawCell(y: y, width: w, height: cellHeight, title: "To", value: toString, context: ctx)
|
|
||||||
y += cellHeight
|
|
||||||
|
|
||||||
let height = self.drawBigTextCell(y: y, width: w, title: "Last operation", value: period.lastOperation, lineMargin: 0, context: ctx)
|
|
||||||
y += height + 8
|
|
||||||
}
|
|
||||||
|
|
||||||
y += 24
|
|
||||||
|
|
||||||
if !self.events.isEmpty {
|
|
||||||
"LOCATIONS".draw(with: CGRect(x: 15, y: y, width: w - 15, height: 24), options: .usesLineFragmentOrigin, attributes: headerAttributes, context: nil)
|
|
||||||
y += 24
|
|
||||||
self.drawLine(y: y, width: w, margin: 0, context: ctx)
|
|
||||||
y += 1/UIScreen.main.scale
|
|
||||||
|
|
||||||
for event in self.events {
|
|
||||||
let date = Date(timeIntervalSince1970: event.date)
|
|
||||||
self.drawCell(y: y, width: w, height: cellHeight, title: "Date", value: formatter.string(from: date), context: ctx)
|
|
||||||
y += cellHeight
|
|
||||||
|
|
||||||
if let address = event.address {
|
|
||||||
self.drawCell(y: y, width: w, height: cellHeight, title: "Address", value: address, context: ctx)
|
|
||||||
y += cellHeight
|
|
||||||
}
|
|
||||||
|
|
||||||
let location = String(format: "%.05f, %.05f", event.latitude, event.longitude)
|
|
||||||
self.drawCell(y: y, width: w, height: cellHeight, title: "Location", value: location, context: ctx)
|
|
||||||
y += cellHeight + 8
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
y += 24
|
|
||||||
|
|
||||||
"PHOTOS (\(self.photos.count))".draw(with: CGRect(x: 15, y: y, width: w - 15, height: 24), options: .usesLineFragmentOrigin, attributes: headerAttributes, context: nil)
|
|
||||||
y += 24
|
|
||||||
self.drawLine(y: y, width: w, margin: 0, context: ctx)
|
|
||||||
y += 1/UIScreen.main.scale
|
|
||||||
|
|
||||||
// TODO: Fix drawing photos in report image
|
|
||||||
// for photo in self.photos {
|
|
||||||
// let date = Date(timeIntervalSince1970: TimeInterval(photo.date/1000))
|
|
||||||
// var name = "<Unknown model>"
|
|
||||||
// if let brand = photo.brand, let model = photo.model {
|
|
||||||
// name = "\(brand) \(model)"
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// if let url = URL(string: photo.url) {
|
|
||||||
// if let image = ImageCache.default.retrieveImageInDiskCache(forKey: url.cacheKey) {
|
|
||||||
// let imgHeight = image.size.height*w/image.size.width
|
|
||||||
// let rect = CGRect(x: 0, y: y, width: w, height: imgHeight)
|
|
||||||
// image.draw(in: rect)
|
|
||||||
// y += imgHeight
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// self.drawCell(y: y, width: w, height: cellHeight, title: name, value: formatter.string(from: date), lineMargin: 0, context: ctx)
|
|
||||||
// y += cellHeight
|
|
||||||
//
|
|
||||||
// y += 16
|
|
||||||
// }
|
|
||||||
|
|
||||||
realHeight = y
|
|
||||||
}
|
|
||||||
|
|
||||||
return image.cutHeight(to: realHeight)
|
|
||||||
}
|
|
||||||
|
|
||||||
func reportText() -> String {
|
|
||||||
let formatter = DateFormatter()
|
|
||||||
formatter.dateStyle = .long
|
|
||||||
formatter.timeStyle = .none
|
|
||||||
|
|
||||||
var text = (self.brand?.name?.original ?? "<unknown model>") + "\n"
|
|
||||||
text += "Year: \(self.year)\n"
|
|
||||||
if let color = self.color { text += "Color: \(color)\n" }
|
|
||||||
if let category = self.category { text += "Category: \(category)\n" }
|
|
||||||
var position = "Unknown"
|
|
||||||
if let rightWheel = self.isRightWheel {
|
|
||||||
position = rightWheel ? "Right" : "Left"
|
|
||||||
}
|
|
||||||
var japanese = "<Unknown>"
|
|
||||||
if let isJapanese = self.isJapanese {
|
|
||||||
japanese = isJapanese ? "Yes" : "No"
|
|
||||||
}
|
|
||||||
text += "Steering wheel position: \(position)\n"
|
|
||||||
text += "Japanese: \(japanese)\n"
|
|
||||||
text += "Plate number: \(self.getNumber())\n"
|
|
||||||
if let vin = self.vin1 { text += "VIN: \(vin)\n" }
|
|
||||||
if let sts = self.sts { text += "STS: \(sts)\n" }
|
|
||||||
if let pts = self.pts { text += "PTS: \(pts)\n" }
|
|
||||||
if let engineNumber = self.engine?.number { text += "Engine number: \(engineNumber)\n" }
|
|
||||||
if let fuel = self.engine?.fuelType { text += "Fuel type: \(fuel)\n" }
|
|
||||||
if let volume = self.engine?.volume { text += "Volume (cm³): \(volume)\n" }
|
|
||||||
if let powerHp = self.engine?.powerHp { text += "Power (HP): \(powerHp)\n" }
|
|
||||||
if let powerHp = self.engine?.powerHp { text += "Power (HP): \(powerHp)\n" }
|
|
||||||
|
|
||||||
if self.ownershipPeriods.count > 0 {
|
|
||||||
text += "\n"
|
|
||||||
text += "Ownership periods: \(self.ownershipPeriods.count)\n"
|
|
||||||
text += "\n"
|
|
||||||
for period in self.ownershipPeriods {
|
|
||||||
text += "Owner type: \(period.ownerType)\n"
|
|
||||||
let fromDate = Date(timeIntervalSince1970: TimeInterval(period.from/1000))
|
|
||||||
text += "From: \(formatter.string(from: fromDate))\n"
|
|
||||||
let toDate = Date(timeIntervalSince1970: TimeInterval(period.to/1000))
|
|
||||||
let toString = period.to == 0 ? "now" : formatter.string(from: toDate)
|
|
||||||
text += "To: \(toString)\n"
|
|
||||||
text += "Last operation: \(period.lastOperation)\n"
|
|
||||||
text += "\n"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !self.events.isEmpty {
|
|
||||||
text += "\n"
|
|
||||||
text += "Locations\n"
|
|
||||||
text += "\n"
|
|
||||||
for event in self.events {
|
|
||||||
let date = Date(timeIntervalSince1970: event.date)
|
|
||||||
text += "Date: \(formatter.string(from: date))\n"
|
|
||||||
|
|
||||||
if let address = event.address {
|
|
||||||
text += "Address: \(address)\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
let location = String(format: "%.05f, %.05f", event.latitude, event.longitude)
|
|
||||||
text += "Location: \(location)\n"
|
|
||||||
text += "\n"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return text
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -3,18 +3,17 @@ import os.log
|
|||||||
import AVFoundation
|
import AVFoundation
|
||||||
import PKHUD
|
import PKHUD
|
||||||
import AutoCatCore
|
import AutoCatCore
|
||||||
|
import SwiftLocation
|
||||||
|
import CoreLocation
|
||||||
|
|
||||||
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||||
|
|
||||||
@Service var settingsService: SettingsServiceProtocol
|
|
||||||
|
|
||||||
var window: UIWindow?
|
var window: UIWindow?
|
||||||
|
|
||||||
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
||||||
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
|
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
|
||||||
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
|
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
|
||||||
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
|
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
|
||||||
guard let windowScene = (scene as? UIWindowScene) else { return }
|
|
||||||
guard let ad = UIApplication.shared.delegate as? AppDelegate else { return }
|
guard let ad = UIApplication.shared.delegate as? AppDelegate else { return }
|
||||||
|
|
||||||
if let activity = connectionOptions.userActivities.first {
|
if let activity = connectionOptions.userActivities.first {
|
||||||
@ -31,9 +30,43 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Task {
|
||||||
|
try? await registerServices()
|
||||||
|
setupRootController(scene: scene)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func registerServices() async throws {
|
||||||
|
|
||||||
|
let container = ServiceContainer.shared
|
||||||
|
|
||||||
|
let settingsService = SettingsService(defaults: .standard)
|
||||||
|
|
||||||
|
container.register(SettingsServiceProtocol.self, instance: settingsService)
|
||||||
|
container.register(ApiServiceProtocol.self, instance: ApiService())
|
||||||
|
|
||||||
|
let locationService = LocationService(
|
||||||
|
geocoder: CLGeocoder(),
|
||||||
|
locationManager: Location(),
|
||||||
|
settingsService: settingsService
|
||||||
|
)
|
||||||
|
|
||||||
|
container.register(LocationServiceProtocol.self, instance: locationService)
|
||||||
|
|
||||||
|
container.register(StorageServiceProtocol.self,
|
||||||
|
instance: try await StorageService(settingsService: settingsService))
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupRootController(scene: UIScene) {
|
||||||
|
guard let windowScene = (scene as? UIWindowScene) else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
self.window = UIWindow(windowScene: windowScene)
|
self.window = UIWindow(windowScene: windowScene)
|
||||||
let storyboard = UIStoryboard(name: "Main", bundle: nil)
|
let storyboard = UIStoryboard(name: "Main", bundle: nil)
|
||||||
|
|
||||||
|
let settingsService = ServiceContainer.shared.resolve(SettingsServiceProtocol.self)
|
||||||
|
|
||||||
if settingsService.user.token.isEmpty {
|
if settingsService.user.token.isEmpty {
|
||||||
self.window?.rootViewController = storyboard.instantiateViewController(identifier: "AuthController")
|
self.window?.rootViewController = storyboard.instantiateViewController(identifier: "AuthController")
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
34
AutoCat/Screens/HistoryScreen/HistoryCoordinator.swift
Normal file
34
AutoCat/Screens/HistoryScreen/HistoryCoordinator.swift
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
//
|
||||||
|
// HistoryCoordinator.swift
|
||||||
|
// AutoCat
|
||||||
|
//
|
||||||
|
// Created by Selim Mustafaev on 15.01.2025.
|
||||||
|
// Copyright © 2025 Selim Mustafaev. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import SwiftUI
|
||||||
|
import AutoCatCore
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
class HistoryCoordinator {
|
||||||
|
|
||||||
|
var navController: UINavigationController?
|
||||||
|
|
||||||
|
func start() -> UIViewController {
|
||||||
|
|
||||||
|
let resolver = ServiceContainer.shared
|
||||||
|
let viewModel = HistoryViewModel(
|
||||||
|
apiService: resolver.resolve(ApiServiceProtocol.self),
|
||||||
|
storageService: resolver.resolve(StorageServiceProtocol.self)
|
||||||
|
)
|
||||||
|
|
||||||
|
let view = HistoryScreen(viewModel: viewModel)
|
||||||
|
let controller = UIHostingController(rootView: view)
|
||||||
|
|
||||||
|
let navController = UINavigationController(rootViewController: controller)
|
||||||
|
self.navController = navController
|
||||||
|
|
||||||
|
return navController
|
||||||
|
}
|
||||||
|
}
|
||||||
28
AutoCat/Screens/HistoryScreen/HistoryScreen.swift
Normal file
28
AutoCat/Screens/HistoryScreen/HistoryScreen.swift
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// HistoryScreen.swift
|
||||||
|
// AutoCat
|
||||||
|
//
|
||||||
|
// Created by Selim Mustafaev on 15.01.2025.
|
||||||
|
// Copyright © 2025 Selim Mustafaev. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import AutoCatCore
|
||||||
|
|
||||||
|
struct HistoryScreen: View {
|
||||||
|
|
||||||
|
@State var viewModel: HistoryViewModel
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
List(viewModel.vehicles) { vehicle in
|
||||||
|
LicensePlateView(number: PlateNumber(vehicle.getNumber()))
|
||||||
|
.frame(width: 200)
|
||||||
|
}
|
||||||
|
.listStyle(.plain)
|
||||||
|
.navigationTitle(String.localizedStringWithFormat(NSLocalizedString("vehicles found", comment: ""), viewModel.vehicles.count))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//#Preview {
|
||||||
|
// HistoryScreen(viewModel: .init())
|
||||||
|
//}
|
||||||
33
AutoCat/Screens/HistoryScreen/HistoryViewModel.swift
Normal file
33
AutoCat/Screens/HistoryScreen/HistoryViewModel.swift
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
//
|
||||||
|
// HistoryViewModel.swift
|
||||||
|
// AutoCat
|
||||||
|
//
|
||||||
|
// Created by Selim Mustafaev on 15.01.2025.
|
||||||
|
// Copyright © 2025 Selim Mustafaev. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import AutoCatCore
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
@Observable
|
||||||
|
final class HistoryViewModel {
|
||||||
|
|
||||||
|
let apiService: ApiServiceProtocol
|
||||||
|
let storageService: StorageServiceProtocol
|
||||||
|
|
||||||
|
var vehicles: [VehicleDto] = []
|
||||||
|
|
||||||
|
init(apiService: ApiServiceProtocol, storageService: StorageServiceProtocol) {
|
||||||
|
|
||||||
|
self.apiService = apiService
|
||||||
|
self.storageService = storageService
|
||||||
|
|
||||||
|
Task { await loadVehicles() }
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadVehicles() async {
|
||||||
|
|
||||||
|
vehicles = await storageService.loadVehicles()
|
||||||
|
}
|
||||||
|
}
|
||||||
73
AutoCat/SwiftUI/LicensePlateView.swift
Normal file
73
AutoCat/SwiftUI/LicensePlateView.swift
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
//
|
||||||
|
// LicensePlateView.swift
|
||||||
|
// AutoCat
|
||||||
|
//
|
||||||
|
// Created by Selim Mustafaev on 15.01.2025.
|
||||||
|
// Copyright © 2025 Selim Mustafaev. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import AutoCatCore
|
||||||
|
|
||||||
|
struct LicensePlateView: View {
|
||||||
|
|
||||||
|
private static let aspectRatio: CGFloat = 520.0/112.0
|
||||||
|
private static let fontHeightCoeff: CGFloat = 58.0/76.0
|
||||||
|
private static let borderMultiplier = 0.01
|
||||||
|
private static let numberPartMultiplier = (1 - 3*LicensePlateView.borderMultiplier)*0.73
|
||||||
|
private static let reguinPartMultiplier = (1 - 3*LicensePlateView.borderMultiplier)*0.27
|
||||||
|
private static let outerCornerMultiplier = 0.03
|
||||||
|
private static let innerCornerMultiplier = outerCornerMultiplier - borderMultiplier
|
||||||
|
|
||||||
|
let number: PlateNumber
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
GeometryReader { geometry in
|
||||||
|
ZStack {
|
||||||
|
RoundedRectangle(cornerRadius: geometry.size.width*LicensePlateView.outerCornerMultiplier)
|
||||||
|
.fill(Color("PlateForeground"))
|
||||||
|
HStack(spacing: 0) {
|
||||||
|
ZStack {
|
||||||
|
RoundedRectangle(cornerRadius: geometry.size.width*LicensePlateView.innerCornerMultiplier)
|
||||||
|
.fill(Color("PlateBackground"))
|
||||||
|
Text(number.mainPart())
|
||||||
|
.font(.custom("RoadNumbers", size: geometry.size.height))
|
||||||
|
.kerning(3)
|
||||||
|
.offset(y: geometry.size.width*0.015)
|
||||||
|
}
|
||||||
|
.frame(width: geometry.size.width*LicensePlateView.numberPartMultiplier)
|
||||||
|
.padding(geometry.size.width*LicensePlateView.borderMultiplier)
|
||||||
|
|
||||||
|
ZStack {
|
||||||
|
RoundedRectangle(cornerRadius: geometry.size.width*LicensePlateView.innerCornerMultiplier)
|
||||||
|
.fill(Color("PlateBackground"))
|
||||||
|
VStack(spacing: 0) {
|
||||||
|
Text(number.region())
|
||||||
|
.font(.custom("RoadNumbers", size: geometry.size.height*0.7))
|
||||||
|
HStack(spacing: 2) {
|
||||||
|
Text("RUS")
|
||||||
|
.font(.system(size: geometry.size.height*0.3))
|
||||||
|
VStack(spacing: 0) {
|
||||||
|
Rectangle().fill(.white)
|
||||||
|
Rectangle().fill(.blue)
|
||||||
|
Rectangle().fill(.red)
|
||||||
|
}
|
||||||
|
.aspectRatio(1.5, contentMode: .fit)
|
||||||
|
.frame(width: geometry.size.width*0.08)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.offset(y: geometry.size.width*0.015)
|
||||||
|
}
|
||||||
|
.frame(width: geometry.size.width*LicensePlateView.reguinPartMultiplier)
|
||||||
|
.padding(.vertical, geometry.size.width*LicensePlateView.borderMultiplier)
|
||||||
|
.padding(.trailing, geometry.size.width*LicensePlateView.borderMultiplier)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.aspectRatio(LicensePlateView.aspectRatio, contentMode: .fit)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#Preview {
|
||||||
|
LicensePlateView(number: PlateNumber("А123АА761"))
|
||||||
|
}
|
||||||
@ -56,4 +56,9 @@ public actor StorageService: StorageServiceProtocol {
|
|||||||
throw StorageError.vehicleNotFound
|
throw StorageError.vehicleNotFound
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func loadVehicles() async -> [VehicleDto] {
|
||||||
|
|
||||||
|
realm.objects(Vehicle.self).map(\.shallowDto)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,11 +11,17 @@ import Mockable
|
|||||||
@Mockable
|
@Mockable
|
||||||
public protocol StorageServiceProtocol: Sendable {
|
public protocol StorageServiceProtocol: Sendable {
|
||||||
|
|
||||||
|
// Vehicles
|
||||||
|
func loadVehicles() async -> [VehicleDto]
|
||||||
|
func loadVehicle(number: String) async throws -> VehicleDto
|
||||||
|
func updateVehicleIfExists(dto: VehicleDto) async throws
|
||||||
|
|
||||||
|
// Notes
|
||||||
func addNote(text: String, to number: String) async throws -> VehicleDto
|
func addNote(text: String, to number: String) async throws -> VehicleDto
|
||||||
func deleteNote(id: String, for number: String) async throws -> VehicleDto
|
func deleteNote(id: String, for number: String) async throws -> VehicleDto
|
||||||
func editNote(id: String, text: String, for number: String) async throws -> VehicleDto
|
func editNote(id: String, text: String, for number: String) async throws -> VehicleDto
|
||||||
func updateVehicleIfExists(dto: VehicleDto) async throws
|
|
||||||
func loadVehicle(number: String) async throws -> VehicleDto
|
// Events
|
||||||
func add(event: VehicleEventDto, to number: String) async throws -> VehicleDto
|
func add(event: VehicleEventDto, to number: String) async throws -> VehicleDto
|
||||||
func remove(event id: String, from number: String) async throws -> VehicleDto
|
func remove(event id: String, from number: String) async throws -> VehicleDto
|
||||||
func edit(event: VehicleEventDto, for number: String) async throws -> VehicleDto
|
func edit(event: VehicleEventDto, for number: String) async throws -> VehicleDto
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user