diff --git a/Frameworks/Data/Article.swift b/Frameworks/Data/Article.swift index b98df64a7..743f87b1c 100644 --- a/Frameworks/Data/Article.swift +++ b/Frameworks/Data/Article.swift @@ -11,9 +11,9 @@ import Foundation public final class Article: Hashable { weak var account: Account? + public let feedID: String public let articleID: String //Calculated: unique per account - public var uniqueID: String //guid: unique per feed public var title: String? public var contentHTML: String? @@ -28,10 +28,10 @@ public final class Article: Hashable { public var authors: [Author]? public var tags: [String]? public var attachments: [Attachment]? + public var accountInfo: [String: Any]? //If account needs to store more data + public var status: ArticleStatus? public let hashValue: Int - - public var accountInfo: [String: Any]? //If account needs to store more data var feed: Feed? { get { @@ -39,7 +39,7 @@ public final class Article: Hashable { } } - init(account: Account, feedID: String, uniqueID: String, title: String?, contentHTML: String?, contentText: String?, url: String?, externalURL: String?, summary: String?, imageURL: String?, bannerImageURL: String?, datePublished: Date?, dateModified: Date?, authors: [Author]?, tags: [String]?, attachments: [Attachment]?) { + init(account: Account, feedID: String, uniqueID: String, title: String?, contentHTML: String?, contentText: String?, url: String?, externalURL: String?, summary: String?, imageURL: String?, bannerImageURL: String?, datePublished: Date?, dateModified: Date?, authors: [Author]?, tags: [String]?, attachments: [Attachment]?, accountInfo: AccountInfo?) { self.account = account self.feedID = feedID @@ -57,6 +57,7 @@ public final class Article: Hashable { self.authors = authors self.tags = tags self.attachments = attachments + self.accountInfo = accountInfo self.articleID = "\(feedID) \(uniqueID)" self.hashValue = account.hashValue + feedID.hashValue + uniqueID.hashValue diff --git a/Frameworks/Data/Attachment.swift b/Frameworks/Data/Attachment.swift index 97ee24f4f..9ce0543fb 100644 --- a/Frameworks/Data/Attachment.swift +++ b/Frameworks/Data/Attachment.swift @@ -10,13 +10,13 @@ import Foundation public struct Attachment: Equatable { - public let url: String? + public let url: String public let mimeType: String? public let title: String? public let sizeInBytes: Int? public let durationInSeconds: Int? - init(url: String?, mimeType: String?, title: String?, sizeInBytes: Int?, durationInSeconds: Int?) { + init(url: String, mimeType: String?, title: String?, sizeInBytes: Int?, durationInSeconds: Int?) { self.url = url self.mimeType = mimeType diff --git a/Frameworks/Database/Constants.swift b/Frameworks/Database/Constants.swift index 321f85db9..f870f6c39 100644 --- a/Frameworks/Database/Constants.swift +++ b/Frameworks/Database/Constants.swift @@ -16,13 +16,36 @@ public struct DatabaseTableName { public struct DatabaseKey { + // Shared static let articleID = "articleID" static let accountInfo = "accountInfo" + static let url = "url" + static let title = "title" + + // Article + static let feedID = "feedID" + static let uniqueID = "uniqueID" + static let contentHTML = "contentHTML" + static let contentText = "contentText" + static let externalURL = "externalURL" + static let summary = "summary" + static let imageURL = "imageURL" + static let bannerImageURL = "bannerImageURL" + static let datePublished = "datePublished" + static let dateModified = "dateModified" + static let authors = "authors" + static let tags = "tags" + static let attachments = "attachments" // ArticleStatus static let read = "read" static let starred = "starred" static let userDeleted = "userDeleted" static let dateArrived = "dateArrived" + + // Attachment + static let mimeType = "mimeType" + static let sizeInBytes = "sizeInBytes" + static let durationInSeconds = "durationInSeconds" } diff --git a/Frameworks/Database/CreateStatements.sql b/Frameworks/Database/CreateStatements.sql index 0e10c8854..8b02c2dfd 100644 --- a/Frameworks/Database/CreateStatements.sql +++ b/Frameworks/Database/CreateStatements.sql @@ -1,4 +1,4 @@ -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 articles (articleID TEXT NOT NULL PRIMARY KEY, feedID TEXT NOT NULL, uniqueID TEXT, title TEXT, contentHTML TEXT, contentText TEXT, url TEXT, externalURL TEXT, summary TEXT, imageURL TEXT, bannerImageURL TEXT, datePublished DATE, dateModified DATE, authors BLOB, tags BLOB, attachments BLOB, accountInfo BLOB); 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); diff --git a/Frameworks/Database/Database.xcodeproj/project.pbxproj b/Frameworks/Database/Database.xcodeproj/project.pbxproj index 36db5d98b..37966e77d 100644 --- a/Frameworks/Database/Database.xcodeproj/project.pbxproj +++ b/Frameworks/Database/Database.xcodeproj/project.pbxproj @@ -14,6 +14,7 @@ 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 */; }; + 8455807C1F0C0DBD003CCFA1 /* Attachment+Database.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8455807B1F0C0DBD003CCFA1 /* Attachment+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 */; }; @@ -93,6 +94,7 @@ 845580751F0AF670003CCFA1 /* Article+Database.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Article+Database.swift"; path = "Extensions/Article+Database.swift"; sourceTree = ""; }; 845580771F0AF678003CCFA1 /* Folder+Database.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Folder+Database.swift"; path = "Extensions/Folder+Database.swift"; sourceTree = ""; }; 845580791F0AF67D003CCFA1 /* ArticleStatus+Database.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "ArticleStatus+Database.swift"; path = "Extensions/ArticleStatus+Database.swift"; sourceTree = ""; }; + 8455807B1F0C0DBD003CCFA1 /* Attachment+Database.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = "Attachment+Database.swift"; path = "Extensions/Attachment+Database.swift"; sourceTree = ""; }; 8461461E1F0ABC7300870CB3 /* RSParser.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RSParser.xcodeproj; path = ../RSParser/RSParser.xcodeproj; sourceTree = ""; }; 84E156E81F0AB75600F8CC05 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 84E156E91F0AB80500F8CC05 /* Database.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Database.swift; sourceTree = ""; }; @@ -134,7 +136,6 @@ 845580661F0AEBCD003CCFA1 /* Constants.swift */, 84E156EB1F0AB80E00F8CC05 /* ArticlesManager.swift */, 84E156ED1F0AB81400F8CC05 /* StatusesManager.swift */, - 845580711F0AEE49003CCFA1 /* PropertyListTransformer.swift */, 8461462A1F0AC44100870CB3 /* Extensions */, 84E156EF1F0AB81F00F8CC05 /* CreateStatements.sql */, 84E156E81F0AB75600F8CC05 /* Info.plist */, @@ -177,6 +178,8 @@ 845580771F0AF678003CCFA1 /* Folder+Database.swift */, 845580751F0AF670003CCFA1 /* Article+Database.swift */, 845580791F0AF67D003CCFA1 /* ArticleStatus+Database.swift */, + 8455807B1F0C0DBD003CCFA1 /* Attachment+Database.swift */, + 845580711F0AEE49003CCFA1 /* PropertyListTransformer.swift */, ); name = Extensions; sourceTree = ""; @@ -393,6 +396,7 @@ 84E156EA1F0AB80500F8CC05 /* Database.swift in Sources */, 84E156EC1F0AB80E00F8CC05 /* ArticlesManager.swift in Sources */, 84E156EE1F0AB81400F8CC05 /* StatusesManager.swift in Sources */, + 8455807C1F0C0DBD003CCFA1 /* Attachment+Database.swift in Sources */, 845580671F0AEBCD003CCFA1 /* Constants.swift in Sources */, 845580781F0AF678003CCFA1 /* Folder+Database.swift in Sources */, 845580761F0AF670003CCFA1 /* Article+Database.swift in Sources */, diff --git a/Frameworks/Database/Extensions/Article+Database.swift b/Frameworks/Database/Extensions/Article+Database.swift index 270db7feb..66714f532 100644 --- a/Frameworks/Database/Extensions/Article+Database.swift +++ b/Frameworks/Database/Extensions/Article+Database.swift @@ -12,8 +12,32 @@ import Data extension Article { - convenience init?(row: FMResultSet) { + convenience init?(row: FMResultSet, account: Account) { + guard let feedID = row.string(forColumn: DatabaseKey.feedID) else { + return nil + } + guard let uniqueID = row.string(forColumn: DatabaseKey.uniqueID) else { + return nil + } + + let articleID = row.string(forColumn: DatabaseKey.articleID)! + let title = row.string(forColumn: DatabaseKey.title) + let contentHTML = row.string(forColumn: DatabaseKey.contentHTML) + let contentText = row.string(forColumn: DatabaseKey.contentText) + let url = row.string(forColumn: DatabaseKey.url) + let externalURL = row.string(forColumn: DatabaseKey.externalURL) + let summary = row.string(forColumn: DatabaseKey.summary) + let imageURL = row.string(forColumn: DatabaseKey.imageURL) + let bannerImageURL = row.string(forColumn: DatabaseKey.bannerImageURL) + let datePublished = row.date(forColumn: DatabaseKey.datePublished) + let dateModified = row.date(forColumn: DatabaseKey.dateModified) + let authors = PropertyListTransformer.authorsWithRow(row) + let tags = PropertyListTransformer.tagsWithRow(row) + let attachments = PropertyListTransformer.attachmentsWithRow(row) + let accountInfo = PropertyListTransformer.accountInfoWithRow(row) + + self.init(account: account, feedID: feed, uniqueID: uniqueID, title: title, contentHTML: contentHTML, contentText: contentText, url: url, externalURL: externalURL, summary: summary, imageURL: imageURL, bannerImageURL: bannerImageURL, datePublished: datePublished, dateModified: dateModified, authors: authors, tags: tags, attachments: attachments, accountInfo: accountInfo] } func databaseDictionary() -> NSDictionary { diff --git a/Frameworks/Database/Extensions/Attachment+Database.swift b/Frameworks/Database/Extensions/Attachment+Database.swift new file mode 100644 index 000000000..60575514a --- /dev/null +++ b/Frameworks/Database/Extensions/Attachment+Database.swift @@ -0,0 +1,34 @@ +// +// Attachment+Database.swift +// Database +// +// Created by Brent Simmons on 7/4/17. +// Copyright © 2017 Ranchero Software. All rights reserved. +// + +import Foundation + +extension Attachment { + + convenience init?(databaseDictionary d: [String: Any]) { + + guard let url = d[DatabaseKey.url] as? String else { + return nil + } + let mimeType = d[DatabaseKey.mimeType] as? String + let title = d[DatabaseKey.title] as? String + let durationInSeconds = d[DatabaseKey.durationInSeconds] as? Int + + self.init(url: url, mimeType: mimeType, title: title, durationInSeconds: durationInSeconds) + } + + class func attachments(with plist: [Any]) -> [Attachment]? { + + return plist.flatMap{ (oneDictionary) -> Attachment? in + if let d = oneDictionary as? [String: Any] { + return Attachment(databaseDictionary: d) + } + return nil + } + } +} diff --git a/Frameworks/Database/PropertyListTransformer.swift b/Frameworks/Database/PropertyListTransformer.swift index d24dbe8dd..50f3ccb04 100644 --- a/Frameworks/Database/PropertyListTransformer.swift +++ b/Frameworks/Database/PropertyListTransformer.swift @@ -25,6 +25,25 @@ struct PropertyListTransformer { return propertyList(withData: rawAccountInfo) as? AccountInfo } + static func tagsWithRow(_ row: FMResultSet) -> [String]? { + + guard let d = row.data(forColumn: DatabaseKey.tags) else { + return nil + } + return propertyList(withData: d) as? [String] + } + + static func attachmentsWithRow(_ row: FMResultSet) -> [Attachment]? { + + guard let d = row.data(forColumn: DatabaseKey.attachments) else { + return nil + } + guard let plist = propertyList(withData: d) as? [Any] else { + return nil + } + return Attachment.attachments(with: plist) + } + static func propertyListWithRow(_ row: FMResultSet, column: String) -> Any? { guard let rawData = row.data(forColumn: column) else {