From eccfd5e15bb0d6a06f0cc83a1b8eb6d0d22b62d3 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Fri, 14 Aug 2020 10:25:55 -0500 Subject: [PATCH] Finish macOS Share Extension --- .../Base.lproj/ShareViewController.xib | 6 +- Mac/ShareExtension/Info.plist | 7 +- .../ShareExtension.entitlements | 2 +- Mac/ShareExtension/ShareViewController.swift | 112 +++++++++++++++--- NetNewsWire.xcodeproj/project.pbxproj | 12 +- {iOS => Shared}/ShareExtension/SafariExt.js | 0 6 files changed, 115 insertions(+), 24 deletions(-) rename {iOS => Shared}/ShareExtension/SafariExt.js (100%) diff --git a/Mac/ShareExtension/Base.lproj/ShareViewController.xib b/Mac/ShareExtension/Base.lproj/ShareViewController.xib index 611398d9a..f1388f882 100644 --- a/Mac/ShareExtension/Base.lproj/ShareViewController.xib +++ b/Mac/ShareExtension/Base.lproj/ShareViewController.xib @@ -8,6 +8,8 @@ + + @@ -82,7 +84,7 @@ Gw - + @@ -122,6 +124,7 @@ Gw + @@ -130,7 +133,6 @@ Gw - diff --git a/Mac/ShareExtension/Info.plist b/Mac/ShareExtension/Info.plist index e9c8754fa..2ff6da1ee 100644 --- a/Mac/ShareExtension/Info.plist +++ b/Mac/ShareExtension/Info.plist @@ -35,7 +35,12 @@ NSExtensionAttributes NSExtensionActivationRule - TRUEPREDICATE + + NSExtensionActivationSupportsWebURLWithMaxCount + 1 + + NSExtensionJavaScriptPreprocessingFile + SafariExt NSExtensionPointIdentifier com.apple.share-services diff --git a/Mac/ShareExtension/ShareExtension.entitlements b/Mac/ShareExtension/ShareExtension.entitlements index c05386c66..5892e177a 100644 --- a/Mac/ShareExtension/ShareExtension.entitlements +++ b/Mac/ShareExtension/ShareExtension.entitlements @@ -8,7 +8,7 @@ com.apple.security.application-groups - group.$(ORGANIZATION_IDENTIFIER).NetNewsWire-Evergreen + group.$(ORGANIZATION_IDENTIFIER).NetNewsWire diff --git a/Mac/ShareExtension/ShareViewController.swift b/Mac/ShareExtension/ShareViewController.swift index bf0ef02c8..2d7558063 100644 --- a/Mac/ShareExtension/ShareViewController.swift +++ b/Mac/ShareExtension/ShareViewController.swift @@ -7,14 +7,17 @@ // import Cocoa +import os.log class ShareViewController: NSViewController { + @IBOutlet weak var nameTextField: NSTextField! + @IBOutlet weak var folderPopUpButton: NSPopUpButton! + private var url: URL? private var extensionContainers: ExtensionContainers? - private var flattenedContainers: [ExtensionContainer]! - private var selectedContainer: ExtensionContainer? - + private var log = OSLog(subsystem: Bundle.main.bundleIdentifier!, category: "ShareViewController") + override var nibName: NSNib.Name? { return NSNib.Name("ShareViewController") } @@ -23,14 +26,38 @@ class ShareViewController: NSViewController { super.loadView() extensionContainers = ExtensionContainersFile.read() - flattenedContainers = extensionContainers?.flattened ?? [ExtensionContainer]() - if let extensionContainers = extensionContainers { - selectedContainer = ShareDefaultContainer.defaultContainer(containers: extensionContainers) - } - + buildFolderPopupMenu() + var provider: NSItemProvider? = nil - // Try to get the URL if it is passed in + // Try to get any HTML that is maybe passed in + for item in self.extensionContext!.inputItems as! [NSExtensionItem] { + for itemProvider in item.attachments! { + if itemProvider.hasItemConformingToTypeIdentifier(kUTTypePropertyList as String) { + provider = itemProvider + } + } + } + + if provider != nil { + provider!.loadItem(forTypeIdentifier: kUTTypePropertyList as String, options: nil, completionHandler: { [weak self] (pList, error) in + if error != nil { + return + } + guard let dataGraph = pList as? NSDictionary else { + return + } + guard let results = dataGraph["NSExtensionJavaScriptPreprocessingResultsKey"] as? NSDictionary else { + return + } + if let url = URL(string: results["url"] as! String) { + self?.url = url + } + }) + return + } + + // Try to get the URL if it is passed in as a URL for item in self.extensionContext!.inputItems as! [NSExtensionItem] { for itemProvider in item.attachments! { if itemProvider.hasItemConformingToTypeIdentifier(kUTTypeURL as String) { @@ -44,24 +71,27 @@ class ShareViewController: NSViewController { if error != nil { return } - guard let url = urlCoded as? URL else { + if let url = urlCoded as? URL { + self?.url = url return } - self?.url = url + if let urlData = urlCoded as? Data { + self?.url = URL(dataRepresentation: urlData, relativeTo: nil) + } }) } } @IBAction func send(_ sender: AnyObject?) { - guard let url = url, let selectedContainer = selectedContainer, let containerID = selectedContainer.containerID else { + guard let url = url, let selectedContainer = selectedContainer(), let containerID = selectedContainer.containerID else { self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil) return } -// let name = contentText.isEmpty ? nil : contentText -// let request = ExtensionFeedAddRequest(name: name, feedURL: url, destinationContainerID: containerID) -// ExtensionFeedAddRequestFile.save(request) + let name = nameTextField.stringValue.isEmpty ? nil : nameTextField.stringValue + let request = ExtensionFeedAddRequest(name: name, feedURL: url, destinationContainerID: containerID) + ExtensionFeedAddRequestFile.save(request) self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil) } @@ -72,3 +102,55 @@ class ShareViewController: NSViewController { } } + +private extension ShareViewController { + + func buildFolderPopupMenu() { + + let menu = NSMenu(title: "Folders") + menu.autoenablesItems = false + + guard let extensionContainers = extensionContainers else { + folderPopUpButton.menu = nil + return + } + + let defaultContainer = ShareDefaultContainer.defaultContainer(containers: extensionContainers) + var defaultMenuItem: NSMenuItem? = nil + + for account in extensionContainers.accounts { + + let menuItem = NSMenuItem(title: account.name, action: nil, keyEquivalent: "") + menuItem.representedObject = account + + if account.disallowFeedInRootFolder { + menuItem.isEnabled = false + } + + menu.addItem(menuItem) + + if defaultContainer?.containerID == account.containerID { + defaultMenuItem = menuItem + } + + for folder in account.folders { + let menuItem = NSMenuItem(title: folder.name, action: nil, keyEquivalent: "") + menuItem.indentationLevel = 1 + menuItem.representedObject = folder + menu.addItem(menuItem) + if defaultContainer?.containerID == folder.containerID { + defaultMenuItem = menuItem + } + } + + } + + folderPopUpButton.menu = menu + folderPopUpButton.select(defaultMenuItem) + } + + func selectedContainer() -> ExtensionContainer? { + return folderPopUpButton.selectedItem?.representedObject as? ExtensionContainer + } + +} diff --git a/NetNewsWire.xcodeproj/project.pbxproj b/NetNewsWire.xcodeproj/project.pbxproj index ace02d646..2b8f52dd0 100644 --- a/NetNewsWire.xcodeproj/project.pbxproj +++ b/NetNewsWire.xcodeproj/project.pbxproj @@ -73,7 +73,6 @@ 5108F6D22375EED2001ABC45 /* TimelineCustomizerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5108F6D12375EED2001ABC45 /* TimelineCustomizerViewController.swift */; }; 5108F6D42375EEEF001ABC45 /* TimelinePreviewTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5108F6D32375EEEF001ABC45 /* TimelinePreviewTableViewController.swift */; }; 5108F6D823763094001ABC45 /* TickMarkSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5108F6D723763094001ABC45 /* TickMarkSlider.swift */; }; - 510C415F24E5CDE3008226FD /* icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 510C415E24E5CDE3008226FD /* icon.icns */; }; 510C416124E5CDE3008226FD /* ShareViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 510C416024E5CDE3008226FD /* ShareViewController.swift */; }; 510C416424E5CDE3008226FD /* ShareViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 510C416224E5CDE3008226FD /* ShareViewController.xib */; }; 510C416924E5CDE3008226FD /* NetNewsWire Share Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 510C415C24E5CDE3008226FD /* NetNewsWire Share Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; @@ -654,6 +653,8 @@ 51EF0F902279C9500050506E /* AccountsAddViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51EF0F8F2279C9500050506E /* AccountsAddViewController.swift */; }; 51EF0F922279CA620050506E /* AccountsAddTableCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51EF0F912279CA620050506E /* AccountsAddTableCellView.swift */; }; 51EFDA1A24E6159C0085C3D6 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 849C64671ED37A5D003D8FC0 /* Assets.xcassets */; }; + 51EFDA1B24E6D16A0085C3D6 /* SafariExt.js in Resources */ = {isa = PBXBuildFile; fileRef = 515D4FCB2325815A00EE1167 /* SafariExt.js */; }; + 51EFDA1D24E6E27E0085C3D6 /* icon.icns in Resources */ = {isa = PBXBuildFile; fileRef = 51EFDA1C24E6E27E0085C3D6 /* icon.icns */; }; 51F85BEB22724CB600C787DC /* About.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 51F85BEA22724CB600C787DC /* About.rtf */; }; 51F85BEF2272520B00C787DC /* Thanks.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 51F85BEE2272520B00C787DC /* Thanks.rtf */; }; 51F85BF12272524100C787DC /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 51F85BF02272524100C787DC /* Credits.rtf */; }; @@ -1474,7 +1475,6 @@ 5108F6D32375EEEF001ABC45 /* TimelinePreviewTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelinePreviewTableViewController.swift; sourceTree = ""; }; 5108F6D723763094001ABC45 /* TickMarkSlider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TickMarkSlider.swift; sourceTree = ""; }; 510C415C24E5CDE3008226FD /* NetNewsWire Share Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "NetNewsWire Share Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; - 510C415E24E5CDE3008226FD /* icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = icon.icns; sourceTree = ""; }; 510C416024E5CDE3008226FD /* ShareViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareViewController.swift; sourceTree = ""; }; 510C416324E5CDE3008226FD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/ShareViewController.xib; sourceTree = ""; }; 510C416524E5CDE3008226FD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; @@ -1757,6 +1757,7 @@ 51EF0F8D2279C9260050506E /* AccountsAdd.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AccountsAdd.xib; sourceTree = ""; }; 51EF0F8F2279C9500050506E /* AccountsAddViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountsAddViewController.swift; sourceTree = ""; }; 51EF0F912279CA620050506E /* AccountsAddTableCellView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountsAddTableCellView.swift; sourceTree = ""; }; + 51EFDA1C24E6E27E0085C3D6 /* icon.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = icon.icns; sourceTree = ""; }; 51F805D32428499E0022C792 /* NetNewsWire-dev.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "NetNewsWire-dev.entitlements"; sourceTree = ""; }; 51F805ED24284C1C0022C792 /* NetNewsWire-dev.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "NetNewsWire-dev.entitlements"; sourceTree = ""; }; 51F85BEA22724CB600C787DC /* About.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = About.rtf; sourceTree = ""; }; @@ -2269,7 +2270,7 @@ 510C415D24E5CDE3008226FD /* ShareExtension */ = { isa = PBXGroup; children = ( - 510C415E24E5CDE3008226FD /* icon.icns */, + 51EFDA1C24E6E27E0085C3D6 /* icon.icns */, 510C416024E5CDE3008226FD /* ShareViewController.swift */, 510C416224E5CDE3008226FD /* ShareViewController.xib */, 510C416524E5CDE3008226FD /* Info.plist */, @@ -2384,7 +2385,6 @@ 51A9A5E52380C8B20033AADF /* ShareFolderPickerFolderCell.xib */, 513C5CEA232571C2003D4054 /* MainInterface.storyboard */, 513C5CED232571C2003D4054 /* Info.plist */, - 515D4FCB2325815A00EE1167 /* SafariExt.js */, 515D4FCD2325909200EE1167 /* NetNewsWire_iOS_ShareExtension.entitlements */, ); path = ShareExtension; @@ -2600,6 +2600,7 @@ 51B5C85A23F22A7A00032075 /* ShareExtension */ = { isa = PBXGroup; children = ( + 515D4FCB2325815A00EE1167 /* SafariExt.js */, 51B5C87623F22B8200032075 /* ExtensionContainers.swift */, 51B5C87C23F2346200032075 /* ExtensionContainersFile.swift */, 51B5C87A23F2317700032075 /* ExtensionFeedAddRequest.swift */, @@ -4076,8 +4077,9 @@ buildActionMask = 2147483647; files = ( 510C416424E5CDE3008226FD /* ShareViewController.xib in Resources */, + 51EFDA1D24E6E27E0085C3D6 /* icon.icns in Resources */, 51EFDA1A24E6159C0085C3D6 /* Assets.xcassets in Resources */, - 510C415F24E5CDE3008226FD /* icon.icns in Resources */, + 51EFDA1B24E6D16A0085C3D6 /* SafariExt.js in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/iOS/ShareExtension/SafariExt.js b/Shared/ShareExtension/SafariExt.js similarity index 100% rename from iOS/ShareExtension/SafariExt.js rename to Shared/ShareExtension/SafariExt.js