mirror of
https://github.com/Ranchero-Software/NetNewsWire
synced 2025-08-12 06:26:36 +00:00
Continue adopting async/await. Also: rename some Ids to IDs.
This commit is contained in:
@@ -898,6 +898,8 @@ public enum FetchType {
|
||||
noteStatusesForArticleIDsDidChange(articleIDs: articleIDs, statusKey: statusKey, flag: flag)
|
||||
}
|
||||
|
||||
/// Mark articleIDs as read. Will create statuses in the database and in memory as needed. Sends a .StatusesDidChange notification.
|
||||
/// Returns a set of new article statuses.
|
||||
func markArticleIDsAsRead(_ articleIDs: Set<String>) async throws {
|
||||
try await markArticleIDs(articleIDs, statusKey: .read, flag: true)
|
||||
}
|
||||
@@ -908,19 +910,37 @@ public enum FetchType {
|
||||
mark(articleIDs: articleIDs, statusKey: .read, flag: true, completion: completion)
|
||||
}
|
||||
|
||||
/// Mark articleIDs as unread. Will create statuses in the database and in memory as needed. Sends a .StatusesDidChange notification.
|
||||
/// Mark articleIDs as unread. Will create statuses in the database and in memory as needed. Sends a .StatusesDidChange notification.
|
||||
/// Returns a set of new article statuses.
|
||||
func markArticleIDsAsUnread(_ articleIDs: Set<String>) async throws {
|
||||
try await markArticleIDs(articleIDs, statusKey: .read, flag: false)
|
||||
}
|
||||
|
||||
/// Mark articleIDs as unread. Will create statuses in the database and in memory as needed. Sends a .StatusesDidChange notification.
|
||||
/// Returns a set of new article statuses.
|
||||
func markAsUnread(_ articleIDs: Set<String>, completion: DatabaseCompletionBlock? = nil) {
|
||||
mark(articleIDs: articleIDs, statusKey: .read, flag: false, completion: completion)
|
||||
}
|
||||
|
||||
/// Mark articleIDs as starred. Will create statuses in the database and in memory as needed. Sends a .StatusesDidChange notification.
|
||||
/// Mark articleIDs as starred. Will create statuses in the database and in memory as needed. Sends a .StatusesDidChange notification.
|
||||
/// Returns a set of new article statuses.
|
||||
func markArticleIDsAsStarred(_ articleIDs: Set<String>) async throws {
|
||||
try await markArticleIDs(articleIDs, statusKey: .starred, flag: true)
|
||||
}
|
||||
|
||||
/// Mark articleIDs as starred. Will create statuses in the database and in memory as needed. Sends a .StatusesDidChange notification.
|
||||
/// Returns a set of new article statuses.
|
||||
func markAsStarred(_ articleIDs: Set<String>, completion: DatabaseCompletionBlock? = nil) {
|
||||
mark(articleIDs: articleIDs, statusKey: .starred, flag: true, completion: completion)
|
||||
}
|
||||
|
||||
/// Mark articleIDs as unstarred. Will create statuses in the database and in memory as needed. Sends a .StatusesDidChange notification.
|
||||
/// Mark articleIDs as unstarred. Will create statuses in the database and in memory as needed. Sends a .StatusesDidChange notification.
|
||||
/// Returns a set of new article statuses.
|
||||
func markArticleIDsAsUnstarred(_ articleIDs: Set<String>) async throws {
|
||||
try await markArticleIDs(articleIDs, statusKey: .starred, flag: false)
|
||||
}
|
||||
|
||||
/// Mark articleIDs as unstarred. Will create statuses in the database and in memory as needed. Sends a .StatusesDidChange notification.
|
||||
/// Returns a set of new article statuses.
|
||||
func markAsUnstarred(_ articleIDs: Set<String>, completion: DatabaseCompletionBlock? = nil) {
|
||||
mark(articleIDs: articleIDs, statusKey: .starred, flag: false, completion: completion)
|
||||
|
||||
@@ -671,9 +671,9 @@ extension FeedlyAPICaller: FeedlyGetStreamContentsService {
|
||||
}
|
||||
}
|
||||
|
||||
extension FeedlyAPICaller: FeedlyGetStreamIdsService {
|
||||
extension FeedlyAPICaller: FeedlyGetStreamIDsService {
|
||||
|
||||
func getStreamIds(for resource: FeedlyResourceId, continuation: String? = nil, newerThan: Date?, unreadOnly: Bool?, completion: @escaping (Result<FeedlyStreamIds, Error>) -> ()) {
|
||||
func streamIDs(for resource: FeedlyResourceId, continuation: String? = nil, newerThan: Date?, unreadOnly: Bool?, completion: @escaping (Result<FeedlyStreamIDs, Error>) -> ()) {
|
||||
guard !isSuspended else {
|
||||
return DispatchQueue.main.async {
|
||||
completion(.failure(TransportError.suspended))
|
||||
@@ -724,7 +724,7 @@ extension FeedlyAPICaller: FeedlyGetStreamIdsService {
|
||||
request.addValue("application/json", forHTTPHeaderField: "Accept-Type")
|
||||
request.addValue("OAuth \(accessToken)", forHTTPHeaderField: HTTPRequestHeader.authorization)
|
||||
|
||||
send(request: request, resultType: FeedlyStreamIds.self, dateDecoding: .millisecondsSince1970, keyDecoding: .convertFromSnakeCase) { result in
|
||||
send(request: request, resultType: FeedlyStreamIDs.self, dateDecoding: .millisecondsSince1970, keyDecoding: .convertFromSnakeCase) { result in
|
||||
switch result {
|
||||
case .success(let (_, collections)):
|
||||
if let response = collections {
|
||||
|
||||
@@ -186,7 +186,7 @@ final class FeedlyAccountDelegate: AccountDelegate, Logging {
|
||||
|
||||
let group = DispatchGroup()
|
||||
|
||||
let ingestUnread = FeedlyIngestUnreadArticleIdsOperation(account: account, userId: credentials.username, service: caller, database: database, newerThan: nil)
|
||||
let ingestUnread = FeedlyIngestUnreadArticleIdsOperation(account: account, userID: credentials.username, service: caller, database: database, newerThan: nil)
|
||||
|
||||
group.enter()
|
||||
ingestUnread.completionBlock = { _ in
|
||||
|
||||
@@ -44,29 +44,29 @@ extension FeedlyFeedResourceId {
|
||||
}
|
||||
}
|
||||
|
||||
struct FeedlyCategoryResourceId: FeedlyResourceId {
|
||||
struct FeedlyCategoryResourceID: FeedlyResourceId {
|
||||
let id: String
|
||||
|
||||
enum Global {
|
||||
|
||||
static func uncategorized(for userId: String) -> FeedlyCategoryResourceId {
|
||||
static func uncategorized(for userId: String) -> FeedlyCategoryResourceID {
|
||||
// https://developer.feedly.com/cloud/#global-resource-ids
|
||||
let id = "user/\(userId)/category/global.uncategorized"
|
||||
return FeedlyCategoryResourceId(id: id)
|
||||
return FeedlyCategoryResourceID(id: id)
|
||||
}
|
||||
|
||||
/// All articles from all the feeds the user subscribes to.
|
||||
static func all(for userId: String) -> FeedlyCategoryResourceId {
|
||||
static func all(for userId: String) -> FeedlyCategoryResourceID {
|
||||
// https://developer.feedly.com/cloud/#global-resource-ids
|
||||
let id = "user/\(userId)/category/global.all"
|
||||
return FeedlyCategoryResourceId(id: id)
|
||||
return FeedlyCategoryResourceID(id: id)
|
||||
}
|
||||
|
||||
/// All articles from all the feeds the user loves most.
|
||||
static func mustRead(for userId: String) -> FeedlyCategoryResourceId {
|
||||
static func mustRead(for userId: String) -> FeedlyCategoryResourceID {
|
||||
// https://developer.feedly.com/cloud/#global-resource-ids
|
||||
let id = "user/\(userId)/category/global.must"
|
||||
return FeedlyCategoryResourceId(id: id)
|
||||
return FeedlyCategoryResourceID(id: id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// FeedlyStreamIds.swift
|
||||
// FeedlyStreamIDs.swift
|
||||
// Account
|
||||
//
|
||||
// Created by Kiel Gillard on 18/10/19.
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
struct FeedlyStreamIds: Decodable {
|
||||
struct FeedlyStreamIDs: Decodable {
|
||||
let continuation: String?
|
||||
let ids: [String]
|
||||
|
||||
|
||||
@@ -23,12 +23,12 @@ class FeedlyAddNewFeedOperation: FeedlyOperation, FeedlyOperationDelegate, Feedl
|
||||
private let database: SyncDatabase
|
||||
private let feedName: String?
|
||||
private let addToCollectionService: FeedlyAddFeedToCollectionService
|
||||
private let syncUnreadIdsService: FeedlyGetStreamIdsService
|
||||
private let syncUnreadIdsService: FeedlyGetStreamIDsService
|
||||
private let getStreamContentsService: FeedlyGetStreamContentsService
|
||||
private var feedResourceId: FeedlyFeedResourceId?
|
||||
var addCompletionHandler: ((Result<Feed, Error>) -> ())?
|
||||
|
||||
init(account: Account, credentials: Credentials, url: String, feedName: String?, searchService: FeedlySearchService, addToCollectionService: FeedlyAddFeedToCollectionService, syncUnreadIdsService: FeedlyGetStreamIdsService, getStreamContentsService: FeedlyGetStreamContentsService, database: SyncDatabase, container: Container, progress: DownloadProgress) throws {
|
||||
init(account: Account, credentials: Credentials, url: String, feedName: String?, searchService: FeedlySearchService, addToCollectionService: FeedlyAddFeedToCollectionService, syncUnreadIdsService: FeedlyGetStreamIDsService, getStreamContentsService: FeedlyGetStreamContentsService, database: SyncDatabase, container: Container, progress: DownloadProgress) throws {
|
||||
|
||||
|
||||
let validator = FeedlyFeedContainerValidator(container: container)
|
||||
@@ -94,7 +94,7 @@ class FeedlyAddNewFeedOperation: FeedlyOperation, FeedlyOperationDelegate, Feedl
|
||||
createFeeds.downloadProgress = downloadProgress
|
||||
operationQueue.add(createFeeds)
|
||||
|
||||
let syncUnread = FeedlyIngestUnreadArticleIdsOperation(account: account, userId: credentials.username, service: syncUnreadIdsService, database: database, newerThan: nil)
|
||||
let syncUnread = FeedlyIngestUnreadArticleIdsOperation(account: account, userID: credentials.username, service: syncUnreadIdsService, database: database, newerThan: nil)
|
||||
syncUnread.addDependency(createFeeds)
|
||||
syncUnread.downloadProgress = downloadProgress
|
||||
syncUnread.delegate = self
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// FeedlyGetStreamIdsOperation.swift
|
||||
// FeedlyGetStreamIDsOperation.swift
|
||||
// Account
|
||||
//
|
||||
// Created by Kiel Gillard on 18/10/19.
|
||||
@@ -10,7 +10,7 @@ import Foundation
|
||||
import RSCore
|
||||
|
||||
protocol FeedlyGetStreamIdsOperationDelegate: AnyObject {
|
||||
func feedlyGetStreamIdsOperation(_ operation: FeedlyGetStreamIdsOperation, didGet streamIds: FeedlyStreamIds)
|
||||
func feedlyGetStreamIdsOperation(_ operation: FeedlyGetStreamIdsOperation, didGet streamIds: FeedlyStreamIDs)
|
||||
}
|
||||
|
||||
/// Single responsibility is to get the stream ids from Feedly.
|
||||
@@ -24,16 +24,16 @@ final class FeedlyGetStreamIdsOperation: FeedlyOperation, FeedlyEntryIdentifierP
|
||||
return Set(ids)
|
||||
}
|
||||
|
||||
private(set) var streamIds: FeedlyStreamIds?
|
||||
private(set) var streamIds: FeedlyStreamIDs?
|
||||
|
||||
let account: Account
|
||||
let service: FeedlyGetStreamIdsService
|
||||
let service: FeedlyGetStreamIDsService
|
||||
let continuation: String?
|
||||
let resource: FeedlyResourceId
|
||||
let unreadOnly: Bool?
|
||||
let newerThan: Date?
|
||||
|
||||
init(account: Account, resource: FeedlyResourceId, service: FeedlyGetStreamIdsService, continuation: String? = nil, newerThan: Date? = nil, unreadOnly: Bool?) {
|
||||
init(account: Account, resource: FeedlyResourceId, service: FeedlyGetStreamIDsService, continuation: String? = nil, newerThan: Date? = nil, unreadOnly: Bool?) {
|
||||
self.account = account
|
||||
self.resource = resource
|
||||
self.service = service
|
||||
@@ -45,7 +45,7 @@ final class FeedlyGetStreamIdsOperation: FeedlyOperation, FeedlyEntryIdentifierP
|
||||
weak var streamIdsDelegate: FeedlyGetStreamIdsOperationDelegate?
|
||||
|
||||
override func run() {
|
||||
service.getStreamIds(for: resource, continuation: continuation, newerThan: newerThan, unreadOnly: unreadOnly) { result in
|
||||
service.streamIDs(for: resource, continuation: continuation, newerThan: newerThan, unreadOnly: unreadOnly) { result in
|
||||
switch result {
|
||||
case .success(let stream):
|
||||
self.streamIds = stream
|
||||
|
||||
@@ -18,18 +18,18 @@ class FeedlyGetUpdatedArticleIdsOperation: FeedlyOperation, FeedlyEntryIdentifie
|
||||
|
||||
private let account: Account
|
||||
private let resource: FeedlyResourceId
|
||||
private let service: FeedlyGetStreamIdsService
|
||||
private let service: FeedlyGetStreamIDsService
|
||||
private let newerThan: Date?
|
||||
|
||||
init(account: Account, resource: FeedlyResourceId, service: FeedlyGetStreamIdsService, newerThan: Date?) {
|
||||
init(account: Account, resource: FeedlyResourceId, service: FeedlyGetStreamIDsService, newerThan: Date?) {
|
||||
self.account = account
|
||||
self.resource = resource
|
||||
self.service = service
|
||||
self.newerThan = newerThan
|
||||
}
|
||||
|
||||
convenience init(account: Account, userId: String, service: FeedlyGetStreamIdsService, newerThan: Date?) {
|
||||
let all = FeedlyCategoryResourceId.Global.all(for: userId)
|
||||
convenience init(account: Account, userId: String, service: FeedlyGetStreamIDsService, newerThan: Date?) {
|
||||
let all = FeedlyCategoryResourceID.Global.all(for: userId)
|
||||
self.init(account: account, resource: all, service: service, newerThan: newerThan)
|
||||
}
|
||||
|
||||
@@ -50,10 +50,10 @@ class FeedlyGetUpdatedArticleIdsOperation: FeedlyOperation, FeedlyEntryIdentifie
|
||||
return
|
||||
}
|
||||
|
||||
service.getStreamIds(for: resource, continuation: continuation, newerThan: date, unreadOnly: nil, completion: didGetStreamIds(_:))
|
||||
service.streamIDs(for: resource, continuation: continuation, newerThan: date, unreadOnly: nil, completion: didGetStreamIds(_:))
|
||||
}
|
||||
|
||||
private func didGetStreamIds(_ result: Result<FeedlyStreamIds, Error>) {
|
||||
private func didGetStreamIds(_ result: Result<FeedlyStreamIDs, Error>) {
|
||||
guard !isCanceled else {
|
||||
didFinish()
|
||||
return
|
||||
@@ -72,7 +72,7 @@ class FeedlyGetUpdatedArticleIdsOperation: FeedlyOperation, FeedlyEntryIdentifie
|
||||
getStreamIds(continuation)
|
||||
|
||||
case .failure(let error):
|
||||
self.logger.error("Error getting FeedlyStreamIds: \(error.localizedDescription, privacy: .public).")
|
||||
self.logger.error("Error getting FeedlyStreamIDs: \(error.localizedDescription, privacy: .public).")
|
||||
didFinish(with: error)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,16 +21,16 @@ final class FeedlyIngestStarredArticleIdsOperation: FeedlyOperation, Logging {
|
||||
|
||||
private let account: Account
|
||||
private let resource: FeedlyResourceId
|
||||
private let service: FeedlyGetStreamIdsService
|
||||
private let service: FeedlyGetStreamIDsService
|
||||
private let database: SyncDatabase
|
||||
private var remoteEntryIds = Set<String>()
|
||||
|
||||
convenience init(account: Account, userId: String, service: FeedlyGetStreamIdsService, database: SyncDatabase, newerThan: Date?) {
|
||||
convenience init(account: Account, userId: String, service: FeedlyGetStreamIDsService, database: SyncDatabase, newerThan: Date?) {
|
||||
let resource = FeedlyTagResourceId.Global.saved(for: userId)
|
||||
self.init(account: account, resource: resource, service: service, database: database, newerThan: newerThan)
|
||||
}
|
||||
|
||||
init(account: Account, resource: FeedlyResourceId, service: FeedlyGetStreamIdsService, database: SyncDatabase, newerThan: Date?) {
|
||||
init(account: Account, resource: FeedlyResourceId, service: FeedlyGetStreamIDsService, database: SyncDatabase, newerThan: Date?) {
|
||||
self.account = account
|
||||
self.resource = resource
|
||||
self.service = service
|
||||
@@ -42,10 +42,10 @@ final class FeedlyIngestStarredArticleIdsOperation: FeedlyOperation, Logging {
|
||||
}
|
||||
|
||||
private func getStreamIds(_ continuation: String?) {
|
||||
service.getStreamIds(for: resource, continuation: continuation, newerThan: nil, unreadOnly: nil, completion: didGetStreamIds(_:))
|
||||
service.streamIDs(for: resource, continuation: continuation, newerThan: nil, unreadOnly: nil, completion: didGetStreamIds(_:))
|
||||
}
|
||||
|
||||
private func didGetStreamIds(_ result: Result<FeedlyStreamIds, Error>) {
|
||||
private func didGetStreamIds(_ result: Result<FeedlyStreamIDs, Error>) {
|
||||
guard !isCanceled else {
|
||||
didFinish()
|
||||
return
|
||||
|
||||
@@ -19,16 +19,16 @@ class FeedlyIngestStreamArticleIdsOperation: FeedlyOperation, Logging {
|
||||
|
||||
private let account: Account
|
||||
private let resource: FeedlyResourceId
|
||||
private let service: FeedlyGetStreamIdsService
|
||||
private let service: FeedlyGetStreamIDsService
|
||||
|
||||
init(account: Account, resource: FeedlyResourceId, service: FeedlyGetStreamIdsService) {
|
||||
init(account: Account, resource: FeedlyResourceId, service: FeedlyGetStreamIDsService) {
|
||||
self.account = account
|
||||
self.resource = resource
|
||||
self.service = service
|
||||
}
|
||||
|
||||
convenience init(account: Account, userId: String, service: FeedlyGetStreamIdsService) {
|
||||
let all = FeedlyCategoryResourceId.Global.all(for: userId)
|
||||
convenience init(account: Account, userId: String, service: FeedlyGetStreamIDsService) {
|
||||
let all = FeedlyCategoryResourceID.Global.all(for: userId)
|
||||
self.init(account: account, resource: all, service: service)
|
||||
}
|
||||
|
||||
@@ -37,10 +37,10 @@ class FeedlyIngestStreamArticleIdsOperation: FeedlyOperation, Logging {
|
||||
}
|
||||
|
||||
private func getStreamIds(_ continuation: String?) {
|
||||
service.getStreamIds(for: resource, continuation: continuation, newerThan: nil, unreadOnly: nil, completion: didGetStreamIds(_:))
|
||||
service.streamIDs(for: resource, continuation: continuation, newerThan: nil, unreadOnly: nil, completion: didGetStreamIds(_:))
|
||||
}
|
||||
|
||||
private func didGetStreamIds(_ result: Result<FeedlyStreamIds, Error>) {
|
||||
private func didGetStreamIds(_ result: Result<FeedlyStreamIDs, Error>) {
|
||||
guard !isCanceled else {
|
||||
didFinish()
|
||||
return
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
//
|
||||
// Created by Kiel Gillard on 18/10/19.
|
||||
// Copyright © 2019 Ranchero Software, LLC. All rights reserved.
|
||||
//
|
||||
///Users/brent/Projects/NetNewsWire/Account/Sources/Account/Feedly/Operations/FeedlyIngestUnreadArticleIDsOperation.swift
|
||||
|
||||
import Foundation
|
||||
import RSCore
|
||||
@@ -22,16 +22,16 @@ final class FeedlyIngestUnreadArticleIdsOperation: FeedlyOperation, Logging {
|
||||
|
||||
private let account: Account
|
||||
private let resource: FeedlyResourceId
|
||||
private let service: FeedlyGetStreamIdsService
|
||||
private let service: FeedlyGetStreamIDsService
|
||||
private let database: SyncDatabase
|
||||
private var remoteEntryIds = Set<String>()
|
||||
private var remoteEntryIDs = Set<String>()
|
||||
|
||||
convenience init(account: Account, userId: String, service: FeedlyGetStreamIdsService, database: SyncDatabase, newerThan: Date?) {
|
||||
let resource = FeedlyCategoryResourceId.Global.all(for: userId)
|
||||
convenience init(account: Account, userID: String, service: FeedlyGetStreamIDsService, database: SyncDatabase, newerThan: Date?) {
|
||||
let resource = FeedlyCategoryResourceID.Global.all(for: userID)
|
||||
self.init(account: account, resource: resource, service: service, database: database, newerThan: newerThan)
|
||||
}
|
||||
|
||||
init(account: Account, resource: FeedlyResourceId, service: FeedlyGetStreamIdsService, database: SyncDatabase, newerThan: Date?) {
|
||||
init(account: Account, resource: FeedlyResourceId, service: FeedlyGetStreamIDsService, database: SyncDatabase, newerThan: Date?) {
|
||||
self.account = account
|
||||
self.resource = resource
|
||||
self.service = service
|
||||
@@ -39,30 +39,30 @@ final class FeedlyIngestUnreadArticleIdsOperation: FeedlyOperation, Logging {
|
||||
}
|
||||
|
||||
override func run() {
|
||||
getStreamIds(nil)
|
||||
getStreamIDs(nil)
|
||||
}
|
||||
|
||||
private func getStreamIds(_ continuation: String?) {
|
||||
service.getStreamIds(for: resource, continuation: continuation, newerThan: nil, unreadOnly: true, completion: didGetStreamIds(_:))
|
||||
private func getStreamIDs(_ continuation: String?) {
|
||||
service.streamIDs(for: resource, continuation: continuation, newerThan: nil, unreadOnly: true, completion: didGetStreamIDs(_:))
|
||||
}
|
||||
|
||||
private func didGetStreamIds(_ result: Result<FeedlyStreamIds, Error>) {
|
||||
private func didGetStreamIDs(_ result: Result<FeedlyStreamIDs, Error>) {
|
||||
guard !isCanceled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
|
||||
switch result {
|
||||
case .success(let streamIds):
|
||||
case .success(let streamIDs):
|
||||
|
||||
remoteEntryIds.formUnion(streamIds.ids)
|
||||
remoteEntryIDs.formUnion(streamIDs.ids)
|
||||
|
||||
guard let continuation = streamIds.continuation else {
|
||||
removeEntryIdsWithPendingStatus()
|
||||
guard let continuation = streamIDs.continuation else {
|
||||
removeEntryIDsWithPendingStatus()
|
||||
return
|
||||
}
|
||||
|
||||
getStreamIds(continuation)
|
||||
getStreamIDs(continuation)
|
||||
|
||||
case .failure(let error):
|
||||
didFinish(with: error)
|
||||
@@ -70,7 +70,7 @@ final class FeedlyIngestUnreadArticleIdsOperation: FeedlyOperation, Logging {
|
||||
}
|
||||
|
||||
/// Do not override pending statuses with the remote statuses of the same articles, otherwise an article will temporarily re-acquire the remote status before the pending status is pushed and subseqently pulled.
|
||||
private func removeEntryIdsWithPendingStatus() {
|
||||
private func removeEntryIDsWithPendingStatus() {
|
||||
guard !isCanceled else {
|
||||
didFinish()
|
||||
return
|
||||
@@ -78,8 +78,8 @@ final class FeedlyIngestUnreadArticleIdsOperation: FeedlyOperation, Logging {
|
||||
|
||||
database.selectPendingReadStatusArticleIDs { result in
|
||||
switch result {
|
||||
case .success(let pendingArticleIds):
|
||||
self.remoteEntryIds.subtract(pendingArticleIds)
|
||||
case .success(let pendingArticleIDs):
|
||||
self.remoteEntryIDs.subtract(pendingArticleIDs)
|
||||
|
||||
self.updateUnreadStatuses()
|
||||
|
||||
@@ -106,51 +106,28 @@ final class FeedlyIngestUnreadArticleIdsOperation: FeedlyOperation, Logging {
|
||||
}
|
||||
|
||||
if let localUnreadArticleIDs {
|
||||
processUnreadArticleIDs(localUnreadArticleIDs)
|
||||
await processUnreadArticleIDs(localUnreadArticleIDs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func processUnreadArticleIDs(_ localUnreadArticleIDs: Set<String>) {
|
||||
guard !isCanceled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
@MainActor private func processUnreadArticleIDs(_ localUnreadArticleIDs: Set<String>) async {
|
||||
guard !isCanceled else {
|
||||
didFinish()
|
||||
return
|
||||
}
|
||||
|
||||
let remoteUnreadArticleIDs = remoteEntryIds
|
||||
let group = DispatchGroup()
|
||||
|
||||
final class ReadStatusResults {
|
||||
var markAsUnreadError: Error?
|
||||
var markAsReadError: Error?
|
||||
}
|
||||
|
||||
let results = ReadStatusResults()
|
||||
|
||||
group.enter()
|
||||
account.markAsUnread(remoteUnreadArticleIDs) { databaseError in
|
||||
if let databaseError = databaseError {
|
||||
results.markAsUnreadError = databaseError
|
||||
}
|
||||
group.leave()
|
||||
}
|
||||
let remoteUnreadArticleIDs = remoteEntryIDs
|
||||
|
||||
let articleIDsToMarkRead = localUnreadArticleIDs.subtracting(remoteUnreadArticleIDs)
|
||||
group.enter()
|
||||
account.markAsRead(articleIDsToMarkRead) { databaseError in
|
||||
if let databaseError = databaseError {
|
||||
results.markAsReadError = databaseError
|
||||
}
|
||||
group.leave()
|
||||
}
|
||||
do {
|
||||
try await account.markArticleIDsAsUnread(remoteUnreadArticleIDs)
|
||||
|
||||
group.notify(queue: .main) {
|
||||
let markingError = results.markAsReadError ?? results.markAsUnreadError
|
||||
guard let error = markingError else {
|
||||
self.didFinish()
|
||||
return
|
||||
}
|
||||
self.didFinish(with: error)
|
||||
}
|
||||
let articleIDsToMarkRead = localUnreadArticleIDs.subtracting(remoteUnreadArticleIDs)
|
||||
try await account.markArticleIDsAsRead(articleIDsToMarkRead)
|
||||
|
||||
didFinish()
|
||||
} catch let error {
|
||||
didFinish(with: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ final class FeedlyRequestStreamsOperation: FeedlyOperation, Logging {
|
||||
// TODO: Prioritise the must read collection/category before others so the most important content for the user loads first.
|
||||
|
||||
for collection in collectionsProvider.collections {
|
||||
let resource = FeedlyCategoryResourceId(id: collection.id)
|
||||
let resource = FeedlyCategoryResourceID(id: collection.id)
|
||||
let operation = FeedlyGetStreamContentsOperation(account: account,
|
||||
resource: resource,
|
||||
service: service,
|
||||
|
||||
@@ -32,7 +32,7 @@ final class FeedlySyncAllOperation: FeedlyOperation, Logging {
|
||||
///
|
||||
/// Download articles for statuses at the union of those statuses without its corresponding article and those included in 3 (changed since last successful sync).
|
||||
///
|
||||
init(account: Account, feedlyUserId: String, lastSuccessfulFetchStartDate: Date?, markArticlesService: FeedlyMarkArticlesService, getUnreadService: FeedlyGetStreamIdsService, getCollectionsService: FeedlyGetCollectionsService, getStreamContentsService: FeedlyGetStreamContentsService, getStarredService: FeedlyGetStreamIdsService, getStreamIdsService: FeedlyGetStreamIdsService, getEntriesService: FeedlyGetEntriesService, database: SyncDatabase, downloadProgress: DownloadProgress) {
|
||||
init(account: Account, feedlyUserId: String, lastSuccessfulFetchStartDate: Date?, markArticlesService: FeedlyMarkArticlesService, getUnreadService: FeedlyGetStreamIDsService, getCollectionsService: FeedlyGetCollectionsService, getStreamContentsService: FeedlyGetStreamContentsService, getStarredService: FeedlyGetStreamIDsService, getStreamIdsService: FeedlyGetStreamIDsService, getEntriesService: FeedlyGetEntriesService, database: SyncDatabase, downloadProgress: DownloadProgress) {
|
||||
self.syncUUID = UUID()
|
||||
self.operationQueue.suspend()
|
||||
|
||||
@@ -72,7 +72,7 @@ final class FeedlySyncAllOperation: FeedlyOperation, Logging {
|
||||
self.operationQueue.add(getAllArticleIds)
|
||||
|
||||
// Get each page of unread article ids in the global.all stream for the last 31 days (nil = Feedly API default).
|
||||
let getUnread = FeedlyIngestUnreadArticleIdsOperation(account: account, userId: feedlyUserId, service: getUnreadService, database: database, newerThan: nil)
|
||||
let getUnread = FeedlyIngestUnreadArticleIdsOperation(account: account, userID: feedlyUserId, service: getUnreadService, database: database, newerThan: nil)
|
||||
getUnread.delegate = self
|
||||
getUnread.addDependency(getAllArticleIds)
|
||||
getUnread.downloadProgress = downloadProgress
|
||||
|
||||
@@ -39,7 +39,7 @@ final class FeedlySyncStreamContentsOperation: FeedlyOperation, FeedlyOperationD
|
||||
}
|
||||
|
||||
convenience init(account: Account, credentials: Credentials, service: FeedlyGetStreamContentsService, newerThan: Date?) {
|
||||
let all = FeedlyCategoryResourceId.Global.all(for: credentials.username)
|
||||
let all = FeedlyCategoryResourceID.Global.all(for: credentials.username)
|
||||
self.init(account: account, resource: all, service: service, isPagingEnabled: true, newerThan: newerThan)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// FeedlyGetStreamIdsService.swift
|
||||
// FeedlyGetStreamIDsService.swift
|
||||
// Account
|
||||
//
|
||||
// Created by Kiel Gillard on 21/10/19.
|
||||
@@ -8,6 +8,6 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
protocol FeedlyGetStreamIdsService: AnyObject {
|
||||
func getStreamIds(for resource: FeedlyResourceId, continuation: String?, newerThan: Date?, unreadOnly: Bool?, completion: @escaping (Result<FeedlyStreamIds, Error>) -> ())
|
||||
protocol FeedlyGetStreamIDsService: AnyObject {
|
||||
func streamIDs(for resource: FeedlyResourceId, continuation: String?, newerThan: Date?, unreadOnly: Bool?, completion: @escaping (Result<FeedlyStreamIDs, Error>) -> ())
|
||||
}
|
||||
|
||||
@@ -334,7 +334,7 @@ extension NewsBlurAccountDelegate {
|
||||
|
||||
// Mark articles as unread
|
||||
let deltaUnreadArticleIDs = updatableNewsBlurUnreadStoryHashes.subtracting(currentUnreadArticleIDs)
|
||||
account.markAsUnread(deltaUnreadArticleIDs)
|
||||
try await account.markArticleIDsAsUnread(deltaUnreadArticleIDs)
|
||||
|
||||
// Mark articles as read
|
||||
let deltaReadArticleIDs = currentUnreadArticleIDs.subtracting(updatableNewsBlurUnreadStoryHashes)
|
||||
|
||||
@@ -29,7 +29,7 @@ class FeedlyGetStreamContentsOperationTests: XCTestCase {
|
||||
|
||||
func testGetStreamContentsFailure() {
|
||||
let service = TestGetStreamContentsService()
|
||||
let resource = FeedlyCategoryResourceId(id: "user/1234/category/5678")
|
||||
let resource = FeedlyCategoryResourceID(id: "user/1234/category/5678")
|
||||
|
||||
let getStreamContents = FeedlyGetStreamContentsOperation(account: account, resource: resource, service: service, continuation: nil, newerThan: nil, unreadOnly: nil, log: support.log)
|
||||
|
||||
@@ -49,7 +49,7 @@ class FeedlyGetStreamContentsOperationTests: XCTestCase {
|
||||
|
||||
func testValuesPassingForGetStreamContents() {
|
||||
let service = TestGetStreamContentsService()
|
||||
let resource = FeedlyCategoryResourceId(id: "user/1234/category/5678")
|
||||
let resource = FeedlyCategoryResourceID(id: "user/1234/category/5678")
|
||||
|
||||
let continuation: String? = "abcdefg"
|
||||
let newerThan: Date? = Date(timeIntervalSinceReferenceDate: 86)
|
||||
@@ -97,7 +97,7 @@ class FeedlyGetStreamContentsOperationTests: XCTestCase {
|
||||
let jsonName = "JSON/feedly_macintosh_initial"
|
||||
transport.testFiles["/v3/streams/contents"] = "\(jsonName).json"
|
||||
|
||||
let resource = FeedlyCategoryResourceId(id: "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/category/5ca4d61d-e55d-4999-a8d1-c3b9d8789815")
|
||||
let resource = FeedlyCategoryResourceID(id: "user/f2f031bd-f3e3-4893-a447-467a291c6d1e/category/5ca4d61d-e55d-4999-a8d1-c3b9d8789815")
|
||||
let getStreamContents = FeedlyGetStreamContentsOperation(account: account, resource: resource, service: caller, continuation: nil, newerThan: nil, unreadOnly: nil, log: support.log)
|
||||
|
||||
let completionExpectation = expectation(description: "Did Finish")
|
||||
|
||||
@@ -29,7 +29,7 @@ class FeedlyGetStreamIdsOperationTests: XCTestCase {
|
||||
|
||||
func testGetStreamIdsFailure() {
|
||||
let service = TestGetStreamIdsService()
|
||||
let resource = FeedlyCategoryResourceId(id: "user/1234/category/5678")
|
||||
let resource = FeedlyCategoryResourceID(id: "user/1234/category/5678")
|
||||
|
||||
let getStreamIds = FeedlyGetStreamIdsOperation(account: account, resource: resource, service: service, continuation: nil, newerThan: nil, unreadOnly: nil, log: support.log)
|
||||
|
||||
@@ -49,7 +49,7 @@ class FeedlyGetStreamIdsOperationTests: XCTestCase {
|
||||
|
||||
func testValuesPassingForGetStreamIds() {
|
||||
let service = TestGetStreamIdsService()
|
||||
let resource = FeedlyCategoryResourceId(id: "user/1234/category/5678")
|
||||
let resource = FeedlyCategoryResourceID(id: "user/1234/category/5678")
|
||||
|
||||
let continuation: String? = "gfdsa"
|
||||
let newerThan: Date? = Date(timeIntervalSinceReferenceDate: 1000)
|
||||
@@ -57,7 +57,7 @@ class FeedlyGetStreamIdsOperationTests: XCTestCase {
|
||||
|
||||
let getStreamIds = FeedlyGetStreamIdsOperation(account: account, resource: resource, service: service, continuation: continuation, newerThan: newerThan, unreadOnly: unreadOnly, log: support.log)
|
||||
|
||||
let mockStreamIds = FeedlyStreamIds(continuation: "1234", ids: ["item/1", "item/2", "item/3"])
|
||||
let mockStreamIds = FeedlyStreamIDs(continuation: "1234", ids: ["item/1", "item/2", "item/3"])
|
||||
service.mockResult = .success(mockStreamIds)
|
||||
service.getStreamIdsExpectation = expectation(description: "Did Call Service")
|
||||
service.parameterTester = { serviceResource, serviceContinuation, serviceNewerThan, serviceUnreadOnly in
|
||||
@@ -92,7 +92,7 @@ class FeedlyGetStreamIdsOperationTests: XCTestCase {
|
||||
let jsonName = "JSON/feedly_unreads_1000"
|
||||
transport.testFiles["/v3/streams/ids"] = "\(jsonName).json"
|
||||
|
||||
let resource = FeedlyCategoryResourceId(id: "user/1234/category/5678")
|
||||
let resource = FeedlyCategoryResourceID(id: "user/1234/category/5678")
|
||||
let getStreamIds = FeedlyGetStreamIdsOperation(account: account, resource: resource, service: caller, continuation: nil, newerThan: nil, unreadOnly: nil, log: support.log)
|
||||
|
||||
let completionExpectation = expectation(description: "Did Finish")
|
||||
|
||||
@@ -36,7 +36,7 @@ class FeedlyOrganiseParsedItemsByFeedOperationTests: XCTestCase {
|
||||
|
||||
func testNoEntries() {
|
||||
let entries = support.makeParsedItemTestDataFor(numberOfFeeds: 0, numberOfItemsInFeeds: 0)
|
||||
let resource = FeedlyCategoryResourceId(id: "user/12345/category/6789")
|
||||
let resource = FeedlyCategoryResourceID(id: "user/12345/category/6789")
|
||||
let parsedEntries = Set(entries.values.flatMap { $0 })
|
||||
let provider = TestParsedItemsProvider(resource: resource, parsedEntries: parsedEntries)
|
||||
|
||||
@@ -57,7 +57,7 @@ class FeedlyOrganiseParsedItemsByFeedOperationTests: XCTestCase {
|
||||
|
||||
func testGroupsOneEntryByFeedId() {
|
||||
let entries = support.makeParsedItemTestDataFor(numberOfFeeds: 1, numberOfItemsInFeeds: 1)
|
||||
let resource = FeedlyCategoryResourceId(id: "user/12345/category/6789")
|
||||
let resource = FeedlyCategoryResourceID(id: "user/12345/category/6789")
|
||||
let parsedEntries = Set(entries.values.flatMap { $0 })
|
||||
let provider = TestParsedItemsProvider(resource: resource, parsedEntries: parsedEntries)
|
||||
|
||||
@@ -78,7 +78,7 @@ class FeedlyOrganiseParsedItemsByFeedOperationTests: XCTestCase {
|
||||
|
||||
func testGroupsManyEntriesByFeedId() {
|
||||
let entries = support.makeParsedItemTestDataFor(numberOfFeeds: 100, numberOfItemsInFeeds: 100)
|
||||
let resource = FeedlyCategoryResourceId(id: "user/12345/category/6789")
|
||||
let resource = FeedlyCategoryResourceID(id: "user/12345/category/6789")
|
||||
let parsedEntries = Set(entries.values.flatMap { $0 })
|
||||
let provider = TestParsedItemsProvider(resource: resource, parsedEntries: parsedEntries)
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ class FeedlySyncStreamContentsOperationTests: XCTestCase {
|
||||
|
||||
func testIngestsOnePageSuccess() throws {
|
||||
let service = TestGetStreamContentsService()
|
||||
let resource = FeedlyCategoryResourceId(id: "user/1234/category/5678")
|
||||
let resource = FeedlyCategoryResourceID(id: "user/1234/category/5678")
|
||||
let newerThan: Date? = Date(timeIntervalSinceReferenceDate: 0)
|
||||
let items = service.makeMockFeedlyEntryItem()
|
||||
service.mockResult = .success(FeedlyStream(id: resource.id, updated: nil, continuation: nil, items: items))
|
||||
@@ -63,7 +63,7 @@ class FeedlySyncStreamContentsOperationTests: XCTestCase {
|
||||
|
||||
func testIngestsOnePageFailure() {
|
||||
let service = TestGetStreamContentsService()
|
||||
let resource = FeedlyCategoryResourceId(id: "user/1234/category/5678")
|
||||
let resource = FeedlyCategoryResourceID(id: "user/1234/category/5678")
|
||||
let newerThan: Date? = Date(timeIntervalSinceReferenceDate: 0)
|
||||
|
||||
service.mockResult = .failure(URLError(.timedOut))
|
||||
@@ -93,7 +93,7 @@ class FeedlySyncStreamContentsOperationTests: XCTestCase {
|
||||
|
||||
func testIngestsManyPagesSuccess() throws {
|
||||
let service = TestGetPagedStreamContentsService()
|
||||
let resource = FeedlyCategoryResourceId(id: "user/1234/category/5678")
|
||||
let resource = FeedlyCategoryResourceID(id: "user/1234/category/5678")
|
||||
let newerThan: Date? = Date(timeIntervalSinceReferenceDate: 0)
|
||||
|
||||
let continuations = (1...10).map { "\($0)" }
|
||||
|
||||
@@ -9,14 +9,14 @@
|
||||
import XCTest
|
||||
@testable import Account
|
||||
|
||||
final class TestGetPagedStreamIdsService: FeedlyGetStreamIdsService {
|
||||
final class TestGetPagedStreamIdsService: FeedlyGetStreamIDsService {
|
||||
|
||||
var parameterTester: ((FeedlyResourceId, String?, Date?, Bool?) -> ())?
|
||||
var getStreamIdsExpectation: XCTestExpectation?
|
||||
var pages = [String: FeedlyStreamIds]()
|
||||
var pages = [String: FeedlyStreamIDs]()
|
||||
|
||||
func addAtLeastOnePage(for resource: FeedlyResourceId, continuations: [String], numberOfEntriesPerPage count: Int) {
|
||||
pages = [String: FeedlyStreamIds](minimumCapacity: continuations.count + 1)
|
||||
pages = [String: FeedlyStreamIDs](minimumCapacity: continuations.count + 1)
|
||||
|
||||
// A continuation is an identifier for the next page.
|
||||
// The first page has a nil identifier.
|
||||
@@ -31,9 +31,9 @@ final class TestGetPagedStreamIdsService: FeedlyGetStreamIdsService {
|
||||
}
|
||||
}
|
||||
|
||||
private func makeStreamIds(for resource: FeedlyResourceId, continuation: String?, between range: Range<Int>) -> FeedlyStreamIds {
|
||||
private func makeStreamIds(for resource: FeedlyResourceId, continuation: String?, between range: Range<Int>) -> FeedlyStreamIDs {
|
||||
let entryIds = range.map { _ in UUID().uuidString }
|
||||
let stream = FeedlyStreamIds(continuation: continuation, ids: entryIds)
|
||||
let stream = FeedlyStreamIDs(continuation: continuation, ids: entryIds)
|
||||
return stream
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ final class TestGetPagedStreamIdsService: FeedlyGetStreamIdsService {
|
||||
return "\(stream.id)@\(continuation ?? "")"
|
||||
}
|
||||
|
||||
func getStreamIds(for resource: FeedlyResourceId, continuation: String?, newerThan: Date?, unreadOnly: Bool?, completion: @escaping (Result<FeedlyStreamIds, Error>) -> ()) {
|
||||
func getStreamIds(for resource: FeedlyResourceId, continuation: String?, newerThan: Date?, unreadOnly: Bool?, completion: @escaping (Result<FeedlyStreamIDs, Error>) -> ()) {
|
||||
let key = TestGetPagedStreamIdsService.getPagingKey(for: resource, continuation: continuation)
|
||||
guard let page = pages[key] else {
|
||||
XCTFail("Missing page for \(resource.id) and continuation \(String(describing: continuation)). Test may time out because the completion will not be called.")
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
import XCTest
|
||||
@testable import Account
|
||||
|
||||
final class TestGetStreamIdsService: FeedlyGetStreamIdsService {
|
||||
final class TestGetStreamIdsService: FeedlyGetStreamIDsService {
|
||||
|
||||
var mockResult: Result<FeedlyStreamIds, Error>?
|
||||
var mockResult: Result<FeedlyStreamIDs, Error>?
|
||||
var parameterTester: ((FeedlyResourceId, String?, Date?, Bool?) -> ())?
|
||||
var getStreamIdsExpectation: XCTestExpectation?
|
||||
|
||||
func getStreamIds(for resource: FeedlyResourceId, continuation: String?, newerThan: Date?, unreadOnly: Bool?, completion: @escaping (Result<FeedlyStreamIds, Error>) -> ()) {
|
||||
func getStreamIds(for resource: FeedlyResourceId, continuation: String?, newerThan: Date?, unreadOnly: Bool?, completion: @escaping (Result<FeedlyStreamIDs, Error>) -> ()) {
|
||||
guard let result = mockResult else {
|
||||
XCTFail("Missing mock result. Test may time out because the completion will not be called.")
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user