Files
hapi/ios/Hapi/Features/Scratchlist/ScratchlistDismissGuard.swift
T

46 lines
2.1 KiB
Swift

import SwiftUI
import UIKit
/// SwiftUI's interactiveDismissDisabled blocks the gesture silently. Forward
/// presentation callbacks while offering the same discard choice as Cancel.
struct ScratchlistDismissGuard: UIViewControllerRepresentable {
let blocked: Bool
let onAttempt: () -> Void
func makeCoordinator() -> Coordinator { Coordinator() }
func makeUIViewController(context: Context) -> UIViewController { UIViewController() }
func updateUIViewController(_ controller: UIViewController, context: Context) {
context.coordinator.blocked = blocked
context.coordinator.onAttempt = onAttempt
DispatchQueue.main.async { [weak controller, coordinator = context.coordinator] in
guard var root = controller else { return }
while let parent = root.parent { root = parent }
guard let presentation = root.presentationController else { return }
if presentation.delegate !== coordinator {
coordinator.previous = presentation.delegate
presentation.delegate = coordinator
}
}
}
final class Coordinator: NSObject, UIAdaptivePresentationControllerDelegate {
var blocked = false
var onAttempt: (() -> Void)?
weak var previous: (any UIAdaptivePresentationControllerDelegate)?
func presentationControllerShouldDismiss(_ controller: UIPresentationController) -> Bool {
!blocked && (previous?.presentationControllerShouldDismiss?(controller) ?? true)
}
func presentationControllerDidAttemptToDismiss(_ controller: UIPresentationController) {
if blocked { onAttempt?() }
else { previous?.presentationControllerDidAttemptToDismiss?(controller) }
}
func presentationControllerWillDismiss(_ controller: UIPresentationController) {
previous?.presentationControllerWillDismiss?(controller)
}
func presentationControllerDidDismiss(_ controller: UIPresentationController) {
previous?.presentationControllerDidDismiss?(controller)
}
}
}