expo-mail-composer 10.2.1 → 11.0.2
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 +21 -1
- package/android/build.gradle +7 -11
- package/android/src/main/AndroidManifest.xml +11 -12
- package/android/src/main/java/expo/modules/mailcomposer/MailComposerFileProvider.kt +8 -0
- package/android/src/main/java/expo/modules/mailcomposer/MailComposerModule.kt +89 -0
- package/android/src/main/java/expo/modules/mailcomposer/MailComposerPackage.kt +9 -0
- package/android/src/main/java/expo/modules/mailcomposer/MailIntentBuilder.kt +80 -0
- package/build/ExpoMailComposer.d.ts +1 -1
- package/build/ExpoMailComposer.js +1 -1
- package/build/ExpoMailComposer.js.map +1 -1
- package/ios/EXMailComposer/EXMailComposer.h +3 -3
- package/ios/EXMailComposer/EXMailComposer.m +13 -13
- package/ios/EXMailComposer.podspec +2 -2
- package/package.json +4 -7
- package/src/ExpoMailComposer.ts +1 -1
- package/android/src/main/java/expo/modules/mailcomposer/MailComposerFileProvider.java +0 -9
- package/android/src/main/java/expo/modules/mailcomposer/MailComposerModule.java +0 -158
- package/android/src/main/java/expo/modules/mailcomposer/MailComposerPackage.java +0 -16
package/CHANGELOG.md
CHANGED
|
@@ -10,10 +10,30 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## 11.0.2 — 2021-10-15
|
|
14
14
|
|
|
15
15
|
_This version does not introduce any user-facing changes._
|
|
16
16
|
|
|
17
|
+
## 11.0.1 — 2021-10-01
|
|
18
|
+
|
|
19
|
+
_This version does not introduce any user-facing changes._
|
|
20
|
+
|
|
21
|
+
## 11.0.0 — 2021-09-28
|
|
22
|
+
|
|
23
|
+
### 🛠 Breaking changes
|
|
24
|
+
|
|
25
|
+
- Added `AndroidManifest.xml` queries for intent handling. ([#13388](https://github.com/expo/expo/pull/13388) by [@EvanBacon](https://github.com/EvanBacon))
|
|
26
|
+
- Dropped support for iOS 11.0 ([#14383](https://github.com/expo/expo/pull/14383) by [@cruzach](https://github.com/cruzach))
|
|
27
|
+
|
|
28
|
+
### 🐛 Bug fixes
|
|
29
|
+
|
|
30
|
+
- Fix building errors from use_frameworks! in Podfile. ([#14523](https://github.com/expo/expo/pull/14523) by [@kudo](https://github.com/kudo))
|
|
31
|
+
|
|
32
|
+
### 💡 Others
|
|
33
|
+
|
|
34
|
+
- Migrated from `@unimodules/core` to `expo-modules-core`. ([#13757](https://github.com/expo/expo/pull/13757) by [@tsapeta](https://github.com/tsapeta))
|
|
35
|
+
- Rewrote Android part from Java to Kotlin ([#14394](https://github.com/expo/expo/pull/14394) by [@m1st4ke](https://github.com/m1st4ke))
|
|
36
|
+
|
|
17
37
|
## 10.2.0 — 2021-06-16
|
|
18
38
|
|
|
19
39
|
### 🐛 Bug fixes
|
package/android/build.gradle
CHANGED
|
@@ -3,7 +3,7 @@ apply plugin: 'kotlin-android'
|
|
|
3
3
|
apply plugin: 'maven'
|
|
4
4
|
|
|
5
5
|
group = 'host.exp.exponent'
|
|
6
|
-
version = '
|
|
6
|
+
version = '11.0.2'
|
|
7
7
|
|
|
8
8
|
buildscript {
|
|
9
9
|
// Simple helper that allows the root project to override versions declared by this library.
|
|
@@ -53,27 +53,23 @@ android {
|
|
|
53
53
|
targetCompatibility JavaVersion.VERSION_1_8
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
kotlinOptions {
|
|
57
|
+
jvmTarget = JavaVersion.VERSION_1_8
|
|
58
|
+
}
|
|
59
|
+
|
|
56
60
|
defaultConfig {
|
|
57
61
|
minSdkVersion safeExtGet("minSdkVersion", 21)
|
|
58
62
|
targetSdkVersion safeExtGet("targetSdkVersion", 30)
|
|
59
63
|
versionCode 17
|
|
60
|
-
versionName "
|
|
64
|
+
versionName "11.0.2"
|
|
61
65
|
}
|
|
62
66
|
lintOptions {
|
|
63
67
|
abortOnError false
|
|
64
68
|
}
|
|
65
69
|
}
|
|
66
70
|
|
|
67
|
-
if (new File(rootProject.projectDir.parentFile, 'package.json').exists()) {
|
|
68
|
-
apply from: project(":unimodules-core").file("../unimodules-core.gradle")
|
|
69
|
-
} else {
|
|
70
|
-
throw new GradleException(
|
|
71
|
-
"'unimodules-core.gradle' was not found in the usual React Native dependency location. " +
|
|
72
|
-
"This package can only be used in such projects. Are you sure you've installed the dependencies properly?")
|
|
73
|
-
}
|
|
74
|
-
|
|
75
71
|
dependencies {
|
|
76
|
-
|
|
72
|
+
implementation project(':expo-modules-core')
|
|
77
73
|
|
|
78
74
|
api "androidx.appcompat:appcompat:1.2.0"
|
|
79
75
|
|
|
@@ -1,24 +1,23 @@
|
|
|
1
1
|
<manifest package="expo.modules.mailcomposer"
|
|
2
|
-
|
|
2
|
+
xmlns:android="http://schemas.android.com/apk/res/android">
|
|
3
3
|
|
|
4
4
|
<application>
|
|
5
5
|
<!-- https://developer.android.com/guide/topics/manifest/provider-element.html -->
|
|
6
|
-
<provider
|
|
7
|
-
android:name=".
|
|
8
|
-
android:authorities="${applicationId}.MailComposerFileProvider"
|
|
9
|
-
android:exported="false"
|
|
10
|
-
android:grantUriPermissions="true">
|
|
11
|
-
<meta-data
|
|
12
|
-
android:name="android.support.FILE_PROVIDER_PATHS"
|
|
13
|
-
android:resource="@xml/mail_composer_provider_paths"/>
|
|
6
|
+
<provider android:name=".MailComposerFileProvider" android:authorities="${applicationId}.MailComposerFileProvider" android:exported="false" android:grantUriPermissions="true">
|
|
7
|
+
<meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/mail_composer_provider_paths"/>
|
|
14
8
|
</provider>
|
|
15
9
|
</application>
|
|
16
10
|
|
|
17
11
|
<queries>
|
|
18
12
|
<intent>
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
13
|
+
<!-- Required for sending mails if targeting API 30 -->
|
|
14
|
+
<action android:name="android.intent.action.SENDTO" />
|
|
15
|
+
<data android:scheme="mailto" />
|
|
16
|
+
</intent>
|
|
17
|
+
<intent>
|
|
18
|
+
<action android:name="android.intent.action.SEND_MULTIPLE" />
|
|
19
|
+
<category android:name="android.intent.category.DEFAULT" />
|
|
20
|
+
<data android:mimeType="*/*" />
|
|
22
21
|
</intent>
|
|
23
22
|
</queries>
|
|
24
23
|
</manifest>
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
package expo.modules.mailcomposer
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.content.Intent
|
|
5
|
+
import android.content.pm.LabeledIntent
|
|
6
|
+
import android.net.Uri
|
|
7
|
+
import android.os.Bundle
|
|
8
|
+
import expo.modules.core.ExportedModule
|
|
9
|
+
import expo.modules.core.ModuleRegistry
|
|
10
|
+
import expo.modules.core.ModuleRegistryDelegate
|
|
11
|
+
import expo.modules.core.Promise
|
|
12
|
+
import expo.modules.core.arguments.ReadableArguments
|
|
13
|
+
import expo.modules.core.interfaces.ActivityProvider
|
|
14
|
+
import expo.modules.core.interfaces.ExpoMethod
|
|
15
|
+
import expo.modules.core.interfaces.LifecycleEventListener
|
|
16
|
+
|
|
17
|
+
class MailComposerModule(
|
|
18
|
+
context: Context,
|
|
19
|
+
private val moduleRegistryDelegate: ModuleRegistryDelegate = ModuleRegistryDelegate()
|
|
20
|
+
) : ExportedModule(context), LifecycleEventListener {
|
|
21
|
+
private var composerOpened = false
|
|
22
|
+
private var pendingPromise: Promise? = null
|
|
23
|
+
override fun getName() = "ExpoMailComposer"
|
|
24
|
+
private val activityProvider: ActivityProvider by moduleRegistry()
|
|
25
|
+
|
|
26
|
+
private inline fun <reified T> moduleRegistry() = moduleRegistryDelegate.getFromModuleRegistry<T>()
|
|
27
|
+
|
|
28
|
+
override fun onCreate(moduleRegistry: ModuleRegistry) {
|
|
29
|
+
moduleRegistryDelegate.onCreate(moduleRegistry)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
@ExpoMethod
|
|
33
|
+
fun isAvailableAsync(promise: Promise) {
|
|
34
|
+
promise.resolve(true)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@ExpoMethod
|
|
38
|
+
fun composeAsync(options: ReadableArguments, promise: Promise) {
|
|
39
|
+
val intent = Intent(Intent.ACTION_SENDTO).apply { data = Uri.parse("mailto:") }
|
|
40
|
+
val application = activityProvider.currentActivity.application
|
|
41
|
+
val resolveInfo = context.packageManager.queryIntentActivities(intent, 0)
|
|
42
|
+
val mailIntents = resolveInfo.map { info ->
|
|
43
|
+
val isHtml = options.containsKey("isHtml") && options.getBoolean("isHtml")
|
|
44
|
+
val mailIntentBuilder = MailIntentBuilder(options)
|
|
45
|
+
.setComponentName(info.activityInfo.packageName, info.activityInfo.name)
|
|
46
|
+
.putExtraIfKeyExists("recipients", Intent.EXTRA_EMAIL)
|
|
47
|
+
.putExtraIfKeyExists("ccRecipients", Intent.EXTRA_CC)
|
|
48
|
+
.putExtraIfKeyExists("bccRecipients", Intent.EXTRA_BCC)
|
|
49
|
+
.putExtraIfKeyExists("subject", Intent.EXTRA_SUBJECT)
|
|
50
|
+
.putExtraIfKeyExists("body", Intent.EXTRA_TEXT, isHtml)
|
|
51
|
+
.putParcelableArrayListExtraIfKeyExists(
|
|
52
|
+
"attachments",
|
|
53
|
+
Intent.EXTRA_STREAM,
|
|
54
|
+
application
|
|
55
|
+
)
|
|
56
|
+
LabeledIntent(
|
|
57
|
+
mailIntentBuilder.build(),
|
|
58
|
+
info.activityInfo.packageName,
|
|
59
|
+
info.loadLabel(context.packageManager),
|
|
60
|
+
info.icon
|
|
61
|
+
)
|
|
62
|
+
}.toMutableList()
|
|
63
|
+
val chooser = Intent.createChooser(
|
|
64
|
+
mailIntents.removeAt(mailIntents.size - 1),
|
|
65
|
+
null
|
|
66
|
+
).apply {
|
|
67
|
+
putExtra(Intent.EXTRA_INITIAL_INTENTS, mailIntents.toTypedArray())
|
|
68
|
+
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
69
|
+
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
|
70
|
+
}
|
|
71
|
+
pendingPromise = promise
|
|
72
|
+
context.startActivity(chooser)
|
|
73
|
+
composerOpened = true
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
override fun onHostResume() {
|
|
77
|
+
val promise = pendingPromise ?: return
|
|
78
|
+
if (composerOpened) {
|
|
79
|
+
composerOpened = false
|
|
80
|
+
promise.resolve(Bundle().apply { putString("status", "sent") })
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
override fun onHostPause() = Unit
|
|
85
|
+
|
|
86
|
+
override fun onHostDestroy() {
|
|
87
|
+
// do nothing
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
package expo.modules.mailcomposer
|
|
2
|
+
|
|
3
|
+
import android.app.Application
|
|
4
|
+
import android.content.ComponentName
|
|
5
|
+
import android.content.Intent
|
|
6
|
+
import android.net.Uri
|
|
7
|
+
import android.text.Html
|
|
8
|
+
import android.util.Log
|
|
9
|
+
import androidx.core.content.FileProvider
|
|
10
|
+
import expo.modules.core.arguments.ReadableArguments
|
|
11
|
+
import java.io.File
|
|
12
|
+
|
|
13
|
+
class MailIntentBuilder(
|
|
14
|
+
private val options: ReadableArguments
|
|
15
|
+
) {
|
|
16
|
+
private val mailIntent = Intent(Intent.ACTION_SEND_MULTIPLE)
|
|
17
|
+
|
|
18
|
+
@Suppress("UNCHECKED_CAST")
|
|
19
|
+
private fun getStringArrayFrom(key: String): Array<String?> {
|
|
20
|
+
return (options.getList(key) as List<String?>).toTypedArray()
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
private fun contentUriFromFile(file: File, application: Application): Uri = try {
|
|
24
|
+
FileProvider.getUriForFile(
|
|
25
|
+
application,
|
|
26
|
+
application.packageName + ".MailComposerFileProvider",
|
|
27
|
+
file
|
|
28
|
+
)
|
|
29
|
+
} catch (e: Exception) {
|
|
30
|
+
Uri.fromFile(file)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
fun build() = mailIntent
|
|
34
|
+
|
|
35
|
+
fun setComponentName(pkg: String, cls: String) = apply {
|
|
36
|
+
mailIntent.component = ComponentName(pkg, cls)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
fun putExtraIfKeyExists(key: String, intentName: String) = apply {
|
|
40
|
+
if (options.containsKey(key)) {
|
|
41
|
+
if (options.getList(key) != null) {
|
|
42
|
+
mailIntent.putExtra(intentName, getStringArrayFrom(key))
|
|
43
|
+
} else {
|
|
44
|
+
mailIntent.putExtra(intentName, options.getString(key))
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
fun putExtraIfKeyExists(key: String, intentName: String, isBodyHtml: Boolean) = apply {
|
|
50
|
+
if (options.containsKey(key)) {
|
|
51
|
+
val body = if (isBodyHtml) {
|
|
52
|
+
Html.fromHtml(options.getString(key))
|
|
53
|
+
} else {
|
|
54
|
+
options.getString(key)
|
|
55
|
+
}
|
|
56
|
+
mailIntent.putExtra(intentName, body)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
fun putParcelableArrayListExtraIfKeyExists(
|
|
61
|
+
key: String,
|
|
62
|
+
intentName: String,
|
|
63
|
+
application: Application,
|
|
64
|
+
) = apply {
|
|
65
|
+
try {
|
|
66
|
+
if (options.containsKey(key)) {
|
|
67
|
+
val requestedAttachments = getStringArrayFrom(key)
|
|
68
|
+
val attachments = requestedAttachments.map { requestedAttachment ->
|
|
69
|
+
val path = Uri.parse(requestedAttachment).path
|
|
70
|
+
requireNotNull(path, { "Path to attachment can not be null" })
|
|
71
|
+
val attachmentFile = File(path)
|
|
72
|
+
contentUriFromFile(attachmentFile, application)
|
|
73
|
+
}.toCollection(ArrayList())
|
|
74
|
+
mailIntent.putParcelableArrayListExtra(intentName, attachments)
|
|
75
|
+
}
|
|
76
|
+
} catch (error: IllegalArgumentException) {
|
|
77
|
+
Log.e("ExpoMailComposer", "Illegal argument:", error)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: import("
|
|
1
|
+
declare const _default: import("expo-modules-core").ProxyNativeModule;
|
|
2
2
|
export default _default;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoMailComposer.js","sourceRoot":"","sources":["../src/ExpoMailComposer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"ExpoMailComposer.js","sourceRoot":"","sources":["../src/ExpoMailComposer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,eAAe,kBAAkB,CAAC,gBAAgB,CAAC","sourcesContent":["import { NativeModulesProxy } from 'expo-modules-core';\nexport default NativeModulesProxy.ExpoMailComposer;\n"]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// Copyright 2017-present 650 Industries. All rights reserved.
|
|
2
2
|
|
|
3
|
-
#import <
|
|
4
|
-
#import <
|
|
3
|
+
#import <ExpoModulesCore/EXExportedModule.h>
|
|
4
|
+
#import <ExpoModulesCore/EXModuleRegistryConsumer.h>
|
|
5
5
|
|
|
6
6
|
#import <MessageUI/MessageUI.h>
|
|
7
7
|
|
|
8
|
-
@interface EXMailComposer :
|
|
8
|
+
@interface EXMailComposer : EXExportedModule <EXModuleRegistryConsumer, MFMailComposeViewControllerDelegate>
|
|
9
9
|
@end
|
|
@@ -3,23 +3,23 @@
|
|
|
3
3
|
#import <EXMailComposer/EXMailComposer.h>
|
|
4
4
|
#import <MobileCoreServices/MobileCoreServices.h>
|
|
5
5
|
|
|
6
|
-
#import <
|
|
6
|
+
#import <ExpoModulesCore/EXUtilitiesInterface.h>
|
|
7
7
|
#import <ExpoModulesCore/EXFileSystemInterface.h>
|
|
8
8
|
|
|
9
9
|
@interface EXMailComposer ()
|
|
10
10
|
|
|
11
|
-
@property (nonatomic, weak)
|
|
11
|
+
@property (nonatomic, weak) EXModuleRegistry *moduleRegistry;
|
|
12
12
|
|
|
13
|
-
@property (nonatomic, strong)
|
|
14
|
-
@property (nonatomic, strong)
|
|
13
|
+
@property (nonatomic, strong) EXPromiseResolveBlock resolve;
|
|
14
|
+
@property (nonatomic, strong) EXPromiseRejectBlock reject;
|
|
15
15
|
|
|
16
16
|
@end
|
|
17
17
|
|
|
18
18
|
@implementation EXMailComposer
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
EX_EXPORT_MODULE(ExpoMailComposer);
|
|
21
21
|
|
|
22
|
-
- (void)setModuleRegistry:(
|
|
22
|
+
- (void)setModuleRegistry:(EXModuleRegistry *)moduleRegistry
|
|
23
23
|
{
|
|
24
24
|
_moduleRegistry = moduleRegistry;
|
|
25
25
|
}
|
|
@@ -29,18 +29,18 @@ UM_EXPORT_MODULE(ExpoMailComposer);
|
|
|
29
29
|
return dispatch_get_main_queue();
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
isAvailable:(
|
|
34
|
-
rejecter:(
|
|
32
|
+
EX_EXPORT_METHOD_AS(isAvailableAsync,
|
|
33
|
+
isAvailable:(EXPromiseResolveBlock)resolve
|
|
34
|
+
rejecter:(EXPromiseRejectBlock)reject)
|
|
35
35
|
{
|
|
36
36
|
resolve(@([MFMailComposeViewController canSendMail]));
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
EX_EXPORT_METHOD_AS(composeAsync,
|
|
41
41
|
composeAsync:(NSDictionary *)options
|
|
42
|
-
resolver:(
|
|
43
|
-
rejecter:(
|
|
42
|
+
resolver:(EXPromiseResolveBlock)resolve
|
|
43
|
+
rejecter:(EXPromiseRejectBlock)reject)
|
|
44
44
|
{
|
|
45
45
|
if (![MFMailComposeViewController canSendMail]) {
|
|
46
46
|
reject(@"E_COMPOSE_UNAVAILABLE", @"Mail services are not available. Make sure you're signed into the Mail app", nil);
|
|
@@ -118,7 +118,7 @@ UM_EXPORT_METHOD_AS(composeAsync,
|
|
|
118
118
|
|
|
119
119
|
self.resolve = resolve;
|
|
120
120
|
self.reject = reject;
|
|
121
|
-
id<
|
|
121
|
+
id<EXUtilitiesInterface> utilities = [_moduleRegistry getModuleImplementingProtocol:@protocol(EXUtilitiesInterface)];
|
|
122
122
|
[utilities.currentViewController presentViewController:composeController animated:YES completion:nil];
|
|
123
123
|
}
|
|
124
124
|
|
|
@@ -10,10 +10,10 @@ Pod::Spec.new do |s|
|
|
|
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, '12.0'
|
|
14
14
|
s.source = { git: 'https://github.com/expo/expo.git' }
|
|
15
|
+
s.static_framework = true
|
|
15
16
|
|
|
16
|
-
s.dependency 'UMCore'
|
|
17
17
|
s.dependency 'ExpoModulesCore'
|
|
18
18
|
|
|
19
19
|
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')
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-mail-composer",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "11.0.2",
|
|
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",
|
|
@@ -30,19 +30,16 @@
|
|
|
30
30
|
},
|
|
31
31
|
"author": "650 Industries, Inc.",
|
|
32
32
|
"license": "MIT",
|
|
33
|
-
"homepage": "https://docs.expo.
|
|
33
|
+
"homepage": "https://docs.expo.dev/versions/latest/sdk/mail-composer/",
|
|
34
34
|
"jest": {
|
|
35
35
|
"preset": "expo-module-scripts/ios"
|
|
36
36
|
},
|
|
37
|
-
"unimodulePeerDependencies": {
|
|
38
|
-
"@unimodules/core": "*"
|
|
39
|
-
},
|
|
40
37
|
"dependencies": {
|
|
41
|
-
"expo-modules-core": "~0.
|
|
38
|
+
"expo-modules-core": "~0.4.3",
|
|
42
39
|
"query-string": "^6.2.0"
|
|
43
40
|
},
|
|
44
41
|
"devDependencies": {
|
|
45
42
|
"expo-module-scripts": "^2.0.0"
|
|
46
43
|
},
|
|
47
|
-
"gitHead": "
|
|
44
|
+
"gitHead": "d23e1ac491da96b51c25eb2533efcd56499ee287"
|
|
48
45
|
}
|
package/src/ExpoMailComposer.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { NativeModulesProxy } from '
|
|
1
|
+
import { NativeModulesProxy } from 'expo-modules-core';
|
|
2
2
|
export default NativeModulesProxy.ExpoMailComposer;
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
package expo.modules.mailcomposer;
|
|
2
|
-
|
|
3
|
-
import android.app.Application;
|
|
4
|
-
import android.content.ComponentName;
|
|
5
|
-
import android.content.Context;
|
|
6
|
-
import android.content.Intent;
|
|
7
|
-
import android.content.pm.LabeledIntent;
|
|
8
|
-
import android.content.pm.ResolveInfo;
|
|
9
|
-
import android.net.Uri;
|
|
10
|
-
import android.os.Bundle;
|
|
11
|
-
import androidx.core.content.FileProvider;
|
|
12
|
-
import android.text.Html;
|
|
13
|
-
import android.text.Spanned;
|
|
14
|
-
|
|
15
|
-
import java.io.File;
|
|
16
|
-
import java.util.ArrayList;
|
|
17
|
-
import java.util.List;
|
|
18
|
-
|
|
19
|
-
import org.unimodules.core.ExportedModule;
|
|
20
|
-
import org.unimodules.core.ModuleRegistry;
|
|
21
|
-
import org.unimodules.core.Promise;
|
|
22
|
-
import org.unimodules.core.arguments.ReadableArguments;
|
|
23
|
-
import org.unimodules.core.interfaces.ActivityProvider;
|
|
24
|
-
import org.unimodules.core.interfaces.ExpoMethod;
|
|
25
|
-
import org.unimodules.core.interfaces.LifecycleEventListener;
|
|
26
|
-
import org.unimodules.core.interfaces.services.UIManager;
|
|
27
|
-
|
|
28
|
-
public class MailComposerModule extends ExportedModule implements LifecycleEventListener {
|
|
29
|
-
private boolean mComposerOpened = false;
|
|
30
|
-
private ModuleRegistry mModuleRegistry;
|
|
31
|
-
private Promise mPromise;
|
|
32
|
-
|
|
33
|
-
public MailComposerModule(Context context) {
|
|
34
|
-
super(context);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
@Override
|
|
38
|
-
public String getName() {
|
|
39
|
-
return "ExpoMailComposer";
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
@Override
|
|
43
|
-
public void onCreate(ModuleRegistry moduleRegistry) {
|
|
44
|
-
if (mModuleRegistry != null) {
|
|
45
|
-
mModuleRegistry.getModule(UIManager.class).unregisterLifecycleEventListener(this);
|
|
46
|
-
}
|
|
47
|
-
mModuleRegistry = moduleRegistry;
|
|
48
|
-
if (mModuleRegistry != null) {
|
|
49
|
-
mModuleRegistry.getModule(UIManager.class).registerLifecycleEventListener(this);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
@ExpoMethod
|
|
54
|
-
public void isAvailableAsync(final Promise promise) {
|
|
55
|
-
promise.resolve(true);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
@ExpoMethod
|
|
59
|
-
public void composeAsync(ReadableArguments options, Promise promise) {
|
|
60
|
-
|
|
61
|
-
Intent intent = new Intent(Intent.ACTION_SENDTO);
|
|
62
|
-
intent.setData(Uri.parse("mailto:"));
|
|
63
|
-
|
|
64
|
-
String[] recipients = {}, ccRecipients = {}, bccRecipients = {};
|
|
65
|
-
String subject = "";
|
|
66
|
-
String body = "";
|
|
67
|
-
Spanned htmlBody = null;
|
|
68
|
-
ArrayList<Uri> attachments = new ArrayList<>();
|
|
69
|
-
|
|
70
|
-
if (options.containsKey("recipients")) {
|
|
71
|
-
recipients = getStringArrayFrom(options, "recipients");
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
if (options.containsKey("ccRecipients")) {
|
|
75
|
-
ccRecipients = getStringArrayFrom(options, "ccRecipients");
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (options.containsKey("bccRecipients")) {
|
|
79
|
-
bccRecipients = getStringArrayFrom(options, "bccRecipients");
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (options.containsKey("subject")) {
|
|
83
|
-
subject = options.getString("subject");
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
boolean isHtml = options.containsKey("isHtml") && options.getBoolean("isHtml");
|
|
87
|
-
if (options.containsKey("body")) {
|
|
88
|
-
if (isHtml) {
|
|
89
|
-
htmlBody = Html.fromHtml(options.getString("body"));
|
|
90
|
-
} else {
|
|
91
|
-
body = options.getString("body");
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
if (options.containsKey("attachments")) {
|
|
96
|
-
String[] requestedAttachments = getStringArrayFrom(options, "attachments");
|
|
97
|
-
for (String requestedAttachment : requestedAttachments) {
|
|
98
|
-
File attachmentFile = new File(Uri.parse(requestedAttachment).getPath());
|
|
99
|
-
attachments.add(contentUriFromFile(attachmentFile));
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
List<ResolveInfo> resolveInfos = getContext().getPackageManager().queryIntentActivities(intent, 0);
|
|
104
|
-
List<LabeledIntent> mailIntents = new ArrayList<>();
|
|
105
|
-
for (ResolveInfo info : resolveInfos) {
|
|
106
|
-
Intent mailIntent = new Intent(Intent.ACTION_SEND_MULTIPLE);
|
|
107
|
-
mailIntent.setComponent(new ComponentName(info.activityInfo.packageName, info.activityInfo.name));
|
|
108
|
-
mailIntent.putExtra(Intent.EXTRA_EMAIL, recipients);
|
|
109
|
-
mailIntent.putExtra(Intent.EXTRA_CC, ccRecipients);
|
|
110
|
-
mailIntent.putExtra(Intent.EXTRA_BCC, bccRecipients);
|
|
111
|
-
mailIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
|
|
112
|
-
mailIntent.putExtra(Intent.EXTRA_TEXT, isHtml ? htmlBody : body);
|
|
113
|
-
mailIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, attachments);
|
|
114
|
-
mailIntents.add(new LabeledIntent(mailIntent, info.activityInfo.packageName, info.loadLabel(getContext().getPackageManager()), info.icon));
|
|
115
|
-
}
|
|
116
|
-
Intent chooser = Intent.createChooser(mailIntents.remove(mailIntents.size() - 1), null);
|
|
117
|
-
chooser.putExtra(Intent.EXTRA_INITIAL_INTENTS, mailIntents.toArray(new LabeledIntent[mailIntents.size()]));
|
|
118
|
-
|
|
119
|
-
mPromise = promise;
|
|
120
|
-
chooser.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
|
121
|
-
chooser.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
|
122
|
-
getContext().startActivity(chooser);
|
|
123
|
-
mComposerOpened = true;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
@Override
|
|
127
|
-
public void onHostResume() {
|
|
128
|
-
if (mComposerOpened) {
|
|
129
|
-
mComposerOpened = false;
|
|
130
|
-
Bundle response = new Bundle();
|
|
131
|
-
response.putString("status", "sent");
|
|
132
|
-
mPromise.resolve(response);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
@Override
|
|
137
|
-
public void onHostPause() {
|
|
138
|
-
// do nothing
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
@Override
|
|
142
|
-
public void onHostDestroy() {
|
|
143
|
-
// do nothing
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
private String[] getStringArrayFrom(ReadableArguments arguments, String key) {
|
|
147
|
-
return ((List<String>) arguments.getList(key)).toArray(new String[0]);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
private Uri contentUriFromFile(File file) {
|
|
151
|
-
try {
|
|
152
|
-
Application application = mModuleRegistry.getModule(ActivityProvider.class).getCurrentActivity().getApplication();
|
|
153
|
-
return FileProvider.getUriForFile(application, application.getPackageName() + ".MailComposerFileProvider", file);
|
|
154
|
-
} catch (Exception e) {
|
|
155
|
-
return Uri.fromFile(file);
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
package expo.modules.mailcomposer;
|
|
2
|
-
|
|
3
|
-
import android.content.Context;
|
|
4
|
-
|
|
5
|
-
import java.util.Collections;
|
|
6
|
-
import java.util.List;
|
|
7
|
-
|
|
8
|
-
import org.unimodules.core.BasePackage;
|
|
9
|
-
import org.unimodules.core.ExportedModule;
|
|
10
|
-
|
|
11
|
-
public class MailComposerPackage extends BasePackage {
|
|
12
|
-
@Override
|
|
13
|
-
public List<ExportedModule> createExportedModules(Context context) {
|
|
14
|
-
return Collections.singletonList((ExportedModule) new MailComposerModule(context));
|
|
15
|
-
}
|
|
16
|
-
}
|