From bc2d3250226e63a98a363fa66ef4bb9ac013c8d7 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Wed, 22 Apr 2020 20:41:13 -0700 Subject: [PATCH 1/3] =?UTF-8?q?Remove=20an=20error=20log=20that=E2=80=99s?= =?UTF-8?q?=20just=20noise.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Shared/HTMLMetadata/HTMLMetadataDownloader.swift | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Shared/HTMLMetadata/HTMLMetadataDownloader.swift b/Shared/HTMLMetadata/HTMLMetadataDownloader.swift index 327257782..40651d420 100644 --- a/Shared/HTMLMetadata/HTMLMetadataDownloader.swift +++ b/Shared/HTMLMetadata/HTMLMetadataDownloader.swift @@ -28,10 +28,6 @@ struct HTMLMetadataDownloader { return } - if let error = error { - appDelegate.logMessage("Error downloading metadata at \(url): \(error)", type: .warning) - } - completion(nil) } } From f00df4a8e9d5bb9294c59cb02e702fbf703b6d10 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Wed, 22 Apr 2020 21:41:56 -0700 Subject: [PATCH 2/3] Bump version to 41. --- xcconfig/common/NetNewsWire_ios_target_common.xcconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xcconfig/common/NetNewsWire_ios_target_common.xcconfig b/xcconfig/common/NetNewsWire_ios_target_common.xcconfig index 4a153915d..b76a85b25 100644 --- a/xcconfig/common/NetNewsWire_ios_target_common.xcconfig +++ b/xcconfig/common/NetNewsWire_ios_target_common.xcconfig @@ -1,7 +1,7 @@ // High Level Settings common to both the iOS application and any extensions we bundle with it MARKETING_VERSION = 5.0.1 -CURRENT_PROJECT_VERSION = 40 +CURRENT_PROJECT_VERSION = 41 ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon From c55d8c540e3616416b087139534b9b0bfd187781 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Wed, 22 Apr 2020 21:43:10 -0700 Subject: [PATCH 3/3] Implement revised retention policy for feed-based accounts. Keep all articles currently in the feed and all articles in the last 30 days. --- Frameworks/Account/Account.swift | 27 ++++++++++++------ .../ArticlesDatabase/ArticlesDatabase.swift | 5 ++-- .../ArticlesDatabase/ArticlesTable.swift | 28 +++++++++++-------- 3 files changed, 38 insertions(+), 22 deletions(-) diff --git a/Frameworks/Account/Account.swift b/Frameworks/Account/Account.swift index 9824386d4..2c1637eaa 100644 --- a/Frameworks/Account/Account.swift +++ b/Frameworks/Account/Account.swift @@ -1248,32 +1248,41 @@ private extension Account { } } - func sendNotificationAbout(_ newAndUpdatedArticles: NewAndUpdatedArticles) { + func sendNotificationAbout(_ articleChanges: ArticleChanges) { var webFeeds = Set() - if let newArticles = newAndUpdatedArticles.newArticles { + if let newArticles = articleChanges.newArticles { webFeeds.formUnion(Set(newArticles.compactMap { $0.webFeed })) } - if let updatedArticles = newAndUpdatedArticles.updatedArticles { + if let updatedArticles = articleChanges.updatedArticles { webFeeds.formUnion(Set(updatedArticles.compactMap { $0.webFeed })) } var shouldSendNotification = false + var shouldUpdateUnreadCounts = false var userInfo = [String: Any]() - if let newArticles = newAndUpdatedArticles.newArticles, !newArticles.isEmpty { + if let newArticles = articleChanges.newArticles, !newArticles.isEmpty { shouldSendNotification = true + shouldUpdateUnreadCounts = true userInfo[UserInfoKey.newArticles] = newArticles + } + + if let updatedArticles = articleChanges.updatedArticles, !updatedArticles.isEmpty { + shouldSendNotification = true + userInfo[UserInfoKey.updatedArticles] = updatedArticles + } + + if let deletedArticles = articleChanges.deletedArticles, !deletedArticles.isEmpty { + shouldUpdateUnreadCounts = true + } + + if shouldUpdateUnreadCounts { self.updateUnreadCounts(for: webFeeds) { NotificationCenter.default.post(name: .DownloadArticlesDidUpdateUnreadCounts, object: self, userInfo: nil) } } - if let updatedArticles = newAndUpdatedArticles.updatedArticles, !updatedArticles.isEmpty { - shouldSendNotification = true - userInfo[UserInfoKey.updatedArticles] = updatedArticles - } - if shouldSendNotification { userInfo[UserInfoKey.webFeeds] = webFeeds NotificationCenter.default.post(name: .AccountDidDownloadArticles, object: self, userInfo: userInfo) diff --git a/Frameworks/ArticlesDatabase/ArticlesDatabase.swift b/Frameworks/ArticlesDatabase/ArticlesDatabase.swift index 0ee215866..289ce96c0 100644 --- a/Frameworks/ArticlesDatabase/ArticlesDatabase.swift +++ b/Frameworks/ArticlesDatabase/ArticlesDatabase.swift @@ -24,12 +24,13 @@ public typealias UnreadCountDictionaryCompletionBlock = (UnreadCountDictionaryCo public typealias SingleUnreadCountResult = Result public typealias SingleUnreadCountCompletionBlock = (SingleUnreadCountResult) -> Void -public struct NewAndUpdatedArticles { +public struct ArticleChanges { public let newArticles: Set
? public let updatedArticles: Set
? + public let deletedArticles: Set
? } -public typealias UpdateArticlesResult = Result +public typealias UpdateArticlesResult = Result public typealias UpdateArticlesCompletionBlock = (UpdateArticlesResult) -> Void public typealias ArticleSetResult = Result, DatabaseError> diff --git a/Frameworks/ArticlesDatabase/ArticlesTable.swift b/Frameworks/ArticlesDatabase/ArticlesTable.swift index ff36a8f9b..db997afb6 100644 --- a/Frameworks/ArticlesDatabase/ArticlesTable.swift +++ b/Frameworks/ArticlesDatabase/ArticlesTable.swift @@ -175,7 +175,7 @@ final class ArticlesTable: DatabaseTable { func update(_ parsedItems: Set, _ webFeedID: String, _ completion: @escaping UpdateArticlesCompletionBlock) { precondition(retentionStyle == .feedBased) if parsedItems.isEmpty { - callUpdateArticlesCompletionBlock(nil, nil, completion) + callUpdateArticlesCompletionBlock(nil, nil, nil, completion) return } @@ -199,7 +199,7 @@ final class ArticlesTable: DatabaseTable { let incomingArticles = Article.articlesWithParsedItems(parsedItems, webFeedID, self.accountID, statusesDictionary) //2 if incomingArticles.isEmpty { - self.callUpdateArticlesCompletionBlock(nil, nil, completion) + self.callUpdateArticlesCompletionBlock(nil, nil, nil, completion) return } @@ -209,13 +209,19 @@ final class ArticlesTable: DatabaseTable { let newArticles = self.findAndSaveNewArticles(incomingArticles, fetchedArticlesDictionary, database) //5 let updatedArticles = self.findAndSaveUpdatedArticles(incomingArticles, fetchedArticlesDictionary, database) //6 - self.callUpdateArticlesCompletionBlock(newArticles, updatedArticles, completion) //7 + // Articles to delete are 1) no longer in feed and 2) older than 30 days. + let cutoffDate = Date().bySubtracting(days: 30) + let articlesToDelete = fetchedArticles.filter { (article) -> Bool in + return article.status.dateArrived < cutoffDate && !articleIDs.contains(article.articleID) + } + + self.callUpdateArticlesCompletionBlock(newArticles, updatedArticles, articlesToDelete, completion) //7 self.addArticlesToCache(newArticles) self.addArticlesToCache(updatedArticles) // 8. Delete articles no longer in feed. - let articleIDsToDelete = fetchedArticles.articleIDs().filter { !(articleIDs.contains($0)) } + let articleIDsToDelete = articlesToDelete.articleIDs() if !articleIDsToDelete.isEmpty { self.removeArticles(articleIDsToDelete, database) self.removeArticleIDsFromCache(articleIDsToDelete) @@ -244,7 +250,7 @@ final class ArticlesTable: DatabaseTable { func update(_ webFeedIDsAndItems: [String: Set], _ read: Bool, _ completion: @escaping UpdateArticlesCompletionBlock) { precondition(retentionStyle == .syncSystem) if webFeedIDsAndItems.isEmpty { - callUpdateArticlesCompletionBlock(nil, nil, completion) + callUpdateArticlesCompletionBlock(nil, nil, nil, completion) return } @@ -270,13 +276,13 @@ final class ArticlesTable: DatabaseTable { let allIncomingArticles = Article.articlesWithWebFeedIDsAndItems(webFeedIDsAndItems, self.accountID, statusesDictionary) //2 if allIncomingArticles.isEmpty { - self.callUpdateArticlesCompletionBlock(nil, nil, completion) + self.callUpdateArticlesCompletionBlock(nil, nil, nil, completion) return } let incomingArticles = self.filterIncomingArticles(allIncomingArticles) //3 if incomingArticles.isEmpty { - self.callUpdateArticlesCompletionBlock(nil, nil, completion) + self.callUpdateArticlesCompletionBlock(nil, nil, nil, completion) return } @@ -287,7 +293,7 @@ final class ArticlesTable: DatabaseTable { let newArticles = self.findAndSaveNewArticles(incomingArticles, fetchedArticlesDictionary, database) //5 let updatedArticles = self.findAndSaveUpdatedArticles(incomingArticles, fetchedArticlesDictionary, database) //6 - self.callUpdateArticlesCompletionBlock(newArticles, updatedArticles, completion) //7 + self.callUpdateArticlesCompletionBlock(newArticles, updatedArticles, nil, completion) //7 self.addArticlesToCache(newArticles) self.addArticlesToCache(updatedArticles) @@ -849,10 +855,10 @@ private extension ArticlesTable { // MARK: - Saving Parsed Items - func callUpdateArticlesCompletionBlock(_ newArticles: Set
?, _ updatedArticles: Set
?, _ completion: @escaping UpdateArticlesCompletionBlock) { - let newAndUpdatedArticles = NewAndUpdatedArticles(newArticles: newArticles, updatedArticles: updatedArticles) + func callUpdateArticlesCompletionBlock(_ newArticles: Set
?, _ updatedArticles: Set
?, _ deletedArticles: Set
?, _ completion: @escaping UpdateArticlesCompletionBlock) { + let articleChanges = ArticleChanges(newArticles: newArticles, updatedArticles: updatedArticles, deletedArticles: deletedArticles) DispatchQueue.main.async { - completion(.success(newAndUpdatedArticles)) + completion(.success(articleChanges)) } }