From b78406073cd66f5bfaa45732e010fdfb00b2fdda Mon Sep 17 00:00:00 2001 From: Brent Simmons Date: Mon, 3 Sep 2018 22:33:00 -0700 Subject: [PATCH] Start work on a default-RSS-reader popup menu in the preferences window, so people can make NetNewsWire their default reader. --- NetNewsWire.xcodeproj/project.pbxproj | 4 + NetNewsWire/Base.lproj/Preferences.storyboard | 56 +++++++++--- .../GeneralPrefencesViewController.swift | 86 +++++++++++++++++++ 3 files changed, 132 insertions(+), 14 deletions(-) create mode 100644 NetNewsWire/Preferences/GeneralPrefencesViewController.swift diff --git a/NetNewsWire.xcodeproj/project.pbxproj b/NetNewsWire.xcodeproj/project.pbxproj index b1a1f3611..86238525b 100644 --- a/NetNewsWire.xcodeproj/project.pbxproj +++ b/NetNewsWire.xcodeproj/project.pbxproj @@ -59,6 +59,7 @@ 846E773E1F6EF67A00A165E2 /* Account.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 846E773A1F6EF5D700A165E2 /* Account.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 84702AA41FA27AC0006B8943 /* MarkStatusCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84702AA31FA27AC0006B8943 /* MarkStatusCommand.swift */; }; 8472058120142E8900AD578B /* FeedInspectorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8472058020142E8900AD578B /* FeedInspectorViewController.swift */; }; + 84754C8A213E471B009CFDFB /* GeneralPrefencesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84754C89213E471B009CFDFB /* GeneralPrefencesViewController.swift */; }; 847FA121202BA34100BB56C8 /* SidebarContextualMenuDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 847FA120202BA34100BB56C8 /* SidebarContextualMenuDelegate.swift */; }; 848F6AE51FC29CFB002D422E /* FaviconDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 848F6AE41FC29CFA002D422E /* FaviconDownloader.swift */; }; 849A97431ED9EAA9007D329B /* AddFolderWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 849A97421ED9EAA9007D329B /* AddFolderWindowController.swift */; }; @@ -538,6 +539,7 @@ 846E77301F6EF5D600A165E2 /* Account.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Account.xcodeproj; path = Frameworks/Account/Account.xcodeproj; sourceTree = ""; }; 84702AA31FA27AC0006B8943 /* MarkStatusCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MarkStatusCommand.swift; sourceTree = ""; }; 8472058020142E8900AD578B /* FeedInspectorViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedInspectorViewController.swift; sourceTree = ""; }; + 84754C89213E471B009CFDFB /* GeneralPrefencesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = GeneralPrefencesViewController.swift; path = NetNewsWire/Preferences/GeneralPrefencesViewController.swift; sourceTree = ""; }; 847752FE2008879500D93690 /* CoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreServices.framework; path = System/Library/Frameworks/CoreServices.framework; sourceTree = SDKROOT; }; 847FA120202BA34100BB56C8 /* SidebarContextualMenuDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SidebarContextualMenuDelegate.swift; sourceTree = ""; }; 848F6AE41FC29CFA002D422E /* FaviconDownloader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FaviconDownloader.swift; sourceTree = ""; }; @@ -814,6 +816,7 @@ children = ( 849A97A41ED9F94D007D329B /* Preferences.storyboard */, 849A97841ED9ECCD007D329B /* PreferencesWindowController.swift */, + 84754C89213E471B009CFDFB /* GeneralPrefencesViewController.swift */, ); name = Preferences; sourceTree = ""; @@ -1922,6 +1925,7 @@ D5A2678C20130ECF00A8D3C0 /* Author+Scriptability.swift in Sources */, 84F2D5371FC22FCC00998D64 /* PseudoFeed.swift in Sources */, D57BE6E0204CD35F00D11AAC /* NSScriptCommand+NetNewsWire.swift in Sources */, + 84754C8A213E471B009CFDFB /* GeneralPrefencesViewController.swift in Sources */, D553738B20186C20006D8857 /* Article+Scriptability.swift in Sources */, 845EE7C11FC2488C00854A1F /* SmartFeed.swift in Sources */, 84702AA41FA27AC0006B8943 /* MarkStatusCommand.swift in Sources */, diff --git a/NetNewsWire/Base.lproj/Preferences.storyboard b/NetNewsWire/Base.lproj/Preferences.storyboard index 7db1ae995..e8c176cbb 100644 --- a/NetNewsWire/Base.lproj/Preferences.storyboard +++ b/NetNewsWire/Base.lproj/Preferences.storyboard @@ -1,15 +1,16 @@ - + - + + - - + + @@ -29,22 +30,22 @@ - + - + - + - + - + @@ -63,17 +64,41 @@ - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + diff --git a/NetNewsWire/Preferences/GeneralPrefencesViewController.swift b/NetNewsWire/Preferences/GeneralPrefencesViewController.swift new file mode 100644 index 000000000..59b8f9c25 --- /dev/null +++ b/NetNewsWire/Preferences/GeneralPrefencesViewController.swift @@ -0,0 +1,86 @@ +// +// GeneralPrefencesViewController.swift +// NetNewsWire +// +// Created by Brent Simmons on 9/3/18. +// Copyright © 2018 Ranchero Software. All rights reserved. +// + +import AppKit +import RSCore + +final class GeneralPreferencesViewController: NSViewController { + + @IBOutlet var defaultRSSReaderPopup: NSPopUpButton! + static let feedURLScheme = "feed:" + static let feedsURLScheme = "feeds:" + + override func viewWillAppear() { + updateRSSReaderPopup() + } +} + +private extension GeneralPreferencesViewController { + + func updateRSSReaderPopup() { + let rssReaders = fetchRSSReaders() + print(rssReaders) + } + + func fetchRSSReaders() -> Set { + let defaultRSSReaderBundleID = NSWorkspace.shared.defaultAppBundleID(forURLScheme: GeneralPreferencesViewController.feedURLScheme) + let rssReaderBundleIDs = NSWorkspace.shared.bundleIDsForApps(forURLScheme: GeneralPreferencesViewController.feedURLScheme) + + var allReaders = Set() + if let defaultRSSReaderBundleID = defaultRSSReaderBundleID, let defaultReader = RSSReader(bundleID: defaultRSSReaderBundleID, isDefaultReader: true) { + allReaders.insert(defaultReader) + } + rssReaderBundleIDs.forEach { (bundleID) in + let isDefault = bundleID == defaultRSSReaderBundleID + if let reader = RSSReader(bundleID: bundleID, isDefaultReader: isDefault) { + allReaders.insert(reader) + } + } + return allReaders + } +} + +private final class RSSReader: Hashable { + + let bundleID: String + let name: String + let nameMinusAppSuffix: String + let path: String + let isDefaultReader: Bool + + init?(bundleID: String, isDefaultReader: Bool) { + guard let path = NSWorkspace.shared.absolutePathForApplication(withBundleIdentifier: bundleID) else { + return nil + } + + self.path = path + self.bundleID = bundleID + self.isDefaultReader = isDefaultReader + + let name = (path as NSString).lastPathComponent + self.name = name + if name.hasSuffix(".app") { + self.nameMinusAppSuffix = name.rs_string(byStrippingSuffix: ".app", caseSensitive: false) + } + else { + self.nameMinusAppSuffix = name + } + } + + // MARK: - Hashable + + func hash(into hasher: inout Hasher) { + hasher.combine(bundleID) + } + + // MARK: - Equatable + + static func ==(lhs: RSSReader, rhs: RSSReader) -> Bool { + return lhs.bundleID == rhs.bundleID + } +}