Continue fixing build errors.
This commit is contained in:
parent
0336e30b0d
commit
92a60d8f06
|
@ -43,9 +43,19 @@ private func accountAndArticlesDictionary(_ articles: Set<Article>) -> [String:
|
||||||
|
|
||||||
extension Article {
|
extension Article {
|
||||||
|
|
||||||
|
var feed: Feed? {
|
||||||
|
get {
|
||||||
|
return account?.existingFeed(with: feedID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var status: ArticleStatus? {
|
var status: ArticleStatus? {
|
||||||
get {
|
get {
|
||||||
return account?.articleStatus(for: self)
|
guard let status = account?.articleStatus(for: self) else {
|
||||||
|
assertionFailure("Expected ArticleStatus for article.status.")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return status
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,4 +70,19 @@ extension Article {
|
||||||
return contentHTML ?? contentText ?? summary
|
return contentHTML ?? contentText ?? summary
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var logicalDatePublished: Date {
|
||||||
|
get {
|
||||||
|
return datePublished ?? dateModified ?? status?.dateArrived ?? Date.distantPast
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var read: Bool {
|
||||||
|
get {
|
||||||
|
if let status = status {
|
||||||
|
return status.read
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ struct TimelineCellData {
|
||||||
self.attributedDateString = s
|
self.attributedDateString = s
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
self.attributedDateString = NSAttributedString(string: self.dateString, attributes: [NSForegroundColorAttributeName: appearance.dateColor, NSFontAttributeName: appearance.dateFont])
|
self.attributedDateString = NSAttributedString(string: self.dateString, attributes: [NSAttributedStringKey.foregroundColor: appearance.dateColor, NSAttributedStringKey.font: appearance.dateFont])
|
||||||
attributedDateCache[self.dateString] = self.attributedDateString
|
attributedDateCache[self.dateString] = self.attributedDateString
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,20 +59,14 @@ struct TimelineCellData {
|
||||||
self.attributedFeedName = s
|
self.attributedFeedName = s
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
self.attributedFeedName = NSAttributedString(string: self.feedName, attributes: [NSForegroundColorAttributeName: appearance.feedNameColor, NSFontAttributeName: appearance.feedNameFont])
|
self.attributedFeedName = NSAttributedString(string: self.feedName, attributes: [NSAttributedStringKey.foregroundColor: appearance.feedNameColor, NSAttributedStringKey.font: appearance.feedNameFont])
|
||||||
attributedFeedNameCache[self.feedName] = self.attributedFeedName
|
attributedFeedNameCache[self.feedName] = self.attributedFeedName
|
||||||
}
|
}
|
||||||
|
|
||||||
self.showFeedName = showFeedName
|
self.showFeedName = showFeedName
|
||||||
|
|
||||||
self.favicon = nil
|
self.favicon = nil
|
||||||
|
self.read = article.read
|
||||||
if let status = article.status {
|
|
||||||
self.read = status.read
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
self.read = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
init() { //Empty
|
init() { //Empty
|
||||||
|
|
|
@ -124,9 +124,7 @@ class TimelineViewController: NSViewController, NSTableViewDelegate, NSTableView
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let articlesSet = NSMutableSet()
|
markArticles(Set(articles), statusKey: ArticleStatusKey.read.rawValue, flag: true)
|
||||||
articlesSet.addObjects(from: articles)
|
|
||||||
markArticles(articlesSet, statusKey: .read, flag: true)
|
|
||||||
|
|
||||||
reloadCellsForArticles(articles)
|
reloadCellsForArticles(articles)
|
||||||
}
|
}
|
||||||
|
@ -147,21 +145,23 @@ class TimelineViewController: NSViewController, NSTableViewDelegate, NSTableView
|
||||||
}
|
}
|
||||||
let articles = selectedArticles
|
let articles = selectedArticles
|
||||||
var markAsRead = true
|
var markAsRead = true
|
||||||
if articles.first!.status.read {
|
if let status = articles.first!.status {
|
||||||
markAsRead = false
|
if status.read {
|
||||||
|
markAsRead = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
markArticles(NSSet(array: articles), statusKey: .read, flag: markAsRead)
|
markArticles(Set(articles), statusKey: ArticleStatusKey.read.rawValue, flag: markAsRead)
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func markSelectedArticlesAsRead(_ sender: AnyObject) {
|
@IBAction func markSelectedArticlesAsRead(_ sender: AnyObject) {
|
||||||
|
|
||||||
markArticles(NSSet(array: selectedArticles), statusKey: .read, flag: true)
|
markArticles(Set(selectedArticles), statusKey: ArticleStatusKey.read.rawValue, flag: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@IBAction func markSelectedArticlesAsUnread(_ sender: AnyObject) {
|
@IBAction func markSelectedArticlesAsUnread(_ sender: AnyObject) {
|
||||||
|
|
||||||
markArticles(NSSet(array: selectedArticles), statusKey: .read, flag: false)
|
markArticles(Set(selectedArticles), statusKey: ArticleStatusKey.read.rawValue, flag: false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: Navigation
|
// MARK: Navigation
|
||||||
|
@ -186,11 +186,12 @@ class TimelineViewController: NSViewController, NSTableViewDelegate, NSTableView
|
||||||
|
|
||||||
func canMarkAllAsRead() -> Bool {
|
func canMarkAllAsRead() -> Bool {
|
||||||
|
|
||||||
for oneArticle in articles {
|
for article in articles {
|
||||||
if !oneArticle.status.read {
|
if !article.read {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,7 +209,7 @@ class TimelineViewController: NSViewController, NSTableViewDelegate, NSTableView
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
let article = articleAtRow(ix)!
|
let article = articleAtRow(ix)!
|
||||||
if !article.status.read {
|
if !article.read {
|
||||||
return ix
|
return ix
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -520,9 +521,8 @@ class TimelineViewController: NSViewController, NSTableViewDelegate, NSTableView
|
||||||
}
|
}
|
||||||
|
|
||||||
if let selectedArticle = articleAtRow(selectedRow) {
|
if let selectedArticle = articleAtRow(selectedRow) {
|
||||||
let articleSet = NSSet(array: [selectedArticle])
|
if (!selectedArticle.read) {
|
||||||
if (!selectedArticle.status.read) {
|
markArticles(Set([selectedArticle]), statusKey: ArticleStatusKey.read.rawValue, flag: true)
|
||||||
markArticles(articleSet, statusKey: .read, flag: true)
|
|
||||||
}
|
}
|
||||||
postTimelineSelectionDidChangeNotification(selectedArticle)
|
postTimelineSelectionDidChangeNotification(selectedArticle)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ import Foundation
|
||||||
import RSCore
|
import RSCore
|
||||||
import Data
|
import Data
|
||||||
import RSParser
|
import RSParser
|
||||||
|
import Database
|
||||||
|
|
||||||
public enum AccountType: Int {
|
public enum AccountType: Int {
|
||||||
|
|
||||||
|
@ -31,6 +32,7 @@ public final class Account: DisplayNameProvider, Hashable {
|
||||||
public let hashValue: Int
|
public let hashValue: Int
|
||||||
let settingsFile: String
|
let settingsFile: String
|
||||||
let dataFolder: String
|
let dataFolder: String
|
||||||
|
let database: Database
|
||||||
var topLevelObjects = [AnyObject]()
|
var topLevelObjects = [AnyObject]()
|
||||||
var feedIDDictionary = [String: Feed]()
|
var feedIDDictionary = [String: Feed]()
|
||||||
var username: String?
|
var username: String?
|
||||||
|
@ -38,19 +40,22 @@ public final class Account: DisplayNameProvider, Hashable {
|
||||||
|
|
||||||
init?(dataFolder: String, settingsFile: String, type: AccountType, accountID: String) {
|
init?(dataFolder: String, settingsFile: String, type: AccountType, accountID: String) {
|
||||||
|
|
||||||
self.accountID = accountID
|
|
||||||
self.type = type
|
|
||||||
self.settingsFile = settingsFile
|
|
||||||
self.dataFolder = dataFolder
|
|
||||||
self.hashValue = accountID.hashValue
|
|
||||||
|
|
||||||
switch type {
|
switch type {
|
||||||
|
|
||||||
case .onMyMac:
|
case .onMyMac:
|
||||||
self.delegate = LocalAccountDelegate()
|
self.delegate = LocalAccountDelegate()
|
||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.accountID = accountID
|
||||||
|
self.type = type
|
||||||
|
self.settingsFile = settingsFile
|
||||||
|
self.dataFolder = dataFolder
|
||||||
|
self.hashValue = accountID.hashValue
|
||||||
|
|
||||||
|
let databaseFilePath = (dataFolder as NSString).appendingPathComponent("DB.sqlite3")
|
||||||
|
self.database = Database(databaseFilePath: databaseFilePath, accountID: accountID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - API
|
// MARK: - API
|
||||||
|
@ -67,12 +72,16 @@ public final class Account: DisplayNameProvider, Hashable {
|
||||||
|
|
||||||
public func markArticles(_ articles: Set<Article>, statusKey: String, flag: Bool) {
|
public func markArticles(_ articles: Set<Article>, statusKey: String, flag: Bool) {
|
||||||
|
|
||||||
// TODO
|
let statuses = database.statuses(for: articles)
|
||||||
|
if statuses.isEmpty {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
database.mark(statuses, statusKey: statusKey, flag: flag)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func articleStatus(for article: Article) -> ArticleStatus? {
|
public func articleStatus(for article: Article) -> ArticleStatus? {
|
||||||
|
|
||||||
// TODO
|
return database.status(for: article)
|
||||||
}
|
}
|
||||||
|
|
||||||
public func ensureFolder(with name: String) -> Folder? {
|
public func ensureFolder(with name: String) -> Folder? {
|
||||||
|
|
|
@ -131,6 +131,16 @@ final class ArticlesTable: DatabaseTable {
|
||||||
|
|
||||||
// MARK: Status
|
// MARK: Status
|
||||||
|
|
||||||
|
func status(for article: Article) -> ArticleStatus? {
|
||||||
|
|
||||||
|
return statusesTable.cachedStatus(for: article.articleID)
|
||||||
|
}
|
||||||
|
|
||||||
|
func statuses(for articles: Set<Article>) -> Set<ArticleStatus> {
|
||||||
|
|
||||||
|
return statusesTable.cachedStatuses(for: articles.articleIDs())
|
||||||
|
}
|
||||||
|
|
||||||
func mark(_ statuses: Set<ArticleStatus>, _ statusKey: String, _ flag: Bool) {
|
func mark(_ statuses: Set<ArticleStatus>, _ statusKey: String, _ flag: Bool) {
|
||||||
|
|
||||||
statusesTable.mark(statuses, statusKey, flag)
|
statusesTable.mark(statuses, statusKey, flag)
|
||||||
|
|
|
@ -24,11 +24,11 @@ public final class Database {
|
||||||
private let accountID: String
|
private let accountID: String
|
||||||
private let articlesTable: ArticlesTable
|
private let articlesTable: ArticlesTable
|
||||||
|
|
||||||
public init(databaseFile: String, accountID: String) {
|
public init(databaseFilePath: String, accountID: String) {
|
||||||
|
|
||||||
self.accountID = accountID
|
self.accountID = accountID
|
||||||
|
|
||||||
let queue = RSDatabaseQueue(filepath: databaseFile, excludeFromBackup: false)
|
let queue = RSDatabaseQueue(filepath: databaseFilePath, excludeFromBackup: false)
|
||||||
self.articlesTable = ArticlesTable(name: DatabaseTableName.articles, accountID: accountID, queue: queue)
|
self.articlesTable = ArticlesTable(name: DatabaseTableName.articles, accountID: accountID, queue: queue)
|
||||||
|
|
||||||
let createStatementsPath = Bundle(for: type(of: self)).path(forResource: "CreateStatements", ofType: "sql")!
|
let createStatementsPath = Bundle(for: type(of: self)).path(forResource: "CreateStatements", ofType: "sql")!
|
||||||
|
@ -70,6 +70,16 @@ public final class Database {
|
||||||
|
|
||||||
// MARK: - Status
|
// MARK: - Status
|
||||||
|
|
||||||
|
public func status(for article: Article) -> ArticleStatus? {
|
||||||
|
|
||||||
|
return articlesTable.status(for: article)
|
||||||
|
}
|
||||||
|
|
||||||
|
public func statuses(for articles: Set<Article>) -> Set<ArticleStatus> {
|
||||||
|
|
||||||
|
return articlesTable.statuses(for: articles)
|
||||||
|
}
|
||||||
|
|
||||||
public func mark(_ statuses: Set<ArticleStatus>, statusKey: String, flag: Bool) {
|
public func mark(_ statuses: Set<ArticleStatus>, statusKey: String, flag: Bool) {
|
||||||
|
|
||||||
articlesTable.mark(statuses, statusKey, flag)
|
articlesTable.mark(statuses, statusKey, flag)
|
||||||
|
|
|
@ -37,6 +37,20 @@ final class StatusesTable: DatabaseTable {
|
||||||
return cache[articleID]
|
return cache[articleID]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func cachedStatuses(for articleIDs: Set<String>) -> Set<ArticleStatus> {
|
||||||
|
|
||||||
|
assert(Thread.isMainThread)
|
||||||
|
|
||||||
|
var statuses = Set<ArticleStatus>()
|
||||||
|
for articleID in articleIDs {
|
||||||
|
if let articleStatus = cache[articleID] {
|
||||||
|
statuses.insert(articleStatus)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return statuses
|
||||||
|
}
|
||||||
|
|
||||||
func addIfNotCached(_ statuses: Set<ArticleStatus>) {
|
func addIfNotCached(_ statuses: Set<ArticleStatus>) {
|
||||||
|
|
||||||
if statuses.isEmpty {
|
if statuses.isEmpty {
|
||||||
|
|
Loading…
Reference in New Issue