Refactored the OPML load code so that the normalization step is separate from the add step.
This commit is contained in:
parent
31e06cd24a
commit
cdde8e4b09
|
@ -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 doesn’t have a name, so it won’t 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>? {
|
||||||
|
|
|
@ -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 */,
|
||||||
|
|
|
@ -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(()))
|
||||||
|
|
|
@ -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(()))
|
||||||
|
|
|
@ -40,7 +40,7 @@ final class OPMLFile {
|
||||||
}
|
}
|
||||||
|
|
||||||
BatchUpdate.shared.perform {
|
BatchUpdate.shared.perform {
|
||||||
account.loadOPMLItems(opmlItems, parentFolder: nil)
|
account.loadOPMLItems(opmlItems)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 doesn’t have a name, so it won’t 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue