Replace retry button with retry view
This commit is contained in:
parent
e9ad33785a
commit
fcc5805dac
|
|
@ -1,5 +1,11 @@
|
|||
# Changelog
|
||||
|
||||
### 0.9.34
|
||||
- **Add**: `ButtonHolder` - protocol that contains button property.
|
||||
- **Add**: `ButtonHolderView` - view which contains button.
|
||||
- **Add**: Conformance `UIButton` to `ButtonHolderView`.
|
||||
- **[Breaking change]**: Replace functions `footerRetryButton() -> UIButton?` to `footerRetryView() -> ButtonHolderView?` and `footerRetryButtonHeight() -> CGFloat` to `footerRetryViewHeight() -> CGFloat` for `PaginationWrapperUIDelegate`.
|
||||
|
||||
### 0.9.33
|
||||
- **Fix**: `CustomizableButtonView` container class that provides great customization.
|
||||
- **Fix**: `CustomizableButtonViewModel` viewModel class for `CustomizableButtonView` configuration.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
Pod::Spec.new do |s|
|
||||
s.name = "LeadKit"
|
||||
s.version = "0.9.33"
|
||||
s.version = "0.9.34"
|
||||
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"
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@
|
|||
40F118471F8FEF97004AADAF /* AppearanceConfigurable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40F118461F8FEF97004AADAF /* AppearanceConfigurable.swift */; };
|
||||
40F118491F8FF223004AADAF /* TableRow+AppearanceExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40F118481F8FF223004AADAF /* TableRow+AppearanceExtension.swift */; };
|
||||
411073AF23466B41002DD9B9 /* UIViewController+PresentFullScreen.swift in Sources */ = {isa = PBXBuildFile; fileRef = 411073AE23466B41002DD9B9 /* UIViewController+PresentFullScreen.swift */; };
|
||||
4CF65D1424DD684A0006B001 /* ButtonHolder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CF65D1324DD684A0006B001 /* ButtonHolder.swift */; };
|
||||
4CF65D1624DD69250006B001 /* UIButton+ButtonHolder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CF65D1524DD69250006B001 /* UIButton+ButtonHolder.swift */; };
|
||||
4CF65D1824DD6C080006B001 /* ButtonHolderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4CF65D1724DD6C080006B001 /* ButtonHolderView.swift */; };
|
||||
67051ADB1EBC7C36008EADC0 /* SpinnerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67051ADA1EBC7C36008EADC0 /* SpinnerView.swift */; };
|
||||
67051ADD1EBC7C36008EADC0 /* SpinnerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 67051ADA1EBC7C36008EADC0 /* SpinnerView.swift */; };
|
||||
6713C23720AF0C4D00875921 /* NetworkOperationState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6713C23620AF0C4D00875921 /* NetworkOperationState.swift */; };
|
||||
|
|
@ -550,6 +553,9 @@
|
|||
40F118461F8FEF97004AADAF /* AppearanceConfigurable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppearanceConfigurable.swift; sourceTree = "<group>"; };
|
||||
40F118481F8FF223004AADAF /* TableRow+AppearanceExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TableRow+AppearanceExtension.swift"; sourceTree = "<group>"; };
|
||||
411073AE23466B41002DD9B9 /* UIViewController+PresentFullScreen.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+PresentFullScreen.swift"; sourceTree = "<group>"; };
|
||||
4CF65D1324DD684A0006B001 /* ButtonHolder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonHolder.swift; sourceTree = "<group>"; };
|
||||
4CF65D1524DD69250006B001 /* UIButton+ButtonHolder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIButton+ButtonHolder.swift"; sourceTree = "<group>"; };
|
||||
4CF65D1724DD6C080006B001 /* ButtonHolderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ButtonHolderView.swift; sourceTree = "<group>"; };
|
||||
67051ADA1EBC7C36008EADC0 /* SpinnerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SpinnerView.swift; sourceTree = "<group>"; };
|
||||
6713C23620AF0C4D00875921 /* NetworkOperationState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkOperationState.swift; sourceTree = "<group>"; };
|
||||
6713C23B20AF0D5900875921 /* NetworkOperationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkOperationModel.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -859,6 +865,15 @@
|
|||
path = UITableView;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
4CF65D1924DD6C3D0006B001 /* ButtonHolder */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4CF65D1324DD684A0006B001 /* ButtonHolder.swift */,
|
||||
4CF65D1724DD6C080006B001 /* ButtonHolderView.swift */,
|
||||
);
|
||||
path = ButtonHolder;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
671461C41EB3396E00EAB194 /* Classes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
|
@ -1433,6 +1448,7 @@
|
|||
6741CE9F20E2413300FEC4D9 /* UIKit */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
4CF65D1924DD6C3D0006B001 /* ButtonHolder */,
|
||||
6741CEA020E2416C00FEC4D9 /* ScrollViewHolder.swift */,
|
||||
6741CEA420E2418200FEC4D9 /* TableViewHolder.swift */,
|
||||
6741CEA820E2418B00FEC4D9 /* CollectionViewHolder.swift */,
|
||||
|
|
@ -1845,6 +1861,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
67E352512119AC060035BDDB /* UIButton+ViewTextConfigurable.swift */,
|
||||
4CF65D1524DD69250006B001 /* UIButton+ButtonHolder.swift */,
|
||||
);
|
||||
path = UIButton;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -2397,6 +2414,7 @@
|
|||
67EB7FF8206175F700BDD9FB /* PaginationWrappable.swift in Sources */,
|
||||
67990AD6213EA6A50040D195 /* ContentLoadingViewModel+Extensions.swift in Sources */,
|
||||
671463541EB3396E00EAB194 /* StaticViewHeightProtocol.swift in Sources */,
|
||||
4CF65D1824DD6C080006B001 /* ButtonHolderView.swift in Sources */,
|
||||
72AECC6B224A979D00D12E7C /* BaseSearchViewController.swift in Sources */,
|
||||
673CF4112063ABD100C329F6 /* GeneralDataLoadingState+Extensions.swift in Sources */,
|
||||
72005A1E2266226800ECE090 /* CustomizableButton.swift in Sources */,
|
||||
|
|
@ -2424,6 +2442,7 @@
|
|||
671462FC1EB3396E00EAB194 /* UIView+XibNameProtocol.swift in Sources */,
|
||||
67EB7FC0206140E600BDD9FB /* TotalCountCursor.swift in Sources */,
|
||||
36DAAF512007CC920090BE0D /* UITableView+Extensions.swift in Sources */,
|
||||
4CF65D1624DD69250006B001 /* UIButton+ButtonHolder.swift in Sources */,
|
||||
671463841EB3396E00EAB194 /* ResizeDrawingOperation.swift in Sources */,
|
||||
6774528D20625C9E0024EEEF /* GeneralDataLoadingState.swift in Sources */,
|
||||
72005A1F2266226800ECE090 /* CustomizableButtonViewModel.swift in Sources */,
|
||||
|
|
@ -2500,6 +2519,7 @@
|
|||
A6E0DDF11F8A6C80002CA74E /* SeparatorConfiguration.swift in Sources */,
|
||||
6727477F206CD3BD00725163 /* ViewText+Extensions.swift in Sources */,
|
||||
67EB7FEB2061667900BDD9FB /* DefaultTotalCountCursorListingResult.swift in Sources */,
|
||||
4CF65D1424DD684A0006B001 /* ButtonHolder.swift in Sources */,
|
||||
671AD26C206A3E8500EAF887 /* Array+TotalCountCursorListingResult.swift in Sources */,
|
||||
673CF4382063E7CE00C329F6 /* GeneralDataLoadingController+DefaultImplementation.swift in Sources */,
|
||||
B85B768720B1CF6700F837C4 /* Encodable+Extensions.swift in Sources */,
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ final public class PaginationWrapper<Cursor: ResettableRxDataSourceCursor, Deleg
|
|||
|
||||
private func onLoadingMoreState(afterState: LoadingState) {
|
||||
if case .error = afterState { // user tap retry button in table footer
|
||||
uiDelegate?.footerRetryButtonWillDisappear()
|
||||
uiDelegate?.footerRetryViewWillDisappear()
|
||||
wrappedView.footerView = nil
|
||||
addInfiniteScroll(withHandler: false)
|
||||
wrappedView.scrollView.beginInfiniteScroll(true)
|
||||
|
|
@ -187,29 +187,26 @@ final public class PaginationWrapper<Cursor: ResettableRxDataSourceCursor, Deleg
|
|||
|
||||
replacePlaceholderViewIfNeeded(with: errorView)
|
||||
} else if case .loadingMore = afterState {
|
||||
guard let retryButton = uiDelegate?.footerRetryButton(),
|
||||
let retryButtonHeight = uiDelegate?.footerRetryButtonHeight() else {
|
||||
|
||||
guard let retryView = uiDelegate?.footerRetryView(),
|
||||
let retryViewHeight = uiDelegate?.footerRetryViewHeight() else {
|
||||
removeInfiniteScroll()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
retryButton.frame = CGRect(x: 0, y: 0, width: wrappedView.scrollView.bounds.width, height: retryButtonHeight)
|
||||
retryView.frame = CGRect(x: 0, y: 0, width: wrappedView.scrollView.bounds.width, height: retryViewHeight)
|
||||
|
||||
retryButton.rx
|
||||
retryView.button.rx
|
||||
.controlEvent(.touchUpInside)
|
||||
.asDriver()
|
||||
.drive(retryEvent)
|
||||
.disposed(by: disposeBag)
|
||||
|
||||
uiDelegate?.footerRetryButtonWillAppear()
|
||||
uiDelegate?.footerRetryViewWillAppear()
|
||||
|
||||
removeInfiniteScroll { scrollView in
|
||||
self.wrappedView.footerView = retryButton
|
||||
|
||||
let newContentOffset = CGPoint(x: 0, y: scrollView.contentOffset.y + retryButtonHeight)
|
||||
self.wrappedView.footerView = retryView
|
||||
|
||||
let newContentOffset = CGPoint(x: 0, y: scrollView.contentOffset.y + retryViewHeight)
|
||||
scrollView.setContentOffset(newContentOffset, animated: true)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ open class CustomizableButtonView: UIView, InitializableView, ConfigurableView {
|
|||
configureConstraints()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public var buttonTitle: String = "" {
|
||||
willSet {
|
||||
button.text = newValue
|
||||
|
|
@ -242,7 +242,7 @@ open class CustomizableButtonView: UIView, InitializableView, ConfigurableView {
|
|||
} else {
|
||||
button.layer.cornerRadius = 0
|
||||
}
|
||||
|
||||
|
||||
setNeedsDisplay()
|
||||
}
|
||||
|
||||
|
|
@ -289,7 +289,7 @@ private extension UIView {
|
|||
}
|
||||
|
||||
public extension CustomizableButtonView {
|
||||
public struct Appearance {
|
||||
struct Appearance {
|
||||
|
||||
public var buttonFont: UIFont
|
||||
public var buttonStateAttributtedTitles: [UIControl.State: NSAttributedString]
|
||||
|
|
@ -302,7 +302,7 @@ public extension CustomizableButtonView {
|
|||
public var spinnerPosition: SpinnerPosition
|
||||
public var numberOfLines: Int
|
||||
public var alpha: CGFloat
|
||||
|
||||
|
||||
public init(buttonFont: UIFont = .systemFont(ofSize: 15),
|
||||
buttonStateAttributtedTitles: [UIControl.State: NSAttributedString] = [:],
|
||||
buttonTitleStateColors: [UIControl.State: UIColor] = [:],
|
||||
|
|
@ -329,7 +329,7 @@ public extension CustomizableButtonView {
|
|||
}
|
||||
}
|
||||
|
||||
public enum SpinnerPosition {
|
||||
enum SpinnerPosition {
|
||||
case center
|
||||
case leftToText(offset: CGFloat)
|
||||
case rightToText(offset: CGFloat)
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ public extension PaginationWrapperUIDelegate {
|
|||
return AnyLoadingIndicator(indicator)
|
||||
}
|
||||
|
||||
func footerRetryButton() -> UIButton? {
|
||||
func footerRetryView() -> ButtonHolderView? {
|
||||
let retryButton = UIButton(type: .custom)
|
||||
retryButton.backgroundColor = .lightGray
|
||||
retryButton.setTitle("Retry load more", for: .normal)
|
||||
|
|
@ -57,7 +57,7 @@ public extension PaginationWrapperUIDelegate {
|
|||
return retryButton
|
||||
}
|
||||
|
||||
func footerRetryButtonHeight() -> CGFloat {
|
||||
func footerRetryViewHeight() -> CGFloat {
|
||||
return 44
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
//
|
||||
// Copyright (c) 2020 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.UIButton
|
||||
|
||||
public extension UIButton: ButtonHolderView {
|
||||
var button: UIButton {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
//
|
||||
// Copyright (c) 2020 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.UIButton
|
||||
|
||||
/// Protocol that contains button property.
|
||||
public protocol ButtonHolder {
|
||||
|
||||
/// Contained UIButton instance.
|
||||
var button: UIButton { get }
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
//
|
||||
// Copyright (c) 2020 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.UIView
|
||||
|
||||
/// View which contains button
|
||||
public typealias ButtonHolderView = UIView & ButtonHolder
|
||||
|
|
@ -55,21 +55,21 @@ public protocol PaginationWrapperUIDelegate: class {
|
|||
/// - Returns: Configured instace of AnyLoadingIndicator.
|
||||
func loadingMoreIndicator() -> AnyLoadingIndicator?
|
||||
|
||||
/// Returns instance of UIButton for "retry load more" action.
|
||||
/// Returns instance of ButtonHolderView with retry button for "retry load more" action.
|
||||
///
|
||||
/// - Returns: Configured instace of AnyLoadingIndicator.
|
||||
func footerRetryButton() -> UIButton?
|
||||
func footerRetryView() -> ButtonHolderView?
|
||||
|
||||
/// Returns height for "retry load more" button.
|
||||
///
|
||||
/// - Returns: Height of "retry load more" button.
|
||||
func footerRetryButtonHeight() -> CGFloat
|
||||
func footerRetryViewHeight() -> 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()
|
||||
func footerRetryViewWillAppear()
|
||||
|
||||
/// Method is called before "retry load more" will be hidden.
|
||||
/// Typically, it's used when you need to hide custom footer view.
|
||||
func footerRetryButtonWillDisappear()
|
||||
func footerRetryViewWillDisappear()
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue