Initial commit
This commit is contained in:
parent
4b25e202f2
commit
64cb79360f
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
Carthage/
|
||||
@ -3,27 +3,76 @@
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 50;
|
||||
objectVersion = 52;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
7A11470123FDE7E500B424AF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11470023FDE7E500B424AF /* AppDelegate.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 */; };
|
||||
7A11470A23FDE7E600B424AF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7A11470923FDE7E600B424AF /* Assets.xcassets */; };
|
||||
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 */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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 */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@ -31,6 +80,18 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
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;
|
||||
};
|
||||
@ -42,6 +103,7 @@
|
||||
children = (
|
||||
7A1146FF23FDE7E500B424AF /* AutoCat */,
|
||||
7A1146FE23FDE7E500B424AF /* Products */,
|
||||
7A11474C23FFEE8700B424AF /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
@ -56,9 +118,13 @@
|
||||
7A1146FF23FDE7E500B424AF /* AutoCat */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7A530B7C24017FBE00CBFE6E /* Cells */,
|
||||
7A11474523FF2A9000B424AF /* Models */,
|
||||
7A11474223FF06B600B424AF /* Utils */,
|
||||
7A11472C23FECA3E00B424AF /* ThirdParty */,
|
||||
7A11471423FDEAF800B424AF /* Controllers */,
|
||||
7A11470023FDE7E500B424AF /* AppDelegate.swift */,
|
||||
7A11470223FDE7E500B424AF /* SceneDelegate.swift */,
|
||||
7A11470423FDE7E500B424AF /* ViewController.swift */,
|
||||
7A11470623FDE7E500B424AF /* Main.storyboard */,
|
||||
7A11470923FDE7E600B424AF /* Assets.xcassets */,
|
||||
7A11470B23FDE7E600B424AF /* LaunchScreen.storyboard */,
|
||||
@ -67,6 +133,76 @@
|
||||
path = AutoCat;
|
||||
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 */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
@ -77,12 +213,26 @@
|
||||
7A1146F923FDE7E500B424AF /* Sources */,
|
||||
7A1146FA23FDE7E500B424AF /* Frameworks */,
|
||||
7A1146FB23FDE7E500B424AF /* Resources */,
|
||||
7A11475123FFF02E00B424AF /* ShellScript */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
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;
|
||||
productReference = 7A1146FD23FDE7E500B424AF /* AutoCat.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
@ -111,6 +261,15 @@
|
||||
Base,
|
||||
);
|
||||
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 */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
@ -125,6 +284,7 @@
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
7A7547DE2403180A004E8406 /* SectionHeader.xib in Resources */,
|
||||
7A11470D23FDE7E600B424AF /* LaunchScreen.storyboard in Resources */,
|
||||
7A11470A23FDE7E600B424AF /* Assets.xcassets in Resources */,
|
||||
7A11470823FDE7E500B424AF /* Main.storyboard in Resources */,
|
||||
@ -133,14 +293,53 @@
|
||||
};
|
||||
/* 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 */
|
||||
7A1146F923FDE7E500B424AF /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
7A11470523FDE7E500B424AF /* ViewController.swift in Sources */,
|
||||
7A530B802401803A00CBFE6E /* Vehicle.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 */,
|
||||
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;
|
||||
};
|
||||
@ -286,12 +485,17 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = 46DTTB8X4S;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Carthage/Build/iOS",
|
||||
);
|
||||
INFOPLIST_FILE = AutoCat/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCat.AutoCat;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCat;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
@ -304,12 +508,17 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = 46DTTB8X4S;
|
||||
FRAMEWORK_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/Carthage/Build/iOS",
|
||||
);
|
||||
INFOPLIST_FILE = AutoCat/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCat.AutoCat;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = pro.aliencat.AutoCat;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
@ -338,6 +547,123 @@
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* 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 */;
|
||||
}
|
||||
|
||||
@ -2,6 +2,6 @@
|
||||
<Workspace
|
||||
version = "1.0">
|
||||
<FileRef
|
||||
location = "self:AutoCat.xcodeproj">
|
||||
location = "self:">
|
||||
</FileRef>
|
||||
</Workspace>
|
||||
|
||||
@ -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
|
||||
}
|
||||
@ -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>
|
||||
@ -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 SVProgressHUD
|
||||
|
||||
@UIApplicationMain
|
||||
class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
@ -14,7 +7,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
|
||||
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
|
||||
@ -1,24 +1,440 @@
|
||||
<?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>
|
||||
<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="collection view cell content view" minToolsVersion="11.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<scenes>
|
||||
<!--View Controller-->
|
||||
<scene sceneID="tne-QT-ifu">
|
||||
<!--Report Controller-->
|
||||
<scene sceneID="Lbe-ZV-eei">
|
||||
<objects>
|
||||
<viewController id="BYZ-38-t0r" customClass="ViewController" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
|
||||
<viewController storyboardIdentifier="ReportController" id="i1k-Y4-pyh" customClass="ReportController" customModule="AutoCat" customModuleProvider="target" sceneMemberID="viewController">
|
||||
<view key="view" contentMode="scaleToFill" id="u3u-z2-y6J">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
|
||||
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
|
||||
<subviews>
|
||||
<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>
|
||||
</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>
|
||||
<point key="canvasLocation" x="844" y="1648"/>
|
||||
</scene>
|
||||
</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>
|
||||
|
||||
12
AutoCat/Cells/SectionHeader.swift
Normal file
12
AutoCat/Cells/SectionHeader.swift
Normal 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
|
||||
}
|
||||
}
|
||||
48
AutoCat/Cells/SectionHeader.xib
Normal file
48
AutoCat/Cells/SectionHeader.xib
Normal 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>
|
||||
18
AutoCat/Cells/VehicleCell.swift
Normal file
18
AutoCat/Cells/VehicleCell.swift
Normal 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
|
||||
}
|
||||
|
||||
}
|
||||
20
AutoCat/Cells/VehicleHeaderCell.swift
Normal file
20
AutoCat/Cells/VehicleHeaderCell.swift
Normal 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))
|
||||
}
|
||||
}
|
||||
}
|
||||
22
AutoCat/Cells/VehiclePhotoCell.swift
Normal file
22
AutoCat/Cells/VehiclePhotoCell.swift
Normal 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 ?? "")"
|
||||
}
|
||||
}
|
||||
18
AutoCat/Cells/VehicleTextParamCell.swift
Normal file
18
AutoCat/Cells/VehicleTextParamCell.swift
Normal 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
|
||||
}
|
||||
}
|
||||
58
AutoCat/Controllers/AuthController.swift
Normal file
58
AutoCat/Controllers/AuthController.swift
Normal 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)
|
||||
}
|
||||
}
|
||||
91
AutoCat/Controllers/CheckController.swift
Normal file
91
AutoCat/Controllers/CheckController.swift
Normal 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
58
AutoCat/Controllers/MainSplitController.swift
Normal file
58
AutoCat/Controllers/MainSplitController.swift
Normal 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
|
||||
}
|
||||
}
|
||||
217
AutoCat/Controllers/ReportController.swift
Normal file
217
AutoCat/Controllers/ReportController.swift
Normal 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
|
||||
}
|
||||
}
|
||||
@ -41,8 +41,6 @@
|
||||
</dict>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIRequiredDeviceCapabilities</key>
|
||||
<array>
|
||||
<string>armv7</string>
|
||||
|
||||
30
AutoCat/Models/Response.swift
Normal file
30
AutoCat/Models/Response.swift
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
24
AutoCat/Models/Settings.swift
Normal file
24
AutoCat/Models/Settings.swift
Normal 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
11
AutoCat/Models/User.swift
Normal file
@ -0,0 +1,11 @@
|
||||
import Foundation
|
||||
|
||||
class User: Codable {
|
||||
let login: String
|
||||
let token: String
|
||||
|
||||
init() {
|
||||
self.login = ""
|
||||
self.token = ""
|
||||
}
|
||||
}
|
||||
51
AutoCat/Models/Vehicle.swift
Normal file
51
AutoCat/Models/Vehicle.swift
Normal 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>()
|
||||
}
|
||||
@ -1,23 +1,25 @@
|
||||
//
|
||||
// SceneDelegate.swift
|
||||
// AutoCat
|
||||
//
|
||||
// Created by Selim Mustafaev on 20.02.2020.
|
||||
// Copyright © 2020 Selim Mustafaev. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||
|
||||
var window: UIWindow?
|
||||
|
||||
|
||||
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
|
||||
// Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`.
|
||||
// If using a storyboard, the `window` property will automatically be initialized and attached to the scene.
|
||||
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
|
||||
guard let _ = (scene 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) {
|
||||
|
||||
113
AutoCat/ThirdParty/RxRealmDataSources/Reactive+RxRealmDataSources.swift
vendored
Normal file
113
AutoCat/ThirdParty/RxRealmDataSources/Reactive+RxRealmDataSources.swift
vendored
Normal 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
|
||||
41
AutoCat/ThirdParty/RxRealmDataSources/RealmBindObserver.swift
vendored
Normal file
41
AutoCat/ThirdParty/RxRealmDataSources/RealmBindObserver.swift
vendored
Normal 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)
|
||||
}
|
||||
}
|
||||
210
AutoCat/ThirdParty/RxRealmDataSources/RxCollectionViewRealmDataSource.swift
vendored
Normal file
210
AutoCat/ThirdParty/RxRealmDataSources/RxCollectionViewRealmDataSource.swift
vendored
Normal 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
|
||||
223
AutoCat/ThirdParty/RxRealmDataSources/RxTableViewRealmDataSource.swift
vendored
Normal file
223
AutoCat/ThirdParty/RxRealmDataSources/RxTableViewRealmDataSource.swift
vendored
Normal 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
69
AutoCat/Utils/Api.swift
Normal 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])
|
||||
}
|
||||
}
|
||||
@ -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
1
Cartfile
Normal file
@ -0,0 +1 @@
|
||||
github "selim-mustafaev/SVProgressHUD" "ios13-support"
|
||||
1
Cartfile.resolved
Normal file
1
Cartfile.resolved
Normal file
@ -0,0 +1 @@
|
||||
github "selim-mustafaev/SVProgressHUD" "17b1eacb2800ffa91eb5fb12e1a5983dba29f9dc"
|
||||
1
input.xcfilelist
Normal file
1
input.xcfilelist
Normal file
@ -0,0 +1 @@
|
||||
$(SRCROOT)/Carthage/Build/iOS/SVProgressHUD.framework
|
||||
1
output.xcfilelist
Normal file
1
output.xcfilelist
Normal file
@ -0,0 +1 @@
|
||||
$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/SVProgressHUD.framework
|
||||
Loading…
Reference in New Issue
Block a user