From 313518698c47f57f59959249f76a078feb9710b5 Mon Sep 17 00:00:00 2001 From: Maurice Parker Date: Sat, 24 Aug 2019 19:31:29 -0500 Subject: [PATCH] add the ability to respond to NSActivityRequests --- NetNewsWire.xcodeproj/project.pbxproj | 4 ++ Shared/Activity/ActivityFactory.swift | 3 +- Shared/Activity/ActivityID.swift | 1 + Shared/Activity/ActivityType.swift | 13 +++++++ iOS/AppCoordinator.swift | 55 +++++++++++++++++++++++++++ iOS/SceneDelegate.swift | 4 ++ submodules/RSTree | 2 +- 7 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 Shared/Activity/ActivityType.swift diff --git a/NetNewsWire.xcodeproj/project.pbxproj b/NetNewsWire.xcodeproj/project.pbxproj index 7419badfb..5d1f319dc 100644 --- a/NetNewsWire.xcodeproj/project.pbxproj +++ b/NetNewsWire.xcodeproj/project.pbxproj @@ -123,6 +123,7 @@ 51C452B42265141B00C03939 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51C452B32265141B00C03939 /* WebKit.framework */; }; 51C452B82265178500C03939 /* styleSheet.css in Resources */ = {isa = PBXBuildFile; fileRef = 51C452B72265178500C03939 /* styleSheet.css */; }; 51D5948722668EFA00DFC836 /* MarkStatusCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 84702AA31FA27AC0006B8943 /* MarkStatusCommand.swift */; }; + 51D87EE12311D34700E63F03 /* ActivityType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51D87EE02311D34700E63F03 /* ActivityType.swift */; }; 51E3EB33229AB02C00645299 /* ErrorHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51E3EB32229AB02C00645299 /* ErrorHandler.swift */; }; 51E3EB3D229AB08300645299 /* ErrorHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51E3EB3C229AB08300645299 /* ErrorHandler.swift */; }; 51E595A5228CC36500FCC42B /* ArticleStatusSyncTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51E595A4228CC36500FCC42B /* ArticleStatusSyncTimer.swift */; }; @@ -730,6 +731,7 @@ 51C4528B2265095F00C03939 /* AddFolderViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AddFolderViewController.swift; sourceTree = ""; }; 51C452B32265141B00C03939 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS12.2.sdk/System/Library/Frameworks/WebKit.framework; sourceTree = DEVELOPER_DIR; }; 51C452B72265178500C03939 /* styleSheet.css */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.css; path = styleSheet.css; sourceTree = ""; }; + 51D87EE02311D34700E63F03 /* ActivityType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityType.swift; sourceTree = ""; }; 51E3EB32229AB02C00645299 /* ErrorHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorHandler.swift; sourceTree = ""; }; 51E3EB3C229AB08300645299 /* ErrorHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorHandler.swift; sourceTree = ""; }; 51E595A4228CC36500FCC42B /* ArticleStatusSyncTimer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArticleStatusSyncTimer.swift; sourceTree = ""; }; @@ -1093,6 +1095,7 @@ children = ( 51934CCD2310792F006127BE /* ActivityFactory.swift */, 51934CCF23108953006127BE /* ActivityID.swift */, + 51D87EE02311D34700E63F03 /* ActivityType.swift */, ); path = Activity; sourceTree = ""; @@ -2392,6 +2395,7 @@ 51F85BFD2275DCA800C787DC /* SingleLineUILabelSizer.swift in Sources */, 51C4528F226509BD00C03939 /* UnreadFeed.swift in Sources */, 5183CCDD226F1F5C0010922C /* NavigationProgressView.swift in Sources */, + 51D87EE12311D34700E63F03 /* ActivityType.swift in Sources */, 51C452772265091600C03939 /* MultilineUILabelSizer.swift in Sources */, 51C452A522650A2D00C03939 /* SmallIconProvider.swift in Sources */, 51D5948722668EFA00DFC836 /* MarkStatusCommand.swift in Sources */, diff --git a/Shared/Activity/ActivityFactory.swift b/Shared/Activity/ActivityFactory.swift index be33961c1..447139817 100644 --- a/Shared/Activity/ActivityFactory.swift +++ b/Shared/Activity/ActivityFactory.swift @@ -14,7 +14,7 @@ import Articles class ActivityFactory { static func make(_ article: Article) -> NSUserActivity { - let activity = NSUserActivity(activityType: "com.ranchero.NetNewsWire.ReadArticle") + let activity = NSUserActivity(activityType: ActivityType.readArticle.rawValue) activity.title = article.title @@ -25,6 +25,7 @@ class ActivityFactory { activity.userInfo = [ ActivityID.accountID.rawValue: article.accountID, + ActivityID.accountName.rawValue: article.account?.name ?? "", ActivityID.feedID.rawValue: article.feedID, ActivityID.articleID.rawValue: article.articleID ] diff --git a/Shared/Activity/ActivityID.swift b/Shared/Activity/ActivityID.swift index 38a395a09..e6afa8d9c 100644 --- a/Shared/Activity/ActivityID.swift +++ b/Shared/Activity/ActivityID.swift @@ -10,6 +10,7 @@ import Foundation enum ActivityID: String { case accountID = "accountID" + case accountName = "accountName" case feedID = "feedID" case articleID = "articleID" } diff --git a/Shared/Activity/ActivityType.swift b/Shared/Activity/ActivityType.swift new file mode 100644 index 000000000..26000f44a --- /dev/null +++ b/Shared/Activity/ActivityType.swift @@ -0,0 +1,13 @@ +// +// ActivityType.swift +// NetNewsWire-iOS +// +// Created by Maurice Parker on 8/24/19. +// Copyright © 2019 Ranchero Software. All rights reserved. +// + +import Foundation + +enum ActivityType: String { + case readArticle = "com.ranchero.NetNewsWire.ReadArticle" +} diff --git a/iOS/AppCoordinator.swift b/iOS/AppCoordinator.swift index a7f9578cb..0d83d5caa 100644 --- a/iOS/AppCoordinator.swift +++ b/iOS/AppCoordinator.swift @@ -253,6 +253,14 @@ class AppCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider { return rootSplitViewController } + func handle(_ activity: NSUserActivity) { + guard let activityType = ActivityType(rawValue: activity.activityType) else { return } + switch activityType { + case .readArticle: + handleReadArticle(activity) + } + } + // MARK: Notifications @objc func statusesDidChange(_ note: Notification) { @@ -1183,4 +1191,51 @@ private extension AppCoordinator { readActivity?.becomeCurrent() } + func handleReadArticle(_ activity: NSUserActivity) { + guard let accountNode = findAccountNode(for: activity), let feedNode = findFeedNode(for: activity, beginningAt: accountNode) else { + return + } + + masterFeedViewController.discloseFeed(feedNode.representedObject as! Feed) + + guard let articleID = activity.userInfo?[ActivityID.articleID.rawValue] as? String else { return } + + for (index, article) in articles.enumerated() { + if article.articleID == articleID { + selectArticle(IndexPath(row: index, section: 0)) + break + } + } + } + + func findAccountNode(for activity: NSUserActivity) -> Node? { + guard let accountID = activity.userInfo?[ActivityID.accountID.rawValue] as? String else { + return nil + } + + if let node = treeController.rootNode.descendantNode(where: { ($0.representedObject as? Account)?.accountID == accountID }) { + return node + } + + guard let accountName = activity.userInfo?[ActivityID.accountName.rawValue] as? String else { + return nil + } + + if let node = treeController.rootNode.descendantNode(where: { ($0.representedObject as? Account)?.name == accountName }) { + return node + } + + return nil + } + + func findFeedNode(for activity: NSUserActivity, beginningAt startingNode: Node) -> Node? { + guard let feedID = activity.userInfo?[ActivityID.feedID.rawValue] as? String else { + return nil + } + if let node = startingNode.descendantNode(where: { ($0.representedObject as? Feed)?.feedID == feedID }) { + return node + } + return nil + } + } diff --git a/iOS/SceneDelegate.swift b/iOS/SceneDelegate.swift index 084d65d94..7637a9304 100644 --- a/iOS/SceneDelegate.swift +++ b/iOS/SceneDelegate.swift @@ -32,6 +32,10 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate { // The `window` property will automatically be loaded with the storyboard's initial view controller. } + func scene(_ scene: UIScene, continue userActivity: NSUserActivity) { + coordinator.handle(userActivity) + } + func sceneDidEnterBackground(_ scene: UIScene) { appDelegate.prepareAccountsForBackground() } diff --git a/submodules/RSTree b/submodules/RSTree index 350762104..db208e17b 160000 --- a/submodules/RSTree +++ b/submodules/RSTree @@ -1 +1 @@ -Subproject commit 350762104423aef963ca945d4388ca9d47f991ce +Subproject commit db208e17bdf4f5e7e643c580acbc339191693537