Added app icon (temporary)

added viewer controller for vehicle photos
added logout functionality
This commit is contained in:
Selim Mustafaev 2020-02-25 00:11:46 +03:00
parent 64cb79360f
commit 4df15702b3
18 changed files with 278 additions and 42 deletions

View File

@ -39,6 +39,8 @@
7A7547DD2403180A004E8406 /* SectionHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A7547DB2403180A004E8406 /* SectionHeader.swift */; }; 7A7547DD2403180A004E8406 /* SectionHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A7547DB2403180A004E8406 /* SectionHeader.swift */; };
7A7547DE2403180A004E8406 /* SectionHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7A7547DC2403180A004E8406 /* SectionHeader.xib */; }; 7A7547DE2403180A004E8406 /* SectionHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7A7547DC2403180A004E8406 /* SectionHeader.xib */; };
7A7547E024032CB6004E8406 /* VehiclePhotoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A7547DF24032CB6004E8406 /* VehiclePhotoCell.swift */; }; 7A7547E024032CB6004E8406 /* VehiclePhotoCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A7547DF24032CB6004E8406 /* VehiclePhotoCell.swift */; };
7A92D0AC240425B200EF3B77 /* ATGMediaBrowser.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A92D0AB240425B100EF3B77 /* ATGMediaBrowser.framework */; };
7AEFE728240455E200910EB7 /* SettingsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AEFE727240455E200910EB7 /* SettingsController.swift */; };
7AF58D2F24029C5200CE01A0 /* MagazineLayout in Frameworks */ = {isa = PBXBuildFile; productRef = 7AF58D2E24029C5200CE01A0 /* MagazineLayout */; }; 7AF58D2F24029C5200CE01A0 /* MagazineLayout in Frameworks */ = {isa = PBXBuildFile; productRef = 7AF58D2E24029C5200CE01A0 /* MagazineLayout */; };
7AF58D3124029E1000CE01A0 /* VehicleHeaderCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF58D3024029E1000CE01A0 /* VehicleHeaderCell.swift */; }; 7AF58D3124029E1000CE01A0 /* VehicleHeaderCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF58D3024029E1000CE01A0 /* VehicleHeaderCell.swift */; };
7AF58D342402A91C00CE01A0 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 7AF58D332402A91C00CE01A0 /* Kingfisher */; }; 7AF58D342402A91C00CE01A0 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 7AF58D332402A91C00CE01A0 /* Kingfisher */; };
@ -71,6 +73,8 @@
7A7547DB2403180A004E8406 /* SectionHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SectionHeader.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>"; }; 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>"; }; 7A7547DF24032CB6004E8406 /* VehiclePhotoCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehiclePhotoCell.swift; sourceTree = "<group>"; };
7A92D0AB240425B100EF3B77 /* ATGMediaBrowser.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ATGMediaBrowser.framework; path = Carthage/Build/iOS/ATGMediaBrowser.framework; sourceTree = "<group>"; };
7AEFE727240455E200910EB7 /* SettingsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsController.swift; sourceTree = "<group>"; };
7AF58D3024029E1000CE01A0 /* VehicleHeaderCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehicleHeaderCell.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>"; }; 7AF58D57240309CA00CE01A0 /* VehicleTextParamCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VehicleTextParamCell.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
@ -89,6 +93,7 @@
7A11472B23FEA24D00B424AF /* Action in Frameworks */, 7A11472B23FEA24D00B424AF /* Action in Frameworks */,
7A11471F23FEA18700B424AF /* RxRelay in Frameworks */, 7A11471F23FEA18700B424AF /* RxRelay in Frameworks */,
7AF58D2F24029C5200CE01A0 /* MagazineLayout in Frameworks */, 7AF58D2F24029C5200CE01A0 /* MagazineLayout in Frameworks */,
7A92D0AC240425B200EF3B77 /* ATGMediaBrowser.framework in Frameworks */,
7A530B78240010D900CBFE6E /* InputMask in Frameworks */, 7A530B78240010D900CBFE6E /* InputMask in Frameworks */,
7A11471D23FEA18700B424AF /* RxSwift in Frameworks */, 7A11471D23FEA18700B424AF /* RxSwift in Frameworks */,
7A11472623FEA1F400B424AF /* Realm in Frameworks */, 7A11472623FEA1F400B424AF /* Realm in Frameworks */,
@ -140,6 +145,7 @@
7A11471723FDEBFA00B424AF /* ReportController.swift */, 7A11471723FDEBFA00B424AF /* ReportController.swift */,
7A11471923FE839000B424AF /* AuthController.swift */, 7A11471923FE839000B424AF /* AuthController.swift */,
7A530B7924001D3300CBFE6E /* CheckController.swift */, 7A530B7924001D3300CBFE6E /* CheckController.swift */,
7AEFE727240455E200910EB7 /* SettingsController.swift */,
); );
path = Controllers; path = Controllers;
sourceTree = "<group>"; sourceTree = "<group>";
@ -174,6 +180,7 @@
7A11474C23FFEE8700B424AF /* Frameworks */ = { 7A11474C23FFEE8700B424AF /* Frameworks */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
7A92D0AB240425B100EF3B77 /* ATGMediaBrowser.framework */,
7A11474D23FFEE8800B424AF /* SVProgressHUD.framework */, 7A11474D23FFEE8800B424AF /* SVProgressHUD.framework */,
); );
name = Frameworks; name = Frameworks;
@ -323,6 +330,7 @@
7A530B802401803A00CBFE6E /* Vehicle.swift in Sources */, 7A530B802401803A00CBFE6E /* Vehicle.swift in Sources */,
7A11470123FDE7E500B424AF /* AppDelegate.swift in Sources */, 7A11470123FDE7E500B424AF /* AppDelegate.swift in Sources */,
7A530B86240180CC00CBFE6E /* RealmBindObserver.swift in Sources */, 7A530B86240180CC00CBFE6E /* RealmBindObserver.swift in Sources */,
7AEFE728240455E200910EB7 /* SettingsController.swift in Sources */,
7A11474923FF2B2D00B424AF /* Response.swift in Sources */, 7A11474923FF2B2D00B424AF /* Response.swift in Sources */,
7A11471823FDEBFA00B424AF /* ReportController.swift in Sources */, 7A11471823FDEBFA00B424AF /* ReportController.swift in Sources */,
7A11471A23FE839000B424AF /* AuthController.swift in Sources */, 7A11471A23FE839000B424AF /* AuthController.swift in Sources */,

View File

@ -24,21 +24,5 @@
stopOnStyle = "0"> stopOnStyle = "0">
</BreakpointContent> </BreakpointContent>
</BreakpointProxy> </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> </Breakpoints>
</Bucket> </Bucket>

View File

@ -18,7 +18,7 @@
<subviews> <subviews>
<collectionView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" translatesAutoresizingMaskIntoConstraints="NO" id="rG3-ze-Zre"> <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"/> <rect key="frame" x="0.0" y="44" width="375" height="623"/>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/> <color key="backgroundColor" systemColor="systemGroupedBackgroundColor" red="0.94901960780000005" green="0.94901960780000005" blue="0.96862745100000003" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<collectionViewFlowLayout key="collectionViewLayout" automaticEstimatedItemSize="YES" minimumLineSpacing="10" minimumInteritemSpacing="10" id="w9q-DU-Wac"> <collectionViewFlowLayout key="collectionViewLayout" automaticEstimatedItemSize="YES" minimumLineSpacing="10" minimumInteritemSpacing="10" id="w9q-DU-Wac">
<size key="itemSize" width="303" height="85"/> <size key="itemSize" width="303" height="85"/>
<size key="headerReferenceSize" width="0.0" height="0.0"/> <size key="headerReferenceSize" width="0.0" height="0.0"/>
@ -116,38 +116,39 @@
<rect key="frame" x="0.0" y="0.0" width="303" height="264"/> <rect key="frame" x="0.0" y="0.0" width="303" height="264"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="wgf-C8-UOE"> <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="wgf-C8-UOE">
<rect key="frame" x="0.0" y="0.0" width="303" height="198"/> <rect key="frame" x="0.0" y="0.0" width="303" height="198"/>
<constraints> <constraints>
<constraint firstAttribute="width" secondItem="wgf-C8-UOE" secondAttribute="height" multiplier="101:66" id="OzD-Ts-mnv"/> <constraint firstAttribute="width" secondItem="wgf-C8-UOE" secondAttribute="height" multiplier="101:66" id="OzD-Ts-mnv"/>
</constraints> </constraints>
</imageView> </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"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="1HU-6D-JSt">
<rect key="frame" x="8" y="206" width="287" height="21"/> <rect key="frame" x="8" y="206" width="287" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/> <fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<nil key="textColor"/> <nil key="textColor"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </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"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" 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"/> <rect key="frame" x="8" y="235" width="287" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/> <fontDescription key="fontDescription" style="UICTFontTextStyleSubhead"/>
<nil key="textColor"/> <color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
</subviews> </subviews>
<constraints> <constraints>
<constraint firstItem="1HU-6D-JSt" firstAttribute="top" secondItem="wgf-C8-UOE" secondAttribute="bottom" constant="8" id="2nP-F6-Jr9"/> <constraint firstItem="1HU-6D-JSt" firstAttribute="top" secondItem="wgf-C8-UOE" secondAttribute="bottom" constant="4" id="2nP-F6-Jr9"/>
<constraint firstAttribute="trailing" secondItem="1HU-6D-JSt" secondAttribute="trailing" constant="8" id="AI8-D3-c49"/> <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 firstItem="l3q-fD-P3R" firstAttribute="top" secondItem="1HU-6D-JSt" secondAttribute="bottom" constant="4" id="Gxd-mq-F5c"/>
<constraint firstAttribute="trailing" secondItem="wgf-C8-UOE" secondAttribute="trailing" id="Moc-ou-hry"/> <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 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 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 firstAttribute="bottom" secondItem="l3q-fD-P3R" secondAttribute="bottom" constant="4" 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="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="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"/> <constraint firstItem="l3q-fD-P3R" firstAttribute="leading" secondItem="AMu-PZ-gGR" secondAttribute="leading" constant="8" id="u0P-VY-lFV"/>
</constraints> </constraints>
</collectionViewCellContentView> </collectionViewCellContentView>
<color key="backgroundColor" cocoaTouchSystemColor="tableCellGroupedBackgroundColor"/>
<size key="customSize" width="303" height="264"/> <size key="customSize" width="303" height="264"/>
<connections> <connections>
<outlet property="date" destination="l3q-fD-P3R" id="rEm-YK-xrw"/> <outlet property="date" destination="l3q-fD-P3R" id="rEm-YK-xrw"/>
@ -199,18 +200,35 @@
<!--Settings--> <!--Settings-->
<scene sceneID="G47-o0-Caa"> <scene sceneID="G47-o0-Caa">
<objects> <objects>
<viewController id="4jU-Z3-PF2" sceneMemberID="viewController"> <viewController id="4jU-Z3-PF2" customClass="SettingsController" customModule="AutoCat" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="NFd-we-MVH"> <view key="view" contentMode="scaleToFill" id="NFd-we-MVH">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/> <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="8Te-C0-b8T">
<rect key="frame" x="16" y="20" width="343" height="30"/>
<constraints>
<constraint firstAttribute="height" constant="30" id="Xak-Dx-nTf"/>
</constraints>
<state key="normal" title="Logout"/>
<connections>
<action selector="logout:" destination="4jU-Z3-PF2" eventType="touchUpInside" id="RSM-Bp-2sN"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/> <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<constraints>
<constraint firstItem="Uix-8K-fxh" firstAttribute="trailing" secondItem="8Te-C0-b8T" secondAttribute="trailing" constant="16" id="DsI-gO-q9W"/>
<constraint firstItem="8Te-C0-b8T" firstAttribute="top" secondItem="Uix-8K-fxh" secondAttribute="top" constant="20" id="J43-Oo-kme"/>
<constraint firstItem="8Te-C0-b8T" firstAttribute="leading" secondItem="Uix-8K-fxh" secondAttribute="leading" constant="16" id="iSk-SC-T1w"/>
</constraints>
<viewLayoutGuide key="safeArea" id="Uix-8K-fxh"/> <viewLayoutGuide key="safeArea" id="Uix-8K-fxh"/>
</view> </view>
<tabBarItem key="tabBarItem" title="Settings" image="gear" catalog="system" id="zEL-ph-E2f"/> <tabBarItem key="tabBarItem" title="Settings" image="gear" catalog="system" id="zEL-ph-E2f"/>
</viewController> </viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="trD-gZ-yAv" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/> <placeholder placeholderIdentifier="IBFirstResponder" id="trD-gZ-yAv" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects> </objects>
<point key="canvasLocation" x="3262" y="893"/> <point key="canvasLocation" x="3261.5999999999999" y="892.80359820089961"/>
</scene> </scene>
<!--Check Controller--> <!--Check Controller-->
<scene sceneID="t7Z-yv-ZLH"> <scene sceneID="t7Z-yv-ZLH">
@ -424,6 +442,7 @@
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/> <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/> <color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<viewLayoutGuide key="safeArea" id="AB1-mO-dFT"/>
</view> </view>
</viewController> </viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="xYU-vW-bpS" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/> <placeholder placeholderIdentifier="IBFirstResponder" id="xYU-vW-bpS" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>

View File

@ -3,10 +3,16 @@ import MagazineLayout
class SectionHeader: MagazineLayoutCollectionReusableView { class SectionHeader: MagazineLayoutCollectionReusableView {
@IBOutlet weak var title: UILabel! @IBOutlet weak var title: UILabel!
@IBOutlet weak var divider: UIView!
@IBOutlet weak var dividerHeightConstraint: NSLayoutConstraint! @IBOutlet weak var dividerHeightConstraint: NSLayoutConstraint!
override func awakeFromNib() { override func awakeFromNib() {
super.awakeFromNib() super.awakeFromNib()
self.dividerHeightConstraint.constant = 1/UIScreen.main.scale self.dividerHeightConstraint.constant = 1/UIScreen.main.scale
} }
func configure(with section: ReportSection) {
self.title.text = section.description
self.divider.isHidden = section == .photos
}
} }

View File

@ -14,7 +14,7 @@
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <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"> <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"/> <rect key="frame" x="16" y="24" width="288" height="18"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleHeadline"/> <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"/> <color key="textColor" systemColor="secondaryLabelColor" red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
@ -34,11 +34,12 @@
<constraint firstItem="VXr-Tz-HHm" firstAttribute="trailing" secondItem="co2-Tz-MXm" secondAttribute="trailing" id="GTl-lK-7Be"/> <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="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="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="FPf-35-HkN" firstAttribute="top" secondItem="U6b-Vx-4bR" secondAttribute="top" constant="24" id="P1f-gG-3TZ"/>
<constraint firstItem="VXr-Tz-HHm" firstAttribute="bottom" secondItem="FPf-35-HkN" secondAttribute="bottom" constant="8" id="han-2D-OPQ"/> <constraint firstItem="VXr-Tz-HHm" firstAttribute="bottom" secondItem="FPf-35-HkN" secondAttribute="bottom" constant="8" id="han-2D-OPQ"/>
</constraints> </constraints>
<viewLayoutGuide key="safeArea" id="VXr-Tz-HHm"/> <viewLayoutGuide key="safeArea" id="VXr-Tz-HHm"/>
<connections> <connections>
<outlet property="divider" destination="co2-Tz-MXm" id="0C5-OK-vyS"/>
<outlet property="dividerHeightConstraint" destination="6Y8-H1-th4" id="fQS-Xf-i5n"/> <outlet property="dividerHeightConstraint" destination="6Y8-H1-th4" id="fQS-Xf-i5n"/>
<outlet property="title" destination="FPf-35-HkN" id="yr1-mY-pnu"/> <outlet property="title" destination="FPf-35-HkN" id="yr1-mY-pnu"/>
</connections> </connections>

View File

@ -7,6 +7,15 @@ class VehiclePhotoCell: MagazineLayoutCollectionViewCell {
@IBOutlet weak var model: UILabel! @IBOutlet weak var model: UILabel!
@IBOutlet weak var date: UILabel! @IBOutlet weak var date: UILabel!
let formatter = DateFormatter()
override func awakeFromNib() {
super.awakeFromNib()
self.layer.cornerRadius = 8
formatter.timeStyle = .none
formatter.dateStyle = .medium
}
override func prepareForReuse() { override func prepareForReuse() {
super.prepareForReuse() super.prepareForReuse()
self.photo.kf.cancelDownloadTask() self.photo.kf.cancelDownloadTask()
@ -18,5 +27,8 @@ class VehiclePhotoCell: MagazineLayoutCollectionViewCell {
} }
self.model.text = "\(photoModel.brand ?? "") \(photoModel.model ?? "")" self.model.text = "\(photoModel.brand ?? "") \(photoModel.model ?? "")"
let date = Date(timeIntervalSince1970: photoModel.date/1000)
self.date.text = formatter.string(from: date)
} }
} }

View File

@ -2,6 +2,7 @@ import UIKit
import RxSwift import RxSwift
import RxCocoa import RxCocoa
import SVProgressHUD import SVProgressHUD
import RealmSwift
class AuthController: UIViewController { class AuthController: UIViewController {
@ -22,6 +23,10 @@ class AuthController: UIViewController {
authValid.bind(to: self.login.rx.isEnabled).disposed(by: self.bag) authValid.bind(to: self.login.rx.isEnabled).disposed(by: self.bag)
authValid.bind(to: self.signup.rx.isEnabled).disposed(by: self.bag) authValid.bind(to: self.signup.rx.isEnabled).disposed(by: self.bag)
if Settings.shared.user.login.count > 0 {
self.username.text = Settings.shared.user.login
}
} }
@IBAction func loginTapped(_ sender: UIButton) { @IBAction func loginTapped(_ sender: UIButton) {
@ -45,7 +50,19 @@ class AuthController: UIViewController {
} }
func goToMainScreen(user: User) { func goToMainScreen(user: User) {
guard let realm = try? Realm() else {
SVProgressHUD.showError(withStatus: "Database error")
return
}
SVProgressHUD.dismiss() SVProgressHUD.dismiss()
if user.login != Settings.shared.user.login {
try? realm.write {
realm.deleteAll()
}
}
Settings.shared.user = user Settings.shared.user = user
let storyboard = UIStoryboard(name: "Main", bundle: nil) let storyboard = UIStoryboard(name: "Main", bundle: nil)
self.view.window?.rootViewController = storyboard.instantiateViewController(identifier: "MainSplitController") self.view.window?.rootViewController = storyboard.instantiateViewController(identifier: "MainSplitController")

View File

@ -27,7 +27,7 @@ class CheckController: UIViewController, MaskedTextFieldDelegateListener {
ds.headerTitle = "History" ds.headerTitle = "History"
let realm = try! Realm() let realm = try! Realm()
Observable.changeset(from: realm.objects(Vehicle.self)) Observable.changeset(from: realm.objects(Vehicle.self).sorted(byKeyPath: "addedDate", ascending: false))
.bind(to: self.history.rx.realmChanges(ds)) .bind(to: self.history.rx.realmChanges(ds))
.disposed(by: self.bag) .disposed(by: self.bag)

View File

@ -1,17 +1,21 @@
import UIKit import UIKit
import MagazineLayout import MagazineLayout
import ATGMediaBrowser
import Kingfisher
enum ReportSection: Int, CaseIterable, CustomStringConvertible { enum ReportSection: Int, CaseIterable, CustomStringConvertible {
case header = 0 case header = 0
case general = 1 case general = 1
case identifiers = 2 case identifiers = 2
case photos = 3 case engine = 3
case photos = 4
var description: String { var description: String {
switch self { switch self {
case .header: return "Header" case .header: return "Header"
case .general: return "General" case .general: return "General"
case .identifiers: return "Identifiers" case .identifiers: return "Identifiers"
case .engine: return "Engine"
case .photos: return "Photos" case .photos: return "Photos"
} }
} }
@ -49,7 +53,25 @@ enum ReportIdSection: Int, CaseIterable, CustomStringConvertible {
} }
} }
class ReportController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateMagazineLayout { enum ReportEngineSection: Int, CaseIterable, CustomStringConvertible {
case number = 0
case fuelType = 1
case volume = 2
case powerHp = 3
case powerKw = 4
var description: String {
switch self {
case .number: return "Number"
case .fuelType: return "Fuel type"
case .volume: return "Volume (cm³)"
case .powerHp: return "Power (HP)"
case .powerKw: return "Power (kw)"
}
}
}
class ReportController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateMagazineLayout, MediaBrowserViewControllerDataSource, MediaBrowserViewControllerDelegate {
@IBOutlet weak var collection: UICollectionView! @IBOutlet weak var collection: UICollectionView!
@ -81,6 +103,7 @@ class ReportController: UIViewController, UICollectionViewDataSource, UICollecti
// MARK: - UICollectionViewDataSource // MARK: - UICollectionViewDataSource
func numberOfSections(in collectionView: UICollectionView) -> Int { func numberOfSections(in collectionView: UICollectionView) -> Int {
guard self.vehicle != nil else { return 0 }
return ReportSection.allCases.count return ReportSection.allCases.count
} }
@ -92,6 +115,7 @@ class ReportController: UIViewController, UICollectionViewDataSource, UICollecti
case .header: return 1 case .header: return 1
case .general: return ReportGeneralSection.allCases.count case .general: return ReportGeneralSection.allCases.count
case .identifiers: return ReportIdSection.allCases.count case .identifiers: return ReportIdSection.allCases.count
case .engine: return ReportEngineSection.allCases.count
case .photos: return vehicle.photos.count case .photos: return vehicle.photos.count
} }
} }
@ -142,6 +166,28 @@ class ReportController: UIViewController, UICollectionViewDataSource, UICollecti
} }
} }
return cell ?? UICollectionViewCell() return cell ?? UICollectionViewCell()
case .engine:
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "VehicleTextParamCell", for: indexPath) as? VehicleTextParamCell
if let engineSection = ReportEngineSection(rawValue: indexPath.item), let engine = vehicle.engine {
switch engineSection {
case .number:
cell?.configure(param: engineSection.description, value: engine.number ?? "<unknown>")
break
case .fuelType:
cell?.configure(param: engineSection.description, value: engine.fuelType ?? "<unknown>")
break
case .volume:
cell?.configure(param: engineSection.description, value: String(engine.volume))
break
case .powerHp:
cell?.configure(param: engineSection.description, value: String(engine.powerHp))
break
case .powerKw:
cell?.configure(param: engineSection.description, value: String(engine.powerKw))
break
}
}
return cell ?? UICollectionViewCell()
case .photos: case .photos:
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "VehiclePhotoCell", for: indexPath) as? VehiclePhotoCell let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "VehiclePhotoCell", for: indexPath) as? VehiclePhotoCell
let photo = vehicle.photos[indexPath.item] let photo = vehicle.photos[indexPath.item]
@ -155,12 +201,21 @@ class ReportController: UIViewController, UICollectionViewDataSource, UICollecti
guard let section = ReportSection(rawValue: indexPath.section) else { return UICollectionReusableView() } guard let section = ReportSection(rawValue: indexPath.section) else { return UICollectionReusableView() }
if let sectionHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "SectionHeader", for: indexPath) as? SectionHeader { if let sectionHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "SectionHeader", for: indexPath) as? SectionHeader {
sectionHeader.title.text = section.description sectionHeader.configure(with: section)
return sectionHeader return sectionHeader
} }
return UICollectionReusableView() return UICollectionReusableView()
} }
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard indexPath.section == ReportSection.photos.rawValue else { return }
let mediaBrowser = MediaBrowserViewController(index: indexPath.item, dataSource: self, delegate: self)
mediaBrowser.shouldShowTitle = true
mediaBrowser.title = self.vehicle?.photos[indexPath.item].description
present(mediaBrowser, animated: true, completion: nil)
}
// MARK: - UICollectionViewDelegateMagazineLayout // MARK: - UICollectionViewDelegateMagazineLayout
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeModeForItemAt indexPath: IndexPath) -> MagazineLayoutItemSizeMode func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeModeForItemAt indexPath: IndexPath) -> MagazineLayoutItemSizeMode
@ -170,7 +225,10 @@ class ReportController: UIViewController, UICollectionViewDataSource, UICollecti
case .header: return self.fullWidth case .header: return self.fullWidth
case .general: return self.fullWidth case .general: return self.fullWidth
case .identifiers: return self.fullWidth case .identifiers: return self.fullWidth
case .photos: return .init(widthMode: .thirdWidth, heightMode: .dynamic) case .engine: return self.fullWidth
case .photos:
let wMode: MagazineLayoutItemWidthMode = self.traitCollection.horizontalSizeClass != .compact ? .thirdWidth : .halfWidth
return .init(widthMode: wMode, heightMode: .dynamic)
} }
} }
@ -181,6 +239,7 @@ class ReportController: UIViewController, UICollectionViewDataSource, UICollecti
case .header: return .hidden case .header: return .hidden
case .general: return .visible(heightMode: .dynamic) case .general: return .visible(heightMode: .dynamic)
case .identifiers: return .visible(heightMode: .dynamic) case .identifiers: return .visible(heightMode: .dynamic)
case .engine: return .visible(heightMode: .dynamic)
case .photos: return .visible(heightMode: .dynamic) case .photos: return .visible(heightMode: .dynamic)
} }
} }
@ -202,16 +261,46 @@ class ReportController: UIViewController, UICollectionViewDataSource, UICollecti
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, verticalSpacingForElementsInSectionAtIndex index: Int) -> CGFloat func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, verticalSpacingForElementsInSectionAtIndex index: Int) -> CGFloat
{ {
return 0 return index == ReportSection.photos.rawValue ? 16 : 0
} }
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetsForSectionAtIndex index: Int) -> UIEdgeInsets func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetsForSectionAtIndex index: Int) -> UIEdgeInsets
{ {
return .zero return index == ReportSection.photos.rawValue ? UIEdgeInsets(top: 0, left: 0, bottom: 16, right: 0) : .zero
} }
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetsForItemsInSectionAtIndex index: Int) -> UIEdgeInsets func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetsForItemsInSectionAtIndex index: Int) -> UIEdgeInsets
{ {
return .zero return index == ReportSection.photos.rawValue ? UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16) : .zero
}
// MARK: - MediaBrowserViewControllerDataSource & MediaBrowserViewControllerDelegate
func numberOfItems(in mediaBrowser: MediaBrowserViewController) -> Int {
guard let images = self.vehicle?.photos else { return 0 }
return images.count
}
func mediaBrowser(_ mediaBrowser: MediaBrowserViewController, imageAt index: Int, completion: @escaping MediaBrowserViewControllerDataSource.CompletionBlock) {
guard let images = self.vehicle?.photos, let url = URL(string: images[index].url) else {
completion(index, nil, ZoomScale.default, NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey: "Image not found"]))
return
}
KingfisherManager.shared.retrieveImage(with: url) { result in
switch result {
case .success(let res):
completion(index, res.image, ZoomScale.default, nil)
break
case .failure(let error):
completion(index, nil, ZoomScale.default, error)
break
}
}
}
func mediaBrowser(_ mediaBrowser: ATGMediaBrowser.MediaBrowserViewController, didChangeFocusTo index: Int) {
guard let photo = self.vehicle?.photos[index] else { return }
mediaBrowser.title = photo.description
} }
} }

View File

@ -0,0 +1,16 @@
import UIKit
class SettingsController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
@IBAction func logout(_ sender: UIButton) {
Settings.shared.user.token = ""
let storyboard = UIStoryboard(name: "Main", bundle: nil)
self.view.window?.rootViewController = storyboard.instantiateViewController(identifier: "AuthController")
}
}

View File

@ -2,6 +2,26 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>platesmania.com</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
<key>avto-nomer.ru</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
</dict>
</dict>
</dict>
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string> <string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>

View File

@ -2,7 +2,7 @@ import Foundation
class User: Codable { class User: Codable {
let login: String let login: String
let token: String var token: String
init() { init() {
self.login = "" self.login = ""

View File

@ -26,8 +26,17 @@ class VehicleEngine: Object, Decodable {
class VehiclePhoto: Object, Decodable { class VehiclePhoto: Object, Decodable {
@objc dynamic var brand: String? @objc dynamic var brand: String?
@objc dynamic var model: String? @objc dynamic var model: String?
@objc dynamic var date: Int64 = 0 @objc dynamic var date: TimeInterval = 0
@objc dynamic var url: String = "" @objc dynamic var url: String = ""
override var description: String {
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .none
let date = Date(timeIntervalSince1970: self.date/1000)
let dateStr = formatter.string(from: date)
return "\(self.brand ?? "") \(self.model ?? "") (\(dateStr))"
}
} }
class Vehicle: Object, Decodable { class Vehicle: Object, Decodable {
@ -45,7 +54,55 @@ class Vehicle: Object, Decodable {
@objc dynamic var pts: String? @objc dynamic var pts: String?
@objc dynamic var isRightWheel: Bool = false @objc dynamic var isRightWheel: Bool = false
@objc dynamic var isJapanese: Bool = false @objc dynamic var isJapanese: Bool = false
@objc dynamic var addedDate: Int64 = 0 @objc dynamic var addedDate: TimeInterval = 0
@objc dynamic var addedBy: String = "" @objc dynamic var addedBy: String = ""
let photos = List<VehiclePhoto>() let photos = List<VehiclePhoto>()
enum CodingKeys: String, CodingKey {
case _id
case brand
case model
case color
case year
case category
case engine
case number
case vin1
case vin2
case sts
case pts
case isRightWheel
case isJapanese
case addedDate
case addedBy
case photos
}
required init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self._id = try container.decode(String.self, forKey: ._id)
self.brand = try container.decodeIfPresent(VehicleBrand.self, forKey: .brand)
self.model = try container.decodeIfPresent(VehicleModel.self, forKey: .model)
self.color = try container.decodeIfPresent(String.self, forKey: .color)
self.year = try container.decode(Int.self, forKey: .year)
self.category = try container.decodeIfPresent(String.self, forKey: .category)
self.engine = try container.decodeIfPresent(VehicleEngine.self, forKey: .engine)
self.number = try container.decode(String.self, forKey: .number)
self.vin1 = try container.decodeIfPresent(String.self, forKey: .vin1)
self.vin2 = try container.decodeIfPresent(String.self, forKey: .vin2)
self.sts = try container.decodeIfPresent(String.self, forKey: .sts)
self.pts = try container.decodeIfPresent(String.self, forKey: .pts)
self.isRightWheel = try container.decode(Bool.self, forKey: .isRightWheel)
self.isJapanese = try container.decode(Bool.self, forKey: .isJapanese)
self.addedDate = try container.decode(TimeInterval.self, forKey: .addedDate)
self.addedBy = try container.decode(String.self, forKey: .addedBy)
if let photosArray = try container.decodeIfPresent([VehiclePhoto].self, forKey: .photos) {
self.photos.append(objectsIn: photosArray)
}
}
required init() {
}
} }

View File

@ -64,6 +64,9 @@ class Api {
} }
public static func checkVehicle(by number: String) -> Observable<Vehicle> { public static func checkVehicle(by number: String) -> Observable<Vehicle> {
return self.makeRequest(api: "vehicles/check", method: "POST", body: ["number": number]) return self.makeRequest(api: "vehicles/check", method: "POST", body: ["number": number]).map { (vehicle: Vehicle) -> Vehicle in
vehicle.addedDate = Date().timeIntervalSince1970*1000
return vehicle
}
} }
} }

View File

@ -1 +1,2 @@
github "selim-mustafaev/SVProgressHUD" "ios13-support" github "selim-mustafaev/SVProgressHUD" "ios13-support"
github "altayer-digital/ATGMediaBrowser" "master"

View File

@ -1 +1,2 @@
github "altayer-digital/ATGMediaBrowser" "8afc2957ab218ab650fcb538256f118b79ae92bd"
github "selim-mustafaev/SVProgressHUD" "17b1eacb2800ffa91eb5fb12e1a5983dba29f9dc" github "selim-mustafaev/SVProgressHUD" "17b1eacb2800ffa91eb5fb12e1a5983dba29f9dc"

View File

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

View File

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