Rewrite folder management for Reader API
This commit is contained in:
parent
04b1667293
commit
1760d38777
@ -263,7 +263,7 @@ final class ReaderAPIAccountDelegate: AccountDelegate {
|
|||||||
switch result {
|
switch result {
|
||||||
case .success:
|
case .success:
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.clearFolderRelationship(for: feed, withFolderName: folder.name ?? "")
|
self.clearFolderRelationship(for: feed, folderExternalID: folder.externalID)
|
||||||
}
|
}
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
os_log(.error, log: self.log, "Remove feed error: %@.", error.localizedDescription)
|
os_log(.error, log: self.log, "Remove feed error: %@.", error.localizedDescription)
|
||||||
@ -410,14 +410,14 @@ final class ReaderAPIAccountDelegate: AccountDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func addWebFeed(for account: Account, with feed: WebFeed, to container: Container, completion: @escaping (Result<Void, Error>) -> Void) {
|
func addWebFeed(for account: Account, with feed: WebFeed, to container: Container, completion: @escaping (Result<Void, Error>) -> Void) {
|
||||||
if let folder = container as? Folder, let feedName = feed.externalID {
|
if let folder = container as? Folder, let feedExternalID = feed.externalID {
|
||||||
refreshProgress.addToNumberOfTasksAndRemaining(1)
|
refreshProgress.addToNumberOfTasksAndRemaining(1)
|
||||||
caller.createTagging(subscriptionID: feedName, tagName: folder.name ?? "") { result in
|
caller.createTagging(subscriptionID: feedExternalID, tagName: folder.name ?? "") { result in
|
||||||
self.refreshProgress.completeTask()
|
self.refreshProgress.completeTask()
|
||||||
switch result {
|
switch result {
|
||||||
case .success:
|
case .success:
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.saveFolderRelationship(for: feed, withFolderName: folder.name ?? "", id: feed.externalID!)
|
self.saveFolderRelationship(for: feed, folderExternalID: folder.externalID, feedExternalID: feedExternalID)
|
||||||
account.removeWebFeed(feed)
|
account.removeWebFeed(feed)
|
||||||
folder.addWebFeed(feed)
|
folder.addWebFeed(feed)
|
||||||
completion(.success(()))
|
completion(.success(()))
|
||||||
@ -576,35 +576,38 @@ private extension ReaderAPIAccountDelegate {
|
|||||||
guard let tags = tags else { return }
|
guard let tags = tags else { return }
|
||||||
assert(Thread.isMainThread)
|
assert(Thread.isMainThread)
|
||||||
|
|
||||||
os_log(.debug, log: log, "Syncing folders with %ld tags.", tags.count)
|
let folderTags = tags.filter{ $0.type == "folder" }
|
||||||
|
guard !folderTags.isEmpty else { return }
|
||||||
|
|
||||||
let readerFolderNames = tags.compactMap { $0.folderName }
|
os_log(.debug, log: log, "Syncing folders with %ld tags.", folderTags.count)
|
||||||
|
|
||||||
|
let readerFolderExternalIDs = folderTags.compactMap { $0.tagID }
|
||||||
|
|
||||||
// Delete any folders not at Reader
|
// Delete any folders not at Reader
|
||||||
if let folders = account.folders {
|
if let folders = account.folders {
|
||||||
folders.forEach { folder in
|
folders.forEach { folder in
|
||||||
if !readerFolderNames.contains(folder.name ?? "") {
|
if !readerFolderExternalIDs.contains(folder.externalID ?? "") {
|
||||||
for feed in folder.topLevelWebFeeds {
|
for feed in folder.topLevelWebFeeds {
|
||||||
account.addWebFeed(feed)
|
account.addWebFeed(feed)
|
||||||
clearFolderRelationship(for: feed, withFolderName: folder.name ?? "")
|
clearFolderRelationship(for: feed, folderExternalID: folder.externalID)
|
||||||
}
|
}
|
||||||
account.removeFolder(folder)
|
account.removeFolder(folder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let folderNames: [String] = {
|
let folderExternalIDs: [String] = {
|
||||||
if let folders = account.folders {
|
if let folders = account.folders {
|
||||||
return folders.map { $0.name ?? "" }
|
return folders.compactMap { $0.externalID }
|
||||||
} else {
|
} else {
|
||||||
return [String]()
|
return [String]()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Make any folders Reader has, but we don't
|
// Make any folders Reader has, but we don't
|
||||||
tags.forEach { tag in
|
folderTags.forEach { tag in
|
||||||
if let tagFolderName = tag.folderName, !folderNames.contains(tagFolderName) {
|
if !folderExternalIDs.contains(tag.tagID) {
|
||||||
let folder = account.ensureFolder(with: tagFolderName)
|
let folder = account.ensureFolder(with: tag.folderName ?? "None")
|
||||||
folder?.externalID = tag.tagID
|
folder?.externalID = tag.tagID
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -618,7 +621,7 @@ private extension ReaderAPIAccountDelegate {
|
|||||||
self.refreshProgress.completeTask()
|
self.refreshProgress.completeTask()
|
||||||
BatchUpdate.shared.perform {
|
BatchUpdate.shared.perform {
|
||||||
self.syncFeeds(account, subscriptions)
|
self.syncFeeds(account, subscriptions)
|
||||||
self.syncTaggings(account, subscriptions)
|
self.syncFeedFolderRelationship(account, subscriptions)
|
||||||
}
|
}
|
||||||
completion(.success(()))
|
completion(.success(()))
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
@ -649,6 +652,7 @@ private extension ReaderAPIAccountDelegate {
|
|||||||
|
|
||||||
for feed in account.topLevelWebFeeds {
|
for feed in account.topLevelWebFeeds {
|
||||||
if !subFeedIds.contains(feed.webFeedID) {
|
if !subFeedIds.contains(feed.webFeedID) {
|
||||||
|
account.clearWebFeedMetadata(feed)
|
||||||
account.removeWebFeed(feed)
|
account.removeWebFeed(feed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -670,43 +674,38 @@ private extension ReaderAPIAccountDelegate {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func syncTaggings(_ account: Account, _ subscriptions: [ReaderAPISubscription]?) {
|
func syncFeedFolderRelationship(_ account: Account, _ subscriptions: [ReaderAPISubscription]?) {
|
||||||
guard let subscriptions = subscriptions else { return }
|
guard let subscriptions = subscriptions else { return }
|
||||||
assert(Thread.isMainThread)
|
assert(Thread.isMainThread)
|
||||||
os_log(.debug, log: log, "Syncing taggings with %ld subscriptions.", subscriptions.count)
|
os_log(.debug, log: log, "Syncing taggings with %ld subscriptions.", subscriptions.count)
|
||||||
|
|
||||||
// Set up some structures to make syncing easier
|
// Set up some structures to make syncing easier
|
||||||
let folderDict = nameToFolderDictionary(with: account.folders)
|
let folderDict = externalIDToFolderDictionary(with: account.folders)
|
||||||
let taggingsDict = subscriptions.reduce([String: [ReaderAPISubscription]]()) { (dict, subscription) in
|
let taggingsDict = subscriptions.reduce([String: [ReaderAPISubscription]]()) { (dict, subscription) in
|
||||||
var taggedFeeds = dict
|
var taggedFeeds = dict
|
||||||
|
|
||||||
// For each category that this feed belongs to, add the feed to that name in the dict
|
|
||||||
subscription.categories.forEach({ (category) in
|
subscription.categories.forEach({ (category) in
|
||||||
let categoryName = category.categoryLabel.replacingOccurrences(of: "user/-/label/", with: "")
|
if var taggedFeed = taggedFeeds[category.categoryId] {
|
||||||
|
|
||||||
if var taggedFeed = taggedFeeds[categoryName] {
|
|
||||||
taggedFeed.append(subscription)
|
taggedFeed.append(subscription)
|
||||||
taggedFeeds[categoryName] = taggedFeed
|
taggedFeeds[category.categoryId] = taggedFeed
|
||||||
} else {
|
} else {
|
||||||
taggedFeeds[categoryName] = [subscription]
|
taggedFeeds[category.categoryId] = [subscription]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return taggedFeeds
|
return taggedFeeds
|
||||||
}
|
}
|
||||||
|
|
||||||
var taggedFeedIDs = Set<String>()
|
|
||||||
|
|
||||||
// Sync the folders
|
// Sync the folders
|
||||||
for (folderName, groupedTaggings) in taggingsDict {
|
for (folderExternalID, groupedTaggings) in taggingsDict {
|
||||||
guard let folder = folderDict[folderName] else { return }
|
guard let folder = folderDict[folderExternalID] else { return }
|
||||||
let taggingFeedIDs = groupedTaggings.map { $0.feedID }
|
let taggingFeedIDs = groupedTaggings.map { $0.feedID }
|
||||||
|
|
||||||
// Move any feeds not in the folder to the account
|
// Move any feeds not in the folder to the account
|
||||||
for feed in folder.topLevelWebFeeds {
|
for feed in folder.topLevelWebFeeds {
|
||||||
if !taggingFeedIDs.contains(feed.webFeedID) {
|
if !taggingFeedIDs.contains(feed.webFeedID) {
|
||||||
folder.removeWebFeed(feed)
|
folder.removeWebFeed(feed)
|
||||||
clearFolderRelationship(for: feed, withFolderName: folder.name ?? "")
|
clearFolderRelationship(for: feed, folderExternalID: folder.externalID)
|
||||||
account.addWebFeed(feed)
|
account.addWebFeed(feed)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -720,14 +719,15 @@ private extension ReaderAPIAccountDelegate {
|
|||||||
guard let feed = account.existingWebFeed(withWebFeedID: taggingFeedID) else {
|
guard let feed = account.existingWebFeed(withWebFeedID: taggingFeedID) else {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
saveFolderRelationship(for: feed, withFolderName: folderName, id: String(subscription.feedID))
|
saveFolderRelationship(for: feed, folderExternalID: folderExternalID, feedExternalID: subscription.feedID)
|
||||||
folder.addWebFeed(feed)
|
folder.addWebFeed(feed)
|
||||||
taggedFeedIDs.insert(taggingFeedID)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let taggedFeedIDs = Set(subscriptions.map { String($0.feedID) })
|
||||||
|
|
||||||
// Remove all feeds from the account container that have a tag
|
// Remove all feeds from the account container that have a tag
|
||||||
for feed in account.topLevelWebFeeds {
|
for feed in account.topLevelWebFeeds {
|
||||||
if taggedFeedIDs.contains(feed.webFeedID) {
|
if taggedFeedIDs.contains(feed.webFeedID) {
|
||||||
@ -736,18 +736,19 @@ private extension ReaderAPIAccountDelegate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func nameToFolderDictionary(with folders: Set<Folder>?) -> [String: Folder] {
|
func externalIDToFolderDictionary(with folders: Set<Folder>?) -> [String: Folder] {
|
||||||
guard let folders = folders else {
|
guard let folders = folders else {
|
||||||
return [String: Folder]()
|
return [String: Folder]()
|
||||||
}
|
}
|
||||||
|
|
||||||
var d = [String: Folder]()
|
var d = [String: Folder]()
|
||||||
|
|
||||||
for folder in folders {
|
for folder in folders {
|
||||||
let name = folder.name ?? ""
|
if let externalID = folder.externalID, d[externalID] == nil {
|
||||||
if d[name] == nil {
|
d[externalID] = folder
|
||||||
d[name] = folder
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -784,19 +785,19 @@ private extension ReaderAPIAccountDelegate {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func clearFolderRelationship(for feed: WebFeed, withFolderName folderName: String) {
|
func clearFolderRelationship(for feed: WebFeed, folderExternalID: String?) {
|
||||||
if var folderRelationship = feed.folderRelationship {
|
guard var folderRelationship = feed.folderRelationship, let folderExternalID = folderExternalID else { return }
|
||||||
folderRelationship[folderName] = nil
|
folderRelationship[folderExternalID] = nil
|
||||||
feed.folderRelationship = folderRelationship
|
feed.folderRelationship = folderRelationship
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
func saveFolderRelationship(for feed: WebFeed, withFolderName folderName: String, id: String) {
|
func saveFolderRelationship(for feed: WebFeed, folderExternalID: String?, feedExternalID: String) {
|
||||||
|
guard let folderExternalID = folderExternalID else { return }
|
||||||
if var folderRelationship = feed.folderRelationship {
|
if var folderRelationship = feed.folderRelationship {
|
||||||
folderRelationship[folderName] = id
|
folderRelationship[folderExternalID] = feedExternalID
|
||||||
feed.folderRelationship = folderRelationship
|
feed.folderRelationship = folderRelationship
|
||||||
} else {
|
} else {
|
||||||
feed.folderRelationship = [folderName: id]
|
feed.folderRelationship = [folderExternalID: feedExternalID]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1052,7 +1053,7 @@ private extension ReaderAPIAccountDelegate {
|
|||||||
switch result {
|
switch result {
|
||||||
case .success:
|
case .success:
|
||||||
DispatchQueue.main.async {
|
DispatchQueue.main.async {
|
||||||
self.clearFolderRelationship(for: feed, withFolderName: folder.name ?? "")
|
self.clearFolderRelationship(for: feed, folderExternalID: folder.externalID)
|
||||||
folder.removeWebFeed(feed)
|
folder.removeWebFeed(feed)
|
||||||
account.addFeedIfNotInAnyFolder(feed)
|
account.addFeedIfNotInAnyFolder(feed)
|
||||||
completion(.success(()))
|
completion(.success(()))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user