diff --git a/NetNewsWire.xcodeproj/project.pbxproj b/NetNewsWire.xcodeproj/project.pbxproj index 2e7e8bdf2..029e361d3 100644 --- a/NetNewsWire.xcodeproj/project.pbxproj +++ b/NetNewsWire.xcodeproj/project.pbxproj @@ -9,6 +9,8 @@ /* Begin PBXBuildFile section */ 519B8D332143397200FA689C /* SharingServiceDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519B8D322143397200FA689C /* SharingServiceDelegate.swift */; }; 51EC114C2149FE3300B296E3 /* FolderTreeMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51EC114B2149FE3300B296E3 /* FolderTreeMenu.swift */; }; + 51EC11A1214A94AD00B296E3 /* AddFeedFromListSheet.xib in Resources */ = {isa = PBXBuildFile; fileRef = 51EC1193214A94AC00B296E3 /* AddFeedFromListSheet.xib */; }; + 51EC11A3214A990000B296E3 /* AddFeedFromListWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51EC11A2214A990000B296E3 /* AddFeedFromListWindowController.swift */; }; 6581C73820CED60100F4AD34 /* SafariExtensionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6581C73720CED60100F4AD34 /* SafariExtensionHandler.swift */; }; 6581C73A20CED60100F4AD34 /* SafariExtensionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6581C73920CED60100F4AD34 /* SafariExtensionViewController.swift */; }; 6581C73D20CED60100F4AD34 /* SafariExtensionViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 6581C73B20CED60100F4AD34 /* SafariExtensionViewController.xib */; }; @@ -482,6 +484,8 @@ /* Begin PBXFileReference section */ 519B8D322143397200FA689C /* SharingServiceDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharingServiceDelegate.swift; sourceTree = ""; }; 51EC114B2149FE3300B296E3 /* FolderTreeMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = FolderTreeMenu.swift; path = AddFeed/FolderTreeMenu.swift; sourceTree = ""; }; + 51EC1194214A94AC00B296E3 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = NetNewsWire/Base.lproj/AddFeedFromListSheet.xib; sourceTree = SOURCE_ROOT; }; + 51EC11A2214A990000B296E3 /* AddFeedFromListWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AddFeedFromListWindowController.swift; path = AddFeed/AddFeedFromListWindowController.swift; sourceTree = ""; }; 6581C73320CED60000F4AD34 /* Subscribe to Feed.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "Subscribe to Feed.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; 6581C73420CED60100F4AD34 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 6581C73720CED60100F4AD34 /* SafariExtensionHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SafariExtensionHandler.swift; sourceTree = ""; }; @@ -950,6 +954,8 @@ 849A97551ED9EAC3007D329B /* Add Feed */ = { isa = PBXGroup; children = ( + 51EC1193214A94AC00B296E3 /* AddFeedFromListSheet.xib */, + 51EC11A2214A990000B296E3 /* AddFeedFromListWindowController.swift */, 849A97A71ED9F9AA007D329B /* AddFeedSheet.xib */, 849A97511ED9EAC0007D329B /* AddFeedController.swift */, 849A97521ED9EAC0007D329B /* AddFeedWindowController.swift */, @@ -1814,6 +1820,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 51EC11A1214A94AD00B296E3 /* AddFeedFromListSheet.xib in Resources */, 84EB381F1FBA8B9F000D2111 /* KeyboardShortcuts.html in Resources */, 849A97951ED9EF7A007D329B /* IndeterminateProgressWindow.xib in Resources */, 844B5B651FEA11F200C7C76A /* GlobalKeyboardShortcuts.plist in Resources */, @@ -1943,6 +1950,7 @@ 8426118A1FCB67AA0086A189 /* FeedIconDownloader.swift in Sources */, 84162A152038C12C00035290 /* MarkCommandValidationStatus.swift in Sources */, 84E95D241FB1087500552D99 /* ArticlePasteboardWriter.swift in Sources */, + 51EC11A3214A990000B296E3 /* AddFeedFromListWindowController.swift in Sources */, 849A975B1ED9EB0D007D329B /* ArticleUtilities.swift in Sources */, 84DAEE301F86CAFE0058304B /* OPMLImporter.swift in Sources */, 849A975C1ED9EB0D007D329B /* DefaultFeedsImporter.swift in Sources */, @@ -2117,6 +2125,14 @@ /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ + 51EC1193214A94AC00B296E3 /* AddFeedFromListSheet.xib */ = { + isa = PBXVariantGroup; + children = ( + 51EC1194214A94AC00B296E3 /* Base */, + ); + name = AddFeedFromListSheet.xib; + sourceTree = ""; + }; 6581C73B20CED60100F4AD34 /* SafariExtensionViewController.xib */ = { isa = PBXVariantGroup; children = ( diff --git a/NetNewsWire/AppDelegate.swift b/NetNewsWire/AppDelegate.swift index a94d8405c..8e38abf8a 100644 --- a/NetNewsWire/AppDelegate.swift +++ b/NetNewsWire/AppDelegate.swift @@ -49,6 +49,7 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, private var readerWindows = [NSWindowController]() private var feedListWindowController: NSWindowController? private var addFeedController: AddFeedController? + private var addFeedFromListController: AddFeedFromListWindowController? private var addFolderWindowController: AddFolderWindowController? private var keyboardShortcutsWindowController: WebViewWindowController? private var inspectorWindowController: InspectorWindowController? @@ -101,6 +102,18 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, addFeedController = AddFeedController(hostWindow: window) addFeedController?.showAddFeedSheet(urlString, name) } + + func showAddFeedFromListOnMainWindow(_ feedListFeeds: [FeedListFeed]) { + + addFeedFromListController = AddFeedFromListWindowController(feedListFeeds) + + createAndShowMainWindow() + + let isDisplayingSheet = mainWindowController?.isDisplayingSheet ?? false + if !isDisplayingSheet, let mainWindow = mainWindowController?.window { + addFeedFromListController!.runSheetOnWindow(mainWindow) + } + } // MARK: - NSApplicationDelegate diff --git a/NetNewsWire/Base.lproj/AddFeedFromListSheet.xib b/NetNewsWire/Base.lproj/AddFeedFromListSheet.xib new file mode 100644 index 000000000..a622517e9 --- /dev/null +++ b/NetNewsWire/Base.lproj/AddFeedFromListSheet.xib @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/NetNewsWire/FeedList/FeedListViewController.swift b/NetNewsWire/FeedList/FeedListViewController.swift index 6d7ca1790..1557180ca 100644 --- a/NetNewsWire/FeedList/FeedListViewController.swift +++ b/NetNewsWire/FeedList/FeedListViewController.swift @@ -76,8 +76,10 @@ extension FeedListViewController { } @IBAction func addToFeeds(_ sender: Any?) { - + let selectedFeeds = selectedObjects.map { $0 as! FeedListFeed } + appDelegate.showAddFeedFromListOnMainWindow(selectedFeeds) } + } // MARK: - NSOutlineViewDataSource diff --git a/NetNewsWire/MainWindow/AddFeed/AddFeedFromListWindowController.swift b/NetNewsWire/MainWindow/AddFeed/AddFeedFromListWindowController.swift new file mode 100644 index 000000000..d27cd8e5c --- /dev/null +++ b/NetNewsWire/MainWindow/AddFeed/AddFeedFromListWindowController.swift @@ -0,0 +1,122 @@ +// +// AddFeedFromListWindowController.swift +// NetNewsWire +// +// Created by Maurice Parker on 9/13/18. +// Copyright © 2018 Ranchero Software, LLC. All rights reserved. +// + +import AppKit +import RSCore +import RSTree +import Articles +import Account + + +class AddFeedFromListWindowController : NSWindowController { + + @IBOutlet weak var addFeedTextField: NSTextField! + @IBOutlet weak var folderPopupButton: NSPopUpButton! + + private var feedListFeeds: [FeedListFeed]? + private var hostWindow: NSWindow! + private var folderTreeController: TreeController? + + convenience init(_ feedListFeeds: [FeedListFeed]) { + self.init(windowNibName: NSNib.Name(rawValue: "AddFeedFromListSheet")) + self.feedListFeeds = feedListFeeds + } + + func runSheetOnWindow(_ w: NSWindow) { + hostWindow = w + if let sheetWindow = self.window { + hostWindow.beginSheet(sheetWindow) { (returnCode: NSApplication.ModalResponse) -> Void in + } + } + } + + override func windowDidLoad() { + + guard let feedListFeeds = feedListFeeds else { + assertionFailure("Feeds should have been passed in the initializer") + return + } + + if feedListFeeds.count == 1 { + addFeedTextField.stringValue = "Add \"\(feedListFeeds.first!.nameForDisplay)\"?" + } else { + addFeedTextField.stringValue = "Add \(feedListFeeds.count) feeds?" + } + + let rootNode = Node(representedObject: AccountManager.shared.localAccount, parent: nil) + rootNode.canHaveChildNodes = true + folderTreeController = TreeController(delegate: FolderTreeControllerDelegate(), rootNode: rootNode) + + folderPopupButton.menu = FolderTreeMenu.createFolderPopupMenu(with: folderTreeController!.rootNode) + + } + + + // MARK: Actions + + @IBAction func cancel(_ sender: Any?) { + if let sheetWindow = window { + hostWindow.endSheet(sheetWindow, returnCode: NSApplication.ModalResponse.cancel) + } + } + + @IBAction func addFeed(_ sender: Any?) { + + guard let container = folderPopupButton.selectedItem?.representedObject as? Container else { + assertionFailure("Expected the folderPopupButton to have a container.") + return + } + + guard let feedListFeeds = feedListFeeds else { + assertionFailure("Feeds should have been passed in the initializer") + return + } + + var account: Account? + var folder: Folder? + if container is Folder { + folder = (container as! Folder) + account = folder!.account + } else { + account = (container as! Account) + } + + for feedListFeed in feedListFeeds { + + if account!.hasFeed(withURL: feedListFeed.url) { + continue + } + + guard let feed = account!.createFeed(with: feedListFeed.nameForDisplay, editedName: nil, url: feedListFeed.url) else { + continue + } + + guard let url = URL(string: feedListFeed.url) else { + assertionFailure("Malformed URL string: \(feedListFeed.url).") + continue + } + + if account!.addFeed(feed, to: folder) { + NotificationCenter.default.post(name: .UserDidAddFeed, object: self, userInfo: [UserInfoKey.feed: feed]) + } + + InitialFeedDownloader.download(url) { (parsedFeed) in + if let parsedFeed = parsedFeed { + account!.update(feed, with: parsedFeed, {}) + } + } + + } + + if let sheetWindow = window { + hostWindow.endSheet(sheetWindow, returnCode: NSApplication.ModalResponse.OK) + } + + } + +}