2018-02-05 13:29:46 -08:00
|
|
|
|
//
|
|
|
|
|
// AppDelegate.swift
|
2019-04-15 15:03:05 -05:00
|
|
|
|
// NetNewsWire
|
2018-02-05 13:29:46 -08:00
|
|
|
|
//
|
2019-04-15 15:03:05 -05:00
|
|
|
|
// Created by Maurice Parker on 4/8/19.
|
|
|
|
|
// Copyright © 2019 Ranchero Software. All rights reserved.
|
2018-02-05 13:29:46 -08:00
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
import UIKit
|
2025-01-03 11:48:19 -08:00
|
|
|
|
import os
|
2025-02-01 19:43:44 -08:00
|
|
|
|
import RSCore
|
|
|
|
|
import Account
|
2025-02-01 22:11:48 -08:00
|
|
|
|
import Articles
|
2019-04-15 15:03:05 -05:00
|
|
|
|
|
2018-02-05 13:29:46 -08:00
|
|
|
|
@UIApplicationMain
|
2025-02-01 20:04:30 -08:00
|
|
|
|
final class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate {
|
2025-01-22 22:18:09 -08:00
|
|
|
|
|
2025-02-01 16:25:54 -08:00
|
|
|
|
var window: UIWindow?
|
2025-01-22 22:18:09 -08:00
|
|
|
|
|
2025-02-01 19:55:10 -08:00
|
|
|
|
private var coordinator: SceneCoordinator?
|
2025-01-03 11:48:19 -08:00
|
|
|
|
private let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "Application")
|
|
|
|
|
|
2025-02-01 20:04:30 -08:00
|
|
|
|
private var unreadCount = 0 {
|
2019-04-15 15:03:05 -05:00
|
|
|
|
didSet {
|
|
|
|
|
if unreadCount != oldValue {
|
2024-11-03 22:40:38 -08:00
|
|
|
|
UNUserNotificationCenter.current().setBadgeCount(unreadCount)
|
2019-04-15 15:03:05 -05:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-01-22 22:18:09 -08:00
|
|
|
|
|
2025-02-02 10:24:52 -08:00
|
|
|
|
// MARK: - Lifecycle
|
2025-02-01 17:34:45 -08:00
|
|
|
|
|
2019-04-15 13:30:10 -05:00
|
|
|
|
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
2025-02-01 17:34:45 -08:00
|
|
|
|
|
2019-04-15 15:03:05 -05:00
|
|
|
|
AppDefaults.registerDefaults()
|
2025-01-26 21:06:22 -08:00
|
|
|
|
let isFirstRun = AppDefaults.isFirstRun
|
2019-04-15 15:03:05 -05:00
|
|
|
|
if isFirstRun {
|
2025-01-03 11:48:19 -08:00
|
|
|
|
logger.info("Is first run.")
|
2019-04-15 15:03:05 -05:00
|
|
|
|
}
|
2025-01-22 22:18:09 -08:00
|
|
|
|
|
2025-02-02 10:24:52 -08:00
|
|
|
|
_ = AccountManager.shared
|
|
|
|
|
|
|
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(unreadCountDidChange(_:)), name: .UnreadCountDidChange, object: AccountManager.shared)
|
|
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(accountRefreshDidFinish(_:)), name: .AccountRefreshDidFinish, object: nil)
|
|
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(userDidTriggerManualRefresh(_:)), name: .userDidTriggerManualRefresh, object: nil)
|
|
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(userDefaultsDidChange(_:)), name: UserDefaults.didChangeNotification, object: nil)
|
|
|
|
|
|
2019-10-18 10:24:32 -05:00
|
|
|
|
if isFirstRun && !AccountManager.shared.anyAccountHasAtLeastOneFeed() {
|
2025-02-01 21:38:43 -08:00
|
|
|
|
DefaultFeedsImporter.importDefaultFeeds(account: AccountManager.shared.defaultAccount)
|
2019-10-18 10:24:32 -05:00
|
|
|
|
}
|
2025-01-22 22:18:09 -08:00
|
|
|
|
|
2025-02-01 21:38:43 -08:00
|
|
|
|
BackgroundTaskManager.shared.delegate = self
|
|
|
|
|
BackgroundTaskManager.shared.registerTasks()
|
|
|
|
|
|
2019-11-08 12:20:21 -06:00
|
|
|
|
CacheCleaner.purgeIfNecessary()
|
2025-02-01 21:38:43 -08:00
|
|
|
|
addHomeScreenQuickActions()
|
2025-01-22 22:18:09 -08:00
|
|
|
|
|
2025-02-01 20:36:18 -08:00
|
|
|
|
UNUserNotificationCenter.current().requestAuthorization(options: [.badge, .sound, .alert]) { granted, _ in
|
|
|
|
|
guard granted else { return }
|
|
|
|
|
Task { @MainActor in
|
|
|
|
|
UIApplication.shared.registerForRemoteNotifications()
|
2019-04-23 07:48:22 -05:00
|
|
|
|
}
|
|
|
|
|
}
|
2020-03-30 02:48:25 -05:00
|
|
|
|
|
2019-10-02 19:42:16 -05:00
|
|
|
|
UNUserNotificationCenter.current().delegate = self
|
2025-02-01 21:38:43 -08:00
|
|
|
|
|
2025-02-02 10:24:52 -08:00
|
|
|
|
_ = ArticleThemesManager.shared
|
2025-02-01 20:06:58 -08:00
|
|
|
|
_ = UserNotificationManager.shared
|
2025-02-01 20:09:34 -08:00
|
|
|
|
_ = ExtensionContainersFile.shared
|
2025-02-01 20:16:33 -08:00
|
|
|
|
_ = ExtensionFeedAddRequestFile.shared
|
|
|
|
|
_ = WidgetDataEncoder.shared
|
2025-02-01 20:03:01 -08:00
|
|
|
|
_ = ArticleStatusSyncTimer.shared
|
2025-02-01 20:28:37 -08:00
|
|
|
|
_ = FaviconDownloader.shared
|
|
|
|
|
_ = FeedIconDownloader.shared
|
2025-02-01 21:38:43 -08:00
|
|
|
|
|
|
|
|
|
#if DEBUG
|
2025-02-01 20:03:01 -08:00
|
|
|
|
ArticleStatusSyncTimer.shared.update()
|
2025-02-01 21:38:43 -08:00
|
|
|
|
#endif
|
2025-01-22 22:18:09 -08:00
|
|
|
|
|
2025-02-01 17:34:45 -08:00
|
|
|
|
// Create window.
|
2025-02-01 16:25:54 -08:00
|
|
|
|
let window = UIWindow(frame: UIScreen.main.bounds)
|
|
|
|
|
self.window = window
|
2025-02-01 17:34:45 -08:00
|
|
|
|
|
|
|
|
|
// Create UI and add it to window.
|
2025-02-01 16:25:54 -08:00
|
|
|
|
let storyboard = UIStoryboard(name: "Main", bundle: nil)
|
|
|
|
|
let rootSplitViewController = storyboard.instantiateInitialViewController() as! RootSplitViewController
|
2025-02-01 17:34:45 -08:00
|
|
|
|
rootSplitViewController.presentsWithGesture = true
|
|
|
|
|
rootSplitViewController.showsSecondaryOnlyButton = true
|
|
|
|
|
rootSplitViewController.preferredDisplayMode = .oneBesideSecondary
|
|
|
|
|
|
2025-02-01 19:55:10 -08:00
|
|
|
|
coordinator = SceneCoordinator(rootSplitViewController: rootSplitViewController)
|
|
|
|
|
rootSplitViewController.coordinator = coordinator
|
|
|
|
|
rootSplitViewController.delegate = coordinator
|
2025-02-01 16:25:54 -08:00
|
|
|
|
|
|
|
|
|
window.rootViewController = rootSplitViewController
|
2025-02-01 17:34:45 -08:00
|
|
|
|
|
|
|
|
|
window.tintColor = AppColor.accent
|
|
|
|
|
updateUserInterfaceStyle()
|
|
|
|
|
UINavigationBar.appearance().scrollEdgeAppearance = UINavigationBarAppearance()
|
|
|
|
|
|
2025-02-01 16:25:54 -08:00
|
|
|
|
window.makeKeyAndVisible()
|
2025-01-22 22:18:09 -08:00
|
|
|
|
|
2025-02-01 17:34:45 -08:00
|
|
|
|
Task { @MainActor in
|
|
|
|
|
// Ensure Feeds view shows on first run on iPad — otherwise the UI is empty.
|
|
|
|
|
if UIDevice.current.userInterfaceIdiom == .pad && AppDefaults.isFirstRun {
|
2025-02-01 19:53:02 -08:00
|
|
|
|
rootSplitViewController.show(.primary)
|
2025-02-01 17:34:45 -08:00
|
|
|
|
}
|
2025-02-01 20:36:18 -08:00
|
|
|
|
|
|
|
|
|
self.unreadCount = AccountManager.shared.unreadCount
|
2025-02-01 17:34:45 -08:00
|
|
|
|
}
|
|
|
|
|
|
2025-02-01 16:25:54 -08:00
|
|
|
|
return true
|
2018-02-05 13:29:46 -08:00
|
|
|
|
}
|
2025-01-22 22:18:09 -08:00
|
|
|
|
|
2025-02-01 21:38:43 -08:00
|
|
|
|
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
|
2020-05-02 10:02:58 -05:00
|
|
|
|
DispatchQueue.main.async {
|
2025-02-01 13:28:49 -08:00
|
|
|
|
AccountManager.shared.resumeAllIfSuspended()
|
2020-05-02 10:02:58 -05:00
|
|
|
|
AccountManager.shared.receiveRemoteNotification(userInfo: userInfo) {
|
|
|
|
|
self.suspendApplication()
|
|
|
|
|
completionHandler(.newData)
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-02-01 21:38:43 -08:00
|
|
|
|
}
|
2025-01-22 22:18:09 -08:00
|
|
|
|
|
2025-02-01 21:38:43 -08:00
|
|
|
|
func applicationWillEnterForeground(_ application: UIApplication) {
|
|
|
|
|
prepareAccountsForForeground()
|
|
|
|
|
coordinator?.resetFocus()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private func prepareAccountsForForeground() {
|
|
|
|
|
|
|
|
|
|
AccountManager.shared.resumeAllIfSuspended()
|
|
|
|
|
|
|
|
|
|
ExtensionFeedAddRequestFile.shared.resume()
|
|
|
|
|
ArticleStatusSyncTimer.shared.update()
|
|
|
|
|
|
|
|
|
|
if let lastRefresh = AppDefaults.lastRefresh {
|
|
|
|
|
if Date() > lastRefresh.addingTimeInterval(15 * 60) {
|
|
|
|
|
AccountManager.shared.refreshAll(errorHandler: ErrorHandler.log)
|
|
|
|
|
} else {
|
|
|
|
|
AccountManager.shared.syncArticleStatusAll()
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
AccountManager.shared.refreshAll(errorHandler: ErrorHandler.log)
|
|
|
|
|
}
|
2019-06-28 10:28:02 -05:00
|
|
|
|
}
|
2021-05-08 12:42:44 -07:00
|
|
|
|
|
|
|
|
|
func applicationDidEnterBackground(_ application: UIApplication) {
|
|
|
|
|
IconImageCache.shared.emptyCache()
|
2025-02-01 21:38:43 -08:00
|
|
|
|
ArticleStringFormatter.emptyCaches()
|
|
|
|
|
prepareAccountsForBackground()
|
2021-05-08 12:42:44 -07:00
|
|
|
|
}
|
2025-01-22 22:18:09 -08:00
|
|
|
|
|
2025-02-01 21:38:43 -08:00
|
|
|
|
private func prepareAccountsForBackground() {
|
|
|
|
|
ExtensionFeedAddRequestFile.shared.suspend()
|
|
|
|
|
ArticleStatusSyncTimer.shared.invalidate()
|
|
|
|
|
BackgroundTaskManager.shared.scheduleBackgroundFeedRefresh()
|
|
|
|
|
BackgroundTaskManager.shared.syncArticleStatus()
|
|
|
|
|
WidgetDataEncoder.shared.encode()
|
|
|
|
|
BackgroundTaskManager.shared.waitForSyncTasksToFinish()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func applicationWillTerminate(_ application: UIApplication) {
|
|
|
|
|
ArticleStatusSyncTimer.shared.stop()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private func suspendApplication() {
|
|
|
|
|
guard UIApplication.shared.applicationState == .background else { return }
|
|
|
|
|
|
|
|
|
|
AccountManager.shared.suspendNetworkAll()
|
|
|
|
|
AccountManager.shared.suspendDatabaseAll()
|
|
|
|
|
ArticleThemeDownloader.shared.cleanUp()
|
|
|
|
|
|
|
|
|
|
CoalescingQueue.standard.performCallsImmediately()
|
|
|
|
|
coordinator?.suspend()
|
|
|
|
|
logger.info("Application processing suspended.")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// MARK: - Notifications
|
|
|
|
|
|
|
|
|
|
extension AppDelegate {
|
2025-01-22 22:18:09 -08:00
|
|
|
|
|
2019-06-28 10:28:02 -05:00
|
|
|
|
@objc func unreadCountDidChange(_ note: Notification) {
|
2025-02-01 20:28:37 -08:00
|
|
|
|
assert(Thread.isMainThread)
|
|
|
|
|
assert(note.object is AccountManager)
|
|
|
|
|
unreadCount = AccountManager.shared.unreadCount
|
2018-02-05 13:29:46 -08:00
|
|
|
|
}
|
2025-01-22 22:18:09 -08:00
|
|
|
|
|
2019-06-28 10:28:02 -05:00
|
|
|
|
@objc func accountRefreshDidFinish(_ note: Notification) {
|
2025-01-26 21:06:22 -08:00
|
|
|
|
AppDefaults.lastRefresh = Date()
|
2019-06-28 10:28:02 -05:00
|
|
|
|
}
|
2025-01-22 22:18:09 -08:00
|
|
|
|
|
2025-02-01 13:28:49 -08:00
|
|
|
|
@objc func userDidTriggerManualRefresh(_ note: Notification) {
|
|
|
|
|
|
2025-02-01 21:38:43 -08:00
|
|
|
|
assert(Thread.isMainThread)
|
|
|
|
|
|
2025-02-01 13:28:49 -08:00
|
|
|
|
guard let errorHandler = note.userInfo?[UserInfoKey.errorHandler] as? ErrorHandlerBlock else {
|
|
|
|
|
assertionFailure("Expected errorHandler in .userDidTriggerManualRefresh userInfo")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-01 19:55:10 -08:00
|
|
|
|
coordinator?.cleanUp(conditional: true)
|
2020-03-11 14:47:00 -06:00
|
|
|
|
AccountManager.shared.refreshAll(errorHandler: errorHandler)
|
|
|
|
|
}
|
2025-01-22 22:18:09 -08:00
|
|
|
|
|
2025-02-01 21:38:43 -08:00
|
|
|
|
@objc func userDefaultsDidChange(_ note: Notification) {
|
|
|
|
|
updateUserInterfaceStyle()
|
2018-02-05 13:29:46 -08:00
|
|
|
|
}
|
2025-02-01 21:38:43 -08:00
|
|
|
|
}
|
2025-01-03 11:48:19 -08:00
|
|
|
|
|
2025-02-01 21:38:43 -08:00
|
|
|
|
// MARK: - UNUserNotificationCenterDelegate
|
2020-04-21 20:23:46 -05:00
|
|
|
|
|
2025-02-01 21:38:43 -08:00
|
|
|
|
extension AppDelegate {
|
2025-01-22 22:18:09 -08:00
|
|
|
|
|
2019-10-02 19:42:16 -05:00
|
|
|
|
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
|
2024-11-03 22:40:38 -08:00
|
|
|
|
completionHandler([.list, .banner, .badge, .sound])
|
2019-10-02 19:42:16 -05:00
|
|
|
|
}
|
2025-01-22 22:18:09 -08:00
|
|
|
|
|
2025-02-01 17:48:47 -08:00
|
|
|
|
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
|
2019-10-03 09:53:21 -05:00
|
|
|
|
defer { completionHandler() }
|
2025-01-22 22:18:09 -08:00
|
|
|
|
|
2020-12-23 20:15:25 +08:00
|
|
|
|
let userInfo = response.notification.request.content.userInfo
|
2025-01-22 22:18:09 -08:00
|
|
|
|
|
2020-12-23 20:15:25 +08:00
|
|
|
|
switch response.actionIdentifier {
|
|
|
|
|
case "MARK_AS_READ":
|
|
|
|
|
handleMarkAsRead(userInfo: userInfo)
|
|
|
|
|
case "MARK_AS_STARRED":
|
|
|
|
|
handleMarkAsStarred(userInfo: userInfo)
|
|
|
|
|
default:
|
2025-02-01 17:48:47 -08:00
|
|
|
|
handle(response)
|
|
|
|
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
2025-02-01 19:55:10 -08:00
|
|
|
|
self.coordinator?.dismissIfLaunchingFromExternalAction()
|
2020-12-23 20:15:25 +08:00
|
|
|
|
}
|
2019-10-03 09:53:21 -05:00
|
|
|
|
}
|
2025-02-01 17:48:47 -08:00
|
|
|
|
}
|
2018-02-05 13:29:46 -08:00
|
|
|
|
}
|
|
|
|
|
|
2025-02-01 21:38:43 -08:00
|
|
|
|
// MARK: - Home Screen Quick Actions
|
2019-09-01 16:54:07 -05:00
|
|
|
|
|
|
|
|
|
private extension AppDelegate {
|
2025-01-22 22:18:09 -08:00
|
|
|
|
|
2025-02-01 20:33:50 -08:00
|
|
|
|
enum ShortcutItemType: String {
|
|
|
|
|
case firstUnread = "com.ranchero.NetNewsWire.FirstUnread"
|
|
|
|
|
case showSearch = "com.ranchero.NetNewsWire.ShowSearch"
|
|
|
|
|
case addFeed = "com.ranchero.NetNewsWire.ShowAdd"
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-01 21:38:43 -08:00
|
|
|
|
private func addHomeScreenQuickActions() {
|
2019-09-01 16:54:07 -05:00
|
|
|
|
let unreadTitle = NSLocalizedString("First Unread", comment: "First Unread")
|
2019-09-26 15:51:16 -05:00
|
|
|
|
let unreadIcon = UIApplicationShortcutIcon(systemImageName: "chevron.down.circle")
|
2025-02-01 20:33:50 -08:00
|
|
|
|
let unreadItem = UIApplicationShortcutItem(type: ShortcutItemType.firstUnread.rawValue, localizedTitle: unreadTitle, localizedSubtitle: nil, icon: unreadIcon, userInfo: nil)
|
2025-01-22 22:18:09 -08:00
|
|
|
|
|
2019-09-01 16:54:07 -05:00
|
|
|
|
let searchTitle = NSLocalizedString("Search", comment: "Search")
|
|
|
|
|
let searchIcon = UIApplicationShortcutIcon(systemImageName: "magnifyingglass")
|
2025-02-01 20:33:50 -08:00
|
|
|
|
let searchItem = UIApplicationShortcutItem(type: ShortcutItemType.showSearch.rawValue, localizedTitle: searchTitle, localizedSubtitle: nil, icon: searchIcon, userInfo: nil)
|
2019-09-01 16:54:07 -05:00
|
|
|
|
|
2019-09-02 15:45:09 -05:00
|
|
|
|
let addTitle = NSLocalizedString("Add Feed", comment: "Add Feed")
|
2019-09-02 15:14:26 -05:00
|
|
|
|
let addIcon = UIApplicationShortcutIcon(systemImageName: "plus")
|
2025-02-01 20:33:50 -08:00
|
|
|
|
let addItem = UIApplicationShortcutItem(type: ShortcutItemType.addFeed.rawValue, localizedTitle: addTitle, localizedSubtitle: nil, icon: addIcon, userInfo: nil)
|
2019-09-02 15:14:26 -05:00
|
|
|
|
|
2019-09-02 16:05:55 -05:00
|
|
|
|
UIApplication.shared.shortcutItems = [addItem, searchItem, unreadItem]
|
2019-09-01 16:54:07 -05:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-01 17:34:45 -08:00
|
|
|
|
// MARK: - Private
|
|
|
|
|
|
|
|
|
|
private extension AppDelegate {
|
|
|
|
|
|
|
|
|
|
func updateUserInterfaceStyle() {
|
|
|
|
|
|
|
|
|
|
assert(Thread.isMainThread)
|
2025-02-01 19:37:59 -08:00
|
|
|
|
guard let window else {
|
2025-02-01 17:55:37 -08:00
|
|
|
|
// Could be nil legitimately — this can get called before window is set up.
|
2025-02-01 17:34:45 -08:00
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let updatedStyle = AppDefaults.userInterfaceColorPalette.uiUserInterfaceStyle
|
|
|
|
|
if window.overrideUserInterfaceStyle != updatedStyle {
|
|
|
|
|
window.overrideUserInterfaceStyle = updatedStyle
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-01 21:38:43 -08:00
|
|
|
|
// MARK: - BackgroundTaskManagerDelegate
|
2025-01-22 22:18:09 -08:00
|
|
|
|
|
2025-02-01 21:38:43 -08:00
|
|
|
|
extension AppDelegate: BackgroundTaskManagerDelegate {
|
2025-01-22 22:18:09 -08:00
|
|
|
|
|
2025-02-01 21:38:43 -08:00
|
|
|
|
func backgroundTaskManagerApplicationShouldSuspend(_: BackgroundTaskManager) {
|
|
|
|
|
suspendApplication()
|
2019-06-19 23:26:03 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2020-12-23 20:15:25 +08:00
|
|
|
|
|
2025-02-01 19:43:44 -08:00
|
|
|
|
// MARK: - Handle Notification Actions
|
2020-12-23 20:15:25 +08:00
|
|
|
|
|
|
|
|
|
private extension AppDelegate {
|
2025-01-22 22:18:09 -08:00
|
|
|
|
|
2020-12-23 20:15:25 +08:00
|
|
|
|
func handleMarkAsRead(userInfo: [AnyHashable: Any]) {
|
2025-02-01 22:11:48 -08:00
|
|
|
|
handleMarked(userInfo: userInfo, statusKey: .read)
|
2020-12-23 20:15:25 +08:00
|
|
|
|
}
|
2025-01-22 22:18:09 -08:00
|
|
|
|
|
2020-12-23 20:15:25 +08:00
|
|
|
|
func handleMarkAsStarred(userInfo: [AnyHashable: Any]) {
|
2025-02-01 22:11:48 -08:00
|
|
|
|
handleMarked(userInfo: userInfo, statusKey: .starred)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func handleMarked(userInfo: [AnyHashable: Any], statusKey: ArticleStatus.Key) {
|
|
|
|
|
|
2025-01-22 22:18:09 -08:00
|
|
|
|
guard let articlePathUserInfo = userInfo[UserInfoKey.articlePath] as? [AnyHashable: Any],
|
2020-12-23 20:15:25 +08:00
|
|
|
|
let accountID = articlePathUserInfo[ArticlePathKey.accountID] as? String,
|
|
|
|
|
let articleID = articlePathUserInfo[ArticlePathKey.articleID] as? String else {
|
|
|
|
|
return
|
|
|
|
|
}
|
2025-02-01 22:11:48 -08:00
|
|
|
|
|
2025-02-01 13:28:49 -08:00
|
|
|
|
AccountManager.shared.resumeAllIfSuspended()
|
2025-02-01 22:11:48 -08:00
|
|
|
|
|
|
|
|
|
guard let account = AccountManager.shared.existingAccount(with: accountID) else {
|
|
|
|
|
logger.debug("No account found from notification with accountID \(accountID).")
|
2020-12-23 20:15:25 +08:00
|
|
|
|
return
|
|
|
|
|
}
|
2025-02-01 22:11:48 -08:00
|
|
|
|
guard let article = try? account.fetchArticles(.articleIDs([articleID])) else {
|
|
|
|
|
logger.debug("No articles found from search using \(articleID)")
|
2020-12-23 20:15:25 +08:00
|
|
|
|
return
|
|
|
|
|
}
|
2025-02-01 22:11:48 -08:00
|
|
|
|
|
|
|
|
|
account.markArticles(article, statusKey: statusKey, flag: true) { _ in }
|
|
|
|
|
prepareAccountsForBackground()
|
|
|
|
|
account.syncArticleStatus { _ in
|
2020-12-23 21:16:32 +08:00
|
|
|
|
if !AccountManager.shared.isSuspended {
|
2025-02-01 22:11:48 -08:00
|
|
|
|
self.prepareAccountsForBackground()
|
|
|
|
|
self.suspendApplication()
|
2020-12-23 20:15:25 +08:00
|
|
|
|
}
|
2025-02-01 22:11:48 -08:00
|
|
|
|
}
|
2020-12-23 20:15:25 +08:00
|
|
|
|
}
|
2025-02-01 17:48:47 -08:00
|
|
|
|
|
|
|
|
|
func handle(_ response: UNNotificationResponse) {
|
|
|
|
|
AccountManager.shared.resumeAllIfSuspended()
|
2025-02-01 19:55:10 -08:00
|
|
|
|
coordinator?.handle(response)
|
2025-02-01 17:48:47 -08:00
|
|
|
|
}
|
2020-12-23 20:15:25 +08:00
|
|
|
|
}
|