diff --git a/.gitignore b/.gitignore
index 5b5b9b0..aec898f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
AutoCat2.xcodeproj/xcuserdata/
+AutoCat2.xcodeproj/project.xcworkspace/xcuserdata/
.DS_Store
diff --git a/AutoCat2 (macOS).entitlements b/AutoCat2 (macOS).entitlements
deleted file mode 100644
index ee95ab7..0000000
--- a/AutoCat2 (macOS).entitlements
+++ /dev/null
@@ -1,10 +0,0 @@
-
-
-
-
- com.apple.security.app-sandbox
-
- com.apple.security.network.client
-
-
-
diff --git a/AutoCat2.xcodeproj/project.pbxproj b/AutoCat2.xcodeproj/project.pbxproj
index bf88cd4..9734037 100644
--- a/AutoCat2.xcodeproj/project.pbxproj
+++ b/AutoCat2.xcodeproj/project.pbxproj
@@ -7,126 +7,106 @@
objects = {
/* Begin PBXBuildFile section */
- 7A2329B926AF122400264CFA /* MainViewSmall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2329B826AF122400264CFA /* MainViewSmall.swift */; };
- 7A2329BA26AF122400264CFA /* MainViewSmall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2329B826AF122400264CFA /* MainViewSmall.swift */; };
- 7A2329BD26AF123300264CFA /* MainViewBig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2329BB26AF123200264CFA /* MainViewBig.swift */; };
- 7A2329BF26AF140F00264CFA /* CheckView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2329BE26AF140F00264CFA /* CheckView.swift */; };
- 7A2329C026AF140F00264CFA /* CheckView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2329BE26AF140F00264CFA /* CheckView.swift */; };
- 7A2329C226AF141E00264CFA /* SearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2329C126AF141E00264CFA /* SearchView.swift */; };
- 7A2329C326AF141E00264CFA /* SearchView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2329C126AF141E00264CFA /* SearchView.swift */; };
- 7A2329C526AF142900264CFA /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2329C426AF142900264CFA /* SettingsView.swift */; };
- 7A2329C626AF142900264CFA /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2329C426AF142900264CFA /* SettingsView.swift */; };
- 7A2329C826AF143F00264CFA /* RecordsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2329C726AF143F00264CFA /* RecordsView.swift */; };
- 7A2329C926AF143F00264CFA /* RecordsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2329C726AF143F00264CFA /* RecordsView.swift */; };
- 7A2329CB26AF15AC00264CFA /* ReportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2329CA26AF15AC00264CFA /* ReportView.swift */; };
- 7A2329CC26AF15AC00264CFA /* ReportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2329CA26AF15AC00264CFA /* ReportView.swift */; };
- 7A40D5932691C6D8009B0BC4 /* Tests_iOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A40D5922691C6D8009B0BC4 /* Tests_iOS.swift */; };
- 7A40D59D2691C6D8009B0BC4 /* Tests_macOS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A40D59C2691C6D8009B0BC4 /* Tests_macOS.swift */; };
- 7A40D59E2691C6D8009B0BC4 /* AutoCat2.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 7A40D5792691C6D7009B0BC4 /* AutoCat2.xcdatamodeld */; };
- 7A40D59F2691C6D8009B0BC4 /* AutoCat2.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 7A40D5792691C6D7009B0BC4 /* AutoCat2.xcdatamodeld */; };
- 7A40D5A02691C6D8009B0BC4 /* AutoCat2App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A40D57B2691C6D7009B0BC4 /* AutoCat2App.swift */; };
- 7A40D5A12691C6D8009B0BC4 /* AutoCat2App.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A40D57B2691C6D7009B0BC4 /* AutoCat2App.swift */; };
- 7A40D5A22691C6D8009B0BC4 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A40D57C2691C6D7009B0BC4 /* ContentView.swift */; };
- 7A40D5A32691C6D8009B0BC4 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A40D57C2691C6D7009B0BC4 /* ContentView.swift */; };
- 7A40D5A42691C6D8009B0BC4 /* Persistence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A40D57D2691C6D7009B0BC4 /* Persistence.swift */; };
- 7A40D5A52691C6D8009B0BC4 /* Persistence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A40D57D2691C6D7009B0BC4 /* Persistence.swift */; };
- 7A40D5A62691C6D8009B0BC4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7A40D57E2691C6D7009B0BC4 /* Assets.xcassets */; };
- 7A40D5A72691C6D8009B0BC4 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7A40D57E2691C6D7009B0BC4 /* Assets.xcassets */; };
- 7A40D5E126924AEC009B0BC4 /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A40D5E026924AEC009B0BC4 /* User.swift */; };
- 7A40D5E326924B09009B0BC4 /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A40D5E226924B09009B0BC4 /* Settings.swift */; };
- 7A40D5E426924B09009B0BC4 /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A40D5E226924B09009B0BC4 /* Settings.swift */; };
- 7A40D5E526924B0C009B0BC4 /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A40D5E026924AEC009B0BC4 /* User.swift */; };
- 7A40D5E926938BEC009B0BC4 /* AuthView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A40D5E826938BEC009B0BC4 /* AuthView.swift */; };
- 7A40D5EA26938BEC009B0BC4 /* AuthView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A40D5E826938BEC009B0BC4 /* AuthView.swift */; };
- 7A40D5ED2693A1EA009B0BC4 /* AuthVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A40D5EC2693A1EA009B0BC4 /* AuthVM.swift */; };
- 7A40D5EE2693A1EA009B0BC4 /* AuthVM.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A40D5EC2693A1EA009B0BC4 /* AuthVM.swift */; };
- 7A40D5F62693A63A009B0BC4 /* SettingsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A40D5F52693A63A009B0BC4 /* SettingsTests.swift */; };
- 7A40D5FE2693A91F009B0BC4 /* CocoaError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A40D5FD2693A91F009B0BC4 /* CocoaError.swift */; };
- 7A40D5FF2693A91F009B0BC4 /* CocoaError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A40D5FD2693A91F009B0BC4 /* CocoaError.swift */; };
- 7A40D6022694FF5D009B0BC4 /* Api.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A40D6012694FF5D009B0BC4 /* Api.swift */; };
- 7A40D6032694FF5D009B0BC4 /* Api.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A40D6012694FF5D009B0BC4 /* Api.swift */; };
- 7A40D60826998DCF009B0BC4 /* Alert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A40D60726998DCF009B0BC4 /* Alert.swift */; };
- 7A40D60926998DCF009B0BC4 /* Alert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A40D60726998DCF009B0BC4 /* Alert.swift */; };
- 7A40D60C2699A070009B0BC4 /* MockURLProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A40D60B2699A070009B0BC4 /* MockURLProtocol.swift */; };
- 7A503C03269F382F002C1A0D /* login_success.json in Resources */ = {isa = PBXBuildFile; fileRef = 7A503C02269F382F002C1A0D /* login_success.json */; };
- 7A683999269612EA00B2188A /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A683998269612EA00B2188A /* Response.swift */; };
- 7A68399A269612EA00B2188A /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A683998269612EA00B2188A /* Response.swift */; };
- 7A971F0626AD6F2F007E527B /* ApiMethodMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A971F0526AD6F2F007E527B /* ApiMethodMock.swift */; };
- 7A971F0826AD7084007E527B /* LoginMethodMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A971F0726AD7084007E527B /* LoginMethodMock.swift */; };
- 7A971F0A26AD74FD007E527B /* ApiMethodMockProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A971F0926AD74FD007E527B /* ApiMethodMockProtocol.swift */; };
- 7A971F0D26AD7D4C007E527B /* AnyEncodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A971F0C26AD7D4C007E527B /* AnyEncodable.swift */; };
- 7A971F0E26AD7D4C007E527B /* AnyEncodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A971F0C26AD7D4C007E527B /* AnyEncodable.swift */; };
- 7A971F2026ADC351007E527B /* ApiError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A971F1F26ADC351007E527B /* ApiError.swift */; };
- 7A971F2126ADC351007E527B /* ApiError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A971F1F26ADC351007E527B /* ApiError.swift */; };
- 7A971F2326ADF74B007E527B /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A971F2226ADF74B007E527B /* MainView.swift */; };
- 7A971F2426ADF74B007E527B /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A971F2226ADF74B007E527B /* MainView.swift */; };
- 7AAEBD35274A47C500230C28 /* PlateNumberView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AAEBD34274A47C500230C28 /* PlateNumberView.swift */; };
- 7AAEBD36274A47C600230C28 /* PlateNumberView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AAEBD34274A47C500230C28 /* PlateNumberView.swift */; };
- 7ABC05A826B05AF9004BB5A7 /* Vehicle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ABC05A726B05AF9004BB5A7 /* Vehicle.swift */; };
- 7ABC05A926B05AF9004BB5A7 /* Vehicle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ABC05A726B05AF9004BB5A7 /* Vehicle.swift */; };
- 7ACD05D72695C08A00557667 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ACD05D62695C08A00557667 /* Constants.swift */; };
- 7ACD05D82695C08A00557667 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ACD05D62695C08A00557667 /* Constants.swift */; };
- 7ADE63712735E1FF00A152FE /* VName.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ADE63702735E1FF00A152FE /* VName.swift */; };
- 7ADE63732735E27200A152FE /* VBrand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ADE63722735E27200A152FE /* VBrand.swift */; };
- 7ADE63742735E27200A152FE /* VBrand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ADE63722735E27200A152FE /* VBrand.swift */; };
- 7ADE63752735E27D00A152FE /* VName.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ADE63702735E1FF00A152FE /* VName.swift */; };
- 7ADE637827368C4600A152FE /* VehicleService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ADE637727368C4600A152FE /* VehicleService.swift */; };
- 7ADE637927368C4600A152FE /* VehicleService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ADE637727368C4600A152FE /* VehicleService.swift */; };
- 7ADE637B273692F300A152FE /* StorageService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ADE637A273692F300A152FE /* StorageService.swift */; };
- 7ADE637C273692F300A152FE /* StorageService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ADE637A273692F300A152FE /* StorageService.swift */; };
- 7ADE637F2738143000A152FE /* CheckNumberPopup.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ADE637E2738143000A152FE /* CheckNumberPopup.swift */; };
- 7AEFAEED26985A3400ED2C85 /* ACProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AEFAEEC26985A3400ED2C85 /* ACProgressView.swift */; };
- 7AEFAEEE26985A3400ED2C85 /* ACProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AEFAEEC26985A3400ED2C85 /* ACProgressView.swift */; };
- 7AF552D92696E5C100578083 /* ApiTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF552D82696E5C100578083 /* ApiTests.swift */; };
- 7AFADDA7274A49DB00D53EFC /* PlateNumber.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AFADDA6274A49DB00D53EFC /* PlateNumber.swift */; };
- 7AFADDA8274A49DB00D53EFC /* PlateNumber.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AFADDA6274A49DB00D53EFC /* PlateNumber.swift */; };
- 7AFADDAF274A64DD00D53EFC /* RoadNumbers.otf in Resources */ = {isa = PBXBuildFile; fileRef = 7AFADDAD274A64DD00D53EFC /* RoadNumbers.otf */; };
- 7AFADDB0274A64DD00D53EFC /* RoadNumbers.otf in Resources */ = {isa = PBXBuildFile; fileRef = 7AFADDAD274A64DD00D53EFC /* RoadNumbers.otf */; };
- 7AFADDB1274A64DD00D53EFC /* RoadNumbers2.0.otf in Resources */ = {isa = PBXBuildFile; fileRef = 7AFADDAE274A64DD00D53EFC /* RoadNumbers2.0.otf */; };
- 7AFADDB2274A64DD00D53EFC /* RoadNumbers2.0.otf in Resources */ = {isa = PBXBuildFile; fileRef = 7AFADDAE274A64DD00D53EFC /* RoadNumbers2.0.otf */; };
+ 6841A0EE0ECCDB3519F728E6 /* HistoryController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6841A0A6580C6E9FF26DC6E2 /* HistoryController.swift */; };
+ 6841A20034E0A9378C3B4BB4 /* ACTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6841A850CF48F0715B63D998 /* ACTextField.swift */; };
+ 6841A35D2CC223CA7DCD51A2 /* SettingsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6841A5A586BC03AA21D73DF4 /* SettingsController.swift */; };
+ 6841A592745CDD869709EFA7 /* MainTabController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6841A3368FA7CA658C3EEABB /* MainTabController.swift */; };
+ 6841A5FE3E4927BF0EFF19F5 /* UIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6841A709FA6B606978425A26 /* UIViewController.swift */; };
+ 6841A63ECAC11B8956C7539D /* ACButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6841AFB465BF16E122875D9A /* ACButton.swift */; };
+ 6841A7D2375D35B0102D7DEC /* SwiftMaskTextfield.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6841A1A12194A8FA89FB52F6 /* SwiftMaskTextfield.swift */; };
+ 6841A80BB89BFD8D18E79680 /* UITextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6841ADEEC165FA9124C5EF40 /* UITextField.swift */; };
+ 6841A8FF53F0AADF96B138C1 /* UIControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6841AFE790F6FC06838B1E2C /* UIControl.swift */; };
+ 6841ABD5E4B126DEF3612BBD /* PNKeyboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6841AB0052E9DB6914901EA3 /* PNKeyboard.swift */; };
+ 6841AF924E165F1B3A3B5FB5 /* AuthController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6841ABEA0314E3B4E438C311 /* AuthController.swift */; };
+ 7A24C19727EE212E00049E7F /* RoadNumbers.otf in Resources */ = {isa = PBXBuildFile; fileRef = 7A24C19527EE212E00049E7F /* RoadNumbers.otf */; };
+ 7A24C19827EE212E00049E7F /* RoadNumbers2.0.otf in Resources */ = {isa = PBXBuildFile; fileRef = 7A24C19627EE212E00049E7F /* RoadNumbers2.0.otf */; };
+ 7A24C19C27EE25B400049E7F /* PlateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A24C19A27EE25B400049E7F /* PlateView.swift */; };
+ 7A24C19D27EE25B400049E7F /* FlagLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A24C19B27EE25B400049E7F /* FlagLayer.swift */; };
+ 7A24C19F27EE26B900049E7F /* CenterTextLayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A24C19E27EE26B900049E7F /* CenterTextLayer.swift */; };
+ 7A28282F27E720AC0049BDBF /* ACTabBarButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A28282E27E720AC0049BDBF /* ACTabBarButton.swift */; };
+ 7A28283127E721A70049BDBF /* UIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A28283027E721A70049BDBF /* UIView.swift */; };
+ 7A28283327E7263B0049BDBF /* UIStackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A28283227E7263B0049BDBF /* UIStackView.swift */; };
+ 7A28283627E74C110049BDBF /* SwiftEntryKit in Frameworks */ = {isa = PBXBuildFile; productRef = 7A28283527E74C110049BDBF /* SwiftEntryKit */; };
+ 7A28283827E74D930049BDBF /* CheckController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A28283727E74D930049BDBF /* CheckController.swift */; };
+ 7A48B26727D9442A004D1A4B /* PKHUD in Frameworks */ = {isa = PBXBuildFile; productRef = 7A48B26627D9442A004D1A4B /* PKHUD */; };
+ 7A49F4A327D4061900AEAAE0 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A49F4A227D4061900AEAAE0 /* AppDelegate.swift */; };
+ 7A49F4A527D4061900AEAAE0 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A49F4A427D4061900AEAAE0 /* SceneDelegate.swift */; };
+ 7A49F4A727D4061900AEAAE0 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A49F4A627D4061900AEAAE0 /* ViewController.swift */; };
+ 7A49F4AA27D4061900AEAAE0 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7A49F4A827D4061900AEAAE0 /* Main.storyboard */; };
+ 7A49F4AC27D4061A00AEAAE0 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7A49F4AB27D4061A00AEAAE0 /* Assets.xcassets */; };
+ 7A49F4AF27D4061A00AEAAE0 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7A49F4AD27D4061A00AEAAE0 /* LaunchScreen.storyboard */; };
+ 7A49F4BA27D4061B00AEAAE0 /* AutoCat2Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A49F4B927D4061B00AEAAE0 /* AutoCat2Tests.swift */; };
+ 7A49F4C427D4061B00AEAAE0 /* AutoCat2UITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A49F4C327D4061B00AEAAE0 /* AutoCat2UITests.swift */; };
+ 7A49F4C627D4061B00AEAAE0 /* AutoCat2UITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A49F4C527D4061B00AEAAE0 /* AutoCat2UITestsLaunchTests.swift */; };
+ 7A49F4DB27D4064500AEAAE0 /* AutoCatCore.docc in Sources */ = {isa = PBXBuildFile; fileRef = 7A49F4DA27D4064500AEAAE0 /* AutoCatCore.docc */; };
+ 7A49F4E127D4064500AEAAE0 /* AutoCatCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A49F4D727D4064500AEAAE0 /* AutoCatCore.framework */; };
+ 7A49F4E827D4064500AEAAE0 /* AutoCatCoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A49F4E727D4064500AEAAE0 /* AutoCatCoreTests.swift */; };
+ 7A49F4E927D4064500AEAAE0 /* AutoCatCore.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A49F4D927D4064500AEAAE0 /* AutoCatCore.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 7A49F4EC27D4064500AEAAE0 /* AutoCatCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A49F4D727D4064500AEAAE0 /* AutoCatCore.framework */; };
+ 7A49F4ED27D4064500AEAAE0 /* AutoCatCore.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 7A49F4D727D4064500AEAAE0 /* AutoCatCore.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ 7A49F4F927D406B200AEAAE0 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A49F4F627D406B200AEAAE0 /* Constants.swift */; };
+ 7A49F4FA27D406B200AEAAE0 /* ApiError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A49F4F727D406B200AEAAE0 /* ApiError.swift */; };
+ 7A49F4FB27D406B200AEAAE0 /* Api.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A49F4F827D406B200AEAAE0 /* Api.swift */; };
+ 7A49F4FE27D406BA00AEAAE0 /* AnyEncodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A49F4FD27D406BA00AEAAE0 /* AnyEncodable.swift */; };
+ 7A49F50227D406C300AEAAE0 /* StorageService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A49F50027D406C300AEAAE0 /* StorageService.swift */; };
+ 7A49F50327D406C300AEAAE0 /* VehicleService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A49F50127D406C300AEAAE0 /* VehicleService.swift */; };
+ 7A49F50C27D406CB00AEAAE0 /* VBrand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A49F50527D406CB00AEAAE0 /* VBrand.swift */; };
+ 7A49F50D27D406CB00AEAAE0 /* Vehicle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A49F50627D406CB00AEAAE0 /* Vehicle.swift */; };
+ 7A49F50E27D406CB00AEAAE0 /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A49F50727D406CB00AEAAE0 /* User.swift */; };
+ 7A49F50F27D406CB00AEAAE0 /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A49F50827D406CB00AEAAE0 /* Response.swift */; };
+ 7A49F51027D406CB00AEAAE0 /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A49F50927D406CB00AEAAE0 /* Settings.swift */; };
+ 7A49F51127D406CB00AEAAE0 /* PlateNumber.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A49F50A27D406CB00AEAAE0 /* PlateNumber.swift */; };
+ 7A49F51227D406CB00AEAAE0 /* VName.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A49F50B27D406CB00AEAAE0 /* VName.swift */; };
+ 7A49F51527D40C6100AEAAE0 /* AutoCat2.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 7A49F51327D40C6100AEAAE0 /* AutoCat2.xcdatamodeld */; };
+ 7A9F2AC327E71531006492A9 /* ACTabBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9F2AC227E71531006492A9 /* ACTabBarController.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
- 7A40D58F2691C6D8009B0BC4 /* PBXContainerItemProxy */ = {
+ 7A49F4B627D4061B00AEAAE0 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
- containerPortal = 7A40D5742691C6D6009B0BC4 /* Project object */;
+ containerPortal = 7A49F49727D4061900AEAAE0 /* Project object */;
proxyType = 1;
- remoteGlobalIDString = 7A40D5822691C6D8009B0BC4;
- remoteInfo = "AutoCat2 (iOS)";
+ remoteGlobalIDString = 7A49F49E27D4061900AEAAE0;
+ remoteInfo = AutoCat2;
};
- 7A40D5992691C6D8009B0BC4 /* PBXContainerItemProxy */ = {
+ 7A49F4C027D4061B00AEAAE0 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
- containerPortal = 7A40D5742691C6D6009B0BC4 /* Project object */;
+ containerPortal = 7A49F49727D4061900AEAAE0 /* Project object */;
proxyType = 1;
- remoteGlobalIDString = 7A40D5882691C6D8009B0BC4;
- remoteInfo = "AutoCat2 (macOS)";
+ remoteGlobalIDString = 7A49F49E27D4061900AEAAE0;
+ remoteInfo = AutoCat2;
};
- 7A40D5F72693A63A009B0BC4 /* PBXContainerItemProxy */ = {
+ 7A49F4E227D4064500AEAAE0 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
- containerPortal = 7A40D5742691C6D6009B0BC4 /* Project object */;
+ containerPortal = 7A49F49727D4061900AEAAE0 /* Project object */;
proxyType = 1;
- remoteGlobalIDString = 7A40D5822691C6D8009B0BC4;
- remoteInfo = "AutoCat2 (iOS)";
+ remoteGlobalIDString = 7A49F4D627D4064500AEAAE0;
+ remoteInfo = AutoCatCore;
+ };
+ 7A49F4E427D4064500AEAAE0 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 7A49F49727D4061900AEAAE0 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 7A49F49E27D4061900AEAAE0;
+ remoteInfo = AutoCat2;
+ };
+ 7A49F4EA27D4064500AEAAE0 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 7A49F49727D4061900AEAAE0 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 7A49F4D627D4064500AEAAE0;
+ remoteInfo = AutoCatCore;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
- 7A40D5D52691C7D3009B0BC4 /* Embed Frameworks */ = {
- isa = PBXCopyFilesBuildPhase;
- buildActionMask = 2147483647;
- dstPath = "";
- dstSubfolderSpec = 10;
- files = (
- );
- name = "Embed Frameworks";
- runOnlyForDeploymentPostprocessing = 0;
- };
- 7A40D5DE2691C7EB009B0BC4 /* Embed Frameworks */ = {
+ 7A49F4F127D4064500AEAAE0 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "";
dstSubfolderSpec = 10;
files = (
+ 7A49F4ED27D4064500AEAAE0 /* AutoCatCore.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
@@ -134,437 +114,440 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
- 7A2329B826AF122400264CFA /* MainViewSmall.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewSmall.swift; sourceTree = ""; };
- 7A2329BB26AF123200264CFA /* MainViewBig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainViewBig.swift; sourceTree = ""; };
- 7A2329BE26AF140F00264CFA /* CheckView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckView.swift; sourceTree = ""; };
- 7A2329C126AF141E00264CFA /* SearchView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchView.swift; sourceTree = ""; };
- 7A2329C426AF142900264CFA /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = ""; };
- 7A2329C726AF143F00264CFA /* RecordsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RecordsView.swift; sourceTree = ""; };
- 7A2329CA26AF15AC00264CFA /* ReportView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportView.swift; sourceTree = ""; };
- 7A40D57A2691C6D7009B0BC4 /* Shared.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Shared.xcdatamodel; sourceTree = ""; };
- 7A40D57B2691C6D7009B0BC4 /* AutoCat2App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoCat2App.swift; sourceTree = ""; };
- 7A40D57C2691C6D7009B0BC4 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; };
- 7A40D57D2691C6D7009B0BC4 /* Persistence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Persistence.swift; sourceTree = ""; };
- 7A40D57E2691C6D7009B0BC4 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
- 7A40D5832691C6D8009B0BC4 /* AutoCat2.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AutoCat2.app; sourceTree = BUILT_PRODUCTS_DIR; };
- 7A40D5892691C6D8009B0BC4 /* AutoCat2.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AutoCat2.app; sourceTree = BUILT_PRODUCTS_DIR; };
- 7A40D58E2691C6D8009B0BC4 /* Tests iOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Tests iOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
- 7A40D5922691C6D8009B0BC4 /* Tests_iOS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests_iOS.swift; sourceTree = ""; };
- 7A40D5982691C6D8009B0BC4 /* Tests macOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Tests macOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
- 7A40D59C2691C6D8009B0BC4 /* Tests_macOS.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Tests_macOS.swift; sourceTree = ""; };
- 7A40D5E026924AEC009B0BC4 /* User.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = ""; };
- 7A40D5E226924B09009B0BC4 /* Settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Settings.swift; sourceTree = ""; };
- 7A40D5E826938BEC009B0BC4 /* AuthView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthView.swift; sourceTree = ""; };
- 7A40D5EC2693A1EA009B0BC4 /* AuthVM.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthVM.swift; sourceTree = ""; };
- 7A40D5F32693A63A009B0BC4 /* AutoCat2Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AutoCat2Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
- 7A40D5F52693A63A009B0BC4 /* SettingsTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsTests.swift; sourceTree = ""; };
- 7A40D5FD2693A91F009B0BC4 /* CocoaError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CocoaError.swift; sourceTree = ""; };
- 7A40D6012694FF5D009B0BC4 /* Api.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Api.swift; sourceTree = ""; };
- 7A40D60726998DCF009B0BC4 /* Alert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Alert.swift; sourceTree = ""; };
- 7A40D60B2699A070009B0BC4 /* MockURLProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockURLProtocol.swift; sourceTree = ""; };
- 7A503C02269F382F002C1A0D /* login_success.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = login_success.json; sourceTree = ""; };
- 7A683998269612EA00B2188A /* Response.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Response.swift; sourceTree = ""; };
- 7A971F0526AD6F2F007E527B /* ApiMethodMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApiMethodMock.swift; sourceTree = ""; };
- 7A971F0726AD7084007E527B /* LoginMethodMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginMethodMock.swift; sourceTree = ""; };
- 7A971F0926AD74FD007E527B /* ApiMethodMockProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApiMethodMockProtocol.swift; sourceTree = ""; };
- 7A971F0C26AD7D4C007E527B /* AnyEncodable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnyEncodable.swift; sourceTree = ""; };
- 7A971F1F26ADC351007E527B /* ApiError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApiError.swift; sourceTree = ""; };
- 7A971F2226ADF74B007E527B /* MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = ""; };
- 7A971F2526ADFD35007E527B /* AutoCat2 (macOS).entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "AutoCat2 (macOS).entitlements"; sourceTree = ""; };
- 7AAEBD34274A47C500230C28 /* PlateNumberView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlateNumberView.swift; sourceTree = ""; };
- 7ABC05A726B05AF9004BB5A7 /* Vehicle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Vehicle.swift; sourceTree = ""; };
- 7ACD05D62695C08A00557667 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; };
- 7ADE63702735E1FF00A152FE /* VName.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VName.swift; sourceTree = ""; };
- 7ADE63722735E27200A152FE /* VBrand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VBrand.swift; sourceTree = ""; };
- 7ADE637727368C4600A152FE /* VehicleService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehicleService.swift; sourceTree = ""; };
- 7ADE637A273692F300A152FE /* StorageService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageService.swift; sourceTree = ""; };
- 7ADE637E2738143000A152FE /* CheckNumberPopup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckNumberPopup.swift; sourceTree = ""; };
- 7AEFAEEC26985A3400ED2C85 /* ACProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ACProgressView.swift; sourceTree = ""; };
- 7AF552D82696E5C100578083 /* ApiTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApiTests.swift; sourceTree = ""; };
- 7AFADDA6274A49DB00D53EFC /* PlateNumber.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlateNumber.swift; sourceTree = ""; };
- 7AFADDAD274A64DD00D53EFC /* RoadNumbers.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = RoadNumbers.otf; sourceTree = ""; };
- 7AFADDAE274A64DD00D53EFC /* RoadNumbers2.0.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = RoadNumbers2.0.otf; sourceTree = ""; };
- 7AFADDB3274A65BB00D53EFC /* AutoCat2--macOS--Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "AutoCat2--macOS--Info.plist"; sourceTree = ""; };
- 7AFADDB4274A678D00D53EFC /* AutoCat2--iOS--Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "AutoCat2--iOS--Info.plist"; sourceTree = ""; };
+ 6841A0A6580C6E9FF26DC6E2 /* HistoryController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HistoryController.swift; sourceTree = ""; };
+ 6841A1A12194A8FA89FB52F6 /* SwiftMaskTextfield.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftMaskTextfield.swift; sourceTree = ""; };
+ 6841A3368FA7CA658C3EEABB /* MainTabController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainTabController.swift; sourceTree = ""; };
+ 6841A5A586BC03AA21D73DF4 /* SettingsController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsController.swift; sourceTree = ""; };
+ 6841A709FA6B606978425A26 /* UIViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIViewController.swift; sourceTree = ""; };
+ 6841A850CF48F0715B63D998 /* ACTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ACTextField.swift; sourceTree = ""; };
+ 6841AB0052E9DB6914901EA3 /* PNKeyboard.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PNKeyboard.swift; sourceTree = ""; };
+ 6841ABEA0314E3B4E438C311 /* AuthController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AuthController.swift; sourceTree = ""; };
+ 6841ADEEC165FA9124C5EF40 /* UITextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UITextField.swift; sourceTree = ""; };
+ 6841AFB465BF16E122875D9A /* ACButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ACButton.swift; sourceTree = ""; };
+ 6841AFE790F6FC06838B1E2C /* UIControl.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIControl.swift; sourceTree = ""; };
+ 7A24C19527EE212E00049E7F /* RoadNumbers.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = RoadNumbers.otf; sourceTree = ""; };
+ 7A24C19627EE212E00049E7F /* RoadNumbers2.0.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = RoadNumbers2.0.otf; sourceTree = ""; };
+ 7A24C19A27EE25B400049E7F /* PlateView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PlateView.swift; sourceTree = ""; };
+ 7A24C19B27EE25B400049E7F /* FlagLayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FlagLayer.swift; sourceTree = ""; };
+ 7A24C19E27EE26B900049E7F /* CenterTextLayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CenterTextLayer.swift; sourceTree = ""; };
+ 7A28282E27E720AC0049BDBF /* ACTabBarButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ACTabBarButton.swift; sourceTree = ""; };
+ 7A28283027E721A70049BDBF /* UIView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIView.swift; sourceTree = ""; };
+ 7A28283227E7263B0049BDBF /* UIStackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIStackView.swift; sourceTree = ""; };
+ 7A28283727E74D930049BDBF /* CheckController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckController.swift; sourceTree = ""; };
+ 7A49F49F27D4061900AEAAE0 /* AutoCat2.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AutoCat2.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 7A49F4A227D4061900AEAAE0 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
+ 7A49F4A427D4061900AEAAE0 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; };
+ 7A49F4A627D4061900AEAAE0 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
+ 7A49F4A927D4061900AEAAE0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
+ 7A49F4AB27D4061A00AEAAE0 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
+ 7A49F4AE27D4061A00AEAAE0 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
+ 7A49F4B027D4061A00AEAAE0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+ 7A49F4B527D4061B00AEAAE0 /* AutoCat2Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AutoCat2Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 7A49F4B927D4061B00AEAAE0 /* AutoCat2Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoCat2Tests.swift; sourceTree = ""; };
+ 7A49F4BF27D4061B00AEAAE0 /* AutoCat2UITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AutoCat2UITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 7A49F4C327D4061B00AEAAE0 /* AutoCat2UITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoCat2UITests.swift; sourceTree = ""; };
+ 7A49F4C527D4061B00AEAAE0 /* AutoCat2UITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoCat2UITestsLaunchTests.swift; sourceTree = ""; };
+ 7A49F4D727D4064500AEAAE0 /* AutoCatCore.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = AutoCatCore.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+ 7A49F4D927D4064500AEAAE0 /* AutoCatCore.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AutoCatCore.h; sourceTree = ""; };
+ 7A49F4DA27D4064500AEAAE0 /* AutoCatCore.docc */ = {isa = PBXFileReference; lastKnownFileType = folder.documentationcatalog; path = AutoCatCore.docc; sourceTree = ""; };
+ 7A49F4E027D4064500AEAAE0 /* AutoCatCoreTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AutoCatCoreTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 7A49F4E727D4064500AEAAE0 /* AutoCatCoreTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutoCatCoreTests.swift; sourceTree = ""; };
+ 7A49F4F627D406B200AEAAE0 /* Constants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = ""; };
+ 7A49F4F727D406B200AEAAE0 /* ApiError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ApiError.swift; sourceTree = ""; };
+ 7A49F4F827D406B200AEAAE0 /* Api.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Api.swift; sourceTree = ""; };
+ 7A49F4FD27D406BA00AEAAE0 /* AnyEncodable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnyEncodable.swift; sourceTree = ""; };
+ 7A49F50027D406C300AEAAE0 /* StorageService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StorageService.swift; sourceTree = ""; };
+ 7A49F50127D406C300AEAAE0 /* VehicleService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VehicleService.swift; sourceTree = ""; };
+ 7A49F50527D406CB00AEAAE0 /* VBrand.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VBrand.swift; sourceTree = ""; };
+ 7A49F50627D406CB00AEAAE0 /* Vehicle.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Vehicle.swift; sourceTree = ""; };
+ 7A49F50727D406CB00AEAAE0 /* User.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = ""; };
+ 7A49F50827D406CB00AEAAE0 /* Response.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Response.swift; sourceTree = ""; };
+ 7A49F50927D406CB00AEAAE0 /* Settings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Settings.swift; sourceTree = ""; };
+ 7A49F50A27D406CB00AEAAE0 /* PlateNumber.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PlateNumber.swift; sourceTree = ""; };
+ 7A49F50B27D406CB00AEAAE0 /* VName.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = VName.swift; sourceTree = ""; };
+ 7A49F51427D40C6100AEAAE0 /* Shared.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Shared.xcdatamodel; sourceTree = ""; };
+ 7A9F2AC227E71531006492A9 /* ACTabBarController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ACTabBarController.swift; sourceTree = ""; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
- 7A40D5802691C6D8009B0BC4 /* Frameworks */ = {
+ 7A49F49C27D4061900AEAAE0 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 7A49F4EC27D4064500AEAAE0 /* AutoCatCore.framework in Frameworks */,
+ 7A48B26727D9442A004D1A4B /* PKHUD in Frameworks */,
+ 7A28283627E74C110049BDBF /* SwiftEntryKit in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 7A49F4B227D4061B00AEAAE0 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
- 7A40D5862691C6D8009B0BC4 /* Frameworks */ = {
+ 7A49F4BC27D4061B00AEAAE0 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
- 7A40D58B2691C6D8009B0BC4 /* Frameworks */ = {
+ 7A49F4D427D4064500AEAAE0 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
- 7A40D5952691C6D8009B0BC4 /* Frameworks */ = {
- isa = PBXFrameworksBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- 7A40D5F02693A63A009B0BC4 /* Frameworks */ = {
+ 7A49F4DD27D4064500AEAAE0 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ 7A49F4E127D4064500AEAAE0 /* AutoCatCore.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
- 7A40D5732691C6D6009B0BC4 = {
+ 6841A0EB55A59DAC94129594 /* Extensions */ = {
isa = PBXGroup;
children = (
- 7AFADDB4274A678D00D53EFC /* AutoCat2--iOS--Info.plist */,
- 7AFADDB3274A65BB00D53EFC /* AutoCat2--macOS--Info.plist */,
- 7A971F2526ADFD35007E527B /* AutoCat2 (macOS).entitlements */,
- 7A40D5782691C6D7009B0BC4 /* Shared */,
- 7A40D5912691C6D8009B0BC4 /* Tests iOS */,
- 7A40D59B2691C6D8009B0BC4 /* Tests macOS */,
- 7A40D5F42693A63A009B0BC4 /* AutoCat2Tests */,
- 7A40D5842691C6D8009B0BC4 /* Products */,
- );
- sourceTree = "";
- };
- 7A40D5782691C6D7009B0BC4 /* Shared */ = {
- isa = PBXGroup;
- children = (
- 7AFADDAC274A64DD00D53EFC /* Fonts */,
- 7ADE637627368C2A00A152FE /* Services */,
- 7A971F0B26AD7D27007E527B /* ThirdParty */,
- 7A40D6002694FF4C009B0BC4 /* Utils */,
- 7A40D5FC2693A90F009B0BC4 /* Extensions */,
- 7A40D5EB2693A1C3009B0BC4 /* ViewModels */,
- 7A40D5E726938BC8009B0BC4 /* Views */,
- 7A40D5E626924BAA009B0BC4 /* Property Wrappers */,
- 7A40D5DF26924ADE009B0BC4 /* Models */,
- 7A40D57B2691C6D7009B0BC4 /* AutoCat2App.swift */,
- 7A40D57D2691C6D7009B0BC4 /* Persistence.swift */,
- 7A40D57E2691C6D7009B0BC4 /* Assets.xcassets */,
- 7A40D5792691C6D7009B0BC4 /* AutoCat2.xcdatamodeld */,
- );
- path = Shared;
- sourceTree = "";
- };
- 7A40D5842691C6D8009B0BC4 /* Products */ = {
- isa = PBXGroup;
- children = (
- 7A40D5832691C6D8009B0BC4 /* AutoCat2.app */,
- 7A40D5892691C6D8009B0BC4 /* AutoCat2.app */,
- 7A40D58E2691C6D8009B0BC4 /* Tests iOS.xctest */,
- 7A40D5982691C6D8009B0BC4 /* Tests macOS.xctest */,
- 7A40D5F32693A63A009B0BC4 /* AutoCat2Tests.xctest */,
- );
- name = Products;
- sourceTree = "";
- };
- 7A40D5912691C6D8009B0BC4 /* Tests iOS */ = {
- isa = PBXGroup;
- children = (
- 7A40D5922691C6D8009B0BC4 /* Tests_iOS.swift */,
- );
- path = "Tests iOS";
- sourceTree = "";
- };
- 7A40D59B2691C6D8009B0BC4 /* Tests macOS */ = {
- isa = PBXGroup;
- children = (
- 7A40D59C2691C6D8009B0BC4 /* Tests_macOS.swift */,
- );
- path = "Tests macOS";
- sourceTree = "";
- };
- 7A40D5DF26924ADE009B0BC4 /* Models */ = {
- isa = PBXGroup;
- children = (
- 7A40D5E026924AEC009B0BC4 /* User.swift */,
- 7A40D5E226924B09009B0BC4 /* Settings.swift */,
- 7A683998269612EA00B2188A /* Response.swift */,
- 7ABC05A726B05AF9004BB5A7 /* Vehicle.swift */,
- 7ADE63702735E1FF00A152FE /* VName.swift */,
- 7ADE63722735E27200A152FE /* VBrand.swift */,
- 7AFADDA6274A49DB00D53EFC /* PlateNumber.swift */,
- );
- path = Models;
- sourceTree = "";
- };
- 7A40D5E626924BAA009B0BC4 /* Property Wrappers */ = {
- isa = PBXGroup;
- children = (
- );
- path = "Property Wrappers";
- sourceTree = "";
- };
- 7A40D5E726938BC8009B0BC4 /* Views */ = {
- isa = PBXGroup;
- children = (
- 7ADE637D2738139D00A152FE /* macOS */,
- 7AEFAEEC26985A3400ED2C85 /* ACProgressView.swift */,
- 7A2329BE26AF140F00264CFA /* CheckView.swift */,
- 7A40D57C2691C6D7009B0BC4 /* ContentView.swift */,
- 7A40D5E826938BEC009B0BC4 /* AuthView.swift */,
- 7A971F2226ADF74B007E527B /* MainView.swift */,
- 7A2329B826AF122400264CFA /* MainViewSmall.swift */,
- 7A2329C126AF141E00264CFA /* SearchView.swift */,
- 7A2329C426AF142900264CFA /* SettingsView.swift */,
- 7A2329C726AF143F00264CFA /* RecordsView.swift */,
- 7A2329CA26AF15AC00264CFA /* ReportView.swift */,
- 7AAEBD34274A47C500230C28 /* PlateNumberView.swift */,
- );
- path = Views;
- sourceTree = "";
- };
- 7A40D5EB2693A1C3009B0BC4 /* ViewModels */ = {
- isa = PBXGroup;
- children = (
- 7A40D5EC2693A1EA009B0BC4 /* AuthVM.swift */,
- );
- path = ViewModels;
- sourceTree = "";
- };
- 7A40D5F42693A63A009B0BC4 /* AutoCat2Tests */ = {
- isa = PBXGroup;
- children = (
- 7A971F0326AD6EA1007E527B /* Api */,
- 7A40D5F52693A63A009B0BC4 /* SettingsTests.swift */,
- 7AF552D82696E5C100578083 /* ApiTests.swift */,
- );
- path = AutoCat2Tests;
- sourceTree = "";
- };
- 7A40D5FC2693A90F009B0BC4 /* Extensions */ = {
- isa = PBXGroup;
- children = (
- 7A40D5FD2693A91F009B0BC4 /* CocoaError.swift */,
- 7A40D60726998DCF009B0BC4 /* Alert.swift */,
+ 6841AFE790F6FC06838B1E2C /* UIControl.swift */,
+ 6841ADEEC165FA9124C5EF40 /* UITextField.swift */,
+ 6841A709FA6B606978425A26 /* UIViewController.swift */,
+ 7A28283027E721A70049BDBF /* UIView.swift */,
+ 7A28283227E7263B0049BDBF /* UIStackView.swift */,
);
path = Extensions;
sourceTree = "";
};
- 7A40D6002694FF4C009B0BC4 /* Utils */ = {
+ 6841A450B0D0A7DB09CC746A /* ThirdParty */ = {
isa = PBXGroup;
children = (
- 7A40D6012694FF5D009B0BC4 /* Api.swift */,
- 7A971F1F26ADC351007E527B /* ApiError.swift */,
- 7ACD05D62695C08A00557667 /* Constants.swift */,
- );
- path = Utils;
- sourceTree = "";
- };
- 7A40D60A2699A04F009B0BC4 /* Mocks */ = {
- isa = PBXGroup;
- children = (
- 7A971F0526AD6F2F007E527B /* ApiMethodMock.swift */,
- 7A971F0726AD7084007E527B /* LoginMethodMock.swift */,
- );
- path = Mocks;
- sourceTree = "";
- };
- 7A503C00269F370A002C1A0D /* Responses */ = {
- isa = PBXGroup;
- children = (
- 7A503C02269F382F002C1A0D /* login_success.json */,
- );
- path = Responses;
- sourceTree = "";
- };
- 7A971F0326AD6EA1007E527B /* Api */ = {
- isa = PBXGroup;
- children = (
- 7A971F0426AD6ED6007E527B /* Lib */,
- 7A40D60A2699A04F009B0BC4 /* Mocks */,
- 7A503C00269F370A002C1A0D /* Responses */,
- );
- path = Api;
- sourceTree = "";
- };
- 7A971F0426AD6ED6007E527B /* Lib */ = {
- isa = PBXGroup;
- children = (
- 7A40D60B2699A070009B0BC4 /* MockURLProtocol.swift */,
- 7A971F0926AD74FD007E527B /* ApiMethodMockProtocol.swift */,
- );
- path = Lib;
- sourceTree = "";
- };
- 7A971F0B26AD7D27007E527B /* ThirdParty */ = {
- isa = PBXGroup;
- children = (
- 7A971F0C26AD7D4C007E527B /* AnyEncodable.swift */,
+ 7A24C19E27EE26B900049E7F /* CenterTextLayer.swift */,
+ 6841A1A12194A8FA89FB52F6 /* SwiftMaskTextfield.swift */,
);
path = ThirdParty;
sourceTree = "";
};
- 7ADE637627368C2A00A152FE /* Services */ = {
+ 6841A5B816D903B6AC0E8FDD /* Controllers */ = {
isa = PBXGroup;
children = (
- 7ADE637727368C4600A152FE /* VehicleService.swift */,
- 7ADE637A273692F300A152FE /* StorageService.swift */,
+ 6841ABEA0314E3B4E438C311 /* AuthController.swift */,
+ 6841A3368FA7CA658C3EEABB /* MainTabController.swift */,
+ 6841A0A6580C6E9FF26DC6E2 /* HistoryController.swift */,
+ 6841A5A586BC03AA21D73DF4 /* SettingsController.swift */,
+ 7A28283727E74D930049BDBF /* CheckController.swift */,
);
- path = Services;
+ path = Controllers;
sourceTree = "";
};
- 7ADE637D2738139D00A152FE /* macOS */ = {
+ 6841AEAC436660C91E968C9F /* Components */ = {
isa = PBXGroup;
children = (
- 7A2329BB26AF123200264CFA /* MainViewBig.swift */,
- 7ADE637E2738143000A152FE /* CheckNumberPopup.swift */,
+ 7A24C19927EE259000049E7F /* PlateView */,
+ 7A28282D27E720830049BDBF /* ACTabBar */,
+ 6841A0EB55A59DAC94129594 /* Extensions */,
+ 6841AFB465BF16E122875D9A /* ACButton.swift */,
+ 6841A850CF48F0715B63D998 /* ACTextField.swift */,
+ 6841AB0052E9DB6914901EA3 /* PNKeyboard.swift */,
);
- path = macOS;
+ path = Components;
sourceTree = "";
};
- 7AFADDAC274A64DD00D53EFC /* Fonts */ = {
+ 7A24C19427EE212E00049E7F /* Fonts */ = {
isa = PBXGroup;
children = (
- 7AFADDAD274A64DD00D53EFC /* RoadNumbers.otf */,
- 7AFADDAE274A64DD00D53EFC /* RoadNumbers2.0.otf */,
+ 7A24C19527EE212E00049E7F /* RoadNumbers.otf */,
+ 7A24C19627EE212E00049E7F /* RoadNumbers2.0.otf */,
);
path = Fonts;
sourceTree = "";
};
+ 7A24C19927EE259000049E7F /* PlateView */ = {
+ isa = PBXGroup;
+ children = (
+ 7A24C19B27EE25B400049E7F /* FlagLayer.swift */,
+ 7A24C19A27EE25B400049E7F /* PlateView.swift */,
+ );
+ path = PlateView;
+ sourceTree = "";
+ };
+ 7A28282D27E720830049BDBF /* ACTabBar */ = {
+ isa = PBXGroup;
+ children = (
+ 7A9F2AC227E71531006492A9 /* ACTabBarController.swift */,
+ 7A28282E27E720AC0049BDBF /* ACTabBarButton.swift */,
+ );
+ path = ACTabBar;
+ sourceTree = "";
+ };
+ 7A49F49627D4061900AEAAE0 = {
+ isa = PBXGroup;
+ children = (
+ 7A49F4A127D4061900AEAAE0 /* AutoCat2 */,
+ 7A49F4B827D4061B00AEAAE0 /* AutoCat2Tests */,
+ 7A49F4C227D4061B00AEAAE0 /* AutoCat2UITests */,
+ 7A49F4D827D4064500AEAAE0 /* AutoCatCore */,
+ 7A49F4E627D4064500AEAAE0 /* AutoCatCoreTests */,
+ 7A49F4A027D4061900AEAAE0 /* Products */,
+ );
+ sourceTree = "";
+ };
+ 7A49F4A027D4061900AEAAE0 /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 7A49F49F27D4061900AEAAE0 /* AutoCat2.app */,
+ 7A49F4B527D4061B00AEAAE0 /* AutoCat2Tests.xctest */,
+ 7A49F4BF27D4061B00AEAAE0 /* AutoCat2UITests.xctest */,
+ 7A49F4D727D4064500AEAAE0 /* AutoCatCore.framework */,
+ 7A49F4E027D4064500AEAAE0 /* AutoCatCoreTests.xctest */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 7A49F4A127D4061900AEAAE0 /* AutoCat2 */ = {
+ isa = PBXGroup;
+ children = (
+ 7A24C19427EE212E00049E7F /* Fonts */,
+ 7A49F4A227D4061900AEAAE0 /* AppDelegate.swift */,
+ 7A49F4A427D4061900AEAAE0 /* SceneDelegate.swift */,
+ 7A49F4A627D4061900AEAAE0 /* ViewController.swift */,
+ 7A49F4A827D4061900AEAAE0 /* Main.storyboard */,
+ 7A49F4AB27D4061A00AEAAE0 /* Assets.xcassets */,
+ 7A49F4AD27D4061A00AEAAE0 /* LaunchScreen.storyboard */,
+ 7A49F4B027D4061A00AEAAE0 /* Info.plist */,
+ 6841A5B816D903B6AC0E8FDD /* Controllers */,
+ 6841AEAC436660C91E968C9F /* Components */,
+ 6841A450B0D0A7DB09CC746A /* ThirdParty */,
+ );
+ path = AutoCat2;
+ sourceTree = "";
+ };
+ 7A49F4B827D4061B00AEAAE0 /* AutoCat2Tests */ = {
+ isa = PBXGroup;
+ children = (
+ 7A49F4B927D4061B00AEAAE0 /* AutoCat2Tests.swift */,
+ );
+ path = AutoCat2Tests;
+ sourceTree = "";
+ };
+ 7A49F4C227D4061B00AEAAE0 /* AutoCat2UITests */ = {
+ isa = PBXGroup;
+ children = (
+ 7A49F4C327D4061B00AEAAE0 /* AutoCat2UITests.swift */,
+ 7A49F4C527D4061B00AEAAE0 /* AutoCat2UITestsLaunchTests.swift */,
+ );
+ path = AutoCat2UITests;
+ sourceTree = "";
+ };
+ 7A49F4D827D4064500AEAAE0 /* AutoCatCore */ = {
+ isa = PBXGroup;
+ children = (
+ 7A49F51327D40C6100AEAAE0 /* AutoCat2.xcdatamodeld */,
+ 7A49F50427D406CB00AEAAE0 /* Models */,
+ 7A49F4FF27D406C300AEAAE0 /* Services */,
+ 7A49F4FC27D406BA00AEAAE0 /* ThirdParty */,
+ 7A49F4F527D406B200AEAAE0 /* Utils */,
+ 7A49F4D927D4064500AEAAE0 /* AutoCatCore.h */,
+ 7A49F4DA27D4064500AEAAE0 /* AutoCatCore.docc */,
+ );
+ path = AutoCatCore;
+ sourceTree = "";
+ };
+ 7A49F4E627D4064500AEAAE0 /* AutoCatCoreTests */ = {
+ isa = PBXGroup;
+ children = (
+ 7A49F4E727D4064500AEAAE0 /* AutoCatCoreTests.swift */,
+ );
+ path = AutoCatCoreTests;
+ sourceTree = "";
+ };
+ 7A49F4F527D406B200AEAAE0 /* Utils */ = {
+ isa = PBXGroup;
+ children = (
+ 7A49F4F627D406B200AEAAE0 /* Constants.swift */,
+ 7A49F4F727D406B200AEAAE0 /* ApiError.swift */,
+ 7A49F4F827D406B200AEAAE0 /* Api.swift */,
+ );
+ path = Utils;
+ sourceTree = "";
+ };
+ 7A49F4FC27D406BA00AEAAE0 /* ThirdParty */ = {
+ isa = PBXGroup;
+ children = (
+ 7A49F4FD27D406BA00AEAAE0 /* AnyEncodable.swift */,
+ );
+ path = ThirdParty;
+ sourceTree = "";
+ };
+ 7A49F4FF27D406C300AEAAE0 /* Services */ = {
+ isa = PBXGroup;
+ children = (
+ 7A49F50027D406C300AEAAE0 /* StorageService.swift */,
+ 7A49F50127D406C300AEAAE0 /* VehicleService.swift */,
+ );
+ path = Services;
+ sourceTree = "";
+ };
+ 7A49F50427D406CB00AEAAE0 /* Models */ = {
+ isa = PBXGroup;
+ children = (
+ 7A49F50527D406CB00AEAAE0 /* VBrand.swift */,
+ 7A49F50627D406CB00AEAAE0 /* Vehicle.swift */,
+ 7A49F50727D406CB00AEAAE0 /* User.swift */,
+ 7A49F50827D406CB00AEAAE0 /* Response.swift */,
+ 7A49F50927D406CB00AEAAE0 /* Settings.swift */,
+ 7A49F50A27D406CB00AEAAE0 /* PlateNumber.swift */,
+ 7A49F50B27D406CB00AEAAE0 /* VName.swift */,
+ );
+ path = Models;
+ sourceTree = "";
+ };
/* End PBXGroup section */
+/* Begin PBXHeadersBuildPhase section */
+ 7A49F4D227D4064500AEAAE0 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 7A49F4E927D4064500AEAAE0 /* AutoCatCore.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
/* Begin PBXNativeTarget section */
- 7A40D5822691C6D8009B0BC4 /* AutoCat2 (iOS) */ = {
+ 7A49F49E27D4061900AEAAE0 /* AutoCat2 */ = {
isa = PBXNativeTarget;
- buildConfigurationList = 7A40D5AA2691C6D8009B0BC4 /* Build configuration list for PBXNativeTarget "AutoCat2 (iOS)" */;
+ buildConfigurationList = 7A49F4C927D4061B00AEAAE0 /* Build configuration list for PBXNativeTarget "AutoCat2" */;
buildPhases = (
- 7A40D57F2691C6D8009B0BC4 /* Sources */,
- 7A40D5802691C6D8009B0BC4 /* Frameworks */,
- 7A40D5812691C6D8009B0BC4 /* Resources */,
- 7A40D5D52691C7D3009B0BC4 /* Embed Frameworks */,
+ 7A49F49B27D4061900AEAAE0 /* Sources */,
+ 7A49F49C27D4061900AEAAE0 /* Frameworks */,
+ 7A49F49D27D4061900AEAAE0 /* Resources */,
+ 7A49F4F127D4064500AEAAE0 /* Embed Frameworks */,
);
buildRules = (
);
dependencies = (
+ 7A49F4EB27D4064500AEAAE0 /* PBXTargetDependency */,
);
- name = "AutoCat2 (iOS)";
+ name = AutoCat2;
packageProductDependencies = (
+ 7A48B26627D9442A004D1A4B /* PKHUD */,
+ 7A28283527E74C110049BDBF /* SwiftEntryKit */,
);
- productName = "AutoCat2 (iOS)";
- productReference = 7A40D5832691C6D8009B0BC4 /* AutoCat2.app */;
+ productName = AutoCat2;
+ productReference = 7A49F49F27D4061900AEAAE0 /* AutoCat2.app */;
productType = "com.apple.product-type.application";
};
- 7A40D5882691C6D8009B0BC4 /* AutoCat2 (macOS) */ = {
+ 7A49F4B427D4061B00AEAAE0 /* AutoCat2Tests */ = {
isa = PBXNativeTarget;
- buildConfigurationList = 7A40D5AD2691C6D8009B0BC4 /* Build configuration list for PBXNativeTarget "AutoCat2 (macOS)" */;
+ buildConfigurationList = 7A49F4CC27D4061B00AEAAE0 /* Build configuration list for PBXNativeTarget "AutoCat2Tests" */;
buildPhases = (
- 7A40D5852691C6D8009B0BC4 /* Sources */,
- 7A40D5862691C6D8009B0BC4 /* Frameworks */,
- 7A40D5872691C6D8009B0BC4 /* Resources */,
- 7A40D5DE2691C7EB009B0BC4 /* Embed Frameworks */,
+ 7A49F4B127D4061B00AEAAE0 /* Sources */,
+ 7A49F4B227D4061B00AEAAE0 /* Frameworks */,
+ 7A49F4B327D4061B00AEAAE0 /* Resources */,
);
buildRules = (
);
dependencies = (
- );
- name = "AutoCat2 (macOS)";
- packageProductDependencies = (
- );
- productName = "AutoCat2 (macOS)";
- productReference = 7A40D5892691C6D8009B0BC4 /* AutoCat2.app */;
- productType = "com.apple.product-type.application";
- };
- 7A40D58D2691C6D8009B0BC4 /* Tests iOS */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = 7A40D5B02691C6D8009B0BC4 /* Build configuration list for PBXNativeTarget "Tests iOS" */;
- buildPhases = (
- 7A40D58A2691C6D8009B0BC4 /* Sources */,
- 7A40D58B2691C6D8009B0BC4 /* Frameworks */,
- 7A40D58C2691C6D8009B0BC4 /* Resources */,
- );
- buildRules = (
- );
- dependencies = (
- 7A40D5902691C6D8009B0BC4 /* PBXTargetDependency */,
- );
- name = "Tests iOS";
- productName = "Tests iOS";
- productReference = 7A40D58E2691C6D8009B0BC4 /* Tests iOS.xctest */;
- productType = "com.apple.product-type.bundle.ui-testing";
- };
- 7A40D5972691C6D8009B0BC4 /* Tests macOS */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = 7A40D5B32691C6D8009B0BC4 /* Build configuration list for PBXNativeTarget "Tests macOS" */;
- buildPhases = (
- 7A40D5942691C6D8009B0BC4 /* Sources */,
- 7A40D5952691C6D8009B0BC4 /* Frameworks */,
- 7A40D5962691C6D8009B0BC4 /* Resources */,
- );
- buildRules = (
- );
- dependencies = (
- 7A40D59A2691C6D8009B0BC4 /* PBXTargetDependency */,
- );
- name = "Tests macOS";
- productName = "Tests macOS";
- productReference = 7A40D5982691C6D8009B0BC4 /* Tests macOS.xctest */;
- productType = "com.apple.product-type.bundle.ui-testing";
- };
- 7A40D5F22693A63A009B0BC4 /* AutoCat2Tests */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = 7A40D5F92693A63A009B0BC4 /* Build configuration list for PBXNativeTarget "AutoCat2Tests" */;
- buildPhases = (
- 7A40D5EF2693A63A009B0BC4 /* Sources */,
- 7A40D5F02693A63A009B0BC4 /* Frameworks */,
- 7A40D5F12693A63A009B0BC4 /* Resources */,
- );
- buildRules = (
- );
- dependencies = (
- 7A40D5F82693A63A009B0BC4 /* PBXTargetDependency */,
+ 7A49F4B727D4061B00AEAAE0 /* PBXTargetDependency */,
);
name = AutoCat2Tests;
productName = AutoCat2Tests;
- productReference = 7A40D5F32693A63A009B0BC4 /* AutoCat2Tests.xctest */;
+ productReference = 7A49F4B527D4061B00AEAAE0 /* AutoCat2Tests.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
+ 7A49F4BE27D4061B00AEAAE0 /* AutoCat2UITests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 7A49F4CF27D4061B00AEAAE0 /* Build configuration list for PBXNativeTarget "AutoCat2UITests" */;
+ buildPhases = (
+ 7A49F4BB27D4061B00AEAAE0 /* Sources */,
+ 7A49F4BC27D4061B00AEAAE0 /* Frameworks */,
+ 7A49F4BD27D4061B00AEAAE0 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 7A49F4C127D4061B00AEAAE0 /* PBXTargetDependency */,
+ );
+ name = AutoCat2UITests;
+ productName = AutoCat2UITests;
+ productReference = 7A49F4BF27D4061B00AEAAE0 /* AutoCat2UITests.xctest */;
+ productType = "com.apple.product-type.bundle.ui-testing";
+ };
+ 7A49F4D627D4064500AEAAE0 /* AutoCatCore */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 7A49F4EE27D4064500AEAAE0 /* Build configuration list for PBXNativeTarget "AutoCatCore" */;
+ buildPhases = (
+ 7A49F4D227D4064500AEAAE0 /* Headers */,
+ 7A49F4D327D4064500AEAAE0 /* Sources */,
+ 7A49F4D427D4064500AEAAE0 /* Frameworks */,
+ 7A49F4D527D4064500AEAAE0 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = AutoCatCore;
+ productName = AutoCatCore;
+ productReference = 7A49F4D727D4064500AEAAE0 /* AutoCatCore.framework */;
+ productType = "com.apple.product-type.framework";
+ };
+ 7A49F4DF27D4064500AEAAE0 /* AutoCatCoreTests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 7A49F4F227D4064500AEAAE0 /* Build configuration list for PBXNativeTarget "AutoCatCoreTests" */;
+ buildPhases = (
+ 7A49F4DC27D4064500AEAAE0 /* Sources */,
+ 7A49F4DD27D4064500AEAAE0 /* Frameworks */,
+ 7A49F4DE27D4064500AEAAE0 /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 7A49F4E327D4064500AEAAE0 /* PBXTargetDependency */,
+ 7A49F4E527D4064500AEAAE0 /* PBXTargetDependency */,
+ );
+ name = AutoCatCoreTests;
+ productName = AutoCatCoreTests;
+ productReference = 7A49F4E027D4064500AEAAE0 /* AutoCatCoreTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
- 7A40D5742691C6D6009B0BC4 /* Project object */ = {
+ 7A49F49727D4061900AEAAE0 /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = 1;
- LastSwiftUpdateCheck = 1300;
- LastUpgradeCheck = 1310;
+ LastSwiftUpdateCheck = 1320;
+ LastUpgradeCheck = 1320;
TargetAttributes = {
- 7A40D5822691C6D8009B0BC4 = {
- CreatedOnToolsVersion = 13.0;
+ 7A49F49E27D4061900AEAAE0 = {
+ CreatedOnToolsVersion = 13.2.1;
};
- 7A40D5882691C6D8009B0BC4 = {
- CreatedOnToolsVersion = 13.0;
+ 7A49F4B427D4061B00AEAAE0 = {
+ CreatedOnToolsVersion = 13.2.1;
+ TestTargetID = 7A49F49E27D4061900AEAAE0;
};
- 7A40D58D2691C6D8009B0BC4 = {
- CreatedOnToolsVersion = 13.0;
- TestTargetID = 7A40D5822691C6D8009B0BC4;
+ 7A49F4BE27D4061B00AEAAE0 = {
+ CreatedOnToolsVersion = 13.2.1;
+ TestTargetID = 7A49F49E27D4061900AEAAE0;
};
- 7A40D5972691C6D8009B0BC4 = {
- CreatedOnToolsVersion = 13.0;
- TestTargetID = 7A40D5882691C6D8009B0BC4;
+ 7A49F4D627D4064500AEAAE0 = {
+ CreatedOnToolsVersion = 13.2.1;
};
- 7A40D5F22693A63A009B0BC4 = {
- CreatedOnToolsVersion = 13.0;
- TestTargetID = 7A40D5822691C6D8009B0BC4;
+ 7A49F4DF27D4064500AEAAE0 = {
+ CreatedOnToolsVersion = 13.2.1;
+ TestTargetID = 7A49F49E27D4061900AEAAE0;
};
};
};
- buildConfigurationList = 7A40D5772691C6D6009B0BC4 /* Build configuration list for PBXProject "AutoCat2" */;
+ buildConfigurationList = 7A49F49A27D4061900AEAAE0 /* Build configuration list for PBXProject "AutoCat2" */;
compatibilityVersion = "Xcode 13.0";
developmentRegion = en;
hasScannedForEncodings = 0;
@@ -572,201 +555,201 @@
en,
Base,
);
- mainGroup = 7A40D5732691C6D6009B0BC4;
+ mainGroup = 7A49F49627D4061900AEAAE0;
packageReferences = (
+ 7A48B26527D9442A004D1A4B /* XCRemoteSwiftPackageReference "PKHUD" */,
+ 7A28283427E74C110049BDBF /* XCRemoteSwiftPackageReference "SwiftEntryKit" */,
);
- productRefGroup = 7A40D5842691C6D8009B0BC4 /* Products */;
+ productRefGroup = 7A49F4A027D4061900AEAAE0 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
- 7A40D5822691C6D8009B0BC4 /* AutoCat2 (iOS) */,
- 7A40D5882691C6D8009B0BC4 /* AutoCat2 (macOS) */,
- 7A40D58D2691C6D8009B0BC4 /* Tests iOS */,
- 7A40D5972691C6D8009B0BC4 /* Tests macOS */,
- 7A40D5F22693A63A009B0BC4 /* AutoCat2Tests */,
+ 7A49F49E27D4061900AEAAE0 /* AutoCat2 */,
+ 7A49F4B427D4061B00AEAAE0 /* AutoCat2Tests */,
+ 7A49F4BE27D4061B00AEAAE0 /* AutoCat2UITests */,
+ 7A49F4D627D4064500AEAAE0 /* AutoCatCore */,
+ 7A49F4DF27D4064500AEAAE0 /* AutoCatCoreTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
- 7A40D5812691C6D8009B0BC4 /* Resources */ = {
+ 7A49F49D27D4061900AEAAE0 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- 7AFADDAF274A64DD00D53EFC /* RoadNumbers.otf in Resources */,
- 7A40D5A62691C6D8009B0BC4 /* Assets.xcassets in Resources */,
- 7AFADDB1274A64DD00D53EFC /* RoadNumbers2.0.otf in Resources */,
+ 7A24C19727EE212E00049E7F /* RoadNumbers.otf in Resources */,
+ 7A49F4AF27D4061A00AEAAE0 /* LaunchScreen.storyboard in Resources */,
+ 7A24C19827EE212E00049E7F /* RoadNumbers2.0.otf in Resources */,
+ 7A49F4AC27D4061A00AEAAE0 /* Assets.xcassets in Resources */,
+ 7A49F4AA27D4061900AEAAE0 /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
- 7A40D5872691C6D8009B0BC4 /* Resources */ = {
- isa = PBXResourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 7AFADDB0274A64DD00D53EFC /* RoadNumbers.otf in Resources */,
- 7A40D5A72691C6D8009B0BC4 /* Assets.xcassets in Resources */,
- 7AFADDB2274A64DD00D53EFC /* RoadNumbers2.0.otf in Resources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
- 7A40D58C2691C6D8009B0BC4 /* Resources */ = {
+ 7A49F4B327D4061B00AEAAE0 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
- 7A40D5962691C6D8009B0BC4 /* Resources */ = {
+ 7A49F4BD27D4061B00AEAAE0 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
- 7A40D5F12693A63A009B0BC4 /* Resources */ = {
+ 7A49F4D527D4064500AEAAE0 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 7A49F4DE27D4064500AEAAE0 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- 7A503C03269F382F002C1A0D /* login_success.json in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
- 7A40D57F2691C6D8009B0BC4 /* Sources */ = {
+ 7A49F49B27D4061900AEAAE0 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- 7A40D5E926938BEC009B0BC4 /* AuthView.swift in Sources */,
- 7A971F2326ADF74B007E527B /* MainView.swift in Sources */,
- 7ADE63732735E27200A152FE /* VBrand.swift in Sources */,
- 7A971F0D26AD7D4C007E527B /* AnyEncodable.swift in Sources */,
- 7ACD05D72695C08A00557667 /* Constants.swift in Sources */,
- 7A40D5E326924B09009B0BC4 /* Settings.swift in Sources */,
- 7ADE637827368C4600A152FE /* VehicleService.swift in Sources */,
- 7AEFAEED26985A3400ED2C85 /* ACProgressView.swift in Sources */,
- 7A40D5A02691C6D8009B0BC4 /* AutoCat2App.swift in Sources */,
- 7A683999269612EA00B2188A /* Response.swift in Sources */,
- 7A2329BF26AF140F00264CFA /* CheckView.swift in Sources */,
- 7A40D60826998DCF009B0BC4 /* Alert.swift in Sources */,
- 7A2329C226AF141E00264CFA /* SearchView.swift in Sources */,
- 7ADE637B273692F300A152FE /* StorageService.swift in Sources */,
- 7ADE63712735E1FF00A152FE /* VName.swift in Sources */,
- 7A40D5A42691C6D8009B0BC4 /* Persistence.swift in Sources */,
- 7A971F2026ADC351007E527B /* ApiError.swift in Sources */,
- 7A2329CB26AF15AC00264CFA /* ReportView.swift in Sources */,
- 7AAEBD35274A47C500230C28 /* PlateNumberView.swift in Sources */,
- 7A40D5ED2693A1EA009B0BC4 /* AuthVM.swift in Sources */,
- 7A40D59E2691C6D8009B0BC4 /* AutoCat2.xcdatamodeld in Sources */,
- 7AFADDA7274A49DB00D53EFC /* PlateNumber.swift in Sources */,
- 7ABC05A826B05AF9004BB5A7 /* Vehicle.swift in Sources */,
- 7A2329B926AF122400264CFA /* MainViewSmall.swift in Sources */,
- 7A2329C826AF143F00264CFA /* RecordsView.swift in Sources */,
- 7A40D5E126924AEC009B0BC4 /* User.swift in Sources */,
- 7A40D5FE2693A91F009B0BC4 /* CocoaError.swift in Sources */,
- 7A40D6022694FF5D009B0BC4 /* Api.swift in Sources */,
- 7A40D5A22691C6D8009B0BC4 /* ContentView.swift in Sources */,
- 7A2329C526AF142900264CFA /* SettingsView.swift in Sources */,
+ 7A9F2AC327E71531006492A9 /* ACTabBarController.swift in Sources */,
+ 7A28283327E7263B0049BDBF /* UIStackView.swift in Sources */,
+ 7A49F4A727D4061900AEAAE0 /* ViewController.swift in Sources */,
+ 7A49F4A327D4061900AEAAE0 /* AppDelegate.swift in Sources */,
+ 7A49F4A527D4061900AEAAE0 /* SceneDelegate.swift in Sources */,
+ 6841AF924E165F1B3A3B5FB5 /* AuthController.swift in Sources */,
+ 6841A592745CDD869709EFA7 /* MainTabController.swift in Sources */,
+ 6841A8FF53F0AADF96B138C1 /* UIControl.swift in Sources */,
+ 6841A63ECAC11B8956C7539D /* ACButton.swift in Sources */,
+ 6841A20034E0A9378C3B4BB4 /* ACTextField.swift in Sources */,
+ 6841A80BB89BFD8D18E79680 /* UITextField.swift in Sources */,
+ 7A24C19F27EE26B900049E7F /* CenterTextLayer.swift in Sources */,
+ 6841A5FE3E4927BF0EFF19F5 /* UIViewController.swift in Sources */,
+ 7A28282F27E720AC0049BDBF /* ACTabBarButton.swift in Sources */,
+ 6841A0EE0ECCDB3519F728E6 /* HistoryController.swift in Sources */,
+ 7A28283127E721A70049BDBF /* UIView.swift in Sources */,
+ 6841A35D2CC223CA7DCD51A2 /* SettingsController.swift in Sources */,
+ 7A28283827E74D930049BDBF /* CheckController.swift in Sources */,
+ 6841A7D2375D35B0102D7DEC /* SwiftMaskTextfield.swift in Sources */,
+ 6841ABD5E4B126DEF3612BBD /* PNKeyboard.swift in Sources */,
+ 7A24C19C27EE25B400049E7F /* PlateView.swift in Sources */,
+ 7A24C19D27EE25B400049E7F /* FlagLayer.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
- 7A40D5852691C6D8009B0BC4 /* Sources */ = {
+ 7A49F4B127D4061B00AEAAE0 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- 7AAEBD36274A47C600230C28 /* PlateNumberView.swift in Sources */,
- 7ADE637927368C4600A152FE /* VehicleService.swift in Sources */,
- 7A40D5EA26938BEC009B0BC4 /* AuthView.swift in Sources */,
- 7A971F2426ADF74B007E527B /* MainView.swift in Sources */,
- 7ADE63742735E27200A152FE /* VBrand.swift in Sources */,
- 7A971F0E26AD7D4C007E527B /* AnyEncodable.swift in Sources */,
- 7ACD05D82695C08A00557667 /* Constants.swift in Sources */,
- 7A2329BD26AF123300264CFA /* MainViewBig.swift in Sources */,
- 7A40D5A12691C6D8009B0BC4 /* AutoCat2App.swift in Sources */,
- 7AEFAEEE26985A3400ED2C85 /* ACProgressView.swift in Sources */,
- 7A40D5A52691C6D8009B0BC4 /* Persistence.swift in Sources */,
- 7AFADDA8274A49DB00D53EFC /* PlateNumber.swift in Sources */,
- 7A68399A269612EA00B2188A /* Response.swift in Sources */,
- 7A2329C026AF140F00264CFA /* CheckView.swift in Sources */,
- 7A40D60926998DCF009B0BC4 /* Alert.swift in Sources */,
- 7A2329C326AF141E00264CFA /* SearchView.swift in Sources */,
- 7A40D5E526924B0C009B0BC4 /* User.swift in Sources */,
- 7A971F2126ADC351007E527B /* ApiError.swift in Sources */,
- 7A2329CC26AF15AC00264CFA /* ReportView.swift in Sources */,
- 7ADE637C273692F300A152FE /* StorageService.swift in Sources */,
- 7ADE637F2738143000A152FE /* CheckNumberPopup.swift in Sources */,
- 7A40D5EE2693A1EA009B0BC4 /* AuthVM.swift in Sources */,
- 7A40D59F2691C6D8009B0BC4 /* AutoCat2.xcdatamodeld in Sources */,
- 7ABC05A926B05AF9004BB5A7 /* Vehicle.swift in Sources */,
- 7A2329BA26AF122400264CFA /* MainViewSmall.swift in Sources */,
- 7A2329C926AF143F00264CFA /* RecordsView.swift in Sources */,
- 7A40D5A32691C6D8009B0BC4 /* ContentView.swift in Sources */,
- 7ADE63752735E27D00A152FE /* VName.swift in Sources */,
- 7A40D5FF2693A91F009B0BC4 /* CocoaError.swift in Sources */,
- 7A40D6032694FF5D009B0BC4 /* Api.swift in Sources */,
- 7A40D5E426924B09009B0BC4 /* Settings.swift in Sources */,
- 7A2329C626AF142900264CFA /* SettingsView.swift in Sources */,
+ 7A49F4BA27D4061B00AEAAE0 /* AutoCat2Tests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
- 7A40D58A2691C6D8009B0BC4 /* Sources */ = {
+ 7A49F4BB27D4061B00AEAAE0 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- 7A40D5932691C6D8009B0BC4 /* Tests_iOS.swift in Sources */,
+ 7A49F4C627D4061B00AEAAE0 /* AutoCat2UITestsLaunchTests.swift in Sources */,
+ 7A49F4C427D4061B00AEAAE0 /* AutoCat2UITests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
- 7A40D5942691C6D8009B0BC4 /* Sources */ = {
+ 7A49F4D327D4064500AEAAE0 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- 7A40D59D2691C6D8009B0BC4 /* Tests_macOS.swift in Sources */,
+ 7A49F50D27D406CB00AEAAE0 /* Vehicle.swift in Sources */,
+ 7A49F50327D406C300AEAAE0 /* VehicleService.swift in Sources */,
+ 7A49F4DB27D4064500AEAAE0 /* AutoCatCore.docc in Sources */,
+ 7A49F50227D406C300AEAAE0 /* StorageService.swift in Sources */,
+ 7A49F4FE27D406BA00AEAAE0 /* AnyEncodable.swift in Sources */,
+ 7A49F51227D406CB00AEAAE0 /* VName.swift in Sources */,
+ 7A49F51127D406CB00AEAAE0 /* PlateNumber.swift in Sources */,
+ 7A49F50C27D406CB00AEAAE0 /* VBrand.swift in Sources */,
+ 7A49F51027D406CB00AEAAE0 /* Settings.swift in Sources */,
+ 7A49F4F927D406B200AEAAE0 /* Constants.swift in Sources */,
+ 7A49F50F27D406CB00AEAAE0 /* Response.swift in Sources */,
+ 7A49F4FB27D406B200AEAAE0 /* Api.swift in Sources */,
+ 7A49F51527D40C6100AEAAE0 /* AutoCat2.xcdatamodeld in Sources */,
+ 7A49F50E27D406CB00AEAAE0 /* User.swift in Sources */,
+ 7A49F4FA27D406B200AEAAE0 /* ApiError.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
- 7A40D5EF2693A63A009B0BC4 /* Sources */ = {
+ 7A49F4DC27D4064500AEAAE0 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- 7A40D60C2699A070009B0BC4 /* MockURLProtocol.swift in Sources */,
- 7A971F0826AD7084007E527B /* LoginMethodMock.swift in Sources */,
- 7AF552D92696E5C100578083 /* ApiTests.swift in Sources */,
- 7A971F0A26AD74FD007E527B /* ApiMethodMockProtocol.swift in Sources */,
- 7A40D5F62693A63A009B0BC4 /* SettingsTests.swift in Sources */,
- 7A971F0626AD6F2F007E527B /* ApiMethodMock.swift in Sources */,
+ 7A49F4E827D4064500AEAAE0 /* AutoCatCoreTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
- 7A40D5902691C6D8009B0BC4 /* PBXTargetDependency */ = {
+ 7A49F4B727D4061B00AEAAE0 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
- target = 7A40D5822691C6D8009B0BC4 /* AutoCat2 (iOS) */;
- targetProxy = 7A40D58F2691C6D8009B0BC4 /* PBXContainerItemProxy */;
+ target = 7A49F49E27D4061900AEAAE0 /* AutoCat2 */;
+ targetProxy = 7A49F4B627D4061B00AEAAE0 /* PBXContainerItemProxy */;
};
- 7A40D59A2691C6D8009B0BC4 /* PBXTargetDependency */ = {
+ 7A49F4C127D4061B00AEAAE0 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
- target = 7A40D5882691C6D8009B0BC4 /* AutoCat2 (macOS) */;
- targetProxy = 7A40D5992691C6D8009B0BC4 /* PBXContainerItemProxy */;
+ target = 7A49F49E27D4061900AEAAE0 /* AutoCat2 */;
+ targetProxy = 7A49F4C027D4061B00AEAAE0 /* PBXContainerItemProxy */;
};
- 7A40D5F82693A63A009B0BC4 /* PBXTargetDependency */ = {
+ 7A49F4E327D4064500AEAAE0 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
- target = 7A40D5822691C6D8009B0BC4 /* AutoCat2 (iOS) */;
- targetProxy = 7A40D5F72693A63A009B0BC4 /* PBXContainerItemProxy */;
+ target = 7A49F4D627D4064500AEAAE0 /* AutoCatCore */;
+ targetProxy = 7A49F4E227D4064500AEAAE0 /* PBXContainerItemProxy */;
+ };
+ 7A49F4E527D4064500AEAAE0 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 7A49F49E27D4061900AEAAE0 /* AutoCat2 */;
+ targetProxy = 7A49F4E427D4064500AEAAE0 /* PBXContainerItemProxy */;
+ };
+ 7A49F4EB27D4064500AEAAE0 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 7A49F4D627D4064500AEAAE0 /* AutoCatCore */;
+ targetProxy = 7A49F4EA27D4064500AEAAE0 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
+/* Begin PBXVariantGroup section */
+ 7A49F4A827D4061900AEAAE0 /* Main.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 7A49F4A927D4061900AEAAE0 /* Base */,
+ );
+ name = Main.storyboard;
+ sourceTree = "";
+ };
+ 7A49F4AD27D4061A00AEAAE0 /* LaunchScreen.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 7A49F4AE27D4061A00AEAAE0 /* Base */,
+ );
+ name = LaunchScreen.storyboard;
+ sourceTree = "";
+ };
+/* End PBXVariantGroup section */
+
/* Begin XCBuildConfiguration section */
- 7A40D5A82691C6D8009B0BC4 /* Debug */ = {
+ 7A49F4C727D4061B00AEAAE0 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
@@ -811,23 +794,23 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 15.0;
- MACOSX_DEPLOYMENT_TARGET = 12.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 15.2;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
- 7A40D5A92691C6D8009B0BC4 /* Release */ = {
+ 7A49F4C827D4061B00AEAAE0 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
@@ -866,260 +849,89 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 15.0;
- MACOSX_DEPLOYMENT_TARGET = 12.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 15.2;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
+ SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
- };
- name = Release;
- };
- 7A40D5AB2691C6D8009B0BC4 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
- CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 1;
- DEVELOPMENT_TEAM = 46DTTB8X4S;
- ENABLE_PREVIEWS = YES;
- GENERATE_INFOPLIST_FILE = YES;
- INFOPLIST_FILE = "AutoCat2--iOS--Info.plist";
- INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
- INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
- INFOPLIST_KEY_UILaunchScreen_Generation = YES;
- INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
- INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
- IPHONEOS_DEPLOYMENT_TARGET = 15.0;
- LD_RUNPATH_SEARCH_PATHS = (
- "$(inherited)",
- "@executable_path/Frameworks",
- );
- MARKETING_VERSION = 1.0;
- PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCat2;
- PRODUCT_NAME = AutoCat2;
- SDKROOT = iphoneos;
- SWIFT_EMIT_LOC_STRINGS = YES;
- SWIFT_VERSION = 5.0;
- TARGETED_DEVICE_FAMILY = "1,2";
- };
- name = Debug;
- };
- 7A40D5AC2691C6D8009B0BC4 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
- CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 1;
- DEVELOPMENT_TEAM = 46DTTB8X4S;
- ENABLE_PREVIEWS = YES;
- GENERATE_INFOPLIST_FILE = YES;
- INFOPLIST_FILE = "AutoCat2--iOS--Info.plist";
- INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
- INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
- INFOPLIST_KEY_UILaunchScreen_Generation = YES;
- INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
- INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
- IPHONEOS_DEPLOYMENT_TARGET = 15.0;
- LD_RUNPATH_SEARCH_PATHS = (
- "$(inherited)",
- "@executable_path/Frameworks",
- );
- MARKETING_VERSION = 1.0;
- PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCat2;
- PRODUCT_NAME = AutoCat2;
- SDKROOT = iphoneos;
- SWIFT_EMIT_LOC_STRINGS = YES;
- SWIFT_VERSION = 5.0;
- TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
- 7A40D5AE2691C6D8009B0BC4 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
- CODE_SIGN_ENTITLEMENTS = "AutoCat2 (macOS).entitlements";
- CODE_SIGN_IDENTITY = "Apple Development";
- CODE_SIGN_STYLE = Automatic;
- COMBINE_HIDPI_IMAGES = YES;
- CURRENT_PROJECT_VERSION = 1;
- DEVELOPMENT_TEAM = 46DTTB8X4S;
- ENABLE_APP_SANDBOX = YES;
- ENABLE_HARDENED_RUNTIME = YES;
- ENABLE_PREVIEWS = YES;
- ENABLE_USER_SELECTED_FILES = readonly;
- GENERATE_INFOPLIST_FILE = YES;
- INFOPLIST_FILE = "AutoCat2--macOS--Info.plist";
- INFOPLIST_KEY_NSHumanReadableCopyright = "";
- LD_RUNPATH_SEARCH_PATHS = (
- "$(inherited)",
- "@executable_path/../Frameworks",
- );
- MACOSX_DEPLOYMENT_TARGET = 12.0;
- MARKETING_VERSION = 1.0;
- PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCat2;
- PRODUCT_NAME = AutoCat2;
- SDKROOT = macosx;
- SWIFT_EMIT_LOC_STRINGS = YES;
- SWIFT_VERSION = 5.0;
- };
- name = Debug;
- };
- 7A40D5AF2691C6D8009B0BC4 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
- CODE_SIGN_ENTITLEMENTS = "AutoCat2 (macOS).entitlements";
- CODE_SIGN_IDENTITY = "Apple Development";
- CODE_SIGN_STYLE = Automatic;
- COMBINE_HIDPI_IMAGES = YES;
- CURRENT_PROJECT_VERSION = 1;
- DEVELOPMENT_TEAM = 46DTTB8X4S;
- ENABLE_APP_SANDBOX = YES;
- ENABLE_HARDENED_RUNTIME = YES;
- ENABLE_PREVIEWS = YES;
- ENABLE_USER_SELECTED_FILES = readonly;
- GENERATE_INFOPLIST_FILE = YES;
- INFOPLIST_FILE = "AutoCat2--macOS--Info.plist";
- INFOPLIST_KEY_NSHumanReadableCopyright = "";
- LD_RUNPATH_SEARCH_PATHS = (
- "$(inherited)",
- "@executable_path/../Frameworks",
- );
- MACOSX_DEPLOYMENT_TARGET = 12.0;
- MARKETING_VERSION = 1.0;
- PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCat2;
- PRODUCT_NAME = AutoCat2;
- SDKROOT = macosx;
- SWIFT_EMIT_LOC_STRINGS = YES;
- SWIFT_VERSION = 5.0;
- };
- name = Release;
- };
- 7A40D5B12691C6D8009B0BC4 /* Debug */ = {
+ 7A49F4CA27D4061B00AEAAE0 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 46DTTB8X4S;
GENERATE_INFOPLIST_FILE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 15.0;
+ INFOPLIST_FILE = AutoCat2/Info.plist;
+ INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
+ INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
+ INFOPLIST_KEY_UIMainStoryboardFile = Main;
+ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+ IPHONEOS_DEPLOYMENT_TARGET = 14.7;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
- "@loader_path/Frameworks",
);
MARKETING_VERSION = 1.0;
- PRODUCT_BUNDLE_IDENTIFIER = "pro.aliencat.Tests-iOS";
+ PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCat2;
PRODUCT_NAME = "$(TARGET_NAME)";
- SDKROOT = iphoneos;
- SWIFT_EMIT_LOC_STRINGS = NO;
+ SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
- TARGETED_DEVICE_FAMILY = "1,2";
- TEST_TARGET_NAME = "AutoCat2 (iOS)";
+ TARGETED_DEVICE_FAMILY = 1;
};
name = Debug;
};
- 7A40D5B22691C6D8009B0BC4 /* Release */ = {
+ 7A49F4CB27D4061B00AEAAE0 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 46DTTB8X4S;
GENERATE_INFOPLIST_FILE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 15.0;
+ INFOPLIST_FILE = AutoCat2/Info.plist;
+ INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
+ INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
+ INFOPLIST_KEY_UIMainStoryboardFile = Main;
+ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+ INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+ IPHONEOS_DEPLOYMENT_TARGET = 14.7;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
- "@loader_path/Frameworks",
);
MARKETING_VERSION = 1.0;
- PRODUCT_BUNDLE_IDENTIFIER = "pro.aliencat.Tests-iOS";
+ PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCat2;
PRODUCT_NAME = "$(TARGET_NAME)";
- SDKROOT = iphoneos;
- SWIFT_EMIT_LOC_STRINGS = NO;
+ SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
- TARGETED_DEVICE_FAMILY = "1,2";
- TEST_TARGET_NAME = "AutoCat2 (iOS)";
- VALIDATE_PRODUCT = YES;
+ TARGETED_DEVICE_FAMILY = 1;
};
name = Release;
};
- 7A40D5B42691C6D8009B0BC4 /* Debug */ = {
+ 7A49F4CD27D4061B00AEAAE0 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
- CODE_SIGN_STYLE = Automatic;
- COMBINE_HIDPI_IMAGES = YES;
- CURRENT_PROJECT_VERSION = 1;
- DEVELOPMENT_TEAM = 46DTTB8X4S;
- GENERATE_INFOPLIST_FILE = YES;
- LD_RUNPATH_SEARCH_PATHS = (
- "$(inherited)",
- "@executable_path/../Frameworks",
- "@loader_path/../Frameworks",
- );
- MACOSX_DEPLOYMENT_TARGET = 12.0;
- MARKETING_VERSION = 1.0;
- PRODUCT_BUNDLE_IDENTIFIER = "pro.aliencat.Tests-macOS";
- PRODUCT_NAME = "$(TARGET_NAME)";
- SDKROOT = macosx;
- SWIFT_EMIT_LOC_STRINGS = NO;
- SWIFT_VERSION = 5.0;
- TEST_TARGET_NAME = "AutoCat2 (macOS)";
- };
- name = Debug;
- };
- 7A40D5B52691C6D8009B0BC4 /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
- CODE_SIGN_STYLE = Automatic;
- COMBINE_HIDPI_IMAGES = YES;
- CURRENT_PROJECT_VERSION = 1;
- DEVELOPMENT_TEAM = 46DTTB8X4S;
- GENERATE_INFOPLIST_FILE = YES;
- LD_RUNPATH_SEARCH_PATHS = (
- "$(inherited)",
- "@executable_path/../Frameworks",
- "@loader_path/../Frameworks",
- );
- MACOSX_DEPLOYMENT_TARGET = 12.0;
- MARKETING_VERSION = 1.0;
- PRODUCT_BUNDLE_IDENTIFIER = "pro.aliencat.Tests-macOS";
- PRODUCT_NAME = "$(TARGET_NAME)";
- SDKROOT = macosx;
- SWIFT_EMIT_LOC_STRINGS = NO;
- SWIFT_VERSION = 5.0;
- TEST_TARGET_NAME = "AutoCat2 (macOS)";
- };
- name = Release;
- };
- 7A40D5FA2693A63A009B0BC4 /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 46DTTB8X4S;
GENERATE_INFOPLIST_FILE = YES;
- LD_RUNPATH_SEARCH_PATHS = (
- "$(inherited)",
- "@executable_path/Frameworks",
- "@loader_path/Frameworks",
- );
+ IPHONEOS_DEPLOYMENT_TARGET = 15.2;
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCat2Tests;
PRODUCT_NAME = "$(TARGET_NAME)";
- SDKROOT = iphoneos;
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
@@ -1127,102 +939,263 @@
};
name = Debug;
};
- 7A40D5FB2693A63A009B0BC4 /* Release */ = {
+ 7A49F4CE27D4061B00AEAAE0 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
+ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 46DTTB8X4S;
GENERATE_INFOPLIST_FILE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 15.2;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCat2Tests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_EMIT_LOC_STRINGS = NO;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AutoCat2.app/AutoCat2";
+ };
+ name = Release;
+ };
+ 7A49F4D027D4061B00AEAAE0 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = 46DTTB8X4S;
+ GENERATE_INFOPLIST_FILE = YES;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCat2UITests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_EMIT_LOC_STRINGS = NO;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ TEST_TARGET_NAME = AutoCat2;
+ };
+ name = Debug;
+ };
+ 7A49F4D127D4061B00AEAAE0 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = 46DTTB8X4S;
+ GENERATE_INFOPLIST_FILE = YES;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCat2UITests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_EMIT_LOC_STRINGS = NO;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ TEST_TARGET_NAME = AutoCat2;
+ };
+ name = Release;
+ };
+ 7A49F4EF27D4064500AEAAE0 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEFINES_MODULE = YES;
+ DEVELOPMENT_TEAM = 46DTTB8X4S;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ DYLIB_INSTALL_NAME_BASE = "@rpath";
+ GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_KEY_NSHumanReadableCopyright = "";
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ IPHONEOS_DEPLOYMENT_TARGET = 14.7;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
MARKETING_VERSION = 1.0;
- PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCat2Tests;
+ PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCatCore;
+ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
+ SKIP_INSTALL = YES;
+ SWIFT_EMIT_LOC_STRINGS = YES;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VERSIONING_SYSTEM = "apple-generic";
+ VERSION_INFO_PREFIX = "";
+ };
+ name = Debug;
+ };
+ 7A49F4F027D4064500AEAAE0 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEFINES_MODULE = YES;
+ DEVELOPMENT_TEAM = 46DTTB8X4S;
+ DYLIB_COMPATIBILITY_VERSION = 1;
+ DYLIB_CURRENT_VERSION = 1;
+ DYLIB_INSTALL_NAME_BASE = "@rpath";
+ GENERATE_INFOPLIST_FILE = YES;
+ INFOPLIST_KEY_NSHumanReadableCopyright = "";
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
+ IPHONEOS_DEPLOYMENT_TARGET = 14.7;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ "@loader_path/Frameworks",
+ );
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCatCore;
+ PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
+ SKIP_INSTALL = YES;
+ SWIFT_EMIT_LOC_STRINGS = YES;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VERSIONING_SYSTEM = "apple-generic";
+ VERSION_INFO_PREFIX = "";
+ };
+ name = Release;
+ };
+ 7A49F4F327D4064500AEAAE0 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = 46DTTB8X4S;
+ GENERATE_INFOPLIST_FILE = YES;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCatCoreTests;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_EMIT_LOC_STRINGS = NO;
+ SWIFT_VERSION = 5.0;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AutoCat2.app/AutoCat2";
+ };
+ name = Debug;
+ };
+ 7A49F4F427D4064500AEAAE0 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
+ CODE_SIGN_STYLE = Automatic;
+ CURRENT_PROJECT_VERSION = 1;
+ DEVELOPMENT_TEAM = 46DTTB8X4S;
+ GENERATE_INFOPLIST_FILE = YES;
+ MARKETING_VERSION = 1.0;
+ PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCatCoreTests;
PRODUCT_NAME = "$(TARGET_NAME)";
- SDKROOT = iphoneos;
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AutoCat2.app/AutoCat2";
- VALIDATE_PRODUCT = YES;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
- 7A40D5772691C6D6009B0BC4 /* Build configuration list for PBXProject "AutoCat2" */ = {
+ 7A49F49A27D4061900AEAAE0 /* Build configuration list for PBXProject "AutoCat2" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- 7A40D5A82691C6D8009B0BC4 /* Debug */,
- 7A40D5A92691C6D8009B0BC4 /* Release */,
+ 7A49F4C727D4061B00AEAAE0 /* Debug */,
+ 7A49F4C827D4061B00AEAAE0 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
- 7A40D5AA2691C6D8009B0BC4 /* Build configuration list for PBXNativeTarget "AutoCat2 (iOS)" */ = {
+ 7A49F4C927D4061B00AEAAE0 /* Build configuration list for PBXNativeTarget "AutoCat2" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- 7A40D5AB2691C6D8009B0BC4 /* Debug */,
- 7A40D5AC2691C6D8009B0BC4 /* Release */,
+ 7A49F4CA27D4061B00AEAAE0 /* Debug */,
+ 7A49F4CB27D4061B00AEAAE0 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
- 7A40D5AD2691C6D8009B0BC4 /* Build configuration list for PBXNativeTarget "AutoCat2 (macOS)" */ = {
+ 7A49F4CC27D4061B00AEAAE0 /* Build configuration list for PBXNativeTarget "AutoCat2Tests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- 7A40D5AE2691C6D8009B0BC4 /* Debug */,
- 7A40D5AF2691C6D8009B0BC4 /* Release */,
+ 7A49F4CD27D4061B00AEAAE0 /* Debug */,
+ 7A49F4CE27D4061B00AEAAE0 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
- 7A40D5B02691C6D8009B0BC4 /* Build configuration list for PBXNativeTarget "Tests iOS" */ = {
+ 7A49F4CF27D4061B00AEAAE0 /* Build configuration list for PBXNativeTarget "AutoCat2UITests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- 7A40D5B12691C6D8009B0BC4 /* Debug */,
- 7A40D5B22691C6D8009B0BC4 /* Release */,
+ 7A49F4D027D4061B00AEAAE0 /* Debug */,
+ 7A49F4D127D4061B00AEAAE0 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
- 7A40D5B32691C6D8009B0BC4 /* Build configuration list for PBXNativeTarget "Tests macOS" */ = {
+ 7A49F4EE27D4064500AEAAE0 /* Build configuration list for PBXNativeTarget "AutoCatCore" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- 7A40D5B42691C6D8009B0BC4 /* Debug */,
- 7A40D5B52691C6D8009B0BC4 /* Release */,
+ 7A49F4EF27D4064500AEAAE0 /* Debug */,
+ 7A49F4F027D4064500AEAAE0 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
- 7A40D5F92693A63A009B0BC4 /* Build configuration list for PBXNativeTarget "AutoCat2Tests" */ = {
+ 7A49F4F227D4064500AEAAE0 /* Build configuration list for PBXNativeTarget "AutoCatCoreTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
- 7A40D5FA2693A63A009B0BC4 /* Debug */,
- 7A40D5FB2693A63A009B0BC4 /* Release */,
+ 7A49F4F327D4064500AEAAE0 /* Debug */,
+ 7A49F4F427D4064500AEAAE0 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
+/* Begin XCRemoteSwiftPackageReference section */
+ 7A28283427E74C110049BDBF /* XCRemoteSwiftPackageReference "SwiftEntryKit" */ = {
+ isa = XCRemoteSwiftPackageReference;
+ repositoryURL = "https://github.com/huri000/SwiftEntryKit";
+ requirement = {
+ kind = upToNextMajorVersion;
+ minimumVersion = 2.0.0;
+ };
+ };
+ 7A48B26527D9442A004D1A4B /* XCRemoteSwiftPackageReference "PKHUD" */ = {
+ isa = XCRemoteSwiftPackageReference;
+ repositoryURL = "https://github.com/pkluz/PKHUD.git";
+ requirement = {
+ kind = upToNextMajorVersion;
+ minimumVersion = 5.0.0;
+ };
+ };
+/* End XCRemoteSwiftPackageReference section */
+
+/* Begin XCSwiftPackageProductDependency section */
+ 7A28283527E74C110049BDBF /* SwiftEntryKit */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 7A28283427E74C110049BDBF /* XCRemoteSwiftPackageReference "SwiftEntryKit" */;
+ productName = SwiftEntryKit;
+ };
+ 7A48B26627D9442A004D1A4B /* PKHUD */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 7A48B26527D9442A004D1A4B /* XCRemoteSwiftPackageReference "PKHUD" */;
+ productName = PKHUD;
+ };
+/* End XCSwiftPackageProductDependency section */
+
/* Begin XCVersionGroup section */
- 7A40D5792691C6D7009B0BC4 /* AutoCat2.xcdatamodeld */ = {
+ 7A49F51327D40C6100AEAAE0 /* AutoCat2.xcdatamodeld */ = {
isa = XCVersionGroup;
children = (
- 7A40D57A2691C6D7009B0BC4 /* Shared.xcdatamodel */,
+ 7A49F51427D40C6100AEAAE0 /* Shared.xcdatamodel */,
);
- currentVersion = 7A40D57A2691C6D7009B0BC4 /* Shared.xcdatamodel */;
+ currentVersion = 7A49F51427D40C6100AEAAE0 /* Shared.xcdatamodel */;
path = AutoCat2.xcdatamodeld;
sourceTree = "";
versionGroupType = wrapper.xcdatamodel;
};
/* End XCVersionGroup section */
};
- rootObject = 7A40D5742691C6D6009B0BC4 /* Project object */;
+ rootObject = 7A49F49727D4061900AEAAE0 /* Project object */;
}
diff --git a/AutoCat2.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/AutoCat2.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
new file mode 100644
index 0000000..d0c7372
--- /dev/null
+++ b/AutoCat2.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -0,0 +1,23 @@
+{
+ "pins" : [
+ {
+ "identity" : "pkhud",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/pkluz/PKHUD.git",
+ "state" : {
+ "revision" : "8fd26f23057c6bebd6695524b1c3e05e93aba571",
+ "version" : "5.4.0"
+ }
+ },
+ {
+ "identity" : "swiftentrykit",
+ "kind" : "remoteSourceControl",
+ "location" : "https://github.com/huri000/SwiftEntryKit",
+ "state" : {
+ "revision" : "5ad36cccf0c4b9fea32f4e9b17a8e38f07563ef0",
+ "version" : "2.0.0"
+ }
+ }
+ ],
+ "version" : 2
+}
diff --git a/AutoCat2.xcodeproj/xcuserdata/selim.xcuserdatad/xcschemes/xcschememanagement.plist b/AutoCat2.xcodeproj/xcuserdata/selim.xcuserdatad/xcschemes/xcschememanagement.plist
index a2751d7..973e834 100644
--- a/AutoCat2.xcodeproj/xcuserdata/selim.xcuserdatad/xcschemes/xcschememanagement.plist
+++ b/AutoCat2.xcodeproj/xcuserdata/selim.xcuserdatad/xcschemes/xcschememanagement.plist
@@ -4,39 +4,16 @@
SchemeUserState
- AutoCat2 (iOS).xcscheme_^#shared#^_
+ AutoCat2.xcscheme
orderHint
0
- AutoCat2 (macOS).xcscheme_^#shared#^_
+ AutoCatCore.xcscheme_^#shared#^_
orderHint
1
- AutoCatCore.xcscheme_^#shared#^_
-
- orderHint
- 2
-
-
- SuppressBuildableAutocreation
-
- 7A40D5822691C6D8009B0BC4
-
- primary
-
-
- 7A40D58D2691C6D8009B0BC4
-
- primary
-
-
- 7A40D5F22693A63A009B0BC4
-
- primary
-
-
diff --git a/AutoCat2/AppDelegate.swift b/AutoCat2/AppDelegate.swift
new file mode 100644
index 0000000..1c0c270
--- /dev/null
+++ b/AutoCat2/AppDelegate.swift
@@ -0,0 +1,36 @@
+//
+// AppDelegate.swift
+// AutoCat2
+//
+// Created by Selim Mustafaev on 05.03.2022.
+//
+
+import UIKit
+
+@main
+class AppDelegate: UIResponder, UIApplicationDelegate {
+
+
+
+ func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
+ // Override point for customization after application launch.
+ return true
+ }
+
+ // MARK: UISceneSession Lifecycle
+
+ func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
+ // Called when a new scene session is being created.
+ // Use this method to select a configuration to create the new scene with.
+ return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
+ }
+
+ func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) {
+ // Called when the user discards a scene session.
+ // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
+ // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
+ }
+
+
+}
+
diff --git a/Shared/Assets.xcassets/AccentColor.colorset/Contents.json b/AutoCat2/Assets.xcassets/AccentColor.colorset/Contents.json
similarity index 100%
rename from Shared/Assets.xcassets/AccentColor.colorset/Contents.json
rename to AutoCat2/Assets.xcassets/AccentColor.colorset/Contents.json
diff --git a/Shared/Assets.xcassets/AppIcon.appiconset/Contents.json b/AutoCat2/Assets.xcassets/AppIcon.appiconset/Contents.json
similarity index 65%
rename from Shared/Assets.xcassets/AppIcon.appiconset/Contents.json
rename to AutoCat2/Assets.xcassets/AppIcon.appiconset/Contents.json
index c136eaf..9221b9b 100644
--- a/Shared/Assets.xcassets/AppIcon.appiconset/Contents.json
+++ b/AutoCat2/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -89,56 +89,6 @@
"idiom" : "ios-marketing",
"scale" : "1x",
"size" : "1024x1024"
- },
- {
- "idiom" : "mac",
- "scale" : "1x",
- "size" : "16x16"
- },
- {
- "idiom" : "mac",
- "scale" : "2x",
- "size" : "16x16"
- },
- {
- "idiom" : "mac",
- "scale" : "1x",
- "size" : "32x32"
- },
- {
- "idiom" : "mac",
- "scale" : "2x",
- "size" : "32x32"
- },
- {
- "idiom" : "mac",
- "scale" : "1x",
- "size" : "128x128"
- },
- {
- "idiom" : "mac",
- "scale" : "2x",
- "size" : "128x128"
- },
- {
- "idiom" : "mac",
- "scale" : "1x",
- "size" : "256x256"
- },
- {
- "idiom" : "mac",
- "scale" : "2x",
- "size" : "256x256"
- },
- {
- "idiom" : "mac",
- "scale" : "1x",
- "size" : "512x512"
- },
- {
- "idiom" : "mac",
- "scale" : "2x",
- "size" : "512x512"
}
],
"info" : {
diff --git a/Shared/Assets.xcassets/Colors/Contents.json b/AutoCat2/Assets.xcassets/Colors/Contents.json
similarity index 100%
rename from Shared/Assets.xcassets/Colors/Contents.json
rename to AutoCat2/Assets.xcassets/Colors/Contents.json
diff --git a/Shared/Assets.xcassets/Colors/PlateForeground.colorset/Contents.json b/AutoCat2/Assets.xcassets/Colors/DarkKeyBackground.colorset/Contents.json
similarity index 61%
rename from Shared/Assets.xcassets/Colors/PlateForeground.colorset/Contents.json
rename to AutoCat2/Assets.xcassets/Colors/DarkKeyBackground.colorset/Contents.json
index 945ab6a..bb37c2e 100644
--- a/Shared/Assets.xcassets/Colors/PlateForeground.colorset/Contents.json
+++ b/AutoCat2/Assets.xcassets/Colors/DarkKeyBackground.colorset/Contents.json
@@ -2,13 +2,8 @@
"colors" : [
{
"color" : {
- "color-space" : "srgb",
- "components" : {
- "alpha" : "1.000",
- "blue" : "0.000",
- "green" : "0.000",
- "red" : "0.000"
- }
+ "platform" : "ios",
+ "reference" : "systemGray2Color"
},
"idiom" : "universal"
},
@@ -20,12 +15,12 @@
}
],
"color" : {
- "color-space" : "display-p3",
+ "color-space" : "srgb",
"components" : {
"alpha" : "1.000",
- "blue" : "0.866",
- "green" : "0.866",
- "red" : "0.866"
+ "blue" : "0.290",
+ "green" : "0.282",
+ "red" : "0.282"
}
},
"idiom" : "universal"
diff --git a/Shared/Assets.xcassets/Colors/PlateBackground.colorset/Contents.json b/AutoCat2/Assets.xcassets/Colors/KeyBackground.colorset/Contents.json
similarity index 78%
rename from Shared/Assets.xcassets/Colors/PlateBackground.colorset/Contents.json
rename to AutoCat2/Assets.xcassets/Colors/KeyBackground.colorset/Contents.json
index 2257e90..eb0fccd 100644
--- a/Shared/Assets.xcassets/Colors/PlateBackground.colorset/Contents.json
+++ b/AutoCat2/Assets.xcassets/Colors/KeyBackground.colorset/Contents.json
@@ -20,12 +20,12 @@
}
],
"color" : {
- "color-space" : "display-p3",
+ "color-space" : "srgb",
"components" : {
- "alpha" : "1.000",
- "blue" : "0.152",
- "green" : "0.152",
- "red" : "0.152"
+ "alpha" : "0.300",
+ "blue" : "1.000",
+ "green" : "1.000",
+ "red" : "1.000"
}
},
"idiom" : "universal"
diff --git a/Shared/Assets.xcassets/Contents.json b/AutoCat2/Assets.xcassets/Contents.json
similarity index 100%
rename from Shared/Assets.xcassets/Contents.json
rename to AutoCat2/Assets.xcassets/Contents.json
diff --git a/AutoCat2/Base.lproj/LaunchScreen.storyboard b/AutoCat2/Base.lproj/LaunchScreen.storyboard
new file mode 100644
index 0000000..865e932
--- /dev/null
+++ b/AutoCat2/Base.lproj/LaunchScreen.storyboard
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AutoCat2/Base.lproj/Main.storyboard b/AutoCat2/Base.lproj/Main.storyboard
new file mode 100644
index 0000000..25a7638
--- /dev/null
+++ b/AutoCat2/Base.lproj/Main.storyboard
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AutoCat2/Components/ACButton.swift b/AutoCat2/Components/ACButton.swift
new file mode 100644
index 0000000..2727e37
--- /dev/null
+++ b/AutoCat2/Components/ACButton.swift
@@ -0,0 +1,84 @@
+//
+// Created by Selim Mustafaev on 06.03.2022.
+//
+
+import UIKit
+
+enum ACButtonStyle {
+ case generic
+ case roundedBlue
+}
+
+class ACButton: UIButton {
+
+ private var style: ACButtonStyle = .generic
+
+ convenience init(style: ACButtonStyle = .roundedBlue, title: String, onTap: @escaping () -> Void) {
+ self.init()
+ self.style(style)
+ self.onTap(onTap)
+ self.title(title)
+ translatesAutoresizingMaskIntoConstraints = false
+ }
+
+ convenience init(style: ACButtonStyle = .roundedBlue, title: String, onTapAsync: @escaping () async -> Void) {
+ self.init()
+ self.style(style)
+ self.onTapAsync(onTapAsync)
+ self.title(title)
+ translatesAutoresizingMaskIntoConstraints = false
+ }
+
+ override func layoutSubviews() {
+ super.layoutSubviews()
+
+ if style == .roundedBlue {
+ self.layer.opacity = self.isEnabled ? 1 : 0.5
+ } else {
+ self.layer.opacity = 1
+ }
+ }
+
+ @discardableResult
+ func style(_ style: ACButtonStyle) -> ACButton {
+
+ self.style = style
+
+ switch style {
+ case .generic:
+ break
+ case .roundedBlue:
+ backgroundColor = .systemBlue
+ layer.cornerRadius = 6
+ }
+
+ return self
+ }
+
+ @discardableResult
+ func title(_ title: String) -> ACButton {
+
+ setTitle(title, for: .normal)
+ return self
+ }
+
+ @discardableResult
+ func enable(_ enabled: Bool) -> ACButton {
+ isEnabled = enabled
+ return self
+ }
+
+ @discardableResult
+ func onTap(_ handler: @escaping () -> Void) -> ACButton {
+
+ addAction(for: .touchUpInside, handler)
+ return self
+ }
+
+ @discardableResult
+ func onTapAsync(_ handler: @escaping () async -> Void) -> ACButton {
+
+ addActionAsync(for: .touchUpInside, handler)
+ return self
+ }
+}
diff --git a/AutoCat2/Components/ACTabBar/ACTabBarButton.swift b/AutoCat2/Components/ACTabBar/ACTabBarButton.swift
new file mode 100644
index 0000000..59796aa
--- /dev/null
+++ b/AutoCat2/Components/ACTabBar/ACTabBarButton.swift
@@ -0,0 +1,82 @@
+//
+// ACTabBarButton.swift
+// AutoCat2
+//
+// Created by Selim Mustafaev on 20.03.2022.
+//
+
+import UIKit
+
+class ACTabBarButton: UIView {
+
+ enum State {
+ case normal
+ case selected
+ }
+
+ private var state: State = .normal
+ private var tabBarItem: UITabBarItem?
+
+ // MARK: - Views
+
+ private lazy var imageView: UIImageView = {
+ let view = UIImageView()
+ view.contentMode = .scaleAspectFit
+ view.translatesAutoresizingMaskIntoConstraints = false
+ return view
+ }()
+
+ private lazy var titleLabel: UILabel = {
+ let label = UILabel()
+ label.font = UIFont.preferredFont(forTextStyle: .caption2)
+ label.textColor = tintColor
+ label.translatesAutoresizingMaskIntoConstraints = false
+ return label
+ }()
+
+ private lazy var stackView: UIStackView = {
+ let stack = UIStackView(arrangedSubviews: [imageView, titleLabel])
+ stack.axis = .vertical
+ stack.spacing = 0
+ stack.distribution = .fill
+ stack.alignment = .center
+ stack.translatesAutoresizingMaskIntoConstraints = false
+ return stack
+ }()
+
+ // MARK: - Lifecycle
+
+ override init(frame: CGRect) {
+ super.init(frame: frame)
+ setup()
+ }
+
+ required init?(coder: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
+ }
+
+ convenience init(tabBarItem: UITabBarItem) {
+ self.init(frame: .zero)
+ apply(tabBarItem: tabBarItem)
+ }
+
+ func setup() {
+ addSubview(stackView)
+ NSLayoutConstraint.activate([
+ stackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 4),
+ stackView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -4),
+ stackView.topAnchor.constraint(equalTo: topAnchor, constant: 4),
+ stackView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -4),
+ imageView.widthAnchor.constraint(equalToConstant: 32),
+ imageView.heightAnchor.constraint(equalToConstant: 32)
+ ])
+ }
+
+ func apply(tabBarItem: UITabBarItem) {
+ self.tabBarItem = tabBarItem
+
+ imageView.contentMode = .scaleAspectFit
+ imageView.image = state == .normal ? tabBarItem.image : tabBarItem.selectedImage
+ titleLabel.text = tabBarItem.title
+ }
+}
diff --git a/AutoCat2/Components/ACTabBar/ACTabBarController.swift b/AutoCat2/Components/ACTabBar/ACTabBarController.swift
new file mode 100644
index 0000000..36a4fd1
--- /dev/null
+++ b/AutoCat2/Components/ACTabBar/ACTabBarController.swift
@@ -0,0 +1,67 @@
+//
+// ACTabBarController.swift
+// AutoCat2
+//
+// Created by Selim Mustafaev on 20.03.2022.
+//
+
+import UIKit
+
+class ACTabBarController: UIViewController {
+
+ // MARK: - Properties
+
+ var viewControllers: [UIViewController] = [] {
+ didSet {
+ setupControllers()
+ }
+ }
+
+ // MARK: - Views
+
+ private lazy var buttonsStackView: UIStackView = {
+ let stack = UIStackView()
+ stack.translatesAutoresizingMaskIntoConstraints = false
+ stack.axis = .horizontal
+ stack.spacing = 0
+ stack.distribution = .fillEqually
+ return stack
+ }()
+
+ private let tabBarView: UIView = {
+ let view = UIView()
+ view.translatesAutoresizingMaskIntoConstraints = false
+ return view
+ }()
+
+ // MARK: - Lifecycle
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+
+// tabBarView.backgroundColor = .green
+// buttonsStackView.backgroundColor = .magenta
+
+ view.addSubview(tabBarView)
+ tabBarView.addSubview(buttonsStackView)
+
+ NSLayoutConstraint.activate([
+ tabBarView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
+ tabBarView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
+ tabBarView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
+ buttonsStackView.leadingAnchor.constraint(equalTo: tabBarView.leadingAnchor),
+ buttonsStackView.trailingAnchor.constraint(equalTo: tabBarView.trailingAnchor),
+ buttonsStackView.topAnchor.constraint(equalTo: tabBarView.topAnchor),
+ buttonsStackView.bottomAnchor.constraint(equalTo: tabBarView.safeAreaLayoutGuide.bottomAnchor)
+ ])
+ }
+
+ func setupControllers() {
+ buttonsStackView.removeAllArrangedSubviews()
+
+ for controller in viewControllers {
+ let button = ACTabBarButton(tabBarItem: controller.tabBarItem)
+ buttonsStackView.addArrangedSubview(button)
+ }
+ }
+}
diff --git a/AutoCat2/Components/ACTextField.swift b/AutoCat2/Components/ACTextField.swift
new file mode 100644
index 0000000..4156d27
--- /dev/null
+++ b/AutoCat2/Components/ACTextField.swift
@@ -0,0 +1,98 @@
+//
+// Created by Selim Mustafaev on 06.03.2022.
+//
+
+import UIKit
+
+enum ACTextFieldStyle {
+
+ case generic
+ case roundBordered
+}
+
+class ACTextField: UITextField, UITextFieldDelegate {
+
+ private var style: ACTextFieldStyle = .generic
+ private var onTextChanged: ((String?) -> Void)?
+
+ var editable: Bool = true
+
+ // MARK: - Lifecycle
+
+ convenience init(placeholder: String? = nil, style: ACTextFieldStyle = .roundBordered) {
+ self.init(frame: .zero)
+
+ self.delegate = self
+ self.placeholderText(placeholder)
+ self.style(style)
+
+ addTarget(self, action: #selector(textFieldDidChange), for: .editingChanged)
+
+ translatesAutoresizingMaskIntoConstraints = false
+ }
+
+ override func layoutSubviews() {
+ super.layoutSubviews()
+ style(style)
+ }
+
+ // MARK: - Setters
+
+ @discardableResult
+ func placeholderText(_ placeholder: String?) -> ACTextField {
+ self.placeholder = placeholder
+ return self
+ }
+
+ @discardableResult
+ func keyboardType(_ keyboardType: UIKeyboardType) -> ACTextField {
+ self.keyboardType = keyboardType
+ return self
+ }
+
+ @discardableResult
+ func style(_ style: ACTextFieldStyle) -> ACTextField {
+
+ self.style = style
+ borderStyle = .roundedRect
+
+ switch style {
+ case .generic:
+ layer.borderWidth = 0
+ layer.cornerRadius = 0
+ layer.borderColor = nil
+ break
+ case .roundBordered:
+ layer.borderWidth = 1
+ layer.cornerRadius = 6
+ layer.borderColor = UIColor.secondaryLabel.cgColor
+ }
+
+ return self
+ }
+
+ @discardableResult
+ func secure(_ secure: Bool) -> ACTextField {
+ isSecureTextEntry = secure
+ return self
+ }
+
+ @discardableResult
+ func onTextChanged(_ handler: @escaping (String?) -> Void) -> ACTextField {
+ onTextChanged = handler
+ return self
+ }
+
+ // MARK: - UITextFieldDelegate
+
+ func textField(_ textField: UITextField,
+ shouldChangeCharactersIn range: NSRange,
+ replacementString string: String) -> Bool {
+ editable
+ }
+
+ @objc func textFieldDidChange(_ textField: UITextField) {
+ onTextChanged?(textField.text)
+ }
+
+}
diff --git a/AutoCat2/Components/Extensions/UIControl.swift b/AutoCat2/Components/Extensions/UIControl.swift
new file mode 100644
index 0000000..1f4114b
--- /dev/null
+++ b/AutoCat2/Components/Extensions/UIControl.swift
@@ -0,0 +1,23 @@
+//
+// Created by Selim Mustafaev on 06.03.2022.
+//
+
+import UIKit
+
+extension UIControl {
+
+ func addAction(for controlEvents: UIControl.Event = .touchUpInside, _ closure: @escaping () -> Void) {
+
+ addAction(UIAction { _ in closure() }, for: controlEvents)
+ }
+
+ func addActionAsync(for controlEvents: UIControl.Event = .touchUpInside, _ closure: @escaping () async -> Void) {
+
+ addAction(UIAction { _ in
+ Task {
+ await closure()
+ }
+ }, for: controlEvents)
+ }
+
+}
diff --git a/AutoCat2/Components/Extensions/UIStackView.swift b/AutoCat2/Components/Extensions/UIStackView.swift
new file mode 100644
index 0000000..1f563ae
--- /dev/null
+++ b/AutoCat2/Components/Extensions/UIStackView.swift
@@ -0,0 +1,26 @@
+//
+// UIStackView.swift
+// AutoCat2
+//
+// Created by Selim Mustafaev on 20.03.2022.
+//
+
+import UIKit
+
+extension UIStackView {
+
+ func removeAllArrangedSubviews() {
+
+ let removedSubviews = arrangedSubviews.reduce([]) { (allSubviews, subview) -> [UIView] in
+ self.removeArrangedSubview(subview)
+ return allSubviews + [subview]
+ }
+
+ // Deactivate all constraints
+ NSLayoutConstraint.deactivate(removedSubviews.flatMap({ $0.constraints }))
+
+ // Remove the views from self
+ removedSubviews.forEach({ $0.removeFromSuperview() })
+ }
+
+}
diff --git a/AutoCat2/Components/Extensions/UITextField.swift b/AutoCat2/Components/Extensions/UITextField.swift
new file mode 100644
index 0000000..ae3f2fa
--- /dev/null
+++ b/AutoCat2/Components/Extensions/UITextField.swift
@@ -0,0 +1,18 @@
+//
+// Created by Selim Mustafaev on 06.03.2022.
+//
+
+import UIKit
+import Combine
+
+extension UITextField {
+
+ var textPublisher: AnyPublisher {
+
+ NotificationCenter.default.publisher(for: UITextField.textDidChangeNotification, object: self)
+ .map { ($0.object as? UITextField)?.text }
+ .eraseToAnyPublisher()
+ }
+
+}
+
diff --git a/AutoCat2/Components/Extensions/UIView.swift b/AutoCat2/Components/Extensions/UIView.swift
new file mode 100644
index 0000000..e02ae0c
--- /dev/null
+++ b/AutoCat2/Components/Extensions/UIView.swift
@@ -0,0 +1,25 @@
+//
+// UIView.swift
+// AutoCat2
+//
+// Created by Selim Mustafaev on 20.03.2022.
+//
+
+import UIKit
+
+extension UIView {
+
+ func disableTranslatesAutoresizingMaskIntoConstraints() -> Self {
+ translatesAutoresizingMaskIntoConstraints = false
+ return self
+ }
+
+ func pin(to view: UIView, insets: UIEdgeInsets = .zero) {
+ NSLayoutConstraint.activate([
+ leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: insets.left),
+ trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -insets.right),
+ topAnchor.constraint(equalTo: view.topAnchor, constant: insets.top),
+ bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -insets.bottom)
+ ])
+ }
+}
diff --git a/AutoCat2/Components/Extensions/UIViewController.swift b/AutoCat2/Components/Extensions/UIViewController.swift
new file mode 100644
index 0000000..633ef26
--- /dev/null
+++ b/AutoCat2/Components/Extensions/UIViewController.swift
@@ -0,0 +1,16 @@
+//
+// Created by Selim Mustafaev on 10.03.2022.
+//
+
+import UIKit
+
+extension UIViewController {
+
+ func show(error: Error) {
+
+ let alert = UIAlertController(title: nil, message: error.localizedDescription, preferredStyle: .alert)
+ alert.addAction(UIAlertAction(title: "OK", style: .default))
+ present(alert, animated: true)
+ }
+
+}
\ No newline at end of file
diff --git a/AutoCat2/Components/PNKeyboard.swift b/AutoCat2/Components/PNKeyboard.swift
new file mode 100644
index 0000000..7b4dee1
--- /dev/null
+++ b/AutoCat2/Components/PNKeyboard.swift
@@ -0,0 +1,216 @@
+import UIKit
+import AutoCatCore
+
+protocol PNKeyboardDelegate: AnyObject {
+ func returnClicked()
+}
+
+protocol PNButtonDelegate: AnyObject {
+ func buttonTapped(_ button: PNButton)
+}
+
+enum PNButtonType {
+ case symbol(String)
+ case backspace
+ case done
+}
+
+class PNButton: UIButton {
+ private(set) var type: PNButtonType
+ private var timer: Timer?
+ private var waitCount = 0
+ private var rectLayer = CAShapeLayer()
+ private var bgColor = UIColor(named: "KeyBackground")
+
+ weak var delegate: PNButtonDelegate?
+
+ init(letter: Character) {
+ self.type = .symbol(String(letter))
+ super.init(frame: .zero)
+ self.setup()
+ self.titleLabel?.font = UIFont(name: "RoadNumbers", size: 36)
+ let title = String(Constants.pnLettersMap[letter] ?? letter)
+ self.setTitle(title, for: .normal)
+ self.setTitleColor(.label, for: .normal)
+ }
+
+ init(digit: Int) {
+ self.type = .symbol(String(digit))
+ super.init(frame: .zero)
+ self.setup()
+ self.titleLabel?.font = UIFont(name: "RoadNumbersCyr-Regular", size: 30)
+ let character = Character(String(digit))
+ let title = String(Constants.pnLettersMap[character] ?? character)
+ self.setTitle(title, for: .normal)
+ self.setTitleColor(.label, for: .normal)
+ }
+
+ init(imageName: String, type: PNButtonType) {
+ self.type = type
+ self.bgColor = UIColor(named: "DarkKeyBackground")
+ super.init(frame: .zero)
+ self.setup()
+ self.setImage(UIImage(systemName: imageName), for: .normal)
+ self.tintColor = .label
+ }
+
+ required init?(coder: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
+ }
+
+ func setup(_ radius: CGFloat = 0.5) {
+ self.rectLayer.cornerRadius = 6
+ self.layer.addSublayer(self.rectLayer)
+ self.imageView?.layer.zPosition = 2
+
+ self.rectLayer.shadowColor = UIColor.black.cgColor
+ self.rectLayer.shadowOpacity = 0.4
+ self.rectLayer.shadowOffset = CGSize(width: 0.0, height : 1.0)
+ self.rectLayer.shadowRadius = radius
+
+ self.addTarget(self, action: #selector(buttonDown), for: .touchDown)
+ self.addTarget(self, action: #selector(buttonUp), for: [.touchUpInside, .touchUpOutside])
+ self.addTarget(self, action: #selector(touchUpInside), for: .touchUpInside)
+ }
+
+ override func layoutSubviews() {
+ super.layoutSubviews()
+ self.rectLayer.backgroundColor = self.bgColor?.cgColor
+ self.rectLayer.frame = self.layer.bounds.inset(by: UIEdgeInsets(top: 4, left: 4, bottom: 4, right: 4))
+ }
+
+ @objc func buttonDown(_ sender: PNButton) {
+ sender.layer.opacity = 0.3
+ self.timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true, block: { _ in
+ self.waitCount += 1
+ if self.waitCount > 5 {
+ self.delegate?.buttonTapped(self)
+ }
+ })
+ }
+
+ @objc func buttonUp(_ sender: PNButton) {
+ sender.layer.opacity = 1
+ self.timer?.invalidate()
+ self.timer = nil
+ self.waitCount = 0
+ }
+
+ @objc func touchUpInside(_ sender: PNButton) {
+ self.delegate?.buttonTapped(self)
+ }
+
+ func setBacgroundColor(color: UIColor) {
+ self.bgColor = color
+ self.setNeedsLayout()
+ }
+}
+
+class PNKeyboard: UIView, UIInputViewAudioFeedback, PNButtonDelegate {
+ private weak var target: UIKeyInput?
+ weak var delegate: PNKeyboardDelegate?
+
+ private let insets: UIEdgeInsets
+
+ init(target: UIKeyInput?, insets: UIEdgeInsets) {
+ self.target = target
+ self.insets = insets
+ super.init(frame: .zero)
+ self.autoresizingMask = [.flexibleWidth, .flexibleHeight]
+
+ let blurEffectView = UIVisualEffectView(effect: UIBlurEffect())
+ blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
+ self.addSubview(blurEffectView)
+
+ self.setupButtons()
+ }
+
+ required init?(coder: NSCoder) {
+ fatalError("init(coder:) has not been implemented")
+ }
+
+ func setupButtons() {
+ let letters: [PNButton] = Constants.pnLettersMap.keys.sorted().map { letter in
+ let button = PNButton(letter: letter)
+ button.delegate = self
+ return button
+ }
+ let digits: [PNButton] = [1,2,3,4,5,6,7,8,9,0].map { digit in
+ let button = PNButton(digit: digit)
+ button.delegate = self
+ return button
+ }
+ let backspace = PNButton(imageName: "delete.left", type: .backspace)
+ backspace.delegate = self
+
+ let done = PNButton(imageName: "arrow.turn.down.left", type: .done)
+ done.delegate = self
+ done.setBacgroundColor(color: .systemBlue)
+ done.tintColor = .white
+
+ let letterRows = [
+ self.createLetterStack([letters[0], letters[1], letters[2]]),
+ self.createLetterStack([letters[3], letters[4], letters[5]]),
+ self.createLetterStack([letters[6], letters[7], letters[8]]),
+ self.createLetterStack([letters[9], letters[10], letters[11]])
+ ]
+
+ let lettersStack = UIStackView(arrangedSubviews: letterRows)
+ lettersStack.axis = .vertical
+ lettersStack.distribution = .fillEqually
+ //lettersStack.spacing = 8
+
+ let digitRows = [
+ self.createLetterStack([digits[0], digits[1], digits[2]]),
+ self.createLetterStack([digits[3], digits[4], digits[5]]),
+ self.createLetterStack([digits[6], digits[7], digits[8]]),
+ self.createLetterStack([digits[9], backspace, done])
+ ]
+
+ let digitsStack = UIStackView(arrangedSubviews: digitRows)
+ digitsStack.axis = .vertical
+ digitsStack.distribution = .fillEqually
+ //digitsStack.spacing = 8
+
+ let mainStack = UIStackView(arrangedSubviews: [lettersStack, digitsStack])
+ mainStack.spacing = 16
+ mainStack.distribution = .fillEqually
+ mainStack.translatesAutoresizingMaskIntoConstraints = false
+ self.addSubview(mainStack)
+
+ NSLayoutConstraint.activate([
+ mainStack.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: insets.left),
+ mainStack.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -insets.right),
+ mainStack.topAnchor.constraint(equalTo: self.topAnchor, constant: insets.top),
+ mainStack.bottomAnchor.constraint(equalTo: self.safeAreaLayoutGuide.bottomAnchor, constant: -insets.bottom)
+ ])
+ }
+
+ func createLetterStack(_ views: [UIView]) -> UIStackView {
+ let stack = UIStackView(arrangedSubviews: views)
+ stack.distribution = .fillEqually
+ //stack.spacing = 8
+ return stack
+ }
+
+ // MARK: - PNButtonDelegate
+
+ func buttonTapped(_ button: PNButton) {
+ UIDevice.current.playInputClick()
+
+ switch button.type {
+ case .symbol(let s):
+ self.target?.insertText(s)
+ case .backspace:
+ self.target?.deleteBackward()
+ case .done:
+ self.delegate?.returnClicked()
+ }
+ }
+
+ // MARK: - UIInputViewAudioFeedback
+
+ var enableInputClicksWhenVisible: Bool {
+ return true
+ }
+}
diff --git a/AutoCat2/Components/PlateView/FlagLayer.swift b/AutoCat2/Components/PlateView/FlagLayer.swift
new file mode 100644
index 0000000..2b87d06
--- /dev/null
+++ b/AutoCat2/Components/PlateView/FlagLayer.swift
@@ -0,0 +1,31 @@
+import UIKit
+
+class FlagLayer: CALayer {
+ let pixelWidth = 1/UIScreen.main.scale
+
+ // Flag colors - https://ru.wikipedia.org/wiki/%D0%A4%D0%BB%D0%B0%D0%B3_%D0%A0%D0%BE%D1%81%D1%81%D0%B8%D0%B8
+ let blue = CGColor(srgbRed: 0, green: 57/256.0, blue: 166/256.0, alpha: 1)
+ let red = CGColor(srgbRed: 213/256.0, green: 43/256.0, blue: 30/256.0, alpha: 1)
+
+ override func draw(in ctx: CGContext) {
+ ctx.saveGState()
+ super.draw(in: ctx)
+
+ ctx.setStrokeColor(UIColor.black.cgColor)
+ ctx.setLineWidth(0)
+
+ ctx.setFillColor(UIColor.white.cgColor)
+ ctx.fill(bounds.inset(by: UIEdgeInsets(top: 0, left: 0, bottom: bounds.height*2/3, right: 0)))
+
+ ctx.setFillColor(self.blue)
+ ctx.fill(bounds.insetBy(dx: 0, dy: bounds.height/3))
+
+ ctx.setFillColor(self.red)
+ ctx.fill(bounds.inset(by: UIEdgeInsets(top: bounds.height*2/3, left: 0, bottom: 0, right: 0)))
+
+ ctx.setLineWidth(pixelWidth)
+ ctx.stroke(bounds.insetBy(dx: pixelWidth/2, dy: pixelWidth/2))
+
+ ctx.restoreGState()
+ }
+}
diff --git a/AutoCat2/Components/PlateView/PlateView.swift b/AutoCat2/Components/PlateView/PlateView.swift
new file mode 100644
index 0000000..4181156
--- /dev/null
+++ b/AutoCat2/Components/PlateView/PlateView.swift
@@ -0,0 +1,138 @@
+import UIKit
+import AutoCatCore
+
+class PlateView: UIView {
+ // Some driver plate parameters from "ГОСТ Р 50577-93"
+ // http://docs.cntd.ru/document/gost-r-50577-93
+ private static let aspectRatio: CGFloat = 112.0/520.0
+ private static let fontHeightCoeff: CGFloat = 58.0/76.0
+
+ private var bgLayer = CALayer()
+ private var mainBgLayer = CALayer()
+ private var regionBgLayer = CALayer()
+ private var numberLayer = CenterTextLayer(coeff: fontHeightCoeff)
+ private var regionLayer = CenterTextLayer(coeff: fontHeightCoeff)
+ private var countryLayer = CenterTextLayer()
+ private var flagLayer = FlagLayer()
+
+ var number: PlateNumber? {
+ didSet {
+ self.layoutSubviews()
+ }
+ }
+
+ var foreground: UIColor? {
+ didSet {
+ self.layoutSubviews()
+ }
+ }
+
+ override init(frame: CGRect) {
+ super.init(frame: frame)
+ setup()
+ }
+
+ required init?(coder: NSCoder) {
+ super.init(coder: coder)
+ setup()
+ }
+
+ func setup() {
+ self.layer.backgroundColor = UIColor.clear.cgColor
+
+ self.bgLayer.cornerRadius = 6 //self.bounds.height/8
+ self.layer.addSublayer(self.bgLayer)
+
+ self.mainBgLayer.cornerRadius = 4
+ self.layer.addSublayer(self.mainBgLayer)
+
+ self.regionBgLayer.cornerRadius = 4
+ self.layer.addSublayer(self.regionBgLayer)
+
+ self.numberLayer.alignmentMode = .center
+ self.numberLayer.contentsScale = UIScreen.main.scale
+ self.layer.addSublayer(self.numberLayer)
+
+ self.regionLayer.alignmentMode = .center
+ self.regionLayer.contentsScale = UIScreen.main.scale
+ self.layer.addSublayer(self.regionLayer)
+
+ self.countryLayer.contentsScale = UIScreen.main.scale
+ self.countryLayer.string = "RUS"
+ self.countryLayer.alignmentMode = .center
+ self.layer.addSublayer(self.countryLayer)
+
+ self.flagLayer.contentsScale = UIScreen.main.scale
+ self.layer.addSublayer(self.flagLayer)
+ }
+
+ private func pathForFlag(in rect: CGRect) -> CGPath {
+ let path = CGMutablePath()
+ let rect = CGPath(rect: rect, transform: nil)
+ path.addPath(rect)
+ return path
+ }
+
+ override func layoutSubviews() {
+ super.layoutSubviews()
+ guard let number = self.number else { return }
+ guard let fgColorMain = UIColor(named: "PlateForeground")?.cgColor else { return }
+ guard let bgColor = UIColor(named: "PlateBackground")?.cgColor else { return }
+
+ let fgColor = self.foreground?.cgColor ?? fgColorMain
+
+ self.bgLayer.backgroundColor = fgColor
+ self.bgLayer.frame = self.bounds
+
+ self.mainBgLayer.backgroundColor = bgColor
+ self.regionBgLayer.backgroundColor = bgColor
+ self.mainBgLayer.frame = self.bounds.inset(by: UIEdgeInsets(top: 2, left: 2, bottom: 2, right: self.bounds.width*0.27 + 1))
+ self.regionBgLayer.frame = self.bounds.inset(by: UIEdgeInsets(top: 2, left: self.bounds.width*0.73 + 1, bottom: 2, right: 2))
+
+ self.numberLayer.frame = self.mainBgLayer.frame.insetBy(dx: 4, dy: 0)
+ let font = UIFont(name: "RoadNumbers", size: self.mainBgLayer.frame.height*1.1) ?? UIFont.boldSystemFont(ofSize: 24)
+ let attributes: [NSAttributedString.Key: Any] = [
+ .kern: 3,
+ .font: font,
+ .foregroundColor: fgColor
+ ]
+ let attributed = NSAttributedString(string: number.mainPart(), attributes: attributes)
+ self.numberLayer.string = attributed
+
+ let rbgSize = self.regionBgLayer.frame.size
+
+ self.regionLayer.frame = self.regionBgLayer.frame.inset(by: UIEdgeInsets(top: 2, left: 2, bottom: rbgSize.height*0.35, right: 2))
+ let regionFont = UIFont(name: "RoadNumbers", size: rbgSize.height*0.8) ?? UIFont.boldSystemFont(ofSize: 24)
+ let regionAttrs: [NSAttributedString.Key: Any] = [
+ .kern: 1,
+ .font: regionFont,
+ .foregroundColor: fgColor
+ ]
+ let attributedRegion = NSAttributedString(string: number.region(), attributes: regionAttrs)
+ self.regionLayer.string = attributedRegion
+
+ self.countryLayer.foregroundColor = fgColor
+ self.countryLayer.frame = self.regionBgLayer.frame.inset(by: UIEdgeInsets(top: rbgSize.height*0.64, left: rbgSize.width*0.08, bottom: rbgSize.height*0.07, right: rbgSize.width*0.42))
+ self.countryLayer.fontSize = self.countryLayer.frame.size.height
+
+ let top = (self.regionBgLayer.frame.origin.y + rbgSize.height*0.68).rounded(.toNearestOrAwayFromZero)
+ let left = (self.regionBgLayer.frame.origin.x + rbgSize.width*0.62).rounded(.toNearestOrAwayFromZero)
+ let w = (rbgSize.width*0.34).rounded(.toNearestOrAwayFromZero)
+ let h = (rbgSize.height*0.28).rounded(.toNearestOrAwayFromZero)
+ self.flagLayer.frame = CGRect(x: left, y: top, width: w, height: h)
+ self.flagLayer.setNeedsDisplay()
+ }
+
+ override var intrinsicContentSize: CGSize {
+ guard self.bounds.width != 0 || self.bounds.height != 0 else {
+ return CGSize.zero
+ }
+
+ let curAspectRatio = self.bounds.height/self.bounds.width
+ if curAspectRatio >= PlateView.aspectRatio {
+ return CGSize(width: self.bounds.width, height: self.bounds.width*PlateView.aspectRatio)
+ } else {
+ return CGSize(width: self.bounds.height/PlateView.aspectRatio, height: self.bounds.height)
+ }
+ }
+}
diff --git a/AutoCat2/Controllers/AuthController.swift b/AutoCat2/Controllers/AuthController.swift
new file mode 100644
index 0000000..918862e
--- /dev/null
+++ b/AutoCat2/Controllers/AuthController.swift
@@ -0,0 +1,99 @@
+//
+// Created by Selim Mustafaev on 06.03.2022.
+//
+
+import UIKit
+import PKHUD
+import AutoCatCore
+
+class AuthController: UIViewController {
+
+ private lazy var emailField = ACTextField(placeholder: "Email")
+ .onTextChanged(textChanged)
+ .keyboardType(.emailAddress)
+
+ private lazy var passwordField = ACTextField(placeholder: "Password")
+ .onTextChanged(textChanged)
+ .secure(true)
+
+ private lazy var loginButton = ACButton(title: "Log in", onTapAsync: loginTapped)
+ .enable(false)
+
+ private lazy var signupButton = ACButton(title: "Sign up", onTapAsync: signupTapped)
+ .enable(false)
+
+ private lazy var stackView: UIStackView = {
+ let stack = UIStackView(arrangedSubviews: [
+ emailField,
+ passwordField,
+ loginButton,
+ signupButton
+ ])
+
+ stack.axis = .vertical
+ stack.spacing = 16
+ stack.translatesAutoresizingMaskIntoConstraints = false
+
+ return stack
+ }()
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+
+ view.backgroundColor = .systemBackground
+ view.addSubview(stackView)
+ NSLayoutConstraint.activate([
+ stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
+ stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor),
+ stackView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.7),
+ loginButton.heightAnchor.constraint(equalToConstant: 40),
+ signupButton.heightAnchor.constraint(equalToConstant: 40)
+ ])
+ }
+
+ func textChanged(_ text: String?) {
+ guard let email = emailField.text, let pass = passwordField.text else {
+ loginButton.isEnabled = false
+ signupButton.isEnabled = false
+ return
+ }
+
+ let enabled = email.count >= 5 && pass.count >= 5
+ loginButton.isEnabled = enabled
+ signupButton.isEnabled = enabled
+ }
+
+ // MARK: - Button handlers
+
+ func loginTapped() async {
+ guard let email = emailField.text, let password = passwordField.text else {
+ return
+ }
+
+ do {
+ HUD.show(.progress)
+ Settings.shared.user = try await Api.shared.login(email: email, password: password)
+ view.window?.rootViewController = MainTabController()
+ HUD.hide()
+ } catch {
+ HUD.hide()
+ show(error: error)
+ }
+ }
+
+ func signupTapped() async {
+ guard let email = emailField.text, let password = passwordField.text else {
+ return
+ }
+
+ do {
+ HUD.show(.progress)
+ Settings.shared.user = try await Api.shared.signup(email: email, password: password)
+ view.window?.rootViewController = MainTabController()
+ HUD.hide()
+ } catch {
+ HUD.hide()
+ show(error: error)
+ }
+ }
+}
diff --git a/AutoCat2/Controllers/CheckController.swift b/AutoCat2/Controllers/CheckController.swift
new file mode 100644
index 0000000..fcf88f7
--- /dev/null
+++ b/AutoCat2/Controllers/CheckController.swift
@@ -0,0 +1,112 @@
+//
+// CheckController.swift
+// AutoCat2
+//
+// Created by Selim Mustafaev on 20.03.2022.
+//
+
+import UIKit
+
+class CheckController: UIViewController {
+
+ public var onCheck: ((String) -> Void)?
+
+ private lazy var keyboardView: PNKeyboard = {
+ let keyboard = PNKeyboard(target: self.numberField, insets: .zero)
+ keyboard.delegate = self
+ return keyboard
+ }()
+
+ private lazy var numberField: SwiftMaskTextfield = {
+ let textField = SwiftMaskTextfield()
+ textField.formatPattern = "@###@@###"
+ textField.placeholder = "A001AA 777"
+ textField.borderStyle = .roundedRect
+ textField.font = .preferredFont(forTextStyle: .largeTitle)
+ textField.textAlignment = .center
+ textField.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged)
+ return textField
+ }()
+
+ private let plateView = PlateView(frame: .zero)
+
+ private lazy var checkButton = ACButton(title: "Check", onTap: check)
+ .enable(false)
+
+ private lazy var stackView: UIStackView = {
+ let stack = UIStackView(arrangedSubviews: [plateView, checkButton])
+ stack.axis = .horizontal
+ stack.spacing = 16
+ stack.translatesAutoresizingMaskIntoConstraints = false
+ return stack
+ }()
+
+ private let titleLabel: UILabel = {
+ let label = UILabel()
+ label.text = "Check new plate number"
+ label.font = UIFont.preferredFont(forTextStyle: .headline)
+ label.textAlignment = .center
+ label.translatesAutoresizingMaskIntoConstraints = false
+ return label
+ }()
+
+ private lazy var mainStackView: UIStackView = {
+ let stack = UIStackView(arrangedSubviews: [titleLabel, stackView, keyboardView])
+ stack.axis = .vertical
+ stack.spacing = 16
+ stack.translatesAutoresizingMaskIntoConstraints = false
+ return stack
+ }()
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+
+ //view.backgroundColor = .systemBackground
+ checkButton.contentEdgeInsets = .init(top: 0, left: 8, bottom: 0, right: 8)
+
+ view.addSubview(mainStackView)
+ mainStackView.pin(to: view, insets: .init(top: 16, left: 16, bottom: 16, right: 16))
+
+ NSLayoutConstraint.activate([
+ plateView.heightAnchor.constraint(equalToConstant: 40)
+ ])
+ }
+
+ override func viewDidAppear(_ animated: Bool) {
+ super.viewDidAppear(animated)
+
+ DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
+ self.numberField.becomeFirstResponder()
+ }
+ }
+
+ func check() {
+ guard let number = numberField.text else {
+ return
+ }
+
+ let numberNormalized = number.filter { !$0.isWhitespace }.uppercased()
+ numberField.resignFirstResponder()
+ onCheck?(numberNormalized)
+ }
+}
+
+extension CheckController: PNKeyboardDelegate {
+
+ func returnClicked() {
+ check()
+ }
+}
+
+extension CheckController: UITextFieldDelegate {
+
+ @objc func textFieldDidChange(_ textField: UITextField) {
+ guard let text = textField.text else {
+ self.checkButton.isEnabled = false
+ return
+ }
+
+ self.checkButton.isEnabled = text.count >= 8
+ }
+
+}
diff --git a/AutoCat2/Controllers/HistoryController.swift b/AutoCat2/Controllers/HistoryController.swift
new file mode 100644
index 0000000..f45bc9e
--- /dev/null
+++ b/AutoCat2/Controllers/HistoryController.swift
@@ -0,0 +1,37 @@
+//
+// Created by Selim Mustafaev on 13.03.2022.
+//
+
+import UIKit
+import PKHUD
+import AutoCatCore
+
+class HistoryController: UIViewController {
+
+
+ private lazy var tableView: UITableView = {
+ let table = UITableView()
+ table.translatesAutoresizingMaskIntoConstraints = false
+ return table
+ }()
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+
+ title = "Check history"
+
+ view.addSubview(tableView)
+ tableView.pin(to: view)
+ }
+
+ func checkPlateNumber(_ number: String) async {
+ print("Check plate number: ", number)
+
+ do {
+ HUD.show(.progress)
+ try await VehicleService.shared.check(plateNumber: number, force: false)
+ } catch {
+ show(error: error)
+ }
+ }
+}
diff --git a/AutoCat2/Controllers/MainTabController.swift b/AutoCat2/Controllers/MainTabController.swift
new file mode 100644
index 0000000..ee59ade
--- /dev/null
+++ b/AutoCat2/Controllers/MainTabController.swift
@@ -0,0 +1,62 @@
+//
+// Created by Selim Mustafaev on 06.03.2022.
+//
+
+import UIKit
+import SwiftEntryKit
+
+class MainTabController: UITabBarController, UITabBarControllerDelegate {
+
+ // Dummy controller, tabbar item will be used as a button
+ private let addController = UIViewController()
+
+ let historyController = HistoryController()
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+
+ self.view.backgroundColor = .systemBackground
+ self.delegate = self
+
+ let historyNavController = UINavigationController(rootViewController: historyController)
+ historyNavController.tabBarItem = UITabBarItem(title: "Check", image: UIImage(systemName: "eye"), selectedImage: UIImage(systemName: "eye.fill"))
+
+ let settingsController = SettingsController()
+ settingsController.tabBarItem = UITabBarItem(title: "Settings", image: UIImage(systemName: "gear"), selectedImage: nil)
+
+ addController.tabBarItem = UITabBarItem(title: "New", image: UIImage(systemName: "plus"), selectedImage: nil)
+
+ self.viewControllers = [historyNavController, addController, settingsController]
+ }
+
+ func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
+ if viewController == addController {
+ showCheckPuller()
+ return false
+ } else {
+ return true
+ }
+ }
+
+ func showCheckPuller() {
+ var attributes = EKAttributes.bottomToast
+ attributes.displayDuration = .infinity
+ attributes.positionConstraints.keyboardRelation = .bind(offset: .none)
+ attributes.entryBackground = .color(color: .standardBackground)
+ attributes.screenBackground = .color(color: EKColor(UIColor(white: 0.3, alpha: 0.5)))
+ attributes.roundCorners = .top(radius: 24)
+ attributes.screenInteraction = .dismiss
+ attributes.entryInteraction = .forward
+ //attributes.shadow = .active(with: .init(color: .black, opacity: 0.2, radius: 24, offset: .zero))
+
+ let checkController = CheckController()
+ checkController.onCheck = { number in
+ SwiftEntryKit.dismiss()
+ Task {
+ await self.historyController.checkPlateNumber(number)
+ }
+ }
+
+ SwiftEntryKit.display(entry: checkController, using: attributes)
+ }
+}
diff --git a/AutoCat2/Controllers/SettingsController.swift b/AutoCat2/Controllers/SettingsController.swift
new file mode 100644
index 0000000..30d0c48
--- /dev/null
+++ b/AutoCat2/Controllers/SettingsController.swift
@@ -0,0 +1,12 @@
+//
+// Created by Selim Mustafaev on 13.03.2022.
+//
+
+import UIKit
+
+class SettingsController: UIViewController {
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ }
+}
diff --git a/Shared/Fonts/RoadNumbers.otf b/AutoCat2/Fonts/RoadNumbers.otf
similarity index 100%
rename from Shared/Fonts/RoadNumbers.otf
rename to AutoCat2/Fonts/RoadNumbers.otf
diff --git a/Shared/Fonts/RoadNumbers2.0.otf b/AutoCat2/Fonts/RoadNumbers2.0.otf
similarity index 100%
rename from Shared/Fonts/RoadNumbers2.0.otf
rename to AutoCat2/Fonts/RoadNumbers2.0.otf
diff --git a/AutoCat2/Info.plist b/AutoCat2/Info.plist
new file mode 100644
index 0000000..73daeb7
--- /dev/null
+++ b/AutoCat2/Info.plist
@@ -0,0 +1,30 @@
+
+
+
+
+ UIAppFonts
+
+ RoadNumbers.otf
+ RoadNumbers2.0.otf
+
+ UIApplicationSceneManifest
+
+ UIApplicationSupportsMultipleScenes
+
+ UISceneConfigurations
+
+ UIWindowSceneSessionRoleApplication
+
+
+ UISceneConfigurationName
+ Default Configuration
+ UISceneDelegateClassName
+ $(PRODUCT_MODULE_NAME).SceneDelegate
+ UISceneStoryboardFile
+ Main
+
+
+
+
+
+
diff --git a/AutoCat2/SceneDelegate.swift b/AutoCat2/SceneDelegate.swift
new file mode 100644
index 0000000..db94ff6
--- /dev/null
+++ b/AutoCat2/SceneDelegate.swift
@@ -0,0 +1,63 @@
+//
+// SceneDelegate.swift
+// AutoCat2
+//
+// Created by Selim Mustafaev on 05.03.2022.
+//
+
+import UIKit
+import AutoCatCore
+
+class SceneDelegate: UIResponder, UIWindowSceneDelegate {
+
+ var window: UIWindow?
+
+
+ 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`.
+ // 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).
+ guard let scene = (scene as? UIWindowScene) else { return }
+
+ self.window = UIWindow(windowScene: scene)
+
+ if Settings.shared.user.token.isEmpty {
+ self.window?.rootViewController = AuthController()
+ } else {
+ self.window?.rootViewController = MainTabController()
+ }
+
+ self.window?.makeKeyAndVisible()
+ }
+
+ func sceneDidDisconnect(_ scene: UIScene) {
+ // Called as the scene is being released by the system.
+ // This occurs shortly after the scene enters the background, or when its session is discarded.
+ // Release any resources associated with this scene that can be re-created the next time the scene connects.
+ // The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
+ }
+
+ func sceneDidBecomeActive(_ scene: UIScene) {
+ // Called when the scene has moved from an inactive state to an active state.
+ // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
+ }
+
+ func sceneWillResignActive(_ scene: UIScene) {
+ // Called when the scene will move from an active state to an inactive state.
+ // This may occur due to temporary interruptions (ex. an incoming phone call).
+ }
+
+ func sceneWillEnterForeground(_ scene: UIScene) {
+ // Called as the scene transitions from the background to the foreground.
+ // Use this method to undo the changes made on entering the background.
+ }
+
+ func sceneDidEnterBackground(_ scene: UIScene) {
+ // Called as the scene transitions from the foreground to the background.
+ // Use this method to save data, release shared resources, and store enough scene-specific state information
+ // to restore the scene back to its current state.
+ }
+
+
+}
+
diff --git a/AutoCat2/ThirdParty/CenterTextLayer.swift b/AutoCat2/ThirdParty/CenterTextLayer.swift
new file mode 100644
index 0000000..8fd0a12
--- /dev/null
+++ b/AutoCat2/ThirdParty/CenterTextLayer.swift
@@ -0,0 +1,51 @@
+//
+// CenterTextLayer.swift
+// CenterTextLayer
+//
+// Created by Cem Olcay on 12/04/2017.
+//
+// http://stackoverflow.com/a/41518502/2048130
+//
+
+#if os(iOS) || os(tvOS)
+ import UIKit
+#elseif os(OSX)
+ import AppKit
+#endif
+
+public class CenterTextLayer: CATextLayer {
+
+ var heightCoefficient: CGFloat = 1
+
+ public override init() {
+ super.init()
+ }
+
+ public override init(layer: Any) {
+ super.init(layer: layer)
+ }
+
+ public required init(coder aDecoder: NSCoder) {
+ super.init(layer: aDecoder)
+ }
+
+ public init(coeff: CGFloat) {
+ super.init()
+ self.heightCoefficient = coeff
+ }
+
+ public override func draw(in ctx: CGContext) {
+ #if os(iOS) || os(tvOS)
+ let multiplier = CGFloat(1)
+ #elseif os(OSX)
+ let multiplier = CGFloat(-1)
+ #endif
+ let h = ((string as? NSAttributedString)?.size().height ?? fontSize)*heightCoefficient;
+ let yDiff = (bounds.size.height - h) / 2 * multiplier
+
+ ctx.saveGState()
+ ctx.translateBy(x: 0.0, y: yDiff)
+ super.draw(in: ctx)
+ ctx.restoreGState()
+ }
+}
diff --git a/AutoCat2/ThirdParty/SwiftMaskTextfield.swift b/AutoCat2/ThirdParty/SwiftMaskTextfield.swift
new file mode 100644
index 0000000..706d47d
--- /dev/null
+++ b/AutoCat2/ThirdParty/SwiftMaskTextfield.swift
@@ -0,0 +1,269 @@
+/*
+ * MIT License
+ *
+ * Copyright (c) 2016 Gabriel Maccori Kozma
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+import UIKit
+
+//**********************************************************************************************************
+//
+// MARK: - Constants -
+//
+//**********************************************************************************************************
+
+//**********************************************************************************************************
+//
+// MARK: - Definitions -
+//
+//**********************************************************************************************************
+
+//**********************************************************************************************************
+//
+// MARK: - Class -
+//
+//**********************************************************************************************************
+
+open class SwiftMaskTextfield : UITextField {
+
+//**************************************************
+// MARK: - Properties
+//**************************************************
+
+ public let lettersAndDigitsReplacementChar: String = "*"
+ public let anyLetterReplecementChar: String = "@"
+ public let lowerCaseLetterReplecementChar: String = "a"
+ public let upperCaseLetterReplecementChar: String = "A"
+ public let digitsReplecementChar: String = "#"
+
+ /**
+ Var that holds the format pattern that you wish to apply
+ to some text
+
+ If the pattern is set to "" no mask would be applied and
+ the textfield would behave like a normal one
+ */
+ @IBInspectable open var formatPattern: String = ""
+
+ /**
+ Var that holds the prefix to be added to the textfield
+
+ If the prefix is set to "" no string will be added to the beggining
+ of the text
+ */
+ @IBInspectable open var prefix: String = ""
+
+ /**
+ Var that have the maximum length, based on the mask set
+ */
+ open var maxLength: Int {
+ get {
+ return formatPattern.count + prefix.count
+ }
+ }
+
+ /**
+ Overriding the var text from UITextField so if any text
+ is applied programmatically by calling formatText
+ */
+ override open var text: String? {
+ set {
+ super.text = newValue
+ self.formatText()
+ }
+
+ get {
+ return super.text
+ }
+ }
+
+//**************************************************
+// MARK: - Constructors
+//**************************************************
+
+ public required init?(coder aDecoder: NSCoder) {
+ super.init(coder: aDecoder)
+ self.setup()
+ }
+
+ public override init(frame: CGRect) {
+ super.init(frame: frame)
+ self.setup()
+ }
+
+ deinit {
+ self.deRegisterForNotifications()
+ }
+
+//**************************************************
+// MARK: - Private Methods
+//**************************************************
+
+ fileprivate func setup() {
+ self.registerForNotifications()
+ }
+
+ fileprivate func registerForNotifications() {
+ NotificationCenter.default.addObserver(self,
+ selector: #selector(textDidChange),
+ name: NSNotification.Name(rawValue: "UITextFieldTextDidChangeNotification"),
+ object: self)
+ }
+
+ fileprivate func deRegisterForNotifications() {
+ NotificationCenter.default.removeObserver(self)
+ }
+
+ @objc fileprivate func textDidChange() {
+ self.undoManager?.removeAllActions()
+ self.formatText()
+ }
+
+ fileprivate func getOnlyDigitsString(_ string: String) -> String {
+ let charactersArray = string.components(separatedBy: CharacterSet.decimalDigits.inverted)
+ return charactersArray.joined(separator: "")
+ }
+
+ fileprivate func getOnlyLettersString(_ string: String) -> String {
+ let charactersArray = string.components(separatedBy: CharacterSet.letters.inverted)
+ return charactersArray.joined(separator: "")
+ }
+
+ fileprivate func getUppercaseLettersString(_ string: String) -> String {
+ let charactersArray = string.components(separatedBy: CharacterSet.uppercaseLetters.inverted)
+ return charactersArray.joined(separator: "")
+ }
+
+ fileprivate func getLowercaseLettersString(_ string: String) -> String {
+ let charactersArray = string.components(separatedBy: CharacterSet.lowercaseLetters.inverted)
+ return charactersArray.joined(separator: "")
+ }
+
+ fileprivate func getFilteredString(_ string: String) -> String {
+ let charactersArray = string.components(separatedBy: CharacterSet.alphanumerics.inverted)
+ return charactersArray.joined(separator: "")
+ }
+
+ fileprivate func getStringWithoutPrefix(_ string: String) -> String {
+ if string.range(of: self.prefix) != nil {
+ if string.count > self.prefix.count {
+ let prefixIndex = string.index(string.endIndex, offsetBy: (string.count - self.prefix.count) * -1)
+ return String(string[prefixIndex...])
+ } else if string.count == self.prefix.count {
+ return ""
+ }
+
+ }
+ return string
+ }
+
+//**************************************************
+// MARK: - Self Public Methods
+//**************************************************
+
+ /**
+ Func that formats the text based on formatPattern
+
+ Override this function if you want to customize the behaviour of
+ the class
+ */
+ open func formatText() {
+ var currentTextForFormatting = ""
+
+ if let text = super.text {
+ if text.count > 0 {
+ currentTextForFormatting = self.getStringWithoutPrefix(text)
+ }
+ }
+
+ if self.maxLength > 0 {
+ var formatterIndex = self.formatPattern.startIndex, currentTextForFormattingIndex = currentTextForFormatting.startIndex
+ var finalText = ""
+
+ currentTextForFormatting = self.getFilteredString(currentTextForFormatting)
+
+ if currentTextForFormatting.count > 0 {
+ while true {
+ let formatPatternRange = formatterIndex ..< formatPattern.index(after: formatterIndex)
+ let currentFormatCharacter = String(self.formatPattern[formatPatternRange])
+
+ let currentTextForFormattingPatterRange = currentTextForFormattingIndex ..< currentTextForFormatting.index(after: currentTextForFormattingIndex)
+ let currentTextForFormattingCharacter = String(currentTextForFormatting[currentTextForFormattingPatterRange])
+
+ switch currentFormatCharacter {
+ case self.lettersAndDigitsReplacementChar:
+ finalText += currentTextForFormattingCharacter
+ currentTextForFormattingIndex = currentTextForFormatting.index(after: currentTextForFormattingIndex)
+ formatterIndex = formatPattern.index(after: formatterIndex)
+ case self.anyLetterReplecementChar:
+ let filteredChar = self.getOnlyLettersString(currentTextForFormattingCharacter)
+ if !filteredChar.isEmpty {
+ finalText += filteredChar
+ formatterIndex = formatPattern.index(after: formatterIndex)
+ }
+ currentTextForFormattingIndex = currentTextForFormatting.index(after: currentTextForFormattingIndex)
+ case self.lowerCaseLetterReplecementChar:
+ let filteredChar = self.getLowercaseLettersString(currentTextForFormattingCharacter)
+ if !filteredChar.isEmpty {
+ finalText += filteredChar
+ formatterIndex = formatPattern.index(after: formatterIndex)
+ }
+ currentTextForFormattingIndex = currentTextForFormatting.index(after: currentTextForFormattingIndex)
+ case self.upperCaseLetterReplecementChar:
+ let filteredChar = self.getUppercaseLettersString(currentTextForFormattingCharacter)
+ if !filteredChar.isEmpty {
+ finalText += filteredChar
+ formatterIndex = formatPattern.index(after: formatterIndex)
+ }
+ currentTextForFormattingIndex = currentTextForFormatting.index(after: currentTextForFormattingIndex)
+ case self.digitsReplecementChar:
+ let filteredChar = self.getOnlyDigitsString(currentTextForFormattingCharacter)
+ if !filteredChar.isEmpty {
+ finalText += filteredChar
+ formatterIndex = formatPattern.index(after: formatterIndex)
+ }
+ currentTextForFormattingIndex = currentTextForFormatting.index(after: currentTextForFormattingIndex)
+ default:
+ finalText += currentFormatCharacter
+ formatterIndex = formatPattern.index(after: formatterIndex)
+ }
+
+ if formatterIndex >= self.formatPattern.endIndex ||
+ currentTextForFormattingIndex >= currentTextForFormatting.endIndex {
+ break
+ }
+ }
+ }
+
+ if finalText.count > 0 {
+ super.text = "\(self.prefix)\(finalText)"
+ } else {
+ super.text = finalText
+ }
+
+ if let text = self.text {
+ if text.count > self.maxLength {
+ super.text = String(text[text.index(text.startIndex, offsetBy: self.maxLength)])
+ }
+ }
+ }
+ }
+}
diff --git a/AutoCat2/ViewController.swift b/AutoCat2/ViewController.swift
new file mode 100644
index 0000000..14df048
--- /dev/null
+++ b/AutoCat2/ViewController.swift
@@ -0,0 +1,19 @@
+//
+// ViewController.swift
+// AutoCat2
+//
+// Created by Selim Mustafaev on 05.03.2022.
+//
+
+import UIKit
+
+class ViewController: UIViewController {
+
+ override func viewDidLoad() {
+ super.viewDidLoad()
+ // Do any additional setup after loading the view.
+ }
+
+
+}
+
diff --git a/AutoCat2Tests/Api/Lib/ApiMethodMockProtocol.swift b/AutoCat2Tests/Api/Lib/ApiMethodMockProtocol.swift
deleted file mode 100644
index bf45947..0000000
--- a/AutoCat2Tests/Api/Lib/ApiMethodMockProtocol.swift
+++ /dev/null
@@ -1,7 +0,0 @@
-import Foundation
-
-protocol ApiMethodMockProtocol {
- var path: String { get }
- var httpMethod: String { get }
- func response(headers: [String: String], params: [String: Any]) -> (status: Int, data: Data?)
-}
diff --git a/AutoCat2Tests/Api/Lib/MockURLProtocol.swift b/AutoCat2Tests/Api/Lib/MockURLProtocol.swift
deleted file mode 100644
index b60320c..0000000
--- a/AutoCat2Tests/Api/Lib/MockURLProtocol.swift
+++ /dev/null
@@ -1,96 +0,0 @@
-import Foundation
-
-extension URL {
- public var queryParameters: [String: String]? {
- guard
- let components = URLComponents(url: self, resolvingAgainstBaseURL: true),
- let queryItems = components.queryItems else { return nil }
- return queryItems.reduce(into: [String: String]()) { (result, item) in
- result[item.name] = item.value
- }
- }
-}
-
-extension URLRequest {
- func bodySteamAsJSON() -> [String: Any]? {
- guard let bodyStream = self.httpBodyStream else { return nil }
-
- bodyStream.open()
-
- // Will read 16 chars per iteration. Can use bigger buffer if needed
- let bufferSize: Int = 16
- let buffer = UnsafeMutablePointer.allocate(capacity: bufferSize)
- var dat = Data()
-
- while bodyStream.hasBytesAvailable {
- let readDat = bodyStream.read(buffer, maxLength: bufferSize)
- dat.append(buffer, count: readDat)
- }
-
- buffer.deallocate()
- bodyStream.close()
-
- return try? JSONSerialization.jsonObject(with: dat, options: JSONSerialization.ReadingOptions.allowFragments) as? [String: Any]
- }
-}
-
-class MockURLProtocol: URLProtocol {
-
- static var baseUrl: String = ""
- static var apiMethodMocks: [ApiMethodMockProtocol] = []
-
- override class func canInit(with request: URLRequest) -> Bool {
- return true
- }
-
- override class func canonicalRequest(for request: URLRequest) -> URLRequest {
- return request
- }
-
- override func startLoading() {
- guard let requestUrl = request.url else { return }
-
- let methodMock = MockURLProtocol.apiMethodMocks.first {
- return request.url?.absoluteString == MockURLProtocol.baseUrl + $0.path
- && request.httpMethod == $0.httpMethod
- }
-
- guard let methodMock = methodMock else {
- if let response = HTTPURLResponse(url: requestUrl, statusCode: 404, httpVersion: "HTTP/2", headerFields: [:]) {
- client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed)
- client?.urlProtocolDidFinishLoading(self)
- }
-
- return
- }
-
- // Assuming we use url parameters in GET requests and JSON-encoded body in everything else
- var params: [String: Any] = [:]
- if request.httpBodyStream != nil {
- if let bodyDict = request.bodySteamAsJSON() {
- params = bodyDict
- }
- } else {
- if let urlParams = requestUrl.queryParameters {
- params = urlParams
- }
- }
-
- let result = methodMock.response(headers: request.allHTTPHeaderFields ?? [:], params: params)
- guard let response = HTTPURLResponse(url: requestUrl, statusCode: result.status, httpVersion: "HTTP/2", headerFields: [:]) else { return }
-
- client?.urlProtocol(self, didReceive: response, cacheStoragePolicy: .notAllowed)
-
- if let data = result.data {
- client?.urlProtocol(self, didLoad: data)
- }
-
- client?.urlProtocolDidFinishLoading(self)
-
- //client?.urlProtocol(self, didFailWithError: error)
- }
-
- override func stopLoading() {
-
- }
-}
diff --git a/AutoCat2Tests/Api/Mocks/ApiMethodMock.swift b/AutoCat2Tests/Api/Mocks/ApiMethodMock.swift
deleted file mode 100644
index f4e82ff..0000000
--- a/AutoCat2Tests/Api/Mocks/ApiMethodMock.swift
+++ /dev/null
@@ -1,39 +0,0 @@
-import Foundation
-import AutoCat2
-
-open class ApiMethodMock: ApiMethodMockProtocol {
-
- private(set) var path: String
- private(set) var httpMethod: String
-
- init(httpMethod: String, path: String) {
- self.httpMethod = httpMethod
- self.path = path
- }
-
- func readData(from path: String) -> Data? {
- guard let url = Bundle(for: type(of: self)).url(forResource: path, withExtension: "json") else { return nil }
- return try? Data(contentsOf: url)
- }
-
- func error(message: String, code: ApiErrorCode? = nil) -> Data? {
- var errorData: [String: AnyEncodable] = [
- "success": false,
- "error": AnyEncodable(message)
- ]
-
- if let code = code {
- errorData["errorCode"] = AnyEncodable(code)
- }
-
- return try? JSONEncoder().encode(errorData)
- }
-
- func notFoundResponse() -> (status: Int, data: Data?) {
- return (status: 404, data: self.error(message: "Not found"))
- }
-
- open func response(headers: [String : String], params: [String : Any]) -> (status: Int, data: Data?) {
- return self.notFoundResponse()
- }
-}
diff --git a/AutoCat2Tests/Api/Mocks/LoginMethodMock.swift b/AutoCat2Tests/Api/Mocks/LoginMethodMock.swift
deleted file mode 100644
index 837f49b..0000000
--- a/AutoCat2Tests/Api/Mocks/LoginMethodMock.swift
+++ /dev/null
@@ -1,24 +0,0 @@
-import Foundation
-
-class LoginMethodMock: ApiMethodMock {
- private var login: String
- private var password: String
-
- init(httpMethod: String, path: String, login: String, password: String) {
- self.login = login
- self.password = password
- super.init(httpMethod: httpMethod, path: path)
- }
-
- override func response(headers: [String : String], params: [String : Any]) -> (status: Int, data: Data?) {
- guard let login = params["email"] as? String, let password = params["password"] as? String else {
- return (status: 400, data: self.error(message: "Invalid parameters"))
- }
-
- if login != self.login || password != self.password {
- return (status: 200, data: self.error(message: "Incorrect login or password", code: .invalidLoginOrPassword))
- }
-
- return (status: 200, data: readData(from: "login_success"))
- }
-}
diff --git a/AutoCat2Tests/Api/Responses/login_success.json b/AutoCat2Tests/Api/Responses/login_success.json
deleted file mode 100644
index 60c13de..0000000
--- a/AutoCat2Tests/Api/Responses/login_success.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "success": true,
- "data": {
- "_id": "832c1bd4-5caa-4c9d-b24c-4c000cd8a793",
- "email": "selim@fastmail.fm",
- "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6InNlbGltQGZhc3RtYWlsLmZtIiwiaWF0IjoxNjI2MjgwNDgxLCJleHAiOjE2NTc4MTY0ODF9.eU6wpacgCSnhM4EiyMY2lUptsfSfHz9guuvOsAw4X90"
- }
-}
diff --git a/AutoCat2Tests/ApiTests.swift b/AutoCat2Tests/ApiTests.swift
deleted file mode 100644
index df060d4..0000000
--- a/AutoCat2Tests/ApiTests.swift
+++ /dev/null
@@ -1,45 +0,0 @@
-import XCTest
-import AutoCat2
-
-class ApiTests: XCTestCase {
-
- private var api: ApiProtocol!
-
- private let testLogin = "test@gmail.com"
- private let testPassword = "12345"
-
- override func setUpWithError() throws {
- MockURLProtocol.baseUrl = Constants.baseUrl
- MockURLProtocol.apiMethodMocks = [
- LoginMethodMock(httpMethod: "POST", path: "user/login", login: self.testLogin, password: self.testPassword)
- ]
-
- let sessionConfig = URLSessionConfiguration.default
- sessionConfig.protocolClasses = [MockURLProtocol.self]
- let session = URLSession(configuration: sessionConfig)
- self.api = Api(session: session)
- }
-
- override func tearDownWithError() throws {
- MockURLProtocol.baseUrl = ""
- MockURLProtocol.apiMethodMocks = []
- }
-
- func testLoginSuccess() async throws {
- let user = try await self.api.login(email: self.testLogin, password: self.testPassword)
- XCTAssertTrue(!user.token.isEmpty)
- }
-
- func testLoginInvalidParams() async throws {
- do {
- _ = try await self.api.login(email: "", password: "")
- } catch let error as ApiError {
- XCTAssertTrue(error.code == .invalidLoginOrPassword)
- return
- } catch {
- XCTFail("Wrong exception type")
- }
-
- XCTFail("Exception expected")
- }
-}
diff --git a/AutoCat2Tests/AutoCat2Tests.swift b/AutoCat2Tests/AutoCat2Tests.swift
new file mode 100644
index 0000000..bfee03a
--- /dev/null
+++ b/AutoCat2Tests/AutoCat2Tests.swift
@@ -0,0 +1,36 @@
+//
+// AutoCat2Tests.swift
+// AutoCat2Tests
+//
+// Created by Selim Mustafaev on 05.03.2022.
+//
+
+import XCTest
+@testable import AutoCat2
+
+class AutoCat2Tests: XCTestCase {
+
+ override func setUpWithError() throws {
+ // Put setup code here. This method is called before the invocation of each test method in the class.
+ }
+
+ override func tearDownWithError() throws {
+ // Put teardown code here. This method is called after the invocation of each test method in the class.
+ }
+
+ func testExample() throws {
+ // This is an example of a functional test case.
+ // Use XCTAssert and related functions to verify your tests produce the correct results.
+ // Any test you write for XCTest can be annotated as throws and async.
+ // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error.
+ // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards.
+ }
+
+ func testPerformanceExample() throws {
+ // This is an example of a performance test case.
+ self.measure {
+ // Put the code you want to measure the time of here.
+ }
+ }
+
+}
diff --git a/AutoCat2Tests/SettingsTests.swift b/AutoCat2Tests/SettingsTests.swift
deleted file mode 100644
index b290da7..0000000
--- a/AutoCat2Tests/SettingsTests.swift
+++ /dev/null
@@ -1,67 +0,0 @@
-import XCTest
-import AutoCat2
-
-class SettingsTests: XCTestCase {
-
- private var settings: SettingsProtocol!
-
- override func setUpWithError() throws {
- guard let userDefaults = UserDefaults(suiteName: #file) else {
- throw CocoaError.error("Failed to create UserDefaults")
- }
- userDefaults.removePersistentDomain(forName: #file)
- self.settings = Settings(defaults: userDefaults)
- }
-
- override func tearDownWithError() throws {
- // Put teardown code here. This method is called after the invocation of each test method in the class.
- }
-
- func testAlternativeOrder() {
- XCTAssert(self.settings.recognizeAlternativeOrder == false, "recognizeAlternativeOrder: wrong default value")
- self.settings.recognizeAlternativeOrder = true
- XCTAssert(self.settings.recognizeAlternativeOrder == true, "recognizeAlternativeOrder: failed to change value")
- }
-
- func testShortenedNumbers() {
- XCTAssert(self.settings.recognizeShortenedNumbers == false, "recognizeShortenedNumbers: wrong default value")
- self.settings.recognizeShortenedNumbers = true
- XCTAssert(self.settings.recognizeShortenedNumbers == true, "recognizeShortenedNumbers: failed to change value")
- }
-
- func testDefaultRegion() {
- XCTAssert(self.settings.defaultRegion == "161", "defaultRegion: wrong default value")
- self.settings.defaultRegion = "761"
- XCTAssert(self.settings.defaultRegion == "761", "defaultRegion: failed to change value")
- }
-
- func testRecordBeep() {
- XCTAssert(self.settings.recordBeep == false, "recordBeep: wrong default value")
- self.settings.recordBeep = true
- XCTAssert(self.settings.recordBeep == true, "recordBeep: failed to change value")
- }
-
- func testDebugInfo() {
- XCTAssert(self.settings.showDebugInfo == false, "showDebugInfo: wrong default value")
- self.settings.showDebugInfo = true
- XCTAssert(self.settings.showDebugInfo == true, "showDebugInfo: failed to change value")
- }
-
- func testDefaultUser() {
- XCTAssert(self.settings.user.email.isEmpty, "Default user email is not empty")
- XCTAssert(self.settings.user.token.isEmpty, "Default user token is not empty")
- XCTAssert(self.settings.user.firebaseIdToken == nil, "Default user firebase ID token is not nil")
- XCTAssert(self.settings.user.firebaseRefreshToken == nil, "Default user firebase refresh token is not nil")
- }
-
- func testSaveUser() {
- self.settings.user.token = "TestToken"
- XCTAssert(self.settings.user.token == "TestToken", "Failed to save user token to settings")
-
- self.settings.user.firebaseIdToken = "TestFirebaseToken"
- XCTAssert(self.settings.user.firebaseIdToken == "TestFirebaseToken", "Failed to save user firebaseIdToken to settings")
-
- self.settings.user.firebaseRefreshToken = "TestResreshToken"
- XCTAssert(self.settings.user.firebaseRefreshToken == "TestResreshToken", "Failed to save user firebaseRefreshToken to settings")
- }
-}
diff --git a/AutoCat2Tests/SettingsTests.swift.plist b/AutoCat2Tests/SettingsTests.swift.plist
deleted file mode 100644
index 4ac7f85..0000000
Binary files a/AutoCat2Tests/SettingsTests.swift.plist and /dev/null differ
diff --git a/Tests macOS/Tests_macOS.swift b/AutoCat2UITests/AutoCat2UITests.swift
similarity index 91%
rename from Tests macOS/Tests_macOS.swift
rename to AutoCat2UITests/AutoCat2UITests.swift
index c8e41f7..4b40741 100644
--- a/Tests macOS/Tests_macOS.swift
+++ b/AutoCat2UITests/AutoCat2UITests.swift
@@ -1,13 +1,13 @@
//
-// Tests_macOS.swift
-// Tests macOS
+// AutoCat2UITests.swift
+// AutoCat2UITests
//
-// Created by Selim Mustafaev on 04.07.2021.
+// Created by Selim Mustafaev on 05.03.2022.
//
import XCTest
-class Tests_macOS: XCTestCase {
+class AutoCat2UITests: XCTestCase {
override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.
diff --git a/AutoCat2UITests/AutoCat2UITestsLaunchTests.swift b/AutoCat2UITests/AutoCat2UITestsLaunchTests.swift
new file mode 100644
index 0000000..4b30d7e
--- /dev/null
+++ b/AutoCat2UITests/AutoCat2UITestsLaunchTests.swift
@@ -0,0 +1,32 @@
+//
+// AutoCat2UITestsLaunchTests.swift
+// AutoCat2UITests
+//
+// Created by Selim Mustafaev on 05.03.2022.
+//
+
+import XCTest
+
+class AutoCat2UITestsLaunchTests: XCTestCase {
+
+ override class var runsForEachTargetApplicationUIConfiguration: Bool {
+ true
+ }
+
+ override func setUpWithError() throws {
+ continueAfterFailure = false
+ }
+
+ func testLaunch() throws {
+ let app = XCUIApplication()
+ app.launch()
+
+ // Insert steps here to perform after app launch but before taking a screenshot,
+ // such as logging into a test account or navigating somewhere in the app
+
+ let attachment = XCTAttachment(screenshot: app.screenshot())
+ attachment.name = "Launch Screen"
+ attachment.lifetime = .keepAlways
+ add(attachment)
+ }
+}
diff --git a/Shared/AutoCat2.xcdatamodeld/.xccurrentversion b/AutoCatCore/AutoCat2.xcdatamodeld/.xccurrentversion
similarity index 100%
rename from Shared/AutoCat2.xcdatamodeld/.xccurrentversion
rename to AutoCatCore/AutoCat2.xcdatamodeld/.xccurrentversion
diff --git a/Shared/AutoCat2.xcdatamodeld/Shared.xcdatamodel/contents b/AutoCatCore/AutoCat2.xcdatamodeld/Shared.xcdatamodel/contents
similarity index 81%
rename from Shared/AutoCat2.xcdatamodeld/Shared.xcdatamodel/contents
rename to AutoCatCore/AutoCat2.xcdatamodeld/Shared.xcdatamodel/contents
index ef04a39..480e6a4 100644
--- a/Shared/AutoCat2.xcdatamodeld/Shared.xcdatamodel/contents
+++ b/AutoCatCore/AutoCat2.xcdatamodeld/Shared.xcdatamodel/contents
@@ -1,16 +1,16 @@
-
-
+
+
-
+
-
+
diff --git a/AutoCatCore/AutoCatCore.docc/AutoCatCore.md b/AutoCatCore/AutoCatCore.docc/AutoCatCore.md
new file mode 100755
index 0000000..6cff9e5
--- /dev/null
+++ b/AutoCatCore/AutoCatCore.docc/AutoCatCore.md
@@ -0,0 +1,13 @@
+# ``AutoCatCore``
+
+Summary
+
+## Overview
+
+Text
+
+## Topics
+
+### Group
+
+- ``Symbol``
\ No newline at end of file
diff --git a/AutoCatCore/AutoCatCore.h b/AutoCatCore/AutoCatCore.h
new file mode 100644
index 0000000..c9cf052
--- /dev/null
+++ b/AutoCatCore/AutoCatCore.h
@@ -0,0 +1,18 @@
+//
+// AutoCatCore.h
+// AutoCatCore
+//
+// Created by Selim Mustafaev on 05.03.2022.
+//
+
+#import
+
+//! Project version number for AutoCatCore.
+FOUNDATION_EXPORT double AutoCatCoreVersionNumber;
+
+//! Project version string for AutoCatCore.
+FOUNDATION_EXPORT const unsigned char AutoCatCoreVersionString[];
+
+// In this header, you should import all the public headers of your framework using statements like #import
+
+
diff --git a/Shared/Models/PlateNumber.swift b/AutoCatCore/Models/PlateNumber.swift
similarity index 100%
rename from Shared/Models/PlateNumber.swift
rename to AutoCatCore/Models/PlateNumber.swift
diff --git a/Shared/Models/Response.swift b/AutoCatCore/Models/Response.swift
similarity index 85%
rename from Shared/Models/Response.swift
rename to AutoCatCore/Models/Response.swift
index be792a0..c499b71 100644
--- a/Shared/Models/Response.swift
+++ b/AutoCatCore/Models/Response.swift
@@ -4,7 +4,7 @@ class Response: Decodable where T: Decodable {
let success: Bool
let data: T?
let error: String?
- let errorCode: ApiErrorCode?
+ let errorCode: Int?
enum CodingKeys: String, CodingKey {
case success
@@ -22,7 +22,7 @@ class Response: Decodable where T: Decodable {
errorCode = nil
} else {
error = try container.decode(String.self, forKey: .error)
- errorCode = try container.decodeIfPresent(ApiErrorCode.self, forKey: .errorCode)
+ errorCode = try container.decodeIfPresent(Int.self, forKey: .errorCode)
data = nil
}
}
diff --git a/Shared/Models/Settings.swift b/AutoCatCore/Models/Settings.swift
similarity index 100%
rename from Shared/Models/Settings.swift
rename to AutoCatCore/Models/Settings.swift
diff --git a/Shared/Models/User.swift b/AutoCatCore/Models/User.swift
similarity index 100%
rename from Shared/Models/User.swift
rename to AutoCatCore/Models/User.swift
diff --git a/Shared/Models/VBrand.swift b/AutoCatCore/Models/VBrand.swift
similarity index 100%
rename from Shared/Models/VBrand.swift
rename to AutoCatCore/Models/VBrand.swift
diff --git a/Shared/Models/VName.swift b/AutoCatCore/Models/VName.swift
similarity index 100%
rename from Shared/Models/VName.swift
rename to AutoCatCore/Models/VName.swift
diff --git a/Shared/Models/Vehicle.swift b/AutoCatCore/Models/Vehicle.swift
similarity index 100%
rename from Shared/Models/Vehicle.swift
rename to AutoCatCore/Models/Vehicle.swift
diff --git a/Shared/Services/StorageService.swift b/AutoCatCore/Services/StorageService.swift
similarity index 53%
rename from Shared/Services/StorageService.swift
rename to AutoCatCore/Services/StorageService.swift
index 884e213..d7b2740 100644
--- a/Shared/Services/StorageService.swift
+++ b/AutoCatCore/Services/StorageService.swift
@@ -11,21 +11,37 @@ class StorageService: StorageServiceProtocol {
private let container: NSPersistentCloudKitContainer
- static let shared = StorageService()
+ static var shared: StorageService {
+ get async throws {
+ print("!!!!!!!!!!!!!!!!!!!!!!!!! StorageService init")
+ let service = StorageService()
+ try await service.loadPersistentStores()
+ return service
+ }
+ }
init(inMemory: Bool = false) {
- container = NSPersistentCloudKitContainer(name: "AutoCat2")
+ let bundle = Bundle(for: Self.self)
+ let url = bundle.url(forResource: "AutoCat2", withExtension: "momd")
+ let mom = NSManagedObjectModel(contentsOf: url!)
+
+ container = NSPersistentCloudKitContainer(name: "AutoCat2", managedObjectModel: mom!)
if inMemory {
container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
}
-
- container.loadPersistentStores(completionHandler: { (storeDescription, error) in
- if let error = error as NSError? {
- // TODO: Handle error properly
- fatalError("Unresolved error \(error), \(error.userInfo)")
- }
- })
+ }
+
+ private func loadPersistentStores() async throws {
+ try await withCheckedThrowingContinuation { (continuation: CheckedContinuation) in
+ container.loadPersistentStores(completionHandler: { (storeDescription, error) in
+ if let error = error as NSError? {
+ continuation.resume(throwing: error)
+ } else {
+ continuation.resume(returning: ())
+ }
+ })
+ }
}
private func save() throws {
diff --git a/Shared/Services/VehicleService.swift b/AutoCatCore/Services/VehicleService.swift
similarity index 58%
rename from Shared/Services/VehicleService.swift
rename to AutoCatCore/Services/VehicleService.swift
index 502096a..9c46535 100644
--- a/Shared/Services/VehicleService.swift
+++ b/AutoCatCore/Services/VehicleService.swift
@@ -5,14 +5,19 @@ protocol VehicleServiceProtocol {
func check(plateNumber: String, force: Bool) async throws -> CDVehicle
}
-class VehicleService: VehicleServiceProtocol {
+public class VehicleService: VehicleServiceProtocol {
private let api: ApiProtocol
private let storage: StorageServiceProtocol
- static let shared = VehicleService()
+ public static var shared: VehicleService {
+ get async throws {
+ let storageService = try await StorageService.shared
+ return VehicleService(api: Api.shared, storage: storageService)
+ }
+ }
- init(api: ApiProtocol = Api.shared, storage: StorageServiceProtocol = StorageService.shared) {
+ init(api: ApiProtocol = Api.shared, storage: StorageServiceProtocol) {
self.api = api
self.storage = storage
@@ -20,7 +25,8 @@ class VehicleService: VehicleServiceProtocol {
// MARK: - VehicleServiceProtocol
- func check(plateNumber: String, force: Bool) async throws -> CDVehicle {
+ @discardableResult
+ public func check(plateNumber: String, force: Bool) async throws -> CDVehicle {
let vehicle = try await api.check(plateNumber: plateNumber, force: force)
return try storage.store(vehicle: vehicle)
diff --git a/Shared/ThirdParty/AnyEncodable.swift b/AutoCatCore/ThirdParty/AnyEncodable.swift
similarity index 100%
rename from Shared/ThirdParty/AnyEncodable.swift
rename to AutoCatCore/ThirdParty/AnyEncodable.swift
diff --git a/Shared/Utils/Api.swift b/AutoCatCore/Utils/Api.swift
similarity index 62%
rename from Shared/Utils/Api.swift
rename to AutoCatCore/Utils/Api.swift
index bd62446..4288f41 100644
--- a/Shared/Utils/Api.swift
+++ b/AutoCatCore/Utils/Api.swift
@@ -30,10 +30,6 @@ public class Api: ApiProtocol {
// MARK: - Private wrappres
- private func genError(_ msg: String, suggestion: String, code: Int = 0) -> Error {
- return NSError(domain: "", code: code, userInfo: [NSLocalizedDescriptionKey: msg, NSLocalizedRecoverySuggestionErrorKey: suggestion])
- }
-
private func createRequest(api: String, method: String, body: B? = nil, params: [String:P]? = nil) -> URLRequest? where B: Encodable, P: LosslessStringConvertible {
guard var urlComponents = URLComponents(string: Constants.baseUrl + api) else { return nil }
@@ -60,38 +56,54 @@ public class Api: ApiProtocol {
private func makeRequest(api: String, method: String = "GET", body: B?, params: [String:P]? = nil) async throws -> T where T: Decodable, B: Encodable, P: LosslessStringConvertible {
guard let request = self.createRequest(api: api, method: method, body: body, params: params) else {
- throw self.genError("Error creating request", suggestion: "")
+ throw ApiError.message("Error creating request")
}
- let (data, response) = try await self.session.data(for: request)
- guard let httpResponse = response as? HTTPURLResponse else {
- throw self.genError("non-HTTP response received", suggestion: "")
- }
-
- // let str = String(data: data, encoding: .utf8)
- // print("================================")
- // if let string = str?.replacingOccurrences(of: "\\\"", with: "\"")
- // .replacingOccurrences(of: "\\'", with: "'")
- // .replacingOccurrences(of: "\\n", with: "") {
- // print(string)
- // }
- // print("================================")
-
- do {
- if data.count > 0 {
- let resp = try JSONDecoder().decode(Response.self, from: data)
- if resp.success {
- return resp.data!
- } else {
- throw ApiError(httpStatus: httpResponse.statusCode, message: resp.error, code: resp.errorCode)
+ return try await withCheckedThrowingContinuation { (continuation: CheckedContinuation) in
+
+ let task = self.session.dataTask(with: request) { data, response, error in
+
+ if let error = error {
+ continuation.resume(throwing: error)
+ return
+ }
+
+ guard let data = data, data.count > 0 else {
+ continuation.resume(throwing: ApiError.message("No data in response"))
+ return
+ }
+
+
+ // let str = String(data: data, encoding: .utf8)
+ // print("================================")
+ // if let string = str?.replacingOccurrences(of: "\\\"", with: "\"")
+ // .replacingOccurrences(of: "\\'", with: "'")
+ // .replacingOccurrences(of: "\\n", with: "") {
+ // print(string)
+ // }
+ // print("================================")
+
+ do {
+ let resp = try JSONDecoder().decode(Response.self, from: data)
+ if resp.success {
+ continuation.resume(returning: resp.data!)
+ } else {
+ if let code = resp.errorCode {
+ continuation.resume(throwing: ApiError(code: code))
+ } else if let errorMessage = resp.error {
+ continuation.resume(throwing: ApiError.message(errorMessage))
+ } else {
+ continuation.resume(throwing: ApiError.generic)
+ }
+ }
+ } catch let error as Swift.DecodingError {
+ continuation.resume(throwing: ApiError.message((error as CustomDebugStringConvertible).debugDescription))
+ } catch {
+ continuation.resume(throwing: error)
}
- } else {
- throw ApiError(httpStatus: httpResponse.statusCode)
}
- } catch let error as Swift.DecodingError {
- throw CocoaError.error((error as CustomDebugStringConvertible).debugDescription)
- } catch {
- throw error
+
+ task.resume()
}
}
@@ -113,6 +125,7 @@ public class Api: ApiProtocol {
// MARK: - AutoCat public API
+ @MainActor
public func login(email: String, password: String) async throws -> User {
let body = [
@@ -122,7 +135,19 @@ public class Api: ApiProtocol {
return try await self.makeBodyRequest(api: "user/login", body: body)
}
+
+ @MainActor
+ public func signup(email: String, password: String) async throws -> User {
+
+ let body = [
+ "email": email,
+ "password": password
+ ]
+
+ return try await self.makeBodyRequest(api: "user/signup", body: body)
+ }
+ @MainActor
public func check(plateNumber: String, force: Bool = false) async throws -> Vehicle {
var body = [
diff --git a/AutoCatCore/Utils/ApiError.swift b/AutoCatCore/Utils/ApiError.swift
new file mode 100644
index 0000000..8de2cb9
--- /dev/null
+++ b/AutoCatCore/Utils/ApiError.swift
@@ -0,0 +1,31 @@
+import Foundation
+
+public enum ApiError: LocalizedError {
+
+ case generic
+ case message(String)
+ case httpError(Int)
+ case invalidLoginOrPassword
+
+ public var errorDescription: String? {
+ switch self {
+ case .generic:
+ return "Something bad happened"
+ case .message(let message):
+ return message
+ case .httpError(let status):
+ return "General http error (status \(status))"
+ case .invalidLoginOrPassword:
+ return "Invalid login or password"
+ }
+ }
+
+ init(code: Int) {
+ switch code {
+ case 0:
+ self = .invalidLoginOrPassword
+ default:
+ self = .generic
+ }
+ }
+}
diff --git a/Shared/Utils/Constants.swift b/AutoCatCore/Utils/Constants.swift
similarity index 100%
rename from Shared/Utils/Constants.swift
rename to AutoCatCore/Utils/Constants.swift
diff --git a/AutoCatCoreTests/AutoCatCoreTests.swift b/AutoCatCoreTests/AutoCatCoreTests.swift
new file mode 100644
index 0000000..95ed638
--- /dev/null
+++ b/AutoCatCoreTests/AutoCatCoreTests.swift
@@ -0,0 +1,36 @@
+//
+// AutoCatCoreTests.swift
+// AutoCatCoreTests
+//
+// Created by Selim Mustafaev on 05.03.2022.
+//
+
+import XCTest
+@testable import AutoCatCore
+
+class AutoCatCoreTests: XCTestCase {
+
+ override func setUpWithError() throws {
+ // Put setup code here. This method is called before the invocation of each test method in the class.
+ }
+
+ override func tearDownWithError() throws {
+ // Put teardown code here. This method is called after the invocation of each test method in the class.
+ }
+
+ func testExample() throws {
+ // This is an example of a functional test case.
+ // Use XCTAssert and related functions to verify your tests produce the correct results.
+ // Any test you write for XCTest can be annotated as throws and async.
+ // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error.
+ // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards.
+ }
+
+ func testPerformanceExample() throws {
+ // This is an example of a performance test case.
+ self.measure {
+ // Put the code you want to measure the time of here.
+ }
+ }
+
+}
diff --git a/Shared/Assets.xcassets/Colors/PlateBackgroundError.colorset/Contents.json b/Shared/Assets.xcassets/Colors/PlateBackgroundError.colorset/Contents.json
deleted file mode 100644
index dcf9455..0000000
--- a/Shared/Assets.xcassets/Colors/PlateBackgroundError.colorset/Contents.json
+++ /dev/null
@@ -1,38 +0,0 @@
-{
- "colors" : [
- {
- "color" : {
- "color-space" : "display-p3",
- "components" : {
- "alpha" : "1.000",
- "blue" : "0.000",
- "green" : "0.000",
- "red" : "1.000"
- }
- },
- "idiom" : "universal"
- },
- {
- "appearances" : [
- {
- "appearance" : "luminosity",
- "value" : "dark"
- }
- ],
- "color" : {
- "color-space" : "display-p3",
- "components" : {
- "alpha" : "1.000",
- "blue" : "0.182",
- "green" : "0.225",
- "red" : "1.000"
- }
- },
- "idiom" : "universal"
- }
- ],
- "info" : {
- "author" : "xcode",
- "version" : 1
- }
-}
diff --git a/Shared/AutoCat2App.swift b/Shared/AutoCat2App.swift
deleted file mode 100644
index af0a06e..0000000
--- a/Shared/AutoCat2App.swift
+++ /dev/null
@@ -1,20 +0,0 @@
-//
-// AutoCat2App.swift
-// Shared
-//
-// Created by Selim Mustafaev on 04.07.2021.
-//
-
-import SwiftUI
-
-@main
-struct AutoCat2App: App {
- let storageService = StorageService.shared
-
- var body: some Scene {
- WindowGroup {
- ContentView()
- .environment(\.managedObjectContext, storageService.context)
- }
- }
-}
diff --git a/Shared/Extensions/Alert.swift b/Shared/Extensions/Alert.swift
deleted file mode 100644
index b6d95d2..0000000
--- a/Shared/Extensions/Alert.swift
+++ /dev/null
@@ -1,28 +0,0 @@
-import Foundation
-import SwiftUI
-
-enum AlertMessage: Identifiable {
- case info(title: String, body: String)
- case error(error: Error)
-
- var id: Int {
- switch self {
- case .info(let title, let body):
- return title.hashValue + body.hashValue
- case .error(let error):
- return error.localizedDescription.hashValue
- }
- }
-}
-
-extension Alert {
- init(_ message: AlertMessage) {
- switch message {
- case .info(let title, let body):
- self.init(title: Text(title), message: Text(body))
- case .error(let error):
- let msg = (error as NSError).displayMessage
- self.init(title: Text(msg.title), message: Text(msg.body))
- }
- }
-}
diff --git a/Shared/Extensions/CocoaError.swift b/Shared/Extensions/CocoaError.swift
deleted file mode 100644
index 94f74b0..0000000
--- a/Shared/Extensions/CocoaError.swift
+++ /dev/null
@@ -1,68 +0,0 @@
-import CoreLocation
-
-extension NSError {
- public var displayMessage: (title: String, body: String) {
-// if let description = self.userInfo[NSLocalizedDescriptionKey] as? String {
-// return (title: "Error", body: description)
-// } else if let failure = self.userInfo[NSLocalizedFailureErrorKey] as? String, let reason = self.localizedFailureReason {
-// if let recovery = self.localizedRecoverySuggestion {
-// return (title: failure, body: reason + "\n" + recovery)
-// } else {
-// return (title: failure, body: reason)
-// }
-// } else {
-// return (title: "Error", body: "")
-// }
-
- if let recovery = self.localizedRecoverySuggestion {
- return (title: "Error", body: self.localizedDescription + "\n" + recovery)
- } else {
- return (title: "Error", body: self.localizedDescription)
- }
- }
-}
-
-extension CocoaError {
- public static func error(_ description: String) -> NSError {
- return error(Code(rawValue: 0), userInfo: [NSLocalizedDescriptionKey: description], url: nil) as NSError
- }
-
- public static func error(_ error: String, reason: String, suggestion: String? = nil) -> NSError {
- var info = [
- NSLocalizedFailureErrorKey: error,
- NSLocalizedFailureReasonErrorKey: reason
- ]
-
- if let suggestion = suggestion {
- info[NSLocalizedRecoverySuggestionErrorKey] = suggestion
- }
-
- return self.error(Code(rawValue: 0), userInfo: info, url: nil) as NSError
- }
-}
-
-extension CLError.Code: CustomStringConvertible {
- public var description: String {
- switch self {
- case .locationUnknown: return "Location unknown"
- case .denied: return "Access denied"
- case .network: return "general, network-related error"
- case .headingFailure: return "heading could not be determined"
- case .regionMonitoringDenied: return "Location region monitoring has been denied"
- case .regionMonitoringSetupDelayed: return "CL could not immediately initialize region monitoring"
- case .regionMonitoringResponseDelayed: return "While events for this fence will be delivered, delivery will not occur immediately"
- case .geocodeFoundNoResult: return "A geocode request yielded no result"
- case .geocodeFoundPartialResult: return "A geocode request yielded a partial result"
- case .geocodeCanceled: return "A geocode request was cancelled"
- case .deferredFailed: return "Deferred mode failed"
- case .deferredNotUpdatingLocation: return "Deferred mode failed because location updates disabled or paused"
- case .deferredAccuracyTooLow: return "Deferred mode not supported for the requested accuracy"
- case .deferredDistanceFiltered: return "Deferred mode does not support distance filters"
- case .deferredCanceled: return "Deferred mode request canceled a previous request"
- case .rangingUnavailable: return "Ranging cannot be performed"
- case .rangingFailure: return "General ranging failure"
- case .promptDeclined: return "Authorization request not presented to user"
- default: return "Unknown location error (\(self.rawValue)"
- }
- }
-}
diff --git a/Shared/Persistence.swift b/Shared/Persistence.swift
deleted file mode 100644
index 395345d..0000000
--- a/Shared/Persistence.swift
+++ /dev/null
@@ -1,55 +0,0 @@
-//
-// Persistence.swift
-// Shared
-//
-// Created by Selim Mustafaev on 04.07.2021.
-//
-
-import CoreData
-
-struct PersistenceController {
- static let shared = PersistenceController()
-
- static var preview: PersistenceController = {
- let result = PersistenceController(inMemory: true)
- let viewContext = result.container.viewContext
-// for _ in 0..<10 {
-// let newItem = Item(context: viewContext)
-// newItem.timestamp = Date()
-// }
- do {
- try viewContext.save()
- } catch {
- // Replace this implementation with code to handle the error appropriately.
- // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
- let nsError = error as NSError
- fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
- }
- return result
- }()
-
- let container: NSPersistentCloudKitContainer
-
- init(inMemory: Bool = false) {
- container = NSPersistentCloudKitContainer(name: "AutoCat2")
- if inMemory {
- container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
- }
- container.loadPersistentStores(completionHandler: { (storeDescription, error) in
- if let error = error as NSError? {
- // Replace this implementation with code to handle the error appropriately.
- // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
-
- /*
- Typical reasons for an error here include:
- * The parent directory does not exist, cannot be created, or disallows writing.
- * The persistent store is not accessible, due to permissions or data protection when the device is locked.
- * The device is out of space.
- * The store could not be migrated to the current model version.
- Check the error message to determine what the actual problem was.
- */
- fatalError("Unresolved error \(error), \(error.userInfo)")
- }
- })
- }
-}
diff --git a/Shared/Utils/ApiError.swift b/Shared/Utils/ApiError.swift
deleted file mode 100644
index b1be874..0000000
--- a/Shared/Utils/ApiError.swift
+++ /dev/null
@@ -1,35 +0,0 @@
-import Foundation
-
-public enum ApiErrorCode: Int, CustomStringConvertible, Codable {
- case invalidLoginOrPassword = 0
-
- public var description: String {
- switch self {
- case .invalidLoginOrPassword: return "Invalid login or password"
- }
- }
-}
-
-public class ApiError: LocalizedError {
- public let httpStatus: Int
- public let message: String?
- public let code: ApiErrorCode?
-
- init(httpStatus: Int, message: String? = nil, code: ApiErrorCode? = nil) {
- self.httpStatus = httpStatus
- self.message = message
- self.code = code
- }
-
- public var errorDescription: String? {
- if let code = code {
- return code.description
- }
-
- if let message = message {
- return message
- }
-
- return "General http error (status \(self.httpStatus))"
- }
-}
diff --git a/Shared/ViewModels/AuthVM.swift b/Shared/ViewModels/AuthVM.swift
deleted file mode 100644
index 4a8cdeb..0000000
--- a/Shared/ViewModels/AuthVM.swift
+++ /dev/null
@@ -1,17 +0,0 @@
-import Foundation
-
-public class AuthVM: ObservableObject {
-
- private let api: ApiProtocol
- private var settings: SettingsProtocol
-
- init(api: ApiProtocol = Api.shared, settings: SettingsProtocol = Settings.shared) {
-
- self.api = api
- self.settings = settings
- }
-
- public func login(user: String, password: String) async throws {
- settings.user = try await api.login(email: user, password: password)
- }
-}
diff --git a/Shared/Views/ACProgressView.swift b/Shared/Views/ACProgressView.swift
deleted file mode 100644
index 2eed1cc..0000000
--- a/Shared/Views/ACProgressView.swift
+++ /dev/null
@@ -1,68 +0,0 @@
-import SwiftUI
-
-struct ACProgressView: View {
- @State var isDeterminate: Bool = false
- @State var progress: CGFloat = 0
- @State var text: String? = nil
- @State var isAnimating: Bool = false
-
- var body: some View {
- ZStack(alignment: .center) {
- Color.black.opacity(0.4)
- VStack {
- VStack(spacing: 24) {
- if self.isDeterminate {
- ZStack {
- Circle()
- .stroke(Color.secondary.opacity(0.2), style: StrokeStyle(lineWidth: 4))
- .frame(width: 100, height: 100)
- Circle()
- .trim(from: 0, to: self.progress)
- .stroke(Color.blue, style: StrokeStyle(lineWidth: 4))
- .rotationEffect(.degrees(-90))
- .frame(width: 100, height: 100)
- Text("\(Int(self.progress*100)) %")
- }
- } else {
- let gradient = AngularGradient(
- gradient: Gradient(colors: [Color.blue, Color.blue.opacity(0.01)]),
- center: .center,
- startAngle: .degrees(360),
- endAngle: .degrees(0))
- Circle()
- .stroke(gradient, style: StrokeStyle(lineWidth: 4))
- .rotationEffect(Angle(degrees: self.isAnimating ? 360 : 0))
- .onAppear {
- withAnimation(.linear(duration: 1).repeatForever(autoreverses: false)) {
- self.isAnimating = true
- }
- }
- .onDisappear(perform: {
- self.isAnimating = false
- })
- .frame(width: 100, height: 100)
- }
-
- if let msg = self.text {
- Text(msg)
- }
- }
- .padding(28)
- }
- //.frame(width: 160, height: 160)
- .background(.regularMaterial)
- .cornerRadius(20)
- }
- .edgesIgnoringSafeArea(.all)
- }
-}
-
-struct ACProgressView_Previews: PreviewProvider {
- static var previews: some View {
- Group {
- ACProgressView()
- ACProgressView(isDeterminate: true, progress: 0.3, text: "Loading...")
- .preferredColorScheme(.dark)
- }
- }
-}
diff --git a/Shared/Views/AuthView.swift b/Shared/Views/AuthView.swift
deleted file mode 100644
index ed0b556..0000000
--- a/Shared/Views/AuthView.swift
+++ /dev/null
@@ -1,71 +0,0 @@
-import SwiftUI
-
-struct AuthView: View {
-
- enum Field {
- case email
- case password
- }
-
- @ObservedObject var viewModel = AuthVM()
-
- @State private var login: String = ""
- @State private var password: String = ""
- @State private var showProgress: Bool = false
- @State private var alert: AlertMessage? = nil
- @FocusState private var focus: Field?
-
- var body: some View {
- ZStack {
- VStack(alignment: .center, spacing: 16) {
- Spacer()
- #if os(iOS)
- TextField("Login", text: $login)
- .focused($focus, equals: .email)
- .textContentType(.emailAddress)
- .keyboardType(.emailAddress)
- #else
- TextField("Login", text: $login)
- .focused($focus, equals: .email)
- #endif
- SecureField("Password", text: $password)
- .focused($focus, equals: .password)
- Button("Login") {
- Task.init {
- do {
- self.focus = nil
- self.showProgress = true
- try await self.viewModel.login(user: self.login, password: self.password)
- self.showProgress = false
- } catch {
- self.showProgress = false
- self.alert = .error(error: error)
- }
- }
- }
- .alert(item: $alert, content: Alert.init)
- Spacer()
- }
- .buttonStyle(.bordered)
- .controlSize(.large)
- .textFieldStyle(.roundedBorder)
- .padding(20)
-
- if self.showProgress {
- ACProgressView()
- }
- }
- }
-}
-
-struct AuthView_Previews: PreviewProvider {
- static var previews: some View {
- Group {
- AuthView()
- .previewDevice("iPhone 8")
- AuthView()
- .preferredColorScheme(.dark)
- .previewDevice("iPhone 8")
- }
- }
-}
diff --git a/Shared/Views/CheckView.swift b/Shared/Views/CheckView.swift
deleted file mode 100644
index 8a58a50..0000000
--- a/Shared/Views/CheckView.swift
+++ /dev/null
@@ -1,35 +0,0 @@
-import SwiftUI
-
-struct CheckView: View {
- @State private var number: String = ""
- @FetchRequest(entity: CDVehicle.entity(), sortDescriptors: []) var vehicles: FetchedResults
-
- var body: some View {
- NavigationView {
- VStack(alignment: .center, spacing: 16) {
- TextField("A123AA777", text: $number)
- Button("Check") {
-
- }
- List(vehicles) { vehicle in
- Text(vehicle.number ?? "")
- }
- }
- .toolbar {
- ToolbarItem(placement: .primaryAction) {
- Button("New") {}
- }
- }
- #if os(iOS)
- .navigationBarTitle("Title", displayMode: .inline)
- #endif
- }
- }
-}
-
-struct CheckView_Previews: PreviewProvider {
- static var previews: some View {
- CheckView()
- .preferredColorScheme(.dark)
- }
-}
diff --git a/Shared/Views/ContentView.swift b/Shared/Views/ContentView.swift
deleted file mode 100644
index f1a3363..0000000
--- a/Shared/Views/ContentView.swift
+++ /dev/null
@@ -1,20 +0,0 @@
-import SwiftUI
-import CoreData
-
-struct ContentView: View {
- @StateObject var settings = Settings.shared
-
- var body: some View {
- if settings.user.token.isEmpty {
- AuthView()
- } else {
- MainView()
- }
- }
-}
-
-struct ContentView_Previews: PreviewProvider {
- static var previews: some View {
- ContentView()
- }
-}
diff --git a/Shared/Views/MainView.swift b/Shared/Views/MainView.swift
deleted file mode 100644
index 5abb5de..0000000
--- a/Shared/Views/MainView.swift
+++ /dev/null
@@ -1,17 +0,0 @@
-import SwiftUI
-
-struct MainView: View {
- var body: some View {
- #if os(iOS)
- MainViewSmall()
- #else
- MainViewBig()
- #endif
- }
-}
-
-struct MainView_Previews: PreviewProvider {
- static var previews: some View {
- MainView()
- }
-}
diff --git a/Shared/Views/MainViewSmall.swift b/Shared/Views/MainViewSmall.swift
deleted file mode 100644
index 0facd81..0000000
--- a/Shared/Views/MainViewSmall.swift
+++ /dev/null
@@ -1,45 +0,0 @@
-import SwiftUI
-
-struct MainViewSmall: View {
- var body: some View {
- NavigationView {
- TabView {
- CheckView()
- .tabItem {
- Image(systemName: "eye")
- Text("Check")
- }
- RecordsView()
- .tabItem {
- Image(systemName: "recordingtape")
- Text("Records")
- }
- SearchView()
- .tabItem {
- Image(systemName: "magnifyingglass")
- Text("Search")
- }
- SettingsView()
- .tabItem {
- Image(systemName: "gear")
- Text("Settings")
- }
- }
- #if os(iOS)
- .navigationBarHidden(true)
- #endif
- Text("detail")
- }
- }
-}
-
-struct MainViewSmall_Previews: PreviewProvider {
- static var previews: some View {
- Group {
- MainViewSmall()
- MainViewSmall()
- .previewInterfaceOrientation(.landscapeLeft)
- .previewDevice("iPad Pro (9.7-inch)")
- }
- }
-}
diff --git a/Shared/Views/PlateNumberView.swift b/Shared/Views/PlateNumberView.swift
deleted file mode 100644
index efacb01..0000000
--- a/Shared/Views/PlateNumberView.swift
+++ /dev/null
@@ -1,67 +0,0 @@
-//
-// PlateNumberView.swift
-// AutoCat2
-//
-// Created by Selim Mustafaev on 21.11.2021.
-//
-
-import SwiftUI
-
-struct PlateNumberView: View {
-
- let number: PlateNumber
- let unrecognized: Bool
- let outdated: Bool
-
- private var fgColor: Color {
- if unrecognized {
- return Color("PlateBackgroundError")
- } else {
- return Color("PlateForeground")
- }
- }
-
- var body: some View {
- ZStack {
- RoundedRectangle(cornerRadius: 6)
- .fill(fgColor)
- GeometryReader { geometry in
- HStack(alignment: .center, spacing: 2) {
- ZStack {
- RoundedRectangle(cornerRadius: 4)
- .fill(Color("PlateBackground"))
- Text(number.mainPart())
- .font(Font.custom("RoadNumbers", size: geometry.size.height*0.9))
- }
- .frame(width: geometry.size.width*0.73 - 1)
- ZStack {
- RoundedRectangle(cornerRadius: 4)
- .fill(Color("PlateBackground"))
- VStack(spacing: 0) {
- Text(number.region())
- .frame(height: geometry.size.height*0.65, alignment: .center)
- HStack {
-
- }
- .frame(height: geometry.size.height*0.35, alignment: .center)
- }
- }
- .frame(width: geometry.size.width*0.27 - 1)
- }
- }
- .padding(2)
- }
- .aspectRatio(520.0/112.0, contentMode: .fit)
- }
-}
-
-struct PlateNumberView_Previews: PreviewProvider {
- static var previews: some View {
- Group {
- PlateNumberView(number: PlateNumber("Е201АМ761"), unrecognized: false, outdated: false)
- PlateNumberView(number: PlateNumber("Е201АМ761"), unrecognized: true, outdated: false)
- PlateNumberView(number: PlateNumber("Е201АМ761"), unrecognized: false, outdated: true)
- }
- .previewLayout(.fixed(width: 200, height: 50))
- }
-}
diff --git a/Shared/Views/RecordsView.swift b/Shared/Views/RecordsView.swift
deleted file mode 100644
index 6b9ade4..0000000
--- a/Shared/Views/RecordsView.swift
+++ /dev/null
@@ -1,13 +0,0 @@
-import SwiftUI
-
-struct RecordsView: View {
- var body: some View {
- Text("Records view")
- }
-}
-
-struct RecordsView_Previews: PreviewProvider {
- static var previews: some View {
- RecordsView()
- }
-}
diff --git a/Shared/Views/ReportView.swift b/Shared/Views/ReportView.swift
deleted file mode 100644
index 2808fdc..0000000
--- a/Shared/Views/ReportView.swift
+++ /dev/null
@@ -1,13 +0,0 @@
-import SwiftUI
-
-struct ReportView: View {
- var body: some View {
- Text("Report view")
- }
-}
-
-struct ReportView_Previews: PreviewProvider {
- static var previews: some View {
- ReportView()
- }
-}
diff --git a/Shared/Views/SearchView.swift b/Shared/Views/SearchView.swift
deleted file mode 100644
index 023ae7c..0000000
--- a/Shared/Views/SearchView.swift
+++ /dev/null
@@ -1,13 +0,0 @@
-import SwiftUI
-
-struct SearchView: View {
- var body: some View {
- Text("Search view")
- }
-}
-
-struct SearchView_Previews: PreviewProvider {
- static var previews: some View {
- SearchView()
- }
-}
diff --git a/Shared/Views/SettingsView.swift b/Shared/Views/SettingsView.swift
deleted file mode 100644
index 680d1a0..0000000
--- a/Shared/Views/SettingsView.swift
+++ /dev/null
@@ -1,13 +0,0 @@
-import SwiftUI
-
-struct SettingsView: View {
- var body: some View {
- Text("Search view")
- }
-}
-
-struct SettingsView_Previews: PreviewProvider {
- static var previews: some View {
- SettingsView()
- }
-}
diff --git a/Shared/Views/macOS/CheckNumberPopup.swift b/Shared/Views/macOS/CheckNumberPopup.swift
deleted file mode 100644
index d40d5fc..0000000
--- a/Shared/Views/macOS/CheckNumberPopup.swift
+++ /dev/null
@@ -1,56 +0,0 @@
-//
-// CheckNumberPopup.swift
-// AutoCat2 (macOS)
-//
-// Created by Selim Mustafaev on 07.11.2021.
-//
-
-import SwiftUI
-
-struct CheckNumberPopup: View {
- @Environment(\.presentationMode) var presentation
- @State var plateNumber: String = ""
- @State var progress = false
- @State private var alert: AlertMessage? = nil
-
- var body: some View {
- VStack(alignment: .center, spacing: 8) {
- Text("Check new plate number")
- TextField("qwe", text: $plateNumber, prompt: Text("asdf"))
- .disabled(progress)
- Spacer()
- if progress {
- ProgressView()
- .progressViewStyle(CircularProgressViewStyle())
- }
- Spacer()
- HStack {
- Button("Cancel") {
- self.presentation.wrappedValue.dismiss()
- }
- .disabled(progress)
- Button("Check") {
- Task.init {
- progress = true
- do {
- try await VehicleService.shared.check(plateNumber: plateNumber.uppercased(), force: false)
- } catch {
- alert = .error(error: error)
- }
- progress = false
- }
- }
- .alert(item: $alert, content: Alert.init)
- .disabled(progress)
- }
- }
- .padding()
- .frame(minWidth: 300, minHeight: 180)
- }
-}
-
-struct CheckNumberPopup_Previews: PreviewProvider {
- static var previews: some View {
- CheckNumberPopup()
- }
-}
diff --git a/Shared/Views/macOS/MainViewBig.swift b/Shared/Views/macOS/MainViewBig.swift
deleted file mode 100644
index 0e54a00..0000000
--- a/Shared/Views/macOS/MainViewBig.swift
+++ /dev/null
@@ -1,84 +0,0 @@
-import SwiftUI
-
-struct MainViewBig: View {
- var body: some View {
- NavigationView {
- SidebarView()
- Text("Master")
- Text("Detail")
- }
- }
-}
-
-struct SidebarView: View {
- @State var selection: String?
- @State private var showAddPlateNumberView = false
-
- @FetchRequest(entity: CDVehicle.entity(), sortDescriptors: []) var vehicles: FetchedResults
-
- var body: some View {
- List(selection: $selection) {
- Section("History") {
- NavigationLink(destination: VehiclesListView(vehicles: vehicles)) {
- Label("All", systemImage: "car.2")
- .badge(vehicles.count)
- }
- NavigationLink(destination: VehiclesListView(vehicles: vehicles.filter(\.unrecognized))) {
- Label("Unreconized", systemImage: "eye.slash")
- .badge(vehicles.filter(\.unrecognized).count)
- }
- NavigationLink(destination: VehiclesListView(vehicles: vehicles.filter(\.outdated))) {
- Label("Outdated", systemImage: "wind")
- .badge(vehicles.filter(\.outdated).count)
- }
- }
- .collapsible(false)
-
- Section("Other") {
- Label("Recordings", systemImage: "waveform.path")
- Label("Search", systemImage: "magnifyingglass")
- }
- .collapsible(false)
- }
- .frame(minWidth: 180)
- .sheet(isPresented: $showAddPlateNumberView, onDismiss: {
- print("Dismiss")
- }, content: {
- CheckNumberPopup()
- })
- .toolbar {
- ToolbarItem {
- Spacer()
- }
- ToolbarItem {
- Button {
- self.showAddPlateNumberView = true
- } label: {
- Image(systemName: "plus")
- }
-
- }
- }
- }
-}
-
-struct VehiclesListView: View where VehicleCollection: RandomAccessCollection, VehicleCollection.Element == CDVehicle {
-
- var vehicles: VehicleCollection
- @State var selection: CDVehicle?
-
- var body: some View {
- List(selection: $selection) {
- ForEach(vehicles, id: \.self) { vehicle in
- let number = PlateNumber(vehicle.number ?? "")
- PlateNumberView(number: number, unrecognized: vehicle.unrecognized, outdated: vehicle.outdated)
- }
- }
- }
-}
-
-struct MainViewBig_Previews: PreviewProvider {
- static var previews: some View {
- MainViewBig()
- }
-}
diff --git a/Tests iOS/Tests_iOS.swift b/Tests iOS/Tests_iOS.swift
deleted file mode 100644
index f46c9b9..0000000
--- a/Tests iOS/Tests_iOS.swift
+++ /dev/null
@@ -1,21 +0,0 @@
-import XCTest
-
-class Tests_iOS: XCTestCase {
-
- override func setUpWithError() throws {
- continueAfterFailure = false
- }
-
- override func tearDownWithError() throws {
- // Put teardown code here. This method is called after the invocation of each test method in the class.
- }
-
- func testExample() throws {
- // UI tests must launch the application that they test.
- let app = XCUIApplication()
- app.launch()
-
- // Use recording to get started writing UI tests.
- // Use XCTAssert and related functions to verify your tests produce the correct results.
- }
-}