expo-mail-composer 11.2.0 → 12.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/android/build.gradle +2 -2
- package/build/ExpoMailComposer.d.ts +1 -1
- package/build/ExpoMailComposer.d.ts.map +1 -1
- package/build/ExpoMailComposer.js +2 -2
- package/build/ExpoMailComposer.js.map +1 -1
- package/expo-module.config.json +7 -0
- package/ios/{EXMailComposer.podspec → ExpoMailComposer.podspec} +11 -4
- package/ios/MailComposerExceptions.swift +46 -0
- package/ios/MailComposerModule.swift +45 -0
- package/ios/MailComposerOptions.swift +26 -0
- package/ios/MailComposingSession.swift +82 -0
- package/package.json +3 -3
- package/src/ExpoMailComposer.ts +3 -2
- package/tsconfig.json +1 -1
- package/ios/EXMailComposer/EXMailComposer.h +0 -9
- package/ios/EXMailComposer/EXMailComposer.m +0 -164
- package/unimodule.json +0 -4
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,18 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 12.0.0 — 2022-10-25
|
|
14
|
+
|
|
15
|
+
### 🛠 Breaking changes
|
|
16
|
+
|
|
17
|
+
- Bumped iOS deployment target to 13.0 and deprecated support for iOS 12. ([#18873](https://github.com/expo/expo/pull/18873) by [@tsapeta](https://github.com/tsapeta))
|
|
18
|
+
|
|
19
|
+
## 11.3.0 — 2022-07-07
|
|
20
|
+
|
|
21
|
+
### 🎉 New features
|
|
22
|
+
|
|
23
|
+
- Native module on iOS is now written in Swift using the new API and JSI. ([#17488](https://github.com/expo/expo/pull/17488) by [@tsapeta](https://github.com/tsapeta))
|
|
24
|
+
|
|
13
25
|
## 11.2.0 — 2022-04-18
|
|
14
26
|
|
|
15
27
|
### ⚠️ Notices
|
package/android/build.gradle
CHANGED
|
@@ -3,7 +3,7 @@ apply plugin: 'kotlin-android'
|
|
|
3
3
|
apply plugin: 'maven-publish'
|
|
4
4
|
|
|
5
5
|
group = 'host.exp.exponent'
|
|
6
|
-
version = '
|
|
6
|
+
version = '12.0.0'
|
|
7
7
|
|
|
8
8
|
buildscript {
|
|
9
9
|
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
|
|
@@ -74,7 +74,7 @@ android {
|
|
|
74
74
|
minSdkVersion safeExtGet("minSdkVersion", 21)
|
|
75
75
|
targetSdkVersion safeExtGet("targetSdkVersion", 31)
|
|
76
76
|
versionCode 17
|
|
77
|
-
versionName "
|
|
77
|
+
versionName "12.0.0"
|
|
78
78
|
}
|
|
79
79
|
lintOptions {
|
|
80
80
|
abortOnError false
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoMailComposer.d.ts","sourceRoot":"","sources":["../src/ExpoMailComposer.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"ExpoMailComposer.d.ts","sourceRoot":"","sources":["../src/ExpoMailComposer.ts"],"names":[],"mappings":";AAEA,wBAAuD"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export default
|
|
1
|
+
import { requireNativeModule } from 'expo-modules-core';
|
|
2
|
+
export default requireNativeModule('ExpoMailComposer');
|
|
3
3
|
//# sourceMappingURL=ExpoMailComposer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoMailComposer.js","sourceRoot":"","sources":["../src/ExpoMailComposer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"ExpoMailComposer.js","sourceRoot":"","sources":["../src/ExpoMailComposer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAExD,eAAe,mBAAmB,CAAC,kBAAkB,CAAC,CAAC","sourcesContent":["import { requireNativeModule } from 'expo-modules-core';\n\nexport default requireNativeModule('ExpoMailComposer');\n"]}
|
|
@@ -3,23 +3,30 @@ require 'json'
|
|
|
3
3
|
package = JSON.parse(File.read(File.join(__dir__, '..', 'package.json')))
|
|
4
4
|
|
|
5
5
|
Pod::Spec.new do |s|
|
|
6
|
-
s.name = '
|
|
6
|
+
s.name = 'ExpoMailComposer'
|
|
7
7
|
s.version = package['version']
|
|
8
8
|
s.summary = package['description']
|
|
9
9
|
s.description = package['description']
|
|
10
10
|
s.license = package['license']
|
|
11
11
|
s.author = package['author']
|
|
12
12
|
s.homepage = package['homepage']
|
|
13
|
-
s.platform = :ios, '
|
|
13
|
+
s.platform = :ios, '13.0'
|
|
14
|
+
s.swift_version = '5.4'
|
|
14
15
|
s.source = { git: 'https://github.com/expo/expo.git' }
|
|
15
16
|
s.static_framework = true
|
|
16
17
|
|
|
17
18
|
s.dependency 'ExpoModulesCore'
|
|
18
19
|
|
|
20
|
+
# Swift/Objective-C compatibility
|
|
21
|
+
s.pod_target_xcconfig = {
|
|
22
|
+
'DEFINES_MODULE' => 'YES',
|
|
23
|
+
'SWIFT_COMPILATION_MODE' => 'wholemodule'
|
|
24
|
+
}
|
|
25
|
+
|
|
19
26
|
if !$ExpoUseSources&.include?(package['name']) && ENV['EXPO_USE_SOURCE'].to_i == 0 && File.exist?("#{s.name}.xcframework") && Gem::Version.new(Pod::VERSION) >= Gem::Version.new('1.10.0')
|
|
20
|
-
s.source_files = "
|
|
27
|
+
s.source_files = "**/*.h"
|
|
21
28
|
s.vendored_frameworks = "#{s.name}.xcframework"
|
|
22
29
|
else
|
|
23
|
-
s.source_files = "
|
|
30
|
+
s.source_files = "**/*.{h,m,swift}"
|
|
24
31
|
end
|
|
25
32
|
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// Copyright 2022-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
import MessageUI
|
|
4
|
+
import ExpoModulesCore
|
|
5
|
+
|
|
6
|
+
internal final class CannotSendMailException: Exception {
|
|
7
|
+
override var reason: String {
|
|
8
|
+
"Mail services are not available, make sure you're signed into the Mail app"
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
internal final class OperationInProgressException: Exception {
|
|
13
|
+
override var reason: String {
|
|
14
|
+
"Cannot compose an email because another email composing operation is in progress"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
internal final class MissingViewControllerException: Exception {
|
|
19
|
+
override var reason: String {
|
|
20
|
+
"Unable to find the current view controller to present the compose view controller"
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
internal final class SendingFailedException: GenericException<Error?> {
|
|
25
|
+
override var reason: String {
|
|
26
|
+
"Something went wrong while trying to send the email: \(param.debugDescription)"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
internal final class UnknownResultException: GenericException<MFMailComposeResult> {
|
|
31
|
+
override var reason: String {
|
|
32
|
+
"Received unknown result: \(param)"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
internal final class FileSystemNotFoundException: Exception {
|
|
37
|
+
override var reason: String {
|
|
38
|
+
"FileSystem module not found, make sure 'expo-file-system' is linked correctly"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
internal final class FileSystemReadPermissionException: GenericException<String> {
|
|
43
|
+
override var reason: String {
|
|
44
|
+
"File '\(param)' is not readable"
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Copyright 2022-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
import MessageUI
|
|
4
|
+
import MobileCoreServices
|
|
5
|
+
import ExpoModulesCore
|
|
6
|
+
|
|
7
|
+
public class MailComposerModule: Module {
|
|
8
|
+
var currentSession: MailComposingSession?
|
|
9
|
+
|
|
10
|
+
public func definition() -> ModuleDefinition {
|
|
11
|
+
Name("ExpoMailComposer")
|
|
12
|
+
|
|
13
|
+
AsyncFunction("isAvailableAsync", canSendMail)
|
|
14
|
+
|
|
15
|
+
AsyncFunction("composeAsync") { (options: MailComposerOptions, promise: Promise) in
|
|
16
|
+
guard canSendMail() else {
|
|
17
|
+
throw CannotSendMailException()
|
|
18
|
+
}
|
|
19
|
+
guard self.currentSession == nil else {
|
|
20
|
+
throw OperationInProgressException()
|
|
21
|
+
}
|
|
22
|
+
guard let appContext = self.appContext else {
|
|
23
|
+
throw AppContextLostException()
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
let session = MailComposingSession(appContext)
|
|
27
|
+
try session.compose(options: options)
|
|
28
|
+
|
|
29
|
+
// This is important to retain the session until it finishes
|
|
30
|
+
self.currentSession = session
|
|
31
|
+
|
|
32
|
+
session.presentViewController { result in
|
|
33
|
+
promise.settle(with: result)
|
|
34
|
+
|
|
35
|
+
// Release the session so it can get deallocated
|
|
36
|
+
self.currentSession = nil
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
.runOnQueue(.main)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
private func canSendMail() -> Bool {
|
|
44
|
+
return MFMailComposeViewController.canSendMail()
|
|
45
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
// Copyright 2022-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
import ExpoModulesCore
|
|
4
|
+
|
|
5
|
+
internal struct MailComposerOptions: Record {
|
|
6
|
+
@Field
|
|
7
|
+
var recipients: [String]?
|
|
8
|
+
|
|
9
|
+
@Field
|
|
10
|
+
var ccRecipients: [String]?
|
|
11
|
+
|
|
12
|
+
@Field
|
|
13
|
+
var bccRecipients: [String]?
|
|
14
|
+
|
|
15
|
+
@Field
|
|
16
|
+
var subject: String = ""
|
|
17
|
+
|
|
18
|
+
@Field
|
|
19
|
+
var body: String = ""
|
|
20
|
+
|
|
21
|
+
@Field
|
|
22
|
+
var isHtml: Bool = false
|
|
23
|
+
|
|
24
|
+
@Field
|
|
25
|
+
var attachments: [URL]?
|
|
26
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// Copyright 2022-present 650 Industries. All rights reserved.
|
|
2
|
+
|
|
3
|
+
import MessageUI
|
|
4
|
+
import MobileCoreServices
|
|
5
|
+
import ExpoModulesCore
|
|
6
|
+
|
|
7
|
+
internal final class MailComposingSession: NSObject, MFMailComposeViewControllerDelegate {
|
|
8
|
+
typealias ComposingCallback = (Result<[String: String], Exception>) -> ()
|
|
9
|
+
|
|
10
|
+
let appContext: AppContext
|
|
11
|
+
let composeController: MFMailComposeViewController
|
|
12
|
+
var callback: ComposingCallback?
|
|
13
|
+
|
|
14
|
+
init(_ appContext: AppContext) {
|
|
15
|
+
self.appContext = appContext
|
|
16
|
+
self.composeController = MFMailComposeViewController()
|
|
17
|
+
super.init()
|
|
18
|
+
|
|
19
|
+
self.composeController.mailComposeDelegate = self
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
func compose(options: MailComposerOptions) throws {
|
|
23
|
+
composeController.setToRecipients(options.recipients)
|
|
24
|
+
composeController.setCcRecipients(options.ccRecipients)
|
|
25
|
+
composeController.setBccRecipients(options.bccRecipients)
|
|
26
|
+
composeController.setSubject(options.subject)
|
|
27
|
+
composeController.setMessageBody(options.body, isHTML: options.isHtml)
|
|
28
|
+
|
|
29
|
+
if let attachments = options.attachments {
|
|
30
|
+
guard let fileSystem = appContext.fileSystem else {
|
|
31
|
+
throw FileSystemNotFoundException()
|
|
32
|
+
}
|
|
33
|
+
for attachment in attachments {
|
|
34
|
+
guard fileSystem.permissions(forURI: attachment).contains(.read) else {
|
|
35
|
+
throw FileSystemReadPermissionException(attachment.path)
|
|
36
|
+
}
|
|
37
|
+
let mimeType = findMimeType(forAttachment: attachment)
|
|
38
|
+
let fileData = try Data(contentsOf: attachment)
|
|
39
|
+
composeController.addAttachmentData(fileData, mimeType: mimeType, fileName: attachment.lastPathComponent)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
func presentViewController(_ callback: @escaping ComposingCallback) {
|
|
45
|
+
guard let currentViewController = appContext.utilities?.currentViewController() else {
|
|
46
|
+
callback(.failure(MissingViewControllerException()))
|
|
47
|
+
return
|
|
48
|
+
}
|
|
49
|
+
self.callback = callback
|
|
50
|
+
currentViewController.present(composeController, animated: true)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// MARK: - MFMailComposeViewControllerDelegate
|
|
54
|
+
|
|
55
|
+
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
|
|
56
|
+
composeController.dismiss(animated: true) {
|
|
57
|
+
guard let callback = self.callback else {
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
switch result {
|
|
61
|
+
case .cancelled:
|
|
62
|
+
callback(.success(["status": "cancelled"]))
|
|
63
|
+
case .saved:
|
|
64
|
+
callback(.success(["status": "saved"]))
|
|
65
|
+
case .sent:
|
|
66
|
+
callback(.success(["status": "sent"]))
|
|
67
|
+
case .failed:
|
|
68
|
+
callback(.failure(SendingFailedException(error)))
|
|
69
|
+
@unknown default:
|
|
70
|
+
callback(.failure(UnknownResultException(result)))
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private func findMimeType(forAttachment attachment: URL) -> String {
|
|
77
|
+
if let identifier = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, attachment.pathExtension as CFString, nil)?.takeRetainedValue(),
|
|
78
|
+
let type = UTTypeCopyPreferredTagWithClass(identifier, kUTTagClassMIMEType)?.takeRetainedValue() {
|
|
79
|
+
return type as String
|
|
80
|
+
}
|
|
81
|
+
return "application/octet-stream"
|
|
82
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-mail-composer",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "12.0.0",
|
|
4
4
|
"description": "Provides an API to compose mails using OS specific UI",
|
|
5
5
|
"main": "build/MailComposer.js",
|
|
6
6
|
"types": "build/MailComposer.d.ts",
|
|
@@ -38,10 +38,10 @@
|
|
|
38
38
|
"query-string": "^6.2.0"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
|
-
"expo-module-scripts": "^
|
|
41
|
+
"expo-module-scripts": "^3.0.0"
|
|
42
42
|
},
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"expo": "*"
|
|
45
45
|
},
|
|
46
|
-
"gitHead": "
|
|
46
|
+
"gitHead": "eab2b09c735fb0fc2bf734a3f29a6593adba3838"
|
|
47
47
|
}
|
package/src/ExpoMailComposer.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { requireNativeModule } from 'expo-modules-core';
|
|
2
|
+
|
|
3
|
+
export default requireNativeModule('ExpoMailComposer');
|
package/tsconfig.json
CHANGED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
// Copyright 2017-present 650 Industries. All rights reserved.
|
|
2
|
-
|
|
3
|
-
#import <ExpoModulesCore/EXExportedModule.h>
|
|
4
|
-
#import <ExpoModulesCore/EXModuleRegistryConsumer.h>
|
|
5
|
-
|
|
6
|
-
#import <MessageUI/MessageUI.h>
|
|
7
|
-
|
|
8
|
-
@interface EXMailComposer : EXExportedModule <EXModuleRegistryConsumer, MFMailComposeViewControllerDelegate>
|
|
9
|
-
@end
|
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
// Copyright 2017-present 650 Industries. All rights reserved.
|
|
2
|
-
|
|
3
|
-
#import <EXMailComposer/EXMailComposer.h>
|
|
4
|
-
#import <MobileCoreServices/MobileCoreServices.h>
|
|
5
|
-
|
|
6
|
-
#import <ExpoModulesCore/EXUtilitiesInterface.h>
|
|
7
|
-
#import <ExpoModulesCore/EXFileSystemInterface.h>
|
|
8
|
-
|
|
9
|
-
@interface EXMailComposer ()
|
|
10
|
-
|
|
11
|
-
@property (nonatomic, weak) EXModuleRegistry *moduleRegistry;
|
|
12
|
-
|
|
13
|
-
@property (nonatomic, strong) EXPromiseResolveBlock resolve;
|
|
14
|
-
@property (nonatomic, strong) EXPromiseRejectBlock reject;
|
|
15
|
-
|
|
16
|
-
@end
|
|
17
|
-
|
|
18
|
-
@implementation EXMailComposer
|
|
19
|
-
|
|
20
|
-
EX_EXPORT_MODULE(ExpoMailComposer);
|
|
21
|
-
|
|
22
|
-
- (void)setModuleRegistry:(EXModuleRegistry *)moduleRegistry
|
|
23
|
-
{
|
|
24
|
-
_moduleRegistry = moduleRegistry;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
- (dispatch_queue_t)methodQueue
|
|
28
|
-
{
|
|
29
|
-
return dispatch_get_main_queue();
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
EX_EXPORT_METHOD_AS(isAvailableAsync,
|
|
33
|
-
isAvailable:(EXPromiseResolveBlock)resolve
|
|
34
|
-
rejecter:(EXPromiseRejectBlock)reject)
|
|
35
|
-
{
|
|
36
|
-
resolve(@([MFMailComposeViewController canSendMail]));
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
EX_EXPORT_METHOD_AS(composeAsync,
|
|
41
|
-
composeAsync:(NSDictionary *)options
|
|
42
|
-
resolver:(EXPromiseResolveBlock)resolve
|
|
43
|
-
rejecter:(EXPromiseRejectBlock)reject)
|
|
44
|
-
{
|
|
45
|
-
if (![MFMailComposeViewController canSendMail]) {
|
|
46
|
-
reject(@"E_COMPOSE_UNAVAILABLE", @"Mail services are not available. Make sure you're signed into the Mail app", nil);
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
MFMailComposeViewController* composeController = [[MFMailComposeViewController alloc] init];
|
|
51
|
-
composeController.mailComposeDelegate = self;
|
|
52
|
-
|
|
53
|
-
NSMutableArray *recipients = [[NSMutableArray alloc] init];
|
|
54
|
-
for (NSString *recipient in options[@"recipients"]) {
|
|
55
|
-
[recipients addObject:recipient];
|
|
56
|
-
}
|
|
57
|
-
[composeController setToRecipients:recipients];
|
|
58
|
-
|
|
59
|
-
NSMutableArray *ccRecipients = [[NSMutableArray alloc] init];
|
|
60
|
-
for (NSString *ccRecipient in options[@"ccRecipients"]) {
|
|
61
|
-
[ccRecipients addObject:ccRecipient];
|
|
62
|
-
}
|
|
63
|
-
[composeController setCcRecipients:ccRecipients];
|
|
64
|
-
|
|
65
|
-
NSMutableArray *bccRecipients = [[NSMutableArray alloc] init];
|
|
66
|
-
for (NSString *bccRecipient in options[@"bccRecipients"]) {
|
|
67
|
-
[bccRecipients addObject:bccRecipient];
|
|
68
|
-
}
|
|
69
|
-
[composeController setBccRecipients:bccRecipients];
|
|
70
|
-
|
|
71
|
-
if (options[@"subject"] != nil) {
|
|
72
|
-
[composeController setSubject:options[@"subject"]];
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (options[@"body"] != nil) {
|
|
76
|
-
BOOL isHTML = NO;
|
|
77
|
-
if (options[@"isHtml"]) {
|
|
78
|
-
isHTML = YES;
|
|
79
|
-
}
|
|
80
|
-
[composeController setMessageBody:options[@"body"] isHTML:isHTML];
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (options[@"attachments"] != nil) {
|
|
84
|
-
for (NSString *uri in options[@"attachments"]) {
|
|
85
|
-
NSURL *url = [NSURL URLWithString:uri];
|
|
86
|
-
NSString *path = [url.path stringByStandardizingPath];
|
|
87
|
-
id<EXFileSystemInterface> fileSystem = [_moduleRegistry getModuleImplementingProtocol:@protocol(EXFileSystemInterface)];
|
|
88
|
-
if (!fileSystem) {
|
|
89
|
-
reject(@"E_MISSING_MODULE", @"No FileSystem module.", nil);
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
if (!([fileSystem permissionsForURI:url] & EXFileSystemPermissionRead)) {
|
|
93
|
-
reject(@"E_FILESYSTEM_PERMISSIONS", [NSString stringWithFormat:@"File '%@' isn't readable.", uri], nil);
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
if (![[NSFileManager defaultManager] fileExistsAtPath:path]) {
|
|
98
|
-
reject(@"E_INVALID_ATTACHMENT", [NSString stringWithFormat:@"The file does not exist. Given path: `%@`.", path], nil);
|
|
99
|
-
return;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
NSString *mimeType = @"application/octet-stream";
|
|
103
|
-
if ([path pathExtension]) {
|
|
104
|
-
CFStringRef identifier = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)[path pathExtension], NULL);
|
|
105
|
-
CFStringRef typeRef = UTTypeCopyPreferredTagWithClass (identifier, kUTTagClassMIMEType);
|
|
106
|
-
CFRelease(identifier);
|
|
107
|
-
if (typeRef != NULL) {
|
|
108
|
-
mimeType = [NSString stringWithString:(__bridge NSString *)(typeRef)];
|
|
109
|
-
CFRelease(typeRef);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
NSData *fileData = [NSData dataWithContentsOfFile:path];
|
|
114
|
-
|
|
115
|
-
[composeController addAttachmentData:fileData mimeType:mimeType fileName:[path lastPathComponent]];
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
self.resolve = resolve;
|
|
120
|
-
self.reject = reject;
|
|
121
|
-
id<EXUtilitiesInterface> utilities = [_moduleRegistry getModuleImplementingProtocol:@protocol(EXUtilitiesInterface)];
|
|
122
|
-
[utilities.currentViewController presentViewController:composeController animated:YES completion:nil];
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
- (void)mailComposeController:(MFMailComposeViewController *)controller
|
|
126
|
-
didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error {
|
|
127
|
-
__weak typeof(self) weakSelf = self;
|
|
128
|
-
dispatch_async(dispatch_get_main_queue(), ^{
|
|
129
|
-
[controller dismissViewControllerAnimated:YES completion:^{
|
|
130
|
-
__strong typeof(self) strongSelf = weakSelf;
|
|
131
|
-
if (strongSelf && strongSelf.resolve != nil && strongSelf.reject != nil) {
|
|
132
|
-
if (error != nil) {
|
|
133
|
-
strongSelf.reject(@"E_MAIL_ERROR", @"An error occurred while trying to send the e-mail.", error);
|
|
134
|
-
strongSelf.reject = nil;
|
|
135
|
-
strongSelf.resolve = nil;
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
switch (result) {
|
|
140
|
-
case MFMailComposeResultSent:
|
|
141
|
-
strongSelf.resolve(@{ @"status": @"sent" });
|
|
142
|
-
break;
|
|
143
|
-
case MFMailComposeResultSaved:
|
|
144
|
-
strongSelf.resolve(@{ @"status": @"saved" });
|
|
145
|
-
break;
|
|
146
|
-
case MFMailComposeResultCancelled:
|
|
147
|
-
strongSelf.resolve(@{ @"status": @"cancelled" });
|
|
148
|
-
break;
|
|
149
|
-
case MFMailComposeResultFailed:
|
|
150
|
-
strongSelf.reject(@"E_MAIL_ERROR", @"Something went wrong while trying to send the e-mail.", error);
|
|
151
|
-
break;
|
|
152
|
-
default:
|
|
153
|
-
strongSelf.reject(@"E_MAIL_ERROR", @"Something went wrong while trying to send the e-mail.", error);
|
|
154
|
-
break;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
strongSelf.reject = nil;
|
|
158
|
-
strongSelf.resolve = nil;
|
|
159
|
-
}
|
|
160
|
-
}];
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
@end
|
package/unimodule.json
DELETED