expo-sharing 11.0.0 → 11.1.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 +2 -2
- package/android/src/main/java/expo/modules/sharing/SharingExceptions.kt +15 -0
- package/android/src/main/java/expo/modules/sharing/SharingModule.kt +52 -74
- package/android/src/main/java/expo/modules/sharing/SharingOptions.kt +10 -0
- package/build/ExpoSharing.d.ts +1 -1
- package/build/ExpoSharing.d.ts.map +1 -1
- package/build/ExpoSharing.js +2 -2
- package/build/ExpoSharing.js.map +1 -1
- package/build/ExpoSharing.web.d.ts +1 -1
- package/build/ExpoSharing.web.d.ts.map +1 -1
- package/build/Sharing.d.ts +1 -1
- package/build/Sharing.d.ts.map +1 -1
- package/expo-module.config.json +7 -0
- package/ios/EXSharing/EXSharingModule.m +14 -3
- package/package.json +2 -2
- package/src/ExpoSharing.ts +2 -3
- package/android/src/main/java/expo/modules/sharing/SharingPackage.kt +0 -9
- package/unimodule.json +0 -4
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,18 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
+
## 11.1.0 — 2022-12-30
|
|
14
|
+
|
|
15
|
+
### 🎉 New features
|
|
16
|
+
|
|
17
|
+
- Migrated Android implementation to Expo Modules API. ([#20112](https://github.com/expo/expo/pull/20112) by [@alanhughes](https://github.com/alanjhughes))
|
|
18
|
+
|
|
19
|
+
## 11.0.1 — 2022-10-27
|
|
20
|
+
|
|
21
|
+
### 🐛 Bug fixes
|
|
22
|
+
|
|
23
|
+
- On iOS, dismiss share sheet after sharing to an app is canceled, so the file doesn't fail to attach when trying to share again ([#19656](https://github.com/expo/expo/pull/19656) by [@keith-kurak](https://github.com/keith-kurak))
|
|
24
|
+
|
|
13
25
|
## 11.0.0 — 2022-10-25
|
|
14
26
|
|
|
15
27
|
### 🛠 Breaking changes
|
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@ Sharing standalone module
|
|
|
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/sharing.
|
|
7
|
+
- [Documentation for the main branch](https://github.com/expo/expo/blob/main/docs/pages/versions/unversioned/sdk/sharing.mdx)
|
|
8
8
|
- [Documentation for the latest stable release](https://docs.expo.dev/versions/latest/sdk/sharing/)
|
|
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.1.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 16
|
|
77
|
-
versionName '11.
|
|
77
|
+
versionName '11.1.0'
|
|
78
78
|
}
|
|
79
79
|
lintOptions {
|
|
80
80
|
abortOnError false
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
package expo.modules.sharing
|
|
2
|
+
|
|
3
|
+
import expo.modules.kotlin.exception.CodedException
|
|
4
|
+
|
|
5
|
+
internal class MissingCurrentActivityException :
|
|
6
|
+
CodedException("Activity which was provided during module initialization is no longer available")
|
|
7
|
+
|
|
8
|
+
internal class SharingInProgressException :
|
|
9
|
+
CodedException("Another share request is being processed now.")
|
|
10
|
+
|
|
11
|
+
internal class SharingFailedException(message: String, e: Exception) :
|
|
12
|
+
CodedException(message, e.cause)
|
|
13
|
+
|
|
14
|
+
internal class SharingInvalidArgsException(message: String?, e: Exception) :
|
|
15
|
+
CodedException(message, e.cause)
|
|
@@ -1,81 +1,69 @@
|
|
|
1
1
|
package expo.modules.sharing
|
|
2
2
|
|
|
3
|
-
import android.app.Activity
|
|
4
3
|
import android.content.Context
|
|
5
4
|
import android.content.Intent
|
|
6
5
|
import android.content.pm.PackageManager
|
|
7
6
|
import android.net.Uri
|
|
8
7
|
import androidx.core.content.FileProvider
|
|
9
|
-
import expo.modules.core.ExportedModule
|
|
10
|
-
import expo.modules.core.ModuleRegistry
|
|
11
|
-
import expo.modules.core.ModuleRegistryDelegate
|
|
12
|
-
import expo.modules.core.Promise
|
|
13
|
-
import expo.modules.core.arguments.ReadableArguments
|
|
14
8
|
import expo.modules.core.errors.InvalidArgumentException
|
|
15
|
-
import expo.modules.core.interfaces.ActivityEventListener
|
|
16
|
-
import expo.modules.core.interfaces.ActivityProvider
|
|
17
|
-
import expo.modules.core.interfaces.ExpoMethod
|
|
18
|
-
import expo.modules.core.interfaces.services.UIManager
|
|
19
|
-
import expo.modules.interfaces.filesystem.FilePermissionModuleInterface
|
|
20
9
|
import expo.modules.interfaces.filesystem.Permission
|
|
10
|
+
import expo.modules.kotlin.Promise
|
|
11
|
+
import expo.modules.kotlin.exception.Exceptions
|
|
12
|
+
import expo.modules.kotlin.modules.Module
|
|
13
|
+
import expo.modules.kotlin.modules.ModuleDefinition
|
|
21
14
|
import java.io.File
|
|
22
15
|
import java.net.URLConnection
|
|
23
16
|
|
|
24
|
-
class SharingModule(
|
|
25
|
-
context: Context
|
|
26
|
-
|
|
27
|
-
|
|
17
|
+
class SharingModule : Module() {
|
|
18
|
+
private val context: Context
|
|
19
|
+
get() = appContext.reactContext ?: throw Exceptions.ReactContextLost()
|
|
20
|
+
private val currentActivity
|
|
21
|
+
get() = appContext.currentActivity ?: throw MissingCurrentActivityException()
|
|
28
22
|
private var pendingPromise: Promise? = null
|
|
29
|
-
private val uiManager: UIManager by moduleRegistry()
|
|
30
|
-
override fun getName() = "ExpoSharing"
|
|
31
23
|
|
|
32
|
-
|
|
33
|
-
|
|
24
|
+
override fun definition() = ModuleDefinition {
|
|
25
|
+
Name("ExpoSharing")
|
|
34
26
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
27
|
+
AsyncFunction("shareAsync") { url: String?, params: SharingOptions, promise: Promise ->
|
|
28
|
+
if (pendingPromise != null) {
|
|
29
|
+
throw SharingInProgressException()
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
val fileToShare = getLocalFileFoUrl(url)
|
|
33
|
+
val contentUri = FileProvider.getUriForFile(
|
|
34
|
+
context,
|
|
35
|
+
context.applicationInfo.packageName + ".SharingFileProvider",
|
|
36
|
+
fileToShare
|
|
37
|
+
)
|
|
38
|
+
val mimeType = params.mimeType
|
|
39
|
+
?: URLConnection.guessContentTypeFromName(fileToShare.name)
|
|
40
|
+
?: "*/*"
|
|
41
|
+
val intent = Intent.createChooser(
|
|
42
|
+
createSharingIntent(contentUri, mimeType),
|
|
43
|
+
params.dialogTitle
|
|
44
|
+
)
|
|
45
|
+
val resInfoList = context.packageManager.queryIntentActivities(
|
|
46
|
+
intent,
|
|
47
|
+
PackageManager.MATCH_DEFAULT_ONLY
|
|
48
|
+
)
|
|
49
|
+
resInfoList.forEach {
|
|
50
|
+
val packageName = it.activityInfo.packageName
|
|
51
|
+
context.grantUriPermission(packageName, contentUri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
|
52
|
+
}
|
|
53
|
+
pendingPromise = promise
|
|
54
|
+
currentActivity.startActivity(intent)
|
|
55
|
+
} catch (e: InvalidArgumentException) {
|
|
56
|
+
throw SharingInvalidArgsException(e.message, e)
|
|
57
|
+
} catch (e: Exception) {
|
|
58
|
+
throw SharingFailedException("Failed to share the file: ${e.message}", e)
|
|
59
|
+
}
|
|
49
60
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
fileToShare
|
|
56
|
-
)
|
|
57
|
-
val mimeType = params.getString(MIME_TYPE_OPTIONS_KEY)
|
|
58
|
-
?: URLConnection.guessContentTypeFromName(fileToShare.name)
|
|
59
|
-
?: "*/*"
|
|
60
|
-
val intent = Intent.createChooser(
|
|
61
|
-
createSharingIntent(contentUri, mimeType),
|
|
62
|
-
params.getString(DIALOG_TITLE_OPTIONS_KEY)
|
|
63
|
-
)
|
|
64
|
-
val resInfoList = context.packageManager.queryIntentActivities(
|
|
65
|
-
intent,
|
|
66
|
-
PackageManager.MATCH_DEFAULT_ONLY
|
|
67
|
-
)
|
|
68
|
-
resInfoList.forEach {
|
|
69
|
-
val packageName = it.activityInfo.packageName
|
|
70
|
-
context.grantUriPermission(packageName, contentUri, Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
|
61
|
+
|
|
62
|
+
OnActivityResult { _, (requestCode) ->
|
|
63
|
+
if (requestCode == REQUEST_CODE && pendingPromise != null) {
|
|
64
|
+
pendingPromise?.resolve(null)
|
|
65
|
+
pendingPromise = null
|
|
71
66
|
}
|
|
72
|
-
val activityProvider: ActivityProvider by moduleRegistry()
|
|
73
|
-
activityProvider.currentActivity.startActivityForResult(intent, REQUEST_CODE)
|
|
74
|
-
pendingPromise = promise
|
|
75
|
-
} catch (e: InvalidArgumentException) {
|
|
76
|
-
promise.reject("ERR_SHARING_URL", e.message, e)
|
|
77
|
-
} catch (e: Exception) {
|
|
78
|
-
promise.reject("ERR_SHARING", "Failed to share the file: " + e.message, e)
|
|
79
67
|
}
|
|
80
68
|
}
|
|
81
69
|
|
|
@@ -97,8 +85,9 @@ class SharingModule(
|
|
|
97
85
|
}
|
|
98
86
|
|
|
99
87
|
private fun isAllowedToRead(url: String?): Boolean {
|
|
100
|
-
val
|
|
101
|
-
return
|
|
88
|
+
val permissions = appContext.filePermission
|
|
89
|
+
return permissions?.getPathPermissions(context, url)?.contains(Permission.READ)
|
|
90
|
+
?: false
|
|
102
91
|
}
|
|
103
92
|
|
|
104
93
|
private fun createSharingIntent(uri: Uri, mimeType: String?) =
|
|
@@ -108,18 +97,7 @@ class SharingModule(
|
|
|
108
97
|
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
|
109
98
|
}
|
|
110
99
|
|
|
111
|
-
override fun onActivityResult(activity: Activity, requestCode: Int, resultCode: Int, data: Intent?) {
|
|
112
|
-
if (requestCode == REQUEST_CODE && pendingPromise != null) {
|
|
113
|
-
pendingPromise?.resolve(null)
|
|
114
|
-
pendingPromise = null
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
override fun onNewIntent(intent: Intent) = Unit
|
|
119
|
-
|
|
120
100
|
companion object {
|
|
121
101
|
private const val REQUEST_CODE = 8524
|
|
122
|
-
private const val MIME_TYPE_OPTIONS_KEY = "mimeType"
|
|
123
|
-
private const val DIALOG_TITLE_OPTIONS_KEY = "dialogTitle"
|
|
124
102
|
}
|
|
125
103
|
}
|
package/build/ExpoSharing.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoSharing.d.ts","sourceRoot":"","sources":["../src/ExpoSharing.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"ExpoSharing.d.ts","sourceRoot":"","sources":["../src/ExpoSharing.ts"],"names":[],"mappings":";AACA,wBAAkD"}
|
package/build/ExpoSharing.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export default
|
|
1
|
+
import { requireNativeModule } from 'expo-modules-core';
|
|
2
|
+
export default requireNativeModule('ExpoSharing');
|
|
3
3
|
//# sourceMappingURL=ExpoSharing.js.map
|
package/build/ExpoSharing.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoSharing.js","sourceRoot":"","sources":["../src/ExpoSharing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"ExpoSharing.js","sourceRoot":"","sources":["../src/ExpoSharing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACxD,eAAe,mBAAmB,CAAC,aAAa,CAAC,CAAC","sourcesContent":["import { requireNativeModule } from 'expo-modules-core';\nexport default requireNativeModule('ExpoSharing');\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoSharing.web.d.ts","sourceRoot":"","sources":["../src/ExpoSharing.web.ts"],"names":[],"mappings":"AAEA,
|
|
1
|
+
{"version":3,"file":"ExpoSharing.web.d.ts","sourceRoot":"","sources":["../src/ExpoSharing.web.ts"],"names":[],"mappings":"AAEA,KAAK,YAAY,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;;;wBAMxC,QAAQ,OAAO,CAAC;oBAOpB,MAAM,YAAW,YAAY,GAAQ,QAAQ,IAAI,CAAC;;AAX1E,wBAmBE"}
|
package/build/Sharing.d.ts
CHANGED
package/build/Sharing.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sharing.d.ts","sourceRoot":"","sources":["../src/Sharing.ts"],"names":[],"mappings":"AAKA,
|
|
1
|
+
{"version":3,"file":"Sharing.d.ts","sourceRoot":"","sources":["../src/Sharing.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,cAAc,GAAG;IAC3B;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAGF;;;GAGG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,OAAO,CAAC,CASzD;AAGD;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAKzF"}
|
|
@@ -48,11 +48,10 @@ EX_EXPORT_METHOD_AS(shareAsync,
|
|
|
48
48
|
_documentInteractionController.delegate = self;
|
|
49
49
|
_documentInteractionController.UTI = params[@"UTI"];
|
|
50
50
|
|
|
51
|
-
UIViewController *viewController = [[_moduleRegistry getModuleImplementingProtocol:@protocol(EXUtilitiesInterface)] currentViewController];
|
|
52
|
-
|
|
53
51
|
EX_WEAKIFY(self);
|
|
54
52
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
55
53
|
EX_ENSURE_STRONGIFY(self);
|
|
54
|
+
UIViewController *viewController = [[self.moduleRegistry getModuleImplementingProtocol:@protocol(EXUtilitiesInterface)] currentViewController];
|
|
56
55
|
UIView *rootView = [viewController view];
|
|
57
56
|
if ([self.documentInteractionController presentOpenInMenuFromRect:CGRectZero inView:rootView animated:YES]) {
|
|
58
57
|
self.pendingResolver = resolve;
|
|
@@ -68,7 +67,19 @@ EX_EXPORT_METHOD_AS(shareAsync,
|
|
|
68
67
|
_pendingResolver(nil);
|
|
69
68
|
_pendingResolver = nil;
|
|
70
69
|
|
|
71
|
-
|
|
70
|
+
// This delegate method is called whenever:
|
|
71
|
+
// a) the share sheet is canceled
|
|
72
|
+
// b) an app is chosen, it's dialog opened, and the share is confirmed/ sent
|
|
73
|
+
// c) an app is chosen, it's dialog opened, and that dialog is canceled
|
|
74
|
+
// In case c), the share sheet remains open, even though the promise was resolved
|
|
75
|
+
// Future attempts to share without closing the sheet will fail to attach the file, so we need to close it
|
|
76
|
+
// No other delegate methods fire only when the share sheet is dismissed, unfortunately
|
|
77
|
+
EX_WEAKIFY(self);
|
|
78
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
79
|
+
EX_ENSURE_STRONGIFY(self);
|
|
80
|
+
[self.documentInteractionController dismissMenuAnimated:true];
|
|
81
|
+
self.documentInteractionController = nil;
|
|
82
|
+
});
|
|
72
83
|
}
|
|
73
84
|
|
|
74
85
|
@end
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-sharing",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.1.0",
|
|
4
4
|
"description": "ExpoSharing standalone module",
|
|
5
5
|
"main": "build/Sharing.js",
|
|
6
6
|
"types": "build/Sharing.d.ts",
|
|
@@ -37,5 +37,5 @@
|
|
|
37
37
|
"peerDependencies": {
|
|
38
38
|
"expo": "*"
|
|
39
39
|
},
|
|
40
|
-
"gitHead": "
|
|
40
|
+
"gitHead": "ba80e8181b79d06e00a245653727f4eaeb80420e"
|
|
41
41
|
}
|
package/src/ExpoSharing.ts
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
export default NativeModulesProxy.ExpoSharing;
|
|
1
|
+
import { requireNativeModule } from 'expo-modules-core';
|
|
2
|
+
export default requireNativeModule('ExpoSharing');
|
package/unimodule.json
DELETED