Merge branch 'feature/newflow' of github.com:TouchInstinct/LeadKit into feature/newflow
# Conflicts: # CHANGELOG.md # LeadKit.xcodeproj/project.pbxproj
This commit is contained in:
commit
cbb647afe7
11
CHANGELOG.md
11
CHANGELOG.md
|
|
@ -1,10 +1,13 @@
|
|||
# Changelog
|
||||
|
||||
### 0.7.14
|
||||
- **[Breaking change]**: Remove `ModuleConfigurator`, change type of `ConfigurableController.viewModel` property from `IUO` to plain `ViewModelT`.
|
||||
### 0.7.15
|
||||
- **[Breaking Chanage]**: Remove `ModuleConfigurator`, change type of `ConfigurableController.viewModel` property from `IUO` to plain `ViewModelT`.
|
||||
- **Add**: `InitializableView` protocol with default implementation.
|
||||
- **Update**: `ConfigurableController` protocol now inherit `InitializableView`.
|
||||
- **[Breaking change]**: `setAppearance` of `ConfigurableController` replaced with `configureAppearance` of `InitializableView`.
|
||||
- **[Breaking Change]**: `setAppearance` of `ConfigurableController` replaced with `configureAppearance` of `InitializableView`.
|
||||
|
||||
### 0.7.14
|
||||
- **[Breaking Change]**: `PaginationWrapper` separating state views from data loading.
|
||||
|
||||
### 0.7.13
|
||||
- **Update**: Migrate from `Variable` to `BehaviorRelay`.
|
||||
|
|
@ -28,7 +31,7 @@
|
|||
- **Remove**: `App`, `Log` and `LogFormatter`.
|
||||
- **Remove**: `CocoaLumberjack` dependency.
|
||||
- **Add**: Rotate operation for image drawing.
|
||||
- **Add**: `mapViewEvents` overload with closure that returns array of disposables.
|
||||
- **Add**: `mapViewEvents` overload with closure that returns array of disposables.
|
||||
- **Update**: Update `ObjectMapper` to 3.1.
|
||||
- **Add**: `apiRequestParameters` method to `NetworkServiceConfiguration` extension.
|
||||
- **Update**: Rename setToCenter(withInsets:) to pintToSuperview(withInsets:excluding:)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = "LeadKit"
|
||||
s.version = "0.7.14"
|
||||
s.version = "0.7.15"
|
||||
s.summary = "iOS framework with a bunch of tools for rapid development"
|
||||
s.homepage = "https://github.com/TouchInstinct/LeadKit"
|
||||
s.license = "Apache License, Version 2.0"
|
||||
|
|
|
|||
|
|
@ -359,7 +359,7 @@
|
|||
6774526C206249E30024EEEF /* UICollectionView+PaginationWrappable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6774526B206249E30024EEEF /* UICollectionView+PaginationWrappable.swift */; };
|
||||
6774526D206249E30024EEEF /* UICollectionView+PaginationWrappable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6774526B206249E30024EEEF /* UICollectionView+PaginationWrappable.swift */; };
|
||||
6774526E206249E30024EEEF /* UICollectionView+PaginationWrappable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6774526B206249E30024EEEF /* UICollectionView+PaginationWrappable.swift */; };
|
||||
6774527020624A2A0024EEEF /* PaginationWrapperDelegate+DefaultImplementation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6774526F20624A2A0024EEEF /* PaginationWrapperDelegate+DefaultImplementation.swift */; };
|
||||
6774527020624A2A0024EEEF /* PaginationWrapperUIDelegate+DefaultImplementation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6774526F20624A2A0024EEEF /* PaginationWrapperUIDelegate+DefaultImplementation.swift */; };
|
||||
6774527420624E820024EEEF /* DataLoadingModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6774527320624E820024EEEF /* DataLoadingModel.swift */; };
|
||||
6774527520624E820024EEEF /* DataLoadingModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6774527320624E820024EEEF /* DataLoadingModel.swift */; };
|
||||
6774527620624E820024EEEF /* DataLoadingModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6774527320624E820024EEEF /* DataLoadingModel.swift */; };
|
||||
|
|
@ -489,8 +489,6 @@
|
|||
67EB7FFE206176C900BDD9FB /* AnyPaginationWrappable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67EB7FFC206176C900BDD9FB /* AnyPaginationWrappable.swift */; };
|
||||
67EB7FFF206176C900BDD9FB /* AnyPaginationWrappable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67EB7FFC206176C900BDD9FB /* AnyPaginationWrappable.swift */; };
|
||||
67EB8001206177D600BDD9FB /* PaginationWrapperDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67EB8000206177D600BDD9FB /* PaginationWrapperDelegate.swift */; };
|
||||
67EB8002206177D600BDD9FB /* PaginationWrapperDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67EB8000206177D600BDD9FB /* PaginationWrapperDelegate.swift */; };
|
||||
67EB8003206177D600BDD9FB /* PaginationWrapperDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67EB8000206177D600BDD9FB /* PaginationWrapperDelegate.swift */; };
|
||||
67ED2BDE20B44DEB00508B3E /* InitializableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67ED2BDD20B44DEB00508B3E /* InitializableView.swift */; };
|
||||
67ED2BDF20B44DEB00508B3E /* InitializableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67ED2BDD20B44DEB00508B3E /* InitializableView.swift */; };
|
||||
67ED2BE020B44DEB00508B3E /* InitializableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67ED2BDD20B44DEB00508B3E /* InitializableView.swift */; };
|
||||
|
|
@ -507,6 +505,8 @@
|
|||
67FDC2601FA310EA00C76A77 /* RequestError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67FDC25E1FA310EA00C76A77 /* RequestError.swift */; };
|
||||
67FDC2611FA310EA00C76A77 /* RequestError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67FDC25E1FA310EA00C76A77 /* RequestError.swift */; };
|
||||
67FDC2621FA310EA00C76A77 /* RequestError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67FDC25E1FA310EA00C76A77 /* RequestError.swift */; };
|
||||
820CAD8420B43B080033EF94 /* PaginationWrapperDelegate+DefaultImplementation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 820CAD8320B43B080033EF94 /* PaginationWrapperDelegate+DefaultImplementation.swift */; };
|
||||
825F8F2820B3384C00594857 /* PaginationWrapperUIDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 825F8F2720B3384C00594857 /* PaginationWrapperUIDelegate.swift */; };
|
||||
82F8BB181F5DDED100C1061B /* Single+DeferredJust.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82F8BB171F5DDED100C1061B /* Single+DeferredJust.swift */; };
|
||||
A658E54D1F8CD7790093527A /* TableRow+SeparatorsExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A658E54C1F8CD7790093527A /* TableRow+SeparatorsExtensions.swift */; };
|
||||
A658E54E1F8CD7790093527A /* TableRow+SeparatorsExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = A658E54C1F8CD7790093527A /* TableRow+SeparatorsExtensions.swift */; };
|
||||
|
|
@ -720,7 +720,7 @@
|
|||
6771DFE91EEA7CB8002DCDAE /* DateFormattingService+MappingTransform.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DateFormattingService+MappingTransform.swift"; sourceTree = "<group>"; };
|
||||
67745267206249360024EEEF /* UITableView+PaginationWrappable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITableView+PaginationWrappable.swift"; sourceTree = "<group>"; };
|
||||
6774526B206249E30024EEEF /* UICollectionView+PaginationWrappable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UICollectionView+PaginationWrappable.swift"; sourceTree = "<group>"; };
|
||||
6774526F20624A2A0024EEEF /* PaginationWrapperDelegate+DefaultImplementation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PaginationWrapperDelegate+DefaultImplementation.swift"; sourceTree = "<group>"; };
|
||||
6774526F20624A2A0024EEEF /* PaginationWrapperUIDelegate+DefaultImplementation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PaginationWrapperUIDelegate+DefaultImplementation.swift"; sourceTree = "<group>"; };
|
||||
6774527320624E820024EEEF /* DataLoadingModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataLoadingModel.swift; sourceTree = "<group>"; };
|
||||
67745278206252020024EEEF /* DataLoadingState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataLoadingState.swift; sourceTree = "<group>"; };
|
||||
6774527F206256A20024EEEF /* RxDataLoadingModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RxDataLoadingModel.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -773,6 +773,8 @@
|
|||
67FD4381206BD24B005B0C64 /* EqutableOptionalArray.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EqutableOptionalArray.swift; sourceTree = "<group>"; };
|
||||
67FDC25E1FA310EA00C76A77 /* RequestError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RequestError.swift; sourceTree = "<group>"; };
|
||||
78405D3B3D3C3E17456877FF /* Pods_LeadKit_iOSTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeadKit_iOSTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
820CAD8320B43B080033EF94 /* PaginationWrapperDelegate+DefaultImplementation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PaginationWrapperDelegate+DefaultImplementation.swift"; sourceTree = "<group>"; };
|
||||
825F8F2720B3384C00594857 /* PaginationWrapperUIDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaginationWrapperUIDelegate.swift; sourceTree = "<group>"; };
|
||||
82F8BB171F5DDED100C1061B /* Single+DeferredJust.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "Single+DeferredJust.swift"; sourceTree = "<group>"; };
|
||||
8590CA7831555C295C5DC572 /* Pods_LeadKit_LeadKit_watchOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeadKit_LeadKit_watchOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
887F99C5326BD220C2811BD6 /* Pods_LeadKit_LeadKit_iOS_Extensions.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_LeadKit_LeadKit_iOS_Extensions.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
|
|
@ -1470,7 +1472,8 @@
|
|||
67745266206248F00024EEEF /* PaginationDataLoading */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
6774526F20624A2A0024EEEF /* PaginationWrapperDelegate+DefaultImplementation.swift */,
|
||||
6774526F20624A2A0024EEEF /* PaginationWrapperUIDelegate+DefaultImplementation.swift */,
|
||||
820CAD8320B43B080033EF94 /* PaginationWrapperDelegate+DefaultImplementation.swift */,
|
||||
6774526B206249E30024EEEF /* UICollectionView+PaginationWrappable.swift */,
|
||||
67745267206249360024EEEF /* UITableView+PaginationWrappable.swift */,
|
||||
);
|
||||
|
|
@ -1549,6 +1552,7 @@
|
|||
children = (
|
||||
67EB7FFC206176C900BDD9FB /* AnyPaginationWrappable.swift */,
|
||||
67EB8000206177D600BDD9FB /* PaginationWrapperDelegate.swift */,
|
||||
825F8F2720B3384C00594857 /* PaginationWrapperUIDelegate.swift */,
|
||||
);
|
||||
path = PaginationDataLoading;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -2597,6 +2601,7 @@
|
|||
67EB8001206177D600BDD9FB /* PaginationWrapperDelegate.swift in Sources */,
|
||||
67FD4382206BD24B005B0C64 /* EqutableOptionalArray.swift in Sources */,
|
||||
6774529A20625E5B0024EEEF /* PaginationDataLoadingState.swift in Sources */,
|
||||
825F8F2820B3384C00594857 /* PaginationWrapperUIDelegate.swift in Sources */,
|
||||
678D26A020692BFF00B05B93 /* TextFieldViewEvents.swift in Sources */,
|
||||
6727478F206CD88600725163 /* DateFormattingService.swift in Sources */,
|
||||
678D26A420692BFF00B05B93 /* TextFieldViewModelEvents.swift in Sources */,
|
||||
|
|
@ -2697,7 +2702,7 @@
|
|||
671463981EB3396E00EAB194 /* AnyLoadingIndicator.swift in Sources */,
|
||||
671463A71EB340C000EAB194 /* UIViewController+ConfigurableController.swift in Sources */,
|
||||
671463141EB3396E00EAB194 /* UIViewController+TopVisibleViewController.swift in Sources */,
|
||||
6774527020624A2A0024EEEF /* PaginationWrapperDelegate+DefaultImplementation.swift in Sources */,
|
||||
6774527020624A2A0024EEEF /* PaginationWrapperUIDelegate+DefaultImplementation.swift in Sources */,
|
||||
6727478A206CD83600725163 /* DateFormat.swift in Sources */,
|
||||
67745280206256A20024EEEF /* RxDataLoadingModel.swift in Sources */,
|
||||
A6F32C081F6EBDAA00AC08EE /* String+LocalizedComponent.swift in Sources */,
|
||||
|
|
@ -2723,6 +2728,7 @@
|
|||
6714628C1EB3396E00EAB194 /* CGImage+Alpha.swift in Sources */,
|
||||
671462741EB3396E00EAB194 /* LeadKitError.swift in Sources */,
|
||||
677452A420625FA90024EEEF /* RxDataSource.swift in Sources */,
|
||||
820CAD8420B43B080033EF94 /* PaginationWrapperDelegate+DefaultImplementation.swift in Sources */,
|
||||
671AD262206A35EC00EAF887 /* UIApplication+Cellular.swift in Sources */,
|
||||
671462D81EB3396E00EAB194 /* TimeInterval+DateComponents.swift in Sources */,
|
||||
6714638C1EB3396E00EAB194 /* SolidFillDrawingOperation.swift in Sources */,
|
||||
|
|
@ -2886,7 +2892,6 @@
|
|||
678D26A320692BFF00B05B93 /* TextFieldViewEvents.swift in Sources */,
|
||||
67153E43207DFBA80049D8C0 /* FloatingPoint+DegreesRadiansConvertion.swift in Sources */,
|
||||
67745283206256A20024EEEF /* RxDataLoadingModel.swift in Sources */,
|
||||
67EB8003206177D600BDD9FB /* PaginationWrapperDelegate.swift in Sources */,
|
||||
671463571EB3396E00EAB194 /* StaticViewHeightProtocol.swift in Sources */,
|
||||
671463631EB3396E00EAB194 /* SupportProtocol.swift in Sources */,
|
||||
671462871EB3396E00EAB194 /* CGContext+Initializers.swift in Sources */,
|
||||
|
|
@ -3090,7 +3095,6 @@
|
|||
6774526D206249E30024EEEF /* UICollectionView+PaginationWrappable.swift in Sources */,
|
||||
6714627D1EB3396E00EAB194 /* AlamofireManager+Extensions.swift in Sources */,
|
||||
673CF4352063E29B00C329F6 /* TextWithButtonPlaceholder.swift in Sources */,
|
||||
67EB8002206177D600BDD9FB /* PaginationWrapperDelegate.swift in Sources */,
|
||||
6727476F206CCDDB00725163 /* ViewBackground+Configuration.swift in Sources */,
|
||||
673CF4232063D90600C329F6 /* DisposeBagHolder.swift in Sources */,
|
||||
677452AA206263360024EEEF /* CursorType+RxDataSourceDefaultImplementation.swift in Sources */,
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ final public class PaginationWrapper<Cursor: ResettableRxDataSourceCursor, Deleg
|
|||
private var wrappedView: AnyPaginationWrappable
|
||||
private let paginationViewModel: DataLoadingModel
|
||||
private weak var delegate: Delegate?
|
||||
private weak var uiDelegate: PaginationWrapperUIDelegate?
|
||||
|
||||
/// Sets the offset between the real end of the scroll view content and the scroll position,
|
||||
/// so the handler can be triggered before reaching end. Defaults to 0.0;
|
||||
|
|
@ -70,10 +71,15 @@ final public class PaginationWrapper<Cursor: ResettableRxDataSourceCursor, Deleg
|
|||
/// - Parameters:
|
||||
/// - wrappedView: UIScrollView instance to work with.
|
||||
/// - cursor: Cursor object that acts as data source.
|
||||
/// - delegate: Delegate object for data loading events handling and UI customization.
|
||||
public init(wrappedView: AnyPaginationWrappable, cursor: Cursor, delegate: Delegate) {
|
||||
/// - delegate: Delegate object for data loading events handling.
|
||||
/// - uiDelegate: Delegate object for UI customization.
|
||||
public init(wrappedView: AnyPaginationWrappable,
|
||||
cursor: Cursor,
|
||||
delegate: Delegate,
|
||||
uiDelegate: PaginationWrapperUIDelegate? = nil) {
|
||||
self.wrappedView = wrappedView
|
||||
self.delegate = delegate
|
||||
self.uiDelegate = uiDelegate
|
||||
|
||||
self.paginationViewModel = PaginationDataLoadingModel(cursor: cursor)
|
||||
|
||||
|
|
@ -116,7 +122,7 @@ final public class PaginationWrapper<Cursor: ResettableRxDataSourceCursor, Deleg
|
|||
|
||||
removeCurrentPlaceholderView()
|
||||
|
||||
guard let loadingIndicator = delegate?.initialLoadingIndicator() else {
|
||||
guard let loadingIndicator = uiDelegate?.initialLoadingIndicator() else {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -137,7 +143,7 @@ final public class PaginationWrapper<Cursor: ResettableRxDataSourceCursor, Deleg
|
|||
|
||||
private func onLoadingMoreState(afterState: LoadingState) {
|
||||
if case .error = afterState { // user tap retry button in table footer
|
||||
delegate?.footerRetryButtonWillDisappear()
|
||||
uiDelegate?.footerRetryButtonWillDisappear()
|
||||
wrappedView.footerView = nil
|
||||
addInfiniteScroll(withHandler: false)
|
||||
wrappedView.scrollView.beginInfiniteScroll(true)
|
||||
|
|
@ -171,20 +177,19 @@ final public class PaginationWrapper<Cursor: ResettableRxDataSourceCursor, Deleg
|
|||
wrappedView.scrollView.support.refreshControl?.endRefreshing()
|
||||
}
|
||||
|
||||
let customErrorHandling = delegate?.customInitialLoadingErrorHandling(for: error) ?? false
|
||||
delegate?.clearData()
|
||||
|
||||
guard !customErrorHandling, let errorView = delegate?.errorPlaceholder(for: error) else {
|
||||
let customErrorHandling = uiDelegate?.customInitialLoadingErrorHandling(for: error) ?? false
|
||||
guard !customErrorHandling, let errorView = uiDelegate?.errorPlaceholder(for: error) else {
|
||||
return
|
||||
}
|
||||
|
||||
replacePlaceholderViewIfNeeded(with: errorView)
|
||||
|
||||
delegate?.clearView()
|
||||
} else if case .loadingMore = afterState {
|
||||
removeInfiniteScroll()
|
||||
|
||||
guard let retryButton = delegate?.footerRetryButton(),
|
||||
let retryButtonHeigth = delegate?.footerRetryButtonHeight() else {
|
||||
guard let retryButton = uiDelegate?.footerRetryButton(),
|
||||
let retryButtonHeigth = uiDelegate?.footerRetryButtonHeight() else {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -196,7 +201,7 @@ final public class PaginationWrapper<Cursor: ResettableRxDataSourceCursor, Deleg
|
|||
.drive(retryEvent)
|
||||
.disposed(by: disposeBag)
|
||||
|
||||
delegate?.footerRetryButtonWillAppear()
|
||||
uiDelegate?.footerRetryButtonWillAppear()
|
||||
|
||||
wrappedView.footerView = retryButton
|
||||
}
|
||||
|
|
@ -207,9 +212,9 @@ final public class PaginationWrapper<Cursor: ResettableRxDataSourceCursor, Deleg
|
|||
wrappedView.scrollView.support.refreshControl?.endRefreshing()
|
||||
}
|
||||
|
||||
delegate?.clearView()
|
||||
delegate?.clearData()
|
||||
|
||||
guard let emptyView = delegate?.emptyPlaceholder() else {
|
||||
guard let emptyView = uiDelegate?.emptyPlaceholder() else {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -264,7 +269,7 @@ final public class PaginationWrapper<Cursor: ResettableRxDataSourceCursor, Deleg
|
|||
wrappedView.scrollView.addInfiniteScroll { _ in }
|
||||
}
|
||||
|
||||
wrappedView.scrollView.infiniteScrollIndicatorView = delegate?.loadingMoreIndicator().view
|
||||
wrappedView.scrollView.infiniteScrollIndicatorView = uiDelegate?.loadingMoreIndicator().view
|
||||
}
|
||||
|
||||
private func removeInfiniteScroll() {
|
||||
|
|
|
|||
|
|
@ -20,62 +20,10 @@
|
|||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
public extension PaginationWrapperDelegate {
|
||||
|
||||
func emptyPlaceholder() -> UIView {
|
||||
return TextPlaceholderView(title: .empty)
|
||||
}
|
||||
|
||||
func customInitialLoadingErrorHandling(for error: Error) -> Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func errorPlaceholder(for error: Error) -> UIView {
|
||||
return TextPlaceholderView(title: .error)
|
||||
}
|
||||
|
||||
func initialLoadingIndicator() -> AnyLoadingIndicator {
|
||||
let indicator = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)
|
||||
indicator.color = .gray
|
||||
|
||||
return AnyLoadingIndicator(indicator)
|
||||
}
|
||||
|
||||
func loadingMoreIndicator() -> AnyLoadingIndicator {
|
||||
let indicator = UIActivityIndicatorView(activityIndicatorStyle: .gray)
|
||||
|
||||
return AnyLoadingIndicator(indicator)
|
||||
}
|
||||
|
||||
func footerRetryButton() -> UIButton {
|
||||
let retryButton = UIButton(type: .custom)
|
||||
retryButton.backgroundColor = .lightGray
|
||||
retryButton.setTitle("Retry load more", for: .normal)
|
||||
|
||||
return retryButton
|
||||
}
|
||||
|
||||
func footerRetryButtonHeight() -> CGFloat {
|
||||
return 44
|
||||
}
|
||||
|
||||
func footerRetryButtonWillAppear() {
|
||||
// by default - nothing will happen
|
||||
}
|
||||
|
||||
func footerRetryButtonWillDisappear() {
|
||||
// by default - nothing will happen
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public extension PaginationWrapperDelegate
|
||||
where DataSourceType: ResettableRxDataSourceCursor,
|
||||
DataSourceType.ResultType == [DataSourceType.Element] {
|
||||
DataSourceType.ResultType == [DataSourceType.Element] {
|
||||
|
||||
/// Convenient typealias.
|
||||
typealias PaginationWrapperType = PaginationWrapper<DataSourceType, Self>
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
//
|
||||
// Copyright (c) 2018 Touch Instinct
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the Software), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
|
||||
public extension PaginationWrapperUIDelegate {
|
||||
|
||||
func emptyPlaceholder() -> UIView {
|
||||
return TextPlaceholderView(title: .empty)
|
||||
}
|
||||
|
||||
func customInitialLoadingErrorHandling(for error: Error) -> Bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func errorPlaceholder(for error: Error) -> UIView {
|
||||
return TextPlaceholderView(title: .error)
|
||||
}
|
||||
|
||||
func initialLoadingIndicator() -> AnyLoadingIndicator {
|
||||
let indicator = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)
|
||||
indicator.color = .gray
|
||||
|
||||
return AnyLoadingIndicator(indicator)
|
||||
}
|
||||
|
||||
func loadingMoreIndicator() -> AnyLoadingIndicator {
|
||||
let indicator = UIActivityIndicatorView(activityIndicatorStyle: .gray)
|
||||
|
||||
return AnyLoadingIndicator(indicator)
|
||||
}
|
||||
|
||||
func footerRetryButton() -> UIButton {
|
||||
let retryButton = UIButton(type: .custom)
|
||||
retryButton.backgroundColor = .lightGray
|
||||
retryButton.setTitle("Retry load more", for: .normal)
|
||||
|
||||
return retryButton
|
||||
}
|
||||
|
||||
func footerRetryButtonHeight() -> CGFloat {
|
||||
return 44
|
||||
}
|
||||
|
||||
func footerRetryButtonWillAppear() {
|
||||
// by default - nothing will happen
|
||||
}
|
||||
|
||||
func footerRetryButtonWillDisappear() {
|
||||
// by default - nothing will happen
|
||||
}
|
||||
}
|
||||
|
|
@ -20,8 +20,7 @@
|
|||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
/// PaginationWrapper delegate used for pagination results handling and
|
||||
/// customization of bound states (loading, empty, error, etc.).
|
||||
/// PaginationWrapper delegate used for pagination results handling
|
||||
public protocol PaginationWrapperDelegate: class {
|
||||
|
||||
associatedtype DataSourceType: DataSource
|
||||
|
|
@ -42,56 +41,6 @@ public protocol PaginationWrapperDelegate: class {
|
|||
func paginationWrapper(didReload allItems: DataSourceType.ResultType,
|
||||
using dataSource: DataSourceType)
|
||||
|
||||
/// Returns placeholder view for empty state.
|
||||
///
|
||||
/// - Returns: Configured instace of UIView.
|
||||
func emptyPlaceholder() -> UIView
|
||||
|
||||
/// Called when initial loading error is occured.
|
||||
/// It should return true if error is handled and false if it doesn't.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - error: Error that occured due data loading.
|
||||
/// - Returns: Bool value. If true - then error placeholder wouldn't be shown.
|
||||
func customInitialLoadingErrorHandling(for error: Error) -> Bool
|
||||
|
||||
/// Returns placeholder view for error state.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - error: Error that occured due data loading.
|
||||
/// - Returns: Configured instace of UIView.
|
||||
func errorPlaceholder(for error: Error) -> UIView
|
||||
|
||||
/// Returns loading idicator for initial loading state.
|
||||
/// This indicator will appear at center of the placeholders container.
|
||||
///
|
||||
/// - Returns: Configured instace of AnyLoadingIndicator.
|
||||
func initialLoadingIndicator() -> AnyLoadingIndicator
|
||||
|
||||
/// Returns loading idicator for initial loading state.
|
||||
///
|
||||
/// - Returns: Configured instace of AnyLoadingIndicator.
|
||||
func loadingMoreIndicator() -> AnyLoadingIndicator
|
||||
|
||||
/// Returns instance of UIButton for "retry load more" action.
|
||||
///
|
||||
/// - Returns: Configured instace of AnyLoadingIndicator.
|
||||
func footerRetryButton() -> UIButton
|
||||
|
||||
/// Returns height for "retry load more" button.
|
||||
///
|
||||
/// - Returns: Height of "retry load more" button.
|
||||
func footerRetryButtonHeight() -> CGFloat
|
||||
|
||||
/// Method is called before "retry load more" will be shown.
|
||||
/// Typically, it's used when you need to show custom footer view.
|
||||
func footerRetryButtonWillAppear()
|
||||
|
||||
/// Method is called before "retry load more" will be hidden.
|
||||
/// Typically, it's used when you need to hide custom footer view.
|
||||
func footerRetryButtonWillDisappear()
|
||||
|
||||
/// Clears view when placeholder is shown.
|
||||
func clearView()
|
||||
|
||||
/// Handles empty data state.
|
||||
func clearData()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,75 @@
|
|||
//
|
||||
// Copyright (c) 2018 Touch Instinct
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the Software), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
|
||||
/// PaginationWrapper UI delegate used for customization
|
||||
/// of bound states (loading, empty, error, etc.).
|
||||
public protocol PaginationWrapperUIDelegate: class {
|
||||
|
||||
/// Returns placeholder view for empty state.
|
||||
///
|
||||
/// - Returns: Configured instace of UIView.
|
||||
func emptyPlaceholder() -> UIView?
|
||||
|
||||
/// Called when initial loading error is occured.
|
||||
/// It should return true if error is handled and false if it doesn't.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - error: Error that occured due data loading.
|
||||
/// - Returns: Bool value. If true - then error placeholder wouldn't be shown.
|
||||
func customInitialLoadingErrorHandling(for error: Error) -> Bool
|
||||
|
||||
/// Returns placeholder view for error state.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - error: Error that occured due data loading.
|
||||
/// - Returns: Configured instace of UIView.
|
||||
func errorPlaceholder(for error: Error) -> UIView?
|
||||
|
||||
/// Returns loading idicator for initial loading state.
|
||||
/// This indicator will appear at center of the placeholders container.
|
||||
///
|
||||
/// - Returns: Configured instace of AnyLoadingIndicator.
|
||||
func initialLoadingIndicator() -> AnyLoadingIndicator?
|
||||
|
||||
/// Returns loading idicator for initial loading state.
|
||||
///
|
||||
/// - Returns: Configured instace of AnyLoadingIndicator.
|
||||
func loadingMoreIndicator() -> AnyLoadingIndicator?
|
||||
|
||||
/// Returns instance of UIButton for "retry load more" action.
|
||||
///
|
||||
/// - Returns: Configured instace of AnyLoadingIndicator.
|
||||
func footerRetryButton() -> UIButton?
|
||||
|
||||
/// Returns height for "retry load more" button.
|
||||
///
|
||||
/// - Returns: Height of "retry load more" button.
|
||||
func footerRetryButtonHeight() -> CGFloat
|
||||
|
||||
/// Method is called before "retry load more" will be shown.
|
||||
/// Typically, it's used when you need to show custom footer view.
|
||||
func footerRetryButtonWillAppear()
|
||||
|
||||
/// Method is called before "retry load more" will be hidden.
|
||||
/// Typically, it's used when you need to hide custom footer view.
|
||||
func footerRetryButtonWillDisappear()
|
||||
}
|
||||
Loading…
Reference in New Issue