Skip to content

Instantly share code, notes, and snippets.

@devahmedshendy
Created September 9, 2022 15:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save devahmedshendy/3be8bc3e9ad3d96a3d8ac0922904a692 to your computer and use it in GitHub Desktop.
Save devahmedshendy/3be8bc3e9ad3d96a3d8ac0922904a692 to your computer and use it in GitHub Desktop.
final class UnitsViewModel {
// MARK: - Public Members/Methods
let onLoadingMoreUnits = PassthroughSubject<Bool, Never>()
let onInitialResult = PassthroughSubject<[UnitDto], Never>()
let onError = PassthroughSubject<HighLevelError.Reason, Never>()
var moreUnitsToLoad: Bool {
unitsQueue.isNotEmpty
}
// MARK: - Properties
private var unitsQueue = [UnitDto]()
private let publicUnitsSubject = CurrentValueSubject<[UnitDto], Never>([])
private var repository: Repository
private var subscription: AnyCancellable?
private var processUnitsSubscriptions: AnyCancellable?
private var unitsResultSubscription: AnyCancellable?
private var bindOnPrivateUnitsSubs: AnyCancellable?
// MARK: - init
init(repository: Repository) {
self.repository = repository
loadAllUnits()
}
// MARK: - Operations
private func loadAllUnits() {
unitsResultSubscription?.cancel()
unitsResultSubscription = nil
unitsResultSubscription = repository
.getUnits()
.sink(
receiveCompletion: (onCompletionHandler(_:)),
receiveValue: (onUnitsResultHandler(models:))
)
}
private func onUnitsResultHandler(models: [UnitModel]) {
let units = models.map(UnitDto.init(from:))
unitsQueue.append(contentsOf: units)
processUnits()
}
func processUnits() {
if !moreUnitsToLoad { return }
processUnitsSubscriptions?.cancel()
processUnitsSubscriptions = nil
onLoadingMoreUnits.send(true)
processUnitsSubscriptions = unitsQueue.enqueue(count: 3)
.publisherWithFailure
.flatMap(maxPublishers: .max(1), loadTotalUpdates(into:))
.collect()
.sink(
receiveCompletion: (onCompletionHandler(_:)),
receiveValue: (onInitialResultHandler(_ :))
)
}
private func onInitialResultHandler(_ units: [UnitDto]) {
onInitialResult.send(units)
onLoadingMoreUnits.send(false)
}
private func onCompletionHandler(_ completion: HighLevelCompletion) {
if case let .failure(error) = completion {
onError.send(error.reason)
print(error)
}
}
private func loadTotalUpdates(into unit: UnitDto) -> AnyPublisher<UnitDto, HighLevelError> {
return repository
.loadUpdates(for: UnitModel(from: unit))
.map(unit.applyUpdates(_:))
.eraseToAnyPublisher()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment