Simplify Container and its function implementations.

This commit is contained in:
Brent Simmons 2017-10-07 21:41:21 -07:00
parent dccb215c76
commit ca611623aa
16 changed files with 202 additions and 378 deletions

View File

@ -18,7 +18,7 @@ func markArticles(_ articles: Set<Article>, 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
}

View File

@ -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)

View File

@ -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)

View File

@ -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)
}

View File

@ -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 = "<group>"; };
841974001F6DD1EC006346C4 /* Folder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Folder.swift; sourceTree = "<group>"; };
8419740D1F6DD25F006346C4 /* Container.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Container.swift; sourceTree = "<group>"; };
841974171F6DD535006346C4 /* Folder+Container.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Folder+Container.swift"; sourceTree = "<group>"; };
841974191F6DD583006346C4 /* Account+Container.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Account+Container.swift"; sourceTree = "<group>"; };
841974241F6DDCE4006346C4 /* AccountDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountDelegate.swift; sourceTree = "<group>"; };
8419742C1F6DDE84006346C4 /* LocalAccountDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalAccountDelegate.swift; sourceTree = "<group>"; };
8419742D1F6DDE96006346C4 /* LocalAccountRefresher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalAccountRefresher.swift; sourceTree = "<group>"; };
846E77531F6F00E300A165E2 /* AccountManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountManager.swift; sourceTree = "<group>"; };
846E77561F6F03D600A165E2 /* Article+Account.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "Article+Account.swift"; path = "Extensions/Article+Account.swift"; sourceTree = "<group>"; };
846E77581F6F03E300A165E2 /* Feed+Account.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "Feed+Account.swift"; path = "Extensions/Feed+Account.swift"; sourceTree = "<group>"; };
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 = "<group>"; };
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 = "<group>"; };
848935101F62486800CEBD24 /* Account.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Account.swift; sourceTree = "<group>"; };
84C365491F899F3B001EC85C /* CombinedRefreshProgress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CombinedRefreshProgress.swift; sourceTree = "<group>"; };
84C8B3F31F89DE430053CCA6 /* DataExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataExtensions.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -184,16 +178,6 @@
name = Products;
sourceTree = "<group>";
};
841974141F6DD4FF006346C4 /* Container */ = {
isa = PBXGroup;
children = (
8419740D1F6DD25F006346C4 /* Container.swift */,
841974191F6DD583006346C4 /* Account+Container.swift */,
841974171F6DD535006346C4 /* Folder+Container.swift */,
);
path = Container;
sourceTree = "<group>";
};
8419742B1F6DDE84006346C4 /* LocalAccount */ = {
isa = PBXGroup;
children = (
@ -214,15 +198,6 @@
name = Frameworks;
sourceTree = "<group>";
};
846E77551F6F03B200A165E2 /* Extensions */ = {
isa = PBXGroup;
children = (
846E77581F6F03E300A165E2 /* Feed+Account.swift */,
846E77561F6F03D600A165E2 /* Article+Account.swift */,
);
name = Extensions;
sourceTree = "<group>";
};
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;
};

View File

@ -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

View File

@ -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<Feed>
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<Feed> {
var feeds = Set<Feed>()
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)
}
}

View File

@ -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<Feed> {
var feeds = Set<Feed>()
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
}
}

View File

@ -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<Feed>
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)
}
}

View File

@ -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<Feed> {
var feeds = Set<Feed>()
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
}
}

View File

@ -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)
}
}
}

View File

@ -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)
}
}
}

View File

@ -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)
}
}
}

View File

@ -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 {

View File

@ -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;

View File

@ -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 {