mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-31 21:59:10 +08:00
329839e467
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added iOS sharing for URLs, text, web pages, and images. * Shared content can be reviewed, titled, and saved to an AFFiNE workspace. * Choose destinations including workspaces, tags, and collections. * Added previews, attachment handling, import status, retry support, and success/error feedback. * Pending shares are processed when AFFiNE opens or returns to the foreground. * **Bug Fixes** * Improved workspace profile handling across different workspace types. * Onboarding completion is now recorded immediately after successful sign-in verification. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com>
90 lines
2.5 KiB
Swift
90 lines
2.5 KiB
Swift
//
|
|
// ShareViewController.swift
|
|
// ShareExtension
|
|
//
|
|
|
|
import SwiftUI
|
|
import UIKit
|
|
|
|
final class ShareViewController: UIViewController {
|
|
private let viewModel = ShareViewModel()
|
|
private var hostingController: UIHostingController<ShareExtensionView>?
|
|
|
|
override func viewDidLoad() {
|
|
super.viewDidLoad()
|
|
view.backgroundColor = .systemBackground
|
|
|
|
let rootView = ShareExtensionView(
|
|
viewModel: viewModel,
|
|
onCancel: { [weak self] in
|
|
self?.cancel()
|
|
},
|
|
onSave: { [weak self] in
|
|
self?.save()
|
|
}
|
|
)
|
|
let hosting = UIHostingController(rootView: rootView)
|
|
hostingController = hosting
|
|
addChild(hosting)
|
|
view.addSubview(hosting.view)
|
|
hosting.view.translatesAutoresizingMaskIntoConstraints = false
|
|
NSLayoutConstraint.activate([
|
|
hosting.view.topAnchor.constraint(equalTo: view.topAnchor),
|
|
hosting.view.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
|
hosting.view.trailingAnchor.constraint(equalTo: view.trailingAnchor),
|
|
hosting.view.bottomAnchor.constraint(equalTo: view.bottomAnchor),
|
|
])
|
|
hosting.didMove(toParent: self)
|
|
|
|
Task {
|
|
await viewModel.load(from: extensionContext)
|
|
}
|
|
}
|
|
|
|
private func cancel() {
|
|
extensionContext?.completeRequest(returningItems: nil)
|
|
}
|
|
|
|
private func save() {
|
|
Task { [weak self] in
|
|
guard let self else { return }
|
|
let success = await viewModel.save()
|
|
guard success else { return }
|
|
_ = await openMainAppIfPossible()
|
|
extensionContext?.completeRequest(returningItems: nil, completionHandler: nil)
|
|
}
|
|
}
|
|
|
|
@discardableResult
|
|
private func openMainAppIfPossible() async -> Bool {
|
|
let url = ShareInboxConstants.openInboxURL
|
|
let openedByContext = await withCheckedContinuation { continuation in
|
|
extensionContext?.open(url) { success in
|
|
continuation.resume(returning: success)
|
|
} ?? continuation.resume(returning: false)
|
|
}
|
|
let opened = openedByContext || openMainAppViaResponderChain(url)
|
|
#if DEBUG
|
|
NSLog(
|
|
"[AFFiNE Share] open url=%@ extensionContext=%@ final=%@",
|
|
url.absoluteString,
|
|
openedByContext ? "YES" : "NO",
|
|
opened ? "YES" : "NO"
|
|
)
|
|
#endif
|
|
return opened
|
|
}
|
|
|
|
private func openMainAppViaResponderChain(_ url: URL) -> Bool {
|
|
var responder: UIResponder? = self
|
|
while let current = responder {
|
|
if let application = current as? UIApplication {
|
|
application.open(url, options: [:], completionHandler: nil)
|
|
return true
|
|
}
|
|
responder = current.next
|
|
}
|
|
return false
|
|
}
|
|
}
|