Tusker/Tusker/Scenes/ComposeSceneDelegate.swift

129 lines
4.6 KiB
Swift

//
// ComposeSceneDelegate.swift
// Tusker
//
// Created by Shadowfacts on 12/12/20.
// Copyright © 2020 Shadowfacts. All rights reserved.
//
import UIKit
import Combine
import UserAccounts
import ComposeUI
class ComposeSceneDelegate: UIResponder, UIWindowSceneDelegate, TuskerSceneDelegate {
var window: UIWindow?
var rootViewController: TuskerRootViewController? { nil }
private var cancellables = Set<AnyCancellable>()
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = scene as? UIWindowScene else {
return
}
guard UserAccountsManager.shared.onboardingComplete else {
UIApplication.shared.requestSceneSessionDestruction(session, options: nil, errorHandler: nil)
return
}
let account: UserAccountInfo
let controller: MastodonController
let draft: Draft?
if let activity = connectionOptions.userActivities.first ?? session.stateRestorationActivity {
if let activityAccount = UserActivityManager.getAccount(from: activity) {
account = activityAccount
} else {
// todo: this potentially changes the account for the draft, should show the same warning to user as in the drafts selection screen
account = UserAccountsManager.shared.getMostRecentAccount()!
}
controller = MastodonController.getForAccount(account)
if let activityDraft = UserActivityManager.getDraft(from: activity) {
draft = activityDraft
} else if let mentioning = activity.userInfo?["mentioning"] as? String {
draft = controller.createDraft(inReplyToID: nil, mentioningAcct: mentioning)
} else {
draft = nil
}
} else {
account = UserAccountsManager.shared.getMostRecentAccount()!
controller = MastodonController.getForAccount(account)
draft = nil
}
session.mastodonController = controller
controller.initialize()
let composeVC = ComposeHostingController(draft: draft, mastodonController: controller)
composeVC.delegate = self
window = UIWindow(windowScene: windowScene)
window!.rootViewController = composeVC
window!.makeKeyAndVisible()
updateTitle(draft: composeVC.controller.draft)
composeVC.controller.$draft
.sink { [unowned self] in self.updateTitle(draft: $0) }
.store(in: &cancellables)
NotificationCenter.default.addObserver(self, selector: #selector(themePrefChanged), name: .themePreferenceChanged, object: nil)
themePrefChanged()
}
func sceneWillResignActive(_ scene: UIScene) {
DraftsPersistentContainer.shared.save()
if let window = window,
let nav = window.rootViewController as? UINavigationController,
let compose = nav.topViewController as? ComposeHostingController,
!compose.controller.didPostSuccessfully {
scene.userActivity = UserActivityManager.editDraftActivity(id: compose.controller.draft.id, accountID: scene.session.mastodonController!.accountInfo!.id)
}
}
func stateRestorationActivity(for scene: UIScene) -> NSUserActivity? {
return scene.userActivity
}
private func updateTitle(draft: Draft) {
// Don't set the scene title on macOS since it shows both that and the VC title in the window titlebar
#if !targetEnvironment(macCatalyst)
guard !ProcessInfo.processInfo.isiOSAppOnMac,
let scene = window?.windowScene,
let mastodonController = scene.session.mastodonController else {
return
}
if let inReplyToID = draft.inReplyToID,
let inReplyTo = mastodonController.persistentContainer.status(for: inReplyToID) {
scene.title = "Reply to @\(inReplyTo.account.acct)"
} else {
scene.title = "New Post"
}
#endif
}
@objc private func themePrefChanged() {
applyAppearancePreferences()
}
}
extension ComposeSceneDelegate: ComposeHostingControllerDelegate {
func dismissCompose(mode: DismissMode) -> Bool {
let animation: UIWindowScene.DismissalAnimation
switch mode {
case .cancel:
animation = .decline
case .post:
animation = .commit
}
closeWindow(animation: animation)
return true
}
}