125 lines
3.3 KiB
Swift
125 lines
3.3 KiB
Swift
//
|
|
// UserActivityHandlingContext.swift
|
|
// Tusker
|
|
//
|
|
// Created by Shadowfacts on 2/25/23.
|
|
// Copyright © 2023 Shadowfacts. All rights reserved.
|
|
//
|
|
|
|
import UIKit
|
|
#if canImport(Duckable)
|
|
import Duckable
|
|
#endif
|
|
import ComposeUI
|
|
|
|
@MainActor
|
|
protocol UserActivityHandlingContext {
|
|
var isHandoff: Bool { get }
|
|
|
|
func select(route: TuskerRoute)
|
|
func present(_ vc: UIViewController)
|
|
|
|
var topViewController: UIViewController? { get }
|
|
func popToRoot()
|
|
func push(_ vc: UIViewController)
|
|
|
|
func compose(editing draft: Draft)
|
|
|
|
func finalize(activity: NSUserActivity)
|
|
}
|
|
|
|
struct ActiveAccountUserActivityHandlingContext: UserActivityHandlingContext {
|
|
let isHandoff: Bool
|
|
let root: TuskerRootViewController
|
|
var navigationDelegate: TuskerNavigationDelegate {
|
|
root.getNavigationDelegate()!
|
|
}
|
|
|
|
func select(route: TuskerRoute) {
|
|
root.select(route: route, animated: true)
|
|
}
|
|
|
|
func present(_ vc: UIViewController) {
|
|
navigationDelegate.present(vc, animated: true)
|
|
}
|
|
|
|
var topViewController: UIViewController? { root.getNavigationController().topViewController }
|
|
|
|
func popToRoot() {
|
|
_ = root.getNavigationController().popToRootViewController(animated: true)
|
|
}
|
|
|
|
func push(_ vc: UIViewController) {
|
|
navigationDelegate.show(vc, sender: nil)
|
|
}
|
|
|
|
func compose(editing draft: Draft) {
|
|
navigationDelegate.compose(editing: draft, animated: true, isDucked: true)
|
|
}
|
|
|
|
func finalize(activity: NSUserActivity) {
|
|
}
|
|
}
|
|
|
|
class StateRestorationUserActivityHandlingContext: UserActivityHandlingContext {
|
|
private var state = State.initial
|
|
let root: TuskerRootViewController
|
|
|
|
init(root: TuskerRootViewController) {
|
|
self.root = root
|
|
}
|
|
|
|
var isHandoff: Bool { false }
|
|
|
|
func select(route: TuskerRoute) {
|
|
root.select(route: route, animated: false)
|
|
state = .selectedRoute
|
|
}
|
|
|
|
var topViewController: UIViewController? { root.getNavigationController().topViewController }
|
|
|
|
func popToRoot() {
|
|
// unnecessary during state restoration
|
|
}
|
|
|
|
func push(_ vc: UIViewController) {
|
|
precondition(state >= .selectedRoute)
|
|
root.getNavigationController().pushViewController(vc, animated: false)
|
|
state = .pushed
|
|
}
|
|
|
|
func present(_ vc: UIViewController) {
|
|
root.present(vc, animated: false)
|
|
state = .presented
|
|
}
|
|
|
|
func compose(editing draft: Draft) {
|
|
if #available(iOS 16.0, *),
|
|
UIDevice.current.userInterfaceIdiom == .phone {
|
|
self.root.compose(editing: draft, animated: false, isDucked: true)
|
|
} else {
|
|
DispatchQueue.main.async {
|
|
self.root.compose(editing: draft, animated: true, isDucked: false)
|
|
}
|
|
}
|
|
state = .presented
|
|
}
|
|
|
|
func finalize(activity: NSUserActivity) {
|
|
precondition(state > .initial)
|
|
#if !os(visionOS)
|
|
if #available(iOS 16.0, *),
|
|
let duckedDraft = UserActivityManager.getDuckedDraft(from: activity) {
|
|
self.root.compose(editing: duckedDraft, animated: false, isDucked: true)
|
|
}
|
|
#endif
|
|
}
|
|
|
|
enum State: Comparable {
|
|
case initial
|
|
case selectedRoute
|
|
case pushed
|
|
case presented
|
|
}
|
|
}
|