crossmate

A collaborative crossword app for iOS
Log | Files | Refs | LICENSE

MailComposeView.swift (2050B)


      1 import MessageUI
      2 import SwiftUI
      3 
      4 /// A plain-text attachment for a `MailComposeView`.
      5 struct MailAttachment {
      6     let data: Data
      7     let mimeType: String
      8     let fileName: String
      9 
     10     /// Convenience for the common case: a UTF-8 `.txt` payload.
     11     static func text(_ string: String, fileName: String) -> MailAttachment {
     12         MailAttachment(data: Data(string.utf8), mimeType: "text/plain", fileName: fileName)
     13     }
     14 }
     15 
     16 /// Wraps `MFMailComposeViewController` for presentation via `.sheet`. Callers
     17 /// should gate presentation on `MFMailComposeViewController.canSendMail()` and
     18 /// provide their own fallback when it returns false.
     19 struct MailComposeView: UIViewControllerRepresentable {
     20     let recipients: [String]
     21     let subject: String
     22     let body: String
     23     var attachment: MailAttachment?
     24     let onFinish: () -> Void
     25 
     26     func makeCoordinator() -> Coordinator {
     27         Coordinator(onFinish: onFinish)
     28     }
     29 
     30     func makeUIViewController(context: Context) -> MFMailComposeViewController {
     31         let controller = MFMailComposeViewController()
     32         controller.mailComposeDelegate = context.coordinator
     33         controller.setToRecipients(recipients)
     34         controller.setSubject(subject)
     35         controller.setMessageBody(body, isHTML: false)
     36         if let attachment {
     37             controller.addAttachmentData(
     38                 attachment.data,
     39                 mimeType: attachment.mimeType,
     40                 fileName: attachment.fileName
     41             )
     42         }
     43         return controller
     44     }
     45 
     46     func updateUIViewController(_ controller: MFMailComposeViewController, context: Context) {}
     47 
     48     final class Coordinator: NSObject, MFMailComposeViewControllerDelegate {
     49         private let onFinish: () -> Void
     50 
     51         init(onFinish: @escaping () -> Void) {
     52             self.onFinish = onFinish
     53         }
     54 
     55         func mailComposeController(
     56             _ controller: MFMailComposeViewController,
     57             didFinishWith result: MFMailComposeResult,
     58             error: Error?
     59         ) {
     60             onFinish()
     61         }
     62     }
     63 }