Search pagination
This commit is contained in:
parent
3ce8e2d0ae
commit
7ec9c50886
@ -7,6 +7,7 @@
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
6841A4F018B0E07966C1CEFC /* PagedResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6841A913FABBB0AB20DEF4FC /* PagedResponse.swift */; };
|
||||
6841A85D4B60DB71D1E68DA0 /* ImageGrid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6841AC687EA6293A0757678C /* ImageGrid.swift */; };
|
||||
7A000AA224C2EEDE001F5B00 /* Location.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A000AA124C2EEDE001F5B00 /* Location.swift */; };
|
||||
7A0420AA25619AEC00034941 /* Osago.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0420A925619AEC00034941 /* Osago.swift */; };
|
||||
@ -81,6 +82,19 @@
|
||||
7A96AE31246B2FE400297C33 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A96AE30246B2FE400297C33 /* Constants.swift */; };
|
||||
7A96AE33246C095700297C33 /* Base64FS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A96AE32246C095700297C33 /* Base64FS.swift */; };
|
||||
7A9FEEC82529AB23001CA50E /* RxRealmDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9FEEC72529AB23001CA50E /* RxRealmDataSource.swift */; };
|
||||
7AA7BC2C25A5DFB80053A5D5 /* RxSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 7A11471C23FEA18700B424AF /* RxSwift */; };
|
||||
7AA7BC2D25A5DFB80053A5D5 /* RxRelay in Frameworks */ = {isa = PBXBuildFile; productRef = 7A11471E23FEA18700B424AF /* RxRelay */; };
|
||||
7AA7BC2E25A5DFB80053A5D5 /* RxCocoa in Frameworks */ = {isa = PBXBuildFile; productRef = 7A11472023FEA18700B424AF /* RxCocoa */; };
|
||||
7AA7BC2F25A5DFB80053A5D5 /* RxBlocking in Frameworks */ = {isa = PBXBuildFile; productRef = 7A11472223FEA18700B424AF /* RxBlocking */; };
|
||||
7AA7BC3025A5DFB80053A5D5 /* Realm in Frameworks */ = {isa = PBXBuildFile; productRef = 7A11472523FEA1F400B424AF /* Realm */; };
|
||||
7AA7BC3125A5DFB80053A5D5 /* RealmSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 7A11472723FEA1F400B424AF /* RealmSwift */; };
|
||||
7AA7BC3225A5DFB80053A5D5 /* RxRealm in Frameworks */ = {isa = PBXBuildFile; productRef = 7A530B8A240181F500CBFE6E /* RxRealm */; };
|
||||
7AA7BC3325A5DFB80053A5D5 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 7AF58D332402A91C00CE01A0 /* Kingfisher */; };
|
||||
7AA7BC3425A5DFB80053A5D5 /* SwiftDate in Frameworks */ = {isa = PBXBuildFile; productRef = 7A051610241412CA00FC55AC /* SwiftDate */; };
|
||||
7AA7BC3525A5DFB80053A5D5 /* ExceptionCatcher in Frameworks */ = {isa = PBXBuildFile; productRef = 7A813DC02508C4D900CC93B9 /* ExceptionCatcher */; };
|
||||
7AA7BC3625A5DFB80053A5D5 /* PKHUD in Frameworks */ = {isa = PBXBuildFile; productRef = 7AABDE1C2532F3EB0041AFC6 /* PKHUD */; };
|
||||
7AA7BC3725A5DFB80053A5D5 /* DifferenceKit in Frameworks */ = {isa = PBXBuildFile; productRef = 7AABDE22253327F10041AFC6 /* DifferenceKit */; };
|
||||
7AA7BC3825A5DFB80053A5D5 /* Eureka in Frameworks */ = {isa = PBXBuildFile; productRef = 7AEF47A3253DC4D2001D6238 /* Eureka */; };
|
||||
7AABDE26253350C30041AFC6 /* RxSectionedDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AABDE25253350C30041AFC6 /* RxSectionedDataSource.swift */; };
|
||||
7AAE6AD324CDDF950023860B /* VehicleEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AAE6AD224CDDF950023860B /* VehicleEvent.swift */; };
|
||||
7AB562BA249C9E9B00473D53 /* Region.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB562B9249C9E9B00473D53 /* Region.swift */; };
|
||||
@ -96,19 +110,6 @@
|
||||
7AE24C5F251F1B4E00758E39 /* Buttons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE24C5E251F1B4E00758E39 /* Buttons.swift */; };
|
||||
7AE26A3324EEF9EC00625033 /* UIViewControllerExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE26A3224EEF9EC00625033 /* UIViewControllerExt.swift */; };
|
||||
7AE26A3524F31B0700625033 /* EventsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE26A3424F31B0700625033 /* EventsController.swift */; };
|
||||
7AE492922591FF5100322D2E /* RxSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 7A11471C23FEA18700B424AF /* RxSwift */; };
|
||||
7AE492932591FF5100322D2E /* RxRelay in Frameworks */ = {isa = PBXBuildFile; productRef = 7A11471E23FEA18700B424AF /* RxRelay */; };
|
||||
7AE492942591FF5100322D2E /* RxCocoa in Frameworks */ = {isa = PBXBuildFile; productRef = 7A11472023FEA18700B424AF /* RxCocoa */; };
|
||||
7AE492952591FF5100322D2E /* RxBlocking in Frameworks */ = {isa = PBXBuildFile; productRef = 7A11472223FEA18700B424AF /* RxBlocking */; };
|
||||
7AE492962591FF5100322D2E /* Realm in Frameworks */ = {isa = PBXBuildFile; productRef = 7A11472523FEA1F400B424AF /* Realm */; };
|
||||
7AE492972591FF5100322D2E /* RealmSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 7A11472723FEA1F400B424AF /* RealmSwift */; };
|
||||
7AE492982591FF5100322D2E /* RxRealm in Frameworks */ = {isa = PBXBuildFile; productRef = 7A530B8A240181F500CBFE6E /* RxRealm */; };
|
||||
7AE492992591FF5100322D2E /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = 7AF58D332402A91C00CE01A0 /* Kingfisher */; };
|
||||
7AE4929A2591FF5100322D2E /* SwiftDate in Frameworks */ = {isa = PBXBuildFile; productRef = 7A051610241412CA00FC55AC /* SwiftDate */; };
|
||||
7AE4929B2591FF5100322D2E /* ExceptionCatcher in Frameworks */ = {isa = PBXBuildFile; productRef = 7A813DC02508C4D900CC93B9 /* ExceptionCatcher */; };
|
||||
7AE4929C2591FF5100322D2E /* PKHUD in Frameworks */ = {isa = PBXBuildFile; productRef = 7AABDE1C2532F3EB0041AFC6 /* PKHUD */; };
|
||||
7AE4929D2591FF5100322D2E /* DifferenceKit in Frameworks */ = {isa = PBXBuildFile; productRef = 7AABDE22253327F10041AFC6 /* DifferenceKit */; };
|
||||
7AE4929E2591FF5100322D2E /* Eureka in Frameworks */ = {isa = PBXBuildFile; productRef = 7AEF47A3253DC4D2001D6238 /* Eureka */; };
|
||||
7AE492A1259232F000322D2E /* MultilineLinkRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE492A0259232F000322D2E /* MultilineLinkRow.swift */; };
|
||||
7AEFC3BE2529D3CC00BADFB2 /* ConfigurableCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AEFC3BD2529D3CC00BADFB2 /* ConfigurableCell.swift */; };
|
||||
7AEFE728240455E200910EB7 /* SettingsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AEFE727240455E200910EB7 /* SettingsController.swift */; };
|
||||
@ -116,6 +117,7 @@
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
6841A913FABBB0AB20DEF4FC /* PagedResponse.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PagedResponse.swift; sourceTree = "<group>"; };
|
||||
6841AC687EA6293A0757678C /* ImageGrid.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageGrid.swift; sourceTree = "<group>"; };
|
||||
7A000AA124C2EEDE001F5B00 /* Location.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Location.swift; sourceTree = "<group>"; };
|
||||
7A0420A925619AEC00034941 /* Osago.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Osago.swift; sourceTree = "<group>"; };
|
||||
@ -227,20 +229,20 @@
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
7AE492972591FF5100322D2E /* RealmSwift in Frameworks */,
|
||||
7AE4929B2591FF5100322D2E /* ExceptionCatcher in Frameworks */,
|
||||
7AE492962591FF5100322D2E /* Realm in Frameworks */,
|
||||
7AE492922591FF5100322D2E /* RxSwift in Frameworks */,
|
||||
7AE492952591FF5100322D2E /* RxBlocking in Frameworks */,
|
||||
7AE4929E2591FF5100322D2E /* Eureka in Frameworks */,
|
||||
7AE492992591FF5100322D2E /* Kingfisher in Frameworks */,
|
||||
7AA7BC3125A5DFB80053A5D5 /* RealmSwift in Frameworks */,
|
||||
7AA7BC3525A5DFB80053A5D5 /* ExceptionCatcher in Frameworks */,
|
||||
7AA7BC3025A5DFB80053A5D5 /* Realm in Frameworks */,
|
||||
7AA7BC2C25A5DFB80053A5D5 /* RxSwift in Frameworks */,
|
||||
7AA7BC2F25A5DFB80053A5D5 /* RxBlocking in Frameworks */,
|
||||
7AA7BC3825A5DFB80053A5D5 /* Eureka in Frameworks */,
|
||||
7AA7BC3325A5DFB80053A5D5 /* Kingfisher in Frameworks */,
|
||||
7A813DBE2506A57100CC93B9 /* AuthenticationServices.framework in Frameworks */,
|
||||
7AE4929C2591FF5100322D2E /* PKHUD in Frameworks */,
|
||||
7AE492942591FF5100322D2E /* RxCocoa in Frameworks */,
|
||||
7AE4929A2591FF5100322D2E /* SwiftDate in Frameworks */,
|
||||
7AE4929D2591FF5100322D2E /* DifferenceKit in Frameworks */,
|
||||
7AE492982591FF5100322D2E /* RxRealm in Frameworks */,
|
||||
7AE492932591FF5100322D2E /* RxRelay in Frameworks */,
|
||||
7AA7BC3625A5DFB80053A5D5 /* PKHUD in Frameworks */,
|
||||
7AA7BC2E25A5DFB80053A5D5 /* RxCocoa in Frameworks */,
|
||||
7AA7BC3425A5DFB80053A5D5 /* SwiftDate in Frameworks */,
|
||||
7AA7BC3725A5DFB80053A5D5 /* DifferenceKit in Frameworks */,
|
||||
7AA7BC3225A5DFB80053A5D5 /* RxRealm in Frameworks */,
|
||||
7AA7BC2D25A5DFB80053A5D5 /* RxRelay in Frameworks */,
|
||||
7A96AE2F246B2BCD00297C33 /* WebKit.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
@ -298,7 +300,6 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
7A0420B825693CEE00034941 /* JS */,
|
||||
7A64AE6B2469DC6900ABE48E /* AutoCat.entitlements */,
|
||||
7A3F07A924360D9100E59687 /* Extensions */,
|
||||
7A6DD90424326788009DE740 /* Fonts */,
|
||||
7A6DD901242BF48D009DE740 /* Views */,
|
||||
@ -313,6 +314,7 @@
|
||||
7A11470923FDE7E600B424AF /* Assets.xcassets */,
|
||||
7A11470B23FDE7E600B424AF /* LaunchScreen.storyboard */,
|
||||
7A11470E23FDE7E600B424AF /* Info.plist */,
|
||||
7A64AE6B2469DC6900ABE48E /* AutoCat.entitlements */,
|
||||
7A61FF892575A2CD00D905D5 /* Localizable.strings */,
|
||||
7A61FFA2257D3CFC00D905D5 /* Localizable.stringsdict */,
|
||||
7A61FF8F2575A5B300D905D5 /* InfoPlist.strings */,
|
||||
@ -385,6 +387,7 @@
|
||||
7A2DE69725868AC800A113FC /* VehicleAd.swift */,
|
||||
7AF12B1C258C9CFF0090F8B8 /* Cloneable.swift */,
|
||||
7A8AB76725A0DC8200ECF2C1 /* DebugInfo.swift */,
|
||||
6841A913FABBB0AB20DEF4FC /* PagedResponse.swift */,
|
||||
);
|
||||
path = Models;
|
||||
sourceTree = "<group>";
|
||||
@ -666,6 +669,7 @@
|
||||
7A000AA224C2EEDE001F5B00 /* Location.swift in Sources */,
|
||||
7A7547E024032CB6004E8406 /* VehiclePhotoCell.swift in Sources */,
|
||||
6841A85D4B60DB71D1E68DA0 /* ImageGrid.swift in Sources */,
|
||||
6841A4F018B0E07966C1CEFC /* PagedResponse.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -843,7 +847,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 62;
|
||||
CURRENT_PROJECT_VERSION = 63;
|
||||
DEVELOPMENT_TEAM = 46DTTB8X4S;
|
||||
INFOPLIST_FILE = AutoCat/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
@ -866,7 +870,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CODE_SIGN_ENTITLEMENTS = AutoCat/AutoCat.entitlements;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 62;
|
||||
CURRENT_PROJECT_VERSION = 63;
|
||||
DEVELOPMENT_TEAM = 46DTTB8X4S;
|
||||
INFOPLIST_FILE = AutoCat/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
|
||||
@ -51,6 +51,10 @@
|
||||
ReferencedContainer = "container:AutoCat.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<LocationScenarioReference
|
||||
identifier = "com.apple.dt.IDEFoundation.CurrentLocationScenarioIdentifier"
|
||||
referenceType = "1">
|
||||
</LocationScenarioReference>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
|
||||
@ -4,15 +4,17 @@ import RxCocoa
|
||||
import RealmSwift
|
||||
import PKHUD
|
||||
|
||||
class SearchController: UIViewController, UISearchResultsUpdating, UITableViewDelegate {
|
||||
class SearchController: UIViewController, UISearchResultsUpdating, UITableViewDelegate, UIScrollViewDelegate {
|
||||
|
||||
@IBOutlet weak var tableView: UITableView!
|
||||
@IBOutlet weak var showMapButton: UIBarButtonItem!
|
||||
|
||||
let bag = DisposeBag()
|
||||
let searchController = UISearchController(searchResultsController: nil)
|
||||
var refreshControl = UIRefreshControl()
|
||||
var datasource: RxSectionedDataSource<Vehicle,VehicleCell>!
|
||||
private let bag = DisposeBag()
|
||||
private let searchController = UISearchController(searchResultsController: nil)
|
||||
private var refreshControl = UIRefreshControl()
|
||||
private var datasource: RxSectionedDataSource<Vehicle,VehicleCell>!
|
||||
private var isLoadingPage = false
|
||||
private var pageLoadingIndicator = UIActivityIndicatorView(style: .medium)
|
||||
|
||||
var filterRelay = BehaviorRelay<Filter>(value: Filter())
|
||||
var filter = Filter()
|
||||
@ -28,6 +30,8 @@ class SearchController: UIViewController, UISearchResultsUpdating, UITableViewDe
|
||||
navigationItem.searchController = searchController
|
||||
definesPresentationContext = true
|
||||
|
||||
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: self.pageLoadingIndicator)
|
||||
|
||||
//self.refreshControl.attributedTitle = NSAttributedString(string: "")
|
||||
self.refreshControl.addTarget(self, action: #selector(self.refresh(_:)), for: .valueChanged)
|
||||
self.tableView.addSubview(self.refreshControl)
|
||||
@ -39,12 +43,17 @@ class SearchController: UIViewController, UISearchResultsUpdating, UITableViewDe
|
||||
self.filterRelay
|
||||
//.throttle(.seconds(2), scheduler: MainScheduler.instance)
|
||||
.debounce(.milliseconds(500), scheduler: MainScheduler.instance)
|
||||
.flatMap { Api.getVehicles(with: $0).catchErrorJustReturn([]) }
|
||||
.do(onNext: { _ in self.pageLoadingIndicator.startAnimating() })
|
||||
.flatMap { Api.getVehicles(with: $0, pageToken: self.datasource.pageToken).catchErrorJustReturn(PagedResponse<Vehicle>()) }
|
||||
.observeOn(MainScheduler.instance)
|
||||
.do(onNext: {
|
||||
self.navigationItem.title = String.localizedStringWithFormat(NSLocalizedString("vehicles found", comment: ""), $0.count)
|
||||
self.showMapButton.isEnabled = $0.count > 0
|
||||
if let count = $0.count {
|
||||
self.navigationItem.title = String.localizedStringWithFormat(NSLocalizedString("vehicles found", comment: ""), count)
|
||||
self.showMapButton.isEnabled = count > 0
|
||||
}
|
||||
self.refreshControl.endRefreshing()
|
||||
self.isLoadingPage = false
|
||||
self.pageLoadingIndicator.stopAnimating()
|
||||
})
|
||||
.bind(to: self.datasource.data)
|
||||
.disposed(by: self.bag)
|
||||
@ -163,4 +172,14 @@ class SearchController: UIViewController, UISearchResultsUpdating, UITableViewDe
|
||||
let vehicle = self.datasource.item(at: indexPath)
|
||||
self.updateDetailController(with: vehicle)
|
||||
}
|
||||
|
||||
func scrollViewDidScroll(_ scrollView: UIScrollView) {
|
||||
guard tableView.contentSize.height > 0 else { return }
|
||||
|
||||
let toBottom = tableView.contentSize.height - (tableView.contentOffset.y + tableView.frame.size.height)
|
||||
if toBottom < 100 && !self.isLoadingPage && self.datasource.needMoreData() {
|
||||
self.isLoadingPage = true
|
||||
self.filterRelay.accept(self.filter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
13
AutoCat/Models/PagedResponse.swift
Normal file
13
AutoCat/Models/PagedResponse.swift
Normal file
@ -0,0 +1,13 @@
|
||||
import Foundation
|
||||
|
||||
class PagedResponse<T>: Decodable where T: Decodable {
|
||||
let count: Int?
|
||||
let pageToken: String?
|
||||
let items: [T]
|
||||
|
||||
init() {
|
||||
self.items = []
|
||||
self.count = nil
|
||||
self.pageToken = nil
|
||||
}
|
||||
}
|
||||
@ -207,6 +207,7 @@ class Vehicle: Object, Decodable, Identifiable, Differentiable, Cloneable {
|
||||
case isRightWheel
|
||||
case isJapanese
|
||||
case addedDate
|
||||
case updatedDate
|
||||
case addedBy
|
||||
case photos
|
||||
case ownershipPeriods
|
||||
@ -235,6 +236,7 @@ class Vehicle: Object, Decodable, Identifiable, Differentiable, Cloneable {
|
||||
self.addedDate = (try container.decode(TimeInterval.self, forKey: .addedDate))/1000
|
||||
self.addedBy = try container.decode(String.self, forKey: .addedBy)
|
||||
self.debugInfo = try container.decodeIfPresent(DebugInfo.self, forKey: .debugInfo)
|
||||
self.updatedDate = (try container.decode(TimeInterval.self, forKey: .updatedDate))/1000
|
||||
|
||||
if let photosArray = try container.decodeIfPresent([VehiclePhoto].self, forKey: .photos) {
|
||||
self.photos.append(objectsIn: photosArray)
|
||||
@ -248,12 +250,6 @@ class Vehicle: Object, Decodable, Identifiable, Differentiable, Cloneable {
|
||||
self.events.append(objectsIn: eventsArray)
|
||||
}
|
||||
|
||||
if let lastEventDate = self.events.max(by: { $0.date < $1.date })?.date {
|
||||
self.updatedDate = max(self.addedDate, lastEventDate)
|
||||
} else {
|
||||
self.updatedDate = self.addedDate
|
||||
}
|
||||
|
||||
if let osago = try container.decodeIfPresent([Osago].self, forKey: .osagoContracts) {
|
||||
self.osagoContracts.append(objectsIn: osago)
|
||||
}
|
||||
|
||||
@ -194,8 +194,12 @@ class Api {
|
||||
return self.makeBodyRequest(api: "user/signup", body: body)
|
||||
}
|
||||
|
||||
public static func getVehicles(with filter: Filter) -> Single<[Vehicle]> {
|
||||
return self.makeGetRequest(api: "vehicles", params: filter.queryDictionary())
|
||||
public static func getVehicles(with filter: Filter, pageToken: String? = nil) -> Single<PagedResponse<Vehicle>> {
|
||||
var params = filter.queryDictionary()
|
||||
if let token = pageToken {
|
||||
params["pageToken"] = token;
|
||||
}
|
||||
return self.makeGetRequest(api: "vehicles", params: params)
|
||||
}
|
||||
|
||||
public static func checkVehicle(by number: String, force: Bool = false) -> Single<Vehicle> {
|
||||
|
||||
@ -3,10 +3,13 @@ import DifferenceKit
|
||||
import RxSwift
|
||||
import RxCocoa
|
||||
|
||||
class RxSectionedDataSource<Item,Cell>: NSObject, UITableViewDataSource where Item: Dated & Hashable & Differentiable, Cell: UITableViewCell & ConfigurableCell, Cell.Item == Item {
|
||||
class RxSectionedDataSource<Item,Cell>: NSObject, UITableViewDataSource where Item: Dated & Hashable & Differentiable & Decodable, Cell: UITableViewCell & ConfigurableCell, Cell.Item == Item {
|
||||
private var tv: UITableView
|
||||
private var cellIdentifier: String
|
||||
private var sections: [DateSection<Item>] = []
|
||||
private var items: [Item] = []
|
||||
private(set) var pageToken: String? = nil
|
||||
private(set) var count: Int? = nil
|
||||
|
||||
init(table: UITableView, cellIdentifier: String = String(describing: Cell.self)) {
|
||||
self.tv = table
|
||||
@ -49,13 +52,26 @@ class RxSectionedDataSource<Item,Cell>: NSObject, UITableViewDataSource where I
|
||||
self.sections[indexPath.section].elements[indexPath.row] = item
|
||||
}
|
||||
|
||||
var data: Binder<[Item]> {
|
||||
var data: Binder<PagedResponse<Item>> {
|
||||
return Binder(self) { datasource, data in
|
||||
let newSections = data.groupedByDate()
|
||||
if let count = data.count {
|
||||
self.count = count
|
||||
self.items = data.items
|
||||
} else {
|
||||
self.items.append(contentsOf: data.items)
|
||||
}
|
||||
self.pageToken = data.pageToken
|
||||
|
||||
let newSections = self.items.groupedByDate()
|
||||
let changeset = StagedChangeset(source: self.sections, target: newSections)
|
||||
self.tv.reload(using: changeset, with: .automatic) { newSects in
|
||||
self.sections = newSects
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func needMoreData() -> Bool {
|
||||
guard let count = self.count else { return true }
|
||||
return self.items.count < count
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user