2021-12-08 02:58:02 +00:00
|
|
|
//
|
|
|
|
// AppDelegate.swift
|
|
|
|
// Reader
|
|
|
|
//
|
|
|
|
// Created by Shadowfacts on 10/29/21.
|
|
|
|
//
|
|
|
|
|
|
|
|
import UIKit
|
2022-01-14 23:59:51 +00:00
|
|
|
import WebKit
|
|
|
|
import OSLog
|
2022-01-16 16:58:28 +00:00
|
|
|
import Combine
|
2022-06-19 18:56:56 +00:00
|
|
|
import Persistence
|
2022-06-22 20:05:06 +00:00
|
|
|
import BackgroundTasks
|
2021-12-08 02:58:02 +00:00
|
|
|
|
|
|
|
@main
|
|
|
|
class AppDelegate: UIResponder, UIApplicationDelegate {
|
2022-01-16 16:58:28 +00:00
|
|
|
|
|
|
|
private var cancellables = Set<AnyCancellable>()
|
2022-01-16 17:32:45 +00:00
|
|
|
|
|
|
|
#if targetEnvironment(macCatalyst)
|
|
|
|
private var readerMac: NSObject!
|
|
|
|
#endif
|
2021-12-08 02:58:02 +00:00
|
|
|
|
|
|
|
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
|
2022-06-15 22:37:53 +00:00
|
|
|
LocalData.migrateIfNecessary()
|
|
|
|
|
2022-01-14 23:59:51 +00:00
|
|
|
swizzleWKWebView()
|
|
|
|
|
2022-01-16 16:58:28 +00:00
|
|
|
Preferences.shared.objectWillChange
|
|
|
|
.debounce(for: .milliseconds(250), scheduler: RunLoop.main)
|
|
|
|
.sink { _ in
|
|
|
|
Preferences.save()
|
|
|
|
}
|
|
|
|
.store(in: &cancellables)
|
|
|
|
|
2022-01-16 17:32:45 +00:00
|
|
|
#if targetEnvironment(macCatalyst)
|
|
|
|
let macBundleURL = Bundle.main.builtInPlugInsURL!.appendingPathComponent("ReaderMac.bundle")
|
|
|
|
let bundle = Bundle(url: macBundleURL)!
|
|
|
|
do {
|
|
|
|
try bundle.loadAndReturnError()
|
|
|
|
|
|
|
|
let clazz = NSClassFromString("ReaderMac.ReaderMac")! as! NSObject.Type
|
|
|
|
readerMac = clazz.init()
|
|
|
|
readerMac.perform(Selector(("setup")))
|
|
|
|
} catch {
|
|
|
|
print("Unable to load ReaderMac bundle: \(error)")
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
NotificationCenter.default.addObserver(self, selector: #selector(updateAppearance), name: .appearanceChanged, object: nil)
|
|
|
|
updateAppearance()
|
|
|
|
|
2022-06-22 20:05:06 +00:00
|
|
|
BGTaskScheduler.shared.register(forTaskWithIdentifier: BackgroundManager.refreshIdentifier, using: nil) { task in
|
|
|
|
Task {
|
|
|
|
BackgroundManager.shared.handleBackgroundRefresh(task: task as! BGAppRefreshTask)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-08 02:58:02 +00:00
|
|
|
return true
|
|
|
|
}
|
2022-06-22 20:05:06 +00:00
|
|
|
|
|
|
|
func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
|
|
|
|
if identifier == BackgroundManager.refreshIdentifier {
|
|
|
|
BackgroundManager.shared.doRefresh()
|
|
|
|
} else {
|
|
|
|
fatalError("Unknown background url session identifier: \(identifier)")
|
|
|
|
}
|
|
|
|
}
|
2021-12-08 02:58:02 +00:00
|
|
|
|
|
|
|
// MARK: UISceneSession Lifecycle
|
|
|
|
|
|
|
|
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
|
2022-01-16 16:58:28 +00:00
|
|
|
let name: String
|
|
|
|
#if targetEnvironment(macCatalyst)
|
|
|
|
if options.userActivities.first?.activityType == NSUserActivity.preferencesType {
|
|
|
|
name = "prefs"
|
|
|
|
} else {
|
|
|
|
name = "main"
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
name = "main"
|
|
|
|
#endif
|
|
|
|
return UISceneConfiguration(name: name, sessionRole: connectingSceneSession.role)
|
2021-12-08 02:58:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
|
|
|
|
// Called when the user discards a scene session.
|
|
|
|
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
|
|
|
|
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
|
|
|
|
}
|
2022-01-14 23:59:51 +00:00
|
|
|
|
2022-01-15 19:09:30 +00:00
|
|
|
override func buildMenu(with builder: UIMenuBuilder) {
|
|
|
|
if builder.system == .main {
|
2022-01-16 16:58:28 +00:00
|
|
|
builder.insertSibling(UIMenu(options: .displayInline, children: [
|
|
|
|
UIKeyCommand(title: "Preferences…", action: #selector(showPreferences), input: ",", modifierFlags: .command)
|
|
|
|
]), afterMenu: .about)
|
2022-01-16 16:17:30 +00:00
|
|
|
|
|
|
|
var children = [UIMenuElement]()
|
|
|
|
let accounts: [UIMenuElement] = LocalData.accounts.map { account in
|
2022-01-15 19:09:30 +00:00
|
|
|
var title = account.instanceURL.host!
|
|
|
|
if let port = account.instanceURL.port, port != 80 && port != 443 {
|
|
|
|
title += ":\(port)"
|
|
|
|
}
|
|
|
|
|
|
|
|
let state: UIAction.State
|
|
|
|
if let activeScene = UIApplication.shared.connectedScenes.first(where: { $0.activationState == .foregroundActive }),
|
2022-01-16 16:58:28 +00:00
|
|
|
let sceneDelegate = activeScene.delegate as? SceneDelegate,
|
|
|
|
sceneDelegate.fervorController?.account?.id == account.id {
|
2022-01-15 19:09:30 +00:00
|
|
|
state = .on
|
|
|
|
} else {
|
|
|
|
state = .off
|
|
|
|
}
|
|
|
|
return UIAction(title: title, attributes: [], state: state) { _ in
|
|
|
|
let activity = NSUserActivity.activateAccount(account)
|
|
|
|
let options = UIScene.ActivationRequestOptions()
|
|
|
|
#if targetEnvironment(macCatalyst)
|
|
|
|
options.collectionJoinBehavior = .disallowed
|
|
|
|
#endif
|
|
|
|
UIApplication.shared.requestSceneSessionActivation(nil, userActivity: activity, options: options, errorHandler: nil)
|
|
|
|
}
|
|
|
|
}
|
2022-01-16 16:17:30 +00:00
|
|
|
children.append(UIMenu(options: .displayInline, children: accounts))
|
2022-01-15 19:09:30 +00:00
|
|
|
children.append(UIAction(title: "Add Account...", handler: { _ in
|
|
|
|
let activity = NSUserActivity.addAccount()
|
|
|
|
let options = UIScene.ActivationRequestOptions()
|
|
|
|
#if targetEnvironment(macCatalyst)
|
|
|
|
options.collectionJoinBehavior = .disallowed
|
|
|
|
#endif
|
|
|
|
UIApplication.shared.requestSceneSessionActivation(nil, userActivity: activity, options: options, errorHandler: nil)
|
|
|
|
}))
|
|
|
|
let account = UIMenu(title: "Account", image: nil, identifier: nil, options: [], children: children)
|
|
|
|
builder.insertSibling(account, afterMenu: .file)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-31 02:21:46 +00:00
|
|
|
// this workaround is no longer necessary (in fact, it causes a stack overflow) post-iOS 15.4 because of:
|
|
|
|
// https://github.com/WebKit/WebKit/commit/1dbd34cf01d8b5aedcb8820b13cb6553ed60e8ed
|
|
|
|
@available(iOS, obsoleted: 15.4)
|
2022-01-14 23:59:51 +00:00
|
|
|
private func swizzleWKWebView() {
|
2022-01-31 02:21:46 +00:00
|
|
|
if #available(iOS 15.4, *) {
|
|
|
|
} else {
|
|
|
|
let selector = Selector(("_updateScrollViewBackground"))
|
|
|
|
var originalIMP: IMP?
|
|
|
|
let imp = imp_implementationWithBlock({ (self: WKWebView) in
|
|
|
|
if let originalIMP = originalIMP {
|
|
|
|
let original = unsafeBitCast(originalIMP, to: (@convention(c) (WKWebView, Selector) -> Void).self)
|
|
|
|
original(self, selector)
|
|
|
|
}
|
|
|
|
|
|
|
|
self.scrollView.indicatorStyle = .default
|
|
|
|
|
|
|
|
} as (@convention(block) (WKWebView) -> Void))
|
|
|
|
originalIMP = class_replaceMethod(WKWebView.self, selector, imp, "v@:")
|
|
|
|
if originalIMP == nil {
|
2022-01-14 23:59:51 +00:00
|
|
|
os_log(.error, "Missing originalIMP for -[WKWebView _updateScrollViewBackground], did WebKit change?")
|
|
|
|
}
|
2022-01-31 02:21:46 +00:00
|
|
|
}
|
2022-01-14 23:59:51 +00:00
|
|
|
}
|
2022-01-16 16:58:28 +00:00
|
|
|
|
|
|
|
@objc private func showPreferences() {
|
2022-01-16 17:32:45 +00:00
|
|
|
let existing = UIApplication.shared.connectedScenes.first {
|
|
|
|
$0.session.configuration.name == "prefs"
|
|
|
|
}
|
|
|
|
UIApplication.shared.requestSceneSessionActivation(existing?.session, userActivity: .preferences(), options: nil, errorHandler: nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
@objc private func updateAppearance() {
|
|
|
|
#if targetEnvironment(macCatalyst)
|
|
|
|
readerMac.perform(Selector(("updateAppearance:")), with: Preferences.shared.appearance.rawValue)
|
|
|
|
#endif
|
2022-01-16 16:58:28 +00:00
|
|
|
}
|
2021-12-08 02:58:02 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|