Merge branch 'mac-release'
This commit is contained in:
commit
13eb6450c7
|
@ -1115,7 +1115,7 @@ private extension FeedbinAccountDelegate {
|
||||||
|
|
||||||
let parsedItems: [ParsedItem] = entries.map { entry in
|
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)])
|
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)
|
return Set(parsedItems)
|
||||||
|
|
|
@ -10,7 +10,7 @@ import Foundation
|
||||||
import RSParser
|
import RSParser
|
||||||
import RSCore
|
import RSCore
|
||||||
|
|
||||||
struct FeedbinEntry: Codable {
|
final class FeedbinEntry: Codable {
|
||||||
|
|
||||||
let articleID: Int
|
let articleID: Int
|
||||||
let feedID: Int
|
let feedID: Int
|
||||||
|
@ -23,6 +23,19 @@ struct FeedbinEntry: Codable {
|
||||||
let dateArrived: String?
|
let dateArrived: String?
|
||||||
let jsonFeed: FeedbinEntryJSONFeed?
|
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 {
|
enum CodingKeys: String, CodingKey {
|
||||||
case articleID = "id"
|
case articleID = "id"
|
||||||
case feedID = "feed_id"
|
case feedID = "feed_id"
|
||||||
|
@ -35,19 +48,6 @@ struct FeedbinEntry: Codable {
|
||||||
case dateArrived = "created_at"
|
case dateArrived = "created_at"
|
||||||
case jsonFeed = "json_feed"
|
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 {
|
struct FeedbinEntryJSONFeed: Codable {
|
||||||
|
|
|
@ -20,6 +20,7 @@ final class ArticlesTable: DatabaseTable {
|
||||||
private let statusesTable: StatusesTable
|
private let statusesTable: StatusesTable
|
||||||
private let authorsLookupTable: DatabaseLookupTable
|
private let authorsLookupTable: DatabaseLookupTable
|
||||||
private let attachmentsLookupTable: DatabaseLookupTable
|
private let attachmentsLookupTable: DatabaseLookupTable
|
||||||
|
private var databaseArticlesCache = [String: DatabaseArticle]()
|
||||||
|
|
||||||
private lazy var searchTable: SearchTable = {
|
private lazy var searchTable: SearchTable = {
|
||||||
return SearchTable(queue: queue, articlesTable: self)
|
return SearchTable(queue: queue, articlesTable: self)
|
||||||
|
@ -482,16 +483,21 @@ private extension ArticlesTable {
|
||||||
func makeDatabaseArticles(with resultSet: FMResultSet) -> Set<DatabaseArticle> {
|
func makeDatabaseArticles(with resultSet: FMResultSet) -> Set<DatabaseArticle> {
|
||||||
let articles = resultSet.mapToSet { (row) -> DatabaseArticle? in
|
let articles = resultSet.mapToSet { (row) -> DatabaseArticle? in
|
||||||
|
|
||||||
// The resultSet is a result of a JOIN query with the statuses table,
|
guard let articleID = row.string(forColumn: DatabaseKey.articleID) else {
|
||||||
// so we can get the statuses at the same time and avoid additional database lookups.
|
assertionFailure("Expected articleID.")
|
||||||
|
|
||||||
guard let status = statusesTable.statusWithRow(resultSet) else {
|
|
||||||
assertionFailure("Expected status.")
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let articleID = row.string(forColumn: DatabaseKey.articleID) else {
|
// Articles are removed from the cache when they’re updated.
|
||||||
assertionFailure("Expected articleID.")
|
// 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
|
return nil
|
||||||
}
|
}
|
||||||
guard let feedID = row.string(forColumn: DatabaseKey.feedID) else {
|
guard let feedID = row.string(forColumn: DatabaseKey.feedID) else {
|
||||||
|
@ -514,7 +520,9 @@ private extension ArticlesTable {
|
||||||
let datePublished = row.date(forColumn: DatabaseKey.datePublished)
|
let datePublished = row.date(forColumn: DatabaseKey.datePublished)
|
||||||
let dateModified = row.date(forColumn: DatabaseKey.dateModified)
|
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
|
return articles
|
||||||
|
@ -670,6 +678,7 @@ private extension ArticlesTable {
|
||||||
|
|
||||||
|
|
||||||
func saveUpdatedArticles(_ updatedArticles: Set<Article>, _ fetchedArticles: [String: Article], _ database: FMDatabase) {
|
func saveUpdatedArticles(_ updatedArticles: Set<Article>, _ fetchedArticles: [String: Article], _ database: FMDatabase) {
|
||||||
|
removeArticlesFromDatabaseArticlesCache(updatedArticles)
|
||||||
saveUpdatedRelatedObjects(updatedArticles, fetchedArticles, database)
|
saveUpdatedRelatedObjects(updatedArticles, fetchedArticles, database)
|
||||||
|
|
||||||
for updatedArticle in updatedArticles {
|
for updatedArticle in updatedArticles {
|
||||||
|
@ -694,6 +703,13 @@ private extension ArticlesTable {
|
||||||
updateRowsWithDictionary(changesDictionary, whereKey: DatabaseKey.articleID, matches: updatedArticle.articleID, database: database)
|
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 {
|
func statusIndicatesArticleIsIgnorable(_ status: ArticleStatus) -> Bool {
|
||||||
// Ignorable articles: either userDeleted==1 or (not starred and arrival date > 4 months).
|
// Ignorable articles: either userDeleted==1 or (not starred and arrival date > 4 months).
|
||||||
if status.userDeleted {
|
if status.userDeleted {
|
||||||
|
|
|
@ -105,6 +105,10 @@ final class StatusesTable: DatabaseTable {
|
||||||
guard let articleID = row.string(forColumn: DatabaseKey.articleID) else {
|
guard let articleID = row.string(forColumn: DatabaseKey.articleID) else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
return statusWithRow(row, articleID: articleID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func statusWithRow(_ row: FMResultSet, articleID: String) ->ArticleStatus? {
|
||||||
if let cachedStatus = cache[articleID] {
|
if let cachedStatus = cache[articleID] {
|
||||||
return cachedStatus
|
return cachedStatus
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue