NetNewsWire/Frameworks/Account/Feedbin/FeedbinAccountDelegate.swift

145 lines
3.1 KiB
Swift

//
// FeedbinAccountDelegate.swift
// Account
//
// Created by Maurice Parker on 5/2/19.
// Copyright © 2019 Ranchero Software, LLC. All rights reserved.
//
#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
var credentials: Credentials? {
didSet {
caller.credentials = credentials
}
}
var accountMetadata: AccountMetadata? {
didSet {
caller.accountMetadata = accountMetadata
}
}
init(transport: Transport) {
caller = FeedbinAPICaller(transport: transport)
}
var refreshProgress = DownloadProgress(numberOfTasks: 0)
func refreshAll(for account: Account, completion: (() -> Void)? = nil) {
refreshAll(account) { [weak self] result in
switch result {
case .success():
completion?()
case .failure(let error):
self?.handleError(error)
}
}
}
func renameFolder(_ folder: Folder, to name: String, completion: @escaping (Result<Void, Error>) -> Void) {
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))
}
}
}
func accountDidInitialize(_ account: Account) {
credentials = try? account.retrieveBasicCredentials()
accountMetadata = account.metadata
}
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)
}
}
}
// MARK: Private
private extension FeedbinAccountDelegate {
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
}
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))
}
}
}
func syncFolders(_ account: Account, _ tags: [FeedbinTag]?) {
guard let tags = tags else { return }
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)
}
}
}
}