expo-sms 11.0.0 → 11.2.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 +1 -1
- package/android/build.gradle +4 -4
- package/android/src/main/java/expo/modules/sms/SMSExceptions.kt +9 -0
- package/android/src/main/java/expo/modules/sms/SMSModule.kt +55 -85
- package/android/src/main/java/expo/modules/sms/SMSOptions.kt +14 -0
- package/build/ExpoSMS.d.ts +1 -1
- package/build/ExpoSMS.d.ts.map +1 -1
- package/build/ExpoSMS.js +2 -2
- package/build/ExpoSMS.js.map +1 -1
- package/build/SMS.d.ts +1 -1
- package/build/SMS.js +1 -1
- package/build/SMS.js.map +1 -1
- package/build/SMS.types.d.ts +3 -3
- package/build/SMS.types.d.ts.map +1 -1
- package/expo-module.config.json +10 -0
- package/ios/{EXSMS.podspec → ExpoSMS.podspec} +4 -3
- package/ios/ExpoSMSModule.swift +93 -0
- package/ios/SMSDelegate.swift +37 -0
- package/ios/SMSExceptions.swift +37 -0
- package/ios/SMSOptions.swift +11 -0
- package/package.json +2 -2
- package/src/ExpoSMS.ts +2 -2
- package/src/SMS.ts +1 -1
- package/android/src/main/java/expo/modules/sms/SMSPackage.kt +0 -11
- package/ios/EXSMS/EXSMSModule.h +0 -7
- package/ios/EXSMS/EXSMSModule.m +0 -132
- package/unimodule.json +0 -4
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,18 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 11.2.0 — 2023-02-03
|
|
14
|
+
|
|
15
|
+
### 💡 Others
|
|
16
|
+
|
|
17
|
+
- On Android bump `compileSdkVersion` and `targetSdkVersion` to `33`. ([#20721](https://github.com/expo/expo/pull/20721) by [@lukmccall](https://github.com/lukmccall))
|
|
18
|
+
|
|
19
|
+
## 11.1.0 — 2022-12-30
|
|
20
|
+
|
|
21
|
+
### 🎉 New features
|
|
22
|
+
|
|
23
|
+
- Migrated to Expo Modules API. ([#19996](https://github.com/expo/expo/pull/19996) and ([#19967](https://github.com/expo/expo/pull/19967) by [@alanhughes](https://github.com/alanjhughes))
|
|
24
|
+
|
|
13
25
|
## 11.0.0 — 2022-10-25
|
|
14
26
|
|
|
15
27
|
### 🛠 Breaking changes
|
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Provides access to the system's UI/app for sending SMS messages.
|
|
|
4
4
|
|
|
5
5
|
# API documentation
|
|
6
6
|
|
|
7
|
-
- [Documentation for the main branch](https://github.com/expo/expo/blob/main/docs/pages/versions/unversioned/sdk/sms.
|
|
7
|
+
- [Documentation for the main branch](https://github.com/expo/expo/blob/main/docs/pages/versions/unversioned/sdk/sms.mdx)
|
|
8
8
|
- [Documentation for the latest stable release](https://docs.expo.dev/versions/latest/sdk/sms/)
|
|
9
9
|
|
|
10
10
|
# Installation in managed Expo projects
|
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 = '11.
|
|
6
|
+
version = '11.2.0'
|
|
7
7
|
|
|
8
8
|
buildscript {
|
|
9
9
|
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
|
|
@@ -59,7 +59,7 @@ afterEvaluate {
|
|
|
59
59
|
}
|
|
60
60
|
|
|
61
61
|
android {
|
|
62
|
-
compileSdkVersion safeExtGet("compileSdkVersion",
|
|
62
|
+
compileSdkVersion safeExtGet("compileSdkVersion", 33)
|
|
63
63
|
|
|
64
64
|
compileOptions {
|
|
65
65
|
sourceCompatibility JavaVersion.VERSION_11
|
|
@@ -72,9 +72,9 @@ android {
|
|
|
72
72
|
|
|
73
73
|
defaultConfig {
|
|
74
74
|
minSdkVersion safeExtGet("minSdkVersion", 21)
|
|
75
|
-
targetSdkVersion safeExtGet("targetSdkVersion",
|
|
75
|
+
targetSdkVersion safeExtGet("targetSdkVersion", 33)
|
|
76
76
|
versionCode 28
|
|
77
|
-
versionName "11.
|
|
77
|
+
versionName "11.2.0"
|
|
78
78
|
}
|
|
79
79
|
lintOptions {
|
|
80
80
|
abortOnError false
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
package expo.modules.sms
|
|
2
|
+
|
|
3
|
+
import expo.modules.kotlin.exception.CodedException
|
|
4
|
+
|
|
5
|
+
internal class MissingSMSAppException :
|
|
6
|
+
CodedException("No messaging application available")
|
|
7
|
+
|
|
8
|
+
internal class MissingCurrentActivityException :
|
|
9
|
+
CodedException("Activity which was provided during module initialization is no longer available")
|
|
@@ -2,75 +2,60 @@ package expo.modules.sms
|
|
|
2
2
|
|
|
3
3
|
import android.content.Context
|
|
4
4
|
import android.content.Intent
|
|
5
|
+
import android.content.pm.PackageManager
|
|
5
6
|
import android.net.Uri
|
|
6
7
|
import android.provider.Telephony
|
|
7
|
-
import
|
|
8
|
-
import android.os.Bundle
|
|
9
|
-
|
|
10
|
-
import java.util.ArrayList
|
|
11
|
-
|
|
12
|
-
import expo.modules.core.ExportedModule
|
|
8
|
+
import androidx.core.os.bundleOf
|
|
13
9
|
import expo.modules.core.interfaces.LifecycleEventListener
|
|
14
|
-
import expo.modules.core.ModuleRegistry
|
|
15
|
-
import expo.modules.core.Promise
|
|
16
10
|
import expo.modules.core.interfaces.services.UIManager
|
|
17
|
-
import expo.modules.
|
|
18
|
-
import expo.modules.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
private
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
// Unregister from old UIManager
|
|
40
|
-
mModuleRegistry.getModule(UIManager::class.java)?.unregisterLifecycleEventListener(this)
|
|
41
|
-
}
|
|
11
|
+
import expo.modules.kotlin.Promise
|
|
12
|
+
import expo.modules.kotlin.exception.Exceptions
|
|
13
|
+
import expo.modules.kotlin.modules.Module
|
|
14
|
+
import expo.modules.kotlin.modules.ModuleDefinition
|
|
15
|
+
|
|
16
|
+
class SMSModule : Module(), LifecycleEventListener {
|
|
17
|
+
private var pendingPromise: Promise? = null
|
|
18
|
+
private var smsComposerOpened = false
|
|
19
|
+
|
|
20
|
+
private val context: Context
|
|
21
|
+
get() = appContext.reactContext ?: throw Exceptions.ReactContextLost()
|
|
22
|
+
private val currentActivity
|
|
23
|
+
get() = appContext.activityProvider?.currentActivity
|
|
24
|
+
?: throw MissingCurrentActivityException()
|
|
25
|
+
|
|
26
|
+
override fun definition() = ModuleDefinition {
|
|
27
|
+
Name("ExpoSMS")
|
|
28
|
+
|
|
29
|
+
OnCreate {
|
|
30
|
+
val uiManager = appContext.legacyModule<UIManager>()
|
|
31
|
+
uiManager?.registerLifecycleEventListener(this@SMSModule)
|
|
32
|
+
}
|
|
42
33
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
34
|
+
AsyncFunction("sendSMSAsync") { addresses: List<String>, message: String, options: SMSOptions, promise: Promise ->
|
|
35
|
+
sendSMSAsync(addresses, message, options, promise)
|
|
36
|
+
}
|
|
46
37
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
addresses: ArrayList<String>,
|
|
50
|
-
message: String,
|
|
51
|
-
options: Map<String?, Any?>?,
|
|
52
|
-
promise: Promise
|
|
53
|
-
) {
|
|
54
|
-
if (mPendingPromise != null) {
|
|
55
|
-
promise.reject(
|
|
56
|
-
ERROR_TAG + "_SENDING_IN_PROGRESS",
|
|
57
|
-
"Different SMS sending in progress. Await the old request and then try again."
|
|
58
|
-
)
|
|
59
|
-
return
|
|
38
|
+
AsyncFunction("isAvailableAsync") {
|
|
39
|
+
return@AsyncFunction context.packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
|
|
60
40
|
}
|
|
61
41
|
|
|
62
|
-
|
|
42
|
+
OnDestroy {
|
|
43
|
+
val uiManager = appContext.legacyModule<UIManager>()
|
|
44
|
+
uiManager?.unregisterLifecycleEventListener(this@SMSModule)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
63
47
|
|
|
48
|
+
private fun sendSMSAsync(addresses: List<String>, message: String, options: SMSOptions, promise: Promise) {
|
|
64
49
|
// ACTION_SEND causes a weird flicker on Android 10 devices if the messaging app is not already
|
|
65
50
|
// open in the background, but it seems to be the only intent type that works for including
|
|
66
51
|
// attachments, so we use it if there are attachments and fall back to ACTION_SENDTO otherwise.
|
|
67
|
-
val smsIntent = if (attachments
|
|
52
|
+
val smsIntent = if (options.attachments.isNotEmpty()) {
|
|
68
53
|
Intent(Intent.ACTION_SEND).apply {
|
|
69
54
|
type = "text/plain"
|
|
70
55
|
putExtra("address", addresses.joinToString(separator = ";"))
|
|
71
|
-
val attachment = attachments[0]
|
|
72
|
-
putExtra(Intent.EXTRA_STREAM, Uri.parse(
|
|
73
|
-
type =
|
|
56
|
+
val attachment = options.attachments[0]
|
|
57
|
+
putExtra(Intent.EXTRA_STREAM, Uri.parse(attachment.uri))
|
|
58
|
+
type = attachment.mimeType
|
|
74
59
|
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
|
75
60
|
}
|
|
76
61
|
} else {
|
|
@@ -79,49 +64,34 @@ class SMSModule(context: Context, private val smsPackage: String? = null) : Expo
|
|
|
79
64
|
}
|
|
80
65
|
}
|
|
81
66
|
|
|
82
|
-
val defaultSMSPackage
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
86
|
-
defaultSMSPackage = Telephony.Sms.getDefaultSmsPackage(context)
|
|
87
|
-
}
|
|
67
|
+
val defaultSMSPackage = Telephony.Sms.getDefaultSmsPackage(context)
|
|
68
|
+
defaultSMSPackage?.let {
|
|
69
|
+
smsIntent.setPackage(it)
|
|
70
|
+
} ?: throw MissingSMSAppException()
|
|
88
71
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
return
|
|
72
|
+
smsIntent.apply {
|
|
73
|
+
putExtra("exit_on_sent", true)
|
|
74
|
+
putExtra("compose_mode", true)
|
|
75
|
+
putExtra("sms_body", message)
|
|
94
76
|
}
|
|
95
|
-
smsIntent.putExtra("exit_on_sent", true)
|
|
96
|
-
smsIntent.putExtra("compose_mode", true)
|
|
97
|
-
smsIntent.putExtra("sms_body", message)
|
|
98
|
-
mPendingPromise = promise
|
|
99
|
-
val activityProvider = mModuleRegistry.getModule(
|
|
100
|
-
ActivityProvider::class.java
|
|
101
|
-
)
|
|
102
|
-
activityProvider.currentActivity.startActivity(smsIntent)
|
|
103
|
-
mSMSComposerOpened = true
|
|
104
|
-
}
|
|
105
77
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
78
|
+
pendingPromise = promise
|
|
79
|
+
currentActivity.startActivity(smsIntent)
|
|
80
|
+
smsComposerOpened = true
|
|
109
81
|
}
|
|
110
82
|
|
|
111
83
|
override fun onHostResume() {
|
|
112
|
-
val promise =
|
|
113
|
-
if (
|
|
84
|
+
val promise = pendingPromise
|
|
85
|
+
if (smsComposerOpened && promise != null) {
|
|
114
86
|
// the only way to check the status of the message is to query the device's SMS database
|
|
115
87
|
// but this requires READ_SMS permission, which Google is heavily restricting beginning Jan 2019
|
|
116
88
|
// so we just resolve with an unknown value
|
|
117
89
|
promise.resolve(
|
|
118
|
-
|
|
119
|
-
putString("result", "unknown")
|
|
120
|
-
}
|
|
90
|
+
bundleOf(Pair("result", "unknown"))
|
|
121
91
|
)
|
|
122
|
-
|
|
92
|
+
pendingPromise = null
|
|
123
93
|
}
|
|
124
|
-
|
|
94
|
+
smsComposerOpened = false
|
|
125
95
|
}
|
|
126
96
|
|
|
127
97
|
override fun onHostPause() = Unit
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
package expo.modules.sms
|
|
2
|
+
|
|
3
|
+
import expo.modules.kotlin.records.Field
|
|
4
|
+
import expo.modules.kotlin.records.Record
|
|
5
|
+
|
|
6
|
+
data class SMSOptions(
|
|
7
|
+
@Field val attachments: List<SMSAttachment> = emptyList()
|
|
8
|
+
) : Record
|
|
9
|
+
|
|
10
|
+
data class SMSAttachment(
|
|
11
|
+
@Field val uri: String,
|
|
12
|
+
@Field val mimeType: String,
|
|
13
|
+
@Field val filename: String,
|
|
14
|
+
) : Record
|
package/build/ExpoSMS.d.ts
CHANGED
package/build/ExpoSMS.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoSMS.d.ts","sourceRoot":"","sources":["../src/ExpoSMS.ts"],"names":[],"mappings":";AACA,
|
|
1
|
+
{"version":3,"file":"ExpoSMS.d.ts","sourceRoot":"","sources":["../src/ExpoSMS.ts"],"names":[],"mappings":";AACA,wBAA8C"}
|
package/build/ExpoSMS.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export default
|
|
1
|
+
import { requireNativeModule } from 'expo-modules-core';
|
|
2
|
+
export default requireNativeModule('ExpoSMS');
|
|
3
3
|
//# sourceMappingURL=ExpoSMS.js.map
|
package/build/ExpoSMS.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoSMS.js","sourceRoot":"","sources":["../src/ExpoSMS.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"ExpoSMS.js","sourceRoot":"","sources":["../src/ExpoSMS.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,eAAe,mBAAmB,CAAC,SAAS,CAAC,CAAC","sourcesContent":["import { requireNativeModule } from 'expo-modules-core';\nexport default requireNativeModule('ExpoSMS');\n"]}
|
package/build/SMS.d.ts
CHANGED
|
@@ -14,7 +14,7 @@ export { SMSAttachment, SMSResponse, SMSOptions };
|
|
|
14
14
|
* - If the status of the SMS message cannot be determined: `{ result: 'unknown' }`.
|
|
15
15
|
*
|
|
16
16
|
* Android does not provide information about the status of the SMS message, so on Android devices
|
|
17
|
-
* the Promise will always resolve with { result: 'unknown' }
|
|
17
|
+
* the Promise will always resolve with `{ result: 'unknown' }`.
|
|
18
18
|
*
|
|
19
19
|
* > Note: The only feedback collected by this module is whether any message has been sent. That
|
|
20
20
|
* means we do not check actual content of message nor recipients list.
|
package/build/SMS.js
CHANGED
|
@@ -29,7 +29,7 @@ function processAttachments(attachments) {
|
|
|
29
29
|
* - If the status of the SMS message cannot be determined: `{ result: 'unknown' }`.
|
|
30
30
|
*
|
|
31
31
|
* Android does not provide information about the status of the SMS message, so on Android devices
|
|
32
|
-
* the Promise will always resolve with { result: 'unknown' }
|
|
32
|
+
* the Promise will always resolve with `{ result: 'unknown' }`.
|
|
33
33
|
*
|
|
34
34
|
* > Note: The only feedback collected by this module is whether any message has been sent. That
|
|
35
35
|
* means we do not check actual content of message nor recipients list.
|
package/build/SMS.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SMS.js","sourceRoot":"","sources":["../src/SMS.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAElE,OAAO,OAAO,MAAM,WAAW,CAAC;AAKhC,SAAS,kBAAkB,CACzB,WAAwD;IAExD,IAAI,CAAC,WAAW,EAAE;QAChB,OAAO,IAAI,CAAC;KACb;IACD,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IACvE,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE;QACvD,IAAI,OAAO,EAAE;YACX,OAAO,CAAC,IAAI,CAAC,0EAA0E,CAAC,CAAC;SAC1F;QACD,WAAW,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;KACvC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,cAAc;AACd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,SAA4B,EAC5B,OAAe,EACf,OAAoB;IAEpB,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE;QACzB,MAAM,IAAI,mBAAmB,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;KAC3D;IACD,MAAM,cAAc,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAC1E,cAAc,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QACjC,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS,EAAE;YAC7C,MAAM,IAAI,SAAS,CAAC,2BAA2B,CAAC,CAAC;SAClD;IACH,CAAC,CAAC,CAAC;IACH,MAAM,YAAY,GAAG;QACnB,GAAG,OAAO;KACG,CAAC;IAChB,IAAI,OAAO,EAAE,WAAW,EAAE;QACxB,YAAY,CAAC,WAAW,GAAG,kBAAkB,CAAC,OAAO,EAAE,WAAW,CAAC,IAAI,SAAS,CAAC;KAClF;IACD,OAAO,OAAO,CAAC,YAAY,CAAC,cAAc,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;AACrE,CAAC;AAED,cAAc;AACd;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,OAAO,OAAO,CAAC,gBAAgB,EAAE,CAAC;AACpC,CAAC","sourcesContent":["/* eslint-disable no-unused-expressions */\nimport { UnavailabilityError, Platform } from 'expo-modules-core';\n\nimport ExpoSMS from './ExpoSMS';\nimport { SMSAttachment, SMSResponse, SMSOptions } from './SMS.types';\n\nexport { SMSAttachment, SMSResponse, SMSOptions };\n\nfunction processAttachments(\n attachments: SMSAttachment | SMSAttachment[] | undefined\n): SMSAttachment[] | null {\n if (!attachments) {\n return null;\n }\n attachments = Array.isArray(attachments) ? attachments : [attachments];\n if (Platform.OS === 'android' && attachments.length > 1) {\n if (__DEV__) {\n console.warn('Android only supports a single attachment. The first array item is used.');\n }\n attachments = attachments.slice(0, 1);\n }\n return attachments;\n}\n\n// @needsAudit\n/**\n * Opens the default UI/app for sending SMS messages with prefilled addresses and message.\n *\n * @param addresses An array of addresses (phone numbers) or single address passed as strings. Those\n * would appear as recipients of the prepared message.\n * @param message Message to be sent.\n * @param options A `SMSOptions` object defining additional SMS configuration options.\n *\n * @return Returns a Promise that fulfils with the SMS action is invoked by the user, with corresponding result:\n * - If the user cancelled the SMS sending process: `{ result: 'cancelled' }`.\n * - If the user has sent/scheduled message for sending: `{ result: 'sent' }`.\n * - If the status of the SMS message cannot be determined: `{ result: 'unknown' }`.\n *\n * Android does not provide information about the status of the SMS message, so on Android devices\n * the Promise will always resolve with { result: 'unknown' }
|
|
1
|
+
{"version":3,"file":"SMS.js","sourceRoot":"","sources":["../src/SMS.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAElE,OAAO,OAAO,MAAM,WAAW,CAAC;AAKhC,SAAS,kBAAkB,CACzB,WAAwD;IAExD,IAAI,CAAC,WAAW,EAAE;QAChB,OAAO,IAAI,CAAC;KACb;IACD,WAAW,GAAG,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IACvE,IAAI,QAAQ,CAAC,EAAE,KAAK,SAAS,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE;QACvD,IAAI,OAAO,EAAE;YACX,OAAO,CAAC,IAAI,CAAC,0EAA0E,CAAC,CAAC;SAC1F;QACD,WAAW,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;KACvC;IACD,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,cAAc;AACd;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,SAA4B,EAC5B,OAAe,EACf,OAAoB;IAEpB,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE;QACzB,MAAM,IAAI,mBAAmB,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;KAC3D;IACD,MAAM,cAAc,GAAG,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAC1E,cAAc,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QACjC,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS,EAAE;YAC7C,MAAM,IAAI,SAAS,CAAC,2BAA2B,CAAC,CAAC;SAClD;IACH,CAAC,CAAC,CAAC;IACH,MAAM,YAAY,GAAG;QACnB,GAAG,OAAO;KACG,CAAC;IAChB,IAAI,OAAO,EAAE,WAAW,EAAE;QACxB,YAAY,CAAC,WAAW,GAAG,kBAAkB,CAAC,OAAO,EAAE,WAAW,CAAC,IAAI,SAAS,CAAC;KAClF;IACD,OAAO,OAAO,CAAC,YAAY,CAAC,cAAc,EAAE,OAAO,EAAE,YAAY,CAAC,CAAC;AACrE,CAAC;AAED,cAAc;AACd;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,OAAO,OAAO,CAAC,gBAAgB,EAAE,CAAC;AACpC,CAAC","sourcesContent":["/* eslint-disable no-unused-expressions */\nimport { UnavailabilityError, Platform } from 'expo-modules-core';\n\nimport ExpoSMS from './ExpoSMS';\nimport { SMSAttachment, SMSResponse, SMSOptions } from './SMS.types';\n\nexport { SMSAttachment, SMSResponse, SMSOptions };\n\nfunction processAttachments(\n attachments: SMSAttachment | SMSAttachment[] | undefined\n): SMSAttachment[] | null {\n if (!attachments) {\n return null;\n }\n attachments = Array.isArray(attachments) ? attachments : [attachments];\n if (Platform.OS === 'android' && attachments.length > 1) {\n if (__DEV__) {\n console.warn('Android only supports a single attachment. The first array item is used.');\n }\n attachments = attachments.slice(0, 1);\n }\n return attachments;\n}\n\n// @needsAudit\n/**\n * Opens the default UI/app for sending SMS messages with prefilled addresses and message.\n *\n * @param addresses An array of addresses (phone numbers) or single address passed as strings. Those\n * would appear as recipients of the prepared message.\n * @param message Message to be sent.\n * @param options A `SMSOptions` object defining additional SMS configuration options.\n *\n * @return Returns a Promise that fulfils with the SMS action is invoked by the user, with corresponding result:\n * - If the user cancelled the SMS sending process: `{ result: 'cancelled' }`.\n * - If the user has sent/scheduled message for sending: `{ result: 'sent' }`.\n * - If the status of the SMS message cannot be determined: `{ result: 'unknown' }`.\n *\n * Android does not provide information about the status of the SMS message, so on Android devices\n * the Promise will always resolve with `{ result: 'unknown' }`.\n *\n * > Note: The only feedback collected by this module is whether any message has been sent. That\n * means we do not check actual content of message nor recipients list.\n *\n * @example\n * ```ts\n * const { result } = await SMS.sendSMSAsync(\n * ['0123456789', '9876543210'],\n * 'My sample HelloWorld message',\n * {\n * attachments: {\n * uri: 'path/myfile.png',\n * mimeType: 'image/png',\n * filename: 'myfile.png',\n * },\n * }\n * );\n * ```\n */\nexport async function sendSMSAsync(\n addresses: string | string[],\n message: string,\n options?: SMSOptions\n): Promise<SMSResponse> {\n if (!ExpoSMS.sendSMSAsync) {\n throw new UnavailabilityError('expo-sms', 'sendSMSAsync');\n }\n const finalAddresses = Array.isArray(addresses) ? addresses : [addresses];\n finalAddresses.forEach((address) => {\n if (address === null || address === undefined) {\n throw new TypeError('undefined or null address');\n }\n });\n const finalOptions = {\n ...options,\n } as SMSOptions;\n if (options?.attachments) {\n finalOptions.attachments = processAttachments(options?.attachments) || undefined;\n }\n return ExpoSMS.sendSMSAsync(finalAddresses, message, finalOptions);\n}\n\n// @needsAudit\n/**\n * Determines whether SMS is available. Always returns `false` in the iOS simulator, and in browser.\n *\n * @return Returns a promise that fulfils with a `boolean`, indicating whether SMS is available on this device.\n *\n * @example\n * ```ts\n * const isAvailable = await SMS.isAvailableAsync();\n * if (isAvailable) {\n * // do your SMS stuff here\n * } else {\n * // misfortune... there's no SMS available on this device\n * }\n * ```\n */\nexport async function isAvailableAsync(): Promise<boolean> {\n return ExpoSMS.isAvailableAsync();\n}\n"]}
|
package/build/SMS.types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export
|
|
1
|
+
export type SMSResponse = {
|
|
2
2
|
/**
|
|
3
3
|
* Status of SMS action invoked by the user.
|
|
4
4
|
*/
|
|
@@ -7,7 +7,7 @@ export declare type SMSResponse = {
|
|
|
7
7
|
/**
|
|
8
8
|
* An object that is used to describe an attachment that is included with a SMS message.
|
|
9
9
|
*/
|
|
10
|
-
export
|
|
10
|
+
export type SMSAttachment = {
|
|
11
11
|
/**
|
|
12
12
|
* The content URI of the attachment. The URI needs be a content URI so that it can be accessed by
|
|
13
13
|
* other applications outside of Expo. See [FileSystem.getContentUriAsync](./filesystem/#filesystemgetcontenturiasyncfileuri)).
|
|
@@ -22,7 +22,7 @@ export declare type SMSAttachment = {
|
|
|
22
22
|
*/
|
|
23
23
|
filename: string;
|
|
24
24
|
};
|
|
25
|
-
export
|
|
25
|
+
export type SMSOptions = {
|
|
26
26
|
attachments?: SMSAttachment | SMSAttachment[] | undefined;
|
|
27
27
|
};
|
|
28
28
|
//# sourceMappingURL=SMS.types.d.ts.map
|
package/build/SMS.types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SMS.types.d.ts","sourceRoot":"","sources":["../src/SMS.types.ts"],"names":[],"mappings":"AACA,
|
|
1
|
+
{"version":3,"file":"SMS.types.d.ts","sourceRoot":"","sources":["../src/SMS.types.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,WAAW,GAAG;IACxB;;OAEG;IACH,MAAM,EAAE,SAAS,GAAG,MAAM,GAAG,WAAW,CAAC;CAC1C,CAAC;AAGF;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B;;;OAGG;IACH,GAAG,EAAE,MAAM,CAAC;IACZ;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAGF,MAAM,MAAM,UAAU,GAAG;IACvB,WAAW,CAAC,EAAE,aAAa,GAAG,aAAa,EAAE,GAAG,SAAS,CAAC;CAC3D,CAAC"}
|
|
@@ -3,7 +3,7 @@ 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 = 'ExpoSMS'
|
|
7
7
|
s.version = package['version']
|
|
8
8
|
s.summary = package['description']
|
|
9
9
|
s.description = package['description']
|
|
@@ -11,15 +11,16 @@ Pod::Spec.new do |s|
|
|
|
11
11
|
s.author = package['author']
|
|
12
12
|
s.homepage = package['homepage']
|
|
13
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
|
|
|
19
20
|
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 = "
|
|
21
|
+
s.source_files = "**/*.h"
|
|
21
22
|
s.vendored_frameworks = "#{s.name}.xcframework"
|
|
22
23
|
else
|
|
23
|
-
s.source_files = "
|
|
24
|
+
s.source_files = "**/*.{h,m,swift}"
|
|
24
25
|
end
|
|
25
26
|
end
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import ExpoModulesCore
|
|
2
|
+
import MessageUI
|
|
3
|
+
import CoreServices
|
|
4
|
+
import MobileCoreServices
|
|
5
|
+
import UniformTypeIdentifiers
|
|
6
|
+
|
|
7
|
+
struct ExpoSMSContext {
|
|
8
|
+
let promise: Promise
|
|
9
|
+
let smsDelegate: SMSDelegate
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
public class ExpoSMSModule: Module, SMSResultHandler {
|
|
13
|
+
private var smsContext: ExpoSMSContext?
|
|
14
|
+
private lazy var utils = appContext?.utilities
|
|
15
|
+
|
|
16
|
+
public func definition() -> ModuleDefinition {
|
|
17
|
+
Name("ExpoSMS")
|
|
18
|
+
|
|
19
|
+
AsyncFunction("isAvailableAsync") {
|
|
20
|
+
return MFMessageComposeViewController.canSendText()
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
AsyncFunction("sendSMSAsync") { (addresses: [String], message: String, options: SMSOptions, promise: Promise) in
|
|
24
|
+
try sendSMSAsync(addresses: addresses, message: message, options: options, promise: promise)
|
|
25
|
+
}.runOnQueue(.main)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
private func sendSMSAsync(addresses: [String], message: String, options: SMSOptions, promise: Promise) throws {
|
|
29
|
+
if !MFMessageComposeViewController.canSendText() {
|
|
30
|
+
throw SMSUnavailableException()
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if smsContext != nil {
|
|
34
|
+
throw SMSPendingException()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let smsDelegate = SMSDelegate(handler: self)
|
|
38
|
+
let context = ExpoSMSContext(promise: promise, smsDelegate: smsDelegate)
|
|
39
|
+
|
|
40
|
+
let messageComposeViewController = MFMessageComposeViewController()
|
|
41
|
+
messageComposeViewController.messageComposeDelegate = context.smsDelegate
|
|
42
|
+
messageComposeViewController.recipients = addresses
|
|
43
|
+
messageComposeViewController.body = message
|
|
44
|
+
|
|
45
|
+
for attachment in options.attachments {
|
|
46
|
+
let utiRef = UTTypeCreatePreferredIdentifierForTag(
|
|
47
|
+
kUTTagClassMIMEType, attachment.mimeType as CFString, nil)
|
|
48
|
+
|
|
49
|
+
if utiRef == nil {
|
|
50
|
+
throw SMSMimeTypeException(attachment.mimeType)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
guard let url = URL(string: attachment.uri) else {
|
|
54
|
+
throw SMSUriException(attachment.uri)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
do {
|
|
58
|
+
let data = try Data(contentsOf: url, options: .mappedIfSafe)
|
|
59
|
+
let attached = messageComposeViewController.addAttachmentData(
|
|
60
|
+
data,
|
|
61
|
+
typeIdentifier: attachment.mimeType,
|
|
62
|
+
filename: attachment.filename)
|
|
63
|
+
if !attached {
|
|
64
|
+
throw SMSFileException(attachment.uri)
|
|
65
|
+
}
|
|
66
|
+
} catch {
|
|
67
|
+
context.promise.reject(error)
|
|
68
|
+
return
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
smsContext = context
|
|
73
|
+
utils?.currentViewController()?.present(messageComposeViewController, animated: true, completion: nil)
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
func onSuccess(_ data: [String: String]) {
|
|
77
|
+
guard let promise = smsContext?.promise else {
|
|
78
|
+
log.error("SMS context has been lost")
|
|
79
|
+
return
|
|
80
|
+
}
|
|
81
|
+
smsContext = nil
|
|
82
|
+
promise.resolve(data)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
func onFailure(_ error: String) {
|
|
86
|
+
guard let promise = smsContext?.promise else {
|
|
87
|
+
log.error("SMS context has been lost")
|
|
88
|
+
return
|
|
89
|
+
}
|
|
90
|
+
smsContext = nil
|
|
91
|
+
promise.reject(SMSSendingException(error))
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import MessageUI
|
|
2
|
+
|
|
3
|
+
protocol SMSResultHandler {
|
|
4
|
+
func onSuccess(_ data: [String: String])
|
|
5
|
+
func onFailure(_ error: String)
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
class SMSDelegate: NSObject, MFMessageComposeViewControllerDelegate {
|
|
9
|
+
private let handler: SMSResultHandler
|
|
10
|
+
|
|
11
|
+
init(handler: SMSResultHandler) {
|
|
12
|
+
self.handler = handler
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
func messageComposeViewController(
|
|
16
|
+
_ controller: MFMessageComposeViewController,
|
|
17
|
+
didFinishWith result: MessageComposeResult
|
|
18
|
+
) {
|
|
19
|
+
controller.dismiss(animated: true) {
|
|
20
|
+
switch result {
|
|
21
|
+
case .sent, .cancelled:
|
|
22
|
+
self.handler.onSuccess([
|
|
23
|
+
"result": result == .sent ? "sent" : "cancelled"
|
|
24
|
+
])
|
|
25
|
+
case .failed:
|
|
26
|
+
self.handler.onFailure(
|
|
27
|
+
"""
|
|
28
|
+
User's attempt to save or send an SMS was unsuccessful.
|
|
29
|
+
This can occur when the device loses connection to WiFi or Cellular
|
|
30
|
+
"""
|
|
31
|
+
)
|
|
32
|
+
default:
|
|
33
|
+
self.handler.onFailure("SMS message sending failed with unknown error")
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import ExpoModulesCore
|
|
2
|
+
|
|
3
|
+
internal class SMSUnavailableException: Exception {
|
|
4
|
+
override var reason: String {
|
|
5
|
+
"SMS service is not available"
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
internal class SMSPendingException: Exception {
|
|
10
|
+
override var reason: String {
|
|
11
|
+
"SMS sending in progress, await the old request and then try again"
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
internal class SMSSendingException: GenericException<String> {
|
|
16
|
+
override var reason: String {
|
|
17
|
+
param
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
internal class SMSFileException: GenericException<String> {
|
|
22
|
+
override var reason: String {
|
|
23
|
+
"Failed to attach file: \(param)"
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
internal class SMSMimeTypeException: GenericException<String> {
|
|
28
|
+
override var reason: String {
|
|
29
|
+
"Failed to find UTI for mimeType: \(param)"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
internal class SMSUriException: GenericException<String> {
|
|
34
|
+
override var reason: String {
|
|
35
|
+
"Invalid file uri: \(param)"
|
|
36
|
+
}
|
|
37
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-sms",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.2.0",
|
|
4
4
|
"description": "Provides access to the system's UI/app for sending SMS messages.",
|
|
5
5
|
"main": "build/SMS.js",
|
|
6
6
|
"types": "build/SMS.d.ts",
|
|
@@ -40,5 +40,5 @@
|
|
|
40
40
|
"peerDependencies": {
|
|
41
41
|
"expo": "*"
|
|
42
42
|
},
|
|
43
|
-
"gitHead": "
|
|
43
|
+
"gitHead": "1815e2eaad8c753588c7b1eb74420174a28e01f4"
|
|
44
44
|
}
|
package/src/ExpoSMS.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export default
|
|
1
|
+
import { requireNativeModule } from 'expo-modules-core';
|
|
2
|
+
export default requireNativeModule('ExpoSMS');
|
package/src/SMS.ts
CHANGED
|
@@ -37,7 +37,7 @@ function processAttachments(
|
|
|
37
37
|
* - If the status of the SMS message cannot be determined: `{ result: 'unknown' }`.
|
|
38
38
|
*
|
|
39
39
|
* Android does not provide information about the status of the SMS message, so on Android devices
|
|
40
|
-
* the Promise will always resolve with { result: 'unknown' }
|
|
40
|
+
* the Promise will always resolve with `{ result: 'unknown' }`.
|
|
41
41
|
*
|
|
42
42
|
* > Note: The only feedback collected by this module is whether any message has been sent. That
|
|
43
43
|
* means we do not check actual content of message nor recipients list.
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
package expo.modules.sms
|
|
2
|
-
|
|
3
|
-
import android.content.Context
|
|
4
|
-
import expo.modules.core.BasePackage
|
|
5
|
-
import expo.modules.core.ExportedModule
|
|
6
|
-
|
|
7
|
-
class SMSPackage : BasePackage() {
|
|
8
|
-
override fun createExportedModules(reactContext: Context): List<ExportedModule> {
|
|
9
|
-
return listOf(SMSModule(reactContext))
|
|
10
|
-
}
|
|
11
|
-
}
|
package/ios/EXSMS/EXSMSModule.h
DELETED
package/ios/EXSMS/EXSMSModule.m
DELETED
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
// Copyright © 2018 650 Industries. All rights reserved.
|
|
2
|
-
|
|
3
|
-
#import <MessageUI/MessageUI.h>
|
|
4
|
-
#import <EXSMS/EXSMSModule.h>
|
|
5
|
-
#import <ExpoModulesCore/EXUtilities.h>
|
|
6
|
-
#if SD_MAC
|
|
7
|
-
#import <CoreServices/CoreServices.h>
|
|
8
|
-
#else
|
|
9
|
-
#import <MobileCoreServices/MobileCoreServices.h>
|
|
10
|
-
#endif
|
|
11
|
-
|
|
12
|
-
@interface EXSMSModule () <MFMessageComposeViewControllerDelegate>
|
|
13
|
-
|
|
14
|
-
@property (nonatomic, weak) id<EXUtilitiesInterface> utils;
|
|
15
|
-
@property (nonatomic, strong) EXPromiseResolveBlock resolve;
|
|
16
|
-
@property (nonatomic, strong) EXPromiseRejectBlock reject;
|
|
17
|
-
|
|
18
|
-
@end
|
|
19
|
-
|
|
20
|
-
@implementation EXSMSModule
|
|
21
|
-
|
|
22
|
-
EX_EXPORT_MODULE(ExpoSMS);
|
|
23
|
-
|
|
24
|
-
- (dispatch_queue_t)methodQueue
|
|
25
|
-
{
|
|
26
|
-
// Everything in this module uses `MFMessageComposeViewController` which is a subclass of UIViewController,
|
|
27
|
-
// so everything should be called from main thread.
|
|
28
|
-
return dispatch_get_main_queue();
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
- (void)setModuleRegistry:(EXModuleRegistry *)moduleRegistry
|
|
32
|
-
{
|
|
33
|
-
_utils = [moduleRegistry getModuleImplementingProtocol:@protocol(EXUtilitiesInterface)];
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
EX_EXPORT_METHOD_AS(isAvailableAsync,
|
|
37
|
-
isAvailable:(EXPromiseResolveBlock)resolve
|
|
38
|
-
rejecter:(EXPromiseRejectBlock)reject)
|
|
39
|
-
{
|
|
40
|
-
resolve(@([MFMessageComposeViewController canSendText]));
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
EX_EXPORT_METHOD_AS(sendSMSAsync,
|
|
44
|
-
sendSMS:(NSArray<NSString *> *)addresses
|
|
45
|
-
message:(NSString *)message
|
|
46
|
-
options:(NSDictionary *)options
|
|
47
|
-
resolver:(EXPromiseResolveBlock)resolve
|
|
48
|
-
rejecter:(EXPromiseRejectBlock)reject)
|
|
49
|
-
{
|
|
50
|
-
if (![MFMessageComposeViewController canSendText]) {
|
|
51
|
-
reject(@"E_SMS_UNAVAILABLE", @"SMS service not available", nil);
|
|
52
|
-
return;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (_resolve != nil || _reject != nil) {
|
|
56
|
-
reject(@"E_SMS_SENDING_IN_PROGRESS", @"Different SMS sending in progress. Await the old request and then try again.", nil);
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
_resolve = resolve;
|
|
61
|
-
_reject = reject;
|
|
62
|
-
|
|
63
|
-
MFMessageComposeViewController *messageComposeViewController = [[MFMessageComposeViewController alloc] init];
|
|
64
|
-
messageComposeViewController.messageComposeDelegate = self;
|
|
65
|
-
messageComposeViewController.recipients = addresses;
|
|
66
|
-
messageComposeViewController.body = message;
|
|
67
|
-
|
|
68
|
-
if (options) {
|
|
69
|
-
if (options[@"attachments"]) {
|
|
70
|
-
NSArray *attachments = (NSArray *) [options objectForKey:@"attachments"];
|
|
71
|
-
for (NSDictionary* attachment in attachments) {
|
|
72
|
-
NSString *mimeType = attachment[@"mimeType"];
|
|
73
|
-
CFStringRef mimeTypeRef = (__bridge CFStringRef)mimeType;
|
|
74
|
-
CFStringRef utiRef = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, mimeTypeRef, NULL);
|
|
75
|
-
if (utiRef == NULL) {
|
|
76
|
-
reject(@"E_SMS_ATTACHMENT", [NSString stringWithFormat:@"Failed to find UTI for mimeType: %@", mimeType], nil);
|
|
77
|
-
_resolve = nil;
|
|
78
|
-
_reject = nil;
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
NSString *typeIdentifier = (__bridge_transfer NSString *)utiRef;
|
|
82
|
-
NSString *uri = attachment[@"uri"];
|
|
83
|
-
NSString *filename = attachment[@"filename"];
|
|
84
|
-
NSError *error;
|
|
85
|
-
NSData *attachmentData = [NSData dataWithContentsOfURL:[NSURL URLWithString:uri] options:(NSDataReadingOptions)0 error:&error];
|
|
86
|
-
bool attached = [messageComposeViewController addAttachmentData:attachmentData typeIdentifier:typeIdentifier filename:filename];
|
|
87
|
-
if (!attached) {
|
|
88
|
-
reject(@"E_SMS_ATTACHMENT", [NSString stringWithFormat:@"Failed to attach file: %@", uri], nil);
|
|
89
|
-
_resolve = nil;
|
|
90
|
-
_reject = nil;
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
[self.utils.currentViewController presentViewController:messageComposeViewController animated:YES completion:nil];
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller
|
|
101
|
-
didFinishWithResult:(MessageComposeResult)result
|
|
102
|
-
{
|
|
103
|
-
NSDictionary *resolveData;
|
|
104
|
-
NSString *rejectMessage;
|
|
105
|
-
switch (result) {
|
|
106
|
-
case MessageComposeResultCancelled:
|
|
107
|
-
resolveData = @{@"result": @"cancelled"};
|
|
108
|
-
break;
|
|
109
|
-
case MessageComposeResultSent:
|
|
110
|
-
resolveData = @{@"result": @"sent"};
|
|
111
|
-
break;
|
|
112
|
-
case MessageComposeResultFailed:
|
|
113
|
-
rejectMessage = @"User's attempt to save or send an SMS was unsuccessful. This can occur when the device loses connection to Wifi or Cellular.";
|
|
114
|
-
break;
|
|
115
|
-
default:
|
|
116
|
-
rejectMessage = @"SMS message sending failed with unknown error";
|
|
117
|
-
break;
|
|
118
|
-
}
|
|
119
|
-
EX_WEAKIFY(self);
|
|
120
|
-
[controller dismissViewControllerAnimated:YES completion:^{
|
|
121
|
-
EX_ENSURE_STRONGIFY(self);
|
|
122
|
-
if (rejectMessage) {
|
|
123
|
-
self->_reject(@"E_SMS_SENDING_FAILED", rejectMessage, nil);
|
|
124
|
-
} else {
|
|
125
|
-
self->_resolve(resolveData);
|
|
126
|
-
}
|
|
127
|
-
self->_reject = nil;
|
|
128
|
-
self->_resolve = nil;
|
|
129
|
-
}];
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
@end
|
package/unimodule.json
DELETED