Merge branch 'mac-release'
This commit is contained in:
commit
ea1f21797c
|
@ -564,16 +564,16 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
||||||
database.fetchStarredAndUnreadCount(for: flattenedFeeds().feedIDs(), callback: callback)
|
database.fetchStarredAndUnreadCount(for: flattenedFeeds().feedIDs(), callback: callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func fetchUnreadArticleIDs(_ callback: @escaping (Set<String>) -> Void) {
|
public func fetchUnreadArticleIDs() -> Set<String> {
|
||||||
database.fetchUnreadArticleIDs(callback)
|
return database.fetchUnreadArticleIDs()
|
||||||
}
|
}
|
||||||
|
|
||||||
public func fetchStarredArticleIDs(_ callback: @escaping (Set<String>) -> Void) {
|
public func fetchStarredArticleIDs() -> Set<String> {
|
||||||
database.fetchStarredArticleIDs(callback)
|
return database.fetchStarredArticleIDs()
|
||||||
}
|
}
|
||||||
|
|
||||||
public func fetchArticleIDsForStatusesWithoutArticles(_ callback: @escaping (Set<String>) -> Void) {
|
public func fetchArticleIDsForStatusesWithoutArticles() -> Set<String> {
|
||||||
database.fetchArticleIDsForStatusesWithoutArticles(callback)
|
return database.fetchArticleIDsForStatusesWithoutArticles()
|
||||||
}
|
}
|
||||||
|
|
||||||
public func opmlDocument() -> String {
|
public func opmlDocument() -> String {
|
||||||
|
@ -657,9 +657,9 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
|
||||||
return updatedArticles
|
return updatedArticles
|
||||||
}
|
}
|
||||||
|
|
||||||
func ensureStatuses(_ articleIDs: Set<String>, _ statusKey: ArticleStatus.Key, _ flag: Bool) {
|
func ensureStatuses(_ articleIDs: Set<String>, _ defaultRead: Bool, _ statusKey: ArticleStatus.Key, _ flag: Bool) {
|
||||||
if !articleIDs.isEmpty {
|
if !articleIDs.isEmpty {
|
||||||
database.ensureStatuses(articleIDs, statusKey, flag)
|
database.ensureStatuses(articleIDs, defaultRead, statusKey, flag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,9 +83,9 @@ final class FeedbinAccountDelegate: AccountDelegate {
|
||||||
switch result {
|
switch result {
|
||||||
case .success():
|
case .success():
|
||||||
|
|
||||||
self.refreshArticles(account) {
|
|
||||||
self.sendArticleStatus(for: account) {
|
self.sendArticleStatus(for: account) {
|
||||||
self.refreshArticleStatus(for: account) {
|
self.refreshArticleStatus(for: account) {
|
||||||
|
self.refreshArticles(account) {
|
||||||
self.refreshMissingArticles(account) {
|
self.refreshMissingArticles(account) {
|
||||||
self.refreshProgress.clear()
|
self.refreshProgress.clear()
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
|
@ -948,8 +948,8 @@ private extension FeedbinAccountDelegate {
|
||||||
case .success(let (entries, page)):
|
case .success(let (entries, page)):
|
||||||
|
|
||||||
self.processEntries(account: account, entries: entries) {
|
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.refreshProgress.completeTask()
|
||||||
self.refreshMissingArticles(account) {
|
self.refreshMissingArticles(account) {
|
||||||
self.refreshProgress.completeTask()
|
self.refreshProgress.completeTask()
|
||||||
|
@ -1005,9 +1005,10 @@ private extension FeedbinAccountDelegate {
|
||||||
os_log(.debug, log: log, "Refreshing missing articles...")
|
os_log(.debug, log: log, "Refreshing missing articles...")
|
||||||
let group = DispatchGroup()
|
let group = DispatchGroup()
|
||||||
|
|
||||||
account.fetchArticleIDsForStatusesWithoutArticles { (fetchedArticleIDs) in
|
let fetchedArticleIDs = account.fetchArticleIDsForStatusesWithoutArticles()
|
||||||
let articleIDs = Array(fetchedArticleIDs)
|
let articleIDs = Array(fetchedArticleIDs)
|
||||||
let chunkedArticleIDs = articleIDs.chunked(into: 100)
|
let chunkedArticleIDs = articleIDs.chunked(into: 100)
|
||||||
|
|
||||||
for chunk in chunkedArticleIDs {
|
for chunk in chunkedArticleIDs {
|
||||||
group.enter()
|
group.enter()
|
||||||
self.caller.retrieveEntries(articleIDs: chunk) { result in
|
self.caller.retrieveEntries(articleIDs: chunk) { result in
|
||||||
|
@ -1025,7 +1026,6 @@ private extension FeedbinAccountDelegate {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
group.notify(queue: DispatchQueue.main) {
|
group.notify(queue: DispatchQueue.main) {
|
||||||
self.refreshProgress.completeTask()
|
self.refreshProgress.completeTask()
|
||||||
|
@ -1110,29 +1110,28 @@ private extension FeedbinAccountDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
let feedbinUnreadArticleIDs = Set(articleIDs.map { String($0) } )
|
let feedbinUnreadArticleIDs = Set(articleIDs.map { String($0) } )
|
||||||
account.fetchUnreadArticleIDs { (currentUnreadArticleIDs) in
|
let currentUnreadArticleIDs = account.fetchUnreadArticleIDs()
|
||||||
|
|
||||||
// Mark articles as unread
|
// Mark articles as unread
|
||||||
let deltaUnreadArticleIDs = feedbinUnreadArticleIDs.subtracting(currentUnreadArticleIDs)
|
let deltaUnreadArticleIDs = feedbinUnreadArticleIDs.subtracting(currentUnreadArticleIDs)
|
||||||
account.fetchArticlesAsync(.articleIDs(deltaUnreadArticleIDs)) { (markUnreadArticles) in
|
let markUnreadArticles = account.fetchArticles(.articleIDs(deltaUnreadArticleIDs))
|
||||||
account.update(markUnreadArticles, statusKey: .read, flag: false)
|
account.update(markUnreadArticles, statusKey: .read, flag: false)
|
||||||
|
|
||||||
// Save any unread statuses for articles we haven't yet received
|
// Save any unread statuses for articles we haven't yet received
|
||||||
let markUnreadArticleIDs = Set(markUnreadArticles.map { $0.articleID })
|
let markUnreadArticleIDs = Set(markUnreadArticles.map { $0.articleID })
|
||||||
let missingUnreadArticleIDs = deltaUnreadArticleIDs.subtracting(markUnreadArticleIDs)
|
let missingUnreadArticleIDs = deltaUnreadArticleIDs.subtracting(markUnreadArticleIDs)
|
||||||
account.ensureStatuses(missingUnreadArticleIDs, .read, false)
|
account.ensureStatuses(missingUnreadArticleIDs, true, .read, false)
|
||||||
}
|
|
||||||
|
|
||||||
// Mark articles as read
|
// Mark articles as read
|
||||||
let deltaReadArticleIDs = currentUnreadArticleIDs.subtracting(feedbinUnreadArticleIDs)
|
let deltaReadArticleIDs = currentUnreadArticleIDs.subtracting(feedbinUnreadArticleIDs)
|
||||||
account.fetchArticlesAsync(.articleIDs(deltaReadArticleIDs)) { (markReadArticles) in
|
let markReadArticles = account.fetchArticles(.articleIDs(deltaReadArticleIDs))
|
||||||
account.update(markReadArticles, statusKey: .read, flag: true)
|
account.update(markReadArticles, statusKey: .read, flag: true)
|
||||||
|
|
||||||
// Save any read statuses for articles we haven't yet received
|
// Save any read statuses for articles we haven't yet received
|
||||||
let markReadArticleIDs = Set(markReadArticles.map { $0.articleID })
|
let markReadArticleIDs = Set(markReadArticles.map { $0.articleID })
|
||||||
let missingReadArticleIDs = deltaReadArticleIDs.subtracting(markReadArticleIDs)
|
let missingReadArticleIDs = deltaReadArticleIDs.subtracting(markReadArticleIDs)
|
||||||
account.ensureStatuses(missingReadArticleIDs, .read, true)
|
account.ensureStatuses(missingReadArticleIDs, true, .read, true)
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func syncArticleStarredState(account: Account, articleIDs: [Int]?) {
|
func syncArticleStarredState(account: Account, articleIDs: [Int]?) {
|
||||||
|
@ -1141,29 +1140,27 @@ private extension FeedbinAccountDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
let feedbinStarredArticleIDs = Set(articleIDs.map { String($0) } )
|
let feedbinStarredArticleIDs = Set(articleIDs.map { String($0) } )
|
||||||
account.fetchStarredArticleIDs { (currentStarredArticleIDs) in
|
let currentStarredArticleIDs = account.fetchStarredArticleIDs()
|
||||||
|
|
||||||
// Mark articles as starred
|
// Mark articles as starred
|
||||||
let deltaStarredArticleIDs = feedbinStarredArticleIDs.subtracting(currentStarredArticleIDs)
|
let deltaStarredArticleIDs = feedbinStarredArticleIDs.subtracting(currentStarredArticleIDs)
|
||||||
account.fetchArticlesAsync(.articleIDs(deltaStarredArticleIDs)) { (markStarredArticles) in
|
let markStarredArticles = account.fetchArticles(.articleIDs(deltaStarredArticleIDs))
|
||||||
account.update(markStarredArticles, statusKey: .starred, flag: true)
|
account.update(markStarredArticles, statusKey: .starred, flag: true)
|
||||||
|
|
||||||
// Save any starred statuses for articles we haven't yet received
|
// Save any starred statuses for articles we haven't yet received
|
||||||
let markStarredArticleIDs = Set(markStarredArticles.map { $0.articleID })
|
let markStarredArticleIDs = Set(markStarredArticles.map { $0.articleID })
|
||||||
let missingStarredArticleIDs = deltaStarredArticleIDs.subtracting(markStarredArticleIDs)
|
let missingStarredArticleIDs = deltaStarredArticleIDs.subtracting(markStarredArticleIDs)
|
||||||
account.ensureStatuses(missingStarredArticleIDs, .starred, true)
|
account.ensureStatuses(missingStarredArticleIDs, true, .starred, true)
|
||||||
}
|
|
||||||
|
|
||||||
// Mark articles as unstarred
|
// Mark articles as unstarred
|
||||||
let deltaUnstarredArticleIDs = currentStarredArticleIDs.subtracting(feedbinStarredArticleIDs)
|
let deltaUnstarredArticleIDs = currentStarredArticleIDs.subtracting(feedbinStarredArticleIDs)
|
||||||
account.fetchArticlesAsync(.articleIDs(deltaUnstarredArticleIDs)) { (markUnstarredArticles) in
|
let markUnstarredArticles = account.fetchArticles(.articleIDs(deltaUnstarredArticleIDs))
|
||||||
account.update(markUnstarredArticles, statusKey: .starred, flag: false)
|
account.update(markUnstarredArticles, statusKey: .starred, flag: false)
|
||||||
|
|
||||||
// Save any unstarred statuses for articles we haven't yet received
|
// Save any unstarred statuses for articles we haven't yet received
|
||||||
let markUnstarredArticleIDs = Set(markUnstarredArticles.map { $0.articleID })
|
let markUnstarredArticleIDs = Set(markUnstarredArticles.map { $0.articleID })
|
||||||
let missingUnstarredArticleIDs = deltaUnstarredArticleIDs.subtracting(markUnstarredArticleIDs)
|
let missingUnstarredArticleIDs = deltaUnstarredArticleIDs.subtracting(markUnstarredArticleIDs)
|
||||||
account.ensureStatuses(missingUnstarredArticleIDs, .starred, false)
|
account.ensureStatuses(missingUnstarredArticleIDs, true, .starred, false)
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func deleteTagging(for account: Account, with feed: Feed, from container: Container?, completion: @escaping (Result<Void, Error>) -> Void) {
|
func deleteTagging(for account: Account, with feed: Feed, from container: Container?, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||||
|
|
|
@ -122,22 +122,22 @@ public final class ArticlesDatabase {
|
||||||
return articlesTable.update(feedID, parsedItems, defaultRead, completion)
|
return articlesTable.update(feedID, parsedItems, defaultRead, completion)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func ensureStatuses(_ articleIDs: Set<String>, _ statusKey: ArticleStatus.Key, _ flag: Bool) {
|
public func ensureStatuses(_ articleIDs: Set<String>, _ defaultRead: Bool, _ statusKey: ArticleStatus.Key, _ flag: Bool) {
|
||||||
articlesTable.ensureStatuses(articleIDs, statusKey, flag)
|
articlesTable.ensureStatuses(articleIDs, defaultRead, statusKey, flag)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Status
|
// MARK: - Status
|
||||||
|
|
||||||
public func fetchUnreadArticleIDs(_ callback: @escaping (Set<String>) -> Void) {
|
public func fetchUnreadArticleIDs() -> Set<String> {
|
||||||
articlesTable.fetchUnreadArticleIDs(callback)
|
return articlesTable.fetchUnreadArticleIDs()
|
||||||
}
|
}
|
||||||
|
|
||||||
public func fetchStarredArticleIDs(_ callback: @escaping (Set<String>) -> Void) {
|
public func fetchStarredArticleIDs() -> Set<String> {
|
||||||
articlesTable.fetchStarredArticleIDs(callback)
|
return articlesTable.fetchStarredArticleIDs()
|
||||||
}
|
}
|
||||||
|
|
||||||
public func fetchArticleIDsForStatusesWithoutArticles(_ callback: @escaping (Set<String>) -> Void) {
|
public func fetchArticleIDsForStatusesWithoutArticles() -> Set<String> {
|
||||||
articlesTable.fetchArticleIDsForStatusesWithoutArticles(callback)
|
return articlesTable.fetchArticleIDsForStatusesWithoutArticles()
|
||||||
}
|
}
|
||||||
|
|
||||||
public func mark(_ articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) -> Set<ArticleStatus>? {
|
public func mark(_ articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) -> Set<ArticleStatus>? {
|
||||||
|
|
|
@ -267,9 +267,9 @@ final class ArticlesTable: DatabaseTable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ensureStatuses(_ articleIDs: Set<String>, _ statusKey: ArticleStatus.Key, _ flag: Bool) {
|
func ensureStatuses(_ articleIDs: Set<String>, _ defaultRead: Bool, _ statusKey: ArticleStatus.Key, _ flag: Bool) {
|
||||||
self.queue.update { (database) in
|
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)
|
let statuses = Set(statusesDictionary.values)
|
||||||
self.statusesTable.mark(statuses, statusKey, flag, database)
|
self.statusesTable.mark(statuses, statusKey, flag, database)
|
||||||
}
|
}
|
||||||
|
@ -371,16 +371,16 @@ final class ArticlesTable: DatabaseTable {
|
||||||
|
|
||||||
// MARK: - Statuses
|
// MARK: - Statuses
|
||||||
|
|
||||||
func fetchUnreadArticleIDs(_ callback: @escaping (Set<String>) -> Void) {
|
func fetchUnreadArticleIDs() -> Set<String>{
|
||||||
statusesTable.fetchUnreadArticleIDs(callback)
|
return statusesTable.fetchUnreadArticleIDs()
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchStarredArticleIDs(_ callback: @escaping (Set<String>) -> Void) {
|
func fetchStarredArticleIDs() -> Set<String> {
|
||||||
statusesTable.fetchStarredArticleIDs(callback)
|
return statusesTable.fetchStarredArticleIDs()
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchArticleIDsForStatusesWithoutArticles(_ callback: @escaping (Set<String>) -> Void) {
|
func fetchArticleIDsForStatusesWithoutArticles() -> Set<String> {
|
||||||
statusesTable.fetchArticleIDsForStatusesWithoutArticles(callback)
|
return statusesTable.fetchArticleIDsForStatusesWithoutArticles()
|
||||||
}
|
}
|
||||||
|
|
||||||
func mark(_ articles: Set<Article>, _ statusKey: ArticleStatus.Key, _ flag: Bool) -> Set<ArticleStatus>? {
|
func mark(_ articles: Set<Article>, _ statusKey: ArticleStatus.Key, _ flag: Bool) -> Set<ArticleStatus>? {
|
||||||
|
|
|
@ -74,27 +74,27 @@ final class StatusesTable: DatabaseTable {
|
||||||
|
|
||||||
// MARK: - Fetching
|
// MARK: - Fetching
|
||||||
|
|
||||||
func fetchUnreadArticleIDs(_ callback: @escaping (Set<String>) -> Void) {
|
func fetchUnreadArticleIDs() -> Set<String> {
|
||||||
fetchArticleIDs("select articleID from statuses where read=0 and userDeleted=0;", callback)
|
return fetchArticleIDs("select articleID from statuses where read=0 and userDeleted=0;")
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchStarredArticleIDs(_ callback: @escaping (Set<String>) -> Void) {
|
func fetchStarredArticleIDs() -> Set<String> {
|
||||||
fetchArticleIDs("select articleID from statuses where starred=1 and userDeleted=0;", callback)
|
return fetchArticleIDs("select articleID from statuses where starred=1 and userDeleted=0;")
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchArticleIDsForStatusesWithoutArticles(_ callback: @escaping (Set<String>) -> Void) {
|
func fetchArticleIDsForStatusesWithoutArticles() -> Set<String> {
|
||||||
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)
|
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<String>) -> Void) {
|
func fetchArticleIDs(_ sql: String) -> Set<String> {
|
||||||
queue.fetch { (database) in
|
var articleIDs = Set<String>()
|
||||||
|
queue.fetchSync { (database) in
|
||||||
guard let resultSet = database.executeQuery(sql, withArgumentsIn: nil) else {
|
guard let resultSet = database.executeQuery(sql, withArgumentsIn: nil) else {
|
||||||
callback(Set<String>())
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let statuses = resultSet.mapToSet(self.articleIDWithRow)
|
articleIDs = resultSet.mapToSet(self.articleIDWithRow)
|
||||||
callback(statuses)
|
|
||||||
}
|
}
|
||||||
|
return articleIDs
|
||||||
}
|
}
|
||||||
|
|
||||||
func articleIDWithRow(_ row: FMResultSet) -> String? {
|
func articleIDWithRow(_ row: FMResultSet) -> String? {
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>5.0</string>
|
<string>5.0.1a</string>
|
||||||
<key>CFBundleURLTypes</key>
|
<key>CFBundleURLTypes</key>
|
||||||
<array>
|
<array>
|
||||||
<dict>
|
<dict>
|
||||||
|
@ -33,7 +33,7 @@
|
||||||
</dict>
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>2609</string>
|
<string>2610</string>
|
||||||
<key>LSApplicationCategoryType</key>
|
<key>LSApplicationCategoryType</key>
|
||||||
<string>public.app-category.news</string>
|
<string>public.app-category.news</string>
|
||||||
<key>LSMinimumSystemVersion</key>
|
<key>LSMinimumSystemVersion</key>
|
||||||
|
@ -44,7 +44,7 @@
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
<key>NSAppleEventsUsageDescription</key>
|
<key>NSAppleEventsUsageDescription</key>
|
||||||
<string>NetNewsWire communicates with other apps on your Mac when you choose to share a news item.</string>
|
<string>NetNewsWire communicates with other apps on your Mac when you choose to share an article.</string>
|
||||||
<key>NSAppleScriptEnabled</key>
|
<key>NSAppleScriptEnabled</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>NSHumanReadableCopyright</key>
|
<key>NSHumanReadableCopyright</key>
|
||||||
|
|
Loading…
Reference in New Issue