From 06e91aa8b798214fe9d57fbd15d5eb8ffa31e892 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Sun, 10 May 2020 11:44:30 -0500 Subject: [PATCH] Add the Add Reddit Feed dialog --- .../Reddit/RedditFeedProvider.swift | 47 ++++- Mac/AppDelegate.swift | 12 ++ Mac/Base.lproj/AddRedditFeedSheet.xib | 199 ++++++++++++++++++ Mac/Base.lproj/AddTwitterFeedSheet.xib | 6 +- Mac/Base.lproj/Main.storyboard | 6 + .../AddFeed/AddFeedController.swift | 3 + .../AddFeed/AddFeedWIndowController.swift | 1 + .../AddTwitterFeedWindowController.swift | 1 - .../AddRedditFeedWindowController.swift | 177 ++++++++++++++++ NetNewsWire.xcodeproj/project.pbxproj | 20 ++ .../RedditFeedProvider-Extensions.swift | 2 +- 11 files changed, 468 insertions(+), 6 deletions(-) create mode 100644 Mac/Base.lproj/AddRedditFeedSheet.xib create mode 100644 Mac/MainWindow/AddRedditFeedWindowController.swift diff --git a/Frameworks/Account/FeedProvider/Reddit/RedditFeedProvider.swift b/Frameworks/Account/FeedProvider/Reddit/RedditFeedProvider.swift index 3cab2a4f9..9886f95bb 100644 --- a/Frameworks/Account/FeedProvider/Reddit/RedditFeedProvider.swift +++ b/Frameworks/Account/FeedProvider/Reddit/RedditFeedProvider.swift @@ -27,6 +27,13 @@ public enum RedditFeedProviderError: LocalizedError { } } +public enum RedditFeedType: Int { + case home = 0 + case popular = 1 + case all = 2 + case subreddit = 3 +} + public final class RedditFeedProvider: FeedProvider { var log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "RedditFeedProvider") @@ -163,7 +170,12 @@ public final class RedditFeedProvider: FeedProvider { return } - let api = "\(urlComponents.path).json" + let api: String + if urlComponents.path.isEmpty { + api = "/.json" + } else { + api = "\(urlComponents.path).json" + } let splitPath = urlComponents.path.split(separator: "/") let identifySubreddit: Bool @@ -215,6 +227,39 @@ public final class RedditFeedProvider: FeedProvider { } } + public static func buildURL(_ type: RedditFeedType, username: String?, subreddit: String?) -> URL? { + var components = URLComponents() + components.scheme = "https" + components.host = "www.reddit.com" + + switch type { + case .home: + guard let username = username else { + return nil + } + components.user = username + case .popular: + guard let username = username else { + return nil + } + components.user = username + components.path = "/r/popular" + case .all: + guard let username = username else { + return nil + } + components.user = username + components.path = "/r/all" + case .subreddit: + guard let subreddit = subreddit else { + return nil + } + components.path = "/r/\(subreddit)" + } + + return components.url + } + } // MARK: OAuth1SwiftProvider diff --git a/Mac/AppDelegate.swift b/Mac/AppDelegate.swift index 9b6b86094..94aa2d8ee 100644 --- a/Mac/AppDelegate.swift +++ b/Mac/AppDelegate.swift @@ -403,6 +403,12 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, if item.action == #selector(showAddWebFeedWindow(_:)) || item.action == #selector(showAddFolderWindow(_:)) { return !isDisplayingSheet && !AccountManager.shared.activeAccounts.isEmpty } + if item.action == #selector(showAddRedditFeedWindow(_:)) { + guard !isDisplayingSheet && !AccountManager.shared.activeAccounts.isEmpty else { + return false + } + return ExtensionPointManager.shared.isRedditEnabled + } if item.action == #selector(showAddTwitterFeedWindow(_:)) { guard !isDisplayingSheet && !AccountManager.shared.activeAccounts.isEmpty else { return false @@ -471,6 +477,12 @@ class AppDelegate: NSObject, NSApplicationDelegate, NSUserInterfaceValidations, addWebFeed(nil) } + @IBAction func showAddRedditFeedWindow(_ sender: Any?) { + createAndShowMainWindowIfNecessary() + addFeedController = AddFeedController(hostWindow: mainWindowController!.window!) + addFeedController?.showAddFeedSheet(.redditFeed) + } + @IBAction func showAddTwitterFeedWindow(_ sender: Any?) { createAndShowMainWindowIfNecessary() addFeedController = AddFeedController(hostWindow: mainWindowController!.window!) diff --git a/Mac/Base.lproj/AddRedditFeedSheet.xib b/Mac/Base.lproj/AddRedditFeedSheet.xib new file mode 100644 index 000000000..cdffd1ec3 --- /dev/null +++ b/Mac/Base.lproj/AddRedditFeedSheet.xib @@ -0,0 +1,199 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Mac/Base.lproj/AddTwitterFeedSheet.xib b/Mac/Base.lproj/AddTwitterFeedSheet.xib index 9e04ecb71..b23bb43bf 100644 --- a/Mac/Base.lproj/AddTwitterFeedSheet.xib +++ b/Mac/Base.lproj/AddTwitterFeedSheet.xib @@ -91,12 +91,12 @@ DQ - + - + @@ -115,7 +115,7 @@ DQ - + diff --git a/Mac/Base.lproj/Main.storyboard b/Mac/Base.lproj/Main.storyboard index 5b2a00ebe..e646f425e 100644 --- a/Mac/Base.lproj/Main.storyboard +++ b/Mac/Base.lproj/Main.storyboard @@ -73,6 +73,12 @@ + + + + + + diff --git a/Mac/MainWindow/AddFeed/AddFeedController.swift b/Mac/MainWindow/AddFeed/AddFeedController.swift index 722018deb..19a444ad9 100644 --- a/Mac/MainWindow/AddFeed/AddFeedController.swift +++ b/Mac/MainWindow/AddFeed/AddFeedController.swift @@ -44,6 +44,9 @@ class AddFeedController: AddFeedWindowControllerDelegate { folder: folder, folderTreeController: folderTreeController, delegate: self) + case .redditFeed: + addFeedWindowController = AddRedditFeedWindowController(folderTreeController: folderTreeController, + delegate: self) case .twitterFeed: addFeedWindowController = AddTwitterFeedWindowController(folderTreeController: folderTreeController, delegate: self) diff --git a/Mac/MainWindow/AddFeed/AddFeedWIndowController.swift b/Mac/MainWindow/AddFeed/AddFeedWIndowController.swift index f37b873a4..cbeddaa55 100644 --- a/Mac/MainWindow/AddFeed/AddFeedWIndowController.swift +++ b/Mac/MainWindow/AddFeed/AddFeedWIndowController.swift @@ -11,6 +11,7 @@ import Account enum AddFeedWindowControllerType { case webFeed + case redditFeed case twitterFeed } diff --git a/Mac/MainWindow/AddFeed/AddTwitterFeedWindowController.swift b/Mac/MainWindow/AddFeed/AddTwitterFeedWindowController.swift index c6e7bd04f..7698659fd 100644 --- a/Mac/MainWindow/AddFeed/AddTwitterFeedWindowController.swift +++ b/Mac/MainWindow/AddFeed/AddTwitterFeedWindowController.swift @@ -25,7 +25,6 @@ class AddTwitterFeedWindowController : NSWindowController, AddFeedWindowControll @IBOutlet var addButton: NSButton! @IBOutlet var folderPopupButton: NSPopUpButton! - private var urlString: String? private weak var delegate: AddFeedWindowControllerDelegate? private var folderTreeController: TreeController! diff --git a/Mac/MainWindow/AddRedditFeedWindowController.swift b/Mac/MainWindow/AddRedditFeedWindowController.swift new file mode 100644 index 000000000..bab6760e2 --- /dev/null +++ b/Mac/MainWindow/AddRedditFeedWindowController.swift @@ -0,0 +1,177 @@ +// +// AddRedditFeedWindowController.swift +// NetNewsWire +// +// Created by Maurice Parker on 5/10/20. +// Copyright © 2020 Ranchero Software. All rights reserved. +// + +import AppKit +import RSCore +import RSTree +import Articles +import Account + +class AddRedditFeedWindowController : NSWindowController, AddFeedWindowController { + + @IBOutlet weak var typePopupButton: NSPopUpButton! + @IBOutlet weak var typeDescriptionLabel: NSTextField! + + @IBOutlet weak var accountLabel: NSTextField! + @IBOutlet weak var accountPopupButton: NSPopUpButton! + @IBOutlet weak var subredditTextField: NSTextField! + + @IBOutlet var nameTextField: NSTextField! + @IBOutlet var addButton: NSButton! + @IBOutlet var folderPopupButton: NSPopUpButton! + + private weak var delegate: AddFeedWindowControllerDelegate? + private var folderTreeController: TreeController! + + private var userEnteredSubreddit: String? { + var s = subredditTextField.stringValue + s = s.collapsingWhitespace + if s.isEmpty { + return nil + } + return s + } + + private var userEnteredTitle: String? { + var s = nameTextField.stringValue + s = s.collapsingWhitespace + if s.isEmpty { + return nil + } + return s + } + + var hostWindow: NSWindow! + + convenience init(folderTreeController: TreeController, delegate: AddFeedWindowControllerDelegate?) { + self.init(windowNibName: NSNib.Name("AddRedditFeedSheet")) + self.folderTreeController = folderTreeController + self.delegate = delegate + } + + func runSheetOnWindow(_ hostWindow: NSWindow) { + hostWindow.beginSheet(window!) { (returnCode: NSApplication.ModalResponse) -> Void in + } + } + + override func windowDidLoad() { + + let accountMenu = NSMenu() + for feedProvider in ExtensionPointManager.shared.activeFeedProviders { + if let redditFeedProvider = feedProvider as? RedditFeedProvider { + let accountMenuItem = NSMenuItem() + accountMenuItem.title = redditFeedProvider.title + accountMenu.addItem(accountMenuItem) + } + } + accountPopupButton.menu = accountMenu + + folderPopupButton.menu = FolderTreeMenu.createFolderPopupMenu(with: folderTreeController.rootNode) + + if let container = AddWebFeedDefaultContainer.defaultContainer { + if let folder = container as? Folder, let account = folder.account { + FolderTreeMenu.select(account: account, folder: folder, in: folderPopupButton) + } else { + if let account = container as? Account { + FolderTreeMenu.select(account: account, folder: nil, in: folderPopupButton) + } + } + } + + updateUI() + } + + // MARK: Actions + + @IBAction func selectedType(_ sender: Any) { + subredditTextField.stringValue = "" + updateUI() + } + + @IBAction func cancel(_ sender: Any?) { + cancelSheet() + } + + @IBAction func addFeed(_ sender: Any?) { + guard let type = RedditFeedType(rawValue: typePopupButton.selectedItem?.tag ?? 0), + let atUsername = accountPopupButton.selectedItem?.title else { return } + + let username = String(atUsername[atUsername.index(atUsername.startIndex, offsetBy: 2).. Container? { + return folderPopupButton.selectedItem?.representedObject as? Container + } +} diff --git a/NetNewsWire.xcodeproj/project.pbxproj b/NetNewsWire.xcodeproj/project.pbxproj index 55d921e13..a36afc3b2 100644 --- a/NetNewsWire.xcodeproj/project.pbxproj +++ b/NetNewsWire.xcodeproj/project.pbxproj @@ -93,6 +93,10 @@ 51314705235C41FC00387FDC /* Intents.intentdefinition in Sources */ = {isa = PBXBuildFile; fileRef = 51314707235C41FC00387FDC /* Intents.intentdefinition */; }; 513228FB233037630033D4ED /* Reachability.swift in Sources */ = {isa = PBXBuildFile; fileRef = 513228F2233037620033D4ED /* Reachability.swift */; }; 513228FC233037630033D4ED /* Reachability.swift in Sources */ = {isa = PBXBuildFile; fileRef = 513228F2233037620033D4ED /* Reachability.swift */; }; + 51333D1624685D2E00EB5C91 /* AddRedditFeedWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51333D1524685D2E00EB5C91 /* AddRedditFeedWindowController.swift */; }; + 51333D1724685D2E00EB5C91 /* AddRedditFeedWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51333D1524685D2E00EB5C91 /* AddRedditFeedWindowController.swift */; }; + 51333D3B2468615D00EB5C91 /* AddRedditFeedSheet.xib in Resources */ = {isa = PBXBuildFile; fileRef = 51333D392468615D00EB5C91 /* AddRedditFeedSheet.xib */; }; + 51333D3C2468615D00EB5C91 /* AddRedditFeedSheet.xib in Resources */ = {isa = PBXBuildFile; fileRef = 51333D392468615D00EB5C91 /* AddRedditFeedSheet.xib */; }; 513C5CE9232571C2003D4054 /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 513C5CE8232571C2003D4054 /* ShareViewController.swift */; }; 513C5CEC232571C2003D4054 /* MainInterface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 513C5CEA232571C2003D4054 /* MainInterface.storyboard */; }; 513C5CF0232571C2003D4054 /* NetNewsWire iOS Share Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 513C5CE6232571C2003D4054 /* NetNewsWire iOS Share Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; @@ -1441,6 +1445,8 @@ 51314706235C41FC00387FDC /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.intentdefinition; name = Base; path = Base.lproj/Intents.intentdefinition; sourceTree = ""; }; 51314714235C420900387FDC /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Intents.strings; sourceTree = ""; }; 513228F2233037620033D4ED /* Reachability.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Reachability.swift; sourceTree = ""; }; + 51333D1524685D2E00EB5C91 /* AddRedditFeedWindowController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AddRedditFeedWindowController.swift; sourceTree = ""; }; + 51333D3A2468615D00EB5C91 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Mac/Base.lproj/AddRedditFeedSheet.xib; sourceTree = SOURCE_ROOT; }; 513C5CE6232571C2003D4054 /* NetNewsWire iOS Share Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "NetNewsWire iOS Share Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; 513C5CE8232571C2003D4054 /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = ""; }; 513C5CEB232571C2003D4054 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainInterface.storyboard; sourceTree = ""; }; @@ -2563,6 +2569,8 @@ children = ( 849A97511ED9EAC0007D329B /* AddFeedController.swift */, 51A052CD244FB9D6006C2024 /* AddFeedWIndowController.swift */, + 51333D392468615D00EB5C91 /* AddRedditFeedSheet.xib */, + 51333D1524685D2E00EB5C91 /* AddRedditFeedWindowController.swift */, 514A897F244FD63F0085E65D /* AddTwitterFeedSheet.xib */, 514A89A4244FD6640085E65D /* AddTwitterFeedWindowController.swift */, 848363002262A3BC00DA1D35 /* AddWebFeedSheet.xib */, @@ -3806,6 +3814,7 @@ 514A89A3244FD63F0085E65D /* AddTwitterFeedSheet.xib in Resources */, 5103A9F5242258C600410853 /* AccountsAddCloudKit.xib in Resources */, 65ED405E235DEF6C0081F399 /* DefaultFeeds.opml in Resources */, + 51333D3C2468615D00EB5C91 /* AddRedditFeedSheet.xib in Resources */, 65ED405F235DEF6C0081F399 /* Preferences.storyboard in Resources */, 65ED4061235DEF6C0081F399 /* Assets.xcassets in Resources */, 65ED4062235DEF6C0081F399 /* styleSheet.css in Resources */, @@ -3915,6 +3924,7 @@ 55E15BCB229D65A900D6602A /* AccountsReaderAPI.xib in Resources */, 49F40DF82335B71000552BF4 /* newsfoot.js in Resources */, 510C43ED243C0973009F70C3 /* ExtensionPointAdd.xib in Resources */, + 51333D3B2468615D00EB5C91 /* AddRedditFeedSheet.xib in Resources */, BDCB516724282C8A00102A80 /* AccountsNewsBlur.xib in Resources */, 514A89A2244FD63F0085E65D /* AddTwitterFeedSheet.xib in Resources */, 5103A9982421643300410853 /* blank.html in Resources */, @@ -4127,6 +4137,7 @@ 65ED3FD4235DEF6C0081F399 /* Article+Scriptability.swift in Sources */, 515A5172243E802B0089E588 /* ExtensionPointDetailViewController.swift in Sources */, 65ED3FD5235DEF6C0081F399 /* SmartFeed.swift in Sources */, + 51333D1724685D2E00EB5C91 /* AddRedditFeedWindowController.swift in Sources */, 65ED3FD6235DEF6C0081F399 /* MarkStatusCommand.swift in Sources */, 65ED3FD7235DEF6C0081F399 /* NSApplication+Scriptability.swift in Sources */, 65ED3FD8235DEF6C0081F399 /* NSView-Extensions.swift in Sources */, @@ -4573,6 +4584,7 @@ 849A97541ED9EAC0007D329B /* AddWebFeedWindowController.swift in Sources */, 5144EA40227A37EC00D19003 /* ImportOPMLWindowController.swift in Sources */, 849A976D1ED9EBC8007D329B /* TimelineTableView.swift in Sources */, + 51333D1624685D2E00EB5C91 /* AddRedditFeedWindowController.swift in Sources */, 84D52E951FE588BB00D14F5B /* DetailStatusBarView.swift in Sources */, D5E4CC64202C1AC1009B4FFC /* MainWindowController+Scriptability.swift in Sources */, 51A052CE244FB9D7006C2024 /* AddFeedWIndowController.swift in Sources */, @@ -4789,6 +4801,14 @@ name = Intents.intentdefinition; sourceTree = ""; }; + 51333D392468615D00EB5C91 /* AddRedditFeedSheet.xib */ = { + isa = PBXVariantGroup; + children = ( + 51333D3A2468615D00EB5C91 /* Base */, + ); + name = AddRedditFeedSheet.xib; + sourceTree = ""; + }; 513C5CEA232571C2003D4054 /* MainInterface.storyboard */ = { isa = PBXVariantGroup; children = ( diff --git a/Shared/ExtensionPoints/RedditFeedProvider-Extensions.swift b/Shared/ExtensionPoints/RedditFeedProvider-Extensions.swift index d9bd6187c..bde0735cc 100644 --- a/Shared/ExtensionPoints/RedditFeedProvider-Extensions.swift +++ b/Shared/ExtensionPoints/RedditFeedProvider-Extensions.swift @@ -30,7 +30,7 @@ extension RedditFeedProvider: ExtensionPoint { guard let username = username else { fatalError() } - return "/u/\(username)" + return "u/\(username)" } }