<lambda>null1 package expo.modules.mailcomposer
2 
3 import android.content.Intent
4 import android.content.pm.LabeledIntent
5 import android.net.Uri
6 import android.os.Bundle
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
11 
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()
17   private var composerOpened = false
18   private var pendingPromise: Promise? = null
19 
20   override fun definition() = ModuleDefinition {
21     Name("ExpoMailComposer")
22 
23     AsyncFunction("isAvailableAsync") {
24       return@AsyncFunction true
25     }
26 
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)
31 
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 
45         LabeledIntent(
46           mailIntentBuilder.build(),
47           info.activityInfo.packageName,
48           info.loadLabel(context.packageManager),
49           info.icon
50         )
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       }
60 
61       pendingPromise = promise
62       currentActivity.startActivityForResult(chooser, REQUEST_CODE)
63       composerOpened = true
64     }
65 
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         }
73       }
74     }
75   }
76 
77   companion object {
78     private const val REQUEST_CODE = 8675
79   }
80 }
81