krz/domain-dig
an ios app for DNS & SSL analysis
clone: git clone https://gitbay.org/krz/domain-dig.git
v4.6.0: DomainDig/CloudSharingSheet.swift · raw
1import CloudKit
2import Foundation
3import SwiftUI
4import UIKit
5
6struct CloudSharingSheet: UIViewControllerRepresentable {
7 @Environment(\.dismiss) private var dismiss
8
9 let entity: ShareableEntity
10 let title: String
11
12 func makeCoordinator() -> Coordinator {
13 Coordinator(dismiss: dismiss, title: title)
14 }
15
16 func makeUIViewController(context: Context) -> UIViewController {
17 UIViewController()
18 }
19
20 func updateUIViewController(_ uiViewController: UIViewController, context: Context) {
21 context.coordinator.presentIfNeeded(from: uiViewController, entity: entity)
22 }
23
24 final class Coordinator: NSObject, UIAdaptivePresentationControllerDelegate {
25 private let dismissAction: DismissAction
26 private let title: String
27 private let observer = CKSystemSharingUIObserver(container: .default())
28 private var hasPresented = false
29
30 init(dismiss: DismissAction, title: String) {
31 self.dismissAction = dismiss
32 self.title = title
33 super.init()
34
35 observer.systemSharingUIDidSaveShareBlock = { _, _ in
36 Task { @MainActor in
37 await CloudSyncService.shared.syncNow(trigger: .manual)
38 }
39 }
40
41 observer.systemSharingUIDidStopSharingBlock = { _, _ in
42 Task { @MainActor in
43 await CloudSyncService.shared.syncNow(trigger: .manual)
44 }
45 }
46 }
47
48 func presentIfNeeded(from presenter: UIViewController, entity: ShareableEntity) {
49 guard !hasPresented else { return }
50 hasPresented = true
51
52 let itemProvider = NSItemProvider()
53 let container = CKContainer.default()
54
55 Task { @MainActor in
56 do {
57 if let existingShare = try await CloudSyncService.shared.existingShare(for: entity) {
58 itemProvider.registerCKShare(existingShare, container: container)
59 } else {
60 itemProvider.registerCKShare(container: container) {
61 try await CloudSyncService.shared.createShare(for: entity)
62 }
63 }
64 } catch {
65 dismissAction()
66 return
67 }
68
69 let configuration = UIActivityItemsConfiguration(itemProviders: [itemProvider])
70 let activityController = UIActivityViewController(activityItemsConfiguration: configuration)
71 activityController.completionWithItemsHandler = { [dismissAction] _, _, _, _ in
72 dismissAction()
73 }
74 activityController.popoverPresentationController?.sourceView = presenter.view
75 activityController.presentationController?.delegate = self
76 presenter.present(activityController, animated: true)
77 }
78 }
79
80 func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
81 dismissAction()
82 }
83 }
84}