Merge branch 'mac-release'

This commit is contained in:
Brent Simmons 2019-09-28 13:52:07 -07:00
commit 13eb6450c7
4 changed files with 47 additions and 27 deletions

View File

@ -1115,7 +1115,7 @@ private extension FeedbinAccountDelegate {
let parsedItems: [ParsedItem] = entries.map { entry in
let authors = Set([ParsedAuthor(name: entry.authorName, url: entry.jsonFeed?.jsonFeedAuthor?.url, avatarURL: entry.jsonFeed?.jsonFeedAuthor?.avatarURL, emailAddress: nil)])
return ParsedItem(syncServiceID: String(entry.articleID), uniqueID: String(entry.articleID), feedURL: String(entry.feedID), url: nil, externalURL: entry.url, title: entry.title, contentHTML: entry.contentHTML, contentText: nil, summary: entry.summary, imageURL: nil, bannerImageURL: nil, datePublished: entry.parseDatePublished(), dateModified: nil, authors: authors, tags: nil, attachments: nil)
return ParsedItem(syncServiceID: String(entry.articleID), uniqueID: String(entry.articleID), feedURL: String(entry.feedID), url: nil, externalURL: entry.url, title: entry.title, contentHTML: entry.contentHTML, contentText: nil, summary: entry.summary, imageURL: nil, bannerImageURL: nil, datePublished: entry.parsedDatePublished, dateModified: nil, authors: authors, tags: nil, attachments: nil)
}
return Set(parsedItems)

View File

@ -10,7 +10,7 @@ import Foundation
import RSParser
import RSCore
struct FeedbinEntry: Codable {
final class FeedbinEntry: Codable {
let articleID: Int
let feedID: Int
@ -23,6 +23,19 @@ struct FeedbinEntry: Codable {
let dateArrived: String?
let jsonFeed: FeedbinEntryJSONFeed?
// Feedbin dates can't be decoded by the JSONDecoding 8601 decoding strategy. Feedbin
// requires a very specific date formatter to work and even then it fails occasionally.
// Rather than loose all the entries we only lose the one date by decoding as a string
// and letting the one date fail when parsed.
lazy var parsedDatePublished: Date? = {
if let datePublished = datePublished {
return RSDateWithString(datePublished)
}
else {
return nil
}
}()
enum CodingKeys: String, CodingKey {
case articleID = "id"
case feedID = "feed_id"
@ -35,19 +48,6 @@ struct FeedbinEntry: Codable {
case dateArrived = "created_at"
case jsonFeed = "json_feed"
}
// Feedbin dates can't be decoded by the JSONDecoding 8601 decoding strategy. Feedbin
// requires a very specific date formatter to work and even then it fails occasionally.
// Rather than loose all the entries we only lose the one date by decoding as a string
// and letting the one date fail when parsed.
func parseDatePublished() -> Date? {
if datePublished != nil {
return FeedbinDate.formatter.date(from: datePublished!)
} else {
return nil
}
}
}
struct FeedbinEntryJSONFeed: Codable {

View File

@ -20,6 +20,7 @@ final class ArticlesTable: DatabaseTable {
private let statusesTable: StatusesTable
private let authorsLookupTable: DatabaseLookupTable
private let attachmentsLookupTable: DatabaseLookupTable
private var databaseArticlesCache = [String: DatabaseArticle]()
private lazy var searchTable: SearchTable = {
return SearchTable(queue: queue, articlesTable: self)
@ -482,16 +483,21 @@ private extension ArticlesTable {
func makeDatabaseArticles(with resultSet: FMResultSet) -> Set<DatabaseArticle> {
let articles = resultSet.mapToSet { (row) -> DatabaseArticle? in
// The resultSet is a result of a JOIN query with the statuses table,
// so we can get the statuses at the same time and avoid additional database lookups.
guard let status = statusesTable.statusWithRow(resultSet) else {
assertionFailure("Expected status.")
guard let articleID = row.string(forColumn: DatabaseKey.articleID) else {
assertionFailure("Expected articleID.")
return nil
}
guard let articleID = row.string(forColumn: DatabaseKey.articleID) else {
assertionFailure("Expected articleID.")
// Articles are removed from the cache when theyre updated.
// See saveUpdatedArticles.
if let databaseArticle = databaseArticlesCache[articleID] {
return databaseArticle
}
// The resultSet is a result of a JOIN query with the statuses table,
// so we can get the statuses at the same time and avoid additional database lookups.
guard let status = statusesTable.statusWithRow(resultSet, articleID: articleID) else {
assertionFailure("Expected status.")
return nil
}
guard let feedID = row.string(forColumn: DatabaseKey.feedID) else {
@ -514,7 +520,9 @@ private extension ArticlesTable {
let datePublished = row.date(forColumn: DatabaseKey.datePublished)
let dateModified = row.date(forColumn: DatabaseKey.dateModified)
return DatabaseArticle(articleID: articleID, feedID: feedID, uniqueID: uniqueID, title: title, contentHTML: contentHTML, contentText: contentText, url: url, externalURL: externalURL, summary: summary, imageURL: imageURL, bannerImageURL: bannerImageURL, datePublished: datePublished, dateModified: dateModified, status: status)
let databaseArticle = DatabaseArticle(articleID: articleID, feedID: feedID, uniqueID: uniqueID, title: title, contentHTML: contentHTML, contentText: contentText, url: url, externalURL: externalURL, summary: summary, imageURL: imageURL, bannerImageURL: bannerImageURL, datePublished: datePublished, dateModified: dateModified, status: status)
databaseArticlesCache[articleID] = databaseArticle
return databaseArticle
}
return articles
@ -670,6 +678,7 @@ private extension ArticlesTable {
func saveUpdatedArticles(_ updatedArticles: Set<Article>, _ fetchedArticles: [String: Article], _ database: FMDatabase) {
removeArticlesFromDatabaseArticlesCache(updatedArticles)
saveUpdatedRelatedObjects(updatedArticles, fetchedArticles, database)
for updatedArticle in updatedArticles {
@ -690,10 +699,17 @@ private extension ArticlesTable {
// Not unexpected. There may be no changes.
return
}
updateRowsWithDictionary(changesDictionary, whereKey: DatabaseKey.articleID, matches: updatedArticle.articleID, database: database)
}
func removeArticlesFromDatabaseArticlesCache(_ updatedArticles: Set<Article>) {
let articleIDs = updatedArticles.articleIDs()
for articleID in articleIDs {
databaseArticlesCache[articleID] = nil
}
}
func statusIndicatesArticleIsIgnorable(_ status: ArticleStatus) -> Bool {
// Ignorable articles: either userDeleted==1 or (not starred and arrival date > 4 months).
if status.userDeleted {

View File

@ -105,17 +105,21 @@ final class StatusesTable: DatabaseTable {
guard let articleID = row.string(forColumn: DatabaseKey.articleID) else {
return nil
}
return statusWithRow(row, articleID: articleID)
}
func statusWithRow(_ row: FMResultSet, articleID: String) ->ArticleStatus? {
if let cachedStatus = cache[articleID] {
return cachedStatus
}
guard let dateArrived = row.date(forColumn: DatabaseKey.dateArrived) else {
return nil
}
let articleStatus = ArticleStatus(articleID: articleID, dateArrived: dateArrived, row: row)
cache.addStatusIfNotCached(articleStatus)
return articleStatus
}