krz/domain-dig

an ios app for DNS & SSL analysis

clone: git clone https://gitbay.org/krz/domain-dig.git

v4.4.1: 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}