Grouping history by dates

This commit is contained in:
Selim Mustafaev 2020-03-18 01:29:39 +03:00
parent 8e04a446d2
commit efafeb6cb0
6 changed files with 149 additions and 10 deletions

View File

@ -7,6 +7,10 @@
objects = {
/* Begin PBXBuildFile section */
7A051611241412CA00FC55AC /* SwiftDate in Frameworks */ = {isa = PBXBuildFile; productRef = 7A051610241412CA00FC55AC /* SwiftDate */; };
7A0516162414EC1200FC55AC /* Differentiator in Frameworks */ = {isa = PBXBuildFile; productRef = 7A0516152414EC1200FC55AC /* Differentiator */; };
7A0516182414EC1200FC55AC /* RxDataSources in Frameworks */ = {isa = PBXBuildFile; productRef = 7A0516172414EC1200FC55AC /* RxDataSources */; };
7A05161A2414FF0900FC55AC /* DateSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0516192414FF0900FC55AC /* DateSection.swift */; };
7A11470123FDE7E500B424AF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11470023FDE7E500B424AF /* AppDelegate.swift */; };
7A11470323FDE7E500B424AF /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A11470223FDE7E500B424AF /* SceneDelegate.swift */; };
7A11470823FDE7E500B424AF /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7A11470623FDE7E500B424AF /* Main.storyboard */; };
@ -48,6 +52,7 @@
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
7A0516192414FF0900FC55AC /* DateSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateSection.swift; sourceTree = "<group>"; };
7A1146FD23FDE7E500B424AF /* AutoCat.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AutoCat.app; sourceTree = BUILT_PRODUCTS_DIR; };
7A11470023FDE7E500B424AF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7A11470223FDE7E500B424AF /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
@ -85,9 +90,12 @@
buildActionMask = 2147483647;
files = (
7AF58D342402A91C00CE01A0 /* Kingfisher in Frameworks */,
7A0516162414EC1200FC55AC /* Differentiator in Frameworks */,
7A11472823FEA1F400B424AF /* RealmSwift in Frameworks */,
7A11472123FEA18700B424AF /* RxCocoa in Frameworks */,
7A11474E23FFEE8800B424AF /* SVProgressHUD.framework in Frameworks */,
7A0516182414EC1200FC55AC /* RxDataSources in Frameworks */,
7A051611241412CA00FC55AC /* SwiftDate in Frameworks */,
7A11472323FEA18700B424AF /* RxBlocking in Frameworks */,
7A530B8B240181F500CBFE6E /* RxRealm in Frameworks */,
7A11472B23FEA24D00B424AF /* Action in Frameworks */,
@ -173,6 +181,7 @@
7A11474823FF2B2D00B424AF /* Response.swift */,
7A11474A23FF368B00B424AF /* Settings.swift */,
7A530B7F2401803A00CBFE6E /* Vehicle.swift */,
7A0516192414FF0900FC55AC /* DateSection.swift */,
);
path = Models;
sourceTree = "<group>";
@ -239,6 +248,9 @@
7A530B8A240181F500CBFE6E /* RxRealm */,
7AF58D2E24029C5200CE01A0 /* MagazineLayout */,
7AF58D332402A91C00CE01A0 /* Kingfisher */,
7A051610241412CA00FC55AC /* SwiftDate */,
7A0516152414EC1200FC55AC /* Differentiator */,
7A0516172414EC1200FC55AC /* RxDataSources */,
);
productName = AutoCat;
productReference = 7A1146FD23FDE7E500B424AF /* AutoCat.app */;
@ -276,6 +288,8 @@
7A530B89240181F500CBFE6E /* XCRemoteSwiftPackageReference "RxRealm" */,
7AF58D2D24029C5200CE01A0 /* XCRemoteSwiftPackageReference "MagazineLayout" */,
7AF58D322402A91C00CE01A0 /* XCRemoteSwiftPackageReference "Kingfisher" */,
7A05160F241412CA00FC55AC /* XCRemoteSwiftPackageReference "SwiftDate" */,
7A0516142414EC1200FC55AC /* XCRemoteSwiftPackageReference "RxDataSources" */,
);
productRefGroup = 7A1146FE23FDE7E500B424AF /* Products */;
projectDirPath = "";
@ -346,6 +360,7 @@
7A530B7E24017FEE00CBFE6E /* VehicleCell.swift in Sources */,
7A530B87240180CC00CBFE6E /* Reactive+RxRealmDataSources.swift in Sources */,
7A11474423FF06CA00B424AF /* Api.swift in Sources */,
7A05161A2414FF0900FC55AC /* DateSection.swift in Sources */,
7A11474B23FF368B00B424AF /* Settings.swift in Sources */,
7A7547E024032CB6004E8406 /* VehiclePhotoCell.swift in Sources */,
);
@ -559,6 +574,22 @@
/* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
7A05160F241412CA00FC55AC /* XCRemoteSwiftPackageReference "SwiftDate" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/malcommac/SwiftDate.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 6.1.0;
};
};
7A0516142414EC1200FC55AC /* XCRemoteSwiftPackageReference "RxDataSources" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/RxSwiftCommunity/RxDataSources";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 4.0.1;
};
};
7A11471B23FEA18700B424AF /* XCRemoteSwiftPackageReference "RxSwift" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/ReactiveX/RxSwift.git";
@ -618,6 +649,21 @@
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
7A051610241412CA00FC55AC /* SwiftDate */ = {
isa = XCSwiftPackageProductDependency;
package = 7A05160F241412CA00FC55AC /* XCRemoteSwiftPackageReference "SwiftDate" */;
productName = SwiftDate;
};
7A0516152414EC1200FC55AC /* Differentiator */ = {
isa = XCSwiftPackageProductDependency;
package = 7A0516142414EC1200FC55AC /* XCRemoteSwiftPackageReference "RxDataSources" */;
productName = Differentiator;
};
7A0516172414EC1200FC55AC /* RxDataSources */ = {
isa = XCSwiftPackageProductDependency;
package = 7A0516142414EC1200FC55AC /* XCRemoteSwiftPackageReference "RxDataSources" */;
productName = RxDataSources;
};
7A11471C23FEA18700B424AF /* RxSwift */ = {
isa = XCSwiftPackageProductDependency;
package = 7A11471B23FEA18700B424AF /* XCRemoteSwiftPackageReference "RxSwift" */;

View File

@ -55,6 +55,15 @@
"version": "5.23.8"
}
},
{
"package": "RxDataSources",
"repositoryURL": "https://github.com/RxSwiftCommunity/RxDataSources",
"state": {
"branch": null,
"revision": "a18cee01c9ee55f04d0c7eb15c77a96c3648c88e",
"version": "4.0.1"
}
},
{
"package": "RxRealm",
"repositoryURL": "https://github.com/RxSwiftCommunity/RxRealm",
@ -72,6 +81,15 @@
"revision": "b3e888b4972d9bc76495dd74d30a8c7fad4b9395",
"version": "5.0.1"
}
},
{
"package": "SwiftDate",
"repositoryURL": "https://github.com/malcommac/SwiftDate.git",
"state": {
"branch": null,
"revision": "700dde1b3417fd4a7fd2bec9f5bc8ab2de1b96b4",
"version": "6.1.0"
}
}
]
},

View File

@ -8,7 +8,7 @@
BreakpointExtensionID = "Xcode.Breakpoint.SwiftErrorBreakpoint">
<BreakpointContent
uuid = "C14D0996-5708-44D2-A6BA-4A4B50B522EE"
shouldBeEnabled = "No"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No">
</BreakpointContent>
@ -17,7 +17,7 @@
BreakpointExtensionID = "Xcode.Breakpoint.ExceptionBreakpoint">
<BreakpointContent
uuid = "CF01B44D-372B-4C78-A197-7FDEC607CE0E"
shouldBeEnabled = "No"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
scope = "1"

View File

@ -3,6 +3,9 @@ import InputMask
import RealmSwift
import RxSwift
import SVProgressHUD
import SwiftDate
import RxRealm
import RxDataSources
class CheckController: UIViewController, MaskedTextFieldDelegateListener {
@ -21,19 +24,64 @@ class CheckController: UIViewController, MaskedTextFieldDelegateListener {
self.number.delegate = self.maskFieldDelegate
self.check.isEnabled = false
let ds = RxTableViewRealmDataSource<Vehicle>(cellIdentifier: "VehicleCell", cellType: VehicleCell.self) { cell, ip, vehicle in
cell.configure(with: vehicle)
// let ds = RxTableViewRealmDataSource<Vehicle>(cellIdentifier: "VehicleCell", cellType: VehicleCell.self) { cell, ip, vehicle in
// cell.configure(with: vehicle)
// }
// ds.headerTitle = "History"
let ds = RxTableViewSectionedAnimatedDataSource<DateSection<Vehicle>>(configureCell: { dataSource, tableView, indexPath, item in
if let cell = tableView.dequeueReusableCell(withIdentifier: "VehicleCell", for: indexPath) as? VehicleCell {
cell.configure(with: item)
return cell
} else {
return UITableViewCell()
}
})
ds.titleForHeaderInSection = { dataSourse, index in
return dataSourse.sectionModels[index].header
}
ds.headerTitle = "History"
let realm = try! Realm()
Observable.changeset(from: realm.objects(Vehicle.self).sorted(byKeyPath: "addedDate", ascending: false))
.bind(to: self.history.rx.realmChanges(ds))
.disposed(by: self.bag)
// Observable.changeset(from: realm.objects(Vehicle.self).sorted(byKeyPath: "addedDate", ascending: false))
// .bind(to: self.history.rx.realmChanges(ds))
// .disposed(by: self.bag)
self.history.rx.realmModelSelected(Vehicle.self)
.subscribe(onNext: self.updateDetailController(with:))
.disposed(by: self.bag)
Observable.collection(from: realm.objects(Vehicle.self).sorted(byKeyPath: "addedDate", ascending: false)).map { (vehicles: Results<Vehicle>) -> [DateSection<Vehicle>] in
var sections: [TimeInterval: [Vehicle]] = [:]
for vehicle in vehicles {
let date = Date(timeIntervalSince1970: vehicle.addedDate)
let key = date.dateAtStartOf(.weekday).timeIntervalSince1970
print("==== Key: \(key)")
if sections[key] == nil {
sections[key] = [vehicle]
} else {
sections[key]?.append(vehicle)
}
}
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .medium
var sectionsArray: [DateSection<Vehicle>] = []
for (timestamp, vehicles) in sections {
let dateStr = formatter.string(from: Date(timeIntervalSince1970: timestamp/1000))
sectionsArray.append(DateSection<Vehicle>(header: dateStr, items: vehicles))
}
print("==========================")
for s in sectionsArray {
print(s.header)
}
return sectionsArray
}
.bind(to: self.history.rx.items(dataSource: ds))
.disposed(by: self.bag)
}
override func viewWillAppear(_ animated: Bool) {
@ -44,6 +92,7 @@ class CheckController: UIViewController, MaskedTextFieldDelegateListener {
@IBAction func checkTapped(_ sender: UIButton) {
guard let number = self.number.text else { return }
self.number.resignFirstResponder()
self.number.text = nil
SVProgressHUD.show()
Api.checkVehicle(by: number)
@ -60,7 +109,6 @@ class CheckController: UIViewController, MaskedTextFieldDelegateListener {
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
textField.resignFirstResponder()
if self.check.isEnabled {
self.checkTapped(self.check)
}
@ -96,4 +144,6 @@ class CheckController: UIViewController, MaskedTextFieldDelegateListener {
}
}
}
}

View File

@ -0,0 +1,22 @@
import Foundation
import RxDataSources
struct DateSection<T>: AnimatableSectionModelType where T: IdentifiableType, T: Equatable {
var header: String
var items: [T]
var identity: String {
return header
}
init(original: DateSection, items: [T]) {
self = original
self.items = items
}
init(header: String, items: [T]) {
self.header = header
self.items = items
}
}

View File

@ -1,5 +1,6 @@
import Foundation
import RealmSwift
import RxDataSources
class VehicleName: Object, Decodable {
@objc dynamic var original: String?
@ -39,7 +40,7 @@ class VehiclePhoto: Object, Decodable {
}
}
class Vehicle: Object, Decodable {
class Vehicle: Object, Decodable, IdentifiableType {
@objc dynamic var _id: String = ""
@objc dynamic var brand: VehicleBrand?
@objc dynamic var model: VehicleModel?
@ -58,6 +59,8 @@ class Vehicle: Object, Decodable {
@objc dynamic var addedBy: String = ""
let photos = List<VehiclePhoto>()
var identity: String { _id }
enum CodingKeys: String, CodingKey {
case _id
case brand