Add user activities for read all/unread

This commit is contained in:
Shadowfacts 2022-03-07 21:54:41 -05:00
parent 7f5006c629
commit 2f6d0ae07c
5 changed files with 111 additions and 40 deletions

View File

@ -4,6 +4,8 @@
<dict>
<key>NSUserActivityTypes</key>
<array>
<string>$(PRODUCT_BUNDLE_IDENTIFIER).activity.read-unread</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER).activity.read-all</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER).activity.preferences</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER).activity.add-account</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER).activity.activate-account</string>

View File

@ -5,7 +5,7 @@
// Created by Shadowfacts on 10/29/21.
//
import Foundation
@preconcurrency import Foundation
import UIKit
import OSLog
@ -27,30 +27,31 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
window = UIWindow(windowScene: windowScene)
window!.tintColor = .appTintColor
let activity = connectionOptions.userActivities.first
var activity = connectionOptions.userActivities.first
var account = LocalData.mostRecentAccount()
if activity?.activityType == NSUserActivity.addAccountType {
let loginVC = LoginViewController()
loginVC.delegate = self
window!.rootViewController = loginVC
} else if activity?.activityType == NSUserActivity.activateAccountType,
let idStr = activity!.userInfo?["accountID"] as? String,
let id = Data(base64Encoded: idStr),
let account = LocalData.account(with: id) {
Task { @MainActor in
fervorController = await FervorController(account: account)
syncFromServer()
createAppUI()
account = nil
} else if let id = activity?.accountID() {
account = LocalData.account(with: id)
if account == nil {
activity = nil
logger.log("Missing account for activity, not restoring")
}
} else if let account = LocalData.mostRecentAccount() {
Task { @MainActor in
}
if let account = account {
Task { @MainActor [activity] in
fervorController = await FervorController(account: account)
syncFromServer()
createAppUI()
if let activity = activity {
setupUI(from: activity)
}
}
} else {
let loginVC = LoginViewController()
loginVC.delegate = self
window!.rootViewController = loginVC
createLoginUI()
}
#if targetEnvironment(macCatalyst)
@ -106,6 +107,31 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
// to restore the scene back to its current state.
}
func scene(_ scene: UIScene, continue userActivity: NSUserActivity) {
setupUI(from: userActivity)
}
private func setupUI(from activity: NSUserActivity) {
guard let split = window?.rootViewController as? AppSplitViewController else {
logger.error("Failed to setup UI for user activity: missing split VC")
return
}
switch activity.activityType {
case NSUserActivity.readUnreadType:
split.selectHomeItem(.unread)
case NSUserActivity.readAllType:
split.selectHomeItem(.all)
default:
break
}
}
private func createLoginUI() {
let vc = LoginViewController()
vc.delegate = self
window!.rootViewController = vc
}
private func createAppUI() {
window!.rootViewController = AppSplitViewController(fervorController: fervorController)
}

View File

@ -54,6 +54,18 @@ class AppSplitViewController: UISplitViewController {
setViewController(nav, for: .compact)
}
func selectHomeItem(_ item: HomeViewController.Item) {
let column: Column
if traitCollection.horizontalSizeClass == .compact {
column = .compact
} else {
column = .primary
}
let nav = viewController(for: column) as! UINavigationController
let home = nav.viewControllers.first! as! HomeViewController
home.selectItem(item)
}
}
extension AppSplitViewController: ItemsViewControllerDelegate {

View File

@ -198,6 +198,28 @@ class HomeViewController: UIViewController {
}
}
private func itemsViewController(for item: Item) -> ItemsViewController {
let vc = ItemsViewController(fetchRequest: item.idFetchRequest, fervorController: fervorController)
vc.title = item.title
vc.delegate = itemsDelegate
switch item {
case .all:
vc.userActivity = .readAll()
case .unread:
vc.userActivity = .readUnread()
case .group(let group):
break
case .feed(let feed):
break
}
return vc
}
func selectItem(_ item: Item) {
navigationController!.popToRootViewController(animated: false)
navigationController!.pushViewController(itemsViewController(for: item), animated: false)
}
}
extension HomeViewController {
@ -236,21 +258,6 @@ extension HomeViewController {
}
}
var fetchRequest: NSFetchRequest<Reader.Item> {
let req = Reader.Item.fetchRequest()
switch self {
case .unread:
req.predicate = NSPredicate(format: "read = NO")
case .all:
break
case .group(let group):
req.predicate = NSPredicate(format: "feed in %@", group.feeds!)
case .feed(let feed):
req.predicate = NSPredicate(format: "feed = %@", feed)
}
return req
}
var idFetchRequest: NSFetchRequest<NSManagedObjectID> {
let req = NSFetchRequest<NSManagedObjectID>(entityName: "Item")
req.resultType = .managedObjectIDResultType
@ -307,10 +314,7 @@ extension HomeViewController: UICollectionViewDelegate {
guard let item = dataSource.itemIdentifier(for: indexPath) else {
return
}
let vc = ItemsViewController(fetchRequest: item.idFetchRequest, fervorController: fervorController)
vc.title = item.title
vc.delegate = itemsDelegate
show(vc, sender: nil)
show(itemsViewController(for: item), sender: nil)
UISelectionFeedbackGenerator().selectionChanged()
}
@ -318,8 +322,8 @@ extension HomeViewController: UICollectionViewDelegate {
guard let item = dataSource.itemIdentifier(for: indexPath) else {
return nil
}
return UIContextMenuConfiguration(identifier: nil, previewProvider: {
return ItemsViewController(fetchRequest: item.idFetchRequest, fervorController: self.fervorController)
return UIContextMenuConfiguration(identifier: nil, previewProvider: { [unowned self] in
return self.itemsViewController(for: item)
}, actionProvider: nil)
}

View File

@ -12,6 +12,17 @@ extension NSUserActivity {
static let preferencesType = "net.shadowfacts.Reader.activity.preferences"
static let addAccountType = "net.shadowfacts.Reader.activity.add-account"
static let activateAccountType = "net.shadowfacts.Reader.activity.activate-account"
static let readUnreadType = "net.shadowfacts.Reader.activity.read-unread"
static let readAllType = "net.shadowfacts.Reader.activity.read-all"
func accountID() -> Data? {
if [NSUserActivity.addAccountType].contains(self.activityType),
let id = self.userInfo?["accountID"] as? Data {
return id
} else {
return nil
}
}
static func preferences() -> NSUserActivity {
return NSUserActivity(activityType: preferencesType)
@ -24,9 +35,25 @@ extension NSUserActivity {
static func activateAccount(_ account: LocalData.Account) -> NSUserActivity {
let activity = NSUserActivity(activityType: activateAccountType)
activity.userInfo = [
"accountID": account.id.uuidString
"accountID": account.id,
]
return activity
}
static func readUnread() -> NSUserActivity {
let activity = NSUserActivity(activityType: readUnreadType)
activity.isEligibleForHandoff = true
activity.isEligibleForPrediction = true
activity.title = "Show unread articles"
return activity
}
static func readAll() -> NSUserActivity {
let activity = NSUserActivity(activityType: readAllType)
activity.isEligibleForHandoff = true
activity.isEligibleForPrediction = true
activity.title = "Show all articles"
return activity
}
}