Fixing issue with laggy update of history tableview.
Adding history export feature
This commit is contained in:
parent
dec2c38bbd
commit
913a2cd85c
@ -111,6 +111,7 @@
|
||||
7AE26A3324EEF9EC00625033 /* UIViewControllerExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE26A3224EEF9EC00625033 /* UIViewControllerExt.swift */; };
|
||||
7AE26A3524F31B0700625033 /* EventsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE26A3424F31B0700625033 /* EventsController.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 */; };
|
||||
7AEFE728240455E200910EB7 /* SettingsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AEFE727240455E200910EB7 /* SettingsController.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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@ -299,25 +301,25 @@
|
||||
7A1146FF23FDE7E500B424AF /* AutoCat */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7A0420B825693CEE00034941 /* JS */,
|
||||
7A530B7C24017FBE00CBFE6E /* Cells */,
|
||||
7A11471423FDEAF800B424AF /* Controllers */,
|
||||
7A3F07A924360D9100E59687 /* Extensions */,
|
||||
7A6DD90424326788009DE740 /* Fonts */,
|
||||
7A6DD901242BF48D009DE740 /* Views */,
|
||||
7A530B7C24017FBE00CBFE6E /* Cells */,
|
||||
7A0420B825693CEE00034941 /* JS */,
|
||||
7A11474523FF2A9000B424AF /* Models */,
|
||||
7A11474223FF06B600B424AF /* Utils */,
|
||||
7A11472C23FECA3E00B424AF /* ThirdParty */,
|
||||
7A11471423FDEAF800B424AF /* Controllers */,
|
||||
7A11474223FF06B600B424AF /* Utils */,
|
||||
7A6DD901242BF48D009DE740 /* Views */,
|
||||
7A64AE6B2469DC6900ABE48E /* AutoCat.entitlements */,
|
||||
7A11470E23FDE7E600B424AF /* Info.plist */,
|
||||
7A11470023FDE7E500B424AF /* AppDelegate.swift */,
|
||||
7A11470223FDE7E500B424AF /* SceneDelegate.swift */,
|
||||
7A11470623FDE7E500B424AF /* Main.storyboard */,
|
||||
7A11470923FDE7E600B424AF /* Assets.xcassets */,
|
||||
7A61FF8F2575A5B300D905D5 /* InfoPlist.strings */,
|
||||
7A11470B23FDE7E600B424AF /* LaunchScreen.storyboard */,
|
||||
7A11470E23FDE7E600B424AF /* Info.plist */,
|
||||
7A64AE6B2469DC6900ABE48E /* AutoCat.entitlements */,
|
||||
7A61FF892575A2CD00D905D5 /* Localizable.strings */,
|
||||
7A61FFA2257D3CFC00D905D5 /* Localizable.stringsdict */,
|
||||
7A61FF8F2575A5B300D905D5 /* InfoPlist.strings */,
|
||||
7A11470623FDE7E500B424AF /* Main.storyboard */,
|
||||
);
|
||||
path = AutoCat;
|
||||
sourceTree = "<group>";
|
||||
@ -373,21 +375,21 @@
|
||||
7A11474523FF2A9000B424AF /* Models */ = {
|
||||
isa = PBXGroup;
|
||||
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 */,
|
||||
7A11474A23FF368B00B424AF /* Settings.swift */,
|
||||
7A11474623FF2AA500B424AF /* User.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 */,
|
||||
7AF12B1C258C9CFF0090F8B8 /* Cloneable.swift */,
|
||||
7A8AB76725A0DC8200ECF2C1 /* DebugInfo.swift */,
|
||||
6841A913FABBB0AB20DEF4FC /* PagedResponse.swift */,
|
||||
7AAE6AD224CDDF950023860B /* VehicleEvent.swift */,
|
||||
7AB562B9249C9E9B00473D53 /* VehicleRegion.swift */,
|
||||
);
|
||||
path = Models;
|
||||
sourceTree = "<group>";
|
||||
@ -406,18 +408,19 @@
|
||||
7A3F07A924360D9100E59687 /* Extensions */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7A3F07AA24360DC800E59687 /* Dated.swift */,
|
||||
7A8A2208248D10EC0073DFD9 /* ResizeImage.swift */,
|
||||
7A8A220A248D67B60073DFD9 /* VehicleReportImage.swift */,
|
||||
7A27ADF4249FD2F90035F39E /* FileManagerExt.swift */,
|
||||
7A21112924FC3D7E003BBF6F /* AudioEngine.swift */,
|
||||
7A8AB76425A0DB8F00ECF2C1 /* BundleVersion.swift */,
|
||||
7AE24C5E251F1B4E00758E39 /* Buttons.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 */,
|
||||
7AE26A3224EEF9EC00625033 /* UIViewControllerExt.swift */,
|
||||
7A21112924FC3D7E003BBF6F /* AudioEngine.swift */,
|
||||
7ADF6C92250B954900F237B2 /* Navigation.swift */,
|
||||
7ADF6CA02512244400F237B2 /* MapExt.swift */,
|
||||
7AE24C5E251F1B4E00758E39 /* Buttons.swift */,
|
||||
7A8AB76425A0DB8F00ECF2C1 /* BundleVersion.swift */,
|
||||
7A8A220A248D67B60073DFD9 /* VehicleReportImage.swift */,
|
||||
);
|
||||
path = Extensions;
|
||||
sourceTree = "<group>";
|
||||
@ -632,6 +635,7 @@
|
||||
7A6E03282485951700DB22ED /* OwnersController.swift in Sources */,
|
||||
7A64AE742469DFB600ABE48E /* MediaContentView.swift in Sources */,
|
||||
7A1090EC24A4E3E100B4F0B2 /* CellProgressView.swift in Sources */,
|
||||
7AE8424E26109F78002F6B31 /* Exportable.swift in Sources */,
|
||||
7A96AE2D246B2B7400297C33 /* GoogleSignInController.swift in Sources */,
|
||||
7A15051224DB3E3000F39631 /* AnyEncodable.swift in Sources */,
|
||||
7A1090EA24A3A26300B4F0B2 /* AudioPlayer.swift in Sources */,
|
||||
@ -847,7 +851,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 71;
|
||||
CURRENT_PROJECT_VERSION = 72;
|
||||
DEVELOPMENT_TEAM = 46DTTB8X4S;
|
||||
INFOPLIST_FILE = AutoCat/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
@ -871,7 +875,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 71;
|
||||
CURRENT_PROJECT_VERSION = 72;
|
||||
DEVELOPMENT_TEAM = 46DTTB8X4S;
|
||||
INFOPLIST_FILE = AutoCat/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
|
||||
@ -73,8 +73,8 @@
|
||||
filePath = "AutoCat/Controllers/CheckController.swift"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "345"
|
||||
endingLineNumber = "345"
|
||||
startingLineNumber = "390"
|
||||
endingLineNumber = "390"
|
||||
landmarkName = "check(number:action:force:)"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
@ -89,8 +89,8 @@
|
||||
filePath = "AutoCat/Controllers/CheckController.swift"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "341"
|
||||
endingLineNumber = "341"
|
||||
startingLineNumber = "386"
|
||||
endingLineNumber = "386"
|
||||
landmarkName = "check(number:action:force:)"
|
||||
landmarkType = "7">
|
||||
<Locations>
|
||||
@ -137,8 +137,8 @@
|
||||
filePath = "AutoCat/Controllers/CheckController.swift"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "309"
|
||||
endingLineNumber = "309"
|
||||
startingLineNumber = "354"
|
||||
endingLineNumber = "354"
|
||||
landmarkName = "getEvent(for:)"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
@ -153,8 +153,8 @@
|
||||
filePath = "AutoCat/Controllers/CheckController.swift"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "304"
|
||||
endingLineNumber = "304"
|
||||
startingLineNumber = "349"
|
||||
endingLineNumber = "349"
|
||||
landmarkName = "getEvent(for:)"
|
||||
landmarkType = "7">
|
||||
</BreakpointContent>
|
||||
@ -169,8 +169,8 @@
|
||||
filePath = "AutoCat/Controllers/CheckController.swift"
|
||||
startingColumnNumber = "9223372036854775807"
|
||||
endingColumnNumber = "9223372036854775807"
|
||||
startingLineNumber = "336"
|
||||
endingLineNumber = "336"
|
||||
startingLineNumber = "381"
|
||||
endingLineNumber = "381"
|
||||
landmarkName = "check(number:action:force:)"
|
||||
landmarkType = "7">
|
||||
<Locations>
|
||||
|
||||
@ -100,14 +100,14 @@
|
||||
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
|
||||
<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">
|
||||
<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"/>
|
||||
<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"/>
|
||||
<subviews>
|
||||
<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>
|
||||
<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"/>
|
||||
@ -116,7 +116,7 @@
|
||||
<nil key="highlightedColor"/>
|
||||
</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">
|
||||
<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"/>
|
||||
<color key="textColor" systemColor="secondaryLabelColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
@ -599,11 +599,18 @@
|
||||
</constraints>
|
||||
</view>
|
||||
<navigationItem key="navigationItem" id="IMO-Ew-zSY">
|
||||
<barButtonItem key="rightBarButtonItem" 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>
|
||||
<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="check" destination="Ync-fd-xQI" id="oxC-p6-Mou"/>
|
||||
@ -948,6 +955,7 @@
|
||||
<image name="search-compact" width="17" height="17"/>
|
||||
<image name="settings" width="25" height="25"/>
|
||||
<image name="settings-compact" width="18" height="18"/>
|
||||
<image name="square.and.arrow.up" catalog="system" width="115" height="128"/>
|
||||
<systemColor name="secondaryLabelColor">
|
||||
<color red="0.23529411764705882" green="0.23529411764705882" blue="0.2627450980392157" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</systemColor>
|
||||
|
||||
@ -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
|
||||
|
||||
@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
|
||||
|
||||
@IBAction func textFieldDidBeginEditing(_ textField: UITextField) {
|
||||
|
||||
6
AutoCat/Extensions/Exportable.swift
Normal file
6
AutoCat/Extensions/Exportable.swift
Normal file
@ -0,0 +1,6 @@
|
||||
import Foundation
|
||||
|
||||
protocol Exportable {
|
||||
static var csvHeader: String { get }
|
||||
var csvLine: String { get }
|
||||
}
|
||||
@ -12,4 +12,12 @@ extension FileManager {
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 model: VehicleModel?
|
||||
@objc dynamic var color: String?
|
||||
@ -185,10 +185,19 @@ class Vehicle: Object, Decodable, Identifiable, Differentiable, Cloneable {
|
||||
var ads = List<VehicleAd>()
|
||||
@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 }
|
||||
|
||||
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 {
|
||||
@ -278,7 +287,7 @@ class Vehicle: Object, Decodable, Identifiable, Differentiable, Cloneable {
|
||||
}
|
||||
|
||||
override class func ignoredProperties() -> [String] {
|
||||
return ["id", "identifier", "differenceIdentifier"]
|
||||
return ["id", "identifier", "differenceIdentifier", "formatter"]
|
||||
}
|
||||
|
||||
var unrecognized: Bool {
|
||||
@ -334,4 +343,17 @@ class Vehicle: Object, Decodable, Identifiable, Differentiable, Cloneable {
|
||||
ads.append(objectsIn: copy.ads.map { $0.clone() })
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,10 +73,14 @@ class RealmSectionedDataSource<Item,Cell>: NSObject, UITableViewDataSource
|
||||
items = items.filter(predicate)
|
||||
}
|
||||
|
||||
let newSections = items.groupedByDate()
|
||||
let changeset = StagedChangeset(source: self.sections, target: newSections)
|
||||
self.tv.reload(using: changeset, with: animated ? .fade : .none) { newSects in
|
||||
self.sections = newSects
|
||||
DispatchQueue.global().async {
|
||||
let newSections = items.groupedByDate()
|
||||
let changeset = StagedChangeset(source: self.sections, target: newSections)
|
||||
DispatchQueue.main.async {
|
||||
self.tv.reload(using: changeset, with: animated ? .fade : .none) { newSects in
|
||||
self.sections = newSects
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,4 +88,24 @@ class RealmSectionedDataSource<Item,Cell>: NSObject, UITableViewDataSource
|
||||
self.filterPredicate = predicate
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,10 +63,14 @@ class RxSectionedDataSource<Item,Cell>: NSObject, UITableViewDataSource where I
|
||||
}
|
||||
self.pageToken = data.pageToken
|
||||
|
||||
let newSections = self.items.groupedByDate(type: self.sortParam)
|
||||
let changeset = StagedChangeset(source: self.sections, target: newSections)
|
||||
self.tv.reload(using: changeset, with: .automatic) { newSects in
|
||||
self.sections = newSects
|
||||
DispatchQueue.global().async {
|
||||
let newSections = self.items.groupedByDate(type: self.sortParam)
|
||||
let changeset = StagedChangeset(source: self.sections, target: newSections)
|
||||
DispatchQueue.main.async {
|
||||
self.tv.reload(using: changeset, with: .automatic) { newSects in
|
||||
self.sections = newSects
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,7 +79,6 @@ class PNButton: UIButton {
|
||||
}
|
||||
|
||||
@objc func buttonDown(_ sender: PNButton) {
|
||||
print("buttonDown")
|
||||
sender.layer.opacity = 0.3
|
||||
self.timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true, block: { _ in
|
||||
self.waitCount += 1
|
||||
@ -90,7 +89,6 @@ class PNButton: UIButton {
|
||||
}
|
||||
|
||||
@objc func buttonUp(_ sender: PNButton) {
|
||||
print("buttonUp")
|
||||
sender.layer.opacity = 1
|
||||
self.timer?.invalidate()
|
||||
self.timer = nil
|
||||
@ -98,7 +96,6 @@ class PNButton: UIButton {
|
||||
}
|
||||
|
||||
@objc func touchUpInside(_ sender: PNButton) {
|
||||
print("touchUpInside")
|
||||
self.delegate?.buttonTapped(self)
|
||||
}
|
||||
|
||||
|
||||
@ -106,6 +106,12 @@
|
||||
/* No comment provided by engineer. */
|
||||
"Copy to pasteboard" = "Копировать в буфер обмена";
|
||||
|
||||
/* export as CSV table */
|
||||
"CSV table" = "таблицу в формате CSV";
|
||||
|
||||
/* export as database file */
|
||||
"Database file" = "файл базы данных";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Date and time" = "Дата и время";
|
||||
|
||||
@ -148,6 +154,9 @@
|
||||
/* No comment provided by engineer. */
|
||||
"Events" = "События";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Export history as" = "Экспортировать историю как";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Filter check history" = "Фильтр истории поиска";
|
||||
|
||||
@ -394,7 +403,7 @@
|
||||
/* 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" = "Если включено, вы услышите короткий звуковой сигнал перед началом записи аудио.";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
/* Manufacturing year */
|
||||
"Year" = "Год";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
|
||||
Loading…
Reference in New Issue
Block a user