140 lines
5.0 KiB
Swift
140 lines
5.0 KiB
Swift
//
|
|
// ShareViewController.swift
|
|
// ShareExtension
|
|
//
|
|
// Created by Shadowfacts on 4/17/23.
|
|
// Copyright © 2023 Shadowfacts. All rights reserved.
|
|
//
|
|
|
|
import SwiftUI
|
|
import UserAccounts
|
|
import ComposeUI
|
|
import UniformTypeIdentifiers
|
|
import TuskerPreferences
|
|
import Combine
|
|
|
|
class ShareViewController: UIViewController {
|
|
|
|
private var state: State = .loading
|
|
|
|
required init?(coder: NSCoder) {
|
|
super.init(coder: coder)
|
|
}
|
|
|
|
override func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
|
|
view.tintColor = Preferences.shared.accentColor.color
|
|
|
|
if let account = UserAccountsManager.shared.getMostRecentAccount() {
|
|
Task { @MainActor in
|
|
let draft = await createDraft(account: account)
|
|
state = .ok
|
|
|
|
let context = ShareMastodonContext(accountInfo: account)
|
|
let host = ShareHostingController(draft: draft, mastodonContext: context)
|
|
host.view.translatesAutoresizingMaskIntoConstraints = false
|
|
addChild(host)
|
|
self.view.addSubview(host.view)
|
|
NSLayoutConstraint.activate([
|
|
host.view.leadingAnchor.constraint(equalTo: self.view.leadingAnchor),
|
|
host.view.trailingAnchor.constraint(equalTo: self.view.trailingAnchor),
|
|
host.view.topAnchor.constraint(equalTo: self.view.topAnchor),
|
|
host.view.bottomAnchor.constraint(equalTo: self.view.bottomAnchor),
|
|
])
|
|
host.didMove(toParent: self)
|
|
}
|
|
} else {
|
|
state = .notLoggedIn
|
|
}
|
|
}
|
|
|
|
private func createDraft(account: UserAccountInfo) async -> Draft {
|
|
let (text, attachments) = await getDraftConfigurationFromExtensionContext()
|
|
|
|
let draft = DraftsPersistentContainer.shared.createDraft(
|
|
accountID: account.id,
|
|
text: text,
|
|
contentWarning: "",
|
|
inReplyToID: nil,
|
|
visibility: Preferences.shared.defaultPostVisibility,
|
|
localOnly: false
|
|
)
|
|
|
|
for attachment in attachments {
|
|
DraftsPersistentContainer.shared.viewContext.insert(attachment)
|
|
}
|
|
draft.draftAttachments = attachments
|
|
|
|
return draft
|
|
}
|
|
|
|
private func getDraftConfigurationFromExtensionContext() async -> (String, [DraftAttachment]) {
|
|
guard let extensionContext,
|
|
let inputItem = (extensionContext.inputItems as? [NSExtensionItem])?.first,
|
|
let itemProvider = inputItem.attachments?.first else {
|
|
return ("", [])
|
|
}
|
|
if let url: NSURL = await getObject(from: itemProvider) {
|
|
if let title = inputItem.attributedTitle ?? inputItem.attributedContentText {
|
|
return ("\n\n\(title.string)\n\(url.absoluteString ?? "")", [])
|
|
} else {
|
|
return ("\n\n\(url.absoluteString ?? "")", [])
|
|
}
|
|
} else if let text: NSString = await getObject(from: itemProvider) {
|
|
return ("\n\n\(text)", [])
|
|
} else if let attributedContent = inputItem.attributedContentText {
|
|
return ("\n\n\(attributedContent.string)", [])
|
|
} else {
|
|
let attachments = await withTaskGroup(of: DraftAttachment?.self, returning: [DraftAttachment].self) { group in
|
|
for provider in inputItem.attachments! {
|
|
group.addTask { @MainActor in
|
|
await self.getObject(from: provider)
|
|
}
|
|
}
|
|
|
|
return await group.reduce(into: [], { partialResult, result in
|
|
if let result {
|
|
partialResult.append(result)
|
|
}
|
|
})
|
|
}
|
|
return ("", attachments)
|
|
}
|
|
}
|
|
|
|
private func getObject<T: NSItemProviderReading>(from itemProvider: NSItemProvider) async -> T? {
|
|
guard itemProvider.canLoadObject(ofClass: T.self) else {
|
|
return nil
|
|
}
|
|
return await withCheckedContinuation({ continuation in
|
|
itemProvider.loadObject(ofClass: T.self) { object, error in
|
|
continuation.resume(returning: object as? T)
|
|
}
|
|
})
|
|
}
|
|
|
|
override func viewDidAppear(_ animated: Bool) {
|
|
super.viewDidAppear(animated)
|
|
|
|
if case .notLoggedIn = state {
|
|
let alert = UIAlertController(title: "Not Logged In", message: "You need to log in to an account through the app before you can post.", preferredStyle: .alert)
|
|
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: { [unowned self] _ in
|
|
self.extensionContext!.cancelRequest(withError: Error.notLoggedIn)
|
|
}))
|
|
present(alert, animated: true)
|
|
}
|
|
}
|
|
|
|
enum State {
|
|
case loading
|
|
case notLoggedIn
|
|
case ok
|
|
}
|
|
|
|
enum Error: Swift.Error {
|
|
case notLoggedIn
|
|
}
|
|
|
|
}
|