Last active
May 7, 2019 09:41
-
-
Save hlung/8e4aa6439ac29577edf1fbeb580e9f3d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import RxSwift | |
import RxCocoa | |
class SimplifiedPagedResponseFetcher<LoaderInput, LoaderOutput> | |
where LoaderInput: Pageable, LoaderOutput: PagedResponse { | |
/// The main actor here 🤘. Sends all the Elements currently available. | |
let elementsRelay = BehaviorRelay<[LoaderOutput.Element]>(value: []) | |
lazy var elements: Driver<[LoaderOutput.Element]> = { return elementsRelay.asDriver() }() | |
// MARK: - Reload | |
/// Sends true during reload | |
let isReloadingRelay = BehaviorRelay<Bool>(value: false) | |
lazy var isReloading: Driver<Bool> = { return isReloadingRelay.asDriver() }() | |
/// Sends error from last reload | |
let reloadErrorRelay = BehaviorRelay<Error?>(value: nil) | |
lazy var reloadError: Driver<Error?> = { return reloadErrorRelay.asDriver() }() | |
// MARK: - Load more | |
/// Sends true during loadMore | |
let isLoadingMoreRelay = BehaviorRelay<Bool>(value: false) | |
lazy var isLoadingMore: Driver<Bool> = { return isLoadingMoreRelay.asDriver() }() | |
/// Sends error from last loadMore | |
let loadMoreErrorRelay = BehaviorRelay<Error?>(value: nil) | |
lazy var loadMoreError: Driver<Error?> = { return loadMoreErrorRelay.asDriver() }() | |
// MARK: - Other | |
/// Sends true when there is more elements to load | |
let hasMoreRelay = BehaviorRelay<Bool>(value: false) | |
lazy var hasMore: Driver<Bool> = { return hasMoreRelay.asDriver() }() | |
private var lastOutputNextCursor: String? | |
private let loader: (LoaderInput) -> Single<LoaderOutput> | |
let disposeBag = DisposeBag() | |
init(loader: @escaping (LoaderInput) -> Single<LoaderOutput>) { | |
self.loader = loader | |
} | |
func reload(_ input: LoaderInput) { | |
guard isReloadingRelay.value == false else { return } | |
isReloadingRelay.accept(true) | |
loader(input) | |
.subscribe( | |
onSuccess: { [weak self] (output) in | |
guard let weakSelf = self else { return } | |
weakSelf.lastOutputNextCursor = output.pageInfo.nextCursor | |
weakSelf.hasMoreRelay.accept(output.pageInfo.hasNextPage) | |
weakSelf.reloadErrorRelay.accept(nil) | |
let newElements = output.elements | |
weakSelf.elementsRelay.accept(newElements) | |
weakSelf.isReloadingRelay.accept(false) | |
}, onError: { [weak self] (error) in | |
guard let weakSelf = self else { return } | |
weakSelf.reloadErrorRelay.accept(error as Error?) | |
weakSelf.isReloadingRelay.accept(false) | |
}) | |
.disposed(by: disposeBag) | |
} | |
func loadMore(_ input: LoaderInput) { | |
guard isLoadingMoreRelay.value == false && hasMoreRelay.value == true else { return } | |
isLoadingMoreRelay.accept(true) | |
loader(input) | |
.subscribe( | |
onSuccess: { [weak self] (output) in | |
guard let weakSelf = self else { return } | |
weakSelf.lastOutputNextCursor = output.pageInfo.nextCursor | |
weakSelf.hasMoreRelay.accept(output.pageInfo.hasNextPage) | |
weakSelf.loadMoreErrorRelay.accept(nil) | |
let newElements = output.elements | |
let oldElements = weakSelf.elementsRelay.value | |
weakSelf.elementsRelay.accept(oldElements + newElements) | |
weakSelf.isLoadingMoreRelay.accept(false) | |
}, onError: { [weak self] (error) in | |
guard let weakSelf = self else { return } | |
weakSelf.loadMoreErrorRelay.accept(error as Error?) | |
weakSelf.isLoadingMoreRelay.accept(false) | |
}) | |
.disposed(by: disposeBag) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment