NetNewsWire/Evergreen/MainWindow/AddFeed/AddFeedController.swift

257 lines
6.6 KiB
Swift
Raw Normal View History

2017-05-27 19:43:27 +02:00
//
// AddFeedController.swift
// Evergreen
//
// Created by Brent Simmons on 8/28/16.
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
2017-05-27 19:43:27 +02:00
//
import Cocoa
import RSCore
import RSTree
import Data
2017-05-27 19:43:27 +02:00
import RSFeedFinder
2017-09-17 21:34:10 +02:00
import Account
2017-05-27 19:43:27 +02:00
// Run add-feed sheet.
// If it returns with URL and optional name,
// run FeedFinder plus modal progress window.
// If FeedFinder returns feed,
// add feed.
// Else,
// display error sheet.
class AddFeedController: AddFeedWindowControllerDelegate, FeedFinderDelegate {
2017-10-22 00:56:01 +02:00
private let hostWindow: NSWindow
private var addFeedWindowController: AddFeedWindowController?
private var userEnteredURL: URL?
private var userEnteredFolder: Folder?
private var userEnteredTitle: String?
private var userEnteredAccount: Account?
private var foundFeedURLString: String?
private var titleFromFeed: String?
private var feedFinder: FeedFinder?
private var isFindingFeed = false
private var bestFeedSpecifier: FeedSpecifier?
2017-05-27 19:43:27 +02:00
init(hostWindow: NSWindow) {
self.hostWindow = hostWindow
}
func showAddFeedSheet(_ urlString: String?, _ name: String?) {
let folderTreeControllerDelegate = FolderTreeControllerDelegate()
2017-09-24 21:24:44 +02:00
let rootNode = Node(representedObject: AccountManager.shared.localAccount, parent: nil)
2017-05-27 19:43:27 +02:00
rootNode.canHaveChildNodes = true
let folderTreeController = TreeController(delegate: folderTreeControllerDelegate, rootNode: rootNode)
addFeedWindowController = AddFeedWindowController(urlString: urlString ?? urlStringFromPasteboard, name: name, folderTreeController: folderTreeController, delegate: self)
addFeedWindowController!.runSheetOnWindow(hostWindow)
}
// MARK: AddFeedWindowControllerDelegate
2017-10-22 00:04:59 +02:00
func addFeedWindowController(_: AddFeedWindowController, userEnteredURL url: URL, userEnteredTitle title: String?, container: Container) {
2017-05-27 19:43:27 +02:00
2017-09-17 21:54:08 +02:00
closeAddFeedSheet(NSApplication.ModalResponse.OK)
2017-10-22 00:56:01 +02:00
guard let accountAndFolderSpecifier = accountAndFolderFromContainer(container) else {
return
}
let account = accountAndFolderSpecifier.account
let folder = accountAndFolderSpecifier.folder
if account.hasFeed(withURL: url.absoluteString) {
showAlreadySubscribedError(url.absoluteString)
return
}
userEnteredAccount = account
userEnteredURL = url
userEnteredFolder = folder
userEnteredTitle = title
2017-05-27 19:43:27 +02:00
findFeed()
}
func addFeedWindowControllerUserDidCancel(_: AddFeedWindowController) {
2017-09-17 21:54:08 +02:00
closeAddFeedSheet(NSApplication.ModalResponse.cancel)
2017-05-27 19:43:27 +02:00
}
// MARK: FeedFinderDelegate
public func feedFinder(_ feedFinder: FeedFinder, didFindFeeds feedSpecifiers: Set<FeedSpecifier>) {
isFindingFeed = false
endShowingProgress()
if let error = feedFinder.initialDownloadError {
if feedFinder.initialDownloadStatusCode == 404 {
showNoFeedsErrorMessage()
}
else {
showInitialDownloadError(error)
}
return
}
guard let bestFeedSpecifier = FeedSpecifier.bestFeed(in: feedSpecifiers) else {
showNoFeedsErrorMessage()
return
}
self.bestFeedSpecifier = bestFeedSpecifier
self.foundFeedURLString = bestFeedSpecifier.urlString
if let _ = userEnteredTitle {
addFeedIfPossible()
}
if let url = URL(string: bestFeedSpecifier.urlString) {
downloadTitleForFeed(url, { (title) in
self.titleFromFeed = title
self.addFeedIfPossible()
})
}
else {
// Shouldn't happen.
showNoFeedsErrorMessage()
}
}
}
private extension AddFeedController {
var urlStringFromPasteboard: String? {
get {
2017-09-17 21:54:08 +02:00
if let urlString = NSPasteboard.rs_urlString(from: NSPasteboard.general) {
2017-05-27 19:43:27 +02:00
return urlString.rs_normalizedURL()
}
return nil
}
}
2017-10-22 00:56:01 +02:00
struct AccountAndFolderSpecifier {
let account: Account
let folder: Folder?
}
func accountAndFolderFromContainer(_ container: Container) -> AccountAndFolderSpecifier? {
if let account = container as? Account {
return AccountAndFolderSpecifier(account: account, folder: nil)
}
2017-10-22 01:37:40 +02:00
if let folder = container as? Folder, let account = folder.account {
return AccountAndFolderSpecifier(account: account, folder: folder)
2017-10-22 00:56:01 +02:00
}
return nil
}
2017-09-17 21:54:08 +02:00
func closeAddFeedSheet(_ returnCode: NSApplication.ModalResponse) {
2017-05-27 19:43:27 +02:00
if let sheetWindow = addFeedWindowController?.window {
hostWindow.endSheet(sheetWindow, returnCode: returnCode)
}
}
func addFeedIfPossible() {
// Add feed if not already subscribed-to.
2017-10-22 00:56:01 +02:00
guard let account = userEnteredAccount else {
assertionFailure("Expected account.")
2017-05-27 19:43:27 +02:00
return
}
guard let feedURLString = foundFeedURLString else {
2017-10-22 00:56:01 +02:00
assertionFailure("Expected feedURLString.")
2017-05-27 19:43:27 +02:00
return
}
2017-09-17 22:07:55 +02:00
if account.hasFeed(withURL: feedURLString) {
2017-10-22 00:56:01 +02:00
showAlreadySubscribedError(feedURLString)
2017-05-27 19:43:27 +02:00
return
}
2017-10-22 00:56:01 +02:00
guard let feed = account.createFeed(with: titleFromFeed, editedName: userEnteredTitle, url: feedURLString) else {
return
}
if account.addFeed(feed, to: userEnteredFolder) {
let appInfo = AppInfo()
appInfo.feed = feed
NotificationCenter.default.post(name: .UserDidAddFeed, object: self, userInfo: appInfo.userInfo)
2017-05-27 19:43:27 +02:00
}
}
// MARK: Find Feeds
func findFeed() {
guard let url = userEnteredURL else {
2017-10-22 00:56:01 +02:00
assertionFailure("Expected userEnteredURL.")
2017-05-27 19:43:27 +02:00
return
}
isFindingFeed = true
feedFinder = FeedFinder(url: url, delegate: self)
beginShowingProgress()
}
// MARK: Errors
2017-10-22 00:56:01 +02:00
func showAlreadySubscribedError(_ urlString: String) {
2017-05-27 19:43:27 +02:00
let alert = NSAlert()
alert.alertStyle = .informational
alert.messageText = NSLocalizedString("Already subscribed", comment: "Feed finder")
alert.informativeText = NSLocalizedString("Cant add this feed because youve already subscribed to it.", comment: "Feed finder")
alert.beginSheetModal(for: hostWindow)
}
func showInitialDownloadError(_ error: Error) {
let alert = NSAlert()
alert.alertStyle = .informational
alert.messageText = NSLocalizedString("Download Error", comment: "Feed finder")
let formatString = NSLocalizedString("Cant add this feed because of a download error: “%@”", comment: "Feed finder")
let errorText = NSString.localizedStringWithFormat(formatString as NSString, error.localizedDescription)
alert.informativeText = errorText as String
alert.beginSheetModal(for: hostWindow)
}
func showNoFeedsErrorMessage() {
let alert = NSAlert()
alert.alertStyle = .informational
alert.messageText = NSLocalizedString("Feed not found", comment: "Feed finder")
alert.informativeText = NSLocalizedString("Cant add a feed because no feed was found.", comment: "Feed finder")
alert.beginSheetModal(for: hostWindow)
}
// MARK: Progress
func beginShowingProgress() {
runIndeterminateProgressWithMessage(NSLocalizedString("Finding feed…", comment:"Feed finder"))
}
func endShowingProgress() {
stopIndeterminateProgress()
hostWindow.makeKeyAndOrderFront(self)
}
}