Search pagination
This commit is contained in:
parent
3ce8e2d0ae
commit
7ec9c50886
@ -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;
|
||||||
|
|||||||
@ -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"
|
||||||
|
|||||||
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
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 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)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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> {
|
||||||
|
|||||||
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user