diff --git a/Frameworks/Account/Account.swift b/Frameworks/Account/Account.swift index 5abc9a32c..9b0ef112a 100644 --- a/Frameworks/Account/Account.swift +++ b/Frameworks/Account/Account.swift @@ -9,6 +9,7 @@ import Foundation import RSCore import Data +import RSParser public enum AccountType: Int { @@ -23,9 +24,9 @@ public enum AccountType: Int { public final class Account: DisplayNameProvider, Hashable { - public let identifier: String + public let accountID: String public let type: AccountType - public var nameForDisplay: String? + public var nameForDisplay = "" public let delegate: AccountDelegate public let hashValue: Int let settingsFile: String @@ -33,18 +34,20 @@ public final class Account: DisplayNameProvider, Hashable { var topLevelObjects = [AnyObject]() var feedIDDictionary = [String: Feed]() var username: String? - - init?(dataFolder: String, settingsFile: String, type: AccountType, identifier: String) { - self.identifier = identifier + static public let accounts = [String: Account]() + + init?(dataFolder: String, settingsFile: String, type: AccountType, accountID: String) { + + self.accountID = accountID self.type = type self.settingsFile = settingsFile self.dataFolder = dataFolder - self.hashValue = identifier.hashValue + self.hashValue = accountID.hashValue switch type { - case onMyMac: + case .onMyMac: self.delegate = LocalAccountDelegate() default: return nil @@ -53,11 +56,21 @@ public final class Account: DisplayNameProvider, Hashable { // MARK: - API + static public func existingAccountWithID(_ accountID: String) -> Account? { + + return accounts[accountID] + } + public func refreshAll() { delegate.refreshAll(for: self) } + func update(_ feed: Feed, with parsedFeed: ParsedFeed, _ completion: RSVoidCompletionBlock) { + + // TODO + } + // MARK: - Equatable public class func ==(lhs: Account, rhs: Account) -> Bool { diff --git a/Frameworks/Account/Account.xcodeproj/project.pbxproj b/Frameworks/Account/Account.xcodeproj/project.pbxproj index 10a2b3b99..44732fc68 100644 --- a/Frameworks/Account/Account.xcodeproj/project.pbxproj +++ b/Frameworks/Account/Account.xcodeproj/project.pbxproj @@ -16,6 +16,10 @@ 841974251F6DDCE4006346C4 /* AccountDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 841974241F6DDCE4006346C4 /* AccountDelegate.swift */; }; 8469F8171F6DD0AD0084783E /* Database.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8401A17D1F6DC388002B1BE2 /* Database.framework */; }; 8469F81C1F6DD15E0084783E /* Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = 848935101F62486800CEBD24 /* Account.swift */; }; + 846E77451F6EF9B900A165E2 /* Container.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8419740D1F6DD25F006346C4 /* Container.swift */; }; + 846E774F1F6EF9C000A165E2 /* LocalAccountDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8419742C1F6DDE84006346C4 /* LocalAccountDelegate.swift */; }; + 846E77501F6EF9C400A165E2 /* LocalAccountRefresher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8419742D1F6DDE96006346C4 /* LocalAccountRefresher.swift */; }; + 846E77521F6EFDFB00A165E2 /* Feed+Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = 846E77511F6EFDFB00A165E2 /* Feed+Account.swift */; }; 848935001F62484F00CEBD24 /* Account.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 848934F61F62484F00CEBD24 /* Account.framework */; }; 848935051F62485000CEBD24 /* AccountTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 848935041F62485000CEBD24 /* AccountTests.swift */; }; /* End PBXBuildFile section */ @@ -105,6 +109,7 @@ 841974241F6DDCE4006346C4 /* AccountDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountDelegate.swift; sourceTree = ""; }; 8419742C1F6DDE84006346C4 /* LocalAccountDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalAccountDelegate.swift; sourceTree = ""; }; 8419742D1F6DDE96006346C4 /* LocalAccountRefresher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalAccountRefresher.swift; sourceTree = ""; }; + 846E77511F6EFDFB00A165E2 /* Feed+Account.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Feed+Account.swift"; sourceTree = ""; }; 848934F61F62484F00CEBD24 /* Account.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Account.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 848934FA1F62484F00CEBD24 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 848934FF1F62484F00CEBD24 /* AccountTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AccountTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -209,6 +214,7 @@ 848935101F62486800CEBD24 /* Account.swift */, 841974241F6DDCE4006346C4 /* AccountDelegate.swift */, 841974001F6DD1EC006346C4 /* Folder.swift */, + 846E77511F6EFDFB00A165E2 /* Feed+Account.swift */, 841974141F6DD4FF006346C4 /* Container */, 8419742B1F6DDE84006346C4 /* Local */, 8469F80F1F6DC3C10084783E /* Frameworks */, @@ -430,10 +436,14 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 846E77521F6EFDFB00A165E2 /* Feed+Account.swift in Sources */, 8469F81C1F6DD15E0084783E /* Account.swift in Sources */, + 846E77451F6EF9B900A165E2 /* Container.swift in Sources */, 8419741A1F6DD583006346C4 /* Account+Container.swift in Sources */, 841974251F6DDCE4006346C4 /* AccountDelegate.swift in Sources */, + 846E77501F6EF9C400A165E2 /* LocalAccountRefresher.swift in Sources */, 841974011F6DD1EC006346C4 /* Folder.swift in Sources */, + 846E774F1F6EF9C000A165E2 /* LocalAccountDelegate.swift in Sources */, 841974181F6DD535006346C4 /* Folder+Container.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/Frameworks/Account/AccountDelegate.swift b/Frameworks/Account/AccountDelegate.swift index 0ad488e1c..518390c6e 100644 --- a/Frameworks/Account/AccountDelegate.swift +++ b/Frameworks/Account/AccountDelegate.swift @@ -10,9 +10,6 @@ import Foundation public protocol AccountDelegate { - func refreshAll(for account: Account) { - - - } + func refreshAll(for account: Account) } diff --git a/Frameworks/Account/Container/Account+Container.swift b/Frameworks/Account/Container/Account+Container.swift index d9c9ce2f0..ec3731ba1 100644 --- a/Frameworks/Account/Container/Account+Container.swift +++ b/Frameworks/Account/Container/Account+Container.swift @@ -7,6 +7,7 @@ // import Foundation +import Data extension Account: Container { @@ -27,7 +28,7 @@ extension Account: Container { public func canAddItem(_ item: AnyObject) -> Bool { - return delegate.canAddItem(item, toContainer: self) + return false // TODO } public func isChild(_ obj: AnyObject) -> Bool { diff --git a/Frameworks/Account/Container/Container.swift b/Frameworks/Account/Container/Container.swift index 979187553..96ed99c0d 100644 --- a/Frameworks/Account/Container/Container.swift +++ b/Frameworks/Account/Container/Container.swift @@ -8,6 +8,7 @@ import Foundation import RSCore +import Data public typealias VisitBlock = (_ obj: AnyObject) -> Bool // Return true to stop @@ -16,7 +17,7 @@ extension NSNotification.Name { public static let ChildrenDidChange = Notification.Name("ChildrenDidChangeNotification") } -public protocol Container: class { +public protocol Container { //Recursive func hasAtLeastOneFeed() -> Bool @@ -29,34 +30,6 @@ public protocol Container: class { // visitBlock should return true to stop visiting. // visitObjects returns true if a visitBlock returned true. func visitObjects(_ recurse: Bool, _ visitBlock: VisitBlock) -> Bool - -// -//// func objectIsChild(_ obj: AnyObject) -> Bool -//// func objectIsDescendant(_ obj: AnyObject) -> Bool -//// -//// func fetchArticles() -> [Article] -// -// // visitBlock should return true to stop visiting. -// // visitObjects returns true if a visitBlock returned true. -//// func visitObjects(_ recurse: Bool, visitBlock: VisitBlock) -> Bool -//// func visitChildren(visitBlock: VisitBlock) -> Bool // Above with recurse = false -//// -//// func findObject(_ recurse: Bool, visitBlock: VisitBlock) -> AnyObject? -// -// func canAddItem(_ item: AnyObject) -> Bool -// func addItem(_ item: AnyObject) -> Bool // Return true even if item already exists. -// func addItems(_ items: [AnyObject]) -> Bool // Return true even if some items already exist. -// -// func canAddFolderWithName(_ folderName: String) -> Bool // Special case: folder with name exists. Return true in that case. -// func ensureFolderWithName(_ folderName: String) -> Folder? // Return folder even if item already exists. -// -// // Does not recurse. -// func existingFolderWithName(_ name: String) -> Folder? -// -// // Doesn't add feed. Just creates instance. -// func createFeedWithName(_ name: String?, editedName: String?, urlString: String) -> Feed? -// -// func deleteItems(_ items: [AnyObject]) } public extension Container { diff --git a/Frameworks/Account/Container/Folder+Container.swift b/Frameworks/Account/Container/Folder+Container.swift index 93fa7981d..3532bdaa9 100644 --- a/Frameworks/Account/Container/Folder+Container.swift +++ b/Frameworks/Account/Container/Folder+Container.swift @@ -7,6 +7,7 @@ // import Foundation +import Data extension Folder: Container { diff --git a/Frameworks/Account/Feed+Account.swift b/Frameworks/Account/Feed+Account.swift new file mode 100644 index 000000000..8c5b17601 --- /dev/null +++ b/Frameworks/Account/Feed+Account.swift @@ -0,0 +1,19 @@ +// +// Feed+Account.swift +// Account +// +// Created by Brent Simmons on 9/17/17. +// Copyright © 2017 Ranchero Software, LLC. All rights reserved. +// + +import Foundation +import Data + +public extension Feed { + + var account: Account? { + get { + return Account.existingAccountWithID(accountID) + } + } +} diff --git a/Frameworks/Account/Folder.swift b/Frameworks/Account/Folder.swift index f2baf62d0..07594d2a1 100644 --- a/Frameworks/Account/Folder.swift +++ b/Frameworks/Account/Folder.swift @@ -34,36 +34,7 @@ public final class Folder: DisplayNameProvider, UnreadCountProvider { self.accountID = accountID self.nameForDisplay = nameForDisplay - -// NotificationCenter.default.addObserver(self, selector: #selector(unreadCountDidChange(_:)), name: .UnreadCountDidChange, object: nil) } - - - // MARK: Notifications - -// @objc dynamic public func unreadCountDidChange(_ note: Notification) { -// -// guard let obj = note.object else { -// return -// } -// let potentialChild = obj as AnyObject -// if isChild(potentialChild) { -// updateUnreadCount() -// } -// } - -// public var unreadCount = 0 { -// didSet { -// if unreadCount != oldValue { -// postUnreadCountDidChangeNotification() -// } -// } -// } - -// public func updateUnreadCount() { -// -// unreadCount = calculateUnreadCount(childObjects) -// } } extension Folder: OPMLRepresentable { diff --git a/Frameworks/Account/Local/LocalAccountRefresher.swift b/Frameworks/Account/Local/LocalAccountRefresher.swift index 09b1f5625..90eae2708 100644 --- a/Frameworks/Account/Local/LocalAccountRefresher.swift +++ b/Frameworks/Account/Local/LocalAccountRefresher.swift @@ -10,6 +10,7 @@ import Foundation import RSCore import RSParser import RSWeb +import Data final class LocalAccountRefresher: DownloadSessionDelegate { @@ -32,7 +33,7 @@ final class LocalAccountRefresher: DownloadSessionDelegate { public func downloadSession(_ downloadSession: DownloadSession, requestForRepresentedObject representedObject: AnyObject) -> URLRequest? { - guard let feed = representedObject as? LocalFeed else { + guard let feed = representedObject as? Feed else { return nil } @@ -50,7 +51,7 @@ final class LocalAccountRefresher: DownloadSessionDelegate { public func downloadSession(_ downloadSession: DownloadSession, downloadDidCompleteForRepresentedObject representedObject: AnyObject, response: URLResponse?, data: Data, error: NSError?) { - guard let feed = representedObject as? LocalFeed, !data.isEmpty else { + guard let feed = representedObject as? Feed, !data.isEmpty else { return } @@ -68,10 +69,10 @@ final class LocalAccountRefresher: DownloadSessionDelegate { let parserData = ParserData(url: feed.url, data: data) FeedParser.parse(parserData) { (parsedFeed, error) in - guard let account = self.account, let parsedFeed = parsedFeed, error == nil else { + guard let account = feed.account, let parsedFeed = parsedFeed, error == nil else { return } - account.update(feed, parsedFeed: parsedFeed) { + account.update(feed, with: parsedFeed) { if let httpResponse = response as? HTTPURLResponse { let conditionalGetInfo = HTTPConditionalGetInfo(urlResponse: httpResponse) @@ -87,7 +88,7 @@ final class LocalAccountRefresher: DownloadSessionDelegate { public func downloadSession(_ downloadSession: DownloadSession, shouldContinueAfterReceivingData data: Data, representedObject: AnyObject) -> Bool { - guard let feed = representedObject as? LocalFeed else { + guard let feed = representedObject as? Feed else { return false } diff --git a/Frameworks/Data/Feed.swift b/Frameworks/Data/Feed.swift index 93c212e8b..e428fc93c 100644 --- a/Frameworks/Data/Feed.swift +++ b/Frameworks/Data/Feed.swift @@ -8,6 +8,7 @@ import Foundation import RSCore +import RSWeb public final class Feed: DisplayNameProvider, UnreadCountProvider, Hashable { @@ -18,6 +19,8 @@ public final class Feed: DisplayNameProvider, UnreadCountProvider, Hashable { public var name: String? public var editedName: String? public var accountInfo: AccountInfo? //If account needs to store more data + public var conditionalGetInfo: HTTPConditionalGetInfo? + public var contentHash: String? public let hashValue: Int // MARK: - DisplayNameProvider