NetNewsWire/Evergreen/MainWindow/AddFeed/AddFeedController.swift
2017-09-24 12:24:44 -07:00

240 lines
6.3 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// AddFeedController.swift
// Evergreen
//
// Created by Brent Simmons on 8/28/16.
// Copyright © 2016 Ranchero Software, LLC. All rights reserved.
//
import Cocoa
import RSCore
import RSTree
import Data
import RSFeedFinder
import Account
// 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.
let UserDidAddFeedNotification = Notification.Name("UserDidAddFeedNotification")
let UserDidAddFeedKey = "feed"
class AddFeedController: AddFeedWindowControllerDelegate, FeedFinderDelegate {
fileprivate let hostWindow: NSWindow
fileprivate var addFeedWindowController: AddFeedWindowController?
fileprivate var userEnteredURL: URL?
fileprivate var userEnteredFolder: Folder?
fileprivate var userEnteredTitle: String?
fileprivate var foundFeedURLString: String?
fileprivate var titleFromFeed: String?
fileprivate var feedFinder: FeedFinder?
fileprivate var isFindingFeed = false
fileprivate var bestFeedSpecifier: FeedSpecifier?
init(hostWindow: NSWindow) {
self.hostWindow = hostWindow
}
func showAddFeedSheet(_ urlString: String?, _ name: String?) {
let folderTreeControllerDelegate = FolderTreeControllerDelegate()
let rootNode = Node(representedObject: AccountManager.shared.localAccount, parent: nil)
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
func addFeedWindowController(_: AddFeedWindowController, userEnteredURL url: URL, userEnteredTitle title: String?, folder: Folder) {
closeAddFeedSheet(NSApplication.ModalResponse.OK)
assert(folder.account != nil, "Folder must have an account.")
let account = folder.account ?? AccountManager.shared.localAccount
if account.hasFeed(withURL: url.absoluteString) {
showAlreadySubscribedError(url.absoluteString, folder)
return
}
userEnteredURL = url
userEnteredFolder = folder
userEnteredTitle = title
findFeed()
}
func addFeedWindowControllerUserDidCancel(_: AddFeedWindowController) {
closeAddFeedSheet(NSApplication.ModalResponse.cancel)
}
// 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 {
if let urlString = NSPasteboard.rs_urlString(from: NSPasteboard.general) {
return urlString.rs_normalizedURL()
}
return nil
}
}
func closeAddFeedSheet(_ returnCode: NSApplication.ModalResponse) {
if let sheetWindow = addFeedWindowController?.window {
hostWindow.endSheet(sheetWindow, returnCode: returnCode)
}
}
func addFeedIfPossible() {
// Add feed if not already subscribed-to.
guard let folder = userEnteredFolder else {
assertionFailure("Folder must not be nil here.")
return
}
guard let account = userEnteredFolder?.account else {
assertionFailure("Folder must have an account.")
return
}
guard let feedURLString = foundFeedURLString else {
assertionFailure("urlString must not be nil here.")
return
}
if account.hasFeed(withURL: feedURLString) {
showAlreadySubscribedError(feedURLString, folder)
return
}
if let feed = folder.createFeedWithName(titleFromFeed, editedName: userEnteredTitle, urlString: feedURLString) {
print(feedURLString)
if folder.addItem(feed) {
NotificationCenter.default.post(name: UserDidAddFeedNotification, object: self, userInfo: [UserDidAddFeedKey: feed])
}
}
}
// MARK: Find Feeds
func findFeed() {
guard let url = userEnteredURL else {
assertionFailure("userEnteredURL must not be nil.")
return
}
isFindingFeed = true
feedFinder = FeedFinder(url: url, delegate: self)
beginShowingProgress()
}
// MARK: Errors
func showAlreadySubscribedError(_ urlString: String, _ folder: Folder) {
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)
}
}