func fetchEvents(repo: String) {
let response = Observable.from([repo]).map { urlString -> URL in
return URL(string: "https://api.github.com/repos/\(urlString)/events")!
}.map { url -> URLRequest in
return URLRequest(url: url)
}.flatMap { request -> Observable<(response: HTTPURLResponse, data: Data)> in
return URLSession.shared.rx.response(request: request)
}.share(replay: 1) // keep in a buffer the last emitted event
response.filter { response, _ in
return 200..<300 ~= response.statusCode
}
.compactMap { _, data -> [Event]? in
return try? JSONDecoder().decode([Event].self, from: data)
}
.subscribe(onNext: { [weak self] newEvents in
self?.processEvents(newEvents)
})
.disposed(by: bag)
}
private let events = BehaviorRelay<[Event]>(value: [])
func processEvents(_ newEvents: [Event]) {
var updatedEvents = newEvents + events.value
if updatedEvents.count > 50 {
updatedEvents = [Event](updatedEvents.prefix(upTo: 50)) // this way you will show only the latest activity
}
events.accept(updatedEvents)
DispatchQueue.main.async {
self.tableView.reloadData()
self.refreshControl?.endRefreshing()
}
}
private let lastModified = BehaviorRelay<String?>(value: nil)
private let modifiedFileURL = cachedFileURL("modified.txt")
override func viewDidLoad() {
super.viewDidLoad()
if let lastModifiedString = try? String(contentsOf: modifiedFileURL, encoding: .utf8) {
lastModified.accept(lastModifiedString)
}
}
func fetchEvents(repo: String) {
let response = Observable.from([repo]).map { urlString -> URL in
return URL(string: "https://api.github.com/repos/\(urlString)/events")!
}.map { [weak self] url -> URLRequest in
var request = URLRequest(url: url)
if let modifiedHeader = self?.lastModified.value {
request.addValue(modifiedHeader, forHTTPHeaderField: "Last-Modified")
}
return request
}.flatMap { request -> Observable<(response: HTTPURLResponse, data: Data)> in
return URLSession.shared.rx.response(request: request)
}.share(replay: 1)
response.filter { response, _ in
return 200..<400 ~= response.statusCode
}
.flatMap { response, _ -> Observable<String> in
guard let value = response.allHeaderFields["Last-Modified"] as? String else {
return Observable.empty()
}
return Observable.just(value)
}
.subscribe(onNext: { [weak self] modifiedHeader in
guard let self = self else { return }
self.lastModified.accept(modifiedHeader)
try? modifiedHeader.write(to: self.modifiedFileURL, atomically: true, encoding: .utf8)
})
.disposed(by: bag)
}