Latest changes
This commit is contained in:
parent
c80f073f03
commit
1752d89b78
@ -9,7 +9,6 @@
|
|||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
7A2329B926AF122400264CFA /* MainViewSmall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2329B826AF122400264CFA /* MainViewSmall.swift */; };
|
7A2329B926AF122400264CFA /* MainViewSmall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2329B826AF122400264CFA /* MainViewSmall.swift */; };
|
||||||
7A2329BA26AF122400264CFA /* MainViewSmall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2329B826AF122400264CFA /* MainViewSmall.swift */; };
|
7A2329BA26AF122400264CFA /* MainViewSmall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2329B826AF122400264CFA /* MainViewSmall.swift */; };
|
||||||
7A2329BC26AF123300264CFA /* MainViewBig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2329BB26AF123200264CFA /* MainViewBig.swift */; };
|
|
||||||
7A2329BD26AF123300264CFA /* MainViewBig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2329BB26AF123200264CFA /* MainViewBig.swift */; };
|
7A2329BD26AF123300264CFA /* MainViewBig.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2329BB26AF123200264CFA /* MainViewBig.swift */; };
|
||||||
7A2329BF26AF140F00264CFA /* CheckView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2329BE26AF140F00264CFA /* CheckView.swift */; };
|
7A2329BF26AF140F00264CFA /* CheckView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2329BE26AF140F00264CFA /* CheckView.swift */; };
|
||||||
7A2329C026AF140F00264CFA /* CheckView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2329BE26AF140F00264CFA /* CheckView.swift */; };
|
7A2329C026AF140F00264CFA /* CheckView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A2329BE26AF140F00264CFA /* CheckView.swift */; };
|
||||||
@ -57,25 +56,34 @@
|
|||||||
7A971F0A26AD74FD007E527B /* ApiMethodMockProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A971F0926AD74FD007E527B /* ApiMethodMockProtocol.swift */; };
|
7A971F0A26AD74FD007E527B /* ApiMethodMockProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A971F0926AD74FD007E527B /* ApiMethodMockProtocol.swift */; };
|
||||||
7A971F0D26AD7D4C007E527B /* AnyEncodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A971F0C26AD7D4C007E527B /* AnyEncodable.swift */; };
|
7A971F0D26AD7D4C007E527B /* AnyEncodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A971F0C26AD7D4C007E527B /* AnyEncodable.swift */; };
|
||||||
7A971F0E26AD7D4C007E527B /* AnyEncodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A971F0C26AD7D4C007E527B /* AnyEncodable.swift */; };
|
7A971F0E26AD7D4C007E527B /* AnyEncodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A971F0C26AD7D4C007E527B /* AnyEncodable.swift */; };
|
||||||
7A971F1526AD8AEB007E527B /* Initialization.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A971F1026AD8AEB007E527B /* Initialization.swift */; };
|
|
||||||
7A971F1626AD8AEB007E527B /* Initialization.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A971F1026AD8AEB007E527B /* Initialization.swift */; };
|
|
||||||
7A971F1726AD8AEB007E527B /* Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A971F1126AD8AEB007E527B /* Querying.swift */; };
|
|
||||||
7A971F1826AD8AEB007E527B /* Querying.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A971F1126AD8AEB007E527B /* Querying.swift */; };
|
|
||||||
7A971F1926AD8AEB007E527B /* JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A971F1226AD8AEB007E527B /* JSON.swift */; };
|
|
||||||
7A971F1A26AD8AEB007E527B /* JSON.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A971F1226AD8AEB007E527B /* JSON.swift */; };
|
|
||||||
7A971F1D26AD8AEB007E527B /* Merging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A971F1426AD8AEB007E527B /* Merging.swift */; };
|
|
||||||
7A971F1E26AD8AEB007E527B /* Merging.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A971F1426AD8AEB007E527B /* Merging.swift */; };
|
|
||||||
7A971F2026ADC351007E527B /* ApiError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A971F1F26ADC351007E527B /* ApiError.swift */; };
|
7A971F2026ADC351007E527B /* ApiError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A971F1F26ADC351007E527B /* ApiError.swift */; };
|
||||||
7A971F2126ADC351007E527B /* 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 */; };
|
7A971F2326ADF74B007E527B /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A971F2226ADF74B007E527B /* MainView.swift */; };
|
||||||
7A971F2426ADF74B007E527B /* 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 */; };
|
7ABC05A826B05AF9004BB5A7 /* Vehicle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ABC05A726B05AF9004BB5A7 /* Vehicle.swift */; };
|
||||||
7ABC05A926B05AF9004BB5A7 /* 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 */; };
|
7ACD05D72695C08A00557667 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ACD05D62695C08A00557667 /* Constants.swift */; };
|
||||||
7ACD05D82695C08A00557667 /* 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 */; };
|
7AEFAEED26985A3400ED2C85 /* ACProgressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AEFAEEC26985A3400ED2C85 /* ACProgressView.swift */; };
|
||||||
7AEFAEEE26985A3400ED2C85 /* 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 */; };
|
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 */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
@ -160,17 +168,24 @@
|
|||||||
7A971F0726AD7084007E527B /* LoginMethodMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginMethodMock.swift; sourceTree = "<group>"; };
|
7A971F0726AD7084007E527B /* LoginMethodMock.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginMethodMock.swift; sourceTree = "<group>"; };
|
||||||
7A971F0926AD74FD007E527B /* ApiMethodMockProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApiMethodMockProtocol.swift; sourceTree = "<group>"; };
|
7A971F0926AD74FD007E527B /* ApiMethodMockProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApiMethodMockProtocol.swift; sourceTree = "<group>"; };
|
||||||
7A971F0C26AD7D4C007E527B /* AnyEncodable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnyEncodable.swift; sourceTree = "<group>"; };
|
7A971F0C26AD7D4C007E527B /* AnyEncodable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnyEncodable.swift; sourceTree = "<group>"; };
|
||||||
7A971F1026AD8AEB007E527B /* Initialization.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Initialization.swift; sourceTree = "<group>"; };
|
|
||||||
7A971F1126AD8AEB007E527B /* Querying.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Querying.swift; sourceTree = "<group>"; };
|
|
||||||
7A971F1226AD8AEB007E527B /* JSON.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = JSON.swift; sourceTree = "<group>"; };
|
|
||||||
7A971F1426AD8AEB007E527B /* Merging.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Merging.swift; sourceTree = "<group>"; };
|
|
||||||
7A971F1F26ADC351007E527B /* ApiError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApiError.swift; sourceTree = "<group>"; };
|
7A971F1F26ADC351007E527B /* ApiError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApiError.swift; sourceTree = "<group>"; };
|
||||||
7A971F2226ADF74B007E527B /* MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = "<group>"; };
|
7A971F2226ADF74B007E527B /* MainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = "<group>"; };
|
||||||
7A971F2526ADFD35007E527B /* AutoCat2 (macOS).entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "AutoCat2 (macOS).entitlements"; sourceTree = "<group>"; };
|
7A971F2526ADFD35007E527B /* AutoCat2 (macOS).entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "AutoCat2 (macOS).entitlements"; sourceTree = "<group>"; };
|
||||||
|
7AAEBD34274A47C500230C28 /* PlateNumberView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlateNumberView.swift; sourceTree = "<group>"; };
|
||||||
7ABC05A726B05AF9004BB5A7 /* Vehicle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Vehicle.swift; sourceTree = "<group>"; };
|
7ABC05A726B05AF9004BB5A7 /* Vehicle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Vehicle.swift; sourceTree = "<group>"; };
|
||||||
7ACD05D62695C08A00557667 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
|
7ACD05D62695C08A00557667 /* Constants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
|
||||||
|
7ADE63702735E1FF00A152FE /* VName.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VName.swift; sourceTree = "<group>"; };
|
||||||
|
7ADE63722735E27200A152FE /* VBrand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VBrand.swift; sourceTree = "<group>"; };
|
||||||
|
7ADE637727368C4600A152FE /* VehicleService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehicleService.swift; sourceTree = "<group>"; };
|
||||||
|
7ADE637A273692F300A152FE /* StorageService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageService.swift; sourceTree = "<group>"; };
|
||||||
|
7ADE637E2738143000A152FE /* CheckNumberPopup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckNumberPopup.swift; sourceTree = "<group>"; };
|
||||||
7AEFAEEC26985A3400ED2C85 /* ACProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ACProgressView.swift; sourceTree = "<group>"; };
|
7AEFAEEC26985A3400ED2C85 /* ACProgressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ACProgressView.swift; sourceTree = "<group>"; };
|
||||||
7AF552D82696E5C100578083 /* ApiTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApiTests.swift; sourceTree = "<group>"; };
|
7AF552D82696E5C100578083 /* ApiTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApiTests.swift; sourceTree = "<group>"; };
|
||||||
|
7AFADDA6274A49DB00D53EFC /* PlateNumber.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlateNumber.swift; sourceTree = "<group>"; };
|
||||||
|
7AFADDAD274A64DD00D53EFC /* RoadNumbers.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = RoadNumbers.otf; sourceTree = "<group>"; };
|
||||||
|
7AFADDAE274A64DD00D53EFC /* RoadNumbers2.0.otf */ = {isa = PBXFileReference; lastKnownFileType = file; path = RoadNumbers2.0.otf; sourceTree = "<group>"; };
|
||||||
|
7AFADDB3274A65BB00D53EFC /* AutoCat2--macOS--Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "AutoCat2--macOS--Info.plist"; sourceTree = "<group>"; };
|
||||||
|
7AFADDB4274A678D00D53EFC /* AutoCat2--iOS--Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "AutoCat2--iOS--Info.plist"; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@ -215,19 +230,22 @@
|
|||||||
7A40D5732691C6D6009B0BC4 = {
|
7A40D5732691C6D6009B0BC4 = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
7AFADDB4274A678D00D53EFC /* AutoCat2--iOS--Info.plist */,
|
||||||
|
7AFADDB3274A65BB00D53EFC /* AutoCat2--macOS--Info.plist */,
|
||||||
7A971F2526ADFD35007E527B /* AutoCat2 (macOS).entitlements */,
|
7A971F2526ADFD35007E527B /* AutoCat2 (macOS).entitlements */,
|
||||||
7A40D5782691C6D7009B0BC4 /* Shared */,
|
7A40D5782691C6D7009B0BC4 /* Shared */,
|
||||||
7A40D5912691C6D8009B0BC4 /* Tests iOS */,
|
7A40D5912691C6D8009B0BC4 /* Tests iOS */,
|
||||||
7A40D59B2691C6D8009B0BC4 /* Tests macOS */,
|
7A40D59B2691C6D8009B0BC4 /* Tests macOS */,
|
||||||
7A40D5F42693A63A009B0BC4 /* AutoCat2Tests */,
|
7A40D5F42693A63A009B0BC4 /* AutoCat2Tests */,
|
||||||
7A40D5842691C6D8009B0BC4 /* Products */,
|
7A40D5842691C6D8009B0BC4 /* Products */,
|
||||||
7A40D5D92691C7EB009B0BC4 /* Frameworks */,
|
|
||||||
);
|
);
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
7A40D5782691C6D7009B0BC4 /* Shared */ = {
|
7A40D5782691C6D7009B0BC4 /* Shared */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
7AFADDAC274A64DD00D53EFC /* Fonts */,
|
||||||
|
7ADE637627368C2A00A152FE /* Services */,
|
||||||
7A971F0B26AD7D27007E527B /* ThirdParty */,
|
7A971F0B26AD7D27007E527B /* ThirdParty */,
|
||||||
7A40D6002694FF4C009B0BC4 /* Utils */,
|
7A40D6002694FF4C009B0BC4 /* Utils */,
|
||||||
7A40D5FC2693A90F009B0BC4 /* Extensions */,
|
7A40D5FC2693A90F009B0BC4 /* Extensions */,
|
||||||
@ -271,13 +289,6 @@
|
|||||||
path = "Tests macOS";
|
path = "Tests macOS";
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
7A40D5D92691C7EB009B0BC4 /* Frameworks */ = {
|
|
||||||
isa = PBXGroup;
|
|
||||||
children = (
|
|
||||||
);
|
|
||||||
name = Frameworks;
|
|
||||||
sourceTree = "<group>";
|
|
||||||
};
|
|
||||||
7A40D5DF26924ADE009B0BC4 /* Models */ = {
|
7A40D5DF26924ADE009B0BC4 /* Models */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -285,6 +296,9 @@
|
|||||||
7A40D5E226924B09009B0BC4 /* Settings.swift */,
|
7A40D5E226924B09009B0BC4 /* Settings.swift */,
|
||||||
7A683998269612EA00B2188A /* Response.swift */,
|
7A683998269612EA00B2188A /* Response.swift */,
|
||||||
7ABC05A726B05AF9004BB5A7 /* Vehicle.swift */,
|
7ABC05A726B05AF9004BB5A7 /* Vehicle.swift */,
|
||||||
|
7ADE63702735E1FF00A152FE /* VName.swift */,
|
||||||
|
7ADE63722735E27200A152FE /* VBrand.swift */,
|
||||||
|
7AFADDA6274A49DB00D53EFC /* PlateNumber.swift */,
|
||||||
);
|
);
|
||||||
path = Models;
|
path = Models;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -299,17 +313,18 @@
|
|||||||
7A40D5E726938BC8009B0BC4 /* Views */ = {
|
7A40D5E726938BC8009B0BC4 /* Views */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
7ADE637D2738139D00A152FE /* macOS */,
|
||||||
7AEFAEEC26985A3400ED2C85 /* ACProgressView.swift */,
|
7AEFAEEC26985A3400ED2C85 /* ACProgressView.swift */,
|
||||||
|
7A2329BE26AF140F00264CFA /* CheckView.swift */,
|
||||||
7A40D57C2691C6D7009B0BC4 /* ContentView.swift */,
|
7A40D57C2691C6D7009B0BC4 /* ContentView.swift */,
|
||||||
7A40D5E826938BEC009B0BC4 /* AuthView.swift */,
|
7A40D5E826938BEC009B0BC4 /* AuthView.swift */,
|
||||||
7A971F2226ADF74B007E527B /* MainView.swift */,
|
7A971F2226ADF74B007E527B /* MainView.swift */,
|
||||||
7A2329B826AF122400264CFA /* MainViewSmall.swift */,
|
7A2329B826AF122400264CFA /* MainViewSmall.swift */,
|
||||||
7A2329BB26AF123200264CFA /* MainViewBig.swift */,
|
|
||||||
7A2329BE26AF140F00264CFA /* CheckView.swift */,
|
|
||||||
7A2329C126AF141E00264CFA /* SearchView.swift */,
|
7A2329C126AF141E00264CFA /* SearchView.swift */,
|
||||||
7A2329C426AF142900264CFA /* SettingsView.swift */,
|
7A2329C426AF142900264CFA /* SettingsView.swift */,
|
||||||
7A2329C726AF143F00264CFA /* RecordsView.swift */,
|
7A2329C726AF143F00264CFA /* RecordsView.swift */,
|
||||||
7A2329CA26AF15AC00264CFA /* ReportView.swift */,
|
7A2329CA26AF15AC00264CFA /* ReportView.swift */,
|
||||||
|
7AAEBD34274A47C500230C28 /* PlateNumberView.swift */,
|
||||||
);
|
);
|
||||||
path = Views;
|
path = Views;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@ -390,21 +405,36 @@
|
|||||||
7A971F0B26AD7D27007E527B /* ThirdParty */ = {
|
7A971F0B26AD7D27007E527B /* ThirdParty */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
7A971F0F26AD8AEB007E527B /* GenericJSON */,
|
|
||||||
7A971F0C26AD7D4C007E527B /* AnyEncodable.swift */,
|
7A971F0C26AD7D4C007E527B /* AnyEncodable.swift */,
|
||||||
);
|
);
|
||||||
path = ThirdParty;
|
path = ThirdParty;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
7A971F0F26AD8AEB007E527B /* GenericJSON */ = {
|
7ADE637627368C2A00A152FE /* Services */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
7A971F1026AD8AEB007E527B /* Initialization.swift */,
|
7ADE637727368C4600A152FE /* VehicleService.swift */,
|
||||||
7A971F1126AD8AEB007E527B /* Querying.swift */,
|
7ADE637A273692F300A152FE /* StorageService.swift */,
|
||||||
7A971F1226AD8AEB007E527B /* JSON.swift */,
|
|
||||||
7A971F1426AD8AEB007E527B /* Merging.swift */,
|
|
||||||
);
|
);
|
||||||
path = GenericJSON;
|
path = Services;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
7ADE637D2738139D00A152FE /* macOS */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
7A2329BB26AF123200264CFA /* MainViewBig.swift */,
|
||||||
|
7ADE637E2738143000A152FE /* CheckNumberPopup.swift */,
|
||||||
|
);
|
||||||
|
path = macOS;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
7AFADDAC274A64DD00D53EFC /* Fonts */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
7AFADDAD274A64DD00D53EFC /* RoadNumbers.otf */,
|
||||||
|
7AFADDAE274A64DD00D53EFC /* RoadNumbers2.0.otf */,
|
||||||
|
);
|
||||||
|
path = Fonts;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
@ -424,6 +454,8 @@
|
|||||||
dependencies = (
|
dependencies = (
|
||||||
);
|
);
|
||||||
name = "AutoCat2 (iOS)";
|
name = "AutoCat2 (iOS)";
|
||||||
|
packageProductDependencies = (
|
||||||
|
);
|
||||||
productName = "AutoCat2 (iOS)";
|
productName = "AutoCat2 (iOS)";
|
||||||
productReference = 7A40D5832691C6D8009B0BC4 /* AutoCat2.app */;
|
productReference = 7A40D5832691C6D8009B0BC4 /* AutoCat2.app */;
|
||||||
productType = "com.apple.product-type.application";
|
productType = "com.apple.product-type.application";
|
||||||
@ -442,6 +474,8 @@
|
|||||||
dependencies = (
|
dependencies = (
|
||||||
);
|
);
|
||||||
name = "AutoCat2 (macOS)";
|
name = "AutoCat2 (macOS)";
|
||||||
|
packageProductDependencies = (
|
||||||
|
);
|
||||||
productName = "AutoCat2 (macOS)";
|
productName = "AutoCat2 (macOS)";
|
||||||
productReference = 7A40D5892691C6D8009B0BC4 /* AutoCat2.app */;
|
productReference = 7A40D5892691C6D8009B0BC4 /* AutoCat2.app */;
|
||||||
productType = "com.apple.product-type.application";
|
productType = "com.apple.product-type.application";
|
||||||
@ -508,7 +542,7 @@
|
|||||||
attributes = {
|
attributes = {
|
||||||
BuildIndependentTargetsInParallel = 1;
|
BuildIndependentTargetsInParallel = 1;
|
||||||
LastSwiftUpdateCheck = 1300;
|
LastSwiftUpdateCheck = 1300;
|
||||||
LastUpgradeCheck = 1300;
|
LastUpgradeCheck = 1310;
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
7A40D5822691C6D8009B0BC4 = {
|
7A40D5822691C6D8009B0BC4 = {
|
||||||
CreatedOnToolsVersion = 13.0;
|
CreatedOnToolsVersion = 13.0;
|
||||||
@ -539,6 +573,8 @@
|
|||||||
Base,
|
Base,
|
||||||
);
|
);
|
||||||
mainGroup = 7A40D5732691C6D6009B0BC4;
|
mainGroup = 7A40D5732691C6D6009B0BC4;
|
||||||
|
packageReferences = (
|
||||||
|
);
|
||||||
productRefGroup = 7A40D5842691C6D8009B0BC4 /* Products */;
|
productRefGroup = 7A40D5842691C6D8009B0BC4 /* Products */;
|
||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
projectRoot = "";
|
projectRoot = "";
|
||||||
@ -557,7 +593,9 @@
|
|||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
7AFADDAF274A64DD00D53EFC /* RoadNumbers.otf in Resources */,
|
||||||
7A40D5A62691C6D8009B0BC4 /* Assets.xcassets in Resources */,
|
7A40D5A62691C6D8009B0BC4 /* Assets.xcassets in Resources */,
|
||||||
|
7AFADDB1274A64DD00D53EFC /* RoadNumbers2.0.otf in Resources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -565,7 +603,9 @@
|
|||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
7AFADDB0274A64DD00D53EFC /* RoadNumbers.otf in Resources */,
|
||||||
7A40D5A72691C6D8009B0BC4 /* Assets.xcassets in Resources */,
|
7A40D5A72691C6D8009B0BC4 /* Assets.xcassets in Resources */,
|
||||||
|
7AFADDB2274A64DD00D53EFC /* RoadNumbers2.0.otf in Resources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@ -600,25 +640,26 @@
|
|||||||
files = (
|
files = (
|
||||||
7A40D5E926938BEC009B0BC4 /* AuthView.swift in Sources */,
|
7A40D5E926938BEC009B0BC4 /* AuthView.swift in Sources */,
|
||||||
7A971F2326ADF74B007E527B /* MainView.swift in Sources */,
|
7A971F2326ADF74B007E527B /* MainView.swift in Sources */,
|
||||||
|
7ADE63732735E27200A152FE /* VBrand.swift in Sources */,
|
||||||
7A971F0D26AD7D4C007E527B /* AnyEncodable.swift in Sources */,
|
7A971F0D26AD7D4C007E527B /* AnyEncodable.swift in Sources */,
|
||||||
7ACD05D72695C08A00557667 /* Constants.swift in Sources */,
|
7ACD05D72695C08A00557667 /* Constants.swift in Sources */,
|
||||||
7A971F1926AD8AEB007E527B /* JSON.swift in Sources */,
|
|
||||||
7A2329BC26AF123300264CFA /* MainViewBig.swift in Sources */,
|
|
||||||
7A971F1D26AD8AEB007E527B /* Merging.swift in Sources */,
|
|
||||||
7A40D5E326924B09009B0BC4 /* Settings.swift in Sources */,
|
7A40D5E326924B09009B0BC4 /* Settings.swift in Sources */,
|
||||||
|
7ADE637827368C4600A152FE /* VehicleService.swift in Sources */,
|
||||||
7AEFAEED26985A3400ED2C85 /* ACProgressView.swift in Sources */,
|
7AEFAEED26985A3400ED2C85 /* ACProgressView.swift in Sources */,
|
||||||
7A40D5A02691C6D8009B0BC4 /* AutoCat2App.swift in Sources */,
|
7A40D5A02691C6D8009B0BC4 /* AutoCat2App.swift in Sources */,
|
||||||
7A683999269612EA00B2188A /* Response.swift in Sources */,
|
7A683999269612EA00B2188A /* Response.swift in Sources */,
|
||||||
7A2329BF26AF140F00264CFA /* CheckView.swift in Sources */,
|
7A2329BF26AF140F00264CFA /* CheckView.swift in Sources */,
|
||||||
7A971F1526AD8AEB007E527B /* Initialization.swift in Sources */,
|
|
||||||
7A971F1726AD8AEB007E527B /* Querying.swift in Sources */,
|
|
||||||
7A40D60826998DCF009B0BC4 /* Alert.swift in Sources */,
|
7A40D60826998DCF009B0BC4 /* Alert.swift in Sources */,
|
||||||
7A2329C226AF141E00264CFA /* SearchView.swift in Sources */,
|
7A2329C226AF141E00264CFA /* SearchView.swift in Sources */,
|
||||||
|
7ADE637B273692F300A152FE /* StorageService.swift in Sources */,
|
||||||
|
7ADE63712735E1FF00A152FE /* VName.swift in Sources */,
|
||||||
7A40D5A42691C6D8009B0BC4 /* Persistence.swift in Sources */,
|
7A40D5A42691C6D8009B0BC4 /* Persistence.swift in Sources */,
|
||||||
7A971F2026ADC351007E527B /* ApiError.swift in Sources */,
|
7A971F2026ADC351007E527B /* ApiError.swift in Sources */,
|
||||||
7A2329CB26AF15AC00264CFA /* ReportView.swift in Sources */,
|
7A2329CB26AF15AC00264CFA /* ReportView.swift in Sources */,
|
||||||
|
7AAEBD35274A47C500230C28 /* PlateNumberView.swift in Sources */,
|
||||||
7A40D5ED2693A1EA009B0BC4 /* AuthVM.swift in Sources */,
|
7A40D5ED2693A1EA009B0BC4 /* AuthVM.swift in Sources */,
|
||||||
7A40D59E2691C6D8009B0BC4 /* AutoCat2.xcdatamodeld in Sources */,
|
7A40D59E2691C6D8009B0BC4 /* AutoCat2.xcdatamodeld in Sources */,
|
||||||
|
7AFADDA7274A49DB00D53EFC /* PlateNumber.swift in Sources */,
|
||||||
7ABC05A826B05AF9004BB5A7 /* Vehicle.swift in Sources */,
|
7ABC05A826B05AF9004BB5A7 /* Vehicle.swift in Sources */,
|
||||||
7A2329B926AF122400264CFA /* MainViewSmall.swift in Sources */,
|
7A2329B926AF122400264CFA /* MainViewSmall.swift in Sources */,
|
||||||
7A2329C826AF143F00264CFA /* RecordsView.swift in Sources */,
|
7A2329C826AF143F00264CFA /* RecordsView.swift in Sources */,
|
||||||
@ -634,31 +675,34 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
7AAEBD36274A47C600230C28 /* PlateNumberView.swift in Sources */,
|
||||||
|
7ADE637927368C4600A152FE /* VehicleService.swift in Sources */,
|
||||||
7A40D5EA26938BEC009B0BC4 /* AuthView.swift in Sources */,
|
7A40D5EA26938BEC009B0BC4 /* AuthView.swift in Sources */,
|
||||||
7A971F2426ADF74B007E527B /* MainView.swift in Sources */,
|
7A971F2426ADF74B007E527B /* MainView.swift in Sources */,
|
||||||
|
7ADE63742735E27200A152FE /* VBrand.swift in Sources */,
|
||||||
7A971F0E26AD7D4C007E527B /* AnyEncodable.swift in Sources */,
|
7A971F0E26AD7D4C007E527B /* AnyEncodable.swift in Sources */,
|
||||||
7ACD05D82695C08A00557667 /* Constants.swift in Sources */,
|
7ACD05D82695C08A00557667 /* Constants.swift in Sources */,
|
||||||
7A971F1A26AD8AEB007E527B /* JSON.swift in Sources */,
|
|
||||||
7A2329BD26AF123300264CFA /* MainViewBig.swift in Sources */,
|
7A2329BD26AF123300264CFA /* MainViewBig.swift in Sources */,
|
||||||
7A971F1E26AD8AEB007E527B /* Merging.swift in Sources */,
|
|
||||||
7A40D5A12691C6D8009B0BC4 /* AutoCat2App.swift in Sources */,
|
7A40D5A12691C6D8009B0BC4 /* AutoCat2App.swift in Sources */,
|
||||||
7AEFAEEE26985A3400ED2C85 /* ACProgressView.swift in Sources */,
|
7AEFAEEE26985A3400ED2C85 /* ACProgressView.swift in Sources */,
|
||||||
7A40D5A52691C6D8009B0BC4 /* Persistence.swift in Sources */,
|
7A40D5A52691C6D8009B0BC4 /* Persistence.swift in Sources */,
|
||||||
|
7AFADDA8274A49DB00D53EFC /* PlateNumber.swift in Sources */,
|
||||||
7A68399A269612EA00B2188A /* Response.swift in Sources */,
|
7A68399A269612EA00B2188A /* Response.swift in Sources */,
|
||||||
7A2329C026AF140F00264CFA /* CheckView.swift in Sources */,
|
7A2329C026AF140F00264CFA /* CheckView.swift in Sources */,
|
||||||
7A971F1626AD8AEB007E527B /* Initialization.swift in Sources */,
|
|
||||||
7A971F1826AD8AEB007E527B /* Querying.swift in Sources */,
|
|
||||||
7A40D60926998DCF009B0BC4 /* Alert.swift in Sources */,
|
7A40D60926998DCF009B0BC4 /* Alert.swift in Sources */,
|
||||||
7A2329C326AF141E00264CFA /* SearchView.swift in Sources */,
|
7A2329C326AF141E00264CFA /* SearchView.swift in Sources */,
|
||||||
7A40D5E526924B0C009B0BC4 /* User.swift in Sources */,
|
7A40D5E526924B0C009B0BC4 /* User.swift in Sources */,
|
||||||
7A971F2126ADC351007E527B /* ApiError.swift in Sources */,
|
7A971F2126ADC351007E527B /* ApiError.swift in Sources */,
|
||||||
7A2329CC26AF15AC00264CFA /* ReportView.swift in Sources */,
|
7A2329CC26AF15AC00264CFA /* ReportView.swift in Sources */,
|
||||||
|
7ADE637C273692F300A152FE /* StorageService.swift in Sources */,
|
||||||
|
7ADE637F2738143000A152FE /* CheckNumberPopup.swift in Sources */,
|
||||||
7A40D5EE2693A1EA009B0BC4 /* AuthVM.swift in Sources */,
|
7A40D5EE2693A1EA009B0BC4 /* AuthVM.swift in Sources */,
|
||||||
7A40D59F2691C6D8009B0BC4 /* AutoCat2.xcdatamodeld in Sources */,
|
7A40D59F2691C6D8009B0BC4 /* AutoCat2.xcdatamodeld in Sources */,
|
||||||
7ABC05A926B05AF9004BB5A7 /* Vehicle.swift in Sources */,
|
7ABC05A926B05AF9004BB5A7 /* Vehicle.swift in Sources */,
|
||||||
7A2329BA26AF122400264CFA /* MainViewSmall.swift in Sources */,
|
7A2329BA26AF122400264CFA /* MainViewSmall.swift in Sources */,
|
||||||
7A2329C926AF143F00264CFA /* RecordsView.swift in Sources */,
|
7A2329C926AF143F00264CFA /* RecordsView.swift in Sources */,
|
||||||
7A40D5A32691C6D8009B0BC4 /* ContentView.swift in Sources */,
|
7A40D5A32691C6D8009B0BC4 /* ContentView.swift in Sources */,
|
||||||
|
7ADE63752735E27D00A152FE /* VName.swift in Sources */,
|
||||||
7A40D5FF2693A91F009B0BC4 /* CocoaError.swift in Sources */,
|
7A40D5FF2693A91F009B0BC4 /* CocoaError.swift in Sources */,
|
||||||
7A40D6032694FF5D009B0BC4 /* Api.swift in Sources */,
|
7A40D6032694FF5D009B0BC4 /* Api.swift in Sources */,
|
||||||
7A40D5E426924B09009B0BC4 /* Settings.swift in Sources */,
|
7A40D5E426924B09009B0BC4 /* Settings.swift in Sources */,
|
||||||
@ -841,6 +885,7 @@
|
|||||||
DEVELOPMENT_TEAM = 46DTTB8X4S;
|
DEVELOPMENT_TEAM = 46DTTB8X4S;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = "AutoCat2--iOS--Info.plist";
|
||||||
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
|
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
|
||||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||||
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
||||||
@ -871,6 +916,7 @@
|
|||||||
DEVELOPMENT_TEAM = 46DTTB8X4S;
|
DEVELOPMENT_TEAM = 46DTTB8X4S;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = "AutoCat2--iOS--Info.plist";
|
||||||
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
|
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
|
||||||
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
|
||||||
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
|
||||||
@ -898,6 +944,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
CODE_SIGN_ENTITLEMENTS = "AutoCat2 (macOS).entitlements";
|
CODE_SIGN_ENTITLEMENTS = "AutoCat2 (macOS).entitlements";
|
||||||
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
@ -907,6 +954,7 @@
|
|||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
ENABLE_USER_SELECTED_FILES = readonly;
|
ENABLE_USER_SELECTED_FILES = readonly;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = "AutoCat2--macOS--Info.plist";
|
||||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
@ -928,6 +976,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
CODE_SIGN_ENTITLEMENTS = "AutoCat2 (macOS).entitlements";
|
CODE_SIGN_ENTITLEMENTS = "AutoCat2 (macOS).entitlements";
|
||||||
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
@ -937,6 +986,7 @@
|
|||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
ENABLE_USER_SELECTED_FILES = readonly;
|
ENABLE_USER_SELECTED_FILES = readonly;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = "AutoCat2--macOS--Info.plist";
|
||||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
|
|||||||
@ -20,5 +20,23 @@
|
|||||||
<integer>2</integer>
|
<integer>2</integer>
|
||||||
</dict>
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
|
<key>SuppressBuildableAutocreation</key>
|
||||||
|
<dict>
|
||||||
|
<key>7A40D5822691C6D8009B0BC4</key>
|
||||||
|
<dict>
|
||||||
|
<key>primary</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>7A40D58D2691C6D8009B0BC4</key>
|
||||||
|
<dict>
|
||||||
|
<key>primary</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
<key>7A40D5F22693A63A009B0BC4</key>
|
||||||
|
<dict>
|
||||||
|
<key>primary</key>
|
||||||
|
<true/>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import AutoCat2
|
|||||||
|
|
||||||
class ApiTests: XCTestCase {
|
class ApiTests: XCTestCase {
|
||||||
|
|
||||||
private var api: Api!
|
private var api: ApiProtocol!
|
||||||
|
|
||||||
private let testLogin = "test@gmail.com"
|
private let testLogin = "test@gmail.com"
|
||||||
private let testPassword = "12345"
|
private let testPassword = "12345"
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import AutoCat2
|
|||||||
|
|
||||||
class SettingsTests: XCTestCase {
|
class SettingsTests: XCTestCase {
|
||||||
|
|
||||||
private var settings: Settings!
|
private var settings: SettingsProtocol!
|
||||||
|
|
||||||
override func setUpWithError() throws {
|
override func setUpWithError() throws {
|
||||||
guard let userDefaults = UserDefaults(suiteName: #file) else {
|
guard let userDefaults = UserDefaults(suiteName: #file) else {
|
||||||
|
|||||||
6
Shared/Assets.xcassets/Colors/Contents.json
Normal file
6
Shared/Assets.xcassets/Colors/Contents.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "srgb",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "1.000",
|
||||||
|
"green" : "1.000",
|
||||||
|
"red" : "1.000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "display-p3",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "0.152",
|
||||||
|
"green" : "0.152",
|
||||||
|
"red" : "0.152"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"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
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "srgb",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "0.000",
|
||||||
|
"green" : "0.000",
|
||||||
|
"red" : "0.000"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"color" : {
|
||||||
|
"color-space" : "display-p3",
|
||||||
|
"components" : {
|
||||||
|
"alpha" : "1.000",
|
||||||
|
"blue" : "0.866",
|
||||||
|
"green" : "0.866",
|
||||||
|
"red" : "0.866"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,23 +1,23 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="19186" systemVersion="21A5294g" minimumToolsVersion="Automatic" sourceLanguage="Swift" usedWithCloudKit="YES" userDefinedModelVersionIdentifier="">
|
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="19461" systemVersion="21A559" minimumToolsVersion="Automatic" sourceLanguage="Swift" usedWithCloudKit="YES" userDefinedModelVersionIdentifier="">
|
||||||
<entity name="VBrand" representedClassName="VBrand" syncable="YES" codeGenerationType="class">
|
<entity name="VBrand" representedClassName="CDVBrand" syncable="YES" codeGenerationType="class">
|
||||||
<attribute name="logo" optional="YES" attributeType="String"/>
|
<attribute name="logo" optional="YES" attributeType="String"/>
|
||||||
<relationship name="name" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="VName" inverseName="brand" inverseEntity="VName"/>
|
<relationship name="name" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="VName" inverseName="brand" inverseEntity="VName"/>
|
||||||
<relationship name="vehicle" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Vehicle" inverseName="brand" inverseEntity="Vehicle"/>
|
<relationship name="vehicle" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Vehicle" inverseName="brand" inverseEntity="Vehicle"/>
|
||||||
</entity>
|
</entity>
|
||||||
<entity name="Vehicle" representedClassName="Vehicle" syncable="YES" codeGenerationType="class">
|
<entity name="Vehicle" representedClassName="CDVehicle" syncable="YES" codeGenerationType="class">
|
||||||
<attribute name="currentNumber" optional="YES" attributeType="String"/>
|
<attribute name="currentNumber" optional="YES" attributeType="String"/>
|
||||||
<attribute name="number" optional="YES" attributeType="String"/>
|
<attribute name="number" optional="YES" attributeType="String"/>
|
||||||
<relationship name="brand" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="VBrand" inverseName="vehicle" inverseEntity="VBrand"/>
|
<relationship name="brand" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="VBrand" inverseName="vehicle" inverseEntity="VBrand"/>
|
||||||
</entity>
|
</entity>
|
||||||
<entity name="VName" representedClassName="VName" syncable="YES" codeGenerationType="class">
|
<entity name="VName" representedClassName="CDVName" syncable="YES" codeGenerationType="class">
|
||||||
<attribute name="normalized" optional="YES" attributeType="String"/>
|
<attribute name="normalized" optional="YES" attributeType="String"/>
|
||||||
<attribute name="original" optional="YES" attributeType="String"/>
|
<attribute name="original" optional="YES" attributeType="String"/>
|
||||||
<relationship name="brand" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="VBrand" inverseName="name" inverseEntity="VBrand"/>
|
<relationship name="brand" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="VBrand" inverseName="name" inverseEntity="VBrand"/>
|
||||||
</entity>
|
</entity>
|
||||||
<elements>
|
<elements>
|
||||||
<element name="Vehicle" positionX="-145.9427490234375" positionY="-363.4805297851562" width="128" height="88"/>
|
<element name="VBrand" positionX="118.7528686523438" positionY="-209.1094360351562" width="128" height="74"/>
|
||||||
<element name="VName" positionX="-54" positionY="9" width="128" height="88"/>
|
<element name="Vehicle" positionX="-145.9427490234375" positionY="-363.4805297851562" width="128" height="74"/>
|
||||||
<element name="VBrand" positionX="118.7528686523438" positionY="-209.1094360351562" width="128" height="88"/>
|
<element name="VName" positionX="-54" positionY="9" width="128" height="74"/>
|
||||||
</elements>
|
</elements>
|
||||||
</model>
|
</model>
|
||||||
@ -9,12 +9,12 @@ import SwiftUI
|
|||||||
|
|
||||||
@main
|
@main
|
||||||
struct AutoCat2App: App {
|
struct AutoCat2App: App {
|
||||||
let persistenceController = PersistenceController.shared
|
let storageService = StorageService.shared
|
||||||
|
|
||||||
var body: some Scene {
|
var body: some Scene {
|
||||||
WindowGroup {
|
WindowGroup {
|
||||||
ContentView()
|
ContentView()
|
||||||
.environment(\.managedObjectContext, persistenceController.container.viewContext)
|
.environment(\.managedObjectContext, storageService.context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
Shared/Fonts/RoadNumbers.otf
Normal file
BIN
Shared/Fonts/RoadNumbers.otf
Normal file
Binary file not shown.
BIN
Shared/Fonts/RoadNumbers2.0.otf
Normal file
BIN
Shared/Fonts/RoadNumbers2.0.otf
Normal file
Binary file not shown.
25
Shared/Models/PlateNumber.swift
Normal file
25
Shared/Models/PlateNumber.swift
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import Foundation
|
||||||
|
|
||||||
|
public class PlateNumber {
|
||||||
|
private var number: String
|
||||||
|
private var numberEnglish: String
|
||||||
|
|
||||||
|
public init(_ string: String) {
|
||||||
|
self.number = string
|
||||||
|
self.numberEnglish = String(self.number.map { Constants.pnLettersMap[$0] ?? $0 })
|
||||||
|
}
|
||||||
|
|
||||||
|
public func asString() -> String {
|
||||||
|
return self.number
|
||||||
|
}
|
||||||
|
|
||||||
|
public func mainPart() -> String {
|
||||||
|
let index = self.numberEnglish.index(self.numberEnglish.startIndex, offsetBy: 6)
|
||||||
|
return String(self.numberEnglish[..<index])
|
||||||
|
}
|
||||||
|
|
||||||
|
public func region() -> String {
|
||||||
|
let index = self.numberEnglish.index(self.numberEnglish.startIndex, offsetBy: 6)
|
||||||
|
return String(self.numberEnglish[index...])
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,7 +1,18 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public class Settings: ObservableObject {
|
public protocol SettingsProtocol {
|
||||||
private var defaults: UserDefaults
|
|
||||||
|
var user: User { get set }
|
||||||
|
var recognizeAlternativeOrder: Bool { get set }
|
||||||
|
var recognizeShortenedNumbers: Bool { get set }
|
||||||
|
var defaultRegion: String { get set }
|
||||||
|
var recordBeep: Bool { get set }
|
||||||
|
var showDebugInfo: Bool { get set }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Settings: ObservableObject, SettingsProtocol {
|
||||||
|
private let defaults: UserDefaults
|
||||||
public static let shared = Settings()
|
public static let shared = Settings()
|
||||||
|
|
||||||
@Published
|
@Published
|
||||||
|
|||||||
22
Shared/Models/VBrand.swift
Normal file
22
Shared/Models/VBrand.swift
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import Foundation
|
||||||
|
import CoreData
|
||||||
|
|
||||||
|
public struct VBrand: Decodable {
|
||||||
|
|
||||||
|
let logo: String?
|
||||||
|
let name: VName?
|
||||||
|
}
|
||||||
|
|
||||||
|
extension CDVBrand {
|
||||||
|
|
||||||
|
convenience init(vbrand: VBrand, context: NSManagedObjectContext) {
|
||||||
|
|
||||||
|
self.init(context: context)
|
||||||
|
self.logo = vbrand.logo
|
||||||
|
|
||||||
|
if let vname = vbrand.name {
|
||||||
|
self.name = CDVName(vname: vname, context: context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
19
Shared/Models/VName.swift
Normal file
19
Shared/Models/VName.swift
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import Foundation
|
||||||
|
import CoreData
|
||||||
|
|
||||||
|
public struct VName: Decodable {
|
||||||
|
|
||||||
|
let normalized: String?
|
||||||
|
let original: String?
|
||||||
|
}
|
||||||
|
|
||||||
|
extension CDVName {
|
||||||
|
|
||||||
|
convenience init(vname: VName, context: NSManagedObjectContext) {
|
||||||
|
|
||||||
|
self.init(context: context)
|
||||||
|
self.normalized = vname.normalized
|
||||||
|
self.original = vname.original
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,7 +1,13 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import CoreData
|
import CoreData
|
||||||
|
|
||||||
extension Vehicle {
|
public struct Vehicle: Decodable {
|
||||||
|
|
||||||
|
let number: String
|
||||||
|
let currentNumber: String?
|
||||||
|
let brand: VBrand?
|
||||||
|
|
||||||
|
// TODO: Remove code duplication
|
||||||
public var unrecognized: Bool {
|
public var unrecognized: Bool {
|
||||||
return self.brand == nil
|
return self.brand == nil
|
||||||
}
|
}
|
||||||
@ -14,3 +20,30 @@ extension Vehicle {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension CDVehicle {
|
||||||
|
|
||||||
|
convenience init(vehicle: Vehicle, context: NSManagedObjectContext) {
|
||||||
|
|
||||||
|
self.init(context: context)
|
||||||
|
self.number = vehicle.number
|
||||||
|
self.currentNumber = vehicle.currentNumber
|
||||||
|
|
||||||
|
if let vbrand = vehicle.brand {
|
||||||
|
self.brand = CDVBrand(vbrand: vbrand, context: context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public var unrecognized: Bool {
|
||||||
|
return self.brand == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
public var outdated: Bool {
|
||||||
|
if let current = self.currentNumber {
|
||||||
|
return current != self.number
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
56
Shared/Services/StorageService.swift
Normal file
56
Shared/Services/StorageService.swift
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import Foundation
|
||||||
|
import CoreData
|
||||||
|
|
||||||
|
protocol StorageServiceProtocol {
|
||||||
|
|
||||||
|
var context: NSManagedObjectContext { get }
|
||||||
|
func store(vehicle: Vehicle) throws -> CDVehicle
|
||||||
|
}
|
||||||
|
|
||||||
|
class StorageService: StorageServiceProtocol {
|
||||||
|
|
||||||
|
private let container: NSPersistentCloudKitContainer
|
||||||
|
|
||||||
|
static let shared = StorageService()
|
||||||
|
|
||||||
|
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? {
|
||||||
|
// TODO: Handle error properly
|
||||||
|
fatalError("Unresolved error \(error), \(error.userInfo)")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private func save() throws {
|
||||||
|
guard context.hasChanges else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
try context.save()
|
||||||
|
} catch {
|
||||||
|
context.rollback()
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - StorageServiceProtocol
|
||||||
|
|
||||||
|
var context: NSManagedObjectContext {
|
||||||
|
container.viewContext
|
||||||
|
}
|
||||||
|
|
||||||
|
func store(vehicle: Vehicle) throws -> CDVehicle {
|
||||||
|
|
||||||
|
let cdVehicle = CDVehicle(vehicle: vehicle, context: context)
|
||||||
|
try save()
|
||||||
|
return cdVehicle
|
||||||
|
}
|
||||||
|
}
|
||||||
29
Shared/Services/VehicleService.swift
Normal file
29
Shared/Services/VehicleService.swift
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import Foundation
|
||||||
|
|
||||||
|
protocol VehicleServiceProtocol {
|
||||||
|
|
||||||
|
func check(plateNumber: String, force: Bool) async throws -> CDVehicle
|
||||||
|
}
|
||||||
|
|
||||||
|
class VehicleService: VehicleServiceProtocol {
|
||||||
|
|
||||||
|
private let api: ApiProtocol
|
||||||
|
private let storage: StorageServiceProtocol
|
||||||
|
|
||||||
|
static let shared = VehicleService()
|
||||||
|
|
||||||
|
init(api: ApiProtocol = Api.shared, storage: StorageServiceProtocol = StorageService.shared) {
|
||||||
|
|
||||||
|
self.api = api
|
||||||
|
self.storage = storage
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - VehicleServiceProtocol
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
124
Shared/ThirdParty/GenericJSON/Initialization.swift
vendored
124
Shared/ThirdParty/GenericJSON/Initialization.swift
vendored
@ -1,124 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
|
|
||||||
private struct InitializationError: Error {}
|
|
||||||
|
|
||||||
extension JSON {
|
|
||||||
|
|
||||||
/// Create a JSON value from anything.
|
|
||||||
///
|
|
||||||
/// Argument has to be a valid JSON structure: A `Double`, `Int`, `String`,
|
|
||||||
/// `Bool`, an `Array` of those types or a `Dictionary` of those types.
|
|
||||||
///
|
|
||||||
/// You can also pass `nil` or `NSNull`, both will be treated as `.null`.
|
|
||||||
public init(_ value: Any) throws {
|
|
||||||
switch value {
|
|
||||||
case _ as NSNull:
|
|
||||||
self = .null
|
|
||||||
case let opt as Optional<Any> where opt == nil:
|
|
||||||
self = .null
|
|
||||||
case let num as NSNumber:
|
|
||||||
if num.isBool {
|
|
||||||
self = .bool(num.boolValue)
|
|
||||||
} else {
|
|
||||||
self = .number(num.doubleValue)
|
|
||||||
}
|
|
||||||
case let str as String:
|
|
||||||
self = .string(str)
|
|
||||||
case let bool as Bool:
|
|
||||||
self = .bool(bool)
|
|
||||||
case let array as [Any]:
|
|
||||||
self = .array(try array.map(JSON.init))
|
|
||||||
case let dict as [String:Any]:
|
|
||||||
self = .object(try dict.mapValues(JSON.init))
|
|
||||||
default:
|
|
||||||
throw InitializationError()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension JSON {
|
|
||||||
|
|
||||||
/// Create a JSON value from an `Encodable`. This will give you access to the “raw”
|
|
||||||
/// encoded JSON value the `Encodable` is serialized into.
|
|
||||||
public init<T: Encodable>(encodable: T) throws {
|
|
||||||
let encoded = try JSONEncoder().encode(encodable)
|
|
||||||
self = try JSONDecoder().decode(JSON.self, from: encoded)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension JSON: ExpressibleByBooleanLiteral {
|
|
||||||
|
|
||||||
public init(booleanLiteral value: Bool) {
|
|
||||||
self = .bool(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension JSON: ExpressibleByNilLiteral {
|
|
||||||
|
|
||||||
public init(nilLiteral: ()) {
|
|
||||||
self = .null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension JSON: ExpressibleByArrayLiteral {
|
|
||||||
|
|
||||||
public init(arrayLiteral elements: JSON...) {
|
|
||||||
self = .array(elements)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension JSON: ExpressibleByDictionaryLiteral {
|
|
||||||
|
|
||||||
public init(dictionaryLiteral elements: (String, JSON)...) {
|
|
||||||
var object: [String:JSON] = [:]
|
|
||||||
for (k, v) in elements {
|
|
||||||
object[k] = v
|
|
||||||
}
|
|
||||||
self = .object(object)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension JSON: ExpressibleByFloatLiteral {
|
|
||||||
|
|
||||||
public init(floatLiteral value: Double) {
|
|
||||||
self = .number(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension JSON: ExpressibleByIntegerLiteral {
|
|
||||||
|
|
||||||
public init(integerLiteral value: Int) {
|
|
||||||
self = .number(Double(value))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension JSON: ExpressibleByStringLiteral {
|
|
||||||
|
|
||||||
public init(stringLiteral value: String) {
|
|
||||||
self = .string(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - NSNumber
|
|
||||||
|
|
||||||
extension NSNumber {
|
|
||||||
|
|
||||||
/// Boolean value indicating whether this `NSNumber` wraps a boolean.
|
|
||||||
///
|
|
||||||
/// For example, when using `NSJSONSerialization` Bool values are converted into `NSNumber` instances.
|
|
||||||
///
|
|
||||||
/// - seealso: https://stackoverflow.com/a/49641315/3589408
|
|
||||||
fileprivate var isBool: Bool {
|
|
||||||
let objCType = String(cString: self.objCType)
|
|
||||||
if (self.compare(trueNumber) == .orderedSame && objCType == trueObjCType) || (self.compare(falseNumber) == .orderedSame && objCType == falseObjCType) {
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private let trueNumber = NSNumber(value: true)
|
|
||||||
private let falseNumber = NSNumber(value: false)
|
|
||||||
private let trueObjCType = String(cString: trueNumber.objCType)
|
|
||||||
private let falseObjCType = String(cString: falseNumber.objCType)
|
|
||||||
82
Shared/ThirdParty/GenericJSON/JSON.swift
vendored
82
Shared/ThirdParty/GenericJSON/JSON.swift
vendored
@ -1,82 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
|
|
||||||
/// A JSON value representation. This is a bit more useful than the naïve `[String:Any]` type
|
|
||||||
/// for JSON values, since it makes sure only valid JSON values are present & supports `Equatable`
|
|
||||||
/// and `Codable`, so that you can compare values for equality and code and decode them into data
|
|
||||||
/// or strings.
|
|
||||||
@dynamicMemberLookup public enum JSON: Equatable {
|
|
||||||
case string(String)
|
|
||||||
case number(Double)
|
|
||||||
case object([String:JSON])
|
|
||||||
case array([JSON])
|
|
||||||
case bool(Bool)
|
|
||||||
case null
|
|
||||||
}
|
|
||||||
|
|
||||||
extension JSON: Codable {
|
|
||||||
|
|
||||||
public func encode(to encoder: Encoder) throws {
|
|
||||||
|
|
||||||
var container = encoder.singleValueContainer()
|
|
||||||
|
|
||||||
switch self {
|
|
||||||
case let .array(array):
|
|
||||||
try container.encode(array)
|
|
||||||
case let .object(object):
|
|
||||||
try container.encode(object)
|
|
||||||
case let .string(string):
|
|
||||||
try container.encode(string)
|
|
||||||
case let .number(number):
|
|
||||||
try container.encode(number)
|
|
||||||
case let .bool(bool):
|
|
||||||
try container.encode(bool)
|
|
||||||
case .null:
|
|
||||||
try container.encodeNil()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public init(from decoder: Decoder) throws {
|
|
||||||
|
|
||||||
let container = try decoder.singleValueContainer()
|
|
||||||
|
|
||||||
if let object = try? container.decode([String: JSON].self) {
|
|
||||||
self = .object(object)
|
|
||||||
} else if let array = try? container.decode([JSON].self) {
|
|
||||||
self = .array(array)
|
|
||||||
} else if let string = try? container.decode(String.self) {
|
|
||||||
self = .string(string)
|
|
||||||
} else if let bool = try? container.decode(Bool.self) {
|
|
||||||
self = .bool(bool)
|
|
||||||
} else if let number = try? container.decode(Double.self) {
|
|
||||||
self = .number(number)
|
|
||||||
} else if container.decodeNil() {
|
|
||||||
self = .null
|
|
||||||
} else {
|
|
||||||
throw DecodingError.dataCorrupted(
|
|
||||||
.init(codingPath: decoder.codingPath, debugDescription: "Invalid JSON value.")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension JSON: CustomDebugStringConvertible {
|
|
||||||
|
|
||||||
public var debugDescription: String {
|
|
||||||
switch self {
|
|
||||||
case .string(let str):
|
|
||||||
return str.debugDescription
|
|
||||||
case .number(let num):
|
|
||||||
return num.debugDescription
|
|
||||||
case .bool(let bool):
|
|
||||||
return bool.description
|
|
||||||
case .null:
|
|
||||||
return "null"
|
|
||||||
default:
|
|
||||||
let encoder = JSONEncoder()
|
|
||||||
encoder.outputFormatting = [.prettyPrinted]
|
|
||||||
return try! String(data: encoder.encode(self), encoding: .utf8)!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension JSON: Hashable {}
|
|
||||||
41
Shared/ThirdParty/GenericJSON/Merging.swift
vendored
41
Shared/ThirdParty/GenericJSON/Merging.swift
vendored
@ -1,41 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
|
|
||||||
extension JSON {
|
|
||||||
|
|
||||||
/// Return a new JSON value by merging two other ones
|
|
||||||
///
|
|
||||||
/// If we call the current JSON value `old` and the incoming JSON value
|
|
||||||
/// `new`, the precise merging rules are:
|
|
||||||
///
|
|
||||||
/// 1. If `old` or `new` are anything but an object, return `new`.
|
|
||||||
/// 2. If both `old` and `new` are objects, create a merged object like this:
|
|
||||||
/// 1. Add keys from `old` not present in `new` (“no change” case).
|
|
||||||
/// 2. Add keys from `new` not present in `old` (“create” case).
|
|
||||||
/// 3. For keys present in both `old` and `new`, apply merge recursively to their values (“update” case).
|
|
||||||
public func merging(with new: JSON) -> JSON {
|
|
||||||
|
|
||||||
// If old or new are anything but an object, return new.
|
|
||||||
guard case .object(let lhs) = self, case .object(let rhs) = new else {
|
|
||||||
return new
|
|
||||||
}
|
|
||||||
|
|
||||||
var merged: [String: JSON] = [:]
|
|
||||||
|
|
||||||
// Add keys from old not present in new (“no change” case).
|
|
||||||
for (key, val) in lhs where rhs[key] == nil {
|
|
||||||
merged[key] = val
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add keys from new not present in old (“create” case).
|
|
||||||
for (key, val) in rhs where lhs[key] == nil {
|
|
||||||
merged[key] = val
|
|
||||||
}
|
|
||||||
|
|
||||||
// For keys present in both old and new, apply merge recursively to their values.
|
|
||||||
for key in lhs.keys where rhs[key] != nil {
|
|
||||||
merged[key] = lhs[key]?.merging(with: rhs[key]!)
|
|
||||||
}
|
|
||||||
|
|
||||||
return JSON.object(merged)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
107
Shared/ThirdParty/GenericJSON/Querying.swift
vendored
107
Shared/ThirdParty/GenericJSON/Querying.swift
vendored
@ -1,107 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
|
|
||||||
public extension JSON {
|
|
||||||
|
|
||||||
/// Return the string value if this is a `.string`, otherwise `nil`
|
|
||||||
var stringValue: String? {
|
|
||||||
if case .string(let value) = self {
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the double value if this is a `.number`, otherwise `nil`
|
|
||||||
var doubleValue: Double? {
|
|
||||||
if case .number(let value) = self {
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the bool value if this is a `.bool`, otherwise `nil`
|
|
||||||
var boolValue: Bool? {
|
|
||||||
if case .bool(let value) = self {
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the object value if this is an `.object`, otherwise `nil`
|
|
||||||
var objectValue: [String: JSON]? {
|
|
||||||
if case .object(let value) = self {
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the array value if this is an `.array`, otherwise `nil`
|
|
||||||
var arrayValue: [JSON]? {
|
|
||||||
if case .array(let value) = self {
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return `true` iff this is `.null`
|
|
||||||
var isNull: Bool {
|
|
||||||
if case .null = self {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
/// If this is an `.array`, return item at index
|
|
||||||
///
|
|
||||||
/// If this is not an `.array` or the index is out of bounds, returns `nil`.
|
|
||||||
subscript(index: Int) -> JSON? {
|
|
||||||
if case .array(let arr) = self, arr.indices.contains(index) {
|
|
||||||
return arr[index]
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
/// If this is an `.object`, return item at key
|
|
||||||
subscript(key: String) -> JSON? {
|
|
||||||
if case .object(let dict) = self {
|
|
||||||
return dict[key]
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Dynamic member lookup sugar for string subscripts
|
|
||||||
///
|
|
||||||
/// This lets you write `json.foo` instead of `json["foo"]`.
|
|
||||||
subscript(dynamicMember member: String) -> JSON? {
|
|
||||||
return self[member]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the JSON type at the keypath if this is an `.object`, otherwise `nil`
|
|
||||||
///
|
|
||||||
/// This lets you write `json[keyPath: "foo.bar.jar"]`.
|
|
||||||
subscript(keyPath keyPath: String) -> JSON? {
|
|
||||||
return queryKeyPath(keyPath.components(separatedBy: "."))
|
|
||||||
}
|
|
||||||
|
|
||||||
func queryKeyPath<T>(_ path: T) -> JSON? where T: Collection, T.Element == String {
|
|
||||||
|
|
||||||
// Only object values may be subscripted
|
|
||||||
guard case .object(let object) = self else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Is the path non-empty?
|
|
||||||
guard let head = path.first else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do we have a value at the required key?
|
|
||||||
guard let value = object[head] else {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
let tail = path.dropFirst()
|
|
||||||
|
|
||||||
return tail.isEmpty ? value : value.queryKeyPath(tail)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,12 +1,23 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public class Api {
|
public protocol ApiProtocol {
|
||||||
|
|
||||||
private var session: URLSession
|
func login(email: String, password: String) async throws -> User
|
||||||
|
func check(plateNumber: String, force: Bool) async throws -> Vehicle
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Api: ApiProtocol {
|
||||||
|
|
||||||
|
private let session: URLSession
|
||||||
|
private let settings: SettingsProtocol
|
||||||
|
|
||||||
public static let shared = Api()
|
public static let shared = Api()
|
||||||
|
|
||||||
public init(session: URLSession? = nil) {
|
public init(session: URLSession? = nil, settings: SettingsProtocol = Settings.shared) {
|
||||||
|
|
||||||
|
self.settings = settings
|
||||||
|
|
||||||
if let session = session {
|
if let session = session {
|
||||||
self.session = session
|
self.session = session
|
||||||
} else {
|
} else {
|
||||||
@ -34,7 +45,7 @@ public class Api {
|
|||||||
request.httpMethod = method
|
request.httpMethod = method
|
||||||
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
|
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
|
||||||
request.addValue("application/json", forHTTPHeaderField: "Accept")
|
request.addValue("application/json", forHTTPHeaderField: "Accept")
|
||||||
request.addValue("Bearer " + Settings.shared.user.token, forHTTPHeaderField: "Authorization")
|
request.addValue("Bearer " + settings.user.token, forHTTPHeaderField: "Authorization")
|
||||||
|
|
||||||
if let body = body, method.uppercased() != "GET" {
|
if let body = body, method.uppercased() != "GET" {
|
||||||
let encoder = JSONEncoder()
|
let encoder = JSONEncoder()
|
||||||
@ -103,10 +114,26 @@ public class Api {
|
|||||||
// MARK: - AutoCat public API
|
// MARK: - AutoCat public API
|
||||||
|
|
||||||
public func login(email: String, password: String) async throws -> User {
|
public func login(email: String, password: String) async throws -> User {
|
||||||
|
|
||||||
let body = [
|
let body = [
|
||||||
"email": email,
|
"email": email,
|
||||||
"password": password
|
"password": password
|
||||||
]
|
]
|
||||||
|
|
||||||
return try await self.makeBodyRequest(api: "user/login", body: body)
|
return try await self.makeBodyRequest(api: "user/login", body: body)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public func check(plateNumber: String, force: Bool = false) async throws -> Vehicle {
|
||||||
|
|
||||||
|
var body = [
|
||||||
|
"number": AnyEncodable(plateNumber),
|
||||||
|
"forceUpdate": AnyEncodable(force)
|
||||||
|
]
|
||||||
|
|
||||||
|
if let token = settings.user.firebaseIdToken {
|
||||||
|
body["googleIdToken"] = AnyEncodable(token)
|
||||||
|
}
|
||||||
|
|
||||||
|
return try await self.makeBodyRequest(api: "vehicles/check", body: body)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,11 +3,15 @@ import Foundation
|
|||||||
public struct Constants {
|
public struct Constants {
|
||||||
public static var baseUrl: String {
|
public static var baseUrl: String {
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
//return "http://127.0.0.1:3000/"
|
return "http://127.0.0.1:3000/"
|
||||||
//return "http://192.168.1.67:3000/"
|
//return "http://192.168.1.67:3000/"
|
||||||
return "https://vps.aliencat.pro:8443/"
|
//return "https://vps.aliencat.pro:8443/"
|
||||||
#else
|
#else
|
||||||
return "https://vps.aliencat.pro:8443/"
|
return "https://vps.aliencat.pro:8443/"
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static let pnLettersMap: [Character: Character] = [
|
||||||
|
"А": "A", "В": "B", "Е": "E", "К": "K", "М": "M", "Н": "H", "О": "O", "Р": "P", "С": "C", "Т": "T", "У": "Y", "Х": "X"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,17 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public class AuthVM: ObservableObject {
|
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 {
|
public func login(user: String, password: String) async throws {
|
||||||
Settings.shared.user = try await Api.shared.login(email: user, password: password)
|
settings.user = try await api.login(email: user, password: password)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -47,6 +47,7 @@ struct AuthView: View {
|
|||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
.buttonStyle(.bordered)
|
.buttonStyle(.bordered)
|
||||||
|
.controlSize(.large)
|
||||||
.textFieldStyle(.roundedBorder)
|
.textFieldStyle(.roundedBorder)
|
||||||
.padding(20)
|
.padding(20)
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import SwiftUI
|
|||||||
|
|
||||||
struct CheckView: View {
|
struct CheckView: View {
|
||||||
@State private var number: String = ""
|
@State private var number: String = ""
|
||||||
@FetchRequest(entity: Vehicle.entity(), sortDescriptors: []) var vehicles: FetchedResults<Vehicle>
|
@FetchRequest(entity: CDVehicle.entity(), sortDescriptors: []) var vehicles: FetchedResults<CDVehicle>
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
NavigationView {
|
NavigationView {
|
||||||
|
|||||||
67
Shared/Views/PlateNumberView.swift
Normal file
67
Shared/Views/PlateNumberView.swift
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
//
|
||||||
|
// 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))
|
||||||
|
}
|
||||||
|
}
|
||||||
56
Shared/Views/macOS/CheckNumberPopup.swift
Normal file
56
Shared/Views/macOS/CheckNumberPopup.swift
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
//
|
||||||
|
// 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()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -12,21 +12,22 @@ struct MainViewBig: View {
|
|||||||
|
|
||||||
struct SidebarView: View {
|
struct SidebarView: View {
|
||||||
@State var selection: String?
|
@State var selection: String?
|
||||||
|
@State private var showAddPlateNumberView = false
|
||||||
|
|
||||||
@FetchRequest(entity: Vehicle.entity(), sortDescriptors: []) var vehicles: FetchedResults<Vehicle>
|
@FetchRequest(entity: CDVehicle.entity(), sortDescriptors: []) var vehicles: FetchedResults<CDVehicle>
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
List(selection: $selection) {
|
List(selection: $selection) {
|
||||||
Section("History") {
|
Section("History") {
|
||||||
NavigationLink(destination: VehiclesListView()) {
|
NavigationLink(destination: VehiclesListView(vehicles: vehicles)) {
|
||||||
Label("All", systemImage: "car.2")
|
Label("All", systemImage: "car.2")
|
||||||
.badge(vehicles.count)
|
.badge(vehicles.count)
|
||||||
}
|
}
|
||||||
NavigationLink(destination: VehiclesListView()) {
|
NavigationLink(destination: VehiclesListView(vehicles: vehicles.filter(\.unrecognized))) {
|
||||||
Label("Unreconized", systemImage: "eye.slash")
|
Label("Unreconized", systemImage: "eye.slash")
|
||||||
.badge(vehicles.filter(\.unrecognized).count)
|
.badge(vehicles.filter(\.unrecognized).count)
|
||||||
}
|
}
|
||||||
NavigationLink(destination: VehiclesListView()) {
|
NavigationLink(destination: VehiclesListView(vehicles: vehicles.filter(\.outdated))) {
|
||||||
Label("Outdated", systemImage: "wind")
|
Label("Outdated", systemImage: "wind")
|
||||||
.badge(vehicles.filter(\.outdated).count)
|
.badge(vehicles.filter(\.outdated).count)
|
||||||
}
|
}
|
||||||
@ -40,13 +41,18 @@ struct SidebarView: View {
|
|||||||
.collapsible(false)
|
.collapsible(false)
|
||||||
}
|
}
|
||||||
.frame(minWidth: 180)
|
.frame(minWidth: 180)
|
||||||
|
.sheet(isPresented: $showAddPlateNumberView, onDismiss: {
|
||||||
|
print("Dismiss")
|
||||||
|
}, content: {
|
||||||
|
CheckNumberPopup()
|
||||||
|
})
|
||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarItem {
|
ToolbarItem {
|
||||||
Spacer()
|
Spacer()
|
||||||
}
|
}
|
||||||
ToolbarItem {
|
ToolbarItem {
|
||||||
Button {
|
Button {
|
||||||
|
self.showAddPlateNumberView = true
|
||||||
} label: {
|
} label: {
|
||||||
Image(systemName: "plus")
|
Image(systemName: "plus")
|
||||||
}
|
}
|
||||||
@ -56,16 +62,18 @@ struct SidebarView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct VehiclesListView: View {
|
struct VehiclesListView<VehicleCollection>: View where VehicleCollection: RandomAccessCollection, VehicleCollection.Element == CDVehicle {
|
||||||
var body: some View {
|
|
||||||
Text("Vehicles list")
|
|
||||||
.toolbar {
|
|
||||||
ToolbarItem(placement: .primaryAction) {
|
|
||||||
Button("xxx") {
|
|
||||||
|
|
||||||
}
|
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)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user