diff --git a/Evergreen/Data/ArticleUtilities.swift b/Evergreen/Data/ArticleUtilities.swift index 2d817f343..846484485 100644 --- a/Evergreen/Data/ArticleUtilities.swift +++ b/Evergreen/Data/ArticleUtilities.swift @@ -18,7 +18,7 @@ func markArticles(_ articles: Set
, statusKey: String, flag: Bool) { d.keys.forEach { (accountID) in - guard let accountArticles = d[accountID], let account = accountWithID(accountID) else { + guard let accountArticles = d[accountID], let account = AccountManager.shared.existingAccount(with: accountID) else { return } diff --git a/Evergreen/MainWindow/AddFeed/FolderTreeControllerDelegate.swift b/Evergreen/MainWindow/AddFeed/FolderTreeControllerDelegate.swift index 3beadca78..e5950ed95 100644 --- a/Evergreen/MainWindow/AddFeed/FolderTreeControllerDelegate.swift +++ b/Evergreen/MainWindow/AddFeed/FolderTreeControllerDelegate.swift @@ -29,12 +29,11 @@ private extension FolderTreeControllerDelegate { var folderNodes = [Node]() - let _ = AccountManager.shared.localAccount.visitChildren { (oneRepresentedObject) in + for oneRepresentedObject in AccountManager.shared.localAccount.children { if let folder = oneRepresentedObject as? Folder { folderNodes += [createNode(folder, parent: node)] } - return false } return Node.nodesSortedAlphabetically(folderNodes) diff --git a/Evergreen/MainWindow/Sidebar/SidebarTreeControllerDelegate.swift b/Evergreen/MainWindow/Sidebar/SidebarTreeControllerDelegate.swift index 4c02e6f65..de2fe3de5 100644 --- a/Evergreen/MainWindow/Sidebar/SidebarTreeControllerDelegate.swift +++ b/Evergreen/MainWindow/Sidebar/SidebarTreeControllerDelegate.swift @@ -34,22 +34,19 @@ private extension SidebarTreeControllerDelegate { // This will be expanded later to add synthetic feeds (All Unread, for instance). var updatedChildNodes = [Node]() - - let _ = AccountManager.shared.localAccount.visitChildren { (oneRepresentedObject) in - - if let existingNode = node.childNodeRepresentingObject(oneRepresentedObject as AnyObject) { + + for oneRepresentedObject in AccountManager.shared.localAccount.children { + + if let existingNode = node.childNodeRepresentingObject(oneRepresentedObject) { // Reuse nodes. if !updatedChildNodes.contains(existingNode) { updatedChildNodes += [existingNode] - return false } } if let newNode = createNode(representedObject: oneRepresentedObject as AnyObject, parent: node) { updatedChildNodes += [newNode] } - - return false } updatedChildNodes = Node.nodesSortedAlphabeticallyWithFoldersAtEnd(updatedChildNodes) @@ -60,28 +57,25 @@ private extension SidebarTreeControllerDelegate { var updatedChildNodes = [Node]() let folder = node.representedObject as! Folder - - let _ = folder.visitChildren { (oneRepresentedObject) -> Bool in - + + for oneRepresentedObject in folder.children { + if let existingNode = node.childNodeRepresentingObject(oneRepresentedObject) { if !updatedChildNodes.contains(existingNode) { updatedChildNodes += [existingNode] } - return false } if let newNode = self.createNode(representedObject: oneRepresentedObject, parent: node) { updatedChildNodes += [newNode] } - - return false } updatedChildNodes = Node.nodesSortedAlphabeticallyWithFoldersAtEnd(updatedChildNodes) return updatedChildNodes } - func createNode(representedObject: AnyObject, parent: Node) -> Node? { + func createNode(representedObject: Any, parent: Node) -> Node? { if let feed = representedObject as? Feed { return createNode(feed: feed, parent: parent) diff --git a/Frameworks/Account/Account.swift b/Frameworks/Account/Account.swift index b7a5ceb52..43c3b0625 100644 --- a/Frameworks/Account/Account.swift +++ b/Frameworks/Account/Account.swift @@ -31,22 +31,22 @@ public enum AccountType: Int { // TODO: more } -public final class Account: DisplayNameProvider, Hashable { +public final class Account: DisplayNameProvider, Container, Hashable { public let accountID: String public let type: AccountType public var nameForDisplay = "" public let hashValue: Int + public var children = [AnyObject]() let settingsFile: String let dataFolder: String let database: Database let delegate: AccountDelegate - var topLevelObjects = [AnyObject]() var feedIDDictionary = [String: Feed]() var username: String? var saveTimer: Timer? - var dirty = false { + public var dirty = false { didSet { if refreshInProgress { @@ -164,7 +164,7 @@ public final class Account: DisplayNameProvider, Hashable { } else { if !topLevelObjectsContainsFeed(uniquedFeed) { - topLevelObjects += [uniquedFeed] + children += [uniquedFeed] } didAddFeed = true } @@ -202,8 +202,12 @@ public final class Account: DisplayNameProvider, Hashable { } public func importOPML(_ opmlDocument: RSOPMLDocument) { - - // TODO + + guard let children = opmlDocument.children else { + return + } + importOPMLItems(children, parentFolder: nil, foldersAllowed: true) + dirty = true } // MARK: - Notifications @@ -262,13 +266,13 @@ private extension Account { guard let childrenArray = d[Key.children] as? [[String: Any]] else { return } - topLevelObjects = objects(with: childrenArray) + children = objects(with: childrenArray) updateFeedIDDictionary() } func diskDictionary() -> NSDictionary { - let diskObjects = topLevelObjects.flatMap { (object) -> [String: Any]? in + let diskObjects = children.flatMap { (object) -> [String: Any]? in if let folder = object as? Folder { return folder.dictionary @@ -341,7 +345,7 @@ private extension Account { func topLevelObjectsContainsFeed(_ feed: Feed) -> Bool { - return topLevelObjects.contains(where: { (object) -> Bool in + return children.contains(where: { (object) -> Bool in if let oneFeed = object as? Feed { if oneFeed.feedID == feed.feedID { return true @@ -350,6 +354,26 @@ private extension Account { return false }) } + + func importOPMLItems(_ items: [RSOPMLItem], parentFolder: Folder?, foldersAllowed: Bool) { + + for item in items { + + if let feedSpecifier = item.feedSpecifier { + if hasFeed(withURL: feedSpecifier.feedURL) { + continue + } + + } + + if item.isFolder { + + } + else { + + } + } + } } // MARK: - OPMLRepresentable @@ -359,7 +383,7 @@ extension Account: OPMLRepresentable { public func OPMLString(indentLevel: Int) -> String { var s = "" - for oneObject in topLevelObjects { + for oneObject in children { if let oneOPMLObject = oneObject as? OPMLRepresentable { s += oneOPMLObject.OPMLString(indentLevel: indentLevel + 1) } diff --git a/Frameworks/Account/Account.xcodeproj/project.pbxproj b/Frameworks/Account/Account.xcodeproj/project.pbxproj index 3199dbe02..dbe7276b8 100644 --- a/Frameworks/Account/Account.xcodeproj/project.pbxproj +++ b/Frameworks/Account/Account.xcodeproj/project.pbxproj @@ -11,8 +11,6 @@ 841973FE1F6DD1BC006346C4 /* RSCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 841973EF1F6DD19E006346C4 /* RSCore.framework */; }; 841973FF1F6DD1C5006346C4 /* RSParser.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 841973FA1F6DD1AC006346C4 /* RSParser.framework */; }; 841974011F6DD1EC006346C4 /* Folder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 841974001F6DD1EC006346C4 /* Folder.swift */; }; - 841974181F6DD535006346C4 /* Folder+Container.swift in Sources */ = {isa = PBXBuildFile; fileRef = 841974171F6DD535006346C4 /* Folder+Container.swift */; }; - 8419741A1F6DD583006346C4 /* Account+Container.swift in Sources */ = {isa = PBXBuildFile; fileRef = 841974191F6DD583006346C4 /* Account+Container.swift */; }; 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 */; }; @@ -20,11 +18,10 @@ 846E774F1F6EF9C000A165E2 /* LocalAccountDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8419742C1F6DDE84006346C4 /* LocalAccountDelegate.swift */; }; 846E77501F6EF9C400A165E2 /* LocalAccountRefresher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8419742D1F6DDE96006346C4 /* LocalAccountRefresher.swift */; }; 846E77541F6F00E300A165E2 /* AccountManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 846E77531F6F00E300A165E2 /* AccountManager.swift */; }; - 846E77571F6F03D600A165E2 /* Article+Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = 846E77561F6F03D600A165E2 /* Article+Account.swift */; }; - 846E77591F6F03E300A165E2 /* Feed+Account.swift in Sources */ = {isa = PBXBuildFile; fileRef = 846E77581F6F03E300A165E2 /* 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 */; }; 84C3654A1F899F3B001EC85C /* CombinedRefreshProgress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C365491F899F3B001EC85C /* CombinedRefreshProgress.swift */; }; + 84C8B3F41F89DE430053CCA6 /* DataExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84C8B3F31F89DE430053CCA6 /* DataExtensions.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -107,14 +104,10 @@ 841973F41F6DD1AC006346C4 /* RSParser.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RSParser.xcodeproj; path = ../RSParser/RSParser.xcodeproj; sourceTree = ""; }; 841974001F6DD1EC006346C4 /* Folder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Folder.swift; sourceTree = ""; }; 8419740D1F6DD25F006346C4 /* Container.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container.swift; sourceTree = ""; }; - 841974171F6DD535006346C4 /* Folder+Container.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Folder+Container.swift"; sourceTree = ""; }; - 841974191F6DD583006346C4 /* Account+Container.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Account+Container.swift"; sourceTree = ""; }; 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 = ""; }; 846E77531F6F00E300A165E2 /* AccountManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountManager.swift; sourceTree = ""; }; - 846E77561F6F03D600A165E2 /* Article+Account.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "Article+Account.swift"; path = "Extensions/Article+Account.swift"; sourceTree = ""; }; - 846E77581F6F03E300A165E2 /* Feed+Account.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "Feed+Account.swift"; path = "Extensions/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; }; @@ -122,6 +115,7 @@ 848935061F62485000CEBD24 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 848935101F62486800CEBD24 /* Account.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Account.swift; sourceTree = ""; }; 84C365491F899F3B001EC85C /* CombinedRefreshProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CombinedRefreshProgress.swift; sourceTree = ""; }; + 84C8B3F31F89DE430053CCA6 /* DataExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataExtensions.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -184,16 +178,6 @@ name = Products; sourceTree = ""; }; - 841974141F6DD4FF006346C4 /* Container */ = { - isa = PBXGroup; - children = ( - 8419740D1F6DD25F006346C4 /* Container.swift */, - 841974191F6DD583006346C4 /* Account+Container.swift */, - 841974171F6DD535006346C4 /* Folder+Container.swift */, - ); - path = Container; - sourceTree = ""; - }; 8419742B1F6DDE84006346C4 /* LocalAccount */ = { isa = PBXGroup; children = ( @@ -214,15 +198,6 @@ name = Frameworks; sourceTree = ""; }; - 846E77551F6F03B200A165E2 /* Extensions */ = { - isa = PBXGroup; - children = ( - 846E77581F6F03E300A165E2 /* Feed+Account.swift */, - 846E77561F6F03D600A165E2 /* Article+Account.swift */, - ); - name = Extensions; - sourceTree = ""; - }; 848934EC1F62484F00CEBD24 = { isa = PBXGroup; children = ( @@ -231,8 +206,8 @@ 841974241F6DDCE4006346C4 /* AccountDelegate.swift */, 841974001F6DD1EC006346C4 /* Folder.swift */, 84C365491F899F3B001EC85C /* CombinedRefreshProgress.swift */, - 846E77551F6F03B200A165E2 /* Extensions */, - 841974141F6DD4FF006346C4 /* Container */, + 84C8B3F31F89DE430053CCA6 /* DataExtensions.swift */, + 8419740D1F6DD25F006346C4 /* Container.swift */, 8419742B1F6DDE84006346C4 /* LocalAccount */, 8469F80F1F6DC3C10084783E /* Frameworks */, 848934FA1F62484F00CEBD24 /* Info.plist */, @@ -453,18 +428,15 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 846E77571F6F03D600A165E2 /* Article+Account.swift in Sources */, + 84C8B3F41F89DE430053CCA6 /* DataExtensions.swift in Sources */, 84C3654A1F899F3B001EC85C /* CombinedRefreshProgress.swift in Sources */, 8469F81C1F6DD15E0084783E /* Account.swift in Sources */, 846E77451F6EF9B900A165E2 /* Container.swift in Sources */, - 8419741A1F6DD583006346C4 /* Account+Container.swift in Sources */, 841974251F6DDCE4006346C4 /* AccountDelegate.swift in Sources */, 846E77541F6F00E300A165E2 /* AccountManager.swift in Sources */, 846E77501F6EF9C400A165E2 /* LocalAccountRefresher.swift in Sources */, 841974011F6DD1EC006346C4 /* Folder.swift in Sources */, - 846E77591F6F03E300A165E2 /* Feed+Account.swift in Sources */, 846E774F1F6EF9C000A165E2 /* LocalAccountDelegate.swift in Sources */, - 841974181F6DD535006346C4 /* Folder+Container.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Frameworks/Account/AccountManager.swift b/Frameworks/Account/AccountManager.swift index b971334a5..6a1cfb02d 100644 --- a/Frameworks/Account/AccountManager.swift +++ b/Frameworks/Account/AccountManager.swift @@ -198,12 +198,6 @@ private func accountFilePathWithFolder(_ folderPath: String) -> String { return NSString(string: folderPath).appendingPathComponent(accountDataFileName) } -public func accountWithID(_ accountID: String) -> Account? { - - // Shortcut. - return AccountManager.shared.existingAccount(with: accountID) -} - private struct AccountSpecifier { let type: String diff --git a/Frameworks/Account/Container.swift b/Frameworks/Account/Container.swift new file mode 100644 index 000000000..e60b91db2 --- /dev/null +++ b/Frameworks/Account/Container.swift @@ -0,0 +1,113 @@ +// +// Container.swift +// Evergreen +// +// Created by Brent Simmons on 4/17/16. +// Copyright © 2016 Ranchero Software, LLC. All rights reserved. +// + +import Foundation +import RSCore +import Data + +extension NSNotification.Name { + + public static let ChildrenDidChange = Notification.Name("ChildrenDidChange") +} + +public protocol Container { + + var children: [AnyObject] { get } + + //Recursive + func flattenedFeeds() -> Set + func hasFeed(with feedID: String) -> Bool + func hasFeed(withURL url: String) -> Bool + func existingFeed(with feedID: String) -> Feed? + func existingFeed(withURL url: String) -> Feed? + func existingFolder(with name: String) -> Folder? + + func postChildrenDidChangeNotification() +} + +public extension Container { + + func flattenedFeeds() -> Set { + + var feeds = Set() + + for object in children { + if let feed = object as? Feed { + feeds.insert(feed) + } + else if let container = object as? Container { + feeds.formUnion(container.flattenedFeeds()) + } + } + + return feeds + } + + func hasFeed(with feedID: String) -> Bool { + + return existingFeed(with: feedID) != nil + } + + func hasFeed(withURL url: String) -> Bool { + + return existingFeed(withURL: url) != nil + } + + func existingFeed(with feedID: String) -> Feed? { + + for child in children { + + if let feed = child as? Feed, feed.feedID == feedID { + return feed + } + if let container = child as? Container, let feed = container.existingFeed(with: feedID) { + return feed + } + } + + return nil + } + + func existingFeed(withURL url: String) -> Feed? { + + for child in children { + + if let feed = child as? Feed, feed.url == url { + return feed + } + if let container = child as? Container, let feed = container.existingFeed(withURL: url) { + return feed + } + } + + return nil + } + + func existingFolder(with name: String) -> Folder? { + + for child in children { + + if let folder = child as? Folder { + if folder.name == name { + return folder + } + if let subFolder = folder.existingFolder(with: name) { + return subFolder + } + } + } + + return nil + } + + func postChildrenDidChangeNotification() { + + NotificationCenter.default.post(name: .ChildrenDidChange, object: self) + } +} + diff --git a/Frameworks/Account/Container/Account+Container.swift b/Frameworks/Account/Container/Account+Container.swift deleted file mode 100644 index 4fef6bdb2..000000000 --- a/Frameworks/Account/Container/Account+Container.swift +++ /dev/null @@ -1,68 +0,0 @@ -// -// Account+Container.swift -// Account -// -// Created by Brent Simmons on 9/16/17. -// Copyright © 2017 Ranchero Software, LLC. All rights reserved. -// - -import Foundation -import Data - -extension Account: Container { - - public func flattenedFeeds() -> Set { - - var feeds = Set() - - for object in topLevelObjects { - if let feed = object as? Feed { - feeds.insert(feed) - } - else if let folder = object as? Folder { - feeds.formUnion(folder.flattenedFeeds()) - } - } - - return feeds - } - - public func existingFeed(with feedID: String) -> Feed? { - - return feedIDDictionary[feedID] - } - - public func canAddItem(_ item: AnyObject) -> Bool { - - return false // TODO - } - - public func isChild(_ obj: AnyObject) -> Bool { - - return topLevelObjects.contains(where: { (oneObject) -> Bool in - return oneObject === obj - }) - } - - public func visitObjects(_ recurse: Bool, _ visitBlock: VisitBlock) -> Bool { - - for oneObject in topLevelObjects { - - if let oneContainer = oneObject as? Container { - if visitBlock(oneObject) { - return true - } - if recurse && oneContainer.visitObjects(recurse, visitBlock) { - return true - } - } - else { - if visitBlock(oneObject) { - return true - } - } - } - - return false - } -} diff --git a/Frameworks/Account/Container/Container.swift b/Frameworks/Account/Container/Container.swift deleted file mode 100644 index e4aeaeb16..000000000 --- a/Frameworks/Account/Container/Container.swift +++ /dev/null @@ -1,132 +0,0 @@ -// -// Container.swift -// Evergreen -// -// Created by Brent Simmons on 4/17/16. -// Copyright © 2016 Ranchero Software, LLC. All rights reserved. -// - -import Foundation -import RSCore -import Data - -public typealias VisitBlock = (_ obj: AnyObject) -> Bool // Return true to stop - -extension NSNotification.Name { - - public static let ChildrenDidChange = Notification.Name("ChildrenDidChangeNotification") -} - -public protocol Container { - - //Recursive - func flattenedFeeds() -> Set - func existingFeed(with feedID: String) -> Feed? - func existingFeed(withURL url: String) -> Feed? - func hasFeed(with feedID: String) -> Bool - func hasFeed(withURL url: String) -> Bool - - func isChild(_ obj: AnyObject) -> Bool - - // visitBlock should return true to stop visiting. - // visitObjects returns true if a visitBlock returned true. - func visitObjects(_ recurse: Bool, _ visitBlock: VisitBlock) -> Bool -} - -public extension Container { - - func existingFeed(with feedID: String) -> Feed? { - - let foundObject = findObject(true) { (oneDescendant) -> Bool in - if let oneFeed = oneDescendant as? Feed, oneFeed.feedID == feedID { - return true - } - return false - } - return foundObject as! Feed? - } - - func existingFeed(withURL url: String) -> Feed? { - - let foundObject = findObject(true) { (oneDescendant) -> Bool in - if let oneFeed = oneDescendant as? Feed, oneFeed.url == url { - return true - } - return false - } - return foundObject as! Feed? - } - - func hasFeed(with feedID: String) -> Bool { - - if let _ = existingFeed(with: feedID) { - return true - } - return false - } - - func hasFeed(withURL url: String) -> Bool { - - if let _ = existingFeed(withURL: url) { - return true - } - return false - } - - func visitChildren(visitBlock: VisitBlock) -> Bool { - - return visitObjects(false, visitBlock) - } - - func findObject(_ recurse: Bool, visitBlock: @escaping VisitBlock) -> AnyObject? { - - var foundObject: AnyObject? - - let _ = visitObjects(recurse) { (oneObject) in - - if let _ = foundObject { - return true - } - - if visitBlock(oneObject) { - foundObject = oneObject - return true - } - - return false - } - - return foundObject - } - - func objectIsChild(_ obj: AnyObject) -> Bool { - - return visitObjects(false) { (oneObject) in - return obj === oneObject - } - } - - func objectIsDescendant(_ obj: AnyObject) -> Bool { - - return visitObjects(true) { (oneObject) in - return obj === oneObject - } - } - - func existingFolderWithName(_ name: String) -> Folder? { - - let foundObject = findObject(false) { (oneObject) in - if let oneFolder = oneObject as? Folder, oneFolder.nameForDisplay == name { - return true - } - return false - } - return foundObject as! Folder? - } - - public func postChildrenDidChangeNotification() { - - NotificationCenter.default.post(name: .ChildrenDidChange, object: self) - } -} - diff --git a/Frameworks/Account/Container/Folder+Container.swift b/Frameworks/Account/Container/Folder+Container.swift deleted file mode 100644 index 89f219ab4..000000000 --- a/Frameworks/Account/Container/Folder+Container.swift +++ /dev/null @@ -1,54 +0,0 @@ -// -// Folder+Container.swift -// Account -// -// Created by Brent Simmons on 9/16/17. -// Copyright © 2017 Ranchero Software, LLC. All rights reserved. -// - -import Foundation -import Data - -extension Folder: Container { - - public func flattenedFeeds() -> Set { - - var feeds = Set() - for oneChild in children { - if let oneFeed = oneChild as? Feed { - feeds.insert(oneFeed) - } - else if let oneContainer = oneChild as? Container { - feeds.formUnion(oneContainer.flattenedFeeds()) - } - } - return feeds - } - - public func isChild(_ obj: AnyObject) -> Bool { - - return children.contains { $0 === obj } - } - - public func visitObjects(_ recurse: Bool, _ visitBlock: VisitBlock) -> Bool { - - for oneObject in children { - - if let oneContainer = oneObject as? Container { - if visitBlock(oneObject) { - return true - } - if recurse && oneContainer.visitObjects(recurse, visitBlock) { - return true - } - } - else { - if visitBlock(oneObject) { - return true - } - } - } - return false - } -} - diff --git a/Frameworks/Account/DataExtensions.swift b/Frameworks/Account/DataExtensions.swift new file mode 100644 index 000000000..3a313faad --- /dev/null +++ b/Frameworks/Account/DataExtensions.swift @@ -0,0 +1,28 @@ +// +// DataExtensions.swift +// Account +// +// Created by Brent Simmons on 10/7/17. +// Copyright © 2017 Ranchero Software, LLC. All rights reserved. +// + +import Foundation +import Data + +public extension Feed { + + var account: Account? { + get { + return AccountManager.shared.existingAccount(with: accountID) + } + } +} + +public extension Article { + + var account: Account? { + get { + return AccountManager.shared.existingAccount(with: accountID) + } + } +} diff --git a/Frameworks/Account/Extensions/Article+Account.swift b/Frameworks/Account/Extensions/Article+Account.swift deleted file mode 100644 index 796ad7dc4..000000000 --- a/Frameworks/Account/Extensions/Article+Account.swift +++ /dev/null @@ -1,20 +0,0 @@ -// -// Article+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 Article { - - var account: Account? { - get { - return accountWithID(accountID) - } - } -} - diff --git a/Frameworks/Account/Extensions/Feed+Account.swift b/Frameworks/Account/Extensions/Feed+Account.swift deleted file mode 100644 index 5de9e8c8b..000000000 --- a/Frameworks/Account/Extensions/Feed+Account.swift +++ /dev/null @@ -1,24 +0,0 @@ -// -// Feed+Account.swift -// Account -// -// Created by Brent Simmons on 9/17/17. -// Copyright © 2017 Ranchero Software, LLC. All rights reserved. -// - -import Foundation -import Data - -struct FeedDictionaryKey { - - -} - -public extension Feed { - - var account: Account? { - get { - return accountWithID(accountID) - } - } -} diff --git a/Frameworks/Account/Folder.swift b/Frameworks/Account/Folder.swift index 8de1bb461..2c7a8df01 100644 --- a/Frameworks/Account/Folder.swift +++ b/Frameworks/Account/Folder.swift @@ -9,10 +9,10 @@ import Foundation import Data -public final class Folder: DisplayNameProvider, UnreadCountProvider { +public final class Folder: DisplayNameProvider, Container, UnreadCountProvider { public let account: Account - var children = [AnyObject]() + public var children = [AnyObject]() var name: String? static let untitledName = NSLocalizedString("Untitled ƒ", comment: "Folder name") @@ -180,13 +180,11 @@ extension Folder: OPMLRepresentable { var hasAtLeastOneChild = false - let _ = visitChildren { (oneChild) -> Bool in - - if let oneOPMLObject = oneChild as? OPMLRepresentable { - s += oneOPMLObject.OPMLString(indentLevel: indentLevel + 1) + for child in children { + if let opmlObject = child as? OPMLRepresentable { + s += opmlObject.OPMLString(indentLevel: indentLevel + 1) hasAtLeastOneChild = true } - return false } if !hasAtLeastOneChild { diff --git a/Frameworks/RSParser/OPML/RSOPMLItem.h b/Frameworks/RSParser/OPML/RSOPMLItem.h index 3a66d7e99..666b31bdf 100755 --- a/Frameworks/RSParser/OPML/RSOPMLItem.h +++ b/Frameworks/RSParser/OPML/RSOPMLItem.h @@ -18,7 +18,7 @@ - (void)addChild:(RSOPMLItem *)child; -@property (nonatomic, readonly) RSOPMLFeedSpecifier *OPMLFeedSpecifier; //May be nil. +@property (nonatomic, readonly) RSOPMLFeedSpecifier *feedSpecifier; //May be nil. @property (nonatomic, readonly) NSString *titleFromAttributes; //May be nil. @property (nonatomic, readonly) BOOL isFolder; diff --git a/Frameworks/RSParser/OPML/RSOPMLItem.m b/Frameworks/RSParser/OPML/RSOPMLItem.m index 9eeda020a..3a9b8d64a 100755 --- a/Frameworks/RSParser/OPML/RSOPMLItem.m +++ b/Frameworks/RSParser/OPML/RSOPMLItem.m @@ -22,7 +22,7 @@ @implementation RSOPMLItem @synthesize children = _children; -@synthesize OPMLFeedSpecifier = _OPMLFeedSpecifier; +@synthesize feedSpecifier = _feedSpecifier; - (NSArray *)children { @@ -48,10 +48,10 @@ } -- (RSOPMLFeedSpecifier *)OPMLFeedSpecifier { +- (RSOPMLFeedSpecifier *)feedSpecifier { - if (_OPMLFeedSpecifier) { - return _OPMLFeedSpecifier; + if (_feedSpecifier) { + return _feedSpecifier; } NSString *feedURL = self.attributes.opml_xmlUrl; @@ -59,9 +59,9 @@ return nil; } - _OPMLFeedSpecifier = [[RSOPMLFeedSpecifier alloc] initWithTitle:self.attributes.opml_title feedDescription:self.attributes.opml_description homePageURL:self.attributes.opml_htmlUrl feedURL:feedURL]; + _feedSpecifier = [[RSOPMLFeedSpecifier alloc] initWithTitle:self.attributes.opml_title feedDescription:self.attributes.opml_description homePageURL:self.attributes.opml_htmlUrl feedURL:feedURL]; - return _OPMLFeedSpecifier; + return _feedSpecifier; } - (NSString *)titleFromAttributes {