Add NSUserActivity for reading articles
This commit is contained in:
parent
1ba60e2846
commit
5b1c0485c5
|
@ -47,6 +47,8 @@
|
|||
5183CCED22711DCE0010922C /* Settings.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 5183CCEC22711DCE0010922C /* Settings.storyboard */; };
|
||||
5183CCEF227125970010922C /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5183CCEE227125970010922C /* SettingsViewController.swift */; };
|
||||
51934CCB230F599B006127BE /* ThemedNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51934CC1230F5963006127BE /* ThemedNavigationController.swift */; };
|
||||
51934CCE2310792F006127BE /* ActivityFactory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51934CCD2310792F006127BE /* ActivityFactory.swift */; };
|
||||
51934CD023108953006127BE /* ActivityID.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51934CCF23108953006127BE /* ActivityID.swift */; };
|
||||
519B8D332143397200FA689C /* SharingServiceDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519B8D322143397200FA689C /* SharingServiceDelegate.swift */; };
|
||||
519E743D22C663F900A78E47 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 519E743422C663F900A78E47 /* SceneDelegate.swift */; };
|
||||
51C451A9226377C200C03939 /* ArticlesDatabase.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8407167F2262A61100344432 /* ArticlesDatabase.framework */; };
|
||||
|
@ -701,6 +703,8 @@
|
|||
5183CCEC22711DCE0010922C /* Settings.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Settings.storyboard; sourceTree = "<group>"; };
|
||||
5183CCEE227125970010922C /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = "<group>"; };
|
||||
51934CC1230F5963006127BE /* ThemedNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemedNavigationController.swift; sourceTree = "<group>"; };
|
||||
51934CCD2310792F006127BE /* ActivityFactory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityFactory.swift; sourceTree = "<group>"; };
|
||||
51934CCF23108953006127BE /* ActivityID.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivityID.swift; sourceTree = "<group>"; };
|
||||
5194B5ED22B6965300144881 /* SettingsSubscriptionsImportDocumentPickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsSubscriptionsImportDocumentPickerView.swift; sourceTree = "<group>"; };
|
||||
5194B5F122B69FCC00144881 /* SettingsSubscriptionsExportDocumentPickerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsSubscriptionsExportDocumentPickerView.swift; sourceTree = "<group>"; };
|
||||
519B8D322143397200FA689C /* SharingServiceDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharingServiceDelegate.swift; sourceTree = "<group>"; };
|
||||
|
@ -1084,6 +1088,15 @@
|
|||
path = Settings;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
51934CCC231078DC006127BE /* Activity */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
51934CCD2310792F006127BE /* ActivityFactory.swift */,
|
||||
51934CCF23108953006127BE /* ActivityID.swift */,
|
||||
);
|
||||
path = Activity;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
5194B5E222B693EC00144881 /* Wrappers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -1630,6 +1643,7 @@
|
|||
842E45CD1ED8C308000A8B52 /* AppNotifications.swift */,
|
||||
51C452AD2265102800C03939 /* Timeline */,
|
||||
84702AB31FA27AE8006B8943 /* Commands */,
|
||||
51934CCC231078DC006127BE /* Activity */,
|
||||
51C452A822650DA100C03939 /* Article Rendering */,
|
||||
849A97861ED9ECEF007D329B /* Article Styles */,
|
||||
84DAEE201F86CAE00058304B /* Importers */,
|
||||
|
@ -2434,6 +2448,7 @@
|
|||
51C452762265091600C03939 /* MasterTimelineViewController.swift in Sources */,
|
||||
5183CCE9226F68D90010922C /* AccountRefreshTimer.swift in Sources */,
|
||||
51C452882265093600C03939 /* AddFeedViewController.swift in Sources */,
|
||||
51934CCE2310792F006127BE /* ActivityFactory.swift in Sources */,
|
||||
DF999FF722B5AEFA0064B687 /* SafariView.swift in Sources */,
|
||||
51C4529B22650A1000C03939 /* FaviconDownloader.swift in Sources */,
|
||||
84DEE56622C32CA4005FC42C /* SmartFeedDelegate.swift in Sources */,
|
||||
|
@ -2445,6 +2460,7 @@
|
|||
51E595AD228E1C2100FCC42B /* AddAccountViewController.swift in Sources */,
|
||||
51C452A322650A1E00C03939 /* HTMLMetadataDownloader.swift in Sources */,
|
||||
51C4528D2265095F00C03939 /* AddFolderViewController.swift in Sources */,
|
||||
51934CD023108953006127BE /* ActivityID.swift in Sources */,
|
||||
51C452782265091600C03939 /* MasterTimelineCellData.swift in Sources */,
|
||||
51C45259226508D300C03939 /* AppDefaults.swift in Sources */,
|
||||
51C45293226509C800C03939 /* StarredFeedDelegate.swift in Sources */,
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
//
|
||||
// ActivityFactory.swift
|
||||
// NetNewsWire-iOS
|
||||
//
|
||||
// Created by Maurice Parker on 8/23/19.
|
||||
// Copyright © 2019 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import CoreSpotlight
|
||||
import CoreServices
|
||||
import Articles
|
||||
|
||||
class ActivityFactory {
|
||||
|
||||
static func make(_ article: Article) -> NSUserActivity {
|
||||
let activity = NSUserActivity(activityType: "com.ranchero.NetNewsWire.ReadArticle")
|
||||
|
||||
activity.title = article.title
|
||||
|
||||
let feedNameKeywords = article.feed?.nameForDisplay.components(separatedBy: " ").filter { $0.count > 2 } ?? []
|
||||
let articleTitleKeywords = article.title?.components(separatedBy: " ").filter { $0.count > 2 } ?? []
|
||||
let keywords = feedNameKeywords + articleTitleKeywords
|
||||
activity.keywords = Set(keywords)
|
||||
|
||||
activity.userInfo = [
|
||||
ActivityID.accountID.rawValue: article.accountID,
|
||||
ActivityID.feedID.rawValue: article.feedID,
|
||||
ActivityID.articleID.rawValue: article.articleID
|
||||
]
|
||||
activity.isEligibleForSearch = true
|
||||
activity.isEligibleForPrediction = false
|
||||
activity.isEligibleForHandoff = true
|
||||
|
||||
// CoreSpotlight
|
||||
let attributeSet = CSSearchableItemAttributeSet(itemContentType: kUTTypeCompositeContent as String)
|
||||
attributeSet.title = article.title
|
||||
attributeSet.contentDescription = article.summary
|
||||
attributeSet.keywords = keywords
|
||||
|
||||
if let image = article.avatarImage() {
|
||||
attributeSet.thumbnailData = image.pngData()
|
||||
}
|
||||
|
||||
activity.contentAttributeSet = attributeSet
|
||||
|
||||
return activity
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
//
|
||||
// ActivityID.swift
|
||||
// NetNewsWire-iOS
|
||||
//
|
||||
// Created by Maurice Parker on 8/23/19.
|
||||
// Copyright © 2019 Ranchero Software. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
enum ActivityID: String {
|
||||
case accountID = "accountID"
|
||||
case feedID = "feedID"
|
||||
case articleID = "articleID"
|
||||
}
|
|
@ -7,6 +7,7 @@
|
|||
//
|
||||
|
||||
import Foundation
|
||||
import RSCore
|
||||
import Articles
|
||||
import Account
|
||||
|
||||
|
@ -56,4 +57,30 @@ extension Article {
|
|||
var logicalDatePublished: Date {
|
||||
return datePublished ?? dateModified ?? status.dateArrived
|
||||
}
|
||||
|
||||
func avatarImage() -> RSImage? {
|
||||
if let authors = authors {
|
||||
for author in authors {
|
||||
if let image = appDelegate.authorAvatarDownloader.image(for: author) {
|
||||
return image
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
guard let feed = feed else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let feedIconImage = appDelegate.feedIconDownloader.icon(for: feed)
|
||||
if feedIconImage != nil {
|
||||
return feedIconImage
|
||||
}
|
||||
|
||||
if let faviconImage = appDelegate.faviconDownloader.faviconAsAvatar(for: feed) {
|
||||
return faviconImage
|
||||
}
|
||||
|
||||
return FaviconGenerator.favicon(feed)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -210,6 +210,8 @@ class AppCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private(set) var readActivity: NSUserActivity? = nil
|
||||
|
||||
override init() {
|
||||
super.init()
|
||||
|
@ -508,7 +510,8 @@ class AppCoordinator: NSObject, UndoableCommandRunner, UnreadCountProvider {
|
|||
|
||||
func selectArticle(_ indexPath: IndexPath?) {
|
||||
currentArticleIndexPath = indexPath
|
||||
|
||||
updateReadArticleUserActivity()
|
||||
|
||||
if indexPath == nil {
|
||||
if !rootSplitViewController.isCollapsed {
|
||||
let systemMessageViewController = UIStoryboard.main.instantiateController(ofType: SystemMessageViewController.self)
|
||||
|
@ -1168,4 +1171,16 @@ private extension AppCoordinator {
|
|||
|
||||
}
|
||||
|
||||
// MARK: NSUserActivity
|
||||
|
||||
func updateReadArticleUserActivity() {
|
||||
readActivity?.invalidate()
|
||||
readActivity = nil
|
||||
|
||||
guard let article = currentArticle else { return }
|
||||
|
||||
readActivity = ActivityFactory.make(article)
|
||||
readActivity?.becomeCurrent()
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -463,39 +463,11 @@ private extension MasterTimelineViewController {
|
|||
|
||||
}
|
||||
|
||||
func avatarFor(_ article: Article) -> UIImage? {
|
||||
|
||||
func avatarFor(_ article: Article) -> RSImage? {
|
||||
if !coordinator.showAvatars {
|
||||
return nil
|
||||
}
|
||||
|
||||
if let authors = article.authors {
|
||||
for author in authors {
|
||||
if let image = avatarForAuthor(author) {
|
||||
return image
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
guard let feed = article.feed else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let feedIconImage = appDelegate.feedIconDownloader.icon(for: feed)
|
||||
if feedIconImage != nil {
|
||||
return feedIconImage
|
||||
}
|
||||
|
||||
if let feed = article.feed, let faviconImage = appDelegate.faviconDownloader.faviconAsAvatar(for: feed) {
|
||||
return faviconImage
|
||||
}
|
||||
|
||||
return FaviconGenerator.favicon(feed)
|
||||
|
||||
}
|
||||
|
||||
func avatarForAuthor(_ author: Author) -> UIImage? {
|
||||
return appDelegate.authorAvatarDownloader.image(for: author)
|
||||
return article.avatarImage()
|
||||
}
|
||||
|
||||
func featuredImageFor(_ article: Article) -> UIImage? {
|
||||
|
|
|
@ -47,6 +47,10 @@
|
|||
<string>1</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSUserActivityTypes</key>
|
||||
<array>
|
||||
<string>com.ranchero.NetNewsWire.ReadArticle</string>
|
||||
</array>
|
||||
<key>NSAppTransportSecurity</key>
|
||||
<dict>
|
||||
<key>NSAllowsArbitraryLoads</key>
|
||||
|
|
Loading…
Reference in New Issue