diff --git a/Frameworks/Account/Account.swift b/Frameworks/Account/Account.swift index 639c5c0f9..5b78e8e85 100644 --- a/Frameworks/Account/Account.swift +++ b/Frameworks/Account/Account.swift @@ -593,14 +593,22 @@ public final class Account: DisplayNameProvider, UnreadCountProvider, Container, return _flattenedFeeds } - func deleteFeeds(_ feeds: Set) { - topLevelFeeds.subtract(feeds) + public func deleteFeed(_ feed: Feed, completion: @escaping (Result) -> Void) { + delegate.deleteFeed(for: self, container: self, feed: feed, completion: completion) + } + + func deleteFeed(_ feed: Feed, from container: Container, completion: @escaping (Result) -> Void) { + delegate.deleteFeed(for: self, container: container, feed: feed, completion: completion) + } + + func deleteFeed(_ feed: Feed) { + topLevelFeeds.remove(feed) structureDidChange() postChildrenDidChangeNotification() } - public func deleteFeed(_ feed: Feed) { - topLevelFeeds.remove(feed) + func deleteFeeds(_ feeds: Set) { + topLevelFeeds.subtract(feeds) structureDidChange() postChildrenDidChangeNotification() } diff --git a/Frameworks/Account/AccountDelegate.swift b/Frameworks/Account/AccountDelegate.swift index 17f8aa187..6e95b8fc2 100644 --- a/Frameworks/Account/AccountDelegate.swift +++ b/Frameworks/Account/AccountDelegate.swift @@ -26,6 +26,7 @@ protocol AccountDelegate { func createFeed(for account: Account, with name: String?, url: String, completion: @escaping (Result) -> Void) func renameFeed(for account: Account, with feed: Feed, to name: String, completion: @escaping (Result) -> Void) + func deleteFeed(for account: Account, container: Container, feed: Feed, completion: @escaping (Result) -> Void) // Called at the end of account’s init method. func accountDidInitialize(_ account: Account) diff --git a/Frameworks/Account/Container.swift b/Frameworks/Account/Container.swift index 16c2df398..6cf310e70 100644 --- a/Frameworks/Account/Container.swift +++ b/Frameworks/Account/Container.swift @@ -27,7 +27,7 @@ public protocol Container: class { func hasChildFolder(with: String) -> Bool func childFolder(with: String) -> Folder? - func deleteFeed(_ feed: Feed) + func deleteFeed(_ feed: Feed, completion: @escaping (Result) -> Void) func deleteFolder(_ folder: Folder, completion: @escaping (Result) -> Void) func addFeed(_ feed: Feed) diff --git a/Frameworks/Account/Feedbin/FeedbinAPICaller.swift b/Frameworks/Account/Feedbin/FeedbinAPICaller.swift index 8dcfd9a02..7f88720f9 100644 --- a/Frameworks/Account/Feedbin/FeedbinAPICaller.swift +++ b/Frameworks/Account/Feedbin/FeedbinAPICaller.swift @@ -124,7 +124,6 @@ final class FeedbinAPICaller: NSObject { let callURL = feedbinBaseURL.appendingPathComponent("subscriptions.json") var request = URLRequest(url: callURL, credentials: credentials) - request.httpMethod = HTTPMethod.post request.addValue("application/json; charset=utf-8", forHTTPHeaderField: HTTPRequestHeader.contentType) let payload: Data @@ -135,7 +134,7 @@ final class FeedbinAPICaller: NSObject { return } - transport.send(request: request, payload: payload) { result in + transport.send(request: request, method: HTTPMethod.post, payload: payload) { result in switch result { case .success(let (response, data)): @@ -188,13 +187,19 @@ final class FeedbinAPICaller: NSObject { } - func renameFeed(subscriptionID: String, newName: String, completion: @escaping (Result) -> Void) { + func renameSubscription(subscriptionID: String, newName: String, completion: @escaping (Result) -> Void) { let callURL = feedbinBaseURL.appendingPathComponent("subscriptions/\(subscriptionID)/update.json") let request = URLRequest(url: callURL, credentials: credentials) let payload = FeedbinUpdateSubscription(title: newName) transport.send(request: request, method: HTTPMethod.post, payload: payload, completion: completion) } + func deleteSubscription(subscriptionID: String, completion: @escaping (Result) -> Void) { + let callURL = feedbinBaseURL.appendingPathComponent("subscriptions/\(subscriptionID).json") + let request = URLRequest(url: callURL, credentials: credentials) + transport.send(request: request, method: HTTPMethod.delete, completion: completion) + } + func retrieveTaggings(completionHandler completion: @escaping (Result<[FeedbinTagging]?, Error>) -> Void) { let callURL = feedbinBaseURL.appendingPathComponent("taggings.json") diff --git a/Frameworks/Account/Feedbin/FeedbinAccountDelegate.swift b/Frameworks/Account/Feedbin/FeedbinAccountDelegate.swift index 83a2918f4..8fb43441c 100644 --- a/Frameworks/Account/Feedbin/FeedbinAccountDelegate.swift +++ b/Frameworks/Account/Feedbin/FeedbinAccountDelegate.swift @@ -158,7 +158,7 @@ final class FeedbinAccountDelegate: AccountDelegate { return } - caller.renameFeed(subscriptionID: subscriptionID, newName: name) { result in + caller.renameSubscription(subscriptionID: subscriptionID, newName: name) { result in switch result { case .success: DispatchQueue.main.async { @@ -174,6 +174,35 @@ final class FeedbinAccountDelegate: AccountDelegate { } + func deleteFeed(for account: Account, container: Container, feed: Feed, completion: @escaping (Result) -> Void) { + + // This error should never happen + guard let subscriptionID = feed.subscriptionID else { + completion(.failure(FeedbinAccountDelegateError.invalidParameter)) + return + } + + caller.deleteSubscription(subscriptionID: subscriptionID) { result in + switch result { + case .success: + DispatchQueue.main.async { + if let account = container as? Account { + account.deleteFeed(feed) + } + if let folder = container as? Folder { + folder.deleteFeed(feed) + } + completion(.success(())) + } + case .failure(let error): + DispatchQueue.main.async { + completion(.failure(error)) + } + } + } + + } + func accountDidInitialize(_ account: Account) { credentials = try? account.retrieveBasicCredentials() accountMetadata = account.metadata diff --git a/Frameworks/Account/Folder.swift b/Frameworks/Account/Folder.swift index 3a979dbf3..4ce26ef20 100644 --- a/Frameworks/Account/Folder.swift +++ b/Frameworks/Account/Folder.swift @@ -95,7 +95,11 @@ public final class Folder: DisplayNameProvider, Renamable, Container, UnreadCoun return topLevelFeeds.contains(feed) } - public func deleteFeed(_ feed: Feed) { + public func deleteFeed(_ feed: Feed, completion: @escaping (Result) -> Void) { + // TODO: Something here... + } + + func deleteFeed(_ feed: Feed) { topLevelFeeds.remove(feed) postChildrenDidChangeNotification() } diff --git a/Frameworks/Account/LocalAccount/LocalAccountDelegate.swift b/Frameworks/Account/LocalAccount/LocalAccountDelegate.swift index e359870b4..229b1f3ef 100644 --- a/Frameworks/Account/LocalAccount/LocalAccountDelegate.swift +++ b/Frameworks/Account/LocalAccount/LocalAccountDelegate.swift @@ -64,7 +64,20 @@ final class LocalAccountDelegate: AccountDelegate { feed.editedName = name completion(.success(())) } + + func deleteFeed(for account: Account, container: Container, feed: Feed, completion: @escaping (Result) -> Void) { + + if let account = container as? Account { + account.deleteFeed(feed) + } + if let folder = container as? Folder { + folder.deleteFeed(feed) + } + completion(.success(())) + + } + func accountDidInitialize(_ account: Account) { } diff --git a/Mac/MainWindow/Sidebar/SidebarOutlineDataSource.swift b/Mac/MainWindow/Sidebar/SidebarOutlineDataSource.swift index 6d8def52b..359b5f41e 100644 --- a/Mac/MainWindow/Sidebar/SidebarOutlineDataSource.swift +++ b/Mac/MainWindow/Sidebar/SidebarOutlineDataSource.swift @@ -244,8 +244,14 @@ private extension SidebarOutlineDataSource { } let sourceContainer = node.parent?.representedObject as? Container let destinationFolder = parentNode.representedObject as? Folder - sourceContainer?.deleteFeed(feed) - account.addFeed(feed, to: destinationFolder) + sourceContainer?.deleteFeed(feed) { result in + switch result { + case .success: + account.addFeed(feed, to: destinationFolder) + case .failure(let error): + NSApplication.shared.presentError(error) + } + } } func acceptLocalFeedsDrop(_ outlineView: NSOutlineView, _ draggedFeeds: Set, _ parentNode: Node, _ index: Int) -> Bool { diff --git a/Mac/Scriptability/Account+Scriptability.swift b/Mac/Scriptability/Account+Scriptability.swift index 364b6e342..7c9e9c73c 100644 --- a/Mac/Scriptability/Account+Scriptability.swift +++ b/Mac/Scriptability/Account+Scriptability.swift @@ -55,7 +55,8 @@ class ScriptableAccount: NSObject, UniqueIdScriptingObject, ScriptingObjectConta } } else if let scriptableFeed = element as? ScriptableFeed { BatchUpdate.shared.perform { - account.deleteFeed(scriptableFeed.feed) + account.deleteFeed(scriptableFeed.feed) { result in + } } } } diff --git a/Mac/Scriptability/Folder+Scriptability.swift b/Mac/Scriptability/Folder+Scriptability.swift index b71535e1b..64e44b70d 100644 --- a/Mac/Scriptability/Folder+Scriptability.swift +++ b/Mac/Scriptability/Folder+Scriptability.swift @@ -57,7 +57,7 @@ class ScriptableFolder: NSObject, UniqueIdScriptingObject, ScriptingObjectContai } } else if let scriptableFeed = element as? ScriptableFeed { BatchUpdate.shared.perform { - folder.deleteFeed(scriptableFeed.feed) + folder.deleteFeed(scriptableFeed.feed) { result in } } } } diff --git a/Shared/Commands/DeleteCommand.swift b/Shared/Commands/DeleteCommand.swift index 61f621da7..7b0da79ae 100644 --- a/Shared/Commands/DeleteCommand.swift +++ b/Shared/Commands/DeleteCommand.swift @@ -139,9 +139,19 @@ private struct SidebarItemSpecifier { } if let feed = feed { - container.deleteFeed(feed) - } - else if let folder = folder { + container.deleteFeed(feed) { result in + switch result { + case .success(): + break + case .failure(let error): + #if os(macOS) + NSApplication.shared.presentError(error) + #else + UIApplication.shared.presentError(error) + #endif + } + } + } else if let folder = folder { container.deleteFolder(folder) { result in switch result { case .success(): diff --git a/submodules/RSWeb b/submodules/RSWeb index bb6839d82..9e8ef66b5 160000 --- a/submodules/RSWeb +++ b/submodules/RSWeb @@ -1 +1 @@ -Subproject commit bb6839d82ef733d473cdc09925cc70fb2de238aa +Subproject commit 9e8ef66b5cba0316926f243d0465dfbb1fdc307e