Fixing issue with laggy update of history tableview.

Adding history export feature
This commit is contained in:
Selim Mustafaev 2021-03-28 21:28:08 +03:00
parent dec2c38bbd
commit 913a2cd85c
11 changed files with 222 additions and 95 deletions

View File

@ -111,6 +111,7 @@
7AE26A3324EEF9EC00625033 /* UIViewControllerExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE26A3224EEF9EC00625033 /* UIViewControllerExt.swift */; }; 7AE26A3324EEF9EC00625033 /* UIViewControllerExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE26A3224EEF9EC00625033 /* UIViewControllerExt.swift */; };
7AE26A3524F31B0700625033 /* EventsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE26A3424F31B0700625033 /* EventsController.swift */; }; 7AE26A3524F31B0700625033 /* EventsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE26A3424F31B0700625033 /* EventsController.swift */; };
7AE492A1259232F000322D2E /* MultilineLinkRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE492A0259232F000322D2E /* MultilineLinkRow.swift */; }; 7AE492A1259232F000322D2E /* MultilineLinkRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE492A0259232F000322D2E /* MultilineLinkRow.swift */; };
7AE8424E26109F78002F6B31 /* Exportable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE8424D26109F78002F6B31 /* Exportable.swift */; };
7AEFC3BE2529D3CC00BADFB2 /* ConfigurableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AEFC3BD2529D3CC00BADFB2 /* ConfigurableCell.swift */; }; 7AEFC3BE2529D3CC00BADFB2 /* ConfigurableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AEFC3BD2529D3CC00BADFB2 /* ConfigurableCell.swift */; };
7AEFE728240455E200910EB7 /* SettingsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AEFE727240455E200910EB7 /* SettingsController.swift */; }; 7AEFE728240455E200910EB7 /* SettingsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AEFE727240455E200910EB7 /* SettingsController.swift */; };
7AF12B1D258C9CFF0090F8B8 /* Cloneable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF12B1C258C9CFF0090F8B8 /* Cloneable.swift */; }; 7AF12B1D258C9CFF0090F8B8 /* Cloneable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AF12B1C258C9CFF0090F8B8 /* Cloneable.swift */; };
@ -219,6 +220,7 @@
7AE26A3224EEF9EC00625033 /* UIViewControllerExt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIViewControllerExt.swift; sourceTree = "<group>"; }; 7AE26A3224EEF9EC00625033 /* UIViewControllerExt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIViewControllerExt.swift; sourceTree = "<group>"; };
7AE26A3424F31B0700625033 /* EventsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventsController.swift; sourceTree = "<group>"; }; 7AE26A3424F31B0700625033 /* EventsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EventsController.swift; sourceTree = "<group>"; };
7AE492A0259232F000322D2E /* MultilineLinkRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultilineLinkRow.swift; sourceTree = "<group>"; }; 7AE492A0259232F000322D2E /* MultilineLinkRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultilineLinkRow.swift; sourceTree = "<group>"; };
7AE8424D26109F78002F6B31 /* Exportable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Exportable.swift; sourceTree = "<group>"; };
7AEFC3BD2529D3CC00BADFB2 /* ConfigurableCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurableCell.swift; sourceTree = "<group>"; }; 7AEFC3BD2529D3CC00BADFB2 /* ConfigurableCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConfigurableCell.swift; sourceTree = "<group>"; };
7AEFE727240455E200910EB7 /* SettingsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsController.swift; sourceTree = "<group>"; }; 7AEFE727240455E200910EB7 /* SettingsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsController.swift; sourceTree = "<group>"; };
7AF12B1C258C9CFF0090F8B8 /* Cloneable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Cloneable.swift; sourceTree = "<group>"; }; 7AF12B1C258C9CFF0090F8B8 /* Cloneable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Cloneable.swift; sourceTree = "<group>"; };
@ -299,25 +301,25 @@
7A1146FF23FDE7E500B424AF /* AutoCat */ = { 7A1146FF23FDE7E500B424AF /* AutoCat */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
7A0420B825693CEE00034941 /* JS */, 7A530B7C24017FBE00CBFE6E /* Cells */,
7A11471423FDEAF800B424AF /* Controllers */,
7A3F07A924360D9100E59687 /* Extensions */, 7A3F07A924360D9100E59687 /* Extensions */,
7A6DD90424326788009DE740 /* Fonts */, 7A6DD90424326788009DE740 /* Fonts */,
7A6DD901242BF48D009DE740 /* Views */, 7A0420B825693CEE00034941 /* JS */,
7A530B7C24017FBE00CBFE6E /* Cells */,
7A11474523FF2A9000B424AF /* Models */, 7A11474523FF2A9000B424AF /* Models */,
7A11474223FF06B600B424AF /* Utils */,
7A11472C23FECA3E00B424AF /* ThirdParty */, 7A11472C23FECA3E00B424AF /* ThirdParty */,
7A11471423FDEAF800B424AF /* Controllers */, 7A11474223FF06B600B424AF /* Utils */,
7A6DD901242BF48D009DE740 /* Views */,
7A64AE6B2469DC6900ABE48E /* AutoCat.entitlements */,
7A11470E23FDE7E600B424AF /* Info.plist */,
7A11470023FDE7E500B424AF /* AppDelegate.swift */, 7A11470023FDE7E500B424AF /* AppDelegate.swift */,
7A11470223FDE7E500B424AF /* SceneDelegate.swift */, 7A11470223FDE7E500B424AF /* SceneDelegate.swift */,
7A11470623FDE7E500B424AF /* Main.storyboard */,
7A11470923FDE7E600B424AF /* Assets.xcassets */, 7A11470923FDE7E600B424AF /* Assets.xcassets */,
7A61FF8F2575A5B300D905D5 /* InfoPlist.strings */,
7A11470B23FDE7E600B424AF /* LaunchScreen.storyboard */, 7A11470B23FDE7E600B424AF /* LaunchScreen.storyboard */,
7A11470E23FDE7E600B424AF /* Info.plist */,
7A64AE6B2469DC6900ABE48E /* AutoCat.entitlements */,
7A61FF892575A2CD00D905D5 /* Localizable.strings */, 7A61FF892575A2CD00D905D5 /* Localizable.strings */,
7A61FFA2257D3CFC00D905D5 /* Localizable.stringsdict */, 7A61FFA2257D3CFC00D905D5 /* Localizable.stringsdict */,
7A61FF8F2575A5B300D905D5 /* InfoPlist.strings */, 7A11470623FDE7E500B424AF /* Main.storyboard */,
); );
path = AutoCat; path = AutoCat;
sourceTree = "<group>"; sourceTree = "<group>";
@ -373,21 +375,21 @@
7A11474523FF2A9000B424AF /* Models */ = { 7A11474523FF2A9000B424AF /* Models */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
7A11474623FF2AA500B424AF /* User.swift */, 7A659B5824A2B1BA0043A0F2 /* AudioRecord.swift */,
7AF12B1C258C9CFF0090F8B8 /* Cloneable.swift */,
7A0516192414FF0900FC55AC /* DateSection.swift */,
7A8AB76725A0DC8200ECF2C1 /* DebugInfo.swift */,
7A333813249A532400D878F1 /* Filter.swift */,
7A0420A925619AEC00034941 /* Osago.swift */,
6841A913FABBB0AB20DEF4FC /* PagedResponse.swift */,
7A6DD90D24337930009DE740 /* PlateNumber.swift */,
7A11474823FF2B2D00B424AF /* Response.swift */, 7A11474823FF2B2D00B424AF /* Response.swift */,
7A11474A23FF368B00B424AF /* Settings.swift */, 7A11474A23FF368B00B424AF /* Settings.swift */,
7A11474623FF2AA500B424AF /* User.swift */,
7A530B7F2401803A00CBFE6E /* Vehicle.swift */, 7A530B7F2401803A00CBFE6E /* Vehicle.swift */,
7A0516192414FF0900FC55AC /* DateSection.swift */,
7A6DD90D24337930009DE740 /* PlateNumber.swift */,
7A333813249A532400D878F1 /* Filter.swift */,
7AB562B9249C9E9B00473D53 /* VehicleRegion.swift */,
7A659B5824A2B1BA0043A0F2 /* AudioRecord.swift */,
7AAE6AD224CDDF950023860B /* VehicleEvent.swift */,
7A0420A925619AEC00034941 /* Osago.swift */,
7A2DE69725868AC800A113FC /* VehicleAd.swift */, 7A2DE69725868AC800A113FC /* VehicleAd.swift */,
7AF12B1C258C9CFF0090F8B8 /* Cloneable.swift */, 7AAE6AD224CDDF950023860B /* VehicleEvent.swift */,
7A8AB76725A0DC8200ECF2C1 /* DebugInfo.swift */, 7AB562B9249C9E9B00473D53 /* VehicleRegion.swift */,
6841A913FABBB0AB20DEF4FC /* PagedResponse.swift */,
); );
path = Models; path = Models;
sourceTree = "<group>"; sourceTree = "<group>";
@ -406,18 +408,19 @@
7A3F07A924360D9100E59687 /* Extensions */ = { 7A3F07A924360D9100E59687 /* Extensions */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
7A3F07AA24360DC800E59687 /* Dated.swift */, 7A21112924FC3D7E003BBF6F /* AudioEngine.swift */,
7A8A2208248D10EC0073DFD9 /* ResizeImage.swift */, 7A8AB76425A0DB8F00ECF2C1 /* BundleVersion.swift */,
7A8A220A248D67B60073DFD9 /* VehicleReportImage.swift */, 7AE24C5E251F1B4E00758E39 /* Buttons.swift */,
7A27ADF4249FD2F90035F39E /* FileManagerExt.swift */,
7A27ADF824A09CAD0035F39E /* CocoaError.swift */, 7A27ADF824A09CAD0035F39E /* CocoaError.swift */,
7A3F07AA24360DC800E59687 /* Dated.swift */,
7AE8424D26109F78002F6B31 /* Exportable.swift */,
7A27ADF4249FD2F90035F39E /* FileManagerExt.swift */,
7ADF6CA02512244400F237B2 /* MapExt.swift */,
7ADF6C92250B954900F237B2 /* Navigation.swift */,
7A8A2208248D10EC0073DFD9 /* ResizeImage.swift */,
7A659B5A24A3768A0043A0F2 /* Substrings.swift */, 7A659B5A24A3768A0043A0F2 /* Substrings.swift */,
7AE26A3224EEF9EC00625033 /* UIViewControllerExt.swift */, 7AE26A3224EEF9EC00625033 /* UIViewControllerExt.swift */,
7A21112924FC3D7E003BBF6F /* AudioEngine.swift */, 7A8A220A248D67B60073DFD9 /* VehicleReportImage.swift */,
7ADF6C92250B954900F237B2 /* Navigation.swift */,
7ADF6CA02512244400F237B2 /* MapExt.swift */,
7AE24C5E251F1B4E00758E39 /* Buttons.swift */,
7A8AB76425A0DB8F00ECF2C1 /* BundleVersion.swift */,
); );
path = Extensions; path = Extensions;
sourceTree = "<group>"; sourceTree = "<group>";
@ -632,6 +635,7 @@
7A6E03282485951700DB22ED /* OwnersController.swift in Sources */, 7A6E03282485951700DB22ED /* OwnersController.swift in Sources */,
7A64AE742469DFB600ABE48E /* MediaContentView.swift in Sources */, 7A64AE742469DFB600ABE48E /* MediaContentView.swift in Sources */,
7A1090EC24A4E3E100B4F0B2 /* CellProgressView.swift in Sources */, 7A1090EC24A4E3E100B4F0B2 /* CellProgressView.swift in Sources */,
7AE8424E26109F78002F6B31 /* Exportable.swift in Sources */,
7A96AE2D246B2B7400297C33 /* GoogleSignInController.swift in Sources */, 7A96AE2D246B2B7400297C33 /* GoogleSignInController.swift in Sources */,
7A15051224DB3E3000F39631 /* AnyEncodable.swift in Sources */, 7A15051224DB3E3000F39631 /* AnyEncodable.swift in Sources */,
7A1090EA24A3A26300B4F0B2 /* AudioPlayer.swift in Sources */, 7A1090EA24A3A26300B4F0B2 /* AudioPlayer.swift in Sources */,
@ -847,7 +851,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements; CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 71; CURRENT_PROJECT_VERSION = 72;
DEVELOPMENT_TEAM = 46DTTB8X4S; DEVELOPMENT_TEAM = 46DTTB8X4S;
INFOPLIST_FILE = AutoCat/Info.plist; INFOPLIST_FILE = AutoCat/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0; IPHONEOS_DEPLOYMENT_TARGET = 13.0;
@ -871,7 +875,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements; CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 71; CURRENT_PROJECT_VERSION = 72;
DEVELOPMENT_TEAM = 46DTTB8X4S; DEVELOPMENT_TEAM = 46DTTB8X4S;
INFOPLIST_FILE = AutoCat/Info.plist; INFOPLIST_FILE = AutoCat/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0; IPHONEOS_DEPLOYMENT_TARGET = 13.0;

View File

@ -73,8 +73,8 @@
filePath = "AutoCat/Controllers/CheckController.swift" filePath = "AutoCat/Controllers/CheckController.swift"
startingColumnNumber = "9223372036854775807" startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807"
startingLineNumber = "345" startingLineNumber = "390"
endingLineNumber = "345" endingLineNumber = "390"
landmarkName = "check(number:action:force:)" landmarkName = "check(number:action:force:)"
landmarkType = "7"> landmarkType = "7">
</BreakpointContent> </BreakpointContent>
@ -89,8 +89,8 @@
filePath = "AutoCat/Controllers/CheckController.swift" filePath = "AutoCat/Controllers/CheckController.swift"
startingColumnNumber = "9223372036854775807" startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807"
startingLineNumber = "341" startingLineNumber = "386"
endingLineNumber = "341" endingLineNumber = "386"
landmarkName = "check(number:action:force:)" landmarkName = "check(number:action:force:)"
landmarkType = "7"> landmarkType = "7">
<Locations> <Locations>
@ -137,8 +137,8 @@
filePath = "AutoCat/Controllers/CheckController.swift" filePath = "AutoCat/Controllers/CheckController.swift"
startingColumnNumber = "9223372036854775807" startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807"
startingLineNumber = "309" startingLineNumber = "354"
endingLineNumber = "309" endingLineNumber = "354"
landmarkName = "getEvent(for:)" landmarkName = "getEvent(for:)"
landmarkType = "7"> landmarkType = "7">
</BreakpointContent> </BreakpointContent>
@ -153,8 +153,8 @@
filePath = "AutoCat/Controllers/CheckController.swift" filePath = "AutoCat/Controllers/CheckController.swift"
startingColumnNumber = "9223372036854775807" startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807"
startingLineNumber = "304" startingLineNumber = "349"
endingLineNumber = "304" endingLineNumber = "349"
landmarkName = "getEvent(for:)" landmarkName = "getEvent(for:)"
landmarkType = "7"> landmarkType = "7">
</BreakpointContent> </BreakpointContent>
@ -169,8 +169,8 @@
filePath = "AutoCat/Controllers/CheckController.swift" filePath = "AutoCat/Controllers/CheckController.swift"
startingColumnNumber = "9223372036854775807" startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807"
startingLineNumber = "336" startingLineNumber = "381"
endingLineNumber = "336" endingLineNumber = "381"
landmarkName = "check(number:action:force:)" landmarkName = "check(number:action:force:)"
landmarkType = "7"> landmarkType = "7">
<Locations> <Locations>

View File

@ -100,14 +100,14 @@
<color key="backgroundColor" systemColor="systemBackgroundColor"/> <color key="backgroundColor" systemColor="systemBackgroundColor"/>
<prototypes> <prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="EventCell" id="QIb-Hv-tvk" customClass="EventCell" customModule="AutoCat" customModuleProvider="target"> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="EventCell" id="QIb-Hv-tvk" customClass="EventCell" customModule="AutoCat" customModuleProvider="target">
<rect key="frame" x="0.0" y="28" width="375" height="125.5"/> <rect key="frame" x="0.0" y="28" width="375" height="126"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="QIb-Hv-tvk" id="Ypt-ch-fGT"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="QIb-Hv-tvk" id="Ypt-ch-fGT">
<rect key="frame" x="0.0" y="0.0" width="375" height="125.5"/> <rect key="frame" x="0.0" y="0.0" width="375" height="126"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="HP8-oO-yhP"> <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="HP8-oO-yhP">
<rect key="frame" x="8" y="8" width="359" height="109.5"/> <rect key="frame" x="8" y="8" width="359" height="110"/>
<subviews> <subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="xcQ-Wz-gJ0"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="xcQ-Wz-gJ0">
<rect key="frame" x="0.0" y="0.0" width="359" height="50"/> <rect key="frame" x="0.0" y="0.0" width="359" height="50"/>
@ -116,7 +116,7 @@
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="1tQ-zM-6T9"> <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="1tQ-zM-6T9">
<rect key="frame" x="0.0" y="58" width="359" height="51.5"/> <rect key="frame" x="0.0" y="58" width="359" height="52"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleSubhead"/> <fontDescription key="fontDescription" style="UICTFontTextStyleSubhead"/>
<color key="textColor" systemColor="secondaryLabelColor"/> <color key="textColor" systemColor="secondaryLabelColor"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
@ -599,11 +599,18 @@
</constraints> </constraints>
</view> </view>
<navigationItem key="navigationItem" id="IMO-Ew-zSY"> <navigationItem key="navigationItem" id="IMO-Ew-zSY">
<barButtonItem key="rightBarButtonItem" image="line.horizontal.3.decrease" catalog="system" id="L67-Yc-Py6"> <rightBarButtonItems>
<barButtonItem image="line.horizontal.3.decrease" catalog="system" id="L67-Yc-Py6">
<connections> <connections>
<action selector="onFilter:" destination="twc-qR-t1G" id="qfm-0f-hT0"/> <action selector="onFilter:" destination="twc-qR-t1G" id="qfm-0f-hT0"/>
</connections> </connections>
</barButtonItem> </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> </navigationItem>
<connections> <connections>
<outlet property="check" destination="Ync-fd-xQI" id="oxC-p6-Mou"/> <outlet property="check" destination="Ync-fd-xQI" id="oxC-p6-Mou"/>
@ -948,6 +955,7 @@
<image name="search-compact" width="17" height="17"/> <image name="search-compact" width="17" height="17"/>
<image name="settings" width="25" height="25"/> <image name="settings" width="25" height="25"/>
<image name="settings-compact" width="18" height="18"/> <image name="settings-compact" width="18" height="18"/>
<image name="square.and.arrow.up" catalog="system" width="115" height="128"/>
<systemColor name="secondaryLabelColor"> <systemColor name="secondaryLabelColor">
<color red="0.23529411764705882" green="0.23529411764705882" blue="0.2627450980392157" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/> <color red="0.23529411764705882" green="0.23529411764705882" blue="0.2627450980392157" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor> </systemColor>

View File

@ -113,6 +113,81 @@ class CheckController: UIViewController, UITableViewDelegate, UITextFieldDelegat
} }
} }
// 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)
self.shareFile(tmpUrl)
} 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
}
switch self.historyFilter {
case .all: all.setValue(true, forKey: "checked")
case .unrecognized: unrecognized.setValue(true, forKey: "checked")
case .outdated: outdated.setValue(true, forKey: "checked")
}
sheet.addAction(all)
sheet.addAction(unrecognized)
sheet.addAction(outdated)
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) {
print("")
}
print("")
}
// MARK: - Checking new number // MARK: - Checking new number
@IBAction func checkTapped(_ sender: UIButton) { @IBAction func checkTapped(_ sender: UIButton) {
@ -157,36 +232,6 @@ class CheckController: UIViewController, UITableViewDelegate, UITextFieldDelegat
} }
} }
@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
}
switch self.historyFilter {
case .all: all.setValue(true, forKey: "checked")
case .unrecognized: unrecognized.setValue(true, forKey: "checked")
case .outdated: outdated.setValue(true, forKey: "checked")
}
sheet.addAction(all)
sheet.addAction(unrecognized)
sheet.addAction(outdated)
sheet.addAction(cancel)
sheet.popoverPresentationController?.barButtonItem = sender
self.present(sheet, animated: true)
}
// MARK: - UITextFieldDelegate // MARK: - UITextFieldDelegate
@IBAction func textFieldDidBeginEditing(_ textField: UITextField) { @IBAction func textFieldDidBeginEditing(_ textField: UITextField) {

View File

@ -0,0 +1,6 @@
import Foundation
protocol Exportable {
static var csvHeader: String { get }
var csvLine: String { get }
}

View File

@ -12,4 +12,12 @@ extension FileManager {
} }
return folderUrl.appendingPathComponent(file) return folderUrl.appendingPathComponent(file)
} }
func tmpUrl(name: String, ext: String) -> URL {
let formatter = DateFormatter()
formatter.timeStyle = .none
formatter.dateFormat = "dd.MM.yyyy"
let fileName = "\(name)_\(formatter.string(from: Date())).\(ext)"
return URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(fileName)
}
} }

View File

@ -160,7 +160,7 @@ class VehicleOwnershipPeriod: Object, Decodable, Cloneable {
} }
} }
class Vehicle: Object, Decodable, Identifiable, Differentiable, Cloneable { class Vehicle: Object, Decodable, Identifiable, Differentiable, Cloneable, Exportable {
@objc dynamic var brand: VehicleBrand? @objc dynamic var brand: VehicleBrand?
@objc dynamic var model: VehicleModel? @objc dynamic var model: VehicleModel?
@objc dynamic var color: String? @objc dynamic var color: String?
@ -185,10 +185,19 @@ class Vehicle: Object, Decodable, Identifiable, Differentiable, Cloneable {
var ads = List<VehicleAd>() var ads = List<VehicleAd>()
@objc dynamic var debugInfo: DebugInfo? @objc dynamic var debugInfo: DebugInfo?
lazy var formatter: DateFormatter = {
let f = DateFormatter()
f.dateStyle = .medium
f.timeStyle = .medium
return f
}()
var differenceIdentifier: String { self.number } var differenceIdentifier: String { self.number }
func isContentEqual(to source: Vehicle) -> Bool { func isContentEqual(to source: Vehicle) -> Bool {
return self == source return self.number == source.number &&
self.addedDate == source.addedDate &&
self.updatedDate == source.updatedDate
} }
enum CodingKeys: String, CodingKey { enum CodingKeys: String, CodingKey {
@ -278,7 +287,7 @@ class Vehicle: Object, Decodable, Identifiable, Differentiable, Cloneable {
} }
override class func ignoredProperties() -> [String] { override class func ignoredProperties() -> [String] {
return ["id", "identifier", "differenceIdentifier"] return ["id", "identifier", "differenceIdentifier", "formatter"]
} }
var unrecognized: Bool { var unrecognized: Bool {
@ -334,4 +343,17 @@ class Vehicle: Object, Decodable, Identifiable, Differentiable, Cloneable {
ads.append(objectsIn: copy.ads.map { $0.clone() }) ads.append(objectsIn: copy.ads.map { $0.clone() })
self.ads = ads self.ads = ads
} }
// MARK: - Exportable
static var csvHeader: String {
return "Model, Color, Year, Plate Number, VIN, STS, PTS, Added Date, Updated date"
}
var csvLine: String {
let model = self.brand?.name?.original ?? "<unknown>"
let added = self.formatter.string(from: Date(timeIntervalSince1970: self.addedDate))
let updated = self.formatter.string(from: Date(timeIntervalSince1970: self.updatedDate))
return String(format: "\"%@\", %@, %d, %@, %@, %@, %@, \"%@\", \"%@\"", model, self.color ?? "", self.year, self.number, self.vin1 ?? "", self.sts ?? "", self.pts ?? "", added, updated)
}
} }

View File

@ -73,15 +73,39 @@ class RealmSectionedDataSource<Item,Cell>: NSObject, UITableViewDataSource
items = items.filter(predicate) items = items.filter(predicate)
} }
DispatchQueue.global().async {
let newSections = items.groupedByDate() let newSections = items.groupedByDate()
let changeset = StagedChangeset(source: self.sections, target: newSections) let changeset = StagedChangeset(source: self.sections, target: newSections)
DispatchQueue.main.async {
self.tv.reload(using: changeset, with: animated ? .fade : .none) { newSects in self.tv.reload(using: changeset, with: animated ? .fade : .none) { newSects in
self.sections = newSects self.sections = newSects
} }
} }
}
}
func setFilterPredicate(_ predicate: FilterPredicate<Item>?) { func setFilterPredicate(_ predicate: FilterPredicate<Item>?) {
self.filterPredicate = predicate self.filterPredicate = predicate
self.reload() self.reload()
} }
func makeCsv() throws -> String {
guard let type = Item.self as? Exportable.Type else {
throw CocoaError.error("Type \(Item.self) is not exportable")
}
var result = ""
let newLine: Character = "\r\n" //"\u{000B}"
result.append(type.csvHeader)
result.append(newLine)
for item in self.data {
if let exportableItem = item as? Exportable {
result.append(exportableItem.csvLine)
result.append(newLine)
}
}
return result
}
} }

View File

@ -63,13 +63,17 @@ class RxSectionedDataSource<Item,Cell>: NSObject, UITableViewDataSource where I
} }
self.pageToken = data.pageToken self.pageToken = data.pageToken
DispatchQueue.global().async {
let newSections = self.items.groupedByDate(type: self.sortParam) let newSections = self.items.groupedByDate(type: self.sortParam)
let changeset = StagedChangeset(source: self.sections, target: newSections) let changeset = StagedChangeset(source: self.sections, target: newSections)
DispatchQueue.main.async {
self.tv.reload(using: changeset, with: .automatic) { newSects in self.tv.reload(using: changeset, with: .automatic) { newSects in
self.sections = newSects self.sections = newSects
} }
} }
} }
}
}
func needMoreData() -> Bool { func needMoreData() -> Bool {
guard let count = self.count else { return true } guard let count = self.count else { return true }

View File

@ -79,7 +79,6 @@ class PNButton: UIButton {
} }
@objc func buttonDown(_ sender: PNButton) { @objc func buttonDown(_ sender: PNButton) {
print("buttonDown")
sender.layer.opacity = 0.3 sender.layer.opacity = 0.3
self.timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true, block: { _ in self.timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true, block: { _ in
self.waitCount += 1 self.waitCount += 1
@ -90,7 +89,6 @@ class PNButton: UIButton {
} }
@objc func buttonUp(_ sender: PNButton) { @objc func buttonUp(_ sender: PNButton) {
print("buttonUp")
sender.layer.opacity = 1 sender.layer.opacity = 1
self.timer?.invalidate() self.timer?.invalidate()
self.timer = nil self.timer = nil
@ -98,7 +96,6 @@ class PNButton: UIButton {
} }
@objc func touchUpInside(_ sender: PNButton) { @objc func touchUpInside(_ sender: PNButton) {
print("touchUpInside")
self.delegate?.buttonTapped(self) self.delegate?.buttonTapped(self)
} }

View File

@ -106,6 +106,12 @@
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"Copy to pasteboard" = "Копировать в буфер обмена"; "Copy to pasteboard" = "Копировать в буфер обмена";
/* export as CSV table */
"CSV table" = "таблицу в формате CSV";
/* export as database file */
"Database file" = "файл базы данных";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"Date and time" = "Дата и время"; "Date and time" = "Дата и время";
@ -148,6 +154,9 @@
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"Events" = "События"; "Events" = "События";
/* No comment provided by engineer. */
"Export history as" = "Экспортировать историю как";
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"Filter check history" = "Фильтр истории поиска"; "Filter check history" = "Фильтр истории поиска";
@ -394,7 +403,7 @@
/* No comment provided by engineer. */ /* No comment provided by engineer. */
"When enabled, you will hear short sound before starting audio recording. This will only work when audio record is started via Siri" = "Если включено, вы услышите короткий звуковой сигнал перед началом записи аудио."; "When enabled, you will hear short sound before starting audio recording. This will only work when audio record is started via Siri" = "Если включено, вы услышите короткий звуковой сигнал перед началом записи аудио.";
/* No comment provided by engineer. */ /* Manufacturing year */
"Year" = "Год"; "Year" = "Год";
/* No comment provided by engineer. */ /* No comment provided by engineer. */