Add user activities for read all/unread
This commit is contained in:
parent
7f5006c629
commit
2f6d0ae07c
|
@ -4,6 +4,8 @@
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSUserActivityTypes</key>
|
<key>NSUserActivityTypes</key>
|
||||||
<array>
|
<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.preferences</string>
|
||||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER).activity.add-account</string>
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER).activity.add-account</string>
|
||||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER).activity.activate-account</string>
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER).activity.activate-account</string>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
// Created by Shadowfacts on 10/29/21.
|
// Created by Shadowfacts on 10/29/21.
|
||||||
//
|
//
|
||||||
|
|
||||||
import Foundation
|
@preconcurrency import Foundation
|
||||||
import UIKit
|
import UIKit
|
||||||
import OSLog
|
import OSLog
|
||||||
|
|
||||||
|
@ -27,30 +27,31 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||||
window = UIWindow(windowScene: windowScene)
|
window = UIWindow(windowScene: windowScene)
|
||||||
window!.tintColor = .appTintColor
|
window!.tintColor = .appTintColor
|
||||||
|
|
||||||
let activity = connectionOptions.userActivities.first
|
var activity = connectionOptions.userActivities.first
|
||||||
|
|
||||||
|
var account = LocalData.mostRecentAccount()
|
||||||
|
|
||||||
if activity?.activityType == NSUserActivity.addAccountType {
|
if activity?.activityType == NSUserActivity.addAccountType {
|
||||||
let loginVC = LoginViewController()
|
account = nil
|
||||||
loginVC.delegate = self
|
} else if let id = activity?.accountID() {
|
||||||
window!.rootViewController = loginVC
|
account = LocalData.account(with: id)
|
||||||
} else if activity?.activityType == NSUserActivity.activateAccountType,
|
if account == nil {
|
||||||
let idStr = activity!.userInfo?["accountID"] as? String,
|
activity = nil
|
||||||
let id = Data(base64Encoded: idStr),
|
logger.log("Missing account for activity, not restoring")
|
||||||
let account = LocalData.account(with: id) {
|
|
||||||
Task { @MainActor in
|
|
||||||
fervorController = await FervorController(account: account)
|
|
||||||
syncFromServer()
|
|
||||||
createAppUI()
|
|
||||||
}
|
}
|
||||||
} else if let account = LocalData.mostRecentAccount() {
|
}
|
||||||
Task { @MainActor in
|
|
||||||
|
if let account = account {
|
||||||
|
Task { @MainActor [activity] in
|
||||||
fervorController = await FervorController(account: account)
|
fervorController = await FervorController(account: account)
|
||||||
syncFromServer()
|
syncFromServer()
|
||||||
createAppUI()
|
createAppUI()
|
||||||
|
if let activity = activity {
|
||||||
|
setupUI(from: activity)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let loginVC = LoginViewController()
|
createLoginUI()
|
||||||
loginVC.delegate = self
|
|
||||||
window!.rootViewController = loginVC
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if targetEnvironment(macCatalyst)
|
#if targetEnvironment(macCatalyst)
|
||||||
|
@ -106,6 +107,31 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
|
||||||
// to restore the scene back to its current state.
|
// 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() {
|
private func createAppUI() {
|
||||||
window!.rootViewController = AppSplitViewController(fervorController: fervorController)
|
window!.rootViewController = AppSplitViewController(fervorController: fervorController)
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,18 @@ class AppSplitViewController: UISplitViewController {
|
||||||
setViewController(nav, for: .compact)
|
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 {
|
extension AppSplitViewController: ItemsViewControllerDelegate {
|
||||||
|
|
|
@ -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 {
|
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> {
|
var idFetchRequest: NSFetchRequest<NSManagedObjectID> {
|
||||||
let req = NSFetchRequest<NSManagedObjectID>(entityName: "Item")
|
let req = NSFetchRequest<NSManagedObjectID>(entityName: "Item")
|
||||||
req.resultType = .managedObjectIDResultType
|
req.resultType = .managedObjectIDResultType
|
||||||
|
@ -307,10 +314,7 @@ extension HomeViewController: UICollectionViewDelegate {
|
||||||
guard let item = dataSource.itemIdentifier(for: indexPath) else {
|
guard let item = dataSource.itemIdentifier(for: indexPath) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
let vc = ItemsViewController(fetchRequest: item.idFetchRequest, fervorController: fervorController)
|
show(itemsViewController(for: item), sender: nil)
|
||||||
vc.title = item.title
|
|
||||||
vc.delegate = itemsDelegate
|
|
||||||
show(vc, sender: nil)
|
|
||||||
UISelectionFeedbackGenerator().selectionChanged()
|
UISelectionFeedbackGenerator().selectionChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,8 +322,8 @@ extension HomeViewController: UICollectionViewDelegate {
|
||||||
guard let item = dataSource.itemIdentifier(for: indexPath) else {
|
guard let item = dataSource.itemIdentifier(for: indexPath) else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return UIContextMenuConfiguration(identifier: nil, previewProvider: {
|
return UIContextMenuConfiguration(identifier: nil, previewProvider: { [unowned self] in
|
||||||
return ItemsViewController(fetchRequest: item.idFetchRequest, fervorController: self.fervorController)
|
return self.itemsViewController(for: item)
|
||||||
}, actionProvider: nil)
|
}, actionProvider: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,17 @@ extension NSUserActivity {
|
||||||
static let preferencesType = "net.shadowfacts.Reader.activity.preferences"
|
static let preferencesType = "net.shadowfacts.Reader.activity.preferences"
|
||||||
static let addAccountType = "net.shadowfacts.Reader.activity.add-account"
|
static let addAccountType = "net.shadowfacts.Reader.activity.add-account"
|
||||||
static let activateAccountType = "net.shadowfacts.Reader.activity.activate-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 {
|
static func preferences() -> NSUserActivity {
|
||||||
return NSUserActivity(activityType: preferencesType)
|
return NSUserActivity(activityType: preferencesType)
|
||||||
|
@ -24,9 +35,25 @@ extension NSUserActivity {
|
||||||
static func activateAccount(_ account: LocalData.Account) -> NSUserActivity {
|
static func activateAccount(_ account: LocalData.Account) -> NSUserActivity {
|
||||||
let activity = NSUserActivity(activityType: activateAccountType)
|
let activity = NSUserActivity(activityType: activateAccountType)
|
||||||
activity.userInfo = [
|
activity.userInfo = [
|
||||||
"accountID": account.id.uuidString
|
"accountID": account.id,
|
||||||
]
|
]
|
||||||
return activity
|
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
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue