diff --git a/Sources/StreamChatSwiftUI/ChatChannel/MessageList/Polls/PollAttachmentView.swift b/Sources/StreamChatSwiftUI/ChatChannel/MessageList/Polls/PollAttachmentView.swift index 0fc97086..6f8c8ec0 100644 --- a/Sources/StreamChatSwiftUI/ChatChannel/MessageList/Polls/PollAttachmentView.swift +++ b/Sources/StreamChatSwiftUI/ChatChannel/MessageList/Polls/PollAttachmentView.swift @@ -177,28 +177,16 @@ struct SuggestOptionModifier: ViewModifier { var submit: () -> Void func body(content: Content) -> some View { - if #available(iOS 15.0, *) { - content - .alert(title, isPresented: $showingAlert) { - TextField(L10n.Alert.TextField.pollsNewOption, text: $text) - Button(L10n.Alert.Actions.cancel, role: .cancel) { - showingAlert = false - } - Button(L10n.Alert.Actions.add, action: submit) - } message: { - Text("") - } - } else { - content - .uiAlertController( - title: title, - isPresented: $showingAlert, - text: $text, - textPlaceholder: L10n.Alert.TextField.pollsNewOption, - cancelActionTitle: L10n.Alert.Actions.cancel, - defaultActionTitle: L10n.Alert.Actions.add - ) - } + content + .uiAlert( + title: title, + isPresented: $showingAlert, + text: $text, + placeholder: L10n.Alert.TextField.pollsNewOption, + cancel: L10n.Alert.Actions.cancel, + accept: L10n.Alert.Actions.add, + action: submit + ) } } diff --git a/Sources/StreamChatSwiftUI/Utils/SwiftUI+UIAlertController.swift b/Sources/StreamChatSwiftUI/Utils/SwiftUI+UIAlertController.swift index 175c908f..d79c881c 100644 --- a/Sources/StreamChatSwiftUI/Utils/SwiftUI+UIAlertController.swift +++ b/Sources/StreamChatSwiftUI/Utils/SwiftUI+UIAlertController.swift @@ -4,32 +4,32 @@ import SwiftUI -@available(iOS, deprecated: 15.0, message: "Use .alert()") extension View { /// Presents an alert with a text field for entering text. /// - /// - Note: Only for iOS 14 which lacks text field support. - func uiAlertController( + /// - Note: iOS 14 lacks alert with text field support. + func uiAlert( title: String, isPresented: Binding, message: String = "", text: Binding, - textPlaceholder: String, - cancelActionTitle: String, - defaultActionTitle: String + placeholder: String, + cancel: String, + accept: String, + action: @escaping () -> Void ) -> some View { ZStack { - if isPresented.wrappedValue { - UIAlertControllerView( - isPresented: isPresented, - title: title, - message: message, - text: text, - textPlaceholder: textPlaceholder, - cancelActionTitle: cancelActionTitle, - defaultActionTitle: defaultActionTitle - ) - } + UIAlertControllerView( + isPresented: isPresented, + title: title, + message: message, + text: text, + placeholder: placeholder, + cancel: cancel, + accept: accept, + action: action + ) + .frame(height: 0) self } } @@ -40,56 +40,62 @@ private struct UIAlertControllerView: UIViewControllerRepresentable { let title: String let message: String @Binding var text: String - let textPlaceholder: String - - let cancelActionTitle: String - let defaultActionTitle: String + let placeholder: String + let cancel: String + let accept: String + let action: () -> Void func makeUIViewController(context: Context) -> UIViewController { UIViewController() } func updateUIViewController(_ uiViewController: UIViewController, context: Context) { - guard isPresented else { return } - let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) - alert.addTextField { textField in - textField.delegate = context.coordinator - textField.font = .preferredFont(forTextStyle: .body) - textField.placeholder = textPlaceholder - textField.text = text - } - alert.addAction( - UIAlertAction(title: cancelActionTitle, style: .cancel) { _ in - isPresented = false + if isPresented && uiViewController.presentedViewController == nil { + let alert = UIAlertController(title: title, message: message, preferredStyle: .alert) + context.coordinator.alertController = alert + alert.addTextField { textField in + textField.font = .preferredFont(forTextStyle: .body) + textField.placeholder = placeholder + textField.text = text } - ) - alert.addAction( - UIAlertAction(title: defaultActionTitle, style: .default) { _ in - isPresented = false + alert.addAction( + UIAlertAction(title: cancel, style: .cancel) { _ in + isPresented = false + } + ) + let textField = alert.textFields?.first + alert.addAction( + UIAlertAction(title: accept, style: .default) { _ in + text = textField?.text ?? "" + isPresented = false + action() + } + ) + DispatchQueue.main.async { + uiViewController.present(alert, animated: true) } - ) - DispatchQueue.main.async { - uiViewController.present(alert, animated: true) + } + if !isPresented { + context.coordinator.alertController?.dismiss(animated: true) } } + static func dismantleUIViewController(_ uiViewController: UIViewController, coordinator: Coordinator) { + coordinator.alertController?.dismiss(animated: true) + coordinator.alertController = nil + } + func makeCoordinator() -> Coordinator { - Coordinator { text in - self.text = text - } + Coordinator() } } private extension UIAlertControllerView { final class Coordinator: NSObject, UITextFieldDelegate { - let didChangeSelection: (String) -> Void - - init(didChangeSelection: @escaping (String) -> Void) { - self.didChangeSelection = didChangeSelection - } + var alertController: UIAlertController? - func textFieldDidChangeSelection(_ textField: UITextField) { - didChangeSelection(textField.text ?? "") + init(alertController: UIAlertController? = nil) { + self.alertController = alertController } } }