From 0c176eccd0f9973e46fb3239da2012fcb69dd387 Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Sun, 3 Dec 2017 11:57:53 -0800 Subject: [PATCH] =?UTF-8?q?Fetch=20all=20unread=20counts=20at=20startup.?= =?UTF-8?q?=20This=20is=20done=20with=20a=20single=20SQL=20call,=20and=20i?= =?UTF-8?q?t=E2=80=99s=20done=20in=20the=20background,=20so=20performance?= =?UTF-8?q?=20hit=20should=20not=20be=20noticeable.=20Fix=20#138.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Frameworks/Account/Account.swift | 23 ++++++++++++++ Frameworks/Database/ArticlesTable.swift | 31 +++++++++++++++++++ Frameworks/Database/Database.swift | 7 ++++- .../Database/UnreadCountDictionary.swift | 4 +++ 4 files changed, 64 insertions(+), 1 deletion(-) diff --git a/Frameworks/Account/Account.swift b/Frameworks/Account/Account.swift index 0a8cbc55d..7a527d6a1 100644 --- a/Frameworks/Account/Account.swift +++ b/Frameworks/Account/Account.swift @@ -140,6 +140,7 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container, DispatchQueue.main.async { self.updateUnreadCount() + self.fetchAllUnreadCounts() } } @@ -622,6 +623,28 @@ private extension Account { NotificationCenter.default.post(name: .StatusesDidChange, object: self, userInfo: [UserInfoKey.statuses: statuses, UserInfoKey.articles: articles, UserInfoKey.feeds: feeds]) } + + func fetchAllUnreadCounts() { + + database.fetchAllNonZeroUnreadCounts { (unreadCountDictionary) in + + if unreadCountDictionary.isEmpty { + return + } + + self.flattenedFeeds().forEach{ (feed) in + + // When the unread count is zero, it won’t appear in unreadCountDictionary. + + if let unreadCount = unreadCountDictionary[feed] { + feed.unreadCount = unreadCount + } + else { + feed.unreadCount = 0 + } + } + } + } } // MARK: - Container Overrides diff --git a/Frameworks/Database/ArticlesTable.swift b/Frameworks/Database/ArticlesTable.swift index 89708a4a7..584b3a695 100644 --- a/Frameworks/Database/ArticlesTable.swift +++ b/Frameworks/Database/ArticlesTable.swift @@ -174,6 +174,37 @@ final class ArticlesTable: DatabaseTable { } } + func fetchAllUnreadCounts(_ completion: @escaping UnreadCountCompletionBlock) { + + // Returns only where unreadCount > 0. + + let cutoffDate = articleCutoffDate + + queue.fetch { (database) in + + let sql = "select distinct feedID, count(*) from articles natural join statuses where read=0 and userDeleted=0 and (starred=1 or dateArrived>?) group by feedID;" + + guard let resultSet = database.executeQuery(sql, withArgumentsIn: [cutoffDate]) else { + DispatchQueue.main.async() { + completion(UnreadCountDictionary()) + } + return + } + + var d = UnreadCountDictionary() + while resultSet.next() { + let unreadCount = resultSet.long(forColumnIndex: 1) + if let feedID = resultSet.string(forColumnIndex: 0) { + d[feedID] = unreadCount + } + } + + DispatchQueue.main.async() { + completion(d) + } + } + } + func fetchStarredAndUnreadCount(_ feeds: Set, _ callback: @escaping (Int) -> Void) { if feeds.isEmpty { diff --git a/Frameworks/Database/Database.swift b/Frameworks/Database/Database.swift index c312cce2e..653d95003 100644 --- a/Frameworks/Database/Database.swift +++ b/Frameworks/Database/Database.swift @@ -57,7 +57,7 @@ public final class Database { // MARK: - Unread Counts public func fetchUnreadCounts(for feeds: Set, _ completion: @escaping UnreadCountCompletionBlock) { - + articlesTable.fetchUnreadCounts(feeds, completion) } @@ -71,6 +71,11 @@ public final class Database { articlesTable.fetchStarredAndUnreadCount(feeds, callback) } + public func fetchAllNonZeroUnreadCounts(_ completion: @escaping UnreadCountCompletionBlock) { + + articlesTable.fetchAllUnreadCounts(completion) + } + // MARK: - Saving and Updating Articles public func update(feed: Feed, parsedFeed: ParsedFeed, completion: @escaping UpdateArticlesWithFeedCompletionBlock) { diff --git a/Frameworks/Database/UnreadCountDictionary.swift b/Frameworks/Database/UnreadCountDictionary.swift index 16b731f9b..4182d16fd 100644 --- a/Frameworks/Database/UnreadCountDictionary.swift +++ b/Frameworks/Database/UnreadCountDictionary.swift @@ -12,6 +12,10 @@ import Data public struct UnreadCountDictionary { private var dictionary = [String: Int]() + + public var isEmpty: Bool { + return dictionary.count < 1 + } subscript(_ feedID: String) -> Int? { get {