Merge branch 'feature/newflow' of github.com:TouchInstinct/LeadKit into feature/newflow

# Conflicts:
#	CHANGELOG.md
#	LeadKit.xcodeproj/project.pbxproj
This commit is contained in:
Ivan Smolin 2018-05-22 16:23:10 +03:00
commit cbb647afe7
8 changed files with 189 additions and 134 deletions

View File

@ -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:)

View File

@ -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"

View File

@ -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 */,

View File

@ -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() {

View File

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

View File

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

View File

@ -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()
}

View File

@ -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()
}