Initial commit

This commit is contained in:
Selim Mustafaev 2020-02-24 01:30:42 +03:00
parent 4b25e202f2
commit 64cb79360f
33 changed files with 2238 additions and 58 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
Carthage/

View File

@ -3,27 +3,76 @@
archiveVersion = 1; archiveVersion = 1;
classes = { classes = {
}; };
objectVersion = 50; objectVersion = 52;
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
7A11470123FDE7E500B424AF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11470023FDE7E500B424AF /* AppDelegate.swift */; }; 7A11470123FDE7E500B424AF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11470023FDE7E500B424AF /* AppDelegate.swift */; };
7A11470323FDE7E500B424AF /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11470223FDE7E500B424AF /* SceneDelegate.swift */; }; 7A11470323FDE7E500B424AF /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11470223FDE7E500B424AF /* SceneDelegate.swift */; };
7A11470523FDE7E500B424AF /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11470423FDE7E500B424AF /* ViewController.swift */; };
7A11470823FDE7E500B424AF /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7A11470623FDE7E500B424AF /* Main.storyboard */; }; 7A11470823FDE7E500B424AF /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7A11470623FDE7E500B424AF /* Main.storyboard */; };
7A11470A23FDE7E600B424AF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7A11470923FDE7E600B424AF /* Assets.xcassets */; }; 7A11470A23FDE7E600B424AF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7A11470923FDE7E600B424AF /* Assets.xcassets */; };
7A11470D23FDE7E600B424AF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7A11470B23FDE7E600B424AF /* LaunchScreen.storyboard */; }; 7A11470D23FDE7E600B424AF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7A11470B23FDE7E600B424AF /* LaunchScreen.storyboard */; };
7A11471623FDEB2A00B424AF /* MainSplitController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11471523FDEB2A00B424AF /* MainSplitController.swift */; };
7A11471823FDEBFA00B424AF /* ReportController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11471723FDEBFA00B424AF /* ReportController.swift */; };
7A11471A23FE839000B424AF /* AuthController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11471923FE839000B424AF /* AuthController.swift */; };
7A11471D23FEA18700B424AF /* RxSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 7A11471C23FEA18700B424AF /* RxSwift */; };
7A11471F23FEA18700B424AF /* RxRelay in Frameworks */ = {isa = PBXBuildFile; productRef = 7A11471E23FEA18700B424AF /* RxRelay */; };
7A11472123FEA18700B424AF /* RxCocoa in Frameworks */ = {isa = PBXBuildFile; productRef = 7A11472023FEA18700B424AF /* RxCocoa */; };
7A11472323FEA18700B424AF /* RxBlocking in Frameworks */ = {isa = PBXBuildFile; productRef = 7A11472223FEA18700B424AF /* RxBlocking */; };
7A11472623FEA1F400B424AF /* Realm in Frameworks */ = {isa = PBXBuildFile; productRef = 7A11472523FEA1F400B424AF /* Realm */; };
7A11472823FEA1F400B424AF /* RealmSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 7A11472723FEA1F400B424AF /* RealmSwift */; };
7A11472B23FEA24D00B424AF /* Action in Frameworks */ = {isa = PBXBuildFile; productRef = 7A11472A23FEA24D00B424AF /* Action */; };
7A11474423FF06CA00B424AF /* Api.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11474323FF06CA00B424AF /* Api.swift */; };
7A11474723FF2AA500B424AF /* User.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11474623FF2AA500B424AF /* User.swift */; };
7A11474923FF2B2D00B424AF /* Response.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11474823FF2B2D00B424AF /* Response.swift */; };
7A11474B23FF368B00B424AF /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11474A23FF368B00B424AF /* Settings.swift */; };
7A11474E23FFEE8800B424AF /* SVProgressHUD.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A11474D23FFEE8800B424AF /* SVProgressHUD.framework */; };
7A530B78240010D900CBFE6E /* InputMask in Frameworks */ = {isa = PBXBuildFile; productRef = 7A530B77240010D900CBFE6E /* InputMask */; };
7A530B7A24001D3300CBFE6E /* CheckController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B7924001D3300CBFE6E /* CheckController.swift */; };
7A530B7E24017FEE00CBFE6E /* VehicleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B7D24017FEE00CBFE6E /* VehicleCell.swift */; };
7A530B802401803A00CBFE6E /* Vehicle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B7F2401803A00CBFE6E /* Vehicle.swift */; };
7A530B85240180CC00CBFE6E /* RxCollectionViewRealmDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B81240180CC00CBFE6E /* RxCollectionViewRealmDataSource.swift */; };
7A530B86240180CC00CBFE6E /* RealmBindObserver.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B82240180CC00CBFE6E /* RealmBindObserver.swift */; };
7A530B87240180CC00CBFE6E /* Reactive+RxRealmDataSources.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B83240180CC00CBFE6E /* Reactive+RxRealmDataSources.swift */; };
7A530B88240180CC00CBFE6E /* RxTableViewRealmDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B84240180CC00CBFE6E /* RxTableViewRealmDataSource.swift */; };
7A530B8B240181F500CBFE6E /* RxRealm in Frameworks */ = {isa = PBXBuildFile; productRef = 7A530B8A240181F500CBFE6E /* RxRealm */; };
7A7547DD2403180A004E8406 /* SectionHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A7547DB2403180A004E8406 /* SectionHeader.swift */; };
7A7547DE2403180A004E8406 /* SectionHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7A7547DC2403180A004E8406 /* SectionHeader.xib */; };
7A7547E024032CB6004E8406 /* VehiclePhotoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A7547DF24032CB6004E8406 /* VehiclePhotoCell.swift */; };
7AF58D2F24029C5200CE01A0 /* MagazineLayout in Frameworks */ = {isa = PBXBuildFile; productRef = 7AF58D2E24029C5200CE01A0 /* MagazineLayout */; };
7AF58D3124029E1000CE01A0 /* VehicleHeaderCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF58D3024029E1000CE01A0 /* VehicleHeaderCell.swift */; };
7AF58D342402A91C00CE01A0 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 7AF58D332402A91C00CE01A0 /* Kingfisher */; };
7AF58D58240309CA00CE01A0 /* VehicleTextParamCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF58D57240309CA00CE01A0 /* VehicleTextParamCell.swift */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
7A1146FD23FDE7E500B424AF /* AutoCat.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AutoCat.app; sourceTree = BUILT_PRODUCTS_DIR; }; 7A1146FD23FDE7E500B424AF /* AutoCat.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AutoCat.app; sourceTree = BUILT_PRODUCTS_DIR; };
7A11470023FDE7E500B424AF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; }; 7A11470023FDE7E500B424AF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7A11470223FDE7E500B424AF /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; }; 7A11470223FDE7E500B424AF /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
7A11470423FDE7E500B424AF /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
7A11470723FDE7E500B424AF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; }; 7A11470723FDE7E500B424AF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
7A11470923FDE7E600B424AF /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; }; 7A11470923FDE7E600B424AF /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
7A11470C23FDE7E600B424AF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; }; 7A11470C23FDE7E600B424AF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
7A11470E23FDE7E600B424AF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 7A11470E23FDE7E600B424AF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
7A11471523FDEB2A00B424AF /* MainSplitController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainSplitController.swift; sourceTree = "<group>"; };
7A11471723FDEBFA00B424AF /* ReportController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReportController.swift; sourceTree = "<group>"; };
7A11471923FE839000B424AF /* AuthController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthController.swift; sourceTree = "<group>"; };
7A11474323FF06CA00B424AF /* Api.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Api.swift; sourceTree = "<group>"; };
7A11474623FF2AA500B424AF /* User.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = User.swift; sourceTree = "<group>"; };
7A11474823FF2B2D00B424AF /* Response.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Response.swift; sourceTree = "<group>"; };
7A11474A23FF368B00B424AF /* Settings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Settings.swift; sourceTree = "<group>"; };
7A11474D23FFEE8800B424AF /* SVProgressHUD.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SVProgressHUD.framework; path = Carthage/Build/iOS/SVProgressHUD.framework; sourceTree = "<group>"; };
7A530B7924001D3300CBFE6E /* CheckController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckController.swift; sourceTree = "<group>"; };
7A530B7D24017FEE00CBFE6E /* VehicleCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehicleCell.swift; sourceTree = "<group>"; };
7A530B7F2401803A00CBFE6E /* Vehicle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Vehicle.swift; sourceTree = "<group>"; };
7A530B81240180CC00CBFE6E /* RxCollectionViewRealmDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxCollectionViewRealmDataSource.swift; sourceTree = "<group>"; };
7A530B82240180CC00CBFE6E /* RealmBindObserver.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RealmBindObserver.swift; sourceTree = "<group>"; };
7A530B83240180CC00CBFE6E /* Reactive+RxRealmDataSources.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Reactive+RxRealmDataSources.swift"; sourceTree = "<group>"; };
7A530B84240180CC00CBFE6E /* RxTableViewRealmDataSource.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RxTableViewRealmDataSource.swift; sourceTree = "<group>"; };
7A7547DB2403180A004E8406 /* SectionHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionHeader.swift; sourceTree = "<group>"; };
7A7547DC2403180A004E8406 /* SectionHeader.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = SectionHeader.xib; sourceTree = "<group>"; };
7A7547DF24032CB6004E8406 /* VehiclePhotoCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehiclePhotoCell.swift; sourceTree = "<group>"; };
7AF58D3024029E1000CE01A0 /* VehicleHeaderCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehicleHeaderCell.swift; sourceTree = "<group>"; };
7AF58D57240309CA00CE01A0 /* VehicleTextParamCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehicleTextParamCell.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@ -31,6 +80,18 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
7AF58D342402A91C00CE01A0 /* Kingfisher in Frameworks */,
7A11472823FEA1F400B424AF /* RealmSwift in Frameworks */,
7A11472123FEA18700B424AF /* RxCocoa in Frameworks */,
7A11474E23FFEE8800B424AF /* SVProgressHUD.framework in Frameworks */,
7A11472323FEA18700B424AF /* RxBlocking in Frameworks */,
7A530B8B240181F500CBFE6E /* RxRealm in Frameworks */,
7A11472B23FEA24D00B424AF /* Action in Frameworks */,
7A11471F23FEA18700B424AF /* RxRelay in Frameworks */,
7AF58D2F24029C5200CE01A0 /* MagazineLayout in Frameworks */,
7A530B78240010D900CBFE6E /* InputMask in Frameworks */,
7A11471D23FEA18700B424AF /* RxSwift in Frameworks */,
7A11472623FEA1F400B424AF /* Realm in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -42,6 +103,7 @@
children = ( children = (
7A1146FF23FDE7E500B424AF /* AutoCat */, 7A1146FF23FDE7E500B424AF /* AutoCat */,
7A1146FE23FDE7E500B424AF /* Products */, 7A1146FE23FDE7E500B424AF /* Products */,
7A11474C23FFEE8700B424AF /* Frameworks */,
); );
sourceTree = "<group>"; sourceTree = "<group>";
}; };
@ -56,9 +118,13 @@
7A1146FF23FDE7E500B424AF /* AutoCat */ = { 7A1146FF23FDE7E500B424AF /* AutoCat */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
7A530B7C24017FBE00CBFE6E /* Cells */,
7A11474523FF2A9000B424AF /* Models */,
7A11474223FF06B600B424AF /* Utils */,
7A11472C23FECA3E00B424AF /* ThirdParty */,
7A11471423FDEAF800B424AF /* Controllers */,
7A11470023FDE7E500B424AF /* AppDelegate.swift */, 7A11470023FDE7E500B424AF /* AppDelegate.swift */,
7A11470223FDE7E500B424AF /* SceneDelegate.swift */, 7A11470223FDE7E500B424AF /* SceneDelegate.swift */,
7A11470423FDE7E500B424AF /* ViewController.swift */,
7A11470623FDE7E500B424AF /* Main.storyboard */, 7A11470623FDE7E500B424AF /* Main.storyboard */,
7A11470923FDE7E600B424AF /* Assets.xcassets */, 7A11470923FDE7E600B424AF /* Assets.xcassets */,
7A11470B23FDE7E600B424AF /* LaunchScreen.storyboard */, 7A11470B23FDE7E600B424AF /* LaunchScreen.storyboard */,
@ -67,6 +133,76 @@
path = AutoCat; path = AutoCat;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
7A11471423FDEAF800B424AF /* Controllers */ = {
isa = PBXGroup;
children = (
7A11471523FDEB2A00B424AF /* MainSplitController.swift */,
7A11471723FDEBFA00B424AF /* ReportController.swift */,
7A11471923FE839000B424AF /* AuthController.swift */,
7A530B7924001D3300CBFE6E /* CheckController.swift */,
);
path = Controllers;
sourceTree = "<group>";
};
7A11472C23FECA3E00B424AF /* ThirdParty */ = {
isa = PBXGroup;
children = (
7A530B7B24017DED00CBFE6E /* RxRealmDataSources */,
);
path = ThirdParty;
sourceTree = "<group>";
};
7A11474223FF06B600B424AF /* Utils */ = {
isa = PBXGroup;
children = (
7A11474323FF06CA00B424AF /* Api.swift */,
);
path = Utils;
sourceTree = "<group>";
};
7A11474523FF2A9000B424AF /* Models */ = {
isa = PBXGroup;
children = (
7A11474623FF2AA500B424AF /* User.swift */,
7A11474823FF2B2D00B424AF /* Response.swift */,
7A11474A23FF368B00B424AF /* Settings.swift */,
7A530B7F2401803A00CBFE6E /* Vehicle.swift */,
);
path = Models;
sourceTree = "<group>";
};
7A11474C23FFEE8700B424AF /* Frameworks */ = {
isa = PBXGroup;
children = (
7A11474D23FFEE8800B424AF /* SVProgressHUD.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
7A530B7B24017DED00CBFE6E /* RxRealmDataSources */ = {
isa = PBXGroup;
children = (
7A530B83240180CC00CBFE6E /* Reactive+RxRealmDataSources.swift */,
7A530B82240180CC00CBFE6E /* RealmBindObserver.swift */,
7A530B81240180CC00CBFE6E /* RxCollectionViewRealmDataSource.swift */,
7A530B84240180CC00CBFE6E /* RxTableViewRealmDataSource.swift */,
);
path = RxRealmDataSources;
sourceTree = "<group>";
};
7A530B7C24017FBE00CBFE6E /* Cells */ = {
isa = PBXGroup;
children = (
7A530B7D24017FEE00CBFE6E /* VehicleCell.swift */,
7AF58D3024029E1000CE01A0 /* VehicleHeaderCell.swift */,
7AF58D57240309CA00CE01A0 /* VehicleTextParamCell.swift */,
7A7547DB2403180A004E8406 /* SectionHeader.swift */,
7A7547DC2403180A004E8406 /* SectionHeader.xib */,
7A7547DF24032CB6004E8406 /* VehiclePhotoCell.swift */,
);
path = Cells;
sourceTree = "<group>";
};
/* End PBXGroup section */ /* End PBXGroup section */
/* Begin PBXNativeTarget section */ /* Begin PBXNativeTarget section */
@ -77,12 +213,26 @@
7A1146F923FDE7E500B424AF /* Sources */, 7A1146F923FDE7E500B424AF /* Sources */,
7A1146FA23FDE7E500B424AF /* Frameworks */, 7A1146FA23FDE7E500B424AF /* Frameworks */,
7A1146FB23FDE7E500B424AF /* Resources */, 7A1146FB23FDE7E500B424AF /* Resources */,
7A11475123FFF02E00B424AF /* ShellScript */,
); );
buildRules = ( buildRules = (
); );
dependencies = ( dependencies = (
); );
name = AutoCat; name = AutoCat;
packageProductDependencies = (
7A11471C23FEA18700B424AF /* RxSwift */,
7A11471E23FEA18700B424AF /* RxRelay */,
7A11472023FEA18700B424AF /* RxCocoa */,
7A11472223FEA18700B424AF /* RxBlocking */,
7A11472523FEA1F400B424AF /* Realm */,
7A11472723FEA1F400B424AF /* RealmSwift */,
7A11472A23FEA24D00B424AF /* Action */,
7A530B77240010D900CBFE6E /* InputMask */,
7A530B8A240181F500CBFE6E /* RxRealm */,
7AF58D2E24029C5200CE01A0 /* MagazineLayout */,
7AF58D332402A91C00CE01A0 /* Kingfisher */,
);
productName = AutoCat; productName = AutoCat;
productReference = 7A1146FD23FDE7E500B424AF /* AutoCat.app */; productReference = 7A1146FD23FDE7E500B424AF /* AutoCat.app */;
productType = "com.apple.product-type.application"; productType = "com.apple.product-type.application";
@ -111,6 +261,15 @@
Base, Base,
); );
mainGroup = 7A1146F423FDE7E500B424AF; mainGroup = 7A1146F423FDE7E500B424AF;
packageReferences = (
7A11471B23FEA18700B424AF /* XCRemoteSwiftPackageReference "RxSwift" */,
7A11472423FEA1F400B424AF /* XCRemoteSwiftPackageReference "realm-cocoa" */,
7A11472923FEA24D00B424AF /* XCRemoteSwiftPackageReference "Action" */,
7A530B76240010D900CBFE6E /* XCRemoteSwiftPackageReference "input-mask-ios" */,
7A530B89240181F500CBFE6E /* XCRemoteSwiftPackageReference "RxRealm" */,
7AF58D2D24029C5200CE01A0 /* XCRemoteSwiftPackageReference "MagazineLayout" */,
7AF58D322402A91C00CE01A0 /* XCRemoteSwiftPackageReference "Kingfisher" */,
);
productRefGroup = 7A1146FE23FDE7E500B424AF /* Products */; productRefGroup = 7A1146FE23FDE7E500B424AF /* Products */;
projectDirPath = ""; projectDirPath = "";
projectRoot = ""; projectRoot = "";
@ -125,6 +284,7 @@
isa = PBXResourcesBuildPhase; isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
7A7547DE2403180A004E8406 /* SectionHeader.xib in Resources */,
7A11470D23FDE7E600B424AF /* LaunchScreen.storyboard in Resources */, 7A11470D23FDE7E600B424AF /* LaunchScreen.storyboard in Resources */,
7A11470A23FDE7E600B424AF /* Assets.xcassets in Resources */, 7A11470A23FDE7E600B424AF /* Assets.xcassets in Resources */,
7A11470823FDE7E500B424AF /* Main.storyboard in Resources */, 7A11470823FDE7E500B424AF /* Main.storyboard in Resources */,
@ -133,14 +293,53 @@
}; };
/* End PBXResourcesBuildPhase section */ /* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
7A11475123FFF02E00B424AF /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"$(SRCROOT)/input.xcfilelist",
);
inputPaths = (
);
outputFileListPaths = (
"$(SRCROOT)/output.xcfilelist",
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "# Type a script or drag a script file from your workspace to insert its path.\n/usr/local/bin/carthage copy-frameworks\n";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */
7A1146F923FDE7E500B424AF /* Sources */ = { 7A1146F923FDE7E500B424AF /* Sources */ = {
isa = PBXSourcesBuildPhase; isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
7A11470523FDE7E500B424AF /* ViewController.swift in Sources */, 7A530B802401803A00CBFE6E /* Vehicle.swift in Sources */,
7A11470123FDE7E500B424AF /* AppDelegate.swift in Sources */, 7A11470123FDE7E500B424AF /* AppDelegate.swift in Sources */,
7A530B86240180CC00CBFE6E /* RealmBindObserver.swift in Sources */,
7A11474923FF2B2D00B424AF /* Response.swift in Sources */,
7A11471823FDEBFA00B424AF /* ReportController.swift in Sources */,
7A11471A23FE839000B424AF /* AuthController.swift in Sources */,
7A530B7A24001D3300CBFE6E /* CheckController.swift in Sources */,
7A7547DD2403180A004E8406 /* SectionHeader.swift in Sources */,
7AF58D58240309CA00CE01A0 /* VehicleTextParamCell.swift in Sources */,
7A11474723FF2AA500B424AF /* User.swift in Sources */,
7A530B88240180CC00CBFE6E /* RxTableViewRealmDataSource.swift in Sources */,
7A11471623FDEB2A00B424AF /* MainSplitController.swift in Sources */,
7AF58D3124029E1000CE01A0 /* VehicleHeaderCell.swift in Sources */,
7A530B85240180CC00CBFE6E /* RxCollectionViewRealmDataSource.swift in Sources */,
7A11470323FDE7E500B424AF /* SceneDelegate.swift in Sources */, 7A11470323FDE7E500B424AF /* SceneDelegate.swift in Sources */,
7A530B7E24017FEE00CBFE6E /* VehicleCell.swift in Sources */,
7A530B87240180CC00CBFE6E /* Reactive+RxRealmDataSources.swift in Sources */,
7A11474423FF06CA00B424AF /* Api.swift in Sources */,
7A11474B23FF368B00B424AF /* Settings.swift in Sources */,
7A7547E024032CB6004E8406 /* VehiclePhotoCell.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -286,12 +485,17 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = 46DTTB8X4S; DEVELOPMENT_TEAM = 46DTTB8X4S;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/iOS",
);
INFOPLIST_FILE = AutoCat/Info.plist; INFOPLIST_FILE = AutoCat/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCat.AutoCat; PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCat;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1,2";
@ -304,12 +508,17 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = 46DTTB8X4S; DEVELOPMENT_TEAM = 46DTTB8X4S;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/iOS",
);
INFOPLIST_FILE = AutoCat/Info.plist; INFOPLIST_FILE = AutoCat/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
"@executable_path/Frameworks", "@executable_path/Frameworks",
); );
PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCat.AutoCat; PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCat;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0; SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2"; TARGETED_DEVICE_FAMILY = "1,2";
@ -338,6 +547,123 @@
defaultConfigurationName = Release; defaultConfigurationName = Release;
}; };
/* End XCConfigurationList section */ /* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
7A11471B23FEA18700B424AF /* XCRemoteSwiftPackageReference "RxSwift" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/ReactiveX/RxSwift.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 5.0.1;
};
};
7A11472423FEA1F400B424AF /* XCRemoteSwiftPackageReference "realm-cocoa" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/realm/realm-cocoa";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 4.3.2;
};
};
7A11472923FEA24D00B424AF /* XCRemoteSwiftPackageReference "Action" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/RxSwiftCommunity/Action";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 4.0.1;
};
};
7A530B76240010D900CBFE6E /* XCRemoteSwiftPackageReference "input-mask-ios" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/RedMadRobot/input-mask-ios";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 5.0.0;
};
};
7A530B89240181F500CBFE6E /* XCRemoteSwiftPackageReference "RxRealm" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/RxSwiftCommunity/RxRealm";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 2.0.0;
};
};
7AF58D2D24029C5200CE01A0 /* XCRemoteSwiftPackageReference "MagazineLayout" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/airbnb/MagazineLayout";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 1.5.5;
};
};
7AF58D322402A91C00CE01A0 /* XCRemoteSwiftPackageReference "Kingfisher" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/onevcat/Kingfisher";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 5.13.1;
};
};
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
7A11471C23FEA18700B424AF /* RxSwift */ = {
isa = XCSwiftPackageProductDependency;
package = 7A11471B23FEA18700B424AF /* XCRemoteSwiftPackageReference "RxSwift" */;
productName = RxSwift;
};
7A11471E23FEA18700B424AF /* RxRelay */ = {
isa = XCSwiftPackageProductDependency;
package = 7A11471B23FEA18700B424AF /* XCRemoteSwiftPackageReference "RxSwift" */;
productName = RxRelay;
};
7A11472023FEA18700B424AF /* RxCocoa */ = {
isa = XCSwiftPackageProductDependency;
package = 7A11471B23FEA18700B424AF /* XCRemoteSwiftPackageReference "RxSwift" */;
productName = RxCocoa;
};
7A11472223FEA18700B424AF /* RxBlocking */ = {
isa = XCSwiftPackageProductDependency;
package = 7A11471B23FEA18700B424AF /* XCRemoteSwiftPackageReference "RxSwift" */;
productName = RxBlocking;
};
7A11472523FEA1F400B424AF /* Realm */ = {
isa = XCSwiftPackageProductDependency;
package = 7A11472423FEA1F400B424AF /* XCRemoteSwiftPackageReference "realm-cocoa" */;
productName = Realm;
};
7A11472723FEA1F400B424AF /* RealmSwift */ = {
isa = XCSwiftPackageProductDependency;
package = 7A11472423FEA1F400B424AF /* XCRemoteSwiftPackageReference "realm-cocoa" */;
productName = RealmSwift;
};
7A11472A23FEA24D00B424AF /* Action */ = {
isa = XCSwiftPackageProductDependency;
package = 7A11472923FEA24D00B424AF /* XCRemoteSwiftPackageReference "Action" */;
productName = Action;
};
7A530B77240010D900CBFE6E /* InputMask */ = {
isa = XCSwiftPackageProductDependency;
package = 7A530B76240010D900CBFE6E /* XCRemoteSwiftPackageReference "input-mask-ios" */;
productName = InputMask;
};
7A530B8A240181F500CBFE6E /* RxRealm */ = {
isa = XCSwiftPackageProductDependency;
package = 7A530B89240181F500CBFE6E /* XCRemoteSwiftPackageReference "RxRealm" */;
productName = RxRealm;
};
7AF58D2E24029C5200CE01A0 /* MagazineLayout */ = {
isa = XCSwiftPackageProductDependency;
package = 7AF58D2D24029C5200CE01A0 /* XCRemoteSwiftPackageReference "MagazineLayout" */;
productName = MagazineLayout;
};
7AF58D332402A91C00CE01A0 /* Kingfisher */ = {
isa = XCSwiftPackageProductDependency;
package = 7AF58D322402A91C00CE01A0 /* XCRemoteSwiftPackageReference "Kingfisher" */;
productName = Kingfisher;
};
/* End XCSwiftPackageProductDependency section */
}; };
rootObject = 7A1146F523FDE7E500B424AF /* Project object */; rootObject = 7A1146F523FDE7E500B424AF /* Project object */;
} }

View File

@ -2,6 +2,6 @@
<Workspace <Workspace
version = "1.0"> version = "1.0">
<FileRef <FileRef
location = "self:AutoCat.xcodeproj"> location = "self:">
</FileRef> </FileRef>
</Workspace> </Workspace>

View File

@ -0,0 +1,79 @@
{
"object": {
"pins": [
{
"package": "Action",
"repositoryURL": "https://github.com/RxSwiftCommunity/Action",
"state": {
"branch": null,
"revision": "cdade63f7bbe1f5e1eff7779e5858a796dc2c001",
"version": "4.0.1"
}
},
{
"package": "InputMask",
"repositoryURL": "https://github.com/RedMadRobot/input-mask-ios",
"state": {
"branch": null,
"revision": "78a98f31d5b7fe2c0d84146748f22114c1c17c7c",
"version": "5.0.0"
}
},
{
"package": "Kingfisher",
"repositoryURL": "https://github.com/onevcat/Kingfisher",
"state": {
"branch": null,
"revision": "46bf251fee8ed426921c647790f08ca8ad0105a9",
"version": "5.13.1"
}
},
{
"package": "MagazineLayout",
"repositoryURL": "https://github.com/airbnb/MagazineLayout",
"state": {
"branch": null,
"revision": "bbbe1456c34c1abb527d05ff9da3ff2a54584d78",
"version": "1.5.5"
}
},
{
"package": "Realm",
"repositoryURL": "https://github.com/realm/realm-cocoa",
"state": {
"branch": null,
"revision": "913d59c6522e3007c7cbac3a8e9775abf72c054c",
"version": "4.3.2"
}
},
{
"package": "RealmCore",
"repositoryURL": "https://github.com/realm/realm-core",
"state": {
"branch": null,
"revision": "35662ff940e340bf630ad1d1d88acfc7af18bee6",
"version": "5.23.8"
}
},
{
"package": "RxRealm",
"repositoryURL": "https://github.com/RxSwiftCommunity/RxRealm",
"state": {
"branch": null,
"revision": "70188d79fe2eb19b5013dd1deae33e9e53f10e76",
"version": "2.0.0"
}
},
{
"package": "RxSwift",
"repositoryURL": "https://github.com/ReactiveX/RxSwift.git",
"state": {
"branch": null,
"revision": "b3e888b4972d9bc76495dd74d30a8c7fad4b9395",
"version": "5.0.1"
}
}
]
},
"version": 1
}

View File

@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<Bucket
uuid = "259A9C76-917D-4316-A814-D32A02BB36F4"
type = "1"
version = "2.0">
<Breakpoints>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.SwiftErrorBreakpoint">
<BreakpointContent
uuid = "C14D0996-5708-44D2-A6BA-4A4B50B522EE"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.ExceptionBreakpoint">
<BreakpointContent
uuid = "CF01B44D-372B-4C78-A197-7FDEC607CE0E"
shouldBeEnabled = "No"
ignoreCount = "0"
continueAfterRunningActions = "No"
scope = "1"
stopOnStyle = "0">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
uuid = "DFB5CF8A-D7CD-4328-BF19-E491CF2CE141"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "AutoCat/Models/Response.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "22"
endingLineNumber = "22"
landmarkName = "init(from:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
</Breakpoints>
</Bucket>

View File

@ -1,12 +1,5 @@
//
// AppDelegate.swift
// AutoCat
//
// Created by Selim Mustafaev on 20.02.2020.
// Copyright © 2020 Selim Mustafaev. All rights reserved.
//
import UIKit import UIKit
import SVProgressHUD
@UIApplicationMain @UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate { class AppDelegate: UIResponder, UIApplicationDelegate {
@ -14,7 +7,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
SVProgressHUD.setDefaultStyle(.dark)
SVProgressHUD.setDefaultMaskType(.black)
return true return true
} }

View File

@ -1,24 +1,440 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15705" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="pme-aR-UNJ">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies> <dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15706"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/> <capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="collection view cell content view" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies> </dependencies>
<scenes> <scenes>
<!--View Controller--> <!--Report Controller-->
<scene sceneID="tne-QT-ifu"> <scene sceneID="Lbe-ZV-eei">
<objects> <objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="target" sceneMemberID="viewController"> <viewController storyboardIdentifier="ReportController" id="i1k-Y4-pyh" customClass="ReportController" customModule="AutoCat" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC"> <view key="view" contentMode="scaleToFill" id="u3u-z2-y6J">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/> <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/> <subviews>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/> <collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="rG3-ze-Zre">
<rect key="frame" x="0.0" y="44" width="375" height="623"/>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<collectionViewFlowLayout key="collectionViewLayout" automaticEstimatedItemSize="YES" minimumLineSpacing="10" minimumInteritemSpacing="10" id="w9q-DU-Wac">
<size key="itemSize" width="303" height="85"/>
<size key="headerReferenceSize" width="0.0" height="0.0"/>
<size key="footerReferenceSize" width="0.0" height="0.0"/>
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
</collectionViewFlowLayout>
<cells>
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="VehicleHeaderCell" id="PxV-55-Ajy" customClass="VehicleHeaderCell" customModule="AutoCat" customModuleProvider="target">
<rect key="frame" x="36" y="0.0" width="303" height="85"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<collectionViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" id="xpE-cC-0kB">
<rect key="frame" x="0.0" y="0.0" width="303" height="85"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Y6d-8t-aA6">
<rect key="frame" x="8" y="8" width="64" height="69"/>
<constraints>
<constraint firstAttribute="width" constant="64" id="0bB-fg-k2V"/>
<constraint firstAttribute="height" constant="48" id="Tk0-8G-9hP"/>
</constraints>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Ysk-FW-p2W">
<rect key="frame" x="80" y="26" width="215" height="33.5"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleTitle1"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstItem="Y6d-8t-aA6" firstAttribute="top" secondItem="xpE-cC-0kB" secondAttribute="top" constant="8" id="64b-kd-Pif"/>
<constraint firstItem="Ysk-FW-p2W" firstAttribute="centerY" secondItem="xpE-cC-0kB" secondAttribute="centerY" id="QRj-dD-uNP"/>
<constraint firstAttribute="trailing" secondItem="Ysk-FW-p2W" secondAttribute="trailing" constant="8" id="VU5-Dw-XMx"/>
<constraint firstAttribute="bottom" secondItem="Y6d-8t-aA6" secondAttribute="bottom" constant="8" id="d18-fj-2Xq"/>
<constraint firstItem="Y6d-8t-aA6" firstAttribute="leading" secondItem="xpE-cC-0kB" secondAttribute="leading" constant="8" id="tIc-8G-05A"/>
<constraint firstItem="Ysk-FW-p2W" firstAttribute="leading" secondItem="Y6d-8t-aA6" secondAttribute="trailing" constant="8" id="xRv-Dz-bDZ"/>
</constraints>
</collectionViewCellContentView>
<color key="backgroundColor" systemColor="systemGroupedBackgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<size key="customSize" width="303" height="85"/>
<connections>
<outlet property="logo" destination="Y6d-8t-aA6" id="Bai-Bn-lEh"/>
<outlet property="name" destination="Ysk-FW-p2W" id="xx2-sw-1tL"/>
</connections>
</collectionViewCell>
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" reuseIdentifier="VehicleTextParamCell" id="3Qa-Fn-qe7" customClass="VehicleTextParamCell" customModule="AutoCat" customModuleProvider="target">
<rect key="frame" x="115" y="95" width="145" height="42.5"/>
<autoresizingMask key="autoresizingMask"/>
<collectionViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" id="fmb-JM-Fcr">
<rect key="frame" x="0.0" y="0.0" width="145" height="42.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="023-Q6-kPk">
<rect key="frame" x="16" y="8" width="52.5" height="26.5"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleTitle2"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ptE-4B-jxt">
<rect key="frame" x="76.5" y="8" width="52.5" height="26.5"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleTitle2"/>
<color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="WAm-et-t5P">
<rect key="frame" x="0.0" y="41.5" width="145" height="1"/>
<color key="backgroundColor" systemColor="separatorColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.28999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="1" id="Mpt-xA-af2"/>
</constraints>
</view>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="ptE-4B-jxt" secondAttribute="trailing" constant="16" id="4EF-1X-hrJ"/>
<constraint firstAttribute="bottom" secondItem="WAm-et-t5P" secondAttribute="bottom" id="91A-1k-B4C"/>
<constraint firstItem="ptE-4B-jxt" firstAttribute="leading" secondItem="023-Q6-kPk" secondAttribute="trailing" constant="8" id="BPP-fC-Q8I"/>
<constraint firstItem="023-Q6-kPk" firstAttribute="centerY" secondItem="ptE-4B-jxt" secondAttribute="centerY" id="Ce2-tJ-wbq"/>
<constraint firstItem="WAm-et-t5P" firstAttribute="leading" secondItem="fmb-JM-Fcr" secondAttribute="leading" id="Qr4-Eb-9YL"/>
<constraint firstAttribute="bottom" secondItem="023-Q6-kPk" secondAttribute="bottom" constant="8" id="asT-vZ-W1W"/>
<constraint firstItem="023-Q6-kPk" firstAttribute="top" secondItem="fmb-JM-Fcr" secondAttribute="top" constant="8" id="i2x-Tv-BGw"/>
<constraint firstItem="023-Q6-kPk" firstAttribute="leading" secondItem="fmb-JM-Fcr" secondAttribute="leading" constant="16" id="j9m-4c-c7c"/>
<constraint firstAttribute="trailing" secondItem="WAm-et-t5P" secondAttribute="trailing" id="zil-58-Wao"/>
</constraints>
</collectionViewCellContentView>
<color key="backgroundColor" cocoaTouchSystemColor="tableCellGroupedBackgroundColor"/>
<connections>
<outlet property="dividerHeightConstraint" destination="Mpt-xA-af2" id="bYb-0D-Lz0"/>
<outlet property="paramName" destination="023-Q6-kPk" id="pGj-6y-fbP"/>
<outlet property="paramValue" destination="ptE-4B-jxt" id="4YD-Va-YLb"/>
</connections>
</collectionViewCell>
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" reuseIdentifier="VehiclePhotoCell" id="X77-i3-DVY" customClass="VehiclePhotoCell" customModule="AutoCat" customModuleProvider="target">
<rect key="frame" x="36" y="147.5" width="303" height="264"/>
<autoresizingMask key="autoresizingMask"/>
<collectionViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" id="AMu-PZ-gGR">
<rect key="frame" x="0.0" y="0.0" width="303" height="264"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="wgf-C8-UOE">
<rect key="frame" x="0.0" y="0.0" width="303" height="198"/>
<constraints>
<constraint firstAttribute="width" secondItem="wgf-C8-UOE" secondAttribute="height" multiplier="101:66" id="OzD-Ts-mnv"/>
</constraints>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="1HU-6D-JSt">
<rect key="frame" x="8" y="206" width="287" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="l3q-fD-P3R">
<rect key="frame" x="8" y="235" width="287" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstItem="1HU-6D-JSt" firstAttribute="top" secondItem="wgf-C8-UOE" secondAttribute="bottom" constant="8" id="2nP-F6-Jr9"/>
<constraint firstAttribute="trailing" secondItem="1HU-6D-JSt" secondAttribute="trailing" constant="8" id="AI8-D3-c49"/>
<constraint firstItem="l3q-fD-P3R" firstAttribute="top" secondItem="1HU-6D-JSt" secondAttribute="bottom" constant="8" id="Gxd-mq-F5c"/>
<constraint firstAttribute="trailing" secondItem="wgf-C8-UOE" secondAttribute="trailing" id="Moc-ou-hry"/>
<constraint firstAttribute="trailing" secondItem="l3q-fD-P3R" secondAttribute="trailing" constant="8" id="QwX-uc-3NV"/>
<constraint firstItem="1HU-6D-JSt" firstAttribute="leading" secondItem="AMu-PZ-gGR" secondAttribute="leading" constant="8" id="SAN-qq-lXm"/>
<constraint firstAttribute="bottom" secondItem="l3q-fD-P3R" secondAttribute="bottom" constant="8" id="TcR-1f-apo"/>
<constraint firstItem="wgf-C8-UOE" firstAttribute="leading" secondItem="AMu-PZ-gGR" secondAttribute="leading" id="jVo-O5-SX5"/>
<constraint firstItem="wgf-C8-UOE" firstAttribute="top" secondItem="AMu-PZ-gGR" secondAttribute="top" id="k1d-ot-dij"/>
<constraint firstItem="l3q-fD-P3R" firstAttribute="leading" secondItem="AMu-PZ-gGR" secondAttribute="leading" constant="8" id="u0P-VY-lFV"/>
</constraints>
</collectionViewCellContentView>
<size key="customSize" width="303" height="264"/>
<connections>
<outlet property="date" destination="l3q-fD-P3R" id="rEm-YK-xrw"/>
<outlet property="model" destination="1HU-6D-JSt" id="SfI-p5-s2o"/>
<outlet property="photo" destination="wgf-C8-UOE" id="ztK-ib-ImI"/>
</connections>
</collectionViewCell>
</cells>
<connections>
<outlet property="dataSource" destination="i1k-Y4-pyh" id="vJN-oM-YaN"/>
<outlet property="delegate" destination="i1k-Y4-pyh" id="ou7-HH-r6H"/>
</connections>
</collectionView>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<constraints>
<constraint firstItem="rG3-ze-Zre" firstAttribute="trailing" secondItem="fbN-WR-iQY" secondAttribute="trailing" id="8JI-c0-3hf"/>
<constraint firstItem="rG3-ze-Zre" firstAttribute="bottom" secondItem="fbN-WR-iQY" secondAttribute="bottom" id="ZCY-XN-Awz"/>
<constraint firstItem="rG3-ze-Zre" firstAttribute="top" secondItem="fbN-WR-iQY" secondAttribute="top" id="nqG-ez-Kjm"/>
<constraint firstItem="rG3-ze-Zre" firstAttribute="leading" secondItem="fbN-WR-iQY" secondAttribute="leading" id="qo7-O7-zc7"/>
</constraints>
<viewLayoutGuide key="safeArea" id="fbN-WR-iQY"/>
</view>
<navigationItem key="navigationItem" id="goK-kc-WCv"/>
<connections>
<outlet property="collection" destination="rG3-ze-Zre" id="f8S-jh-WSw"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="gzk-86-k5g" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="844" y="948.57571214392806"/>
</scene>
<!--Search-->
<scene sceneID="3Md-yW-a0R">
<objects>
<viewController id="UPf-uT-oOr" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="IJP-gV-Ojc">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<viewLayoutGuide key="safeArea" id="6Uh-9i-MKR"/>
</view>
<tabBarItem key="tabBarItem" title="Search" image="magnifyingglass" catalog="system" id="gDG-z8-R0t"/>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="xsk-7S-rvc" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="3262" y="143"/>
</scene>
<!--Settings-->
<scene sceneID="G47-o0-Caa">
<objects>
<viewController id="4jU-Z3-PF2" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="NFd-we-MVH">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<viewLayoutGuide key="safeArea" id="Uix-8K-fxh"/>
</view>
<tabBarItem key="tabBarItem" title="Settings" image="gear" catalog="system" id="zEL-ph-E2f"/>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="trD-gZ-yAv" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="3262" y="893"/>
</scene>
<!--Check Controller-->
<scene sceneID="t7Z-yv-ZLH">
<objects>
<viewController id="twc-qR-t1G" customClass="CheckController" customModule="AutoCat" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="g5m-iL-O7A">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="16" translatesAutoresizingMaskIntoConstraints="NO" id="Peq-Zq-kNT">
<rect key="frame" x="62.5" y="68" width="250" height="104"/>
<subviews>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="A001AA 777" textAlignment="center" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="8FU-Gy-4MU">
<rect key="frame" x="0.0" y="0.0" width="250" height="49"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleTitle0"/>
<textInputTraits key="textInputTraits"/>
</textField>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Ync-fd-xQI">
<rect key="frame" x="0.0" y="65" width="250" height="39"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleTitle2"/>
<state key="normal" title="Check"/>
<connections>
<action selector="checkTapped:" destination="twc-qR-t1G" eventType="touchUpInside" id="WiK-lL-7q7"/>
</connections>
</button>
</subviews>
<constraints>
<constraint firstAttribute="width" constant="250" id="lqO-Yy-NyQ"/>
</constraints>
</stackView>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="JKr-UE-x8f">
<rect key="frame" x="0.0" y="196" width="375" height="422"/>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="VehicleCell" id="3ON-lr-UlV" customClass="VehicleCell" customModule="AutoCat" customModuleProvider="target">
<rect key="frame" x="0.0" y="28" width="375" height="70.5"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="3ON-lr-UlV" id="IGw-UK-ebp">
<rect key="frame" x="0.0" y="0.0" width="375" height="70.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="prz-7c-HiS">
<rect key="frame" x="8" y="8" width="359" height="54.5"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Kia (JF) Optima" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="h3N-1o-J20">
<rect key="frame" x="0.0" y="0.0" width="359" height="20.5"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleHeadline"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="A001AA 777" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="tnO-FL-oTE">
<rect key="frame" x="0.0" y="20.5" width="359" height="34"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleTitle1"/>
<color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="prz-7c-HiS" secondAttribute="trailing" constant="8" id="42F-cD-DAn"/>
<constraint firstItem="prz-7c-HiS" firstAttribute="top" secondItem="IGw-UK-ebp" secondAttribute="top" constant="8" id="W9V-oe-unX"/>
<constraint firstItem="prz-7c-HiS" firstAttribute="leading" secondItem="IGw-UK-ebp" secondAttribute="leading" constant="8" id="tvA-Ow-u6L"/>
<constraint firstAttribute="bottom" secondItem="prz-7c-HiS" secondAttribute="bottom" constant="8" id="v1W-gU-mvW"/>
</constraints>
</tableViewCellContentView>
<inset key="separatorInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
<connections>
<outlet property="name" destination="h3N-1o-J20" id="jcM-B4-bEJ"/>
<outlet property="number" destination="tnO-FL-oTE" id="klG-fF-iiQ"/>
</connections>
</tableViewCell>
</prototypes>
</tableView>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<constraints>
<constraint firstItem="JKr-UE-x8f" firstAttribute="trailing" secondItem="3Jk-FW-b3r" secondAttribute="trailing" id="Tc5-ri-5RD"/>
<constraint firstItem="Peq-Zq-kNT" firstAttribute="top" secondItem="3Jk-FW-b3r" secondAttribute="top" constant="24" id="Tft-8o-Cb1"/>
<constraint firstItem="JKr-UE-x8f" firstAttribute="bottom" secondItem="3Jk-FW-b3r" secondAttribute="bottom" id="Zwj-XD-UhD"/>
<constraint firstItem="Peq-Zq-kNT" firstAttribute="centerX" secondItem="g5m-iL-O7A" secondAttribute="centerX" id="fXl-Na-1gb"/>
<constraint firstItem="JKr-UE-x8f" firstAttribute="top" secondItem="Peq-Zq-kNT" secondAttribute="bottom" constant="24" id="mm9-rL-KQ1"/>
<constraint firstItem="JKr-UE-x8f" firstAttribute="leading" secondItem="3Jk-FW-b3r" secondAttribute="leading" id="vfN-fu-5pA"/>
</constraints>
<viewLayoutGuide key="safeArea" id="3Jk-FW-b3r"/>
</view>
<navigationItem key="navigationItem" id="IMO-Ew-zSY"/>
<connections>
<outlet property="check" destination="Ync-fd-xQI" id="oxC-p6-Mou"/>
<outlet property="history" destination="JKr-UE-x8f" id="GP9-Gz-WBm"/>
<outlet property="number" destination="8FU-Gy-4MU" id="cCY-vV-Mdy"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="h7Y-mR-2Ti" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="4200.8000000000002" y="-585.1574212893554"/>
</scene>
<!--Tab Bar Controller-->
<scene sceneID="YhQ-kn-py3">
<objects>
<tabBarController id="s9R-9a-TOT" sceneMemberID="viewController">
<tabBar key="tabBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="7gI-Jq-j4q">
<rect key="frame" x="0.0" y="0.0" width="414" height="49"/>
<autoresizingMask key="autoresizingMask"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</tabBar>
<connections>
<segue destination="TSb-ZG-qfD" kind="relationship" relationship="viewControllers" id="Bwf-98-gjF"/>
<segue destination="UPf-uT-oOr" kind="relationship" relationship="viewControllers" id="FGp-f6-fUh"/>
<segue destination="4jU-Z3-PF2" kind="relationship" relationship="viewControllers" id="aH2-IT-86l"/>
</connections>
</tabBarController>
<placeholder placeholderIdentifier="IBFirstResponder" id="AJs-8F-Qbu" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1729" y="143"/>
</scene>
<!--Auth Controller-->
<scene sceneID="wJp-Rv-eDj">
<objects>
<viewController storyboardIdentifier="AuthController" id="pme-aR-UNJ" customClass="AuthController" customModule="AutoCat" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="JT9-G7-mMt">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" horizontalCompressionResistancePriority="1000" axis="vertical" spacing="16" translatesAutoresizingMaskIntoConstraints="NO" id="TMc-av-b0b">
<rect key="frame" x="56.5" y="245.5" width="262.5" height="176"/>
<subviews>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Login" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="Uey-88-eZL">
<rect key="frame" x="0.0" y="0.0" width="262.5" height="34"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits"/>
</textField>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Password" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="G1p-Hz-8yn">
<rect key="frame" x="0.0" y="50" width="262.5" height="34"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" secureTextEntry="YES"/>
</textField>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ltG-B1-UBj">
<rect key="frame" x="0.0" y="100" width="262.5" height="30"/>
<state key="normal" title="Log in"/>
<connections>
<action selector="loginTapped:" destination="pme-aR-UNJ" eventType="touchUpInside" id="qTu-4S-cqF"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="hRD-Ha-MrP">
<rect key="frame" x="0.0" y="146" width="262.5" height="30"/>
<state key="normal" title="Sign up"/>
<connections>
<action selector="signupTapped:" destination="pme-aR-UNJ" eventType="touchUpInside" id="upt-yE-Xro"/>
</connections>
</button>
</subviews>
</stackView>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<constraints>
<constraint firstItem="TMc-av-b0b" firstAttribute="width" secondItem="JT9-G7-mMt" secondAttribute="width" multiplier="0.7" id="95T-so-Jv9"/>
<constraint firstItem="TMc-av-b0b" firstAttribute="centerY" secondItem="JT9-G7-mMt" secondAttribute="centerY" id="n5u-Ta-swG"/>
<constraint firstItem="TMc-av-b0b" firstAttribute="centerX" secondItem="JT9-G7-mMt" secondAttribute="centerX" id="yc6-lV-4EU"/>
</constraints>
<viewLayoutGuide key="safeArea" id="CSC-sQ-Tm5"/>
</view>
<connections>
<outlet property="login" destination="ltG-B1-UBj" id="Fc0-Cd-BKA"/>
<outlet property="password" destination="G1p-Hz-8yn" id="8VI-cA-YrJ"/>
<outlet property="signup" destination="hRD-Ha-MrP" id="VCG-25-bHL"/>
<outlet property="username" destination="Uey-88-eZL" id="EEe-CA-Pbm"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Yso-GW-Nd2" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-262" y="144"/>
</scene>
<!--Main Split Controller-->
<scene sceneID="10H-jh-3eN">
<objects>
<splitViewController storyboardIdentifier="MainSplitController" id="q8g-Bu-ZOb" customClass="MainSplitController" customModule="AutoCat" customModuleProvider="target" sceneMemberID="viewController">
<connections>
<segue destination="s9R-9a-TOT" kind="relationship" relationship="masterViewController" id="Qf1-ZB-fOc"/>
<segue destination="i1k-Y4-pyh" kind="relationship" relationship="detailViewController" id="6tT-Vk-xmm"/>
</connections>
</splitViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="zgS-sH-9QV" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="844" y="145"/>
</scene>
<!--Check-->
<scene sceneID="pUX-kf-oY1">
<objects>
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="TSb-ZG-qfD" sceneMemberID="viewController">
<tabBarItem key="tabBarItem" title="Check" image="eye" catalog="system" selectedImage="eye.fill" id="QJd-35-4OB"/>
<toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="AAc-4d-GNh">
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<nil name="viewControllers"/>
<connections>
<segue destination="twc-qR-t1G" kind="relationship" relationship="rootViewController" id="4oh-ic-Q3N"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="6BU-7B-5m2" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="3261.5999999999999" y="-585.1574212893554"/>
</scene>
<!--View Controller-->
<scene sceneID="ZJx-Sq-6bu">
<objects>
<viewController id="1Nj-Yj-3Sj" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="mvB-cD-Ow0">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
</view> </view>
</viewController> </viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/> <placeholder placeholderIdentifier="IBFirstResponder" id="xYU-vW-bpS" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects> </objects>
<point key="canvasLocation" x="844" y="1648"/>
</scene> </scene>
</scenes> </scenes>
<resources>
<image name="eye" catalog="system" width="64" height="40"/>
<image name="eye.fill" catalog="system" width="64" height="38"/>
<image name="gear" catalog="system" width="64" height="58"/>
<image name="magnifyingglass" catalog="system" width="64" height="56"/>
</resources>
</document> </document>

View File

@ -0,0 +1,12 @@
import UIKit
import MagazineLayout
class SectionHeader: MagazineLayoutCollectionReusableView {
@IBOutlet weak var title: UILabel!
@IBOutlet weak var dividerHeightConstraint: NSLayoutConstraint!
override func awakeFromNib() {
super.awakeFromNib()
self.dividerHeightConstraint.constant = 1/UIScreen.main.scale
}
}

View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="15705" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15706"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<collectionReusableView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" id="U6b-Vx-4bR" customClass="SectionHeader" customModule="AutoCat" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="320" height="50"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="FPf-35-HkN">
<rect key="frame" x="16" y="8" width="288" height="34"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleHeadline"/>
<color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="co2-Tz-MXm">
<rect key="frame" x="0.0" y="49" width="320" height="1"/>
<color key="backgroundColor" systemColor="separatorColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.28999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="1" id="6Y8-H1-th4"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" systemColor="systemGroupedBackgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="bottom" secondItem="co2-Tz-MXm" secondAttribute="bottom" id="1cv-aB-G49"/>
<constraint firstAttribute="trailing" secondItem="FPf-35-HkN" secondAttribute="trailing" constant="16" id="7fE-KT-Qbf"/>
<constraint firstItem="VXr-Tz-HHm" firstAttribute="trailing" secondItem="co2-Tz-MXm" secondAttribute="trailing" id="GTl-lK-7Be"/>
<constraint firstItem="co2-Tz-MXm" firstAttribute="leading" secondItem="VXr-Tz-HHm" secondAttribute="leading" id="Hzk-ur-lNg"/>
<constraint firstItem="FPf-35-HkN" firstAttribute="leading" secondItem="U6b-Vx-4bR" secondAttribute="leading" constant="16" id="MeA-dL-PeZ"/>
<constraint firstItem="FPf-35-HkN" firstAttribute="top" secondItem="U6b-Vx-4bR" secondAttribute="top" constant="8" id="P1f-gG-3TZ"/>
<constraint firstItem="VXr-Tz-HHm" firstAttribute="bottom" secondItem="FPf-35-HkN" secondAttribute="bottom" constant="8" id="han-2D-OPQ"/>
</constraints>
<viewLayoutGuide key="safeArea" id="VXr-Tz-HHm"/>
<connections>
<outlet property="dividerHeightConstraint" destination="6Y8-H1-th4" id="fQS-Xf-i5n"/>
<outlet property="title" destination="FPf-35-HkN" id="yr1-mY-pnu"/>
</connections>
<point key="canvasLocation" x="132" y="154"/>
</collectionReusableView>
</objects>
</document>

View File

@ -0,0 +1,18 @@
import UIKit
class VehicleCell: UITableViewCell {
@IBOutlet weak var name: UILabel!
@IBOutlet weak var number: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
func configure(with vehicle: Vehicle) {
self.name.text = vehicle.brand?.name?.original
self.number.text = vehicle.number
}
}

View File

@ -0,0 +1,20 @@
import UIKit
import MagazineLayout
import Kingfisher
class VehicleHeaderCell: MagazineLayoutCollectionViewCell {
@IBOutlet weak var logo: UIImageView!
@IBOutlet weak var name: UILabel!
override func prepareForReuse() {
self.logo.kf.cancelDownloadTask()
}
func configure(with vehicle: Vehicle) {
self.name.text = vehicle.brand?.name?.original
if let url = vehicle.brand?.logo {
self.logo.kf.setImage(with: URL(string: url))
}
}
}

View File

@ -0,0 +1,22 @@
import UIKit
import MagazineLayout
import Kingfisher
class VehiclePhotoCell: MagazineLayoutCollectionViewCell {
@IBOutlet weak var photo: UIImageView!
@IBOutlet weak var model: UILabel!
@IBOutlet weak var date: UILabel!
override func prepareForReuse() {
super.prepareForReuse()
self.photo.kf.cancelDownloadTask()
}
func configure(with photoModel: VehiclePhoto) {
if let url = URL(string: photoModel.url) {
self.photo.kf.setImage(with: url)
}
self.model.text = "\(photoModel.brand ?? "") \(photoModel.model ?? "")"
}
}

View File

@ -0,0 +1,18 @@
import UIKit
import MagazineLayout
class VehicleTextParamCell: MagazineLayoutCollectionViewCell {
@IBOutlet weak var paramName: UILabel!
@IBOutlet weak var paramValue: UILabel!
@IBOutlet weak var dividerHeightConstraint: NSLayoutConstraint!
override func awakeFromNib() {
super.awakeFromNib()
self.dividerHeightConstraint.constant = 1/UIScreen.main.scale
}
func configure(param: String, value: String) {
self.paramName.text = param
self.paramValue.text = value
}
}

View File

@ -0,0 +1,58 @@
import UIKit
import RxSwift
import RxCocoa
import SVProgressHUD
class AuthController: UIViewController {
@IBOutlet weak var username: UITextField!
@IBOutlet weak var password: UITextField!
@IBOutlet weak var login: UIButton!
@IBOutlet weak var signup: UIButton!
let bag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
let authValid = Observable.combineLatest(self.username.rx.text, self.password.rx.text) { name, pass -> Bool in
guard let name = name, let pass = pass else { return false }
return name.count >= 4 && pass.count >= 5
}
authValid.bind(to: self.login.rx.isEnabled).disposed(by: self.bag)
authValid.bind(to: self.signup.rx.isEnabled).disposed(by: self.bag)
}
@IBAction func loginTapped(_ sender: UIButton) {
guard let name = self.username.text, let pass = self.password.text else { return }
SVProgressHUD.show()
Api.login(username: name, password: pass)
.observeOn(MainScheduler.instance)
.subscribe(onNext: self.goToMainScreen(user:), onError: self.displayError(error:))
.disposed(by: self.bag)
}
@IBAction func signupTapped(_ sender: UIButton) {
guard let name = self.username.text, let pass = self.password.text else { return }
SVProgressHUD.show()
Api.signup(username: name, password: pass)
.observeOn(MainScheduler.instance)
.subscribe(onNext: self.goToMainScreen(user:), onError: self.displayError(error:))
.disposed(by: self.bag)
}
func goToMainScreen(user: User) {
SVProgressHUD.dismiss()
Settings.shared.user = user
let storyboard = UIStoryboard(name: "Main", bundle: nil)
self.view.window?.rootViewController = storyboard.instantiateViewController(identifier: "MainSplitController")
}
func displayError(error: Error) {
SVProgressHUD.showError(withStatus: error.localizedDescription)
print(error)
}
}

View File

@ -0,0 +1,91 @@
import UIKit
import InputMask
import RealmSwift
import RxSwift
import SVProgressHUD
class CheckController: UIViewController, MaskedTextFieldDelegateListener {
@IBOutlet weak var number: UITextField!
@IBOutlet weak var check: UIButton!
@IBOutlet weak var history: UITableView!
let bag = DisposeBag()
let maskFieldDelegate = MaskedTextFieldDelegate()
override func viewDidLoad() {
super.viewDidLoad()
self.maskFieldDelegate.primaryMaskFormat = "[A][000][AA] [009]"
self.maskFieldDelegate.listener = self
self.number.delegate = self.maskFieldDelegate
self.check.isEnabled = false
let ds = RxTableViewRealmDataSource<Vehicle>(cellIdentifier: "VehicleCell", cellType: VehicleCell.self) { cell, ip, vehicle in
cell.configure(with: vehicle)
}
ds.headerTitle = "History"
let realm = try! Realm()
Observable.changeset(from: realm.objects(Vehicle.self))
.bind(to: self.history.rx.realmChanges(ds))
.disposed(by: self.bag)
self.history.rx.realmModelSelected(Vehicle.self)
.subscribe(onNext: self.updateDetailController(with:))
.disposed(by: self.bag)
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden(true, animated: false)
}
@IBAction func checkTapped(_ sender: UIButton) {
guard let number = self.number.text else { return }
self.number.text = nil
SVProgressHUD.show()
Api.checkVehicle(by: number)
.observeOn(MainScheduler.instance)
.subscribe(onNext: onReceivedVehicle(_:), onError: { err in
SVProgressHUD.showError(withStatus: err.localizedDescription)
print(err.localizedDescription)
}).disposed(by: self.bag)
}
func textField(_ textField: UITextField, didFillMandatoryCharacters complete: Bool, didExtractValue value: String) {
self.check.isEnabled = complete
print(value)
}
func onReceivedVehicle(_ vehicle: Vehicle) {
if let realm = try? Realm() {
try? realm.write {
realm.add(vehicle)
}
}
self.updateDetailController(with: vehicle)
SVProgressHUD.dismiss()
}
func updateDetailController(with vehicle: Vehicle) {
if let splitViewController = self.view.window?.rootViewController as? UISplitViewController
{
var detail: ReportController?
if splitViewController.viewControllers.count == 2 {
detail = splitViewController.viewControllers.last as? ReportController
} else {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
detail = storyboard.instantiateViewController(identifier: "ReportController")
}
if let detail = detail {
detail.vehicle = vehicle
splitViewController.showDetailViewController(detail, sender: self)
//self.performSegue(withIdentifier: "OpenDetailSegue", sender: self)
}
}
}
}

View File

@ -0,0 +1,58 @@
import UIKit
class MainSplitController: UISplitViewController, UISplitViewControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
self.preferredDisplayMode = .allVisible
self.delegate = self
}
func splitViewController(_ splitViewController: UISplitViewController, showDetail vc: UIViewController, sender: Any?) -> Bool {
if self.isCollapsed {
let tabController = self.viewControllers.first as? UITabBarController
let selectedNavController = tabController?.selectedViewController
var vcToPush = vc
if let nav = vc as? UINavigationController {
vcToPush = nav.topViewController!
}
vcToPush.hidesBottomBarWhenPushed = true
selectedNavController?.show(vcToPush, sender: self)
return true
}
return false
}
func splitViewController(_ splitViewController: UISplitViewController, separateSecondaryFrom primaryViewController: UIViewController) -> UIViewController?
{
let tabController = splitViewController.viewControllers.first as? UITabBarController
let selectedNavController = tabController?.selectedViewController as? UINavigationController
if selectedNavController?.topViewController is ReportController {
return selectedNavController?.popViewController(animated: false)
}
return nil
}
func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController: UIViewController, onto primaryViewController: UIViewController) -> Bool
{
guard let detail = secondaryViewController as? ReportController else { return false }
if detail.vehicle == nil {
return false
}
if let tabController = primaryViewController as? UITabBarController {
let selectedNavController = tabController.selectedViewController as? UINavigationController
detail.hidesBottomBarWhenPushed = true
selectedNavController?.pushViewController(detail, animated: false)
return true
}
return false
}
}

View File

@ -0,0 +1,217 @@
import UIKit
import MagazineLayout
enum ReportSection: Int, CaseIterable, CustomStringConvertible {
case header = 0
case general = 1
case identifiers = 2
case photos = 3
var description: String {
switch self {
case .header: return "Header"
case .general: return "General"
case .identifiers: return "Identifiers"
case .photos: return "Photos"
}
}
}
enum ReportGeneralSection: Int, CaseIterable, CustomStringConvertible {
case year = 0
case category = 1
case wheelPosition = 2
case japanese = 3
var description: String {
switch self {
case .year: return "Year"
case .category: return "Category"
case .wheelPosition: return "Steering wheel position"
case .japanese: return "Japanese"
}
}
}
enum ReportIdSection: Int, CaseIterable, CustomStringConvertible {
case number = 0
case vin = 1
case sts = 2
case pts = 3
var description: String {
switch self {
case .number: return "Number"
case .vin: return "VIN"
case .pts: return "PTS"
case .sts: return "STS"
}
}
}
class ReportController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateMagazineLayout {
@IBOutlet weak var collection: UICollectionView!
private let fullWidth = MagazineLayoutItemSizeMode(widthMode: .fullWidth(respectsHorizontalInsets: true), heightMode: .dynamic)
var vehicle: Vehicle? {
didSet {
loadViewIfNeeded()
self.collection.reloadData()
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.collection.collectionViewLayout = MagazineLayout()
let nib = UINib(nibName: "SectionHeader", bundle: nil)
self.collection.register(nib, forSupplementaryViewOfKind: MagazineLayout.SupplementaryViewKind.sectionHeader, withReuseIdentifier: "SectionHeader")
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden(self.traitCollection.horizontalSizeClass != .compact, animated: false)
}
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
self.navigationController?.setNavigationBarHidden(self.traitCollection.horizontalSizeClass != .compact, animated: false)
}
// MARK: - UICollectionViewDataSource
func numberOfSections(in collectionView: UICollectionView) -> Int {
return ReportSection.allCases.count
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
guard let vehicle = self.vehicle else { return 0 }
guard let section = ReportSection(rawValue: section) else { return 0 }
switch section {
case .header: return 1
case .general: return ReportGeneralSection.allCases.count
case .identifiers: return ReportIdSection.allCases.count
case .photos: return vehicle.photos.count
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let section = ReportSection(rawValue: indexPath.section) else { return UICollectionViewCell() }
guard let vehicle = self.vehicle else { return UICollectionViewCell() }
switch section {
case .header:
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "VehicleHeaderCell", for: indexPath) as? VehicleHeaderCell
cell?.configure(with: vehicle)
return cell ?? UICollectionViewCell()
case .general:
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "VehicleTextParamCell", for: indexPath) as? VehicleTextParamCell
if let generalSection = ReportGeneralSection(rawValue: indexPath.item) {
switch generalSection {
case .year:
cell?.configure(param: generalSection.description, value: String(vehicle.year))
break
case .category:
cell?.configure(param: generalSection.description, value: vehicle.category ?? "<unknown>")
break
case .wheelPosition:
cell?.configure(param: generalSection.description, value: vehicle.isRightWheel ? "Right" : "Left")
break
case .japanese:
cell?.configure(param: generalSection.description, value: vehicle.isJapanese ? "Yes" : "No")
}
}
return cell ?? UICollectionViewCell()
case .identifiers:
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "VehicleTextParamCell", for: indexPath) as? VehicleTextParamCell
if let idSection = ReportIdSection(rawValue: indexPath.item) {
switch idSection {
case .number:
cell?.configure(param: idSection.description, value: vehicle.number)
break
case .vin:
cell?.configure(param: idSection.description, value: vehicle.vin1 ?? "<unknown>")
break
case .sts:
cell?.configure(param: idSection.description, value: vehicle.sts ?? "<unknown>")
break
case .pts:
cell?.configure(param: idSection.description, value: vehicle.pts ?? "<unknown>")
break
}
}
return cell ?? UICollectionViewCell()
case .photos:
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "VehiclePhotoCell", for: indexPath) as? VehiclePhotoCell
let photo = vehicle.photos[indexPath.item]
cell?.configure(with: photo)
return cell ?? UICollectionViewCell()
}
}
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView
{
guard let section = ReportSection(rawValue: indexPath.section) else { return UICollectionReusableView() }
if let sectionHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "SectionHeader", for: indexPath) as? SectionHeader {
sectionHeader.title.text = section.description
return sectionHeader
}
return UICollectionReusableView()
}
// MARK: - UICollectionViewDelegateMagazineLayout
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeModeForItemAt indexPath: IndexPath) -> MagazineLayoutItemSizeMode
{
guard let section = ReportSection(rawValue: indexPath.section) else { return self.fullWidth }
switch section {
case .header: return self.fullWidth
case .general: return self.fullWidth
case .identifiers: return self.fullWidth
case .photos: return .init(widthMode: .thirdWidth, heightMode: .dynamic)
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, visibilityModeForHeaderInSectionAtIndex index: Int) -> MagazineLayoutHeaderVisibilityMode
{
guard let section = ReportSection(rawValue: index) else { return .hidden }
switch section {
case .header: return .hidden
case .general: return .visible(heightMode: .dynamic)
case .identifiers: return .visible(heightMode: .dynamic)
case .photos: return .visible(heightMode: .dynamic)
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, visibilityModeForFooterInSectionAtIndex index: Int) -> MagazineLayoutFooterVisibilityMode
{
return .hidden
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, visibilityModeForBackgroundInSectionAtIndex index: Int) -> MagazineLayoutBackgroundVisibilityMode
{
return .hidden
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, horizontalSpacingForItemsInSectionAtIndex index: Int) -> CGFloat
{
return 16
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, verticalSpacingForElementsInSectionAtIndex index: Int) -> CGFloat
{
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetsForSectionAtIndex index: Int) -> UIEdgeInsets
{
return .zero
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetsForItemsInSectionAtIndex index: Int) -> UIEdgeInsets
{
return .zero
}
}

View File

@ -41,8 +41,6 @@
</dict> </dict>
<key>UILaunchStoryboardName</key> <key>UILaunchStoryboardName</key>
<string>LaunchScreen</string> <string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key> <key>UIRequiredDeviceCapabilities</key>
<array> <array>
<string>armv7</string> <string>armv7</string>

View File

@ -0,0 +1,30 @@
import Foundation
class Response<T>: Decodable where T: Decodable {
let success: Bool
let data: T?
let error: String?
enum CodingKeys: String, CodingKey {
case success
case data
case error
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
success = try container.decode(Bool.self, forKey: .success)
if success {
do {
data = try container.decode(T.self, forKey: .data)
} catch {
print(error)
data = nil
}
error = nil
} else {
error = try container.decode(String.self, forKey: .error)
data = nil
}
}
}

View File

@ -0,0 +1,24 @@
import Foundation
class Settings {
private static let defaults = UserDefaults.standard
public static let shared = Settings()
var user: User {
didSet {
if let json = try? JSONEncoder().encode(self.user) {
Settings.defaults.set(json, forKey: "user")
Settings.defaults.synchronize()
}
}
}
init() {
self.user = Settings.getUser()
}
private static func getUser() -> User {
guard let data = Settings.defaults.data(forKey: "user") else { return User() }
return (try? JSONDecoder().decode(User.self, from: data)) ?? User()
}
}

11
AutoCat/Models/User.swift Normal file
View File

@ -0,0 +1,11 @@
import Foundation
class User: Codable {
let login: String
let token: String
init() {
self.login = ""
self.token = ""
}
}

View File

@ -0,0 +1,51 @@
import Foundation
import RealmSwift
class VehicleName: Object, Decodable {
@objc dynamic var original: String?
@objc dynamic var normalized: String?
}
class VehicleBrand: Object, Decodable {
@objc dynamic var name: VehicleName?
@objc dynamic var logo: String?
}
class VehicleModel: Object, Decodable {
@objc dynamic var name: VehicleName?
}
class VehicleEngine: Object, Decodable {
@objc dynamic var number: String?
@objc dynamic var volume: Int = 0
@objc dynamic var powerHp: Float = 0
@objc dynamic var powerKw: Float = 0
@objc dynamic var fuelType: String?
}
class VehiclePhoto: Object, Decodable {
@objc dynamic var brand: String?
@objc dynamic var model: String?
@objc dynamic var date: Int64 = 0
@objc dynamic var url: String = ""
}
class Vehicle: Object, Decodable {
@objc dynamic var _id: String = ""
@objc dynamic var brand: VehicleBrand?
@objc dynamic var model: VehicleModel?
@objc dynamic var color: String?
@objc dynamic var year: Int = 0
@objc dynamic var category: String?
@objc dynamic var engine: VehicleEngine?
@objc dynamic var number: String = ""
@objc dynamic var vin1: String?
@objc dynamic var vin2: String?
@objc dynamic var sts: String?
@objc dynamic var pts: String?
@objc dynamic var isRightWheel: Bool = false
@objc dynamic var isJapanese: Bool = false
@objc dynamic var addedDate: Int64 = 0
@objc dynamic var addedBy: String = ""
let photos = List<VehiclePhoto>()
}

View File

@ -1,23 +1,25 @@
//
// SceneDelegate.swift
// AutoCat
//
// Created by Selim Mustafaev on 20.02.2020.
// Copyright © 2020 Selim Mustafaev. All rights reserved.
//
import UIKit import UIKit
class SceneDelegate: UIResponder, UIWindowSceneDelegate { class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow? var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene. // If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
guard let _ = (scene as? UIWindowScene) else { return } guard let windowScene = (scene as? UIWindowScene) else { return }
self.window = UIWindow(windowScene: windowScene)
let storyboard = UIStoryboard(name: "Main", bundle: nil)
if Settings.shared.user.token.isEmpty {
self.window?.rootViewController = storyboard.instantiateViewController(identifier: "AuthController")
} else {
self.window?.rootViewController = storyboard.instantiateViewController(identifier: "MainSplitController")
}
self.window?.makeKeyAndVisible()
} }
func sceneDidDisconnect(_ scene: UIScene) { func sceneDidDisconnect(_ scene: UIScene) {

View File

@ -0,0 +1,113 @@
//
// RxRealm extensions
//
// Copyright (c) 2016 RxSwiftCommunity. All rights reserved.
// Check the LICENSE file for details
//
import Foundation
import RealmSwift
import RxSwift
import RxCocoa
import RxRealm
#if os(iOS)
// MARK: - iOS / UIKit
import UIKit
extension Reactive where Base: UITableView {
public func realmChanges<E>(_ dataSource: RxTableViewRealmDataSource<E>)
-> RealmBindObserver<E, AnyRealmCollection<E>, RxTableViewRealmDataSource<E>> {
return RealmBindObserver(dataSource: dataSource) {ds, results, changes in
if ds.tableView == nil {
ds.tableView = self.base
}
ds.tableView?.dataSource = ds
ds.applyChanges(items: AnyRealmCollection<E>(results), changes: changes)
}
}
public func realmModelSelected<E>(_ modelType: E.Type) -> ControlEvent<E> where E: RealmSwift.Object {
let source: Observable<E> = self.itemSelected.flatMap { [weak view = self.base as UITableView] indexPath -> Observable<E> in
guard let view = view, let ds = view.dataSource as? RxTableViewRealmDataSource<E> else {
return Observable.empty()
}
return Observable.just(ds.model(at: indexPath))
}
return ControlEvent(events: source)
}
}
extension Reactive where Base: UICollectionView {
public func realmChanges<E>(_ dataSource: RxCollectionViewRealmDataSource<E>)
-> RealmBindObserver<E, AnyRealmCollection<E>, RxCollectionViewRealmDataSource<E>> {
return RealmBindObserver(dataSource: dataSource) {ds, results, changes in
if ds.collectionView == nil {
ds.collectionView = self.base
}
ds.collectionView?.dataSource = ds
ds.applyChanges(items: AnyRealmCollection<E>(results), changes: changes)
}
}
public func realmModelSelected<E>(_ modelType: E.Type) -> ControlEvent<E> where E: RealmSwift.Object {
let source: Observable<E> = self.itemSelected.flatMap { [weak view = self.base as UICollectionView] indexPath -> Observable<E> in
guard let view = view, let ds = view.dataSource as? RxCollectionViewRealmDataSource<E> else {
return Observable.empty()
}
return Observable.just(ds.model(at: indexPath))
}
return ControlEvent(events: source)
}
}
#elseif os(OSX)
// MARK: - macOS / Cocoa
import Cocoa
extension Reactive where Base: NSTableView {
public func realmChanges<E>(_ dataSource: RxTableViewRealmDataSource<E>)
-> RealmBindObserver<E, AnyRealmCollection<E>, RxTableViewRealmDataSource<E>> {
base.delegate = dataSource
base.dataSource = dataSource
return RealmBindObserver(dataSource: dataSource) {ds, results, changes in
if dataSource.tableView == nil {
dataSource.tableView = self.base
}
ds.applyChanges(items: AnyRealmCollection<E>(results), changes: changes)
}
}
}
extension Reactive where Base: NSCollectionView {
public func realmChanges<E>(_ dataSource: RxCollectionViewRealmDataSource<E>)
-> RealmBindObserver<E, AnyRealmCollection<E>, RxCollectionViewRealmDataSource<E>> {
return RealmBindObserver(dataSource: dataSource) {ds, results, changes in
if ds.collectionView == nil {
ds.collectionView = self.base
}
ds.collectionView?.dataSource = ds
ds.applyChanges(items: AnyRealmCollection<E>(results), changes: changes)
}
}
}
#endif

View File

@ -0,0 +1,41 @@
//
// RxRealm extensions
//
// Copyright (c) 2016 RxSwiftCommunity. All rights reserved.
// Check the LICENSE file for details
//
import Foundation
import RealmSwift
import RxSwift
import RxCocoa
import RxRealm
public class RealmBindObserver<O: Object, C: RealmCollection, DS>: ObserverType {
typealias BindingType = (DS, C, RealmChangeset?) -> Void
public typealias E = (C, RealmChangeset?)
let dataSource: DS
let binding: BindingType
init(dataSource: DS, binding: @escaping BindingType) {
self.dataSource = dataSource
self.binding = binding
}
public func on(_ event: Event<E>) {
switch event {
case .next(let element):
binding(dataSource, element.0, element.1)
case .error:
return
case .completed:
return
}
}
func asObserver() -> AnyObserver<E> {
return AnyObserver(eventHandler: on)
}
}

View File

@ -0,0 +1,210 @@
//
// RxRealm extensions
//
// Copyright (c) 2016 RxSwiftCommunity. All rights reserved.
// Check the LICENSE file for details
//
import Foundation
import RealmSwift
import RxSwift
import RxCocoa
import RxRealm
#if os(iOS)
// MARK: - iOS / UIKit
import UIKit
public typealias CollectionCellFactory<E: Object> = (RxCollectionViewRealmDataSource<E>, UICollectionView, IndexPath, E) -> UICollectionViewCell
public typealias CollectionCellConfig<E: Object, CellType: UICollectionViewCell> = (CellType, IndexPath, E) -> Void
open class RxCollectionViewRealmDataSource <E: Object>: NSObject, UICollectionViewDataSource {
private var items: AnyRealmCollection<E>?
// MARK: - Configuration
public var collectionView: UICollectionView?
public var animated = true
// MARK: - Init
public let cellIdentifier: String
public let cellFactory: CollectionCellFactory<E>
public init(cellIdentifier: String, cellFactory: @escaping CollectionCellFactory<E>) {
self.cellIdentifier = cellIdentifier
self.cellFactory = cellFactory
}
public init<CellType>(cellIdentifier: String, cellType: CellType.Type, cellConfig: @escaping CollectionCellConfig<E, CellType>) where CellType: UICollectionViewCell {
self.cellIdentifier = cellIdentifier
self.cellFactory = {ds, cv, ip, model in
let cell = cv.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: ip) as! CellType
cellConfig(cell, ip, model)
return cell
}
}
// MARK: - Data access
public func model(at indexPath: IndexPath) -> E {
return items![indexPath.row]
}
// MARK: - UICollectionViewDataSource protocol
public func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return items?.count ?? 0
}
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
return cellFactory(self, collectionView, indexPath, items![indexPath.row])
}
// MARK: - Applying changeset to the collection view
private let fromRow = {(row: Int) in return IndexPath(row: row, section: 0)}
func applyChanges(items: AnyRealmCollection<E>, changes: RealmChangeset?) {
if self.items == nil {
self.items = items
}
guard let collectionView = collectionView else {
fatalError("You have to bind a collection view to the data source.")
}
guard animated else {
collectionView.reloadData()
return
}
guard let changes = changes else {
collectionView.reloadData()
return
}
let lastItemCount = collectionView.numberOfItems(inSection: 0)
guard items.count == lastItemCount + changes.inserted.count - changes.deleted.count else {
collectionView.reloadData()
return
}
collectionView.performBatchUpdates({[unowned self] in
collectionView.deleteItems(at: changes.deleted.map(self.fromRow))
collectionView.reloadItems(at: changes.updated.map(self.fromRow))
collectionView.insertItems(at: changes.inserted.map(self.fromRow))
}, completion: nil)
}
}
#elseif os(OSX)
// MARK: - macOS / Cocoa
import Cocoa
public typealias CollectionItemFactory<E: Object> = (RxCollectionViewRealmDataSource<E>, NSCollectionView, IndexPath, E) -> NSCollectionViewItem
public typealias CollectionItemConfig<E: Object, ItemType: NSCollectionViewItem> = (ItemType, IndexPath, E) -> Void
open class RxCollectionViewRealmDataSource <E: Object>: NSObject, NSCollectionViewDataSource {
private var items: AnyRealmCollection<E>?
// MARK: - Configuration
public var collectionView: NSCollectionView?
public var animated = true
// MARK: - Init
public let itemIdentifier: String
public let itemFactory: CollectionItemFactory<E>
public weak var delegate: NSCollectionViewDelegate?
public weak var dataSource: NSCollectionViewDataSource?
public init(itemIdentifier: String, itemFactory: @escaping CollectionItemFactory<E>) {
self.itemIdentifier = itemIdentifier
self.itemFactory = itemFactory
}
public init<ItemType>(itemIdentifier: String, itemType: ItemType.Type, itemConfig: @escaping CollectionItemConfig<E, ItemType>) where ItemType: NSCollectionViewItem {
self.itemIdentifier = itemIdentifier
self.itemFactory = { ds, cv, ip, model in
let item = cv.makeItem(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: itemIdentifier), for: ip) as! ItemType
itemConfig(item, ip, model)
return item
}
}
// MARK: - NSCollectionViewDataSource protocol
public func numberOfSections(in collectionView: NSCollectionView) -> Int {
return 1
}
public func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
return items?.count ?? 0
}
@available(OSX 10.11, *)
public func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
return itemFactory(self, collectionView, indexPath, items![indexPath.item])
}
// MARK: - Proxy unimplemented data source and delegate methods
open override func responds(to aSelector: Selector!) -> Bool {
if RxCollectionViewRealmDataSource.instancesRespond(to: aSelector) {
return true
} else if let delegate = delegate {
return delegate.responds(to: aSelector)
} else if let dataSource = dataSource {
return dataSource.responds(to: aSelector)
} else {
return false
}
}
open override func forwardingTarget(for aSelector: Selector!) -> Any? {
return delegate ?? dataSource
}
// MARK: - Applying changeset to the collection view
private let fromRow = {(row: Int) in return IndexPath(item: row, section: 0)}
func applyChanges(items: AnyRealmCollection<E>, changes: RealmChangeset?) {
if self.items == nil {
self.items = items
}
guard let collectionView = collectionView else {
fatalError("You have to bind a collection view to the data source.")
}
guard animated else {
collectionView.reloadData()
return
}
guard let changes = changes else {
collectionView.reloadData()
return
}
let lastItemCount = collectionView.numberOfItems(inSection: 0)
guard items.count == lastItemCount + changes.inserted.count - changes.deleted.count else {
collectionView.reloadData()
return
}
collectionView.performBatchUpdates({[unowned self] in
//TODO: this should be animated, but doesn't seem to be?
collectionView.animator().deleteItems(at: Set(changes.deleted.map(self.fromRow)))
collectionView.animator().reloadItems(at: Set(changes.updated.map(self.fromRow)))
collectionView.animator().insertItems(at: Set(changes.inserted.map(self.fromRow)))
}, completionHandler: nil)
}
}
#endif

View File

@ -0,0 +1,223 @@
//
// RxRealm extensions
//
// Copyright (c) 2016 RxSwiftCommunity. All rights reserved.
// Check the LICENSE file for details
//
import Foundation
import RealmSwift
import RxSwift
import RxCocoa
import RxRealm
#if os(iOS)
// MARK: - iOS / UIKit
import UIKit
public typealias TableCellFactory<E: Object> = (RxTableViewRealmDataSource<E>, UITableView, IndexPath, E) -> UITableViewCell
public typealias TableCellConfig<E: Object, CellType: UITableViewCell> = (CellType, IndexPath, E) -> Void
open class RxTableViewRealmDataSource<E: Object>: NSObject, UITableViewDataSource {
private var items: AnyRealmCollection<E>?
// MARK: - Configuration
public var tableView: UITableView?
public var animated = true
public var rowAnimations = (
insert: UITableView.RowAnimation.automatic,
update: UITableView.RowAnimation.automatic,
delete: UITableView.RowAnimation.automatic)
public var headerTitle: String?
public var footerTitle: String?
// MARK: - Init
public let cellIdentifier: String
public let cellFactory: TableCellFactory<E>
public init(cellIdentifier: String, cellFactory: @escaping TableCellFactory<E>) {
self.cellIdentifier = cellIdentifier
self.cellFactory = cellFactory
}
public init<CellType>(cellIdentifier: String, cellType: CellType.Type, cellConfig: @escaping TableCellConfig<E, CellType>) where CellType: UITableViewCell {
self.cellIdentifier = cellIdentifier
self.cellFactory = {ds, tv, ip, model in
let cell = tv.dequeueReusableCell(withIdentifier: cellIdentifier, for: ip) as! CellType
cellConfig(cell, ip, model)
return cell
}
}
// MARK: - Data access
public func model(at indexPath: IndexPath) -> E {
return items![indexPath.row]
}
// MARK: - UITableViewDataSource protocol
public func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items?.count ?? 0
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
return cellFactory(self, tableView, indexPath, items![indexPath.row])
}
public func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return headerTitle
}
public func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
return footerTitle
}
// MARK: - Applying changeset to the table view
private let fromRow = {(row: Int) in return IndexPath(row: row, section: 0)}
func applyChanges(items: AnyRealmCollection<E>, changes: RealmChangeset?) {
if self.items == nil {
self.items = items
}
guard let tableView = tableView else {
fatalError("You have to bind a table view to the data source.")
}
guard animated else {
tableView.reloadData()
return
}
guard let changes = changes else {
tableView.reloadData()
return
}
let lastItemCount = tableView.numberOfRows(inSection: 0)
guard items.count == lastItemCount + changes.inserted.count - changes.deleted.count else {
tableView.reloadData()
return
}
tableView.beginUpdates()
tableView.deleteRows(at: changes.deleted.map(fromRow), with: rowAnimations.delete)
tableView.insertRows(at: changes.inserted.map(fromRow), with: rowAnimations.insert)
tableView.reloadRows(at: changes.updated.map(fromRow), with: rowAnimations.update)
tableView.endUpdates()
}
}
#elseif os(OSX)
// MARK: - macOS / Cocoa
import Cocoa
public typealias TableCellFactory<E: Object> = (RxTableViewRealmDataSource<E>, NSTableView, Int, E) -> NSTableCellView
public typealias TableCellConfig<E: Object, CellType: NSTableCellView> = (CellType, Int, E) -> Void
open class RxTableViewRealmDataSource<E: Object>: NSObject, NSTableViewDataSource, NSTableViewDelegate {
private var items: AnyRealmCollection<E>?
// MARK: - Configuration
public var tableView: NSTableView?
public var animated = true
public var rowAnimations = (
insert: NSTableView.AnimationOptions.effectFade,
update: NSTableView.AnimationOptions.effectFade,
delete: NSTableView.AnimationOptions.effectFade)
public weak var delegate: NSTableViewDelegate?
public weak var dataSource: NSTableViewDataSource?
// MARK: - Init
public let cellIdentifier: String
public let cellFactory: TableCellFactory<E>
public init(cellIdentifier: String, cellFactory: @escaping TableCellFactory<E>) {
self.cellIdentifier = cellIdentifier
self.cellFactory = cellFactory
}
public init<CellType>(cellIdentifier: String, cellType: CellType.Type, cellConfig: @escaping TableCellConfig<E, CellType>) where CellType: NSTableCellView {
self.cellIdentifier = cellIdentifier
self.cellFactory = { ds, tv, row, model in
let cell = tv.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: cellIdentifier), owner: tv) as! CellType
cellConfig(cell, row, model)
return cell
}
}
// MARK: - UITableViewDataSource protocol
public func numberOfRows(in tableView: NSTableView) -> Int {
return items?.count ?? 0
}
public func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
return cellFactory(self, tableView, row, items![row])
}
// MARK: - Proxy unimplemented data source and delegate methods
open override func responds(to aSelector: Selector!) -> Bool {
if RxTableViewRealmDataSource.instancesRespond(to: aSelector) {
return true
} else if let delegate = delegate {
return delegate.responds(to: aSelector)
} else if let dataSource = dataSource {
return dataSource.responds(to: aSelector)
} else {
return false
}
}
open override func forwardingTarget(for aSelector: Selector!) -> Any? {
return delegate ?? dataSource
}
// MARK: - Applying changeset to the table view
private let fromRow = {(row: Int) in return IndexPath(item: row, section: 0)}
func applyChanges(items: AnyRealmCollection<E>, changes: RealmChangeset?) {
if self.items == nil {
self.items = items
}
guard let tableView = tableView else {
fatalError("You have to bind a table view to the data source.")
}
guard animated else {
tableView.reloadData()
return
}
guard let changes = changes else {
tableView.reloadData()
return
}
let lastItemCount = tableView.numberOfRows
guard items.count == lastItemCount + changes.inserted.count - changes.deleted.count else {
tableView.reloadData()
return
}
tableView.beginUpdates()
tableView.removeRows(at: IndexSet(changes.deleted), withAnimation: rowAnimations.delete)
tableView.insertRows(at: IndexSet(changes.inserted), withAnimation: rowAnimations.insert)
tableView.reloadData(forRowIndexes: IndexSet(changes.updated), columnIndexes: IndexSet([0]))
tableView.endUpdates()
}
}
#endif

69
AutoCat/Utils/Api.swift Normal file
View File

@ -0,0 +1,69 @@
import Foundation
import RxSwift
class Api {
private static let baseUrl = "https://vps.aliencat.pro:8443/"
private static func genError(_ msg: String, suggestion: String, code: Int = 0) -> Error {
return NSError(domain: "", code: code, userInfo: [NSLocalizedDescriptionKey: msg, NSLocalizedRecoverySuggestionErrorKey: suggestion])
}
private static func createRequest(api: String, method: String, body: [String: Any]? = nil) -> URLRequest? {
guard let url = URL(string: baseUrl + api) else { return nil }
var request = URLRequest(url: url)
request.httpMethod = method
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
request.addValue("Bearer " + Settings.shared.user.token, forHTTPHeaderField: "Authorization")
if let body = body {
request.httpBody = try? JSONSerialization.data(withJSONObject: body, options: .prettyPrinted)
}
return request
}
private static func makeRequest<T>(api: String, method: String, body: [String: Any]? = nil) -> Observable<T> where T: Decodable {
guard let request = self.createRequest(api: api, method: method, body: body) else {
return Observable.error(self.genError("Error creating request", suggestion: ""))
}
return URLSession.shared.rx.data(request: request).map { data in
// let str = String(data: data, encoding: .utf8)
// print("================================")
// print(str)
// print("================================")
let resp = try JSONDecoder().decode(Response<T>.self, from: data)
if resp.success {
return resp.data!
} else {
throw self.genError(resp.error!, suggestion: "")
}
}
}
public static func login(username: String, password: String) -> Observable<User> {
let body = [
"login": username,
"password": password
]
return self.makeRequest(api: "user/login", method: "POST", body: body)
}
public static func signup(username: String, password: String) -> Observable<User> {
let body = [
"login": username,
"password": password
]
return self.makeRequest(api: "user/signup", method: "POST", body: body)
}
public static func getVehicles() -> Observable<[Vehicle]> {
return self.makeRequest(api: "vehicles", method: "GET")
}
public static func checkVehicle(by number: String) -> Observable<Vehicle> {
return self.makeRequest(api: "vehicles/check", method: "POST", body: ["number": number])
}
}

View File

@ -1,20 +0,0 @@
//
// ViewController.swift
// AutoCat
//
// Created by Selim Mustafaev on 20.02.2020.
// Copyright © 2020 Selim Mustafaev. All rights reserved.
//
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}

1
Cartfile Normal file
View File

@ -0,0 +1 @@
github "selim-mustafaev/SVProgressHUD" "ios13-support"

1
Cartfile.resolved Normal file
View File

@ -0,0 +1 @@
github "selim-mustafaev/SVProgressHUD" "17b1eacb2800ffa91eb5fb12e1a5983dba29f9dc"

1
input.xcfilelist Normal file
View File

@ -0,0 +1 @@
$(SRCROOT)/Carthage/Build/iOS/SVProgressHUD.framework

1
output.xcfilelist Normal file
View File

@ -0,0 +1 @@
$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/SVProgressHUD.framework