Search pagination

This commit is contained in:
Selim Mustafaev 2021-01-07 17:12:58 +03:00
parent 3ce8e2d0ae
commit 7ec9c50886
7 changed files with 104 additions and 48 deletions

View File

@ -7,6 +7,7 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* 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 */; }; 6841A85D4B60DB71D1E68DA0 /* ImageGrid.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6841AC687EA6293A0757678C /* ImageGrid.swift */; };
7A000AA224C2EEDE001F5B00 /* Location.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A000AA124C2EEDE001F5B00 /* Location.swift */; }; 7A000AA224C2EEDE001F5B00 /* Location.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A000AA124C2EEDE001F5B00 /* Location.swift */; };
7A0420AA25619AEC00034941 /* Osago.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A0420A925619AEC00034941 /* Osago.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 */; }; 7A96AE31246B2FE400297C33 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A96AE30246B2FE400297C33 /* Constants.swift */; };
7A96AE33246C095700297C33 /* Base64FS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A96AE32246C095700297C33 /* Base64FS.swift */; }; 7A96AE33246C095700297C33 /* Base64FS.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A96AE32246C095700297C33 /* Base64FS.swift */; };
7A9FEEC82529AB23001CA50E /* RxRealmDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7A9FEEC72529AB23001CA50E /* RxRealmDataSource.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 */; }; 7AABDE26253350C30041AFC6 /* RxSectionedDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AABDE25253350C30041AFC6 /* RxSectionedDataSource.swift */; };
7AAE6AD324CDDF950023860B /* VehicleEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AAE6AD224CDDF950023860B /* VehicleEvent.swift */; }; 7AAE6AD324CDDF950023860B /* VehicleEvent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AAE6AD224CDDF950023860B /* VehicleEvent.swift */; };
7AB562BA249C9E9B00473D53 /* Region.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AB562B9249C9E9B00473D53 /* Region.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 */; }; 7AE24C5F251F1B4E00758E39 /* Buttons.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE24C5E251F1B4E00758E39 /* Buttons.swift */; };
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 */; };
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 */; }; 7AE492A1259232F000322D2E /* MultilineLinkRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7AE492A0259232F000322D2E /* MultilineLinkRow.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 */; };
@ -116,6 +117,7 @@
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXFileReference 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>"; }; 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>"; }; 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>"; }; 7A0420A925619AEC00034941 /* Osago.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Osago.swift; sourceTree = "<group>"; };
@ -227,20 +229,20 @@
isa = PBXFrameworksBuildPhase; isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
7AE492972591FF5100322D2E /* RealmSwift in Frameworks */, 7AA7BC3125A5DFB80053A5D5 /* RealmSwift in Frameworks */,
7AE4929B2591FF5100322D2E /* ExceptionCatcher in Frameworks */, 7AA7BC3525A5DFB80053A5D5 /* ExceptionCatcher in Frameworks */,
7AE492962591FF5100322D2E /* Realm in Frameworks */, 7AA7BC3025A5DFB80053A5D5 /* Realm in Frameworks */,
7AE492922591FF5100322D2E /* RxSwift in Frameworks */, 7AA7BC2C25A5DFB80053A5D5 /* RxSwift in Frameworks */,
7AE492952591FF5100322D2E /* RxBlocking in Frameworks */, 7AA7BC2F25A5DFB80053A5D5 /* RxBlocking in Frameworks */,
7AE4929E2591FF5100322D2E /* Eureka in Frameworks */, 7AA7BC3825A5DFB80053A5D5 /* Eureka in Frameworks */,
7AE492992591FF5100322D2E /* Kingfisher in Frameworks */, 7AA7BC3325A5DFB80053A5D5 /* Kingfisher in Frameworks */,
7A813DBE2506A57100CC93B9 /* AuthenticationServices.framework in Frameworks */, 7A813DBE2506A57100CC93B9 /* AuthenticationServices.framework in Frameworks */,
7AE4929C2591FF5100322D2E /* PKHUD in Frameworks */, 7AA7BC3625A5DFB80053A5D5 /* PKHUD in Frameworks */,
7AE492942591FF5100322D2E /* RxCocoa in Frameworks */, 7AA7BC2E25A5DFB80053A5D5 /* RxCocoa in Frameworks */,
7AE4929A2591FF5100322D2E /* SwiftDate in Frameworks */, 7AA7BC3425A5DFB80053A5D5 /* SwiftDate in Frameworks */,
7AE4929D2591FF5100322D2E /* DifferenceKit in Frameworks */, 7AA7BC3725A5DFB80053A5D5 /* DifferenceKit in Frameworks */,
7AE492982591FF5100322D2E /* RxRealm in Frameworks */, 7AA7BC3225A5DFB80053A5D5 /* RxRealm in Frameworks */,
7AE492932591FF5100322D2E /* RxRelay in Frameworks */, 7AA7BC2D25A5DFB80053A5D5 /* RxRelay in Frameworks */,
7A96AE2F246B2BCD00297C33 /* WebKit.framework in Frameworks */, 7A96AE2F246B2BCD00297C33 /* WebKit.framework in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
@ -298,7 +300,6 @@
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
7A0420B825693CEE00034941 /* JS */, 7A0420B825693CEE00034941 /* JS */,
7A64AE6B2469DC6900ABE48E /* AutoCat.entitlements */,
7A3F07A924360D9100E59687 /* Extensions */, 7A3F07A924360D9100E59687 /* Extensions */,
7A6DD90424326788009DE740 /* Fonts */, 7A6DD90424326788009DE740 /* Fonts */,
7A6DD901242BF48D009DE740 /* Views */, 7A6DD901242BF48D009DE740 /* Views */,
@ -313,6 +314,7 @@
7A11470923FDE7E600B424AF /* Assets.xcassets */, 7A11470923FDE7E600B424AF /* Assets.xcassets */,
7A11470B23FDE7E600B424AF /* LaunchScreen.storyboard */, 7A11470B23FDE7E600B424AF /* LaunchScreen.storyboard */,
7A11470E23FDE7E600B424AF /* Info.plist */, 7A11470E23FDE7E600B424AF /* Info.plist */,
7A64AE6B2469DC6900ABE48E /* AutoCat.entitlements */,
7A61FF892575A2CD00D905D5 /* Localizable.strings */, 7A61FF892575A2CD00D905D5 /* Localizable.strings */,
7A61FFA2257D3CFC00D905D5 /* Localizable.stringsdict */, 7A61FFA2257D3CFC00D905D5 /* Localizable.stringsdict */,
7A61FF8F2575A5B300D905D5 /* InfoPlist.strings */, 7A61FF8F2575A5B300D905D5 /* InfoPlist.strings */,
@ -385,6 +387,7 @@
7A2DE69725868AC800A113FC /* VehicleAd.swift */, 7A2DE69725868AC800A113FC /* VehicleAd.swift */,
7AF12B1C258C9CFF0090F8B8 /* Cloneable.swift */, 7AF12B1C258C9CFF0090F8B8 /* Cloneable.swift */,
7A8AB76725A0DC8200ECF2C1 /* DebugInfo.swift */, 7A8AB76725A0DC8200ECF2C1 /* DebugInfo.swift */,
6841A913FABBB0AB20DEF4FC /* PagedResponse.swift */,
); );
path = Models; path = Models;
sourceTree = "<group>"; sourceTree = "<group>";
@ -666,6 +669,7 @@
7A000AA224C2EEDE001F5B00 /* Location.swift in Sources */, 7A000AA224C2EEDE001F5B00 /* Location.swift in Sources */,
7A7547E024032CB6004E8406 /* VehiclePhotoCell.swift in Sources */, 7A7547E024032CB6004E8406 /* VehiclePhotoCell.swift in Sources */,
6841A85D4B60DB71D1E68DA0 /* ImageGrid.swift in Sources */, 6841A85D4B60DB71D1E68DA0 /* ImageGrid.swift in Sources */,
6841A4F018B0E07966C1CEFC /* PagedResponse.swift in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -843,7 +847,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 = 62; CURRENT_PROJECT_VERSION = 63;
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;
@ -866,7 +870,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 = 62; CURRENT_PROJECT_VERSION = 63;
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

@ -51,6 +51,10 @@
ReferencedContainer = "container:AutoCat.xcodeproj"> ReferencedContainer = "container:AutoCat.xcodeproj">
</BuildableReference> </BuildableReference>
</BuildableProductRunnable> </BuildableProductRunnable>
<LocationScenarioReference
identifier = "com.apple.dt.IDEFoundation.CurrentLocationScenarioIdentifier"
referenceType = "1">
</LocationScenarioReference>
</LaunchAction> </LaunchAction>
<ProfileAction <ProfileAction
buildConfiguration = "Release" buildConfiguration = "Release"

View File

@ -4,15 +4,17 @@ import RxCocoa
import RealmSwift import RealmSwift
import PKHUD import PKHUD
class SearchController: UIViewController, UISearchResultsUpdating, UITableViewDelegate { class SearchController: UIViewController, UISearchResultsUpdating, UITableViewDelegate, UIScrollViewDelegate {
@IBOutlet weak var tableView: UITableView! @IBOutlet weak var tableView: UITableView!
@IBOutlet weak var showMapButton: UIBarButtonItem! @IBOutlet weak var showMapButton: UIBarButtonItem!
let bag = DisposeBag() private let bag = DisposeBag()
let searchController = UISearchController(searchResultsController: nil) private let searchController = UISearchController(searchResultsController: nil)
var refreshControl = UIRefreshControl() private var refreshControl = UIRefreshControl()
var datasource: RxSectionedDataSource<Vehicle,VehicleCell>! private var datasource: RxSectionedDataSource<Vehicle,VehicleCell>!
private var isLoadingPage = false
private var pageLoadingIndicator = UIActivityIndicatorView(style: .medium)
var filterRelay = BehaviorRelay<Filter>(value: Filter()) var filterRelay = BehaviorRelay<Filter>(value: Filter())
var filter = Filter() var filter = Filter()
@ -28,6 +30,8 @@ class SearchController: UIViewController, UISearchResultsUpdating, UITableViewDe
navigationItem.searchController = searchController navigationItem.searchController = searchController
definesPresentationContext = true definesPresentationContext = true
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: self.pageLoadingIndicator)
//self.refreshControl.attributedTitle = NSAttributedString(string: "") //self.refreshControl.attributedTitle = NSAttributedString(string: "")
self.refreshControl.addTarget(self, action: #selector(self.refresh(_:)), for: .valueChanged) self.refreshControl.addTarget(self, action: #selector(self.refresh(_:)), for: .valueChanged)
self.tableView.addSubview(self.refreshControl) self.tableView.addSubview(self.refreshControl)
@ -39,12 +43,17 @@ class SearchController: UIViewController, UISearchResultsUpdating, UITableViewDe
self.filterRelay self.filterRelay
//.throttle(.seconds(2), scheduler: MainScheduler.instance) //.throttle(.seconds(2), scheduler: MainScheduler.instance)
.debounce(.milliseconds(500), 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) .observeOn(MainScheduler.instance)
.do(onNext: { .do(onNext: {
self.navigationItem.title = String.localizedStringWithFormat(NSLocalizedString("vehicles found", comment: ""), $0.count) if let count = $0.count {
self.showMapButton.isEnabled = $0.count > 0 self.navigationItem.title = String.localizedStringWithFormat(NSLocalizedString("vehicles found", comment: ""), count)
self.showMapButton.isEnabled = count > 0
}
self.refreshControl.endRefreshing() self.refreshControl.endRefreshing()
self.isLoadingPage = false
self.pageLoadingIndicator.stopAnimating()
}) })
.bind(to: self.datasource.data) .bind(to: self.datasource.data)
.disposed(by: self.bag) .disposed(by: self.bag)
@ -163,4 +172,14 @@ class SearchController: UIViewController, UISearchResultsUpdating, UITableViewDe
let vehicle = self.datasource.item(at: indexPath) let vehicle = self.datasource.item(at: indexPath)
self.updateDetailController(with: vehicle) 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)
}
}
} }

View 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
}
}

View File

@ -207,6 +207,7 @@ class Vehicle: Object, Decodable, Identifiable, Differentiable, Cloneable {
case isRightWheel case isRightWheel
case isJapanese case isJapanese
case addedDate case addedDate
case updatedDate
case addedBy case addedBy
case photos case photos
case ownershipPeriods case ownershipPeriods
@ -235,6 +236,7 @@ class Vehicle: Object, Decodable, Identifiable, Differentiable, Cloneable {
self.addedDate = (try container.decode(TimeInterval.self, forKey: .addedDate))/1000 self.addedDate = (try container.decode(TimeInterval.self, forKey: .addedDate))/1000
self.addedBy = try container.decode(String.self, forKey: .addedBy) self.addedBy = try container.decode(String.self, forKey: .addedBy)
self.debugInfo = try container.decodeIfPresent(DebugInfo.self, forKey: .debugInfo) 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) { if let photosArray = try container.decodeIfPresent([VehiclePhoto].self, forKey: .photos) {
self.photos.append(objectsIn: photosArray) self.photos.append(objectsIn: photosArray)
@ -248,12 +250,6 @@ class Vehicle: Object, Decodable, Identifiable, Differentiable, Cloneable {
self.events.append(objectsIn: eventsArray) 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) { if let osago = try container.decodeIfPresent([Osago].self, forKey: .osagoContracts) {
self.osagoContracts.append(objectsIn: osago) self.osagoContracts.append(objectsIn: osago)
} }

View File

@ -194,8 +194,12 @@ class Api {
return self.makeBodyRequest(api: "user/signup", body: body) return self.makeBodyRequest(api: "user/signup", body: body)
} }
public static func getVehicles(with filter: Filter) -> Single<[Vehicle]> { public static func getVehicles(with filter: Filter, pageToken: String? = nil) -> Single<PagedResponse<Vehicle>> {
return self.makeGetRequest(api: "vehicles", params: filter.queryDictionary()) 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> { public static func checkVehicle(by number: String, force: Bool = false) -> Single<Vehicle> {

View File

@ -3,10 +3,13 @@ import DifferenceKit
import RxSwift import RxSwift
import RxCocoa 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 tv: UITableView
private var cellIdentifier: String private var cellIdentifier: String
private var sections: [DateSection<Item>] = [] 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)) { init(table: UITableView, cellIdentifier: String = String(describing: Cell.self)) {
self.tv = table self.tv = table
@ -49,13 +52,26 @@ class RxSectionedDataSource<Item,Cell>: NSObject, UITableViewDataSource where I
self.sections[indexPath.section].elements[indexPath.row] = item self.sections[indexPath.section].elements[indexPath.row] = item
} }
var data: Binder<[Item]> { var data: Binder<PagedResponse<Item>> {
return Binder(self) { datasource, data in 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) let changeset = StagedChangeset(source: self.sections, target: newSections)
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 {
guard let count = self.count else { return true }
return self.items.count < count
}
} }