Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
//
// AcceptRejectItems.swift
//
// Created by Daniel Tartaglia on 9 Jan 2019.
// Copyright © 2019 Daniel Tartaglia. MIT License
//
import RxSwift
struct Input {
let accept: Observable<Void>
let reject: Observable<Void>
let applyAll: Observable<Bool>
}
struct ViewModel<Item> {
let items: Observable<Item>
let remaining: Observable<Int>
let insertions: Observable<Item>
}
extension ViewModel {
init(_ input: Input, items: [Item]) {
if items.isEmpty {
self.items = Observable.empty()
self.remaining = Observable.empty()
self.insertions = Observable.never()
}
else {
let accepted = Observable.merge(input.accept.map { true }, input.reject.map { false })
let complete = accepted.withLatestFrom(input.applyAll)
.take(items.count)
.filter { $0 }
.take(1)
.materialize()
.filter { $0.isCompleted }
self.items = Observable.zip(Observable.from(items[1...]), accepted)
.map { $0.0 }
.startWith(items[0])
.concat(Observable.never())
.takeUntil(complete)
self.remaining = accepted.withLatestFrom(input.applyAll)
.scan(items.count) { last, all in all ? 0 : last - 1 }
.startWith(items.count)
.takeUntil(complete)
.take(items.count + 1)
.filter { $0 != 0 }
self.insertions = accepted.withLatestFrom(input.applyAll) { (accepted: $0, applyAll: $1) }
.scan((accept: nil as Item?, items: items, apply: false)) { prev, next in
if next.accepted {
return (accept: prev.items[0], items: Array(prev.items[1...]), apply: next.applyAll)
}
else {
return (accept: nil, items: Array(prev.items[1...]), apply: next.applyAll)
}
}
.flatMap { (arg) -> Observable<Item> in
let (accept, items, applyAll) = arg
if let item = accept {
if applyAll {
return Observable.from([item] + items)
}
else {
return Observable.just(item)
}
}
else {
return Observable.empty()
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.