diff --git a/Frameworks/Account/Account.swift b/Frameworks/Account/Account.swift index 0eaa2e854..bc510b1bc 100644 --- a/Frameworks/Account/Account.swift +++ b/Frameworks/Account/Account.swift @@ -564,16 +564,16 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container, database.fetchStarredAndUnreadCount(for: flattenedFeeds().feedIDs(), callback: callback) } - public func fetchUnreadArticleIDs(_ callback: @escaping (Set) -> Void) { - database.fetchUnreadArticleIDs(callback) + public func fetchUnreadArticleIDs() -> Set { + return database.fetchUnreadArticleIDs() } - public func fetchStarredArticleIDs(_ callback: @escaping (Set) -> Void) { - database.fetchStarredArticleIDs(callback) + public func fetchStarredArticleIDs() -> Set { + return database.fetchStarredArticleIDs() } - public func fetchArticleIDsForStatusesWithoutArticles(_ callback: @escaping (Set) -> Void) { - database.fetchArticleIDsForStatusesWithoutArticles(callback) + public func fetchArticleIDsForStatusesWithoutArticles() -> Set { + return database.fetchArticleIDsForStatusesWithoutArticles() } public func opmlDocument() -> String { @@ -657,9 +657,9 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container, return updatedArticles } - func ensureStatuses(_ articleIDs: Set, _ statusKey: ArticleStatus.Key, _ flag: Bool) { + func ensureStatuses(_ articleIDs: Set, _ defaultRead: Bool, _ statusKey: ArticleStatus.Key, _ flag: Bool) { if !articleIDs.isEmpty { - database.ensureStatuses(articleIDs, statusKey, flag) + database.ensureStatuses(articleIDs, defaultRead, statusKey, flag) } } diff --git a/Frameworks/Account/Feedbin/FeedbinAccountDelegate.swift b/Frameworks/Account/Feedbin/FeedbinAccountDelegate.swift index 9ff14275a..6c9f3e8e9 100644 --- a/Frameworks/Account/Feedbin/FeedbinAccountDelegate.swift +++ b/Frameworks/Account/Feedbin/FeedbinAccountDelegate.swift @@ -83,9 +83,9 @@ final class FeedbinAccountDelegate: AccountDelegate { switch result { case .success(): - self.refreshArticles(account) { - self.sendArticleStatus(for: account) { - self.refreshArticleStatus(for: account) { + self.sendArticleStatus(for: account) { + self.refreshArticleStatus(for: account) { + self.refreshArticles(account) { self.refreshMissingArticles(account) { self.refreshProgress.clear() DispatchQueue.main.async { @@ -948,8 +948,8 @@ private extension FeedbinAccountDelegate { case .success(let (entries, page)): self.processEntries(account: account, entries: entries) { - self.refreshArticles(account, page: page) { - self.refreshArticleStatus(for: account) { + self.refreshArticleStatus(for: account) { + self.refreshArticles(account, page: page) { self.refreshProgress.completeTask() self.refreshMissingArticles(account) { self.refreshProgress.completeTask() @@ -1005,24 +1005,24 @@ private extension FeedbinAccountDelegate { os_log(.debug, log: log, "Refreshing missing articles...") let group = DispatchGroup() - account.fetchArticleIDsForStatusesWithoutArticles { (fetchedArticleIDs) in - let articleIDs = Array(fetchedArticleIDs) - let chunkedArticleIDs = articleIDs.chunked(into: 100) - for chunk in chunkedArticleIDs { - group.enter() - self.caller.retrieveEntries(articleIDs: chunk) { result in + let fetchedArticleIDs = account.fetchArticleIDsForStatusesWithoutArticles() + let articleIDs = Array(fetchedArticleIDs) + let chunkedArticleIDs = articleIDs.chunked(into: 100) - switch result { - case .success(let entries): + for chunk in chunkedArticleIDs { + group.enter() + self.caller.retrieveEntries(articleIDs: chunk) { result in - self.processEntries(account: account, entries: entries) { - group.leave() - } + switch result { + case .success(let entries): - case .failure(let error): - os_log(.error, log: self.log, "Refresh missing articles failed: %@.", error.localizedDescription) + self.processEntries(account: account, entries: entries) { group.leave() } + + case .failure(let error): + os_log(.error, log: self.log, "Refresh missing articles failed: %@.", error.localizedDescription) + group.leave() } } } @@ -1110,29 +1110,28 @@ private extension FeedbinAccountDelegate { } let feedbinUnreadArticleIDs = Set(articleIDs.map { String($0) } ) - account.fetchUnreadArticleIDs { (currentUnreadArticleIDs) in - // Mark articles as unread - let deltaUnreadArticleIDs = feedbinUnreadArticleIDs.subtracting(currentUnreadArticleIDs) - account.fetchArticlesAsync(.articleIDs(deltaUnreadArticleIDs)) { (markUnreadArticles) in - account.update(markUnreadArticles, statusKey: .read, flag: false) + let currentUnreadArticleIDs = account.fetchUnreadArticleIDs() + + // Mark articles as unread + let deltaUnreadArticleIDs = feedbinUnreadArticleIDs.subtracting(currentUnreadArticleIDs) + let markUnreadArticles = account.fetchArticles(.articleIDs(deltaUnreadArticleIDs)) + account.update(markUnreadArticles, statusKey: .read, flag: false) - // Save any unread statuses for articles we haven't yet received - let markUnreadArticleIDs = Set(markUnreadArticles.map { $0.articleID }) - let missingUnreadArticleIDs = deltaUnreadArticleIDs.subtracting(markUnreadArticleIDs) - account.ensureStatuses(missingUnreadArticleIDs, .read, false) - } + // Save any unread statuses for articles we haven't yet received + let markUnreadArticleIDs = Set(markUnreadArticles.map { $0.articleID }) + let missingUnreadArticleIDs = deltaUnreadArticleIDs.subtracting(markUnreadArticleIDs) + account.ensureStatuses(missingUnreadArticleIDs, true, .read, false) - // Mark articles as read - let deltaReadArticleIDs = currentUnreadArticleIDs.subtracting(feedbinUnreadArticleIDs) - account.fetchArticlesAsync(.articleIDs(deltaReadArticleIDs)) { (markReadArticles) in - account.update(markReadArticles, statusKey: .read, flag: true) + // Mark articles as read + let deltaReadArticleIDs = currentUnreadArticleIDs.subtracting(feedbinUnreadArticleIDs) + let markReadArticles = account.fetchArticles(.articleIDs(deltaReadArticleIDs)) + account.update(markReadArticles, statusKey: .read, flag: true) + + // Save any read statuses for articles we haven't yet received + let markReadArticleIDs = Set(markReadArticles.map { $0.articleID }) + let missingReadArticleIDs = deltaReadArticleIDs.subtracting(markReadArticleIDs) + account.ensureStatuses(missingReadArticleIDs, true, .read, true) - // Save any read statuses for articles we haven't yet received - let markReadArticleIDs = Set(markReadArticles.map { $0.articleID }) - let missingReadArticleIDs = deltaReadArticleIDs.subtracting(markReadArticleIDs) - account.ensureStatuses(missingReadArticleIDs, .read, true) - } - } } func syncArticleStarredState(account: Account, articleIDs: [Int]?) { @@ -1141,29 +1140,27 @@ private extension FeedbinAccountDelegate { } let feedbinStarredArticleIDs = Set(articleIDs.map { String($0) } ) - account.fetchStarredArticleIDs { (currentStarredArticleIDs) in - // Mark articles as starred - let deltaStarredArticleIDs = feedbinStarredArticleIDs.subtracting(currentStarredArticleIDs) - account.fetchArticlesAsync(.articleIDs(deltaStarredArticleIDs)) { (markStarredArticles) in - account.update(markStarredArticles, statusKey: .starred, flag: true) + let currentStarredArticleIDs = account.fetchStarredArticleIDs() + + // Mark articles as starred + let deltaStarredArticleIDs = feedbinStarredArticleIDs.subtracting(currentStarredArticleIDs) + let markStarredArticles = account.fetchArticles(.articleIDs(deltaStarredArticleIDs)) + account.update(markStarredArticles, statusKey: .starred, flag: true) - // Save any starred statuses for articles we haven't yet received - let markStarredArticleIDs = Set(markStarredArticles.map { $0.articleID }) - let missingStarredArticleIDs = deltaStarredArticleIDs.subtracting(markStarredArticleIDs) - account.ensureStatuses(missingStarredArticleIDs, .starred, true) - } + // Save any starred statuses for articles we haven't yet received + let markStarredArticleIDs = Set(markStarredArticles.map { $0.articleID }) + let missingStarredArticleIDs = deltaStarredArticleIDs.subtracting(markStarredArticleIDs) + account.ensureStatuses(missingStarredArticleIDs, true, .starred, true) - // Mark articles as unstarred - let deltaUnstarredArticleIDs = currentStarredArticleIDs.subtracting(feedbinStarredArticleIDs) - account.fetchArticlesAsync(.articleIDs(deltaUnstarredArticleIDs)) { (markUnstarredArticles) in - account.update(markUnstarredArticles, statusKey: .starred, flag: false) + // Mark articles as unstarred + let deltaUnstarredArticleIDs = currentStarredArticleIDs.subtracting(feedbinStarredArticleIDs) + let markUnstarredArticles = account.fetchArticles(.articleIDs(deltaUnstarredArticleIDs)) + account.update(markUnstarredArticles, statusKey: .starred, flag: false) - // Save any unstarred statuses for articles we haven't yet received - let markUnstarredArticleIDs = Set(markUnstarredArticles.map { $0.articleID }) - let missingUnstarredArticleIDs = deltaUnstarredArticleIDs.subtracting(markUnstarredArticleIDs) - account.ensureStatuses(missingUnstarredArticleIDs, .starred, false) - } - } + // Save any unstarred statuses for articles we haven't yet received + let markUnstarredArticleIDs = Set(markUnstarredArticles.map { $0.articleID }) + let missingUnstarredArticleIDs = deltaUnstarredArticleIDs.subtracting(markUnstarredArticleIDs) + account.ensureStatuses(missingUnstarredArticleIDs, true, .starred, false) } func deleteTagging(for account: Account, with feed: Feed, from container: Container?, completion: @escaping (Result) -> Void) { diff --git a/Frameworks/ArticlesDatabase/ArticlesDatabase.swift b/Frameworks/ArticlesDatabase/ArticlesDatabase.swift index 951162def..d3e455e36 100644 --- a/Frameworks/ArticlesDatabase/ArticlesDatabase.swift +++ b/Frameworks/ArticlesDatabase/ArticlesDatabase.swift @@ -122,22 +122,22 @@ public final class ArticlesDatabase { return articlesTable.update(feedID, parsedItems, defaultRead, completion) } - public func ensureStatuses(_ articleIDs: Set, _ statusKey: ArticleStatus.Key, _ flag: Bool) { - articlesTable.ensureStatuses(articleIDs, statusKey, flag) + public func ensureStatuses(_ articleIDs: Set, _ defaultRead: Bool, _ statusKey: ArticleStatus.Key, _ flag: Bool) { + articlesTable.ensureStatuses(articleIDs, defaultRead, statusKey, flag) } // MARK: - Status - public func fetchUnreadArticleIDs(_ callback: @escaping (Set) -> Void) { - articlesTable.fetchUnreadArticleIDs(callback) + public func fetchUnreadArticleIDs() -> Set { + return articlesTable.fetchUnreadArticleIDs() } - public func fetchStarredArticleIDs(_ callback: @escaping (Set) -> Void) { - articlesTable.fetchStarredArticleIDs(callback) + public func fetchStarredArticleIDs() -> Set { + return articlesTable.fetchStarredArticleIDs() } - public func fetchArticleIDsForStatusesWithoutArticles(_ callback: @escaping (Set) -> Void) { - articlesTable.fetchArticleIDsForStatusesWithoutArticles(callback) + public func fetchArticleIDsForStatusesWithoutArticles() -> Set { + return articlesTable.fetchArticleIDsForStatusesWithoutArticles() } public func mark(_ articles: Set
, statusKey: ArticleStatus.Key, flag: Bool) -> Set? { diff --git a/Frameworks/ArticlesDatabase/ArticlesTable.swift b/Frameworks/ArticlesDatabase/ArticlesTable.swift index 444337e20..3ac4de861 100644 --- a/Frameworks/ArticlesDatabase/ArticlesTable.swift +++ b/Frameworks/ArticlesDatabase/ArticlesTable.swift @@ -267,9 +267,9 @@ final class ArticlesTable: DatabaseTable { } } - func ensureStatuses(_ articleIDs: Set, _ statusKey: ArticleStatus.Key, _ flag: Bool) { + func ensureStatuses(_ articleIDs: Set, _ defaultRead: Bool, _ statusKey: ArticleStatus.Key, _ flag: Bool) { self.queue.update { (database) in - let statusesDictionary = self.statusesTable.ensureStatusesForArticleIDs(articleIDs, false, database) + let statusesDictionary = self.statusesTable.ensureStatusesForArticleIDs(articleIDs, defaultRead, database) let statuses = Set(statusesDictionary.values) self.statusesTable.mark(statuses, statusKey, flag, database) } @@ -371,16 +371,16 @@ final class ArticlesTable: DatabaseTable { // MARK: - Statuses - func fetchUnreadArticleIDs(_ callback: @escaping (Set) -> Void) { - statusesTable.fetchUnreadArticleIDs(callback) + func fetchUnreadArticleIDs() -> Set{ + return statusesTable.fetchUnreadArticleIDs() } - func fetchStarredArticleIDs(_ callback: @escaping (Set) -> Void) { - statusesTable.fetchStarredArticleIDs(callback) + func fetchStarredArticleIDs() -> Set { + return statusesTable.fetchStarredArticleIDs() } - func fetchArticleIDsForStatusesWithoutArticles(_ callback: @escaping (Set) -> Void) { - statusesTable.fetchArticleIDsForStatusesWithoutArticles(callback) + func fetchArticleIDsForStatusesWithoutArticles() -> Set { + return statusesTable.fetchArticleIDsForStatusesWithoutArticles() } func mark(_ articles: Set
, _ statusKey: ArticleStatus.Key, _ flag: Bool) -> Set? { diff --git a/Frameworks/ArticlesDatabase/StatusesTable.swift b/Frameworks/ArticlesDatabase/StatusesTable.swift index e8b5078c3..0bb18377d 100644 --- a/Frameworks/ArticlesDatabase/StatusesTable.swift +++ b/Frameworks/ArticlesDatabase/StatusesTable.swift @@ -74,27 +74,27 @@ final class StatusesTable: DatabaseTable { // MARK: - Fetching - func fetchUnreadArticleIDs(_ callback: @escaping (Set) -> Void) { - fetchArticleIDs("select articleID from statuses where read=0 and userDeleted=0;", callback) + func fetchUnreadArticleIDs() -> Set { + return fetchArticleIDs("select articleID from statuses where read=0 and userDeleted=0;") } - func fetchStarredArticleIDs(_ callback: @escaping (Set) -> Void) { - fetchArticleIDs("select articleID from statuses where starred=1 and userDeleted=0;", callback) + func fetchStarredArticleIDs() -> Set { + return fetchArticleIDs("select articleID from statuses where starred=1 and userDeleted=0;") } - func fetchArticleIDsForStatusesWithoutArticles(_ callback: @escaping (Set) -> Void) { - fetchArticleIDs("select articleID from statuses s where (read=0 or starred=1) and userDeleted=0 and not exists (select 1 from articles a where a.articleID = s.articleID);", callback) + func fetchArticleIDsForStatusesWithoutArticles() -> Set { + return fetchArticleIDs("select articleID from statuses s where (read=0 or starred=1) and userDeleted=0 and not exists (select 1 from articles a where a.articleID = s.articleID);") } - func fetchArticleIDs(_ sql: String, _ callback: @escaping (Set) -> Void) { - queue.fetch { (database) in + func fetchArticleIDs(_ sql: String) -> Set { + var articleIDs = Set() + queue.fetchSync { (database) in guard let resultSet = database.executeQuery(sql, withArgumentsIn: nil) else { - callback(Set()) return } - let statuses = resultSet.mapToSet(self.articleIDWithRow) - callback(statuses) + articleIDs = resultSet.mapToSet(self.articleIDWithRow) } + return articleIDs } func articleIDWithRow(_ row: FMResultSet) -> String? { diff --git a/Mac/Resources/Info.plist b/Mac/Resources/Info.plist index bffec6487..02b218ceb 100644 --- a/Mac/Resources/Info.plist +++ b/Mac/Resources/Info.plist @@ -17,7 +17,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 5.0 + 5.0.1a CFBundleURLTypes @@ -33,7 +33,7 @@ CFBundleVersion - 2609 + 2610 LSApplicationCategoryType public.app-category.news LSMinimumSystemVersion @@ -44,7 +44,7 @@ NSAppleEventsUsageDescription - NetNewsWire communicates with other apps on your Mac when you choose to share a news item. + NetNewsWire communicates with other apps on your Mac when you choose to share an article. NSAppleScriptEnabled NSHumanReadableCopyright