// // ContactManager.swift // Padel Tournament // // Created by Razmig Sarkissian on 19/09/2023. // import Foundation import SwiftUI import MessageUI import LeStorage enum ContactManagerError: LocalizedError { case mailFailed case mailNotSent //no network no error case messageFailed case messageNotSent //no network no error } enum ContactType: Identifiable { case mail(date: Date?, recipients: [String]?, bccRecipients: [String]?, body: String?, subject: String?, tournamentBuild: TournamentBuild?) case message(date: Date?, recipients: [String]?, body: String?, tournamentBuild: TournamentBuild?) var id: Int { switch self { case .message: return 0 case .mail: return 1 } } } extension ContactType { static let defaultCustomMessage = "Il est conseillé de vous présenter 10 minutes avant de jouer.\nMerci de confirmer en répondant à ce message et de prévenir votre partenaire." static let defaultSignature = "" static func callingGroupStageCustomMessage(tournament: Tournament?, startDate: Date?, roundLabel: String) -> String { let tournamentCustomMessage = DataStore.shared.appSettings.callMessageBody ?? defaultCustomMessage let clubName = tournament?.clubName ?? "" var text = tournamentCustomMessage let date = startDate ?? tournament?.startDate ?? Date() if let tournament { text = text.replacingOccurrences(of: "#titre", with: tournament.tournamentTitle()) } text = text.replacingOccurrences(of: "#club", with: clubName) text = text.replacingOccurrences(of: "#round", with: roundLabel) text = text.replacingOccurrences(of: "#jour", with: "\(date.formatted(Date.FormatStyle().weekday(.wide).day().month(.wide)))") text = text.replacingOccurrences(of: "#horaire", with: "\(date.formatted(Date.FormatStyle().hour().minute()))") let signature = DataStore.shared.appSettings.callMessageSignature ?? defaultSignature text = text.replacingOccurrences(of: "#signature", with: signature) return text } static func callingGroupStageMessage(tournament: Tournament?, startDate: Date?, roundLabel: String, matchFormat: MatchFormat?) -> String { let useFullCustomMessage = DataStore.shared.appSettings.callUseFullCustomMessage ?? false if useFullCustomMessage { return callingGroupStageCustomMessage(tournament: tournament, startDate: startDate, roundLabel: roundLabel) } let date = startDate ?? tournament?.startDate ?? Date() let clubName = tournament?.clubName ?? "" let message = DataStore.shared.appSettings.callMessageBody ?? defaultCustomMessage let signature = DataStore.shared.appSettings.callMessageSignature ?? defaultSignature let localizedCalled = "convoqué" + (tournament?.tournamentCategory == .women ? "e" : "") + "s" var formatMessage: String? { (DataStore.shared.appSettings.callDisplayFormat ?? false) ? matchFormat?.computedLongLabel.appending(".") : nil } var entryFeeMessage: String? { (DataStore.shared.appSettings.callDisplayEntryFee ?? false) ? tournament?.entryFeeMessage : nil } var computedMessage: String { [formatMessage, entryFeeMessage, message].compacted().map { $0.trimmed }.joined(separator: "\n") } if let tournament { return "Bonjour,\n\nVous êtes \(localizedCalled) pour jouer en \(roundLabel.lowercased()) du \(tournament.tournamentTitle()) au \(clubName) le \(date.formatted(Date.FormatStyle().weekday(.wide).day().month(.wide))) à \(date.formatted(Date.FormatStyle().hour().minute())).\n\n" + computedMessage + "\n\n\(signature)" } else { return "Bonjour,\n\nVous êtes \(localizedCalled) \(roundLabel) au \(clubName) le \(date.formatted(Date.FormatStyle().weekday(.wide).day().month(.wide))) à \(date.formatted(Date.FormatStyle().hour().minute())).\n\nMerci de confirmer en répondant à ce message et de prévenir votre partenaire !\n\n\(signature)" } } } struct MessageComposeView: UIViewControllerRepresentable { typealias Completion = (_ result: MessageComposeResult) -> Void static var canSendText: Bool { MFMessageComposeViewController.canSendText() } let recipients: [String]? let body: String? let completion: Completion? func makeUIViewController(context: Context) -> UIViewController { guard Self.canSendText else { let errorView = ContentUnavailableView("Aucun compte de messagerie", systemImage: "xmark", description: Text("Aucun compte de messagerie n'est configuré sur cet appareil.")) return UIHostingController(rootView: errorView) } let controller = MFMessageComposeViewController() controller.messageComposeDelegate = context.coordinator controller.recipients = recipients controller.body = body return controller } func updateUIViewController(_ uiViewController: UIViewController, context: Context) {} func makeCoordinator() -> Coordinator { Coordinator(completion: self.completion) } class Coordinator: NSObject, MFMessageComposeViewControllerDelegate { private let completion: Completion? public init(completion: Completion?) { self.completion = completion } public func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) { controller.dismiss(animated: true, completion: { self.completion?(result) }) } } } struct MailComposeView: UIViewControllerRepresentable { typealias Completion = (_ result: MFMailComposeResult) -> Void static var canSendMail: Bool { if let mailURL = URL(string: "mailto:?to=jap@padelclub.com") { let mailConfigured = UIApplication.shared.canOpenURL(mailURL) return mailConfigured && MFMailComposeViewController.canSendMail() } else { return MFMailComposeViewController.canSendMail() } } let recipients: [String]? let bccRecipients: [String]? let body: String? let subject: String? let completion: Completion? func makeUIViewController(context: Context) -> UIViewController { guard Self.canSendMail else { let errorView = ContentUnavailableView("Aucun compte mail", systemImage: "xmark", description: Text("Aucun compte mail n'est configuré sur cet appareil.")) return UIHostingController(rootView: errorView) } let controller = MFMailComposeViewController() controller.mailComposeDelegate = context.coordinator controller.setToRecipients(recipients) controller.setBccRecipients(bccRecipients) if let body { controller.setMessageBody(body, isHTML: false) } if let subject { controller.setSubject(subject) } return controller } func updateUIViewController(_ uiViewController: UIViewController, context: Context) {} func makeCoordinator() -> Coordinator { Coordinator(completion: self.completion) } class Coordinator: NSObject, MFMailComposeViewControllerDelegate { private let completion: Completion? public init(completion: Completion?) { self.completion = completion } public func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) { controller.dismiss(animated: true, completion: { self.completion?(result) }) } } }