mirror of
https://github.com/Ranchero-Software/NetNewsWire.git
synced 2025-01-31 11:14:54 +01:00
Continue surgery. Still broken build.
This commit is contained in:
parent
d47c60e6de
commit
41d8a7f3de
@ -21,20 +21,22 @@ public final class ArticleStatus: Hashable {
|
||||
public var starred = false
|
||||
public var userDeleted = false
|
||||
public var dateArrived: Date
|
||||
var accountInfo: AccountInfo?
|
||||
public let articleID: String
|
||||
public var accountInfo: AccountInfo?
|
||||
public let hashValue: Int
|
||||
|
||||
init(read: Bool, starred: Bool, userDeleted: Bool, dateArrived: Date, accountInfo: AccountInfo?) {
|
||||
public init(articleID: String, read: Bool, starred: Bool, userDeleted: Bool, dateArrived: Date, accountInfo: AccountInfo?) {
|
||||
|
||||
self.articleID = articleID
|
||||
self.read = read
|
||||
self.starred = starred
|
||||
self.userDeleted = userDeleted
|
||||
self.dateArrived = dateArrived
|
||||
self.accountInfo = accountInfo
|
||||
self.hashValue = dateArrived.hashValue
|
||||
self.hashValue = articleID.hashValue
|
||||
}
|
||||
|
||||
func boolStatusForKey(_ key: String) -> Bool {
|
||||
public func boolStatus(forKey key: String) -> Bool {
|
||||
|
||||
if let articleStatusKey = ArticleStatusKey(rawValue: key) {
|
||||
switch articleStatusKey {
|
||||
@ -52,7 +54,7 @@ public final class ArticleStatus: Hashable {
|
||||
return false
|
||||
}
|
||||
|
||||
func setBoolStatusForKey(_ status: Bool, key: String) {
|
||||
public func setBoolStatus(_ status: Bool, forKey key: String) {
|
||||
|
||||
if let articleStatusKey = ArticleStatusKey(rawValue: key) {
|
||||
switch articleStatusKey {
|
||||
@ -74,6 +76,6 @@ public final class ArticleStatus: Hashable {
|
||||
|
||||
public class func ==(lhs: ArticleStatus, rhs: ArticleStatus) -> Bool {
|
||||
|
||||
return lhs.dateArrived == rhs.dateArrived && lhs.read == rhs.read && lhs.starred == rhs.starred
|
||||
return lhs.articleID == rhs.articleID && lhs.dateArrived == rhs.dateArrived && lhs.read == rhs.read && lhs.starred == rhs.starred
|
||||
}
|
||||
}
|
||||
|
28
Frameworks/Database/Constants.swift
Normal file
28
Frameworks/Database/Constants.swift
Normal file
@ -0,0 +1,28 @@
|
||||
//
|
||||
// Keys.swift
|
||||
// Database
|
||||
//
|
||||
// Created by Brent Simmons on 7/3/17.
|
||||
// Copyright © 2017 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct DatabaseTableName {
|
||||
|
||||
static let articles = "articles"
|
||||
static let statuses = "statuses"
|
||||
}
|
||||
|
||||
public struct DatabaseKey {
|
||||
|
||||
static let articleID = "articleID"
|
||||
static let accountInfo = "accountInfo"
|
||||
|
||||
// ArticleStatus
|
||||
static let read = "read"
|
||||
static let starred = "starred"
|
||||
static let userDeleted = "userDeleted"
|
||||
static let dateArrived = "dateArrived"
|
||||
}
|
||||
|
@ -1,9 +1,5 @@
|
||||
/*articleID is a hash of [something]+feedID. When there's a guid, [something] is a guid. Otherwise it's a combination of non-null properties.*/
|
||||
|
||||
CREATE TABLE if not EXISTS articles (articleID TEXT NOT NULL PRIMARY KEY, feedID TEXT NOT NULL, guid TEXT, title TEXT, body TEXT, datePublished DATE, dateModified DATE, link TEXT, permalink TEXT, author TEXT);
|
||||
|
||||
CREATE TABLE if not EXISTS statuses (articleID TEXT NOT NULL PRIMARY KEY, read BOOL NOT NULL DEFAULT 0, starred BOOL NOT NULL DEFAULT 0, userDeleted BOOL NOT NULL DEFAULT 0, dateArrived DATE NOT NULL DEFAULT 0);
|
||||
|
||||
/*Indexes*/
|
||||
CREATE TABLE if not EXISTS statuses (articleID TEXT NOT NULL PRIMARY KEY, read BOOL NOT NULL DEFAULT 0, starred BOOL NOT NULL DEFAULT 0, userDeleted BOOL NOT NULL DEFAULT 0, dateArrived DATE NOT NULL DEFAULT 0, accountInfo BLOB);
|
||||
|
||||
CREATE INDEX if not EXISTS feedIndex on articles (feedID);
|
||||
|
@ -12,9 +12,9 @@ import RSDatabase
|
||||
import RSParser
|
||||
import Data
|
||||
|
||||
let sqlLogging = false
|
||||
private let sqlLogging = false
|
||||
|
||||
func logSQL(_ sql: String) {
|
||||
private func logSQL(_ sql: String) {
|
||||
if sqlLogging {
|
||||
print("SQL: \(sql)")
|
||||
}
|
||||
@ -22,9 +22,7 @@ func logSQL(_ sql: String) {
|
||||
|
||||
typealias ArticleResultBlock = (Set<Article>) -> Void
|
||||
|
||||
private let articlesTableName = "articles"
|
||||
|
||||
final class LocalDatabase {
|
||||
final class Database {
|
||||
|
||||
fileprivate let queue: RSDatabaseQueue
|
||||
private let databaseFile: String
|
||||
@ -51,10 +49,6 @@ final class LocalDatabase {
|
||||
|
||||
func fetchArticlesForFeed(_ feed: Feed) -> Set<Article> {
|
||||
|
||||
// if let articles = articleCache.cachedArticlesForFeedID(feed.feedID) {
|
||||
// return articles
|
||||
// }
|
||||
|
||||
var fetchedArticles = Set<Article>()
|
||||
let feedID = feed.feedID
|
||||
|
||||
@ -63,17 +57,12 @@ final class LocalDatabase {
|
||||
fetchedArticles = self.fetchArticlesForFeedID(feedID, database: database)
|
||||
}
|
||||
|
||||
let articles = articleCache.uniquedArticles(fetchedArticles)
|
||||
let articles = articleCache.uniquedArticles(fetchedArticles, statusesManager: statusesManager)
|
||||
return filteredArticles(articles, feedCounts: [feed.feedID: fetchedArticles.count])
|
||||
}
|
||||
|
||||
func fetchArticlesForFeedAsync(_ feed: Feed, _ resultBlock: @escaping ArticleResultBlock) {
|
||||
|
||||
// if let articles = articleCache.cachedArticlesForFeedID(feed.feedID) {
|
||||
// resultBlock(articles)
|
||||
// return
|
||||
// }
|
||||
|
||||
let feedID = feed.feedID
|
||||
|
||||
queue.fetch { (database: FMDatabase!) -> Void in
|
||||
@ -82,7 +71,7 @@ final class LocalDatabase {
|
||||
|
||||
DispatchQueue.main.async() { () -> Void in
|
||||
|
||||
let articles = self.articleCache.uniquedArticles(fetchedArticles)
|
||||
let articles = self.articleCache.uniquedArticles(fetchedArticles, statusesManager: self.statusesManager)
|
||||
let filteredArticles = self.filteredArticles(articles, feedCounts: [feed.feedID: fetchedArticles.count])
|
||||
resultBlock(filteredArticles)
|
||||
}
|
||||
@ -131,13 +120,13 @@ final class LocalDatabase {
|
||||
|
||||
func fetchUnreadArticlesForFolder(_ folder: Folder) -> Set<Article> {
|
||||
|
||||
return fetchUnreadArticlesForFeedIDs(Array(folder.flattenedFeedIDs))
|
||||
return fetchUnreadArticlesForFeedIDs(folder.flattenedFeedIDs())
|
||||
}
|
||||
|
||||
func fetchUnreadArticlesForFeedIDs(_ feedIDs: [String]) -> Set<Article> {
|
||||
|
||||
if feedIDs.isEmpty {
|
||||
return Set<LocalArticle>()
|
||||
return Set<Article>()
|
||||
}
|
||||
|
||||
var fetchedArticles = Set<Article>()
|
||||
@ -158,7 +147,7 @@ final class LocalDatabase {
|
||||
}
|
||||
}
|
||||
|
||||
let articles = articleCache.uniquedArticles(fetchedArticles)
|
||||
let articles = articleCache.uniquedArticles(fetchedArticles, statusesManager: statusesManager)
|
||||
return filteredArticles(articles, feedCounts: counts)
|
||||
}
|
||||
|
||||
@ -193,7 +182,7 @@ final class LocalDatabase {
|
||||
|
||||
fetchArticlesForFeedAsync(feed) { (articles) -> Void in
|
||||
|
||||
let articlesDictionary = self.articlesDictionary(articles as NSSet) as! [String: LocalArticle]
|
||||
let articlesDictionary = self.articlesDictionary(articles as NSSet) as! [String: Article]
|
||||
self.updateArticles(articlesDictionary, parsedArticles: parsedArticlesDictionary, feed: feed, completionHandler: completionHandler)
|
||||
}
|
||||
}
|
||||
@ -208,7 +197,7 @@ final class LocalDatabase {
|
||||
|
||||
// MARK: Private
|
||||
|
||||
private extension LocalDatabase {
|
||||
private extension Database {
|
||||
|
||||
// MARK: Saving Articles
|
||||
|
||||
@ -222,7 +211,7 @@ private extension LocalDatabase {
|
||||
articleCache.cacheArticles(newArticles)
|
||||
|
||||
let newArticleDictionaries = newArticles.map { (oneArticle) in
|
||||
return oneArticle.databaseDictionary
|
||||
return oneArticle.databaseDictionary()
|
||||
}
|
||||
|
||||
queue.update { (database: FMDatabase!) -> Void in
|
||||
@ -232,7 +221,7 @@ private extension LocalDatabase {
|
||||
for oneDictionary in articleChanges {
|
||||
|
||||
let oneArticleDictionary = oneDictionary.mutableCopy() as! NSMutableDictionary
|
||||
let articleID = oneArticleDictionary[articleIDKey]!
|
||||
let articleID = oneArticleDictionary[DatabaseKey.articleID]!
|
||||
oneArticleDictionary.removeObject(forKey: articleIDKey)
|
||||
|
||||
let _ = database.rs_updateRows(with: oneArticleDictionary as [NSObject: AnyObject], whereKey: articleIDKey, equalsValue: articleID, tableName: articlesTableName)
|
||||
@ -292,7 +281,7 @@ private extension LocalDatabase {
|
||||
|
||||
func createNewArticlesWithParsedArticles(_ parsedArticles: Set<ParsedItem>, feedID: String) -> Set<Article> {
|
||||
|
||||
return Set(parsedArticles.map { LocalArticle(account: account, feedID: feedID, parsedArticle: $0) })
|
||||
return Set(parsedArticles.map { Article(account: account, feedID: feedID, parsedArticle: $0) })
|
||||
}
|
||||
|
||||
func articlesWithParsedArticles(_ parsedArticles: Set<ParsedItem>, feedID: String) -> Set<Article> {
|
||||
@ -300,7 +289,7 @@ private extension LocalDatabase {
|
||||
var localArticles = Set<Article>()
|
||||
|
||||
for oneParsedArticle in parsedArticles {
|
||||
let oneLocalArticle = LocalArticle(account: self.account, feedID: feedID, parsedArticle: oneParsedArticle)
|
||||
let oneLocalArticle = Article(account: self.account, feedID: feedID, parsedArticle: oneParsedArticle)
|
||||
localArticles.insert(oneLocalArticle)
|
||||
}
|
||||
|
||||
@ -343,7 +332,7 @@ private extension LocalDatabase {
|
||||
return articlesWithResultSet(resultSet)
|
||||
}
|
||||
|
||||
return Set<LocalArticle>()
|
||||
return Set<Article>()
|
||||
}
|
||||
|
||||
func articlesWithResultSet(_ resultSet: FMResultSet) -> Set<Article> {
|
||||
@ -496,46 +485,4 @@ private extension LocalDatabase {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func deleteOldArticlesInFeed(_ feed: Feed) {
|
||||
|
||||
numberOfArticlesInFeedID(feed.feedID) { (numberOfArticlesInFeed) in
|
||||
|
||||
if numberOfArticlesInFeed <= LocalDatabase.minimumNumberOfArticlesInFeed {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// MARK: Deleting Articles
|
||||
|
||||
// func deleteOldArticles(_ articleIDsInFeeds: Set<String>) {
|
||||
//
|
||||
// queue.update { (database: FMDatabase!) -> Void in
|
||||
//
|
||||
//// let cutoffDate = NSDate.rs_dateWithNumberOfDaysInThePast(60)
|
||||
//// let articles = self.fetchArticlesWithWhereClause(database, whereClause: "statuses.dateArrived < ? limit 200", parameters: [cutoffDate])
|
||||
//
|
||||
//// var articleIDsToDelete = Set<String>()
|
||||
////
|
||||
//// for oneArticle in articles {
|
||||
// // TODO
|
||||
//// if !localAccountShouldIncludeArticle(oneArticle, articleIDsInFeed: articleIDsInFeeds) {
|
||||
//// articleIDsToDelete.insert(oneArticle.articleID)
|
||||
//// }
|
||||
//// }
|
||||
//
|
||||
//// if !articleIDsToDelete.isEmpty {
|
||||
//// database.rs_deleteRowsWhereKey(articleIDKey, inValues: Array(articleIDsToDelete), tableName: articlesTableName)
|
||||
//// }
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -9,6 +9,11 @@
|
||||
/* Begin PBXBuildFile section */
|
||||
844BEE411F0AB3AB004AB7CD /* Database.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 844BEE371F0AB3AA004AB7CD /* Database.framework */; };
|
||||
844BEE461F0AB3AB004AB7CD /* DatabaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 844BEE451F0AB3AB004AB7CD /* DatabaseTests.swift */; };
|
||||
845580671F0AEBCD003CCFA1 /* Constants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845580661F0AEBCD003CCFA1 /* Constants.swift */; };
|
||||
845580721F0AEE49003CCFA1 /* PropertyListTransformer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845580711F0AEE49003CCFA1 /* PropertyListTransformer.swift */; };
|
||||
845580761F0AF670003CCFA1 /* Article+Database.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845580751F0AF670003CCFA1 /* Article+Database.swift */; };
|
||||
845580781F0AF678003CCFA1 /* Folder+Database.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845580771F0AF678003CCFA1 /* Folder+Database.swift */; };
|
||||
8455807A1F0AF67D003CCFA1 /* ArticleStatus+Database.swift in Sources */ = {isa = PBXBuildFile; fileRef = 845580791F0AF67D003CCFA1 /* ArticleStatus+Database.swift */; };
|
||||
846146271F0ABC7B00870CB3 /* RSParser.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 846146241F0ABC7400870CB3 /* RSParser.framework */; };
|
||||
84E156EA1F0AB80500F8CC05 /* Database.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84E156E91F0AB80500F8CC05 /* Database.swift */; };
|
||||
84E156EC1F0AB80E00F8CC05 /* ArticlesManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84E156EB1F0AB80E00F8CC05 /* ArticlesManager.swift */; };
|
||||
@ -83,6 +88,11 @@
|
||||
844BEE401F0AB3AB004AB7CD /* DatabaseTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DatabaseTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
844BEE451F0AB3AB004AB7CD /* DatabaseTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseTests.swift; sourceTree = "<group>"; };
|
||||
844BEE471F0AB3AB004AB7CD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
845580661F0AEBCD003CCFA1 /* Constants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Constants.swift; sourceTree = "<group>"; };
|
||||
845580711F0AEE49003CCFA1 /* PropertyListTransformer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PropertyListTransformer.swift; sourceTree = "<group>"; };
|
||||
845580751F0AF670003CCFA1 /* Article+Database.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Article+Database.swift"; path = "Extensions/Article+Database.swift"; sourceTree = "<group>"; };
|
||||
845580771F0AF678003CCFA1 /* Folder+Database.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Folder+Database.swift"; path = "Extensions/Folder+Database.swift"; sourceTree = "<group>"; };
|
||||
845580791F0AF67D003CCFA1 /* ArticleStatus+Database.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "ArticleStatus+Database.swift"; path = "Extensions/ArticleStatus+Database.swift"; sourceTree = "<group>"; };
|
||||
8461461E1F0ABC7300870CB3 /* RSParser.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RSParser.xcodeproj; path = ../RSParser/RSParser.xcodeproj; sourceTree = "<group>"; };
|
||||
84E156E81F0AB75600F8CC05 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
84E156E91F0AB80500F8CC05 /* Database.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Database.swift; sourceTree = "<group>"; };
|
||||
@ -121,8 +131,11 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
84E156E91F0AB80500F8CC05 /* Database.swift */,
|
||||
845580661F0AEBCD003CCFA1 /* Constants.swift */,
|
||||
84E156EB1F0AB80E00F8CC05 /* ArticlesManager.swift */,
|
||||
84E156ED1F0AB81400F8CC05 /* StatusesManager.swift */,
|
||||
845580711F0AEE49003CCFA1 /* PropertyListTransformer.swift */,
|
||||
8461462A1F0AC44100870CB3 /* Extensions */,
|
||||
84E156EF1F0AB81F00F8CC05 /* CreateStatements.sql */,
|
||||
84E156E81F0AB75600F8CC05 /* Info.plist */,
|
||||
844BEE441F0AB3AB004AB7CD /* DatabaseTests */,
|
||||
@ -158,6 +171,16 @@
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
8461462A1F0AC44100870CB3 /* Extensions */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
845580771F0AF678003CCFA1 /* Folder+Database.swift */,
|
||||
845580751F0AF670003CCFA1 /* Article+Database.swift */,
|
||||
845580791F0AF67D003CCFA1 /* ArticleStatus+Database.swift */,
|
||||
);
|
||||
name = Extensions;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
84E156F21F0AB83600F8CC05 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -370,6 +393,11 @@
|
||||
84E156EA1F0AB80500F8CC05 /* Database.swift in Sources */,
|
||||
84E156EC1F0AB80E00F8CC05 /* ArticlesManager.swift in Sources */,
|
||||
84E156EE1F0AB81400F8CC05 /* StatusesManager.swift in Sources */,
|
||||
845580671F0AEBCD003CCFA1 /* Constants.swift in Sources */,
|
||||
845580781F0AF678003CCFA1 /* Folder+Database.swift in Sources */,
|
||||
845580761F0AF670003CCFA1 /* Article+Database.swift in Sources */,
|
||||
845580721F0AEE49003CCFA1 /* PropertyListTransformer.swift in Sources */,
|
||||
8455807A1F0AF67D003CCFA1 /* ArticleStatus+Database.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
26
Frameworks/Database/Extensions/Article+Database.swift
Normal file
26
Frameworks/Database/Extensions/Article+Database.swift
Normal file
@ -0,0 +1,26 @@
|
||||
//
|
||||
// Article+Database.swift
|
||||
// Database
|
||||
//
|
||||
// Created by Brent Simmons on 7/3/17.
|
||||
// Copyright © 2017 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RSDatabase
|
||||
import Data
|
||||
|
||||
extension Article {
|
||||
|
||||
convenience init?(row: FMResultSet) {
|
||||
|
||||
}
|
||||
|
||||
func databaseDictionary() -> NSDictionary {
|
||||
|
||||
var d = NSMutableDictionary()
|
||||
|
||||
|
||||
return d.copy() as! NSDictionary
|
||||
}
|
||||
}
|
52
Frameworks/Database/Extensions/ArticleStatus+Database.swift
Normal file
52
Frameworks/Database/Extensions/ArticleStatus+Database.swift
Normal file
@ -0,0 +1,52 @@
|
||||
//
|
||||
// ArticleStatus+Database.swift
|
||||
// Database
|
||||
//
|
||||
// Created by Brent Simmons on 7/3/17.
|
||||
// Copyright © 2017 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RSDatabase
|
||||
import Data
|
||||
|
||||
extension ArticleStatus {
|
||||
|
||||
convenience init?(row: FMResultSet) {
|
||||
|
||||
let articleID = row.string(forColumn: DatabaseKey.articleID)
|
||||
if (articleID == nil) {
|
||||
return nil
|
||||
}
|
||||
let read = row.bool(forColumn: DatabaseKey.read)
|
||||
let starred = row.bool(forColumn: DatabaseKey.starred)
|
||||
let userDeleted = row.bool(forColumn: DatabaseKey.userDeleted)
|
||||
|
||||
var dateArrived = row.date(forColumn: DatabaseKey.dateArrived)
|
||||
if (dateArrived == nil) {
|
||||
dateArrived = NSDate.distantPast
|
||||
}
|
||||
|
||||
let accountInfoPlist = PropertyListTransformer.accountInfoWithRow(row)
|
||||
|
||||
self.init(articleID: articleID!, read: read, starred: starred, userDeleted: userDeleted, dateArrived: dateArrived!, accountInfo: accountInfoPlist)
|
||||
}
|
||||
|
||||
func databaseDictionary() -> NSDictionary {
|
||||
|
||||
let d = NSMutableDictionary()
|
||||
|
||||
d[DatabaseKey.articleID] = articleID
|
||||
d[DatabaseKey.read] = read
|
||||
d[DatabaseKey.starred] = starred
|
||||
d[DatabaseKey.userDeleted] = userDeleted
|
||||
d[DatabaseKey.dateArrived] = dateArrived
|
||||
|
||||
if let accountInfo = accountInfo, let data = PropertyListTransformer.data(withPropertyList: accountInfo) {
|
||||
d[DatabaseKey.accountInfo] = data
|
||||
}
|
||||
|
||||
return d.copy() as! NSDictionary
|
||||
}
|
||||
}
|
||||
|
18
Frameworks/Database/Extensions/Folder+Database.swift
Normal file
18
Frameworks/Database/Extensions/Folder+Database.swift
Normal file
@ -0,0 +1,18 @@
|
||||
//
|
||||
// Folder+Database.swift
|
||||
// Database
|
||||
//
|
||||
// Created by Brent Simmons on 7/3/17.
|
||||
// Copyright © 2017 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Data
|
||||
|
||||
extension Folder {
|
||||
|
||||
func flattenedFeedIDs() -> [String] {
|
||||
|
||||
return flattenedFeeds().map { $0.feedID }
|
||||
}
|
||||
}
|
54
Frameworks/Database/PropertyListTransformer.swift
Normal file
54
Frameworks/Database/PropertyListTransformer.swift
Normal file
@ -0,0 +1,54 @@
|
||||
//
|
||||
// AccountInfo.swift
|
||||
// Database
|
||||
//
|
||||
// Created by Brent Simmons on 7/3/17.
|
||||
// Copyright © 2017 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import RSDatabase
|
||||
import Data
|
||||
|
||||
// This allows for serializing structures such as Author, Attachment, and AccountInfo
|
||||
// without having to create separate tables and lookup tables.
|
||||
// While there are good strong arguments for using separate tables,
|
||||
// we decided that the relative simplicity this allows is worth it.
|
||||
|
||||
struct PropertyListTransformer {
|
||||
|
||||
static func accountInfoWithRow(_ row: FMResultSet) -> AccountInfo? {
|
||||
|
||||
guard let rawAccountInfo = row.data(forColumn: DatabaseKey.accountInfo) else {
|
||||
return nil
|
||||
}
|
||||
return propertyList(withData: rawAccountInfo) as? AccountInfo
|
||||
}
|
||||
|
||||
static func propertyListWithRow(_ row: FMResultSet, column: String) -> Any? {
|
||||
|
||||
guard let rawData = row.data(forColumn: column) else {
|
||||
return nil
|
||||
}
|
||||
return propertyList(withData: rawData)
|
||||
}
|
||||
|
||||
static func propertyList(withData data: Data) -> Any? {
|
||||
|
||||
do {
|
||||
return try PropertyListSerialization.propertyList(fromData: rawAccountInfo, options: [], format: nil)
|
||||
} catch {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
static func data(withPropertyList plist: Any) -> Data? {
|
||||
|
||||
do {
|
||||
return try PropertyListSerialization.data(from: plist, format: .binary, options: [])
|
||||
}
|
||||
catch {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
@ -22,7 +22,7 @@ final class StatusesManager {
|
||||
self.queue = queue
|
||||
}
|
||||
|
||||
func markArticles(_ articles: Set<Article>, statusKey: ArticleStatusKey, flag: Bool) {
|
||||
func markArticles(_ articles: Set<Article>, statusKey: String, flag: Bool) {
|
||||
|
||||
assertNoMissingStatuses(articles)
|
||||
let statuses = Set(articles.flatMap { $0.status })
|
||||
@ -36,7 +36,7 @@ final class StatusesManager {
|
||||
if let cachedStatus = cachedStatusForArticleID(oneArticle.articleID) {
|
||||
oneArticle.status = cachedStatus
|
||||
}
|
||||
else if let oneArticleStatus = oneArticle.status as? ArticleStatus {
|
||||
else if let oneArticleStatus = oneArticle.status {
|
||||
cacheStatus(oneArticleStatus)
|
||||
}
|
||||
}
|
||||
@ -85,7 +85,7 @@ private extension StatusesManager {
|
||||
|
||||
// MARK: Marking
|
||||
|
||||
func markArticleStatuses(_ statuses: Set<ArticleStatus>, statusKey: ArticleStatusKey, flag: Bool) {
|
||||
func markArticleStatuses(_ statuses: Set<ArticleStatus>, statusKey: String, flag: Bool) {
|
||||
|
||||
// Ignore the statuses where status.[statusKey] == flag. Update the remainder and save in database.
|
||||
|
||||
@ -93,8 +93,8 @@ private extension StatusesManager {
|
||||
|
||||
statuses.forEach { (oneStatus) in
|
||||
|
||||
if oneStatus.boolStatusForKey(statusKey) != flag {
|
||||
oneStatus.setBoolStatusForKey(flag, articleStatusKey: statusKey)
|
||||
if oneStatus.boolStatus(forKey: statusKey) != flag {
|
||||
oneStatus.setBoolStatus(flag, forKey: statusKey)
|
||||
articleIDs.insert(oneStatus.articleID)
|
||||
}
|
||||
}
|
||||
@ -112,7 +112,7 @@ private extension StatusesManager {
|
||||
return Set<ArticleStatus>()
|
||||
}
|
||||
|
||||
guard let resultSet = database.rs_selectRowsWhereKey(articleIDKey, inValues: Array(articleIDs), tableName: statusesTableName) else {
|
||||
guard let resultSet = database.rs_selectRowsWhereKey(DatabaseKey.articleID, inValues: Array(articleIDs), tableName: statusesTableName) else {
|
||||
return Set<ArticleStatus>()
|
||||
}
|
||||
|
||||
@ -137,7 +137,7 @@ private extension StatusesManager {
|
||||
func saveStatuses(_ statuses: Set<ArticleStatus>) {
|
||||
|
||||
let statusArray = statuses.map { (oneStatus) -> NSDictionary in
|
||||
return oneStatus.databaseDictionary
|
||||
return oneStatus.databaseDictionary()
|
||||
}
|
||||
|
||||
queue.update { (database: FMDatabase!) -> Void in
|
||||
@ -210,9 +210,9 @@ private extension StatusesManager {
|
||||
|
||||
extension ParsedItem {
|
||||
|
||||
var databaseID: String {
|
||||
var articleID: String {
|
||||
get {
|
||||
return "\(feedURL) \(uniqueID)"
|
||||
return "\(feedURL) \(uniqueID)" //Must be same as Article.articleID
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user