expo-mail-composer 12.1.1 → 12.3.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/README.md +2 -2
- package/android/build.gradle +8 -10
- package/android/src/main/AndroidManifest.xml +1 -2
- package/android/src/main/java/expo/modules/mailcomposer/MailComposerModule.kt +55 -73
- package/android/src/main/java/expo/modules/mailcomposer/MailIntentBuilder.kt +32 -24
- package/android/src/main/java/expo/modules/mailcomposer/Records.kt +21 -0
- package/expo-module.config.json +3 -0
- package/package.json +2 -2
- package/android/src/main/java/expo/modules/mailcomposer/MailComposerPackage.kt +0 -9
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,18 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 12.3.0 — 2023-06-21
|
|
14
|
+
|
|
15
|
+
### 🐛 Bug fixes
|
|
16
|
+
|
|
17
|
+
- Fixed Android build warnings for Gradle version 8. ([#22537](https://github.com/expo/expo/pull/22537), [#22609](https://github.com/expo/expo/pull/22609) by [@kudo](https://github.com/kudo))
|
|
18
|
+
|
|
19
|
+
## 12.2.0 — 2023-05-08
|
|
20
|
+
|
|
21
|
+
### 💡 Others
|
|
22
|
+
|
|
23
|
+
- Migrated Android codebase to use the new modules API. ([#21200](https://github.com/expo/expo/pull/21200) by [@alanjhughes](https://github.com/alanjhughes))
|
|
24
|
+
|
|
13
25
|
## 12.1.1 — 2023-02-09
|
|
14
26
|
|
|
15
27
|
_This version does not introduce any user-facing changes._
|
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ Provides an API to compose mails using OS specific UI
|
|
|
16
16
|
|
|
17
17
|
# Installation in managed Expo projects
|
|
18
18
|
|
|
19
|
-
For [managed](https://docs.expo.dev/
|
|
19
|
+
For [managed](https://docs.expo.dev/archive/managed-vs-bare/) Expo projects, please follow the installation instructions in the [API documentation for the latest stable release](https://docs.expo.dev/versions/latest/sdk/mail-composer/).
|
|
20
20
|
|
|
21
21
|
# Installation in bare React Native projects
|
|
22
22
|
|
|
@@ -25,7 +25,7 @@ For bare React Native projects, you must ensure that you have [installed and con
|
|
|
25
25
|
### Add the package to your npm dependencies
|
|
26
26
|
|
|
27
27
|
```
|
|
28
|
-
expo install expo-mail-composer
|
|
28
|
+
npx expo install expo-mail-composer
|
|
29
29
|
```
|
|
30
30
|
|
|
31
31
|
### Configure for iOS
|
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 = '12.
|
|
6
|
+
version = '12.3.0'
|
|
7
7
|
|
|
8
8
|
buildscript {
|
|
9
9
|
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
|
|
@@ -35,19 +35,11 @@ buildscript {
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
// Creating sources with comments
|
|
39
|
-
task androidSourcesJar(type: Jar) {
|
|
40
|
-
classifier = 'sources'
|
|
41
|
-
from android.sourceSets.main.java.srcDirs
|
|
42
|
-
}
|
|
43
|
-
|
|
44
38
|
afterEvaluate {
|
|
45
39
|
publishing {
|
|
46
40
|
publications {
|
|
47
41
|
release(MavenPublication) {
|
|
48
42
|
from components.release
|
|
49
|
-
// Add additional sourcesJar to artifacts
|
|
50
|
-
artifact(androidSourcesJar)
|
|
51
43
|
}
|
|
52
44
|
}
|
|
53
45
|
repositories {
|
|
@@ -70,15 +62,21 @@ android {
|
|
|
70
62
|
jvmTarget = JavaVersion.VERSION_11.majorVersion
|
|
71
63
|
}
|
|
72
64
|
|
|
65
|
+
namespace "expo.modules.mailcomposer"
|
|
73
66
|
defaultConfig {
|
|
74
67
|
minSdkVersion safeExtGet("minSdkVersion", 21)
|
|
75
68
|
targetSdkVersion safeExtGet("targetSdkVersion", 33)
|
|
76
69
|
versionCode 17
|
|
77
|
-
versionName "12.
|
|
70
|
+
versionName "12.3.0"
|
|
78
71
|
}
|
|
79
72
|
lintOptions {
|
|
80
73
|
abortOnError false
|
|
81
74
|
}
|
|
75
|
+
publishing {
|
|
76
|
+
singleVariant("release") {
|
|
77
|
+
withSourcesJar()
|
|
78
|
+
}
|
|
79
|
+
}
|
|
82
80
|
}
|
|
83
81
|
|
|
84
82
|
dependencies {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
<manifest
|
|
2
|
-
xmlns:android="http://schemas.android.com/apk/res/android">
|
|
1
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
3
2
|
|
|
4
3
|
<application>
|
|
5
4
|
<!-- https://developer.android.com/guide/topics/manifest/provider-element.html -->
|
|
@@ -1,93 +1,75 @@
|
|
|
1
1
|
package expo.modules.mailcomposer
|
|
2
2
|
|
|
3
|
-
import android.app.Activity
|
|
4
|
-
import android.content.Context
|
|
5
3
|
import android.content.Intent
|
|
6
4
|
import android.content.pm.LabeledIntent
|
|
7
5
|
import android.net.Uri
|
|
8
6
|
import android.os.Bundle
|
|
9
|
-
import expo.modules.
|
|
10
|
-
import expo.modules.
|
|
11
|
-
import expo.modules.
|
|
12
|
-
import expo.modules.
|
|
13
|
-
import expo.modules.core.arguments.ReadableArguments
|
|
14
|
-
import expo.modules.core.interfaces.ActivityProvider
|
|
15
|
-
import expo.modules.core.interfaces.ExpoMethod
|
|
16
|
-
import expo.modules.core.interfaces.ActivityEventListener
|
|
17
|
-
import expo.modules.core.interfaces.services.UIManager
|
|
7
|
+
import expo.modules.kotlin.Promise
|
|
8
|
+
import expo.modules.kotlin.exception.Exceptions
|
|
9
|
+
import expo.modules.kotlin.modules.Module
|
|
10
|
+
import expo.modules.kotlin.modules.ModuleDefinition
|
|
18
11
|
|
|
19
|
-
class MailComposerModule(
|
|
20
|
-
context
|
|
21
|
-
|
|
22
|
-
|
|
12
|
+
class MailComposerModule : Module() {
|
|
13
|
+
private val context
|
|
14
|
+
get() = appContext.reactContext ?: throw Exceptions.ReactContextLost()
|
|
15
|
+
private val currentActivity
|
|
16
|
+
get() = appContext.currentActivity ?: throw Exceptions.MissingActivity()
|
|
23
17
|
private var composerOpened = false
|
|
24
|
-
private val uiManager: UIManager by moduleRegistry()
|
|
25
18
|
private var pendingPromise: Promise? = null
|
|
26
|
-
override fun getName() = "ExpoMailComposer"
|
|
27
|
-
private val activityProvider: ActivityProvider by moduleRegistry()
|
|
28
19
|
|
|
29
|
-
|
|
20
|
+
override fun definition() = ModuleDefinition {
|
|
21
|
+
Name("ExpoMailComposer")
|
|
30
22
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
23
|
+
AsyncFunction("isAvailableAsync") {
|
|
24
|
+
return@AsyncFunction true
|
|
25
|
+
}
|
|
35
26
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
27
|
+
AsyncFunction("composeAsync") { options: MailComposerOptions, promise: Promise ->
|
|
28
|
+
val intent = Intent(Intent.ACTION_SENDTO).apply { data = Uri.parse("mailto:") }
|
|
29
|
+
val application = currentActivity.application
|
|
30
|
+
val resolveInfo = context.packageManager.queryIntentActivities(intent, 0)
|
|
39
31
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
32
|
+
val mailIntents = resolveInfo.map { info ->
|
|
33
|
+
val mailIntentBuilder = MailIntentBuilder(options)
|
|
34
|
+
.setComponentName(info.activityInfo.packageName, info.activityInfo.name)
|
|
35
|
+
.putRecipients(Intent.EXTRA_EMAIL)
|
|
36
|
+
.putCcRecipients(Intent.EXTRA_CC)
|
|
37
|
+
.putBccRecipients(Intent.EXTRA_BCC)
|
|
38
|
+
.putSubject(Intent.EXTRA_SUBJECT)
|
|
39
|
+
.putBody(Intent.EXTRA_TEXT, options.isHtml ?: false)
|
|
40
|
+
.putAttachments(
|
|
41
|
+
Intent.EXTRA_STREAM,
|
|
42
|
+
application
|
|
43
|
+
)
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
val mailIntents = resolveInfo.map { info ->
|
|
51
|
-
val isHtml = options.containsKey("isHtml") && options.getBoolean("isHtml")
|
|
52
|
-
val mailIntentBuilder = MailIntentBuilder(options)
|
|
53
|
-
.setComponentName(info.activityInfo.packageName, info.activityInfo.name)
|
|
54
|
-
.putExtraIfKeyExists("recipients", Intent.EXTRA_EMAIL)
|
|
55
|
-
.putExtraIfKeyExists("ccRecipients", Intent.EXTRA_CC)
|
|
56
|
-
.putExtraIfKeyExists("bccRecipients", Intent.EXTRA_BCC)
|
|
57
|
-
.putExtraIfKeyExists("subject", Intent.EXTRA_SUBJECT)
|
|
58
|
-
.putExtraIfKeyExists("body", Intent.EXTRA_TEXT, isHtml)
|
|
59
|
-
.putParcelableArrayListExtraIfKeyExists(
|
|
60
|
-
"attachments",
|
|
61
|
-
Intent.EXTRA_STREAM,
|
|
62
|
-
application
|
|
45
|
+
LabeledIntent(
|
|
46
|
+
mailIntentBuilder.build(),
|
|
47
|
+
info.activityInfo.packageName,
|
|
48
|
+
info.loadLabel(context.packageManager),
|
|
49
|
+
info.icon
|
|
63
50
|
)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
null
|
|
74
|
-
).apply {
|
|
75
|
-
putExtra(Intent.EXTRA_INITIAL_INTENTS, mailIntents.toTypedArray())
|
|
76
|
-
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
|
77
|
-
}
|
|
78
|
-
pendingPromise = promise
|
|
79
|
-
activityProvider.currentActivity.startActivityForResult(chooser, REQUEST_CODE)
|
|
80
|
-
composerOpened = true
|
|
81
|
-
}
|
|
51
|
+
}.toMutableList()
|
|
52
|
+
|
|
53
|
+
val chooser = Intent.createChooser(
|
|
54
|
+
mailIntents.removeAt(mailIntents.size - 1),
|
|
55
|
+
null
|
|
56
|
+
).apply {
|
|
57
|
+
putExtra(Intent.EXTRA_INITIAL_INTENTS, mailIntents.toTypedArray())
|
|
58
|
+
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
|
59
|
+
}
|
|
82
60
|
|
|
83
|
-
|
|
61
|
+
pendingPromise = promise
|
|
62
|
+
currentActivity.startActivityForResult(chooser, REQUEST_CODE)
|
|
63
|
+
composerOpened = true
|
|
64
|
+
}
|
|
84
65
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
66
|
+
OnActivityResult { _, payload ->
|
|
67
|
+
if (payload.requestCode == REQUEST_CODE && pendingPromise != null) {
|
|
68
|
+
val promise = pendingPromise ?: return@OnActivityResult
|
|
69
|
+
if (composerOpened) {
|
|
70
|
+
composerOpened = false
|
|
71
|
+
promise.resolve(Bundle().apply { putString("status", "sent") })
|
|
72
|
+
}
|
|
91
73
|
}
|
|
92
74
|
}
|
|
93
75
|
}
|
|
@@ -7,19 +7,13 @@ import android.net.Uri
|
|
|
7
7
|
import android.text.Html
|
|
8
8
|
import android.util.Log
|
|
9
9
|
import androidx.core.content.FileProvider
|
|
10
|
-
import expo.modules.core.arguments.ReadableArguments
|
|
11
10
|
import java.io.File
|
|
12
11
|
|
|
13
12
|
class MailIntentBuilder(
|
|
14
|
-
private val options:
|
|
13
|
+
private val options: MailComposerOptions
|
|
15
14
|
) {
|
|
16
15
|
private val mailIntent = Intent(Intent.ACTION_SEND_MULTIPLE)
|
|
17
16
|
|
|
18
|
-
@Suppress("UNCHECKED_CAST")
|
|
19
|
-
private fun getStringArrayFrom(key: String): Array<String?> {
|
|
20
|
-
return (options.getList(key) as List<String?>).toTypedArray()
|
|
21
|
-
}
|
|
22
|
-
|
|
23
17
|
private fun contentUriFromFile(file: File, application: Application): Uri = try {
|
|
24
18
|
FileProvider.getUriForFile(
|
|
25
19
|
application,
|
|
@@ -36,41 +30,55 @@ class MailIntentBuilder(
|
|
|
36
30
|
mailIntent.component = ComponentName(pkg, cls)
|
|
37
31
|
}
|
|
38
32
|
|
|
39
|
-
fun
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
mailIntent.putExtra(intentName, getStringArrayFrom(key))
|
|
43
|
-
} else {
|
|
44
|
-
mailIntent.putExtra(intentName, options.getString(key))
|
|
45
|
-
}
|
|
33
|
+
fun putRecipients(intentName: String) = apply {
|
|
34
|
+
options.recipients?.let {
|
|
35
|
+
mailIntent.putExtra(intentName, it.toTypedArray())
|
|
46
36
|
}
|
|
47
37
|
}
|
|
48
38
|
|
|
49
|
-
fun
|
|
50
|
-
|
|
39
|
+
fun putCcRecipients(intentName: String) = apply {
|
|
40
|
+
options.ccRecipients?.let {
|
|
41
|
+
mailIntent.putExtra(intentName, it.toTypedArray())
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
fun putBccRecipients(intentName: String) = apply {
|
|
46
|
+
options.bccRecipients?.let {
|
|
47
|
+
mailIntent.putExtra(intentName, it.toTypedArray())
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
fun putSubject(intentName: String) = apply {
|
|
52
|
+
options.subject?.let {
|
|
53
|
+
mailIntent.putExtra(intentName, it)
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
fun putBody(intentName: String, isBodyHtml: Boolean) = apply {
|
|
58
|
+
options.body?.let {
|
|
51
59
|
val body = if (isBodyHtml) {
|
|
52
|
-
Html.fromHtml(options.
|
|
60
|
+
Html.fromHtml(options.body)
|
|
53
61
|
} else {
|
|
54
|
-
options.
|
|
62
|
+
options.body
|
|
55
63
|
}
|
|
56
64
|
mailIntent.putExtra(intentName, body)
|
|
57
65
|
}
|
|
58
66
|
}
|
|
59
67
|
|
|
60
|
-
fun
|
|
61
|
-
key: String,
|
|
68
|
+
fun putAttachments(
|
|
62
69
|
intentName: String,
|
|
63
70
|
application: Application,
|
|
64
71
|
) = apply {
|
|
65
72
|
try {
|
|
66
|
-
|
|
67
|
-
val
|
|
68
|
-
val attachments = requestedAttachments.map { requestedAttachment ->
|
|
73
|
+
options.attachments?.let { requestedAttachments ->
|
|
74
|
+
val attachments = requestedAttachments.toTypedArray().map { requestedAttachment ->
|
|
69
75
|
val path = Uri.parse(requestedAttachment).path
|
|
70
|
-
requireNotNull(path
|
|
76
|
+
requireNotNull(path) { "Path to attachment can not be null" }
|
|
77
|
+
|
|
71
78
|
val attachmentFile = File(path)
|
|
72
79
|
contentUriFromFile(attachmentFile, application)
|
|
73
80
|
}.toCollection(ArrayList())
|
|
81
|
+
|
|
74
82
|
mailIntent.putParcelableArrayListExtra(intentName, attachments)
|
|
75
83
|
}
|
|
76
84
|
} catch (error: IllegalArgumentException) {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
package expo.modules.mailcomposer
|
|
2
|
+
|
|
3
|
+
import expo.modules.kotlin.records.Field
|
|
4
|
+
import expo.modules.kotlin.records.Record
|
|
5
|
+
|
|
6
|
+
data class MailComposerOptions(
|
|
7
|
+
@Field
|
|
8
|
+
val recipients: List<String>?,
|
|
9
|
+
@Field
|
|
10
|
+
val ccRecipients: List<String>?,
|
|
11
|
+
@Field
|
|
12
|
+
val bccRecipients: List<String>?,
|
|
13
|
+
@Field
|
|
14
|
+
val subject: String?,
|
|
15
|
+
@Field
|
|
16
|
+
val body: String?,
|
|
17
|
+
@Field
|
|
18
|
+
val isHtml: Boolean?,
|
|
19
|
+
@Field
|
|
20
|
+
val attachments: List<String>?,
|
|
21
|
+
) : Record
|
package/expo-module.config.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-mail-composer",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.3.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",
|
|
@@ -43,5 +43,5 @@
|
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"expo": "*"
|
|
45
45
|
},
|
|
46
|
-
"gitHead": "
|
|
46
|
+
"gitHead": "fa5ecca8251986b9f197cc14074eec0ab6dfb6db"
|
|
47
47
|
}
|