From ab8ef659627ea728095073d2a5db025d6c4006d5 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Wed, 12 Sep 2018 22:23:23 -0500 Subject: [PATCH 1/7] Implemented the add feed functionality on the feed directory window. Issue #105 --- NetNewsWire.xcodeproj/project.pbxproj | 14 +-- NetNewsWire/FeedList/FeedList.storyboard | 82 +++++++++++------ .../FeedList/FeedListViewController.swift | 88 ++++++++++++++++--- .../AddFeed/AddFeedWindowController.swift | 33 +------ .../MainWindow/AddFeed/FolderTreeMenu.swift | 47 ++++++++++ 5 files changed, 188 insertions(+), 76 deletions(-) create mode 100644 NetNewsWire/MainWindow/AddFeed/FolderTreeMenu.swift diff --git a/NetNewsWire.xcodeproj/project.pbxproj b/NetNewsWire.xcodeproj/project.pbxproj index 4e8bee760..2e7e8bdf2 100644 --- a/NetNewsWire.xcodeproj/project.pbxproj +++ b/NetNewsWire.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* 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 */; }; 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 */; }; @@ -480,6 +481,7 @@ /* 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 = ""; }; 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 = ""; }; @@ -952,6 +954,7 @@ 849A97511ED9EAC0007D329B /* AddFeedController.swift */, 849A97521ED9EAC0007D329B /* AddFeedWindowController.swift */, 849A97A01ED9F180007D329B /* InitialFeedDownloader.swift */, + 51EC114B2149FE3300B296E3 /* FolderTreeMenu.swift */, 849A97A11ED9F180007D329B /* FolderTreeControllerDelegate.swift */, ); name = "Add Feed"; @@ -1528,8 +1531,8 @@ ORGANIZATIONNAME = "Ranchero Software"; TargetAttributes = { 6581C73220CED60000F4AD34 = { - DevelopmentTeam = M8L2WTLA8W; - ProvisioningStyle = Manual; + DevelopmentTeam = SHJK2V3AJG; + ProvisioningStyle = Automatic; }; 840D617B2029031C009BC708 = { CreatedOnToolsVersion = 9.3; @@ -1550,12 +1553,12 @@ }; 849C645F1ED37A5D003D8FC0 = { CreatedOnToolsVersion = 8.2.1; - DevelopmentTeam = M8L2WTLA8W; - ProvisioningStyle = Manual; + DevelopmentTeam = SHJK2V3AJG; + ProvisioningStyle = Automatic; }; 849C64701ED37A5D003D8FC0 = { CreatedOnToolsVersion = 8.2.1; - DevelopmentTeam = 9C84TZ7Q6Z; + DevelopmentTeam = SHJK2V3AJG; ProvisioningStyle = Automatic; TestTargetID = 849C645F1ED37A5D003D8FC0; }; @@ -2005,6 +2008,7 @@ 84B99C691FAE36B800ECDEDB /* FeedListFolder.swift in Sources */, 84411E711FE5FBFA004B527F /* SmallIconProvider.swift in Sources */, 844B5B591FE9FE4F00C7C76A /* SidebarKeyboardDelegate.swift in Sources */, + 51EC114C2149FE3300B296E3 /* FolderTreeMenu.swift in Sources */, 849A97A31ED9F180007D329B /* FolderTreeControllerDelegate.swift in Sources */, 84A1500320048D660046AD9A /* SendToCommand.swift in Sources */, 845A29091FC74B8E007B49E3 /* SingleFaviconDownloader.swift in Sources */, diff --git a/NetNewsWire/FeedList/FeedList.storyboard b/NetNewsWire/FeedList/FeedList.storyboard index 480c7b595..8b7413366 100644 --- a/NetNewsWire/FeedList/FeedList.storyboard +++ b/NetNewsWire/FeedList/FeedList.storyboard @@ -1,15 +1,16 @@ - + - + + - - + + @@ -32,25 +33,25 @@ - + - + - + - - + + - + @@ -81,7 +82,7 @@ - + @@ -120,21 +121,24 @@ - - + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + - + - + + diff --git a/NetNewsWire/FeedList/FeedListViewController.swift b/NetNewsWire/FeedList/FeedListViewController.swift index 6d7ca1790..c4259c318 100644 --- a/NetNewsWire/FeedList/FeedListViewController.swift +++ b/NetNewsWire/FeedList/FeedListViewController.swift @@ -7,6 +7,7 @@ // import AppKit +import Account import RSTree import RSCore @@ -22,10 +23,12 @@ struct FeedListUserInfoKey { final class FeedListViewController: NSViewController { - @IBOutlet var outlineView: NSOutlineView! - @IBOutlet var openHomePageButton: NSButton! - @IBOutlet var addToFeedsButton: NSButton! - + @IBOutlet weak var outlineView: NSOutlineView! + @IBOutlet weak var openHomePageButton: NSButton! + @IBOutlet weak var addToFeedsButton: NSButton! + @IBOutlet weak var folderPopupButton: NSPopUpButton! + + fileprivate var folderTreeController: TreeController? private var sidebarCellAppearance: SidebarCellAppearance! private let treeControllerDelegate = FeedListTreeControllerDelegate() lazy var treeController: TreeController = { @@ -51,16 +54,24 @@ final class FeedListViewController: NSViewController { sidebarCellAppearance = SidebarCellAppearance(theme: appDelegate.currentTheme, fontSize: AppDefaults.shared.sidebarFontSize) NotificationCenter.default.addObserver(self, selector: #selector(faviconDidBecomeAvailable(_:)), name: .FaviconDidBecomeAvailable, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(childrenDidChange(_:)), name: .ChildrenDidChange, object: nil) + outlineView.needsLayout = true - updateUI() + + updateFolderMenu() + updateButtons() + } // MARK: - Notifications - @objc func faviconDidBecomeAvailable(_ note: Notification) { - configureAvailableCells() } + + @objc func childrenDidChange(_ note: Notification) { + updateFolderMenu() + } + } // MARK: Actions @@ -77,6 +88,51 @@ extension FeedListViewController { @IBAction func addToFeeds(_ sender: Any?) { + guard let container = folderPopupButton.selectedItem?.representedObject as? Container else { + assertionFailure("Expected the folderPopupButton to have a container.") + return + } + + var account: Account? + var folder: Folder? + if container is Folder { + folder = (container as! Folder) + account = folder!.account + } else { + account = (container as! Account) + } + + for selectedObject in selectedObjects { + + guard let feedListFeed = selectedObject as? FeedListFeed else { + continue + } + + 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, {}) + } + } + + } + } } @@ -124,8 +180,8 @@ extension FeedListViewController: NSOutlineViewDelegate { func outlineViewSelectionDidChange(_ notification: Notification) { - updateUI() - + updateButtons() + let selectedRow = self.outlineView.selectedRow if selectedRow < 0 || selectedRow == NSNotFound { @@ -211,11 +267,15 @@ private extension FeedListViewController { NotificationCenter.default.post(name: .FeedListSidebarSelectionDidChange, object: self, userInfo: userInfo) } - func updateUI() { - - updateButtons() + func updateFolderMenu() { + + 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) } - + func updateButtons() { let objects = selectedObjects @@ -223,10 +283,12 @@ private extension FeedListViewController { if objects.isEmpty { openHomePageButton.isEnabled = false addToFeedsButton.isEnabled = false + folderPopupButton.isEnabled = false return } addToFeedsButton.isEnabled = true + folderPopupButton.isEnabled = true if let _ = singleSelectedHomePageURL() { openHomePageButton.isEnabled = true diff --git a/NetNewsWire/MainWindow/AddFeed/AddFeedWindowController.swift b/NetNewsWire/MainWindow/AddFeed/AddFeedWindowController.swift index 78e3f92b0..451f801d7 100644 --- a/NetNewsWire/MainWindow/AddFeed/AddFeedWindowController.swift +++ b/NetNewsWire/MainWindow/AddFeed/AddFeedWindowController.swift @@ -68,7 +68,7 @@ class AddFeedWindowController : NSWindowController { nameTextField.stringValue = initialName } - folderPopupButton.menu = createFolderPopupMenu() + folderPopupButton.menu = FolderTreeMenu.createFolderPopupMenu(with: folderTreeController.rootNode) updateUI() } @@ -139,35 +139,4 @@ private extension AddFeedWindowController { return folderPopupButton.selectedItem?.representedObject as? Container } - func createFolderPopupMenu() -> NSMenu { - - let menu = NSMenu(title: "Folders") - - let menuItem = NSMenuItem(title: NSLocalizedString("Top Level", comment: "Add Feed Sheet"), action: nil, keyEquivalent: "") - menuItem.representedObject = folderTreeController.rootNode.representedObject - menu.addItem(menuItem) - - let childNodes = folderTreeController.rootNode.childNodes - addFolderItemsToMenuWithNodes(menu: menu, nodes: childNodes, indentationLevel: 1) - - return menu - } - - func addFolderItemsToMenuWithNodes(menu: NSMenu, nodes: [Node], indentationLevel: Int) { - - nodes.forEach { (oneNode) in - - if let nameProvider = oneNode.representedObject as? DisplayNameProvider { - - let menuItem = NSMenuItem(title: nameProvider.nameForDisplay, action: nil, keyEquivalent: "") - menuItem.indentationLevel = indentationLevel - menuItem.representedObject = oneNode.representedObject - menu.addItem(menuItem) - - if oneNode.numberOfChildNodes > 0 { - addFolderItemsToMenuWithNodes(menu: menu, nodes: oneNode.childNodes, indentationLevel: indentationLevel + 1) - } - } - } - } } diff --git a/NetNewsWire/MainWindow/AddFeed/FolderTreeMenu.swift b/NetNewsWire/MainWindow/AddFeed/FolderTreeMenu.swift new file mode 100644 index 000000000..5b32307d3 --- /dev/null +++ b/NetNewsWire/MainWindow/AddFeed/FolderTreeMenu.swift @@ -0,0 +1,47 @@ +// +// FolderTreeMenu.swift +// NetNewsWire +// +// Created by Maurice Parker on 9/12/18. +// Copyright © 2018 Ranchero Software, LLC. All rights reserved. +// + +import AppKit +import RSCore +import RSTree + +class FolderTreeMenu { + + static func createFolderPopupMenu(with rootNode: Node) -> NSMenu { + + let menu = NSMenu(title: "Folders") + + let menuItem = NSMenuItem(title: NSLocalizedString("Top Level", comment: "Add Feed Sheet"), action: nil, keyEquivalent: "") + menuItem.representedObject = rootNode.representedObject + menu.addItem(menuItem) + + let childNodes = rootNode.childNodes + addFolderItemsToMenuWithNodes(menu: menu, nodes: childNodes, indentationLevel: 1) + + return menu + } + + private static func addFolderItemsToMenuWithNodes(menu: NSMenu, nodes: [Node], indentationLevel: Int) { + + nodes.forEach { (oneNode) in + + if let nameProvider = oneNode.representedObject as? DisplayNameProvider { + + let menuItem = NSMenuItem(title: nameProvider.nameForDisplay, action: nil, keyEquivalent: "") + menuItem.indentationLevel = indentationLevel + menuItem.representedObject = oneNode.representedObject + menu.addItem(menuItem) + + if oneNode.numberOfChildNodes > 0 { + addFolderItemsToMenuWithNodes(menu: menu, nodes: oneNode.childNodes, indentationLevel: indentationLevel + 1) + } + } + } + } + +} From 3a4abb6d6ebb812526bc76659a62f72ee2910da8 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Thu, 13 Sep 2018 07:15:26 -0500 Subject: [PATCH 2/7] Rolledback changes to the Feed List (directory) window. --- NetNewsWire/FeedList/FeedList.storyboard | 82 ++++++----------- .../FeedList/FeedListViewController.swift | 88 +++---------------- 2 files changed, 39 insertions(+), 131 deletions(-) diff --git a/NetNewsWire/FeedList/FeedList.storyboard b/NetNewsWire/FeedList/FeedList.storyboard index 8b7413366..480c7b595 100644 --- a/NetNewsWire/FeedList/FeedList.storyboard +++ b/NetNewsWire/FeedList/FeedList.storyboard @@ -1,16 +1,15 @@ - + - - + - - + + @@ -33,25 +32,25 @@ - + - + - + - - + + - + @@ -82,7 +81,7 @@ - + @@ -121,24 +120,21 @@ - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - + - + - diff --git a/NetNewsWire/FeedList/FeedListViewController.swift b/NetNewsWire/FeedList/FeedListViewController.swift index c4259c318..6d7ca1790 100644 --- a/NetNewsWire/FeedList/FeedListViewController.swift +++ b/NetNewsWire/FeedList/FeedListViewController.swift @@ -7,7 +7,6 @@ // import AppKit -import Account import RSTree import RSCore @@ -23,12 +22,10 @@ struct FeedListUserInfoKey { final class FeedListViewController: NSViewController { - @IBOutlet weak var outlineView: NSOutlineView! - @IBOutlet weak var openHomePageButton: NSButton! - @IBOutlet weak var addToFeedsButton: NSButton! - @IBOutlet weak var folderPopupButton: NSPopUpButton! - - fileprivate var folderTreeController: TreeController? + @IBOutlet var outlineView: NSOutlineView! + @IBOutlet var openHomePageButton: NSButton! + @IBOutlet var addToFeedsButton: NSButton! + private var sidebarCellAppearance: SidebarCellAppearance! private let treeControllerDelegate = FeedListTreeControllerDelegate() lazy var treeController: TreeController = { @@ -54,24 +51,16 @@ final class FeedListViewController: NSViewController { sidebarCellAppearance = SidebarCellAppearance(theme: appDelegate.currentTheme, fontSize: AppDefaults.shared.sidebarFontSize) NotificationCenter.default.addObserver(self, selector: #selector(faviconDidBecomeAvailable(_:)), name: .FaviconDidBecomeAvailable, object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(childrenDidChange(_:)), name: .ChildrenDidChange, object: nil) - outlineView.needsLayout = true - - updateFolderMenu() - updateButtons() - + updateUI() } // MARK: - Notifications + @objc func faviconDidBecomeAvailable(_ note: Notification) { + configureAvailableCells() } - - @objc func childrenDidChange(_ note: Notification) { - updateFolderMenu() - } - } // MARK: Actions @@ -88,51 +77,6 @@ extension FeedListViewController { @IBAction func addToFeeds(_ sender: Any?) { - guard let container = folderPopupButton.selectedItem?.representedObject as? Container else { - assertionFailure("Expected the folderPopupButton to have a container.") - return - } - - var account: Account? - var folder: Folder? - if container is Folder { - folder = (container as! Folder) - account = folder!.account - } else { - account = (container as! Account) - } - - for selectedObject in selectedObjects { - - guard let feedListFeed = selectedObject as? FeedListFeed else { - continue - } - - 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, {}) - } - } - - } - } } @@ -180,8 +124,8 @@ extension FeedListViewController: NSOutlineViewDelegate { func outlineViewSelectionDidChange(_ notification: Notification) { - updateButtons() - + updateUI() + let selectedRow = self.outlineView.selectedRow if selectedRow < 0 || selectedRow == NSNotFound { @@ -267,15 +211,11 @@ private extension FeedListViewController { NotificationCenter.default.post(name: .FeedListSidebarSelectionDidChange, object: self, userInfo: userInfo) } - func updateFolderMenu() { - - 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) + func updateUI() { + + updateButtons() } - + func updateButtons() { let objects = selectedObjects @@ -283,12 +223,10 @@ private extension FeedListViewController { if objects.isEmpty { openHomePageButton.isEnabled = false addToFeedsButton.isEnabled = false - folderPopupButton.isEnabled = false return } addToFeedsButton.isEnabled = true - folderPopupButton.isEnabled = true if let _ = singleSelectedHomePageURL() { openHomePageButton.isEnabled = true From d34e5916ad774fd1cea7e8c4340030c94d9e09ca Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Thu, 13 Sep 2018 10:04:20 -0500 Subject: [PATCH 3/7] Enabled "Add to Feeds" button on Feed Directory. Issue #105 --- NetNewsWire.xcodeproj/project.pbxproj | 16 +++ NetNewsWire/AppDelegate.swift | 13 ++ .../Base.lproj/AddFeedFromListSheet.xib | 107 +++++++++++++++ .../FeedList/FeedListViewController.swift | 4 +- .../AddFeedFromListWindowController.swift | 122 ++++++++++++++++++ 5 files changed, 261 insertions(+), 1 deletion(-) create mode 100644 NetNewsWire/Base.lproj/AddFeedFromListSheet.xib create mode 100644 NetNewsWire/MainWindow/AddFeed/AddFeedFromListWindowController.swift 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) + } + + } + +} From 7c37ed5d882296a6c3d15bdd6ef4586f57d82a9e Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Thu, 13 Sep 2018 15:00:33 -0500 Subject: [PATCH 4/7] Changed the Mark as Read toolbar item to toggle back and forth between read and unread states. Issue #46. --- NetNewsWire/Base.lproj/MainWindow.storyboard | 14 +++---- .../MainWindow/MainWindowController.swift | 38 ++++++++++++++++--- .../Timeline/TimelineViewController.swift | 23 +++++++++++ 3 files changed, 62 insertions(+), 13 deletions(-) diff --git a/NetNewsWire/Base.lproj/MainWindow.storyboard b/NetNewsWire/Base.lproj/MainWindow.storyboard index 76c995b0b..b44312305 100644 --- a/NetNewsWire/Base.lproj/MainWindow.storyboard +++ b/NetNewsWire/Base.lproj/MainWindow.storyboard @@ -1,8 +1,8 @@ - + - + @@ -120,7 +120,7 @@ - + @@ -349,11 +349,11 @@ -