[ios] move mail composing logic to the MailComposer class
to reuse both in the About screen and the Cloud sync manager Signed-off-by: Kiryl Kaveryn <kirylkaveryn@gmail.com>
This commit is contained in:
parent
69bc067ca9
commit
edf982ae7d
3 changed files with 129 additions and 114 deletions
|
@ -487,6 +487,7 @@
|
|||
ED7CCC4F2C1362E300E2A737 /* FileType.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED7CCC4E2C1362E300E2A737 /* FileType.swift */; };
|
||||
ED808D0F2C38407800D52585 /* CircleImageButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED808D0E2C38407800D52585 /* CircleImageButton.swift */; };
|
||||
ED8270F02C2071A3005966DA /* SettingsTableViewDetailedSwitchCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED8270EF2C2071A3005966DA /* SettingsTableViewDetailedSwitchCell.swift */; };
|
||||
ED9857082C4ED02D00694F6C /* MailComposer.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED9857072C4ED02D00694F6C /* MailComposer.swift */; };
|
||||
ED9966802B94FBC20083CE55 /* ColorPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = ED99667D2B94FBC20083CE55 /* ColorPicker.swift */; };
|
||||
EDBD68072B625724005DD151 /* LocationServicesDisabledAlert.xib in Resources */ = {isa = PBXBuildFile; fileRef = EDBD68062B625724005DD151 /* LocationServicesDisabledAlert.xib */; };
|
||||
EDBD680B2B62572E005DD151 /* LocationServicesDisabledAlert.swift in Sources */ = {isa = PBXBuildFile; fileRef = EDBD680A2B62572E005DD151 /* LocationServicesDisabledAlert.swift */; };
|
||||
|
@ -1406,6 +1407,7 @@
|
|||
ED7CCC4E2C1362E300E2A737 /* FileType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileType.swift; sourceTree = "<group>"; };
|
||||
ED808D0E2C38407800D52585 /* CircleImageButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CircleImageButton.swift; sourceTree = "<group>"; };
|
||||
ED8270EF2C2071A3005966DA /* SettingsTableViewDetailedSwitchCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsTableViewDetailedSwitchCell.swift; sourceTree = "<group>"; };
|
||||
ED9857072C4ED02D00694F6C /* MailComposer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MailComposer.swift; sourceTree = "<group>"; };
|
||||
ED99667D2B94FBC20083CE55 /* ColorPicker.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorPicker.swift; sourceTree = "<group>"; };
|
||||
EDBD68062B625724005DD151 /* LocationServicesDisabledAlert.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = LocationServicesDisabledAlert.xib; sourceTree = "<group>"; };
|
||||
EDBD680A2B62572E005DD151 /* LocationServicesDisabledAlert.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocationServicesDisabledAlert.swift; sourceTree = "<group>"; };
|
||||
|
@ -3106,6 +3108,14 @@
|
|||
path = iCloud;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
ED9857022C4ECFFC00694F6C /* MailComposer */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
ED9857072C4ED02D00694F6C /* MailComposer.swift */,
|
||||
);
|
||||
path = MailComposer;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
ED99667C2B94FBC20083CE55 /* ColorPicker */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
@ -3366,6 +3376,7 @@
|
|||
F6E2FBFB1E097B9F0083EBEC /* UI */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
ED9857022C4ECFFC00694F6C /* MailComposer */,
|
||||
ED43B8B92C12061600D07BAA /* DocumentPicker */,
|
||||
ED99667C2B94FBC20083CE55 /* ColorPicker */,
|
||||
F69018B51E9E5FEB00B3C10B /* Autoupdate */,
|
||||
|
@ -4557,6 +4568,7 @@
|
|||
3404164C1E7BF42E00E2B6D6 /* UIView+Coordinates.swift in Sources */,
|
||||
99F3EB0323F4178200C713F8 /* PlacePageCommonLayout.swift in Sources */,
|
||||
99C6532223F2F506004322F3 /* IPlacePageLayout.swift in Sources */,
|
||||
ED9857082C4ED02D00694F6C /* MailComposer.swift in Sources */,
|
||||
99F8B4C623B644A6009FF0B4 /* MapStyleSheet.swift in Sources */,
|
||||
99012851244732DB00C72B10 /* BottomTabBarViewController.swift in Sources */,
|
||||
F63AF5061EA6162400A1DB98 /* FilterTypeCell.swift in Sources */,
|
||||
|
|
|
@ -282,7 +282,7 @@ private extension AboutController {
|
|||
let logFileURL = Logger.getLogFileURL()
|
||||
UIApplication.shared.hideLoadingOverlay {
|
||||
guard let self else { return }
|
||||
self.sendEmailWith(header: "Organic Maps Bugreport", toRecipients: [link], attachmentFileURL: logFileURL)
|
||||
MailComposer.default.sendEmailWith(header: "Organic Maps Bugreport", toRecipients: [link], attachmentFileURL: logFileURL)
|
||||
}
|
||||
}
|
||||
case .reportMapDataProblem, .volunteer, .news:
|
||||
|
@ -314,7 +314,7 @@ private extension AboutController {
|
|||
self?.openUrl(socialMedia.link, externally: true)
|
||||
case .organicMapsEmail:
|
||||
guard let link = socialMedia.link else { fatalError("The Organic Maps email link should be provided.") }
|
||||
self?.sendEmailWith(header: "Organic Maps", toRecipients: [link])
|
||||
MailComposer.default.sendEmailWith(header: "Organic Maps", toRecipients: [link])
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -441,111 +441,6 @@ extension AboutController: UICollectionViewDelegateFlowLayout {
|
|||
return Constants.socialMediaCollectionViewSpacing
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Mail Composing
|
||||
private extension AboutController {
|
||||
func sendEmailWith(header: String, toRecipients: [String], attachmentFileURL: URL? = nil) {
|
||||
func emailSubject(subject: String) -> String {
|
||||
let appInfo = AppInfo.shared()
|
||||
return String(format:"[%@-%@ iOS] %@", appInfo.bundleVersion, appInfo.buildNumber, subject)
|
||||
}
|
||||
|
||||
func emailBody() -> String {
|
||||
let appInfo = AppInfo.shared()
|
||||
return String(format: "\n\n\n\n- %@ (%@)\n- Organic Maps %@-%@\n- %@-%@\n- %@\n",
|
||||
appInfo.deviceModel, UIDevice.current.systemVersion,
|
||||
appInfo.bundleVersion, appInfo.buildNumber,
|
||||
Locale.current.languageCode ?? "",
|
||||
Locale.current.regionCode ?? "",
|
||||
Locale.preferredLanguages.joined(separator: ", "))
|
||||
}
|
||||
|
||||
func openOutlook(subject: String, body: String, recipients: [String]) -> Bool {
|
||||
var components = URLComponents(string: "ms-outlook://compose")!
|
||||
components.queryItems = [
|
||||
URLQueryItem(name: "to", value: recipients.joined(separator: ";")),
|
||||
URLQueryItem(name: "subject", value: subject),
|
||||
URLQueryItem(name: "body", value: body),
|
||||
]
|
||||
|
||||
if let url = components.url, UIApplication.shared.canOpenURL(url) {
|
||||
UIApplication.shared.open(url)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func openGmail(subject: String, body: String, recipients: [String]) -> Bool {
|
||||
var components = URLComponents(string: "googlegmail://co")!
|
||||
components.queryItems = [
|
||||
URLQueryItem(name: "to", value: recipients.joined(separator: ";")),
|
||||
URLQueryItem(name: "subject", value: subject),
|
||||
URLQueryItem(name: "body", value: body),
|
||||
]
|
||||
|
||||
if let url = components.url, UIApplication.shared.canOpenURL(url) {
|
||||
UIApplication.shared.open(url)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func openDefaultMailApp(subject: String, body: String, recipients: [String]) -> Bool {
|
||||
var components = URLComponents(string: "mailto:\(recipients.joined(separator: ";"))")
|
||||
components?.queryItems = [
|
||||
URLQueryItem(name: "subject", value: subject),
|
||||
URLQueryItem(name: "body", value: body.replacingOccurrences(of: "\n", with: "\r\n")),
|
||||
]
|
||||
|
||||
if let url = components?.url, UIApplication.shared.canOpenURL(url) {
|
||||
UIApplication.shared.open(url)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func showMailComposingAlert() {
|
||||
let text = String(format:L("email_error_body"), toRecipients.joined(separator: ";"))
|
||||
let alert = UIAlertController(title: L("email_error_title"), message: text, preferredStyle: .alert)
|
||||
let action = UIAlertAction(title: L("ok"), style: .default, handler: nil)
|
||||
alert.addAction(action)
|
||||
present(alert, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
let subject = emailSubject(subject: header)
|
||||
let body = emailBody()
|
||||
|
||||
// If the attachment file path is provided, the default mail composer should be used.
|
||||
if let attachmentFileURL {
|
||||
if MWMMailViewController.canSendMail(), let attachmentData = try? Data(contentsOf: attachmentFileURL) {
|
||||
let mailViewController = MWMMailViewController()
|
||||
mailViewController.mailComposeDelegate = self
|
||||
mailViewController.setSubject(subject)
|
||||
mailViewController.setMessageBody(body, isHTML:false)
|
||||
mailViewController.setToRecipients(toRecipients)
|
||||
mailViewController.addAttachmentData(attachmentData, mimeType: "application/zip", fileName: attachmentFileURL.lastPathComponent)
|
||||
|
||||
self.present(mailViewController, animated: true, completion:nil)
|
||||
} else {
|
||||
showMailComposingAlert()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Before iOS 14, try to open alternate email apps first, assuming that if users installed them, they're using them.
|
||||
let os = ProcessInfo().operatingSystemVersion
|
||||
if (os.majorVersion < 14 && (openGmail(subject: subject, body: body, recipients: toRecipients) ||
|
||||
openOutlook(subject: subject, body: body, recipients: toRecipients))) {
|
||||
return
|
||||
}
|
||||
|
||||
// From iOS 14, it is possible to change the default mail app, and mailto should open a default mail app.
|
||||
if !openDefaultMailApp(subject: subject, body: body, recipients: toRecipients) {
|
||||
showMailComposingAlert()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - UIStackView + AddArrangedSubviewWithSeparator
|
||||
private extension UIStackView {
|
||||
func addArrangedSubviewWithSeparator(_ view: UIView) {
|
||||
|
@ -564,10 +459,3 @@ private extension UIStackView {
|
|||
addArrangedSubview(view)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - MFMailComposeViewControllerDelegate
|
||||
extension AboutController: MFMailComposeViewControllerDelegate {
|
||||
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
|
||||
dismiss(animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
|
|
115
iphone/Maps/UI/MailComposer/MailComposer.swift
Normal file
115
iphone/Maps/UI/MailComposer/MailComposer.swift
Normal file
|
@ -0,0 +1,115 @@
|
|||
final class MailComposer: NSObject {
|
||||
|
||||
static let `default` = MailComposer()
|
||||
|
||||
private var topViewController: UIViewController { UIViewController.topViewController() }
|
||||
|
||||
private override init() {}
|
||||
|
||||
func sendEmailWith(header: String, toRecipients: [String], attachmentFileURL: URL? = nil) {
|
||||
func emailSubject(subject: String) -> String {
|
||||
let appInfo = AppInfo.shared()
|
||||
return String(format:"[%@-%@ iOS] %@", appInfo.bundleVersion, appInfo.buildNumber, subject)
|
||||
}
|
||||
|
||||
func emailBody() -> String {
|
||||
let appInfo = AppInfo.shared()
|
||||
return String(format: "\n\n\n\n- %@ (%@)\n- Organic Maps %@-%@\n- %@-%@\n- %@\n",
|
||||
appInfo.deviceModel, UIDevice.current.systemVersion,
|
||||
appInfo.bundleVersion, appInfo.buildNumber,
|
||||
Locale.current.languageCode ?? "",
|
||||
Locale.current.regionCode ?? "",
|
||||
Locale.preferredLanguages.joined(separator: ", "))
|
||||
}
|
||||
|
||||
func openOutlook(subject: String, body: String, recipients: [String]) -> Bool {
|
||||
var components = URLComponents(string: "ms-outlook://compose")!
|
||||
components.queryItems = [
|
||||
URLQueryItem(name: "to", value: recipients.joined(separator: ";")),
|
||||
URLQueryItem(name: "subject", value: subject),
|
||||
URLQueryItem(name: "body", value: body),
|
||||
]
|
||||
|
||||
if let url = components.url, UIApplication.shared.canOpenURL(url) {
|
||||
UIApplication.shared.open(url)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func openGmail(subject: String, body: String, recipients: [String]) -> Bool {
|
||||
var components = URLComponents(string: "googlegmail://co")!
|
||||
components.queryItems = [
|
||||
URLQueryItem(name: "to", value: recipients.joined(separator: ";")),
|
||||
URLQueryItem(name: "subject", value: subject),
|
||||
URLQueryItem(name: "body", value: body),
|
||||
]
|
||||
|
||||
if let url = components.url, UIApplication.shared.canOpenURL(url) {
|
||||
UIApplication.shared.open(url)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func openDefaultMailApp(subject: String, body: String, recipients: [String]) -> Bool {
|
||||
var components = URLComponents(string: "mailto:\(recipients.joined(separator: ";"))")
|
||||
components?.queryItems = [
|
||||
URLQueryItem(name: "subject", value: subject),
|
||||
URLQueryItem(name: "body", value: body.replacingOccurrences(of: "\n", with: "\r\n")),
|
||||
]
|
||||
|
||||
if let url = components?.url, UIApplication.shared.canOpenURL(url) {
|
||||
UIApplication.shared.open(url)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func showMailComposingAlert() {
|
||||
let text = String(format:L("email_error_body"), toRecipients.joined(separator: ";"))
|
||||
let alert = UIAlertController(title: L("email_error_title"), message: text, preferredStyle: .alert)
|
||||
let action = UIAlertAction(title: L("ok"), style: .default, handler: nil)
|
||||
alert.addAction(action)
|
||||
topViewController.present(alert, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
let subject = emailSubject(subject: header)
|
||||
let body = emailBody()
|
||||
|
||||
// If the attachment file path is provided, the default mail composer should be used.
|
||||
if let attachmentFileURL {
|
||||
if MWMMailViewController.canSendMail(), let attachmentData = try? Data(contentsOf: attachmentFileURL) {
|
||||
let mailViewController = MWMMailViewController()
|
||||
mailViewController.mailComposeDelegate = self
|
||||
mailViewController.setSubject(subject)
|
||||
mailViewController.setMessageBody(body, isHTML:false)
|
||||
mailViewController.setToRecipients(toRecipients)
|
||||
mailViewController.addAttachmentData(attachmentData, mimeType: "application/zip", fileName: attachmentFileURL.lastPathComponent)
|
||||
topViewController.present(mailViewController, animated: true, completion:nil)
|
||||
} else {
|
||||
showMailComposingAlert()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Before iOS 14, try to open alternate email apps first, assuming that if users installed them, they're using them.
|
||||
let os = ProcessInfo().operatingSystemVersion
|
||||
if (os.majorVersion < 14 && (openGmail(subject: subject, body: body, recipients: toRecipients) ||
|
||||
openOutlook(subject: subject, body: body, recipients: toRecipients))) {
|
||||
return
|
||||
}
|
||||
|
||||
// From iOS 14, it is possible to change the default mail app, and mailto should open a default mail app.
|
||||
if !openDefaultMailApp(subject: subject, body: body, recipients: toRecipients) {
|
||||
showMailComposingAlert()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - MFMailComposeViewControllerDelegate
|
||||
extension MailComposer: MFMailComposeViewControllerDelegate {
|
||||
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
|
||||
controller.dismiss(animated: true, completion: nil)
|
||||
}
|
||||
}
|
Reference in a new issue