Update unread/starred status
This commit is contained in:
parent
b8c7e8c1c6
commit
b7e7e17656
|
@ -138,38 +138,20 @@ final class NewsBlurAPICaller: NSObject {
|
|||
}
|
||||
|
||||
func retrieveUnreadStoryHashes(completion: @escaping (Result<[NewsBlurStoryHash]?, Error>) -> Void) {
|
||||
let url = baseURL
|
||||
.appendingPathComponent("reader/unread_story_hashes")
|
||||
.appendingQueryItems([
|
||||
URLQueryItem(name: "include_timestamps", value: "true"),
|
||||
])
|
||||
retrieveStoryHashes(endpoint: "reader/unread_story_hashes", completion: completion)
|
||||
}
|
||||
|
||||
guard let callURL = url else {
|
||||
completion(.failure(TransportError.noURL))
|
||||
return
|
||||
}
|
||||
|
||||
let request = URLRequest(url: callURL, credentials: credentials)
|
||||
transport.send(request: request, resultType: NewsBlurUnreadStoryHashesResponse.self, dateDecoding: .secondsSince1970) { result in
|
||||
if self.suspended {
|
||||
completion(.failure(TransportError.suspended))
|
||||
return
|
||||
}
|
||||
|
||||
switch result {
|
||||
case .success((_, let payload)):
|
||||
completion(.success(payload?.feeds.values.flatMap { $0 }))
|
||||
case .failure(let error):
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
func retrieveStarredStoryHashes(completion: @escaping (Result<[NewsBlurStoryHash]?, Error>) -> Void) {
|
||||
retrieveStoryHashes(endpoint: "reader/starred_story_hashes", completion: completion)
|
||||
}
|
||||
|
||||
func retrieveStories(hashes: [NewsBlurStoryHash], completion: @escaping (Result<[NewsBlurStory]?, Error>) -> Void) {
|
||||
let url = baseURL
|
||||
.appendingPathComponent("reader/river_stories")
|
||||
.appendingQueryItem(.init(name: "include_hidden", value: "true"))?
|
||||
.appendingQueryItems(hashes.map { URLQueryItem(name: "h", value: $0.hash) })
|
||||
.appendingQueryItems(hashes.map {
|
||||
URLQueryItem(name: "h", value: $0.hash)
|
||||
})
|
||||
|
||||
guard let callURL = url else {
|
||||
completion(.failure(TransportError.noURL))
|
||||
|
@ -207,7 +189,37 @@ final class NewsBlurAPICaller: NSObject {
|
|||
func unstar(hashes: [String], completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
sendStoryStatus(endpoint: "reader/mark_story_hash_as_unstarred", hashes: hashes, completion: completion)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension NewsBlurAPICaller {
|
||||
private func retrieveStoryHashes(endpoint: String, completion: @escaping (Result<[NewsBlurStoryHash]?, Error>) -> Void) {
|
||||
let url = baseURL
|
||||
.appendingPathComponent(endpoint)
|
||||
.appendingQueryItems([
|
||||
URLQueryItem(name: "include_timestamps", value: "true"),
|
||||
])
|
||||
|
||||
guard let callURL = url else {
|
||||
completion(.failure(TransportError.noURL))
|
||||
return
|
||||
}
|
||||
|
||||
let request = URLRequest(url: callURL, credentials: credentials)
|
||||
transport.send(request: request, resultType: NewsBlurUnreadStoryHashesResponse.self, dateDecoding: .secondsSince1970) { result in
|
||||
if self.suspended {
|
||||
completion(.failure(TransportError.suspended))
|
||||
return
|
||||
}
|
||||
|
||||
switch result {
|
||||
case .success((_, let payload)):
|
||||
completion(.success(payload?.feeds.values.flatMap { $0 }))
|
||||
case .failure(let error):
|
||||
completion(.failure(error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func sendStoryStatus(endpoint: String, hashes: [String], completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
let callURL = baseURL.appendingPathComponent(endpoint)
|
||||
|
||||
|
|
|
@ -181,9 +181,45 @@ final class NewsBlurAccountDelegate: AccountDelegate {
|
|||
}
|
||||
|
||||
func refreshArticleStatus(for account: Account, completion: @escaping (Result<Void, Error>) -> ()) {
|
||||
os_log(.debug, log: log, "Refreshing article statuses...")
|
||||
os_log(.debug, log: log, "Refreshing story statuses...")
|
||||
|
||||
// TODO: Fill this in
|
||||
let group = DispatchGroup()
|
||||
var errorOccurred = false
|
||||
|
||||
group.enter()
|
||||
caller.retrieveUnreadStoryHashes { result in
|
||||
switch result {
|
||||
case .success(let storyHashes):
|
||||
self.syncStoryReadState(account: account, hashes: storyHashes)
|
||||
group.leave()
|
||||
case .failure(let error):
|
||||
errorOccurred = true
|
||||
os_log(.info, log: self.log, "Retrieving unread stories failed: %@.", error.localizedDescription)
|
||||
group.leave()
|
||||
}
|
||||
}
|
||||
|
||||
group.enter()
|
||||
caller.retrieveStarredStoryHashes { result in
|
||||
switch result {
|
||||
case .success(let storyHashes):
|
||||
self.syncStoryStarredState(account: account, hashes: storyHashes)
|
||||
group.leave()
|
||||
case .failure(let error):
|
||||
errorOccurred = true
|
||||
os_log(.info, log: self.log, "Retrieving starred stories failed: %@.", error.localizedDescription)
|
||||
group.leave()
|
||||
}
|
||||
}
|
||||
|
||||
group.notify(queue: DispatchQueue.main) {
|
||||
os_log(.debug, log: self.log, "Done refreshing article statuses.")
|
||||
if errorOccurred {
|
||||
completion(.failure(NewsBlurError.unknown))
|
||||
} else {
|
||||
completion(.success(()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func refreshStories(for account: Account, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||
|
@ -548,9 +584,7 @@ extension NewsBlurAccountDelegate {
|
|||
}
|
||||
|
||||
private func mapStoriesToParsedItems(stories: [NewsBlurStory]?) -> Set<ParsedItem> {
|
||||
guard let stories = stories else {
|
||||
return Set<ParsedItem>()
|
||||
}
|
||||
guard let stories = stories else { return Set<ParsedItem>() }
|
||||
|
||||
let parsedItems: [ParsedItem] = stories.map { story in
|
||||
let author = Set([ParsedAuthor(name: story.authorName, url: nil, avatarURL: nil, emailAddress: nil)])
|
||||
|
@ -598,4 +632,70 @@ extension NewsBlurAccountDelegate {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func syncStoryReadState(account: Account, hashes: [NewsBlurStoryHash]?) {
|
||||
guard let hashes = hashes else { return }
|
||||
|
||||
database.selectPendingReadStatusArticleIDs() { result in
|
||||
func process(_ pendingStoryHashes: Set<String>) {
|
||||
|
||||
let newsBlurUnreadStoryHashes = Set(hashes.map { $0.hash } )
|
||||
let updatableNewsBlurUnreadStoryHashes = newsBlurUnreadStoryHashes.subtracting(pendingStoryHashes)
|
||||
|
||||
account.fetchUnreadArticleIDs { articleIDsResult in
|
||||
guard let currentUnreadArticleIDs = try? articleIDsResult.get() else {
|
||||
return
|
||||
}
|
||||
|
||||
// Mark articles as unread
|
||||
let deltaUnreadArticleIDs = updatableNewsBlurUnreadStoryHashes.subtracting(currentUnreadArticleIDs)
|
||||
account.markAsUnread(deltaUnreadArticleIDs)
|
||||
|
||||
// Mark articles as read
|
||||
let deltaReadArticleIDs = currentUnreadArticleIDs.subtracting(updatableNewsBlurUnreadStoryHashes)
|
||||
account.markAsRead(deltaReadArticleIDs)
|
||||
}
|
||||
}
|
||||
|
||||
switch result {
|
||||
case .success(let pendingArticleIDs):
|
||||
process(pendingArticleIDs)
|
||||
case .failure(let error):
|
||||
os_log(.error, log: self.log, "Sync Story Read Status failed: %@.", error.localizedDescription)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func syncStoryStarredState(account: Account, hashes: [NewsBlurStoryHash]?) {
|
||||
guard let hashes = hashes else { return }
|
||||
|
||||
database.selectPendingStarredStatusArticleIDs() { result in
|
||||
func process(_ pendingStoryHashes: Set<String>) {
|
||||
|
||||
let newsBlurStarredStoryHashes = Set(hashes.map { $0.hash } )
|
||||
let updatableNewsBlurUnreadStoryHashes = newsBlurStarredStoryHashes.subtracting(pendingStoryHashes)
|
||||
|
||||
account.fetchStarredArticleIDs { articleIDsResult in
|
||||
guard let currentStarredArticleIDs = try? articleIDsResult.get() else {
|
||||
return
|
||||
}
|
||||
|
||||
// Mark articles as starred
|
||||
let deltaStarredArticleIDs = updatableNewsBlurUnreadStoryHashes.subtracting(currentStarredArticleIDs)
|
||||
account.markAsStarred(deltaStarredArticleIDs)
|
||||
|
||||
// Mark articles as unstarred
|
||||
let deltaUnstarredArticleIDs = currentStarredArticleIDs.subtracting(updatableNewsBlurUnreadStoryHashes)
|
||||
account.markAsUnstarred(deltaUnstarredArticleIDs)
|
||||
}
|
||||
}
|
||||
|
||||
switch result {
|
||||
case .success(let pendingArticleIDs):
|
||||
process(pendingArticleIDs)
|
||||
case .failure(let error):
|
||||
os_log(.error, log: self.log, "Sync Story Starred Status failed: %@.", error.localizedDescription)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue