Remove old CheckController

This commit is contained in:
Selim Mustafaev 2025-02-09 15:01:02 +03:00
parent ded951a880
commit c8d7279fd1
6 changed files with 43 additions and 757 deletions

View File

@ -62,7 +62,7 @@
7A4322952CB2CD0F00085CF6 /* FiltersCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A4322942CB2CD0F00085CF6 /* FiltersCoordinator.swift */; }; 7A4322952CB2CD0F00085CF6 /* FiltersCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A4322942CB2CD0F00085CF6 /* FiltersCoordinator.swift */; };
7A45FB382C27073700618694 /* StorageService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A45FB372C27073700618694 /* StorageService.swift */; }; 7A45FB382C27073700618694 /* StorageService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A45FB372C27073700618694 /* StorageService.swift */; };
7A4927D52CCE438600851C01 /* OptionalBinding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A4927D42CCE438600851C01 /* OptionalBinding.swift */; }; 7A4927D52CCE438600851C01 /* OptionalBinding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A4927D42CCE438600851C01 /* OptionalBinding.swift */; };
7A530B7A24001D3300CBFE6E /* CheckController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B7924001D3300CBFE6E /* CheckController.swift */; }; 7A4955822D58CCF900912E66 /* HistoryFilter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A4955812D58CCF900912E66 /* HistoryFilter.swift */; };
7A530B7E24017FEE00CBFE6E /* VehicleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B7D24017FEE00CBFE6E /* VehicleCell.swift */; }; 7A530B7E24017FEE00CBFE6E /* VehicleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A530B7D24017FEE00CBFE6E /* VehicleCell.swift */; };
7A54BFD32D43B95E00176D6D /* DbUpdatePolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A54BFD22D43B95E00176D6D /* DbUpdatePolicy.swift */; }; 7A54BFD32D43B95E00176D6D /* DbUpdatePolicy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A54BFD22D43B95E00176D6D /* DbUpdatePolicy.swift */; };
7A599C362C18AC7F00D47C18 /* ApiError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A599C352C18AC7F00D47C18 /* ApiError.swift */; }; 7A599C362C18AC7F00D47C18 /* ApiError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A599C352C18AC7F00D47C18 /* ApiError.swift */; };
@ -332,8 +332,8 @@
7A43F9F7246C8A6200BA5B49 /* JWT.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JWT.swift; sourceTree = "<group>"; }; 7A43F9F7246C8A6200BA5B49 /* JWT.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JWT.swift; sourceTree = "<group>"; };
7A45FB372C27073700618694 /* StorageService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageService.swift; sourceTree = "<group>"; }; 7A45FB372C27073700618694 /* StorageService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageService.swift; sourceTree = "<group>"; };
7A4927D42CCE438600851C01 /* OptionalBinding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptionalBinding.swift; sourceTree = "<group>"; }; 7A4927D42CCE438600851C01 /* OptionalBinding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OptionalBinding.swift; sourceTree = "<group>"; };
7A4955812D58CCF900912E66 /* HistoryFilter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryFilter.swift; sourceTree = "<group>"; };
7A52AB292580112E002CD910 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; }; 7A52AB292580112E002CD910 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; 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>"; }; 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>"; }; 7A530B7F2401803A00CBFE6E /* Vehicle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Vehicle.swift; sourceTree = "<group>"; };
7A54BFD22D43B95E00176D6D /* DbUpdatePolicy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DbUpdatePolicy.swift; sourceTree = "<group>"; }; 7A54BFD22D43B95E00176D6D /* DbUpdatePolicy.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DbUpdatePolicy.swift; sourceTree = "<group>"; };
@ -632,7 +632,6 @@
children = ( children = (
7A813DC7250B5C6E00CC93B9 /* Location */, 7A813DC7250B5C6E00CC93B9 /* Location */,
7A11471923FE839000B424AF /* AuthController.swift */, 7A11471923FE839000B424AF /* AuthController.swift */,
7A530B7924001D3300CBFE6E /* CheckController.swift */,
7A96AE2C246B2B7400297C33 /* GoogleSignInController.swift */, 7A96AE2C246B2B7400297C33 /* GoogleSignInController.swift */,
7A11471523FDEB2A00B424AF /* MainSplitController.swift */, 7A11471523FDEB2A00B424AF /* MainSplitController.swift */,
7A27ADF2249F8B650035F39E /* RecordsController.swift */, 7A27ADF2249F8B650035F39E /* RecordsController.swift */,
@ -704,6 +703,7 @@
7A131FD22D37B75500DC7755 /* HistoryScreen.swift */, 7A131FD22D37B75500DC7755 /* HistoryScreen.swift */,
7A131FD42D37B76A00DC7755 /* HistoryViewModel.swift */, 7A131FD42D37B76A00DC7755 /* HistoryViewModel.swift */,
7A131FD62D37B77E00DC7755 /* HistoryCoordinator.swift */, 7A131FD62D37B77E00DC7755 /* HistoryCoordinator.swift */,
7A4955812D58CCF900912E66 /* HistoryFilter.swift */,
); );
path = HistoryScreen; path = HistoryScreen;
sourceTree = "<group>"; sourceTree = "<group>";
@ -1411,7 +1411,6 @@
7A64AE762469DFB600ABE48E /* ContentTransformers.swift in Sources */, 7A64AE762469DFB600ABE48E /* ContentTransformers.swift in Sources */,
7AE24C5F251F1B4E00758E39 /* Buttons.swift in Sources */, 7AE24C5F251F1B4E00758E39 /* Buttons.swift in Sources */,
7A11471A23FE839000B424AF /* AuthController.swift in Sources */, 7A11471A23FE839000B424AF /* AuthController.swift in Sources */,
7A530B7A24001D3300CBFE6E /* CheckController.swift in Sources */,
7A64AE742469DFB600ABE48E /* MediaContentView.swift in Sources */, 7A64AE742469DFB600ABE48E /* MediaContentView.swift in Sources */,
7A1090EC24A4E3E100B4F0B2 /* CellProgressView.swift in Sources */, 7A1090EC24A4E3E100B4F0B2 /* CellProgressView.swift in Sources */,
7AB9FE2A2D08CF35005DE374 /* EventsScreenMode.swift in Sources */, 7AB9FE2A2D08CF35005DE374 /* EventsScreenMode.swift in Sources */,
@ -1443,6 +1442,7 @@
7A4322952CB2CD0F00085CF6 /* FiltersCoordinator.swift in Sources */, 7A4322952CB2CD0F00085CF6 /* FiltersCoordinator.swift in Sources */,
7A131FD72D37B77E00DC7755 /* HistoryCoordinator.swift in Sources */, 7A131FD72D37B77E00DC7755 /* HistoryCoordinator.swift in Sources */,
7A7158002C43EA6900852088 /* OwnersScreen.swift in Sources */, 7A7158002C43EA6900852088 /* OwnersScreen.swift in Sources */,
7A4955822D58CCF900912E66 /* HistoryFilter.swift in Sources */,
7A1441702C2998B200E79018 /* Formatters.swift in Sources */, 7A1441702C2998B200E79018 /* Formatters.swift in Sources */,
7A4322912CB2CC8A00085CF6 /* FiltersScreen.swift in Sources */, 7A4322912CB2CC8A00085CF6 /* FiltersScreen.swift in Sources */,
7ABD1B472D044A3200B43213 /* GalleryScreen.swift in Sources */, 7ABD1B472D044A3200B43213 /* GalleryScreen.swift in Sources */,

View File

@ -244,143 +244,7 @@
</viewController> </viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Vum-9f-55l" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/> <placeholder placeholderIdentifier="IBFirstResponder" id="Vum-9f-55l" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects> </objects>
<point key="canvasLocation" x="4200.8000000000002" y="1660.1199400299852"/> <point key="canvasLocation" x="2614" y="1045"/>
</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>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" keyboardDismissMode="onDrag" 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="64" width="375" height="603"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<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="50" width="375" height="94.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="94.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="6IZ-gM-D28">
<rect key="frame" x="8" y="8" width="359" height="78.5"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" spacing="4" translatesAutoresizingMaskIntoConstraints="NO" id="Rz6-wH-O1q">
<rect key="frame" x="0.0" y="0.0" width="359" height="20"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" horizontalCompressionResistancePriority="749" text="Kia 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="290.5" height="20"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleHeadline"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="exclamationmark.arrow.triangle.2.circlepath" catalog="system" translatesAutoresizingMaskIntoConstraints="NO" id="pdg-uR-pUn">
<rect key="frame" x="294" y="0.5" width="21" height="19"/>
<color key="tintColor" systemColor="systemOrangeColor"/>
<constraints>
<constraint firstAttribute="height" constant="20" id="9HI-9d-T5A"/>
<constraint firstAttribute="width" constant="20" id="YAB-Lz-sqG"/>
</constraints>
</imageView>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" image="text.bubble" catalog="system" translatesAutoresizingMaskIntoConstraints="NO" id="It0-Zx-REl">
<rect key="frame" x="318.5" y="0.5" width="20" height="19.5"/>
<constraints>
<constraint firstAttribute="height" constant="20" id="2hp-7v-GVx"/>
<constraint firstAttribute="width" constant="20" id="sDL-E7-jY4"/>
</constraints>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="12" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="XA5-vL-FV1">
<rect key="frame" x="342.5" y="0.0" width="16.5" height="20"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleCallout"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
<stackView opaque="NO" contentMode="scaleToFill" alignment="bottom" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="nX1-KA-jqp">
<rect key="frame" x="0.0" y="28" width="359" height="50.5"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="VHX-o0-3BP" customClass="PlateView" customModule="AutoCat" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.5" width="295" height="50"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<color key="tintColor" systemColor="systemOrangeColor"/>
</view>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="bottom" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="ApN-fV-Qw4">
<rect key="frame" x="303" y="10.5" width="56" height="40"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" text="1.01.2021" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="rKr-3e-WYb">
<rect key="frame" x="0.0" y="0.0" width="56" height="16"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleFootnote"/>
<color key="textColor" systemColor="secondaryLabelColor"/>
<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="UOb-db-Sty">
<rect key="frame" x="23" y="24" width="33" height="16"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleFootnote"/>
<color key="textColor" systemColor="tertiaryLabelColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
</subviews>
</stackView>
</subviews>
</stackView>
</subviews>
<constraints>
<constraint firstAttribute="trailing" secondItem="6IZ-gM-D28" secondAttribute="trailing" constant="8" id="Ku8-6L-Frz"/>
<constraint firstAttribute="bottom" secondItem="6IZ-gM-D28" secondAttribute="bottom" constant="8" id="NF3-s6-87u"/>
<constraint firstItem="6IZ-gM-D28" firstAttribute="top" secondItem="IGw-UK-ebp" secondAttribute="top" constant="8" id="WfT-Jn-Yx1"/>
<constraint firstItem="6IZ-gM-D28" firstAttribute="leading" secondItem="IGw-UK-ebp" secondAttribute="leading" constant="8" id="zPI-NI-EuK"/>
</constraints>
</tableViewCellContentView>
<inset key="separatorInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
<connections>
<outlet property="addedDate" destination="UOb-db-Sty" id="oVf-sZ-fdF"/>
<outlet property="bubbleImage" destination="It0-Zx-REl" id="Qbl-tj-iw4"/>
<outlet property="name" destination="h3N-1o-J20" id="jcM-B4-bEJ"/>
<outlet property="notesCount" destination="XA5-vL-FV1" id="UjX-bm-6uo"/>
<outlet property="plate" destination="VHX-o0-3BP" id="D8N-L7-O8b"/>
<outlet property="syncImage" destination="pdg-uR-pUn" id="DRx-XJ-WNa"/>
<outlet property="updatedDate" destination="rKr-3e-WYb" id="RpZ-NF-Bcg"/>
</connections>
</tableViewCell>
</prototypes>
</tableView>
</subviews>
<viewLayoutGuide key="safeArea" id="3Jk-FW-b3r"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="JKr-UE-x8f" firstAttribute="top" secondItem="3Jk-FW-b3r" secondAttribute="top" id="PUg-nV-TN6"/>
<constraint firstItem="JKr-UE-x8f" firstAttribute="trailing" secondItem="3Jk-FW-b3r" secondAttribute="trailing" id="Tc5-ri-5RD"/>
<constraint firstItem="JKr-UE-x8f" firstAttribute="bottom" secondItem="g5m-iL-O7A" secondAttribute="bottom" id="Zwj-XD-UhD"/>
<constraint firstItem="JKr-UE-x8f" firstAttribute="leading" secondItem="3Jk-FW-b3r" secondAttribute="leading" id="vfN-fu-5pA"/>
</constraints>
</view>
<navigationItem key="navigationItem" id="IMO-Ew-zSY">
<rightBarButtonItems>
<barButtonItem image="line.horizontal.3.decrease" catalog="system" id="L67-Yc-Py6">
<connections>
<action selector="onFilter:" destination="twc-qR-t1G" id="qfm-0f-hT0"/>
</connections>
</barButtonItem>
<barButtonItem image="square.and.arrow.up" catalog="system" id="8MX-eT-xNO">
<connections>
<action selector="onExport:" destination="twc-qR-t1G" id="Wpe-of-odn"/>
</connections>
</barButtonItem>
</rightBarButtonItems>
</navigationItem>
<connections>
<outlet property="history" destination="JKr-UE-x8f" id="GP9-Gz-WBm"/>
</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> </scene>
<!--Google Sign In Controller--> <!--Google Sign In Controller-->
<scene sceneID="ztj-pr-ty7"> <scene sceneID="ztj-pr-ty7">
@ -429,7 +293,7 @@
</viewController> </viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="WxN-oK-U9s" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/> <placeholder placeholderIdentifier="IBFirstResponder" id="WxN-oK-U9s" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects> </objects>
<point key="canvasLocation" x="1704.8" y="-701.19940029985014"/> <point key="canvasLocation" x="740" y="1045"/>
</scene> </scene>
<!--Main Tab Controller--> <!--Main Tab Controller-->
<scene sceneID="YhQ-kn-py3"> <scene sceneID="YhQ-kn-py3">
@ -441,9 +305,7 @@
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/> <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</tabBar> </tabBar>
<connections> <connections>
<segue destination="TSb-ZG-qfD" kind="relationship" relationship="viewControllers" id="Bwf-98-gjF"/>
<segue destination="RK6-pn-2Bg" kind="relationship" relationship="viewControllers" id="KNz-WF-Kyy"/> <segue destination="RK6-pn-2Bg" kind="relationship" relationship="viewControllers" id="KNz-WF-Kyy"/>
<segue destination="dxo-XS-x8Q" kind="relationship" relationship="viewControllers" id="MgV-gx-h7p"/>
<segue destination="GCa-Re-j14" kind="relationship" relationship="viewControllers" id="FGp-f6-fUh"/> <segue destination="GCa-Re-j14" kind="relationship" relationship="viewControllers" id="FGp-f6-fUh"/>
</connections> </connections>
</tabBarController> </tabBarController>
@ -555,22 +417,6 @@
</objects> </objects>
<point key="canvasLocation" x="199" y="143"/> <point key="canvasLocation" x="199" y="143"/>
</scene> </scene>
<!--Add-->
<scene sceneID="bCG-fh-cdJ">
<objects>
<viewController id="dxo-XS-x8Q" customClass="DummyNewController" customModule="AutoCat" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="7Rw-QC-Av7">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<viewLayoutGuide key="safeArea" id="vIj-pz-YHR"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
</view>
<tabBarItem key="tabBarItem" title="Add" image="plus" catalog="system" id="X0w-PF-Dn8"/>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="C2T-ZN-q8G" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="929" y="-260"/>
</scene>
<!--Global Events Controller--> <!--Global Events Controller-->
<scene sceneID="akP-Pw-M4Q"> <scene sceneID="akP-Pw-M4Q">
<objects> <objects>
@ -609,25 +455,6 @@
</objects> </objects>
<point key="canvasLocation" x="7518" y="144"/> <point key="canvasLocation" x="7518" y="144"/>
</scene> </scene>
<!--History-->
<scene sceneID="pUX-kf-oY1">
<objects>
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="TSb-ZG-qfD" sceneMemberID="viewController">
<tabBarItem key="tabBarItem" title="History" image="clock.arrow.circlepath" catalog="system" id="QJd-35-4OB"/>
<toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="AAc-4d-GNh">
<rect key="frame" x="0.0" y="20" 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>
<!--Search--> <!--Search-->
<scene sceneID="kiS-EQ-VFl"> <scene sceneID="kiS-EQ-VFl">
<objects> <objects>
@ -664,7 +491,7 @@
</navigationController> </navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="elc-Dr-KxW" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/> <placeholder placeholderIdentifier="IBFirstResponder" id="elc-Dr-KxW" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
</objects> </objects>
<point key="canvasLocation" x="3261.5999999999999" y="1660.1199400299852"/> <point key="canvasLocation" x="1729" y="1045"/>
</scene> </scene>
<!--Navigation Controller--> <!--Navigation Controller-->
<scene sceneID="fRx-9f-ao6"> <scene sceneID="fRx-9f-ao6">
@ -686,17 +513,14 @@
</scene> </scene>
</scenes> </scenes>
<resources> <resources>
<image name="clock.arrow.circlepath" catalog="system" width="128" height="119"/>
<image name="exclamationmark.arrow.triangle.2.circlepath" catalog="system" width="128" height="117"/> <image name="exclamationmark.arrow.triangle.2.circlepath" catalog="system" width="128" height="117"/>
<image name="line.horizontal.3.decrease" catalog="system" width="128" height="73"/> <image name="line.horizontal.3.decrease" catalog="system" width="128" height="73"/>
<image name="map" catalog="system" width="128" height="112"/> <image name="map" catalog="system" width="128" height="112"/>
<image name="play.fill" catalog="system" width="120" height="128"/> <image name="play.fill" catalog="system" width="120" height="128"/>
<image name="plus" catalog="system" width="128" height="113"/>
<image name="record" width="31" height="31"/> <image name="record" width="31" height="31"/>
<image name="record-compact" width="23" height="23"/> <image name="record-compact" width="23" height="23"/>
<image name="search" width="23" height="23"/> <image name="search" width="23" height="23"/>
<image name="search-compact" width="17" height="17"/> <image name="search-compact" width="17" height="17"/>
<image name="square.and.arrow.up" catalog="system" width="110" height="128"/>
<image name="text.bubble" catalog="system" width="128" height="110"/> <image name="text.bubble" catalog="system" width="128" height="110"/>
<systemColor name="secondaryLabelColor"> <systemColor name="secondaryLabelColor">
<color red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> <color red="0.23529411759999999" green="0.23529411759999999" blue="0.26274509800000001" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/>

View File

@ -1,508 +0,0 @@
import UIKit
import RealmSwift
import SwiftDate
import PKHUD
import CoreLocation
import AutoCatCore
import SwiftLocation
enum EventAction: Equatable {
case doNotSend
case receiveAndSend
}
enum HistoryFilter: CaseIterable, Identifiable {
case all
case unrecognized
case outdated
case notSynced
var title: String {
switch self {
case .all: return NSLocalizedString("All", comment: "");
case .unrecognized: return NSLocalizedString("Unrecognized", comment: "");
case .outdated: return NSLocalizedString("Outdated", comment: "");
case .notSynced: return NSLocalizedString("Not updated", comment: "");
}
}
var id: Int {
switch self {
case .all: return 0;
case .unrecognized: return 1;
case .outdated: return 2;
case .notSynced: return 3;
}
}
}
extension String.StringInterpolation {
mutating func appendInterpolation(_ value: EventAction) {
switch value {
case .doNotSend: appendLiteral("do not send"); break
case .receiveAndSend: appendLiteral("receive and send"); break
}
}
}
class CheckController: UIViewController, UITableViewDelegate, UISearchResultsUpdating {
@IBOutlet weak var history: UITableView!
private var historyDataSource: RealmSectionedDataSource<Vehicle, VehicleCell>!
private var historyFilter: HistoryFilter = .all
private lazy var searchController: UISearchController = .default
.placeholder(NSLocalizedString("Search plate numbers", comment: ""))
.resultsUpdater(self)
.makeDumb()
// MARK: - Lifecycle
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.searchController = searchController
guard let realm = try? Realm() else { return }
self.hideKeyboardWhenTappedAround()
DispatchQueue.main.async {
self.historyDataSource = RealmSectionedDataSource(table: self.history, data: realm.objects(Vehicle.self).sorted(byKeyPath: "updatedDate", ascending: false)) { count in
self.navigationItem.title = String.localizedStringWithFormat(NSLocalizedString("vehicles found", comment: ""), count)
}
}
self.history.delegate = self
NotificationCenter.default.addObserver(forName: .NSCalendarDayChanged,
object: nil,
queue: .main,
using: calendarDayDidChange)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
if let index = self.history.indexPathForSelectedRow {
self.history.deselectRow(at: index, animated: true)
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
Task { await self.handleQuickActions() }
}
// MARK: -
func handleQuickActions() async {
guard let ad = UIApplication.shared.delegate as? AppDelegate else { return }
switch ad.quickAction {
case .check:
ad.quickAction = .none
if let tabBar = tabBarController as? MainTabController {
tabBar.showCheckPuller()
}
break
case .checkNumber(let number, let event):
ad.quickAction = .none
var action: EventAction = .receiveAndSend
var events: [VehicleEventDto] = []
if let event = event {
events = [event]
action = .doNotSend
}
do {
HUD.show(.progress)
let (vehicle, errors) = try await self.check(number: number, action: action, notes: [], events: events)
if !vehicle.unrecognized {
self.updateDetailController(with: vehicle)
}
HUD.hide()
self.showErrors(errors)
} catch {
HUD.hide()
self.show(error: error)
}
break
case .addVoiceRecord:
self.tabBarController?.selectedIndex = 1
break
case .openReport(let number):
ad.quickAction = .none
if let sd = self.view.window?.windowScene?.delegate as? SceneDelegate {
Task { await sd.openReport(with: number) }
}
break
default:
break
}
}
nonisolated private func calendarDayDidChange(_ notification : Notification) {
MainActor.assumeIsolated {
historyDataSource.reload()
}
}
// MARK: - Actions
@IBAction func onExport(_ sender: UIBarButtonItem) {
let sheet = UIAlertController(title: NSLocalizedString("Export history as", comment: ""), message: nil, preferredStyle: .actionSheet)
let cancel = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel) { _ in sheet.dismiss(animated: true, completion: nil) }
let csv = UIAlertAction(title: NSLocalizedString("CSV table", comment: "export as CSV table"), style: .default) { action in
do {
let csvString = try self.historyDataSource.makeCsv()
let tmpUrl = FileManager.default.tmpUrl(name: "history", ext: "csv")
try csvString.write(to: tmpUrl, atomically: true, encoding: .utf8)
#if targetEnvironment(macCatalyst)
self.save(file: tmpUrl)
#else
self.shareFile(tmpUrl)
#endif
} catch {
self.show(error: error)
}
}
let db = UIAlertAction(title: NSLocalizedString("Database file", comment: "export as database file"), style: .default) { action in
do {
let realm = try Realm()
let tmpUrl = FileManager.default.tmpUrl(name: "history", ext: "realm")
if let dbUrl = realm.configuration.fileURL {
try FileManager.default.copyItem(at: dbUrl, to: tmpUrl)
self.shareFile(tmpUrl)
}
} catch {
self.show(error: error)
}
}
sheet.addAction(csv)
sheet.addAction(db)
sheet.addAction(cancel)
sheet.popoverPresentationController?.barButtonItem = sender
self.present(sheet, animated: true)
}
@IBAction func onFilter(_ sender: UIBarButtonItem) {
let sheet = UIAlertController(title: NSLocalizedString("Filter check history", comment: ""), message: nil, preferredStyle: .actionSheet)
let cancel = UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel) { _ in sheet.dismiss(animated: true, completion: nil) }
let all = UIAlertAction(title: NSLocalizedString("All", comment: ""), style: .default) { action in
self.historyDataSource.setFilterPredicate(nil)
self.historyFilter = .all
}
let unrecognized = UIAlertAction(title: NSLocalizedString("Unrecognized", comment: ""), style: .default) { _ in
self.historyDataSource.setFilterPredicate { $0.unrecognized }
self.historyFilter = .unrecognized
}
let outdated = UIAlertAction(title: NSLocalizedString("Outdated", comment: ""), style: .default) { _ in
self.historyDataSource.setFilterPredicate { $0.outdated }
self.historyFilter = .outdated
}
let notUpdated = UIAlertAction(title: NSLocalizedString("Not updated", comment: ""), style: .default) { _ in
self.historyDataSource.setFilterPredicate { $0.needSync }
self.historyFilter = .notSynced
}
switch self.historyFilter {
case .all: all.setValue(true, forKey: "checked")
case .unrecognized: unrecognized.setValue(true, forKey: "checked")
case .outdated: outdated.setValue(true, forKey: "checked")
case .notSynced: notUpdated.setValue(true, forKey: "checked")
}
sheet.addAction(all)
sheet.addAction(unrecognized)
sheet.addAction(outdated)
sheet.addAction(notUpdated)
sheet.addAction(cancel)
sheet.popoverPresentationController?.barButtonItem = sender
self.present(sheet, animated: true)
}
func shareFile(_ url: URL) {
let activityController = UIActivityViewController(activityItems: [url], applicationActivities: nil)
self.present(activityController, animated: true)
}
func save(file url: URL) {
if #available(iOS 14, *) {
let controller = UIDocumentPickerViewController(forExporting: [url])
self.present(controller, animated: true)
} else {
let controller = UIDocumentPickerViewController(url: url, in: .exportToService)
present(controller, animated: true)
}
}
// MARK: - Checking new number
func checkTapped(number: String) {
let numberNormalized = number.filter { !$0.isWhitespace }.uppercased()
var events: [VehicleEventDto] = []
do {
let realm = try Realm()
if let dbVehicle = realm.object(ofType: Vehicle.self, forPrimaryKey: numberNormalized) {
events.append(contentsOf: dbVehicle.events.map(\.dto))
}
} catch {
print(error)
}
Task {
do {
HUD.show(.progress)
let (vehicle, errors) = try await self.check(number: numberNormalized,
action: .receiveAndSend,
notes: [],
events: events)
if !vehicle.unrecognized && errors.isEmpty {
self.updateDetailController(with: vehicle)
}
HUD.hide()
self.showErrors(errors)
} catch {
HUD.hide()
self.show(error: error)
}
}
}
func updateDetailController(with vehicle: VehicleDto) {
if let splitViewController = self.view.window?.rootViewController as? UISplitViewController
{
Task {
let coordinator = ReportCoordinator(controller: splitViewController, vehicle: vehicle, isPersistent: true)
_ = try? await coordinator.start()
}
}
}
// MARK: - UITableViewDelegate
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let vehicle = self.historyDataSource.item(at: indexPath)
let updateAction = UIContextualAction(style: .normal, title: NSLocalizedString("Update", comment: "")) { action, view, completion in
self.update(vehicle: vehicle)
completion(true)
}
updateAction.image = UIImage(systemName: "arrow.2.circlepath")
updateAction.backgroundColor = .systemBlue
let removeAction = UIContextualAction(style: .destructive, title: NSLocalizedString("Remove", comment: "")) { action, view, completion in
self.remove(vehicle: vehicle)
}
removeAction.image = UIImage(systemName: "trash")
let configuration = UISwipeActionsConfiguration(actions: [updateAction, removeAction])
configuration.performsFirstActionWithFullSwipe = false
return configuration
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vehicle = self.historyDataSource.item(at: indexPath)
self.updateDetailController(with: vehicle)
}
func tableView(_ tableView: UITableView, contextMenuConfigurationForRowAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration? {
let vehicle = self.historyDataSource.item(at: indexPath)
return UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { _ in
let update = UIAction(title: NSLocalizedString("Update", comment: ""), image: UIImage(systemName: "arrow.2.circlepath")) { action in
self.update(vehicle: vehicle)
}
let remove = UIAction(title: NSLocalizedString("Remove", comment: ""), image: UIImage(systemName: "trash"), attributes: [.destructive]) { action in
self.remove(vehicle: vehicle)
}
return UIMenu(title: NSLocalizedString("Actions", comment: ""), children: [update, remove])
}
}
// MARK: - UISearchResultsUpdating
func updateSearchResults(for searchController: UISearchController) {
guard let text = searchController.searchBar.text?.uppercased(),
!text.isEmpty
else {
historyDataSource.setSearchPredicate(nil)
return
}
let regex = try? NSRegularExpression(pattern: text)
historyDataSource.setSearchPredicate { vehicle in
let number = vehicle.getNumber()
if let regex {
let range = NSRange(location: 0, length: number.utf16.count)
return regex.numberOfMatches(in: number, range: range) > 0
} else {
return number.contains(text)
}
}
}
// MARK: - Contextual actions
func update(vehicle: VehicleDto) {
Task {
do {
HUD.show(.progress)
let (vehicle, errors) = try await self.check(number: vehicle.getNumber(),
action: .doNotSend,
notes: Array(vehicle.notes),
events: Array(vehicle.events),
force: true)
if !vehicle.unrecognized {
self.updateDetailController(with: vehicle)
}
HUD.hide()
self.showErrors(errors)
} catch {
HUD.hide()
self.show(error: error)
}
}
}
func remove(vehicle: VehicleDto) {
guard let realm = try? Realm() else { return }
guard let realmVehicle = realm.object(ofType: Vehicle.self, forPrimaryKey: vehicle.getNumber()) else { return }
do {
try realm.write {
realm.delete(realmVehicle)
}
} catch {
print(error)
}
}
// MARK: - Checking number
func save(vehicle: VehicleDto) throws {
let realm = try Realm()
try realm.write {
realm.add(Vehicle(dto: vehicle), update: .all)
}
}
func getEvent(for action: EventAction) async throws -> VehicleEventDto {
if let event = await RxLocationManager.getLastEvent(), (Date().timeIntervalSince1970 - event.date) < 100 {
return event
} else {
return try await RxLocationManager.requestCurrentLocation()
}
}
func prepareEvent(for action: EventAction) async -> (event: VehicleEventDto?, error: Error?) {
guard action != .doNotSend else {
return (event: nil, error: nil)
}
do {
var event = try await getEvent(for: action)
event.address = try? await RxLocationManager.getAddressForLocation(latitude: event.latitude,
longitude: event.longitude)
return (event: event, error: nil)
} catch {
return (event: nil, error: error)
}
}
func checkVehicle(number: String,
notes: [VehicleNoteDto],
events: [VehicleEventDto],
force: Bool = false) async -> (vehicle: VehicleDto, error: Error?) {
do {
let vehicle = try await ApiService.shared.checkVehicle(by: number, notes: notes, events: events, force: force)
try self.save(vehicle: vehicle)
return (vehicle: vehicle, error: nil)
} catch {
let realm = try? await Realm()
if let existingVehicle = realm?.object(ofType: Vehicle.self, forPrimaryKey: number) {
return (vehicle: existingVehicle.dto, error: error)
} else {
let vehicle = Vehicle(number)
try? realm?.write { realm?.add(vehicle, update: .all) }
return (vehicle: vehicle.dto, error: error)
}
}
}
func check(number: String,
action: EventAction,
notes: [VehicleNoteDto],
events: [VehicleEventDto],
force: Bool = false) async throws -> (vehicle: VehicleDto, errors: [Error]) {
async let eventTask = prepareEvent(for: action)
async let vehicleTask = checkVehicle(number: number, notes: notes, events: events, force: force)
let (eventResult, vehicleResult) = await (eventTask, vehicleTask)
var errors = [eventResult.error, vehicleResult.error].map { error -> Error? in
if let clerror = error as? CLError {
if clerror.code != .denied {
return CocoaError.error(NSLocalizedString("Location error", comment: ""), reason: clerror.code.description)
} else {
return nil
}
} else {
return error
}
}
.compactMap { $0 }
RxLocationManager.resetLastEvent()
let realm = try await Realm()
let dbVehicle = realm.object(ofType: Vehicle.self, forPrimaryKey: vehicleResult.vehicle.getNumber())
if let event = eventResult.event, let vehicle = dbVehicle {
try realm.write {
vehicle.events.append(VehicleEvent(dto: event))
vehicle.updatedDate = Date().timeIntervalSince1970
vehicle.synchronized = false
}
}
if vehicleResult.error != nil {
return (vehicle: vehicleResult.vehicle, errors: errors)
} else {
if let event = eventResult.event {
do {
let vehicle = try await ApiService.shared.add(event: event, to: vehicleResult.vehicle.getNumber())
try self.save(vehicle: vehicle)
return (vehicle: vehicle, errors: errors)
} catch {
errors.append(error)
return (vehicle: vehicleResult.vehicle, errors: errors)
}
} else {
return (vehicle: vehicleResult.vehicle, errors: errors)
}
}
}
func showErrors(_ errors: [Error]) {
Task {
for error in errors {
await asyncShowError(error)
}
}
}
func asyncShowError(_ error: Error) async {
await withCheckedContinuation { continuation in
self.show(error: error, animated: true) {
continuation.resume()
}
}
}
}

View File

@ -99,25 +99,6 @@
</array> </array>
</dict> </dict>
</dict> </dict>
<key>UIApplicationShortcutItems</key>
<array>
<dict>
<key>UIApplicationShortcutItemIconType</key>
<string>UIApplicationShortcutIconTypeAudio</string>
<key>UIApplicationShortcutItemTitle</key>
<string>Add voice record</string>
<key>UIApplicationShortcutItemType</key>
<string>AddVoiceRecordAction</string>
</dict>
<dict>
<key>UIApplicationShortcutItemIconType</key>
<string>UIApplicationShortcutIconTypeCompose</string>
<key>UIApplicationShortcutItemTitle</key>
<string>Check plate number</string>
<key>UIApplicationShortcutItemType</key>
<string>CheckNumberAction</string>
</dict>
</array>
<key>UILaunchStoryboardName</key> <key>UILaunchStoryboardName</key>
<string>LaunchScreen</string> <string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key> <key>UIRequiredDeviceCapabilities</key>

View File

@ -17,9 +17,6 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
guard let ad = UIApplication.shared.delegate as? AppDelegate else { return } guard let ad = UIApplication.shared.delegate as? AppDelegate else { return }
if let activity = connectionOptions.userActivities.first { if let activity = connectionOptions.userActivities.first {
if activity.activityType == "pro.aliencat.autocat.addVoiceRecord" {
ad.quickAction = .addVoiceRecord
}
if let url = activity.webpageURL { if let url = activity.webpageURL {
if let param = URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems?.first, let token = param.value { if let param = URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems?.first, let token = param.value {
@ -144,33 +141,10 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
} }
func windowScene(_ windowScene: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) { func windowScene(_ windowScene: UIWindowScene, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: @escaping (Bool) -> Void) {
guard let ad = UIApplication.shared.delegate as? AppDelegate else { return }
if shortcutItem.type == "CheckNumberAction" {
ad.quickAction = .check
if let split = self.window?.rootViewController as? MainSplitController, let tabvc = split.viewControllers.first as? UITabBarController {
if tabvc.selectedIndex == 0 {
if let nav = tabvc.selectedViewController as? UINavigationController, let child = nav.topViewController {
if let check = child as? CheckController {
Task { await check.handleQuickActions() }
} else {
nav.popToRootViewController(animated: false)
}
}
} else {
tabvc.selectedIndex = 0
}
}
} else if shortcutItem.type == "AddVoiceRecordAction" {
self.handleAddVoiceRecordAction()
}
} }
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) { func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
if userActivity.activityType == "pro.aliencat.autocat.addVoiceRecord" {
self.handleAddVoiceRecordAction()
}
if let url = userActivity.webpageURL { if let url = userActivity.webpageURL {
if let param = URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems?.first, let token = param.value { if let param = URLComponents(url: url, resolvingAgainstBaseURL: false)?.queryItems?.first, let token = param.value {
@ -181,25 +155,6 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
} }
} }
func handleAddVoiceRecordAction() {
guard let ad = UIApplication.shared.delegate as? AppDelegate else { return }
ad.quickAction = .addVoiceRecord
if let split = self.window?.rootViewController as? MainSplitController, let tabvc = split.viewControllers.first as? UITabBarController {
if tabvc.selectedIndex == 1 {
if let nav = tabvc.selectedViewController as? UINavigationController, let child = nav.topViewController {
if let record = child as? RecordsController {
record.handleQuickActions()
} else {
nav.popToRootViewController(animated: false)
}
}
} else {
tabvc.selectedIndex = 1
}
}
}
func openReport(with number: String) async { func openReport(with number: String) async {
guard let rootController = self.window?.rootViewController else { return } guard let rootController = self.window?.rootViewController else { return }

View File

@ -0,0 +1,34 @@
//
// HistoryFilter.swift
// AutoCat
//
// Created by Selim Mustafaev on 09.02.2025.
// Copyright © 2025 Selim Mustafaev. All rights reserved.
//
import Foundation
enum HistoryFilter: CaseIterable, Identifiable {
case all
case unrecognized
case outdated
case notSynced
var title: String {
switch self {
case .all: return NSLocalizedString("All", comment: "");
case .unrecognized: return NSLocalizedString("Unrecognized", comment: "");
case .outdated: return NSLocalizedString("Outdated", comment: "");
case .notSynced: return NSLocalizedString("Not updated", comment: "");
}
}
var id: Int {
switch self {
case .all: return 0;
case .unrecognized: return 1;
case .outdated: return 2;
case .notSynced: return 3;
}
}
}