mirror of
https://github.com/Ranchero-Software/NetNewsWire
synced 2025-08-12 06:26:36 +00:00
Implement changed retention policy. Now matches iOS.
This commit is contained in:
@@ -543,8 +543,8 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
||||
return database.fetchStarredArticleIDs()
|
||||
}
|
||||
|
||||
public func fetchArticleIDsForStatusesWithoutArticles() -> Set<String> {
|
||||
return database.fetchArticleIDsForStatusesWithoutArticles()
|
||||
public func fetchArticleIDsForStatusesWithoutArticlesNewerThanCutoffDate() -> Set<String> {
|
||||
return database.fetchArticleIDsForStatusesWithoutArticlesNewerThanCutoffDate()
|
||||
}
|
||||
|
||||
public func opmlDocument() -> String {
|
||||
@@ -593,33 +593,70 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
||||
|
||||
func update(_ feed: Feed, with parsedFeed: ParsedFeed, _ completion: @escaping (() -> Void)) {
|
||||
// Used only by an On My Mac account.
|
||||
precondition(Thread.isMainThread)
|
||||
precondition(type == .onMyMac) // TODO: allow iCloud
|
||||
feed.takeSettings(from: parsedFeed)
|
||||
let feedIDsAndItems = [feed.feedID: parsedFeed.items]
|
||||
update(feedIDsAndItems: feedIDsAndItems, defaultRead: false, completion: completion)
|
||||
let parsedItems = parsedFeed.items
|
||||
guard !parsedItems.isEmpty else {
|
||||
completion()
|
||||
return
|
||||
}
|
||||
|
||||
database.update(with: parsedItems, feedID: feed.feedID) { articleChanges in
|
||||
self.sendNotificationAbout(articleChanges)
|
||||
completion()
|
||||
}
|
||||
}
|
||||
|
||||
func update(feedIDsAndItems: [String: Set<ParsedItem>], defaultRead: Bool, completion: @escaping (() -> Void)) {
|
||||
assert(Thread.isMainThread)
|
||||
// Used only by syncing systems.
|
||||
precondition(Thread.isMainThread)
|
||||
precondition(type != .onMyMac) // TODO: also make sure type != iCloud
|
||||
guard !feedIDsAndItems.isEmpty else {
|
||||
completion()
|
||||
return
|
||||
}
|
||||
database.update(feedIDsAndItems: feedIDsAndItems, defaultRead: defaultRead) { (newArticles, updatedArticles) in
|
||||
var userInfo = [String: Any]()
|
||||
let feeds = Set(feedIDsAndItems.compactMap { (key, _) -> Feed? in
|
||||
self.existingFeed(withFeedID: key)
|
||||
})
|
||||
if let newArticles = newArticles, !newArticles.isEmpty {
|
||||
self.updateUnreadCounts(for: feeds)
|
||||
userInfo[UserInfoKey.newArticles] = newArticles
|
||||
}
|
||||
if let updatedArticles = updatedArticles, !updatedArticles.isEmpty {
|
||||
userInfo[UserInfoKey.updatedArticles] = updatedArticles
|
||||
}
|
||||
userInfo[UserInfoKey.feeds] = feeds
|
||||
|
||||
database.update(feedIDsAndItems: feedIDsAndItems, defaultRead: defaultRead) { articleChanges in
|
||||
self.sendNotificationAbout(articleChanges)
|
||||
completion()
|
||||
}
|
||||
}
|
||||
|
||||
func sendNotificationAbout(_ articleChanges: ArticleChanges) {
|
||||
var webFeeds = Set<Feed>()
|
||||
|
||||
if let newArticles = articleChanges.newArticles {
|
||||
webFeeds.formUnion(Set(newArticles.compactMap { $0.feed }))
|
||||
}
|
||||
if let updatedArticles = articleChanges.updatedArticles {
|
||||
webFeeds.formUnion(Set(updatedArticles.compactMap { $0.feed }))
|
||||
}
|
||||
|
||||
var shouldSendNotification = false
|
||||
var shouldUpdateUnreadCounts = false
|
||||
var userInfo = [String: Any]()
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
if shouldSendNotification {
|
||||
userInfo[UserInfoKey.feeds] = webFeeds
|
||||
NotificationCenter.default.post(name: .AccountDidDownloadArticles, object: self, userInfo: userInfo)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -996,7 +996,7 @@ private extension FeedbinAccountDelegate {
|
||||
os_log(.debug, log: log, "Refreshing missing articles...")
|
||||
let group = DispatchGroup()
|
||||
|
||||
let fetchedArticleIDs = account.fetchArticleIDsForStatusesWithoutArticles()
|
||||
let fetchedArticleIDs = account.fetchArticleIDsForStatusesWithoutArticlesNewerThanCutoffDate()
|
||||
let articleIDs = Array(fetchedArticleIDs)
|
||||
let chunkedArticleIDs = articleIDs.chunked(into: 100)
|
||||
|
||||
|
||||
@@ -139,8 +139,15 @@ public final class ArticlesDatabase {
|
||||
|
||||
// MARK: - Saving and Updating Articles
|
||||
|
||||
/// Update articles and save new ones. The key for feedIDsAndItems is feedID.
|
||||
/// Update articles and save new ones — for feed-based systems (local and iCloud).
|
||||
public func update(with parsedItems: Set<ParsedItem>, feedID: String, completion: @escaping UpdateArticlesCompletionBlock) {
|
||||
precondition(retentionStyle == .feedBased)
|
||||
articlesTable.update(parsedItems, feedID, completion)
|
||||
}
|
||||
|
||||
/// Update articles and save new ones — for sync systems (Feedbin, Feedly, etc.).
|
||||
public func update(feedIDsAndItems: [String: Set<ParsedItem>], defaultRead: Bool, completion: @escaping UpdateArticlesCompletionBlock) {
|
||||
precondition(retentionStyle == .syncSystem)
|
||||
articlesTable.update(feedIDsAndItems, defaultRead, completion)
|
||||
}
|
||||
|
||||
@@ -158,8 +165,8 @@ public final class ArticlesDatabase {
|
||||
return articlesTable.fetchStarredArticleIDs()
|
||||
}
|
||||
|
||||
public func fetchArticleIDsForStatusesWithoutArticles() -> Set<String> {
|
||||
return articlesTable.fetchArticleIDsForStatusesWithoutArticles()
|
||||
public func fetchArticleIDsForStatusesWithoutArticlesNewerThanCutoffDate() -> Set<String> {
|
||||
return articlesTable.fetchArticleIDsForStatusesWithoutArticlesNewerThanCutoffDate()
|
||||
}
|
||||
|
||||
public func mark(_ articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) -> Set<ArticleStatus>? {
|
||||
|
||||
@@ -393,8 +393,8 @@ final class ArticlesTable: DatabaseTable {
|
||||
return statusesTable.fetchStarredArticleIDs()
|
||||
}
|
||||
|
||||
func fetchArticleIDsForStatusesWithoutArticles() -> Set<String> {
|
||||
return statusesTable.fetchArticleIDsForStatusesWithoutArticles()
|
||||
func fetchArticleIDsForStatusesWithoutArticlesNewerThanCutoffDate() -> Set<String> {
|
||||
return statusesTable.fetchArticleIDsForStatusesWithoutArticlesNewerThan(articleCutoffDate)
|
||||
}
|
||||
|
||||
func mark(_ articles: Set<Article>, _ statusKey: ArticleStatus.Key, _ flag: Bool) -> Set<ArticleStatus>? {
|
||||
|
||||
@@ -100,11 +100,18 @@ final class StatusesTable: DatabaseTable {
|
||||
func fetchStarredArticleIDs() -> Set<String> {
|
||||
return fetchArticleIDs("select articleID from statuses where starred=1;")
|
||||
}
|
||||
|
||||
func fetchArticleIDsForStatusesWithoutArticles() -> Set<String> {
|
||||
return fetchArticleIDs("select articleID from statuses s where (read=0 or starred=1) and not exists (select 1 from articles a where a.articleID = s.articleID);")
|
||||
|
||||
func fetchArticleIDsForStatusesWithoutArticlesNewerThan(_ cutoffDate: Date) -> Set<String> {
|
||||
var articleIDs = Set<String>()
|
||||
queue.runInDatabaseSync { database in
|
||||
let sql = "select articleID from statuses s where (starred=1 or dateArrived>?) and not exists (select 1 from articles a where a.articleID = s.articleID);"
|
||||
if let resultSet = database.executeQuery(sql, withArgumentsIn: [cutoffDate]) {
|
||||
articleIDs = resultSet.mapToSet(self.articleIDWithRow)
|
||||
}
|
||||
}
|
||||
return articleIDs
|
||||
}
|
||||
|
||||
|
||||
func fetchArticleIDs(_ sql: String) -> Set<String> {
|
||||
var articleIDs = Set<String>()
|
||||
queue.runInDatabaseSync { (database) in
|
||||
|
||||
Reference in New Issue
Block a user