NetNewsWire/Frameworks/Account/Feedbin/FeedbinAccountDelegate.swift

167 lines
3.8 KiB
Swift
Raw Normal View History

//
// FeedbinAccountDelegate.swift
// Account
//
// Created by Maurice Parker on 5/2/19.
// Copyright © 2019 Ranchero Software, LLC. All rights reserved.
//
2019-05-05 22:41:20 +02:00
#if os(macOS)
import AppKit
#else
import UIKit
import RSCore
#endif
import RSWeb
final class FeedbinAccountDelegate: AccountDelegate {
let supportsSubFolders = false
let server: String? = "api.feedbin.com"
private let caller: FeedbinAPICaller
2019-05-05 10:25:21 +02:00
var credentials: Credentials? {
didSet {
caller.credentials = credentials
}
}
var accountMetadata: AccountMetadata? {
didSet {
caller.accountMetadata = accountMetadata
}
}
init(transport: Transport) {
2019-05-05 10:25:21 +02:00
caller = FeedbinAPICaller(transport: transport)
}
var refreshProgress = DownloadProgress(numberOfTasks: 0)
2019-05-06 17:53:20 +02:00
func refreshAll(for account: Account, completion: (() -> Void)? = nil) {
refreshAll(account) { [weak self] result in
2019-05-05 22:41:20 +02:00
switch result {
case .success():
completion?()
case .failure(let error):
2019-05-06 17:53:20 +02:00
self?.handleError(error)
}
}
}
2019-05-07 00:34:41 +02:00
func renameFolder(for account: Account, with folder: Folder, to name: String, completion: @escaping (Result<Void, Error>) -> Void) {
2019-05-06 17:53:20 +02:00
caller.renameTag(oldName: folder.name ?? "", newName: name) { result in
switch result {
case .success:
folder.name = name
completion(.success(()))
case .failure(let error):
completion(.failure(error))
2019-05-05 22:41:20 +02:00
}
}
2019-05-06 17:53:20 +02:00
}
2019-05-07 00:34:41 +02:00
func deleteFolder(for account: Account, with folder: Folder, completion: @escaping (Result<Void, Error>) -> Void) {
// Feedbin uses tags and if at least one feed isn't tagged, then the folder doesn't exist on their system
guard folder.hasAtLeastOneFeed() else {
account.deleteFolder(folder)
return
}
caller.deleteTag(name: folder.name ?? "") { result in
switch result {
case .success:
account.deleteFolder(folder)
// TODO: Take the serialized taggings and reestablish the folder to feed relationships. Deleting
// a tag on Feedbin doesn't any feeds.
completion(.success(()))
case .failure(let error):
completion(.failure(error))
}
}
}
func accountDidInitialize(_ account: Account) {
credentials = try? account.retrieveBasicCredentials()
accountMetadata = account.metadata
}
2019-05-06 17:53:20 +02:00
static func validateCredentials(transport: Transport, credentials: Credentials, completion: @escaping (Result<Bool, Error>) -> Void) {
let caller = FeedbinAPICaller(transport: transport)
caller.credentials = credentials
caller.validateCredentials() { result in
completion(result)
}
}
}
2019-05-05 22:41:20 +02:00
// MARK: Private
private extension FeedbinAccountDelegate {
2019-05-06 17:53:20 +02:00
func handleError(_ error: Error) {
// TODO: We should do a better job of error handling here.
// We need to prompt for credentials and provide user friendly
// errors.
#if os(macOS)
NSApplication.shared.presentError(error)
#else
UIApplication.shared.presentError(error)
#endif
}
2019-05-05 22:41:20 +02:00
func refreshAll(_ account: Account, completion: @escaping (Result<Void, Error>) -> Void) {
caller.retrieveTags { [weak self] result in
switch result {
case .success(let tags):
self?.syncFolders(account, tags)
completion(.success(()))
case .failure(let error):
completion(.failure(error))
2019-05-05 22:41:20 +02:00
}
}
}
func syncFolders(_ account: Account, _ tags: [FeedbinTag]?) {
guard let tags = tags else { return }
2019-05-05 22:41:20 +02:00
let tagNames = tags.map { $0.name }
// Delete any folders not at Feedbin
if let folders = account.folders {
folders.forEach { folder in
if !tagNames.contains(folder.name ?? "") {
account.deleteFolder(folder)
}
}
}
let folderNames: [String] = {
if let folders = account.folders {
return folders.map { $0.name ?? "" }
} else {
return [String]()
}
}()
// Make any folders Feedbin has, but we don't
tagNames.forEach { tagName in
if !folderNames.contains(tagName) {
account.ensureFolder(with: tagName)
}
}
}
}