Refactored the OPML load code so that the normalization step is separate from the add step.

This commit is contained in:
Maurice Parker 2020-03-31 15:21:53 -05:00
parent 31e06cd24a
commit cdde8e4b09
6 changed files with 82 additions and 36 deletions

View File

@ -468,43 +468,25 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container,
delegate.accountWillBeDeleted(self) delegate.accountWillBeDeleted(self)
} }
func loadOPMLItems(_ items: [RSOPMLItem], parentFolder: Folder?) { func addOPMLItems(_ items: [RSOPMLItem]) {
var feedsToAdd = Set<WebFeed>() for item in items {
items.forEach { (item) in
if let feedSpecifier = item.feedSpecifier { if let feedSpecifier = item.feedSpecifier {
let feed = newWebFeed(with: feedSpecifier) addWebFeed(newWebFeed(with: feedSpecifier))
feedsToAdd.insert(feed)
return
}
guard let folderName = item.titleFromAttributes else {
// Folder doesnt have a name, so it wont be created, and its items will go one level up.
if let itemChildren = item.children {
loadOPMLItems(itemChildren, parentFolder: parentFolder)
}
return
}
if let folder = ensureFolder(with: folderName) {
folder.externalID = item.attributes?["nnw_externalID"] as? String
if let itemChildren = item.children {
loadOPMLItems(itemChildren, parentFolder: folder)
}
}
}
if let parentFolder = parentFolder {
for feed in feedsToAdd {
parentFolder.addWebFeed(feed)
}
} else { } else {
for feed in feedsToAdd { if let title = item.titleFromAttributes, let folder = ensureFolder(with: title) {
addWebFeed(feed) folder.externalID = item.attributes?["nnw_externalID"] as? String
item.children?.forEach { itemChild in
if let feedSpecifier = itemChild.feedSpecifier {
folder.addWebFeed(newWebFeed(with: feedSpecifier))
}
}
}
}
} }
} }
func loadOPMLItems(_ items: [RSOPMLItem]) {
addOPMLItems(OPMLNormalizer.normalize(items))
} }
public func markArticles(_ articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) -> Set<Article>? { public func markArticles(_ articles: Set<Article>, statusKey: ArticleStatus.Key, flag: Bool) -> Set<Article>? {

View File

@ -55,6 +55,7 @@
5165D72A22835F7D00D9D53D /* HTMLFeedFinder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5165D71E22835E9800D9D53D /* HTMLFeedFinder.swift */; }; 5165D72A22835F7D00D9D53D /* HTMLFeedFinder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5165D71E22835E9800D9D53D /* HTMLFeedFinder.swift */; };
5165D73122837F3400D9D53D /* InitialFeedDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5165D73022837F3400D9D53D /* InitialFeedDownloader.swift */; }; 5165D73122837F3400D9D53D /* InitialFeedDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5165D73022837F3400D9D53D /* InitialFeedDownloader.swift */; };
5170743C232AEDB500A461A3 /* OPMLFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5170743B232AEDB500A461A3 /* OPMLFile.swift */; }; 5170743C232AEDB500A461A3 /* OPMLFile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5170743B232AEDB500A461A3 /* OPMLFile.swift */; };
519E84A62433D49000D238B0 /* OPMLNormalizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519E84A52433D49000D238B0 /* OPMLNormalizer.swift */; };
51BB7B84233531BC008E8144 /* AccountBehaviors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BB7B83233531BC008E8144 /* AccountBehaviors.swift */; }; 51BB7B84233531BC008E8144 /* AccountBehaviors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BB7B83233531BC008E8144 /* AccountBehaviors.swift */; };
51BC8FCC237EC055004F8B56 /* Feed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BC8FCB237EC055004F8B56 /* Feed.swift */; }; 51BC8FCC237EC055004F8B56 /* Feed.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BC8FCB237EC055004F8B56 /* Feed.swift */; };
51BFDECE238B508D00216323 /* ContainerIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BFDECD238B508D00216323 /* ContainerIdentifier.swift */; }; 51BFDECE238B508D00216323 /* ContainerIdentifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51BFDECD238B508D00216323 /* ContainerIdentifier.swift */; };
@ -288,6 +289,7 @@
5165D73022837F3400D9D53D /* InitialFeedDownloader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InitialFeedDownloader.swift; sourceTree = "<group>"; }; 5165D73022837F3400D9D53D /* InitialFeedDownloader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InitialFeedDownloader.swift; sourceTree = "<group>"; };
5170743B232AEDB500A461A3 /* OPMLFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OPMLFile.swift; sourceTree = "<group>"; }; 5170743B232AEDB500A461A3 /* OPMLFile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OPMLFile.swift; sourceTree = "<group>"; };
518B2EA52351306200400001 /* Account_project_test.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Account_project_test.xcconfig; sourceTree = "<group>"; }; 518B2EA52351306200400001 /* Account_project_test.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Account_project_test.xcconfig; sourceTree = "<group>"; };
519E84A52433D49000D238B0 /* OPMLNormalizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OPMLNormalizer.swift; sourceTree = "<group>"; };
51BB7B83233531BC008E8144 /* AccountBehaviors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountBehaviors.swift; sourceTree = "<group>"; }; 51BB7B83233531BC008E8144 /* AccountBehaviors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountBehaviors.swift; sourceTree = "<group>"; };
51BC8FCB237EC055004F8B56 /* Feed.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Feed.swift; sourceTree = "<group>"; }; 51BC8FCB237EC055004F8B56 /* Feed.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Feed.swift; sourceTree = "<group>"; };
51BFDECD238B508D00216323 /* ContainerIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainerIdentifier.swift; sourceTree = "<group>"; }; 51BFDECD238B508D00216323 /* ContainerIdentifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContainerIdentifier.swift; sourceTree = "<group>"; };
@ -670,6 +672,7 @@
51E3EB40229AF61B00645299 /* AccountError.swift */, 51E3EB40229AF61B00645299 /* AccountError.swift */,
846E77531F6F00E300A165E2 /* AccountManager.swift */, 846E77531F6F00E300A165E2 /* AccountManager.swift */,
5170743B232AEDB500A461A3 /* OPMLFile.swift */, 5170743B232AEDB500A461A3 /* OPMLFile.swift */,
519E84A52433D49000D238B0 /* OPMLNormalizer.swift */,
84AF4EA3222CFDD100F6A800 /* AccountMetadata.swift */, 84AF4EA3222CFDD100F6A800 /* AccountMetadata.swift */,
510BD110232C3801002692E4 /* AccountMetadataFile.swift */, 510BD110232C3801002692E4 /* AccountMetadataFile.swift */,
84F73CF0202788D80000BCEF /* ArticleFetcher.swift */, 84F73CF0202788D80000BCEF /* ArticleFetcher.swift */,
@ -1102,6 +1105,7 @@
5103A9D92422546800410853 /* CloudKitAccountDelegate.swift in Sources */, 5103A9D92422546800410853 /* CloudKitAccountDelegate.swift in Sources */,
5165D73122837F3400D9D53D /* InitialFeedDownloader.swift in Sources */, 5165D73122837F3400D9D53D /* InitialFeedDownloader.swift in Sources */,
9E784EBE237E890600099B1B /* FeedlyLogoutOperation.swift in Sources */, 9E784EBE237E890600099B1B /* FeedlyLogoutOperation.swift in Sources */,
519E84A62433D49000D238B0 /* OPMLNormalizer.swift in Sources */,
9EEEF71F23545CB4009E9D80 /* FeedlySendArticleStatusesOperation.swift in Sources */, 9EEEF71F23545CB4009E9D80 /* FeedlySendArticleStatusesOperation.swift in Sources */,
9EBD49C223C67784005AD5CD /* FeedlyEntryIdentifierProviding.swift in Sources */, 9EBD49C223C67784005AD5CD /* FeedlyEntryIdentifierProviding.swift in Sources */,
846E77541F6F00E300A165E2 /* AccountManager.swift in Sources */, 846E77541F6F00E300A165E2 /* AccountManager.swift in Sources */,

View File

@ -128,7 +128,7 @@ final class CloudKitAccountDelegate: AccountDelegate {
} }
BatchUpdate.shared.perform { BatchUpdate.shared.perform {
account.loadOPMLItems(children, parentFolder: nil) account.loadOPMLItems(children)
} }
completion(.success(())) completion(.success(()))

View File

@ -85,7 +85,7 @@ final class LocalAccountDelegate: AccountDelegate {
} }
BatchUpdate.shared.perform { BatchUpdate.shared.perform {
account.loadOPMLItems(children, parentFolder: nil) account.loadOPMLItems(children)
} }
completion(.success(())) completion(.success(()))

View File

@ -40,7 +40,7 @@ final class OPMLFile {
} }
BatchUpdate.shared.perform { BatchUpdate.shared.perform {
account.loadOPMLItems(opmlItems, parentFolder: nil) account.loadOPMLItems(opmlItems)
} }
} }

View File

@ -0,0 +1,60 @@
//
// OPMLNormalizer.swift
// Account
//
// Created by Maurice Parker on 3/31/20.
// Copyright © 2020 Ranchero Software, LLC. All rights reserved.
//
import Foundation
import RSParser
final class OPMLNormalizer {
var normalizedOPMLItems = [RSOPMLItem]()
static func normalize(_ items: [RSOPMLItem]) -> [RSOPMLItem] {
let opmlNormalizer = OPMLNormalizer()
opmlNormalizer.loadOPMLItems(items)
return opmlNormalizer.normalizedOPMLItems
}
private func loadOPMLItems(_ items: [RSOPMLItem], parentFolder: RSOPMLItem? = nil) {
var feedsToAdd = [RSOPMLItem]()
items.forEach { (item) in
if let _ = item.feedSpecifier {
if !feedsToAdd.contains(where: { $0.feedSpecifier?.feedURL == item.feedSpecifier?.feedURL } ) {
feedsToAdd.append(item)
}
return
}
guard let _ = item.titleFromAttributes else {
// Folder doesnt have a name, so it wont be created, and its items will go one level up.
if let itemChildren = item.children {
loadOPMLItems(itemChildren, parentFolder: parentFolder)
}
return
}
normalizedOPMLItems.append(item)
if let itemChildren = item.children {
loadOPMLItems(itemChildren, parentFolder: item)
}
}
if let parentFolder = parentFolder {
for feed in feedsToAdd {
parentFolder.addChild(feed)
}
} else {
for feed in feedsToAdd {
normalizedOPMLItems.append(feed)
}
}
}
}