Fixed history

This commit is contained in:
Selim Mustafaev 2020-12-18 18:22:20 +03:00
parent 6d0fb32fa7
commit f1880a88bd
10 changed files with 284 additions and 44 deletions

View File

@ -106,6 +106,7 @@
7AEF47A4253DC4D2001D6238 /* Eureka in Frameworks */ = {isa = PBXBuildFile; productRef = 7AEF47A3253DC4D2001D6238 /* Eureka */; }; 7AEF47A4253DC4D2001D6238 /* Eureka in Frameworks */ = {isa = PBXBuildFile; productRef = 7AEF47A3253DC4D2001D6238 /* Eureka */; };
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 */; };
7AF58D342402A91C00CE01A0 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 7AF58D332402A91C00CE01A0 /* Kingfisher */; }; 7AF58D342402A91C00CE01A0 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 7AF58D332402A91C00CE01A0 /* Kingfisher */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
@ -208,6 +209,7 @@
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>"; };
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>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@ -369,6 +371,7 @@
7AAE6AD224CDDF950023860B /* VehicleEvent.swift */, 7AAE6AD224CDDF950023860B /* VehicleEvent.swift */,
7A0420A925619AEC00034941 /* Osago.swift */, 7A0420A925619AEC00034941 /* Osago.swift */,
7A2DE69725868AC800A113FC /* VehicleAd.swift */, 7A2DE69725868AC800A113FC /* VehicleAd.swift */,
7AF12B1C258C9CFF0090F8B8 /* Cloneable.swift */,
); );
path = Models; path = Models;
sourceTree = "<group>"; sourceTree = "<group>";
@ -604,6 +607,7 @@
7A64AE762469DFB600ABE48E /* ContentTransformers.swift in Sources */, 7A64AE762469DFB600ABE48E /* ContentTransformers.swift in Sources */,
7A11471823FDEBFA00B424AF /* ReportController.swift in Sources */, 7A11471823FDEBFA00B424AF /* ReportController.swift in Sources */,
7AE24C5F251F1B4E00758E39 /* Buttons.swift in Sources */, 7AE24C5F251F1B4E00758E39 /* Buttons.swift in Sources */,
7AF12B1D258C9CFF0090F8B8 /* Cloneable.swift in Sources */,
7A11471A23FE839000B424AF /* AuthController.swift in Sources */, 7A11471A23FE839000B424AF /* AuthController.swift in Sources */,
7A530B7A24001D3300CBFE6E /* CheckController.swift in Sources */, 7A530B7A24001D3300CBFE6E /* CheckController.swift in Sources */,
7A6E03282485951700DB22ED /* OwnersController.swift in Sources */, 7A6E03282485951700DB22ED /* OwnersController.swift in Sources */,

View File

@ -1,9 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17506" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="pme-aR-UNJ"> <document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="pme-aR-UNJ">
<device id="retina4_7" orientation="portrait" appearance="dark"/> <device id="retina4_7" orientation="portrait" appearance="dark"/>
<dependencies> <dependencies>
<deployment identifier="iOS"/> <deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17505"/> <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/> <capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/> <capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
@ -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="124.5"/> <rect key="frame" x="0.0" y="28" width="375" height="125"/>
<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="124.5"/> <rect key="frame" x="0.0" y="0.0" width="375" height="125"/>
<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="108.5"/> <rect key="frame" x="8" y="8" width="359" height="109"/>
<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="50.5"/> <rect key="frame" x="0.0" y="58" width="359" height="51"/>
<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"/>
@ -564,7 +564,13 @@
<constraint firstItem="JKr-UE-x8f" firstAttribute="leading" secondItem="3Jk-FW-b3r" secondAttribute="leading" id="vfN-fu-5pA"/> <constraint firstItem="JKr-UE-x8f" firstAttribute="leading" secondItem="3Jk-FW-b3r" secondAttribute="leading" id="vfN-fu-5pA"/>
</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">
<connections>
<action selector="onFilter:" destination="twc-qR-t1G" id="qfm-0f-hT0"/>
</connections>
</barButtonItem>
</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"/>
<outlet property="history" destination="JKr-UE-x8f" id="GP9-Gz-WBm"/> <outlet property="history" destination="JKr-UE-x8f" id="GP9-Gz-WBm"/>

View File

@ -11,14 +11,21 @@ enum EventAction {
case sendSpecific(VehicleEvent) case sendSpecific(VehicleEvent)
} }
enum HistoryFilter {
case all
case unrecognized
case outdated
}
class CheckController: UIViewController, UITableViewDelegate, UITextFieldDelegate, PNKeyboardDelegate { class CheckController: UIViewController, UITableViewDelegate, UITextFieldDelegate, PNKeyboardDelegate {
@IBOutlet weak var number: SwiftMaskTextfield! @IBOutlet weak var number: SwiftMaskTextfield!
@IBOutlet weak var check: UIButton! @IBOutlet weak var check: UIButton!
@IBOutlet weak var history: UITableView! @IBOutlet weak var history: UITableView!
let bag = DisposeBag() private let bag = DisposeBag()
var historyDataSource: RealmSectionedDataSource<Vehicle, VehicleCell>! private var historyDataSource: RealmSectionedDataSource<Vehicle, VehicleCell>!
private var historyFilter: HistoryFilter = .all
// MARK: - Lifecycle // MARK: - Lifecycle
@ -44,7 +51,7 @@ class CheckController: UIViewController, UITableViewDelegate, UITextFieldDelegat
override func viewWillAppear(_ animated: Bool) { override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated) super.viewWillAppear(animated)
self.navigationController?.setNavigationBarHidden(true, animated: false) //self.navigationController?.setNavigationBarHidden(true, animated: false)
} }
override func viewWillDisappear(_ animated: Bool) { override func viewWillDisappear(_ animated: Bool) {
@ -150,6 +157,36 @@ 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) {
@ -236,16 +273,17 @@ class CheckController: UIViewController, UITableViewDelegate, UITextFieldDelegat
} }
func remove(vehicle: Vehicle) { func remove(vehicle: Vehicle) {
if let realm = vehicle.realm { guard let realm = try? Realm() else { return }
guard let realmVehicle = realm.object(ofType: Vehicle.self, forPrimaryKey: vehicle.getNumber()) else { return }
do { do {
try realm.write { try realm.write {
realm.delete(vehicle) realm.delete(realmVehicle)
} }
} catch { } catch {
print(error) print(error)
} }
} }
}
// MARK: - Checking number // MARK: - Checking number

View File

@ -2,7 +2,7 @@ import Foundation
import RealmSwift import RealmSwift
import DifferenceKit import DifferenceKit
class AudioRecord: Object, Identifiable, Differentiable { class AudioRecord: Object, Identifiable, Differentiable, Cloneable {
@objc dynamic var path: String = "" @objc dynamic var path: String = ""
@objc dynamic var number: String? @objc dynamic var number: String?
@ -35,6 +35,7 @@ class AudioRecord: Object, Identifiable, Differentiable {
} }
required init() { required init() {
super.init()
} }
override static func primaryKey() -> String? { override static func primaryKey() -> String? {
@ -53,4 +54,15 @@ class AudioRecord: Object, Identifiable, Differentiable {
return self.addedDate return self.addedDate
} }
// MARK: - Cloneable
required init(copy: AudioRecord) {
self.path = copy.path
self.number = copy.number
self.rawText = copy.rawText
self.addedDate = copy.addedDate
self.duration = copy.duration
self.event = copy.event?.clone()
}
} }

View File

@ -0,0 +1,11 @@
import Foundation
protocol Cloneable {
init(copy: Self)
}
extension Cloneable {
func clone() -> Self {
return Self.init(copy: self)
}
}

View File

@ -1,15 +1,32 @@
import Foundation import Foundation
import RealmSwift import RealmSwift
class Osago: Object, Decodable { class Osago: Object, Decodable, Cloneable {
@objc dynamic var date: TimeInterval @objc dynamic var date: TimeInterval = 0
@objc dynamic var number: String @objc dynamic var number: String = ""
@objc dynamic var vin: String? @objc dynamic var vin: String?
@objc dynamic var plateNumber: String? @objc dynamic var plateNumber: String?
@objc dynamic var name: String @objc dynamic var name: String = ""
@objc dynamic var status: String @objc dynamic var status: String = ""
@objc dynamic var restrictions: String @objc dynamic var restrictions: String = ""
@objc dynamic var insurant: String? @objc dynamic var insurant: String?
@objc dynamic var owner: String? @objc dynamic var owner: String?
@objc dynamic var usageRegion: String? @objc dynamic var usageRegion: String?
required init(copy: Osago) {
self.date = copy.date
self.number = copy.number
self.vin = copy.vin
self.plateNumber = copy.plateNumber
self.name = copy.name
self.status = copy.status
self.restrictions = copy.restrictions
self.insurant = copy.insurant
self.owner = copy.owner
self.usageRegion = copy.usageRegion
}
required init() {
super.init()
}
} }

View File

@ -2,21 +2,46 @@ import Foundation
import RealmSwift import RealmSwift
import DifferenceKit import DifferenceKit
class VehicleName: Object, Decodable { class VehicleName: Object, Decodable, Cloneable {
@objc dynamic var original: String? @objc dynamic var original: String?
@objc dynamic var normalized: String? @objc dynamic var normalized: String?
required init(copy: VehicleName) {
self.original = copy.original
self.normalized = copy.normalized
} }
class VehicleBrand: Object, Decodable { required init() {
}
}
class VehicleBrand: Object, Decodable, Cloneable {
@objc dynamic var name: VehicleName? @objc dynamic var name: VehicleName?
@objc dynamic var logo: String? @objc dynamic var logo: String?
required init(copy: VehicleBrand) {
self.name = copy.name?.clone()
self.logo = copy.logo
} }
class VehicleModel: Object, Decodable { required init() {
super.init()
}
}
class VehicleModel: Object, Decodable, Cloneable {
@objc dynamic var name: VehicleName? @objc dynamic var name: VehicleName?
required init(copy: VehicleModel) {
self.name = copy.name?.clone()
} }
class VehicleEngine: Object, Decodable { required init() {
super.init()
}
}
class VehicleEngine: Object, Decodable, Cloneable {
@objc dynamic var number: String? @objc dynamic var number: String?
var volume: RealmOptional<Int> = RealmOptional(0) var volume: RealmOptional<Int> = RealmOptional(0)
@objc dynamic var powerHp: Float = 0 @objc dynamic var powerHp: Float = 0
@ -39,9 +64,17 @@ class VehicleEngine: Object, Decodable {
required init() { required init() {
super.init() super.init()
} }
required init(copy: VehicleEngine) {
self.number = copy.number
self.volume = copy.volume
self.powerHp = copy.powerHp
self.powerKw = copy.powerKw
self.fuelType = copy.fuelType
}
} }
class VehiclePhoto: Object, Decodable { class VehiclePhoto: Object, Decodable, Cloneable {
@objc dynamic var brand: String? @objc dynamic var brand: String?
@objc dynamic var model: String? @objc dynamic var model: String?
@objc dynamic var date: TimeInterval = 0 @objc dynamic var date: TimeInterval = 0
@ -56,6 +89,17 @@ class VehiclePhoto: Object, Decodable {
let dateStr = formatter.string(from: date) let dateStr = formatter.string(from: date)
return "\(self.brand ?? "") \(self.model ?? "") (\(dateStr))" return "\(self.brand ?? "") \(self.model ?? "") (\(dateStr))"
} }
required init(copy: VehiclePhoto) {
self.brand = copy.brand
self.model = copy.model
self.date = copy.date
self.url = copy.url
}
required init() {
super.init()
}
} }
enum OwnerType: String, CustomStringConvertible { enum OwnerType: String, CustomStringConvertible {
@ -84,11 +128,11 @@ enum SteeringWheelPosition: CustomStringConvertible {
} }
} }
class VehicleOwnershipPeriod: Object, Decodable { class VehicleOwnershipPeriod: Object, Decodable, Cloneable {
@objc dynamic var lastOperation: String @objc dynamic var lastOperation: String = ""
@objc dynamic var ownerType: String @objc dynamic var ownerType: String = ""
@objc dynamic var from: Int64 @objc dynamic var from: Int64 = 0
@objc dynamic var to: Int64 @objc dynamic var to: Int64 = 0
@objc dynamic var region: String? @objc dynamic var region: String?
@objc dynamic var registrationRegion: String? @objc dynamic var registrationRegion: String?
@objc dynamic var locality: String? @objc dynamic var locality: String?
@ -96,9 +140,27 @@ class VehicleOwnershipPeriod: Object, Decodable {
@objc dynamic var street: String? @objc dynamic var street: String?
@objc dynamic var building: String? @objc dynamic var building: String?
@objc dynamic var inn: String? @objc dynamic var inn: String?
required init(copy: VehicleOwnershipPeriod) {
self.lastOperation = copy.lastOperation
self.ownerType = copy.ownerType
self.from = copy.from
self.to = copy.to
self.region = copy.region
self.registrationRegion = copy.registrationRegion
self.locality = copy.locality
self.code = copy.code
self.street = copy.street
self.building = copy.building
self.inn = copy.inn
} }
class Vehicle: Object, Decodable, Identifiable, Differentiable { required init() {
super.init()
}
}
class Vehicle: Object, Decodable, Identifiable, Differentiable, Cloneable {
@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?
@ -116,11 +178,11 @@ class Vehicle: Object, Decodable, Identifiable, Differentiable {
@objc dynamic var addedDate: TimeInterval = 0 @objc dynamic var addedDate: TimeInterval = 0
@objc dynamic var updatedDate: TimeInterval = 0 @objc dynamic var updatedDate: TimeInterval = 0
@objc dynamic var addedBy: String = "" @objc dynamic var addedBy: String = ""
let photos = List<VehiclePhoto>() var photos = List<VehiclePhoto>()
let ownershipPeriods = List<VehicleOwnershipPeriod>() var ownershipPeriods = List<VehicleOwnershipPeriod>()
let events = List<VehicleEvent>() var events = List<VehicleEvent>()
let osagoContracts = List<Osago>() var osagoContracts = List<Osago>()
let ads = List<VehicleAd>() var ads = List<VehicleAd>()
var identifier: String = "" var identifier: String = ""
var id: String { var id: String {
@ -247,4 +309,45 @@ class Vehicle: Object, Decodable, Identifiable, Differentiable {
return false return false
} }
} }
// MARK: - Cloneable
required init(copy: Vehicle) {
self.brand = copy.brand
self.model = copy.model
self.color = copy.color
self.year = copy.year
self.category = copy.category
self.engine = copy.engine
self.number = copy.number
self.currentNumber = copy.currentNumber
self.vin1 = copy.vin1
self.vin2 = copy.vin2
self.sts = copy.sts
self.pts = copy.pts
self.isRightWheel = copy.isRightWheel
self.isJapanese = copy.isJapanese
self.addedDate = copy.addedDate
self.addedBy = copy.addedBy
let photos = List<VehiclePhoto>()
photos.append(objectsIn: copy.photos.map { $0.clone() })
self.photos = photos
let ownerships = List<VehicleOwnershipPeriod>()
ownerships.append(objectsIn: copy.ownershipPeriods.map { $0.clone() })
self.ownershipPeriods = ownerships
let events = List<VehicleEvent>()
events.append(objectsIn: copy.events.map { $0.clone() })
self.events = events
let osago = List<Osago>()
osago.append(objectsIn: copy.osagoContracts.map { $0.clone() })
self.osagoContracts = osago
let ads = List<VehicleAd>()
ads.append(objectsIn: copy.ads.map { $0.clone() })
self.ads = ads
}
} }

View File

@ -1,7 +1,7 @@
import Foundation import Foundation
import RealmSwift import RealmSwift
class VehicleAd: Object, Decodable { class VehicleAd: Object, Decodable, Cloneable {
@objc dynamic var id: Int = 0 @objc dynamic var id: Int = 0
@objc dynamic var url: String? @objc dynamic var url: String?
@objc dynamic var price: String? @objc dynamic var price: String?
@ -11,4 +11,23 @@ class VehicleAd: Object, Decodable {
@objc dynamic var city: String? @objc dynamic var city: String?
@objc dynamic var adDescription: String? @objc dynamic var adDescription: String?
var photos = List<String>() var photos = List<String>()
required init(copy: VehicleAd) {
self.id = copy.id
self.url = copy.url
self.price = copy.price
self.date = copy.date
self.mileage = copy.mileage
self.region = copy.region
self.city = copy.city
self.adDescription = copy.adDescription
let photos = List<String>()
photos.append(objectsIn: copy.photos)
self.photos = photos
}
required init() {
super.init()
}
} }

View File

@ -3,7 +3,7 @@ import RealmSwift
import RxSwift import RxSwift
import CoreLocation import CoreLocation
class VehicleEvent: Object, Codable { class VehicleEvent: Object, Codable, Cloneable {
@objc dynamic var id: String? @objc dynamic var id: String?
@objc dynamic var date: TimeInterval = Date().timeIntervalSince1970 @objc dynamic var date: TimeInterval = Date().timeIntervalSince1970
@objc dynamic var latitude: Double = 0 @objc dynamic var latitude: Double = 0
@ -47,4 +47,17 @@ class VehicleEvent: Object, Codable {
override static func ignoredProperties() -> [String] { override static func ignoredProperties() -> [String] {
return ["plateNumber"] return ["plateNumber"]
} }
// MARK: - Cloneable
required init(copy: VehicleEvent) {
self.id = copy.id
self.date = copy.date
self.latitude = copy.latitude
self.longitude = copy.longitude
self.speed = copy.speed
self.direction = copy.direction
self.address = copy.address
self.number = copy.number
}
} }

View File

@ -3,13 +3,19 @@ import RealmSwift
import DifferenceKit import DifferenceKit
import ExceptionCatcher import ExceptionCatcher
typealias FilterPredicate<T> = (T) -> Bool
class RealmDiffableDataSourse<Item>: UITableViewDiffableDataSource<DateSection<Item>, Item> where Item: Hashable & ContentEquatable & ContentIdentifiable { class RealmDiffableDataSourse<Item>: UITableViewDiffableDataSource<DateSection<Item>, Item> where Item: Hashable & ContentEquatable & ContentIdentifiable {
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return snapshot().sectionIdentifiers[section].header return snapshot().sectionIdentifiers[section].header
} }
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
} }
class RealmSectionedDataSource<Item,Cell> where Item: Object & Identifiable & Dated & Differentiable, Cell: UITableViewCell & ConfigurableCell, Cell.Item == Item { class RealmSectionedDataSource<Item,Cell> where Item: Object & Identifiable & Dated & Differentiable & Cloneable, Cell: UITableViewCell & ConfigurableCell, Cell.Item == Item {
private var tv: UITableView private var tv: UITableView
private var data: Results<Item> private var data: Results<Item>
@ -18,6 +24,7 @@ class RealmSectionedDataSource<Item,Cell> where Item: Object & Identifiable & Da
private var cellIdentifier: String private var cellIdentifier: String
private var lastUpdateTime = Date() private var lastUpdateTime = Date()
private var dataSource: RealmDiffableDataSourse<Item>! private var dataSource: RealmDiffableDataSourse<Item>!
private var filterPredicate: FilterPredicate<Item>?
init(table: UITableView, data: Results<Item>, cellIdentifier: String = String(describing: Cell.self)) { init(table: UITableView, data: Results<Item>, cellIdentifier: String = String(describing: Cell.self)) {
self.tv = table self.tv = table
@ -29,6 +36,7 @@ class RealmSectionedDataSource<Item,Cell> where Item: Object & Identifiable & Da
cell?.configure(with: model) cell?.configure(with: model)
return cell return cell
} }
self.dataSource.defaultRowAnimation = .fade
self.tv.dataSource = self.dataSource self.tv.dataSource = self.dataSource
self.notificationToken = self.data.observe { changes in self.notificationToken = self.data.observe { changes in
@ -50,7 +58,11 @@ class RealmSectionedDataSource<Item,Cell> where Item: Object & Identifiable & Da
} }
func reload(animated: Bool = true) { func reload(animated: Bool = true) {
self.sections = self.data.groupedByDate() var items = self.data.toArray().map { $0.clone() }
if let predicate = self.filterPredicate {
items = items.filter(predicate)
}
self.sections = items.groupedByDate()
var snapshot = NSDiffableDataSourceSnapshot<DateSection<Item>, Item>() var snapshot = NSDiffableDataSourceSnapshot<DateSection<Item>, Item>()
snapshot.appendSections(self.sections) snapshot.appendSections(self.sections)
for section in self.sections { for section in self.sections {
@ -58,4 +70,9 @@ class RealmSectionedDataSource<Item,Cell> where Item: Object & Identifiable & Da
} }
self.dataSource.apply(snapshot, animatingDifferences: animated, completion: nil) self.dataSource.apply(snapshot, animatingDifferences: animated, completion: nil)
} }
func setFilterPredicate(_ predicate: FilterPredicate<Item>?) {
self.filterPredicate = predicate
self.reload()
}
} }