expo-document-picker 9.2.3 → 10.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 +17 -4
- package/android/build.gradle +7 -11
- package/android/src/main/AndroidManifest.xml +1 -1
- package/android/src/main/java/expo/modules/documentpicker/DocumentDetailsReader.kt +3 -2
- package/android/src/main/java/expo/modules/documentpicker/DocumentPickerModule.kt +23 -23
- package/android/src/main/java/expo/modules/documentpicker/DocumentPickerOptions.kt +35 -12
- package/android/src/main/java/expo/modules/documentpicker/DocumentPickerPackage.kt +1 -1
- package/build/ExpoDocumentPicker.d.ts +1 -1
- package/build/ExpoDocumentPicker.js +1 -1
- package/build/ExpoDocumentPicker.js.map +1 -1
- package/build/ExpoDocumentPicker.web.js +4 -2
- package/build/ExpoDocumentPicker.web.js.map +1 -1
- package/build/index.d.ts +11 -0
- package/build/index.js +15 -0
- package/build/index.js.map +1 -1
- package/build/types.d.ts +35 -2
- package/build/types.js.map +1 -1
- package/ios/EXDocumentPicker/EXDocumentPickerModule.h +3 -3
- package/ios/EXDocumentPicker/EXDocumentPickerModule.m +43 -22
- package/ios/EXDocumentPicker.podspec +2 -2
- package/package.json +5 -8
- package/plugin/build/withDocumentPickerIOS.js +3 -2
- package/plugin/src/withDocumentPickerIOS.ts +1 -1
- package/src/ExpoDocumentPicker.ts +1 -1
- package/src/ExpoDocumentPicker.web.ts +4 -2
- package/src/index.ts +15 -0
- package/src/types.ts +37 -2
package/CHANGELOG.md
CHANGED
|
@@ -10,19 +10,32 @@
|
|
|
10
10
|
|
|
11
11
|
### 💡 Others
|
|
12
12
|
|
|
13
|
-
##
|
|
13
|
+
## 10.0.2 — 2021-10-15
|
|
14
14
|
|
|
15
15
|
_This version does not introduce any user-facing changes._
|
|
16
16
|
|
|
17
|
-
##
|
|
17
|
+
## 10.0.1 — 2021-10-01
|
|
18
|
+
|
|
19
|
+
_This version does not introduce any user-facing changes._
|
|
20
|
+
|
|
21
|
+
## 10.0.0 — 2021-09-28
|
|
22
|
+
|
|
23
|
+
### 🛠 Breaking changes
|
|
24
|
+
|
|
25
|
+
- Dropped support for iOS 11.0 ([#14383](https://github.com/expo/expo/pull/14383) by [@cruzach](https://github.com/cruzach))
|
|
18
26
|
|
|
19
27
|
### 🐛 Bug fixes
|
|
20
28
|
|
|
21
29
|
- Added `AndroidManifest.xml` queries for intent handling. ([#13388](https://github.com/expo/expo/pull/13388) by [@EvanBacon](https://github.com/EvanBacon))
|
|
30
|
+
- Added possibility to pass mimetypes array in order to set multiple mimetypes, fix bug with default mimetype. ([#13751](https://github.com/expo/expo/pull/13751) by [@mstach60161](https://github.com/mstach60161))
|
|
31
|
+
- Added mimetype to getDocumentAsync result. ([#13702](https://github.com/expo/expo/pull/13702) by [@mstach60161](https://github.com/mstach60161))
|
|
32
|
+
- Fixed file uri. ([#13678](https://github.com/expo/expo/pull/13678) by [@mstach60161](https://github.com/mstach60161))
|
|
33
|
+
- Fix building errors from use_frameworks! in Podfile. ([#14523](https://github.com/expo/expo/pull/14523) by [@kudo](https://github.com/kudo))
|
|
22
34
|
|
|
23
|
-
|
|
35
|
+
### 💡 Others
|
|
24
36
|
|
|
25
|
-
|
|
37
|
+
- Migrated from `@unimodules/core` to `expo-modules-core`. ([#13757](https://github.com/expo/expo/pull/13757) by [@tsapeta](https://github.com/tsapeta))
|
|
38
|
+
- Updated `@expo/config-plugins` ([#14443](https://github.com/expo/expo/pull/14443) by [@EvanBacon](https://github.com/EvanBacon))
|
|
26
39
|
|
|
27
40
|
## 9.2.0 — 2021-06-16
|
|
28
41
|
|
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 = '10.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 '10.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.annotation:annotation:1.0.0"
|
|
79
75
|
api 'commons-io:commons-io:2.6'
|
|
@@ -4,7 +4,7 @@ import android.content.Context
|
|
|
4
4
|
import android.net.Uri
|
|
5
5
|
import android.provider.OpenableColumns
|
|
6
6
|
|
|
7
|
-
data class DocumentDetails(val name: String, val uri: String, val size: Int?)
|
|
7
|
+
data class DocumentDetails(val name: String, val uri: String, val size: Int?, val mimeType: String?)
|
|
8
8
|
|
|
9
9
|
class DocumentDetailsReader(private val context: Context) {
|
|
10
10
|
fun read(uri: Uri): DocumentDetails? {
|
|
@@ -22,7 +22,8 @@ class DocumentDetailsReader(private val context: Context) {
|
|
|
22
22
|
null
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
|
-
|
|
25
|
+
val mimeType = context.contentResolver.getType(uri)
|
|
26
|
+
return DocumentDetails(name, uriString, size, mimeType)
|
|
26
27
|
}
|
|
27
28
|
return null
|
|
28
29
|
}
|
|
@@ -7,15 +7,15 @@ import android.net.Uri
|
|
|
7
7
|
import android.os.Bundle
|
|
8
8
|
import org.apache.commons.io.FilenameUtils
|
|
9
9
|
import org.apache.commons.io.IOUtils
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import
|
|
14
|
-
import
|
|
15
|
-
import
|
|
16
|
-
import
|
|
17
|
-
import
|
|
18
|
-
import
|
|
10
|
+
import expo.modules.core.ExportedModule
|
|
11
|
+
import expo.modules.core.ModuleRegistry
|
|
12
|
+
import expo.modules.core.ModuleRegistryDelegate
|
|
13
|
+
import expo.modules.core.Promise
|
|
14
|
+
import expo.modules.core.interfaces.ActivityEventListener
|
|
15
|
+
import expo.modules.core.interfaces.ActivityProvider
|
|
16
|
+
import expo.modules.core.interfaces.ExpoMethod
|
|
17
|
+
import expo.modules.core.interfaces.services.UIManager
|
|
18
|
+
import expo.modules.core.utilities.FileUtilities
|
|
19
19
|
import java.io.File
|
|
20
20
|
import java.io.FileOutputStream
|
|
21
21
|
import java.io.IOException
|
|
@@ -25,7 +25,7 @@ private const val OPEN_DOCUMENT_CODE = 4137
|
|
|
25
25
|
|
|
26
26
|
class DocumentPickerModule(
|
|
27
27
|
mContext: Context,
|
|
28
|
-
private val moduleRegistryDelegate: ModuleRegistryDelegate = ModuleRegistryDelegate()
|
|
28
|
+
private val moduleRegistryDelegate: ModuleRegistryDelegate = ModuleRegistryDelegate()
|
|
29
29
|
) : ExportedModule(mContext), ActivityEventListener {
|
|
30
30
|
private var mPromise: Promise? = null
|
|
31
31
|
private var mCopyToCacheDirectory = true
|
|
@@ -48,17 +48,18 @@ class DocumentPickerModule(
|
|
|
48
48
|
promise.reject("E_DOCUMENT_PICKER", "Different document picking in progress. Await other document picking first.")
|
|
49
49
|
return
|
|
50
50
|
}
|
|
51
|
-
|
|
52
51
|
val pickerOptions = DocumentPickerOptions.optionsFromMap(options, promise) ?: return
|
|
53
|
-
|
|
54
52
|
mPromise = promise
|
|
55
53
|
mCopyToCacheDirectory = pickerOptions.copyToCacheDirectory
|
|
56
|
-
|
|
57
54
|
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
|
|
58
55
|
addCategory(Intent.CATEGORY_OPENABLE)
|
|
59
|
-
type = pickerOptions.
|
|
56
|
+
type = if (pickerOptions.types.size > 1) {
|
|
57
|
+
putExtra(Intent.EXTRA_MIME_TYPES, pickerOptions.types)
|
|
58
|
+
"*/*"
|
|
59
|
+
} else {
|
|
60
|
+
pickerOptions.types[0]
|
|
61
|
+
}
|
|
60
62
|
}
|
|
61
|
-
|
|
62
63
|
mActivityProvider.currentActivity.startActivityForResult(intent, OPEN_DOCUMENT_CODE)
|
|
63
64
|
}
|
|
64
65
|
|
|
@@ -88,7 +89,6 @@ class DocumentPickerModule(
|
|
|
88
89
|
}
|
|
89
90
|
}
|
|
90
91
|
}
|
|
91
|
-
|
|
92
92
|
if (documentDetails == null) {
|
|
93
93
|
promise.reject("E_DOCUMENT_PICKER", "Failed to read the selected document.")
|
|
94
94
|
} else {
|
|
@@ -96,9 +96,10 @@ class DocumentPickerModule(
|
|
|
96
96
|
putString("type", "success")
|
|
97
97
|
putString("uri", documentDetails.uri)
|
|
98
98
|
putString("name", documentDetails.name)
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
99
|
+
documentDetails.mimeType?.let {
|
|
100
|
+
putString("mimeType", documentDetails.mimeType)
|
|
101
|
+
}
|
|
102
|
+
documentDetails.size?.let {
|
|
102
103
|
putInt("size", documentDetails.size)
|
|
103
104
|
}
|
|
104
105
|
}
|
|
@@ -120,10 +121,10 @@ class DocumentPickerModule(
|
|
|
120
121
|
"DocumentPicker",
|
|
121
122
|
FilenameUtils.getExtension(name)
|
|
122
123
|
)
|
|
123
|
-
|
|
124
|
+
val outputFile = File(outputFilePath)
|
|
124
125
|
try {
|
|
125
126
|
context.contentResolver.openInputStream(documentUri).use { inputStream ->
|
|
126
|
-
FileOutputStream(
|
|
127
|
+
FileOutputStream(outputFile).use { outputStream ->
|
|
127
128
|
IOUtils.copy(inputStream, outputStream)
|
|
128
129
|
}
|
|
129
130
|
}
|
|
@@ -131,7 +132,6 @@ class DocumentPickerModule(
|
|
|
131
132
|
e.printStackTrace()
|
|
132
133
|
return null
|
|
133
134
|
}
|
|
134
|
-
|
|
135
|
-
return outputFilePath
|
|
135
|
+
return Uri.fromFile(outputFile).toString()
|
|
136
136
|
}
|
|
137
137
|
}
|
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
package expo.modules.documentpicker
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import expo.modules.core.Promise
|
|
4
4
|
|
|
5
|
-
data class DocumentPickerOptions(val
|
|
5
|
+
data class DocumentPickerOptions(val copyToCacheDirectory: Boolean, val types: Array<String>) {
|
|
6
6
|
companion object {
|
|
7
7
|
fun optionsFromMap(options: Map<String, Any?>, promise: Promise): DocumentPickerOptions? {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
return@let it
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
promise.reject("ERR_INVALID_OPTION", "type must be a string")
|
|
8
|
+
if (options.containsKey("type") && options["type"] == null) {
|
|
9
|
+
promise.reject("ERR_INVALID_OPTION", "type must be a list of strings")
|
|
14
10
|
return null
|
|
15
|
-
}
|
|
16
|
-
|
|
11
|
+
}
|
|
12
|
+
var mimeTypes = arrayListOf("*/*")
|
|
13
|
+
options["type"]?.let {
|
|
14
|
+
val types = it as ArrayList<*>
|
|
15
|
+
if (types.isEmpty() || types[0] !is String) {
|
|
16
|
+
promise.reject("ERR_INVALID_OPTION", "type must be a list of strings")
|
|
17
|
+
return null
|
|
18
|
+
} else {
|
|
19
|
+
@Suppress("UNCHECKED_CAST")
|
|
20
|
+
mimeTypes = types as ArrayList<String>
|
|
21
|
+
}
|
|
22
|
+
}
|
|
17
23
|
val copyToCacheDirectory = options["copyToCacheDirectory"]?.let {
|
|
18
24
|
if (it is Boolean) {
|
|
19
25
|
return@let it
|
|
@@ -21,8 +27,25 @@ data class DocumentPickerOptions(val type: String, val copyToCacheDirectory: Boo
|
|
|
21
27
|
promise.reject("ERR_INVALID_OPTION", "copyToCacheDirectory must be a boolean")
|
|
22
28
|
return null
|
|
23
29
|
} ?: true
|
|
24
|
-
|
|
25
|
-
return DocumentPickerOptions(type, copyToCacheDirectory)
|
|
30
|
+
return DocumentPickerOptions(copyToCacheDirectory, mimeTypes.toTypedArray())
|
|
26
31
|
}
|
|
27
32
|
}
|
|
33
|
+
|
|
34
|
+
override fun equals(other: Any?): Boolean {
|
|
35
|
+
if (this === other) return true
|
|
36
|
+
if (javaClass != other?.javaClass) return false
|
|
37
|
+
|
|
38
|
+
other as DocumentPickerOptions
|
|
39
|
+
|
|
40
|
+
if (copyToCacheDirectory != other.copyToCacheDirectory) return false
|
|
41
|
+
if (!types.contentEquals(other.types)) return false
|
|
42
|
+
|
|
43
|
+
return true
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
override fun hashCode(): Int {
|
|
47
|
+
var result = copyToCacheDirectory.hashCode()
|
|
48
|
+
result = 31 * result + types.contentHashCode()
|
|
49
|
+
return result
|
|
50
|
+
}
|
|
28
51
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
package expo.modules.documentpicker
|
|
2
2
|
|
|
3
3
|
import android.content.Context
|
|
4
|
-
import
|
|
4
|
+
import expo.modules.core.BasePackage
|
|
5
5
|
|
|
6
6
|
class DocumentPickerPackage : BasePackage() {
|
|
7
7
|
override fun createExportedModules(context: Context) = listOf(DocumentPickerModule(context))
|
|
@@ -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":"ExpoDocumentPicker.js","sourceRoot":"","sources":["../src/ExpoDocumentPicker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"ExpoDocumentPicker.js","sourceRoot":"","sources":["../src/ExpoDocumentPicker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,eAAe,kBAAkB,CAAC,kBAAkB,CAAC","sourcesContent":["import { NativeModulesProxy } from 'expo-modules-core';\n\nexport default NativeModulesProxy.ExpoDocumentPicker;\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Platform } from '
|
|
1
|
+
import { Platform } from 'expo-modules-core';
|
|
2
2
|
import { v4 as uuidv4 } from 'uuid';
|
|
3
3
|
export default {
|
|
4
4
|
get name() {
|
|
@@ -12,7 +12,7 @@ export default {
|
|
|
12
12
|
const input = document.createElement('input');
|
|
13
13
|
input.style.display = 'none';
|
|
14
14
|
input.setAttribute('type', 'file');
|
|
15
|
-
input.setAttribute('accept', type);
|
|
15
|
+
input.setAttribute('accept', Array.isArray(type) ? type.join(',') : type);
|
|
16
16
|
input.setAttribute('id', uuidv4());
|
|
17
17
|
if (multiple) {
|
|
18
18
|
input.setAttribute('multiple', 'multiple');
|
|
@@ -22,6 +22,7 @@ export default {
|
|
|
22
22
|
input.addEventListener('change', () => {
|
|
23
23
|
if (input.files) {
|
|
24
24
|
const targetFile = input.files[0];
|
|
25
|
+
const mimeType = targetFile.type;
|
|
25
26
|
const reader = new FileReader();
|
|
26
27
|
reader.onerror = () => {
|
|
27
28
|
reject(new Error(`Failed to read the selected media because the operation failed.`));
|
|
@@ -31,6 +32,7 @@ export default {
|
|
|
31
32
|
resolve({
|
|
32
33
|
type: 'success',
|
|
33
34
|
uri,
|
|
35
|
+
mimeType,
|
|
34
36
|
name: targetFile.name,
|
|
35
37
|
file: targetFile,
|
|
36
38
|
lastModified: targetFile.lastModified,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoDocumentPicker.web.js","sourceRoot":"","sources":["../src/ExpoDocumentPicker.web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"ExpoDocumentPicker.web.js","sourceRoot":"","sources":["../src/ExpoDocumentPicker.web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAC7C,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,MAAM,CAAC;AAIpC,eAAe;IACb,IAAI,IAAI;QACN,OAAO,oBAAoB,CAAC;IAC9B,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,EACrB,IAAI,GAAG,KAAK,EACZ,QAAQ,GAAG,KAAK,GACM;QACtB,YAAY;QACZ,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE;YAC5B,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;SAC3B;QAED,MAAM,KAAK,GAAG,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAC9C,KAAK,CAAC,KAAK,CAAC,OAAO,GAAG,MAAM,CAAC;QAC7B,KAAK,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACnC,KAAK,CAAC,YAAY,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC1E,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;QACnC,IAAI,QAAQ,EAAE;YACZ,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;SAC5C;QAED,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;QAEjC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACrC,KAAK,CAAC,gBAAgB,CAAC,QAAQ,EAAE,GAAG,EAAE;gBACpC,IAAI,KAAK,CAAC,KAAK,EAAE;oBACf,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;oBAClC,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,CAAC;oBACjC,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;oBAChC,MAAM,CAAC,OAAO,GAAG,GAAG,EAAE;wBACpB,MAAM,CAAC,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAC,CAAC;oBACvF,CAAC,CAAC;oBACF,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;wBAC7B,MAAM,GAAG,GAAI,MAAc,CAAC,MAAM,CAAC;wBACnC,OAAO,CAAC;4BACN,IAAI,EAAE,SAAS;4BACf,GAAG;4BACH,QAAQ;4BACR,IAAI,EAAE,UAAU,CAAC,IAAI;4BACrB,IAAI,EAAE,UAAU;4BAChB,YAAY,EAAE,UAAU,CAAC,YAAY;4BACrC,IAAI,EAAE,UAAU,CAAC,IAAI;4BACrB,MAAM,EAAE,KAAK,CAAC,KAAK;yBACpB,CAAC,CAAC;oBACL,CAAC,CAAC;oBACF,6CAA6C;oBAC7C,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;iBAClC;qBAAM;oBACL,OAAO,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;iBAC7B;gBAED,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC;YACnC,CAAC,CAAC,CAAC;YAEH,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC;YACtC,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC7B,CAAC,CAAC,CAAC;IACL,CAAC;CACF,CAAC","sourcesContent":["import { Platform } from 'expo-modules-core';\nimport { v4 as uuidv4 } from 'uuid';\n\nimport { DocumentPickerOptions, DocumentResult } from './types';\n\nexport default {\n get name(): string {\n return 'ExpoDocumentPicker';\n },\n\n async getDocumentAsync({\n type = '*/*',\n multiple = false,\n }: DocumentPickerOptions): Promise<DocumentResult> {\n // SSR guard\n if (!Platform.isDOMAvailable) {\n return { type: 'cancel' };\n }\n\n const input = document.createElement('input');\n input.style.display = 'none';\n input.setAttribute('type', 'file');\n input.setAttribute('accept', Array.isArray(type) ? type.join(',') : type);\n input.setAttribute('id', uuidv4());\n if (multiple) {\n input.setAttribute('multiple', 'multiple');\n }\n\n document.body.appendChild(input);\n\n return new Promise((resolve, reject) => {\n input.addEventListener('change', () => {\n if (input.files) {\n const targetFile = input.files[0];\n const mimeType = targetFile.type;\n const reader = new FileReader();\n reader.onerror = () => {\n reject(new Error(`Failed to read the selected media because the operation failed.`));\n };\n reader.onload = ({ target }) => {\n const uri = (target as any).result;\n resolve({\n type: 'success',\n uri,\n mimeType,\n name: targetFile.name,\n file: targetFile,\n lastModified: targetFile.lastModified,\n size: targetFile.size,\n output: input.files,\n });\n };\n // Read in the image file as a binary string.\n reader.readAsDataURL(targetFile);\n } else {\n resolve({ type: 'cancel' });\n }\n\n document.body.removeChild(input);\n });\n\n const event = new MouseEvent('click');\n input.dispatchEvent(event);\n });\n },\n};\n"]}
|
package/build/index.d.ts
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
1
|
import { DocumentPickerOptions, DocumentResult } from './types';
|
|
2
2
|
export { DocumentPickerOptions, DocumentResult };
|
|
3
|
+
/**
|
|
4
|
+
* Display the system UI for choosing a document. By default, the chosen file is copied to [the app's internal cache directory](filesystem.md#filesystemcachedirectory).
|
|
5
|
+
* > **Notes for Web:** The system UI can only be shown after user activation (e.g. a `Button` press).
|
|
6
|
+
* Therefore, calling `getDocumentAsync` in `componentDidMount`, for example, will **not** work as
|
|
7
|
+
* intended. The `cancel` event will not be returned in the browser due to platform restrictions and
|
|
8
|
+
* inconsistencies across browsers.
|
|
9
|
+
*
|
|
10
|
+
* @return On success returns a promise that fulfils with [`DocumentResult`](#documentresult) object.
|
|
11
|
+
*
|
|
12
|
+
* If the user cancelled the document picking, the promise resolves to `{ type: 'cancel' }`.
|
|
13
|
+
*/
|
|
3
14
|
export declare function getDocumentAsync({ type, copyToCacheDirectory, multiple, }?: DocumentPickerOptions): Promise<DocumentResult>;
|
package/build/index.js
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
import ExpoDocumentPicker from './ExpoDocumentPicker';
|
|
2
|
+
// @needsAudit
|
|
3
|
+
/**
|
|
4
|
+
* Display the system UI for choosing a document. By default, the chosen file is copied to [the app's internal cache directory](filesystem.md#filesystemcachedirectory).
|
|
5
|
+
* > **Notes for Web:** The system UI can only be shown after user activation (e.g. a `Button` press).
|
|
6
|
+
* Therefore, calling `getDocumentAsync` in `componentDidMount`, for example, will **not** work as
|
|
7
|
+
* intended. The `cancel` event will not be returned in the browser due to platform restrictions and
|
|
8
|
+
* inconsistencies across browsers.
|
|
9
|
+
*
|
|
10
|
+
* @return On success returns a promise that fulfils with [`DocumentResult`](#documentresult) object.
|
|
11
|
+
*
|
|
12
|
+
* If the user cancelled the document picking, the promise resolves to `{ type: 'cancel' }`.
|
|
13
|
+
*/
|
|
2
14
|
export async function getDocumentAsync({ type = '*/*', copyToCacheDirectory = true, multiple = false, } = {}) {
|
|
15
|
+
if (typeof type === 'string') {
|
|
16
|
+
type = [type];
|
|
17
|
+
}
|
|
3
18
|
return await ExpoDocumentPicker.getDocumentAsync({ type, copyToCacheDirectory, multiple });
|
|
4
19
|
}
|
|
5
20
|
//# sourceMappingURL=index.js.map
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,MAAM,sBAAsB,CAAC;AAItD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,EACrC,IAAI,GAAG,KAAK,EACZ,oBAAoB,GAAG,IAAI,EAC3B,QAAQ,GAAG,KAAK,MACS,EAAE;IAC3B,OAAO,MAAM,kBAAkB,CAAC,gBAAgB,CAAC,EAAE,IAAI,EAAE,oBAAoB,EAAE,QAAQ,EAAE,CAAC,CAAC;AAC7F,CAAC","sourcesContent":["import ExpoDocumentPicker from './ExpoDocumentPicker';\nimport { DocumentPickerOptions, DocumentResult } from './types';\nexport { DocumentPickerOptions, DocumentResult };\n\nexport async function getDocumentAsync({\n type = '*/*',\n copyToCacheDirectory = true,\n multiple = false,\n}: DocumentPickerOptions = {}): Promise<DocumentResult> {\n return await ExpoDocumentPicker.getDocumentAsync({ type, copyToCacheDirectory, multiple });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,kBAAkB,MAAM,sBAAsB,CAAC;AAItD,cAAc;AACd;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,EACrC,IAAI,GAAG,KAAK,EACZ,oBAAoB,GAAG,IAAI,EAC3B,QAAQ,GAAG,KAAK,MACS,EAAE;IAC3B,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;QAC5B,IAAI,GAAG,CAAC,IAAI,CAAa,CAAC;KAC3B;IACD,OAAO,MAAM,kBAAkB,CAAC,gBAAgB,CAAC,EAAE,IAAI,EAAE,oBAAoB,EAAE,QAAQ,EAAE,CAAC,CAAC;AAC7F,CAAC","sourcesContent":["import ExpoDocumentPicker from './ExpoDocumentPicker';\nimport { DocumentPickerOptions, DocumentResult } from './types';\nexport { DocumentPickerOptions, DocumentResult };\n\n// @needsAudit\n/**\n * Display the system UI for choosing a document. By default, the chosen file is copied to [the app's internal cache directory](filesystem.md#filesystemcachedirectory).\n * > **Notes for Web:** The system UI can only be shown after user activation (e.g. a `Button` press).\n * Therefore, calling `getDocumentAsync` in `componentDidMount`, for example, will **not** work as\n * intended. The `cancel` event will not be returned in the browser due to platform restrictions and\n * inconsistencies across browsers.\n *\n * @return On success returns a promise that fulfils with [`DocumentResult`](#documentresult) object.\n *\n * If the user cancelled the document picking, the promise resolves to `{ type: 'cancel' }`.\n */\nexport async function getDocumentAsync({\n type = '*/*',\n copyToCacheDirectory = true,\n multiple = false,\n}: DocumentPickerOptions = {}): Promise<DocumentResult> {\n if (typeof type === 'string') {\n type = [type] as string[];\n }\n return await ExpoDocumentPicker.getDocumentAsync({ type, copyToCacheDirectory, multiple });\n}\n"]}
|
package/build/types.d.ts
CHANGED
|
@@ -1,15 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
*/
|
|
1
4
|
export declare type DocumentPickerOptions = {
|
|
2
|
-
|
|
5
|
+
/**
|
|
6
|
+
* The [MIME type(s)](https://en.wikipedia.org/wiki/Media_type) of the documents that are available
|
|
7
|
+
* to be picked. Is also supports wildcards like `'image/*'` to choose any image. To allow any type
|
|
8
|
+
* of document you can use `'*/*'`.
|
|
9
|
+
* @default `'*/*'`
|
|
10
|
+
*/
|
|
11
|
+
type?: string | string[];
|
|
12
|
+
/**
|
|
13
|
+
* If `true`, the picked file is copied to [`FileSystem.CacheDirectory`](filesystem.md#filesystemcachedirectory),
|
|
14
|
+
* which allows other Expo APIs to read the file immediately. This may impact performance for
|
|
15
|
+
* large files, so you should consider setting this to `false` if you expect users to pick
|
|
16
|
+
* particularly large files and your app does not need immediate read access.
|
|
17
|
+
* @default `true`
|
|
18
|
+
*/
|
|
3
19
|
copyToCacheDirectory?: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* __Web Only.__ Allows multiple files to be selected from the system UI.
|
|
22
|
+
* @default `false`
|
|
23
|
+
*/
|
|
4
24
|
multiple?: boolean;
|
|
5
25
|
};
|
|
6
26
|
export declare type DocumentResult = {
|
|
7
27
|
type: 'cancel';
|
|
8
28
|
} | {
|
|
9
29
|
type: 'success';
|
|
30
|
+
/**
|
|
31
|
+
* Document original name.
|
|
32
|
+
*/
|
|
10
33
|
name: string;
|
|
11
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Document size in bytes.
|
|
36
|
+
*/
|
|
37
|
+
size?: number;
|
|
38
|
+
/**
|
|
39
|
+
* An URI to the local document file.
|
|
40
|
+
*/
|
|
12
41
|
uri: string;
|
|
42
|
+
/**
|
|
43
|
+
* Document MIME type.
|
|
44
|
+
*/
|
|
45
|
+
mimeType?: string;
|
|
13
46
|
lastModified?: number;
|
|
14
47
|
file?: File;
|
|
15
48
|
output?: FileList | null;
|
package/build/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["// @needsAudit\n/**\n *\n */\nexport type DocumentPickerOptions = {\n /**\n * The [MIME type(s)](https://en.wikipedia.org/wiki/Media_type) of the documents that are available\n * to be picked. Is also supports wildcards like `'image/*'` to choose any image. To allow any type\n * of document you can use `'*/*'`.\n * @default `'*/*'`\n */\n type?: string | string[];\n /**\n * If `true`, the picked file is copied to [`FileSystem.CacheDirectory`](filesystem.md#filesystemcachedirectory),\n * which allows other Expo APIs to read the file immediately. This may impact performance for\n * large files, so you should consider setting this to `false` if you expect users to pick\n * particularly large files and your app does not need immediate read access.\n * @default `true`\n */\n copyToCacheDirectory?: boolean;\n /**\n * __Web Only.__ Allows multiple files to be selected from the system UI.\n * @default `false`\n */\n multiple?: boolean;\n};\n\n// @needsAudit @docsMissing\nexport type DocumentResult =\n | { type: 'cancel' }\n | {\n type: 'success';\n /**\n * Document original name.\n */\n name: string;\n /**\n * Document size in bytes.\n */\n size?: number;\n /**\n * An URI to the local document file.\n */\n uri: string;\n /**\n * Document MIME type.\n */\n mimeType?: string;\n lastModified?: number;\n file?: File;\n output?: FileList | null;\n };\n"]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Copyright © 2018 650 Industries. All rights reserved.
|
|
2
2
|
|
|
3
|
-
#import <
|
|
4
|
-
#import <
|
|
3
|
+
#import <ExpoModulesCore/EXExportedModule.h>
|
|
4
|
+
#import <ExpoModulesCore/EXModuleRegistryConsumer.h>
|
|
5
5
|
|
|
6
|
-
@interface EXDocumentPickerModule :
|
|
6
|
+
@interface EXDocumentPickerModule : EXExportedModule <EXModuleRegistryConsumer>
|
|
7
7
|
@end
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
#import <EXDocumentPicker/EXDocumentPickerModule.h>
|
|
5
|
-
#import <
|
|
5
|
+
#import <ExpoModulesCore/EXUtilitiesInterface.h>
|
|
6
6
|
#import <ExpoModulesCore/EXFileSystemInterface.h>
|
|
7
7
|
|
|
8
8
|
#import <UIKit/UIKit.h>
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
// UTType#typeWithMIMEType doesn't work with wildcard mimetypes
|
|
21
21
|
// so support common top level types with wildcards here.
|
|
22
22
|
if ([mimeType isEqualToString:@"*/*"]) {
|
|
23
|
-
return
|
|
23
|
+
return UTTypeItem;
|
|
24
24
|
} else if ([mimeType isEqualToString:@"image/*"]) {
|
|
25
25
|
return UTTypeImage;
|
|
26
26
|
} else if ([mimeType isEqualToString:@"video/*"]) {
|
|
@@ -43,7 +43,7 @@ static NSString * EXConvertMimeTypeToUTI(NSString *mimeType)
|
|
|
43
43
|
// UTTypeCreatePreferredIdentifierForTag doesn't work with wildcard mimetypes
|
|
44
44
|
// so support common top level types with wildcards here.
|
|
45
45
|
if ([mimeType isEqualToString:@"*/*"]) {
|
|
46
|
-
uti =
|
|
46
|
+
uti = kUTTypeItem;
|
|
47
47
|
} else if ([mimeType isEqualToString:@"image/*"]) {
|
|
48
48
|
uti = kUTTypeImage;
|
|
49
49
|
} else if ([mimeType isEqualToString:@"video/*"]) {
|
|
@@ -62,12 +62,12 @@ static NSString * EXConvertMimeTypeToUTI(NSString *mimeType)
|
|
|
62
62
|
|
|
63
63
|
@interface EXDocumentPickerModule () <UIDocumentPickerDelegate, UIAdaptivePresentationControllerDelegate>
|
|
64
64
|
|
|
65
|
-
@property (nonatomic, weak)
|
|
65
|
+
@property (nonatomic, weak) EXModuleRegistry *moduleRegistry;
|
|
66
66
|
@property (nonatomic, weak) id<EXFileSystemInterface> fileSystem;
|
|
67
|
-
@property (nonatomic, weak) id<
|
|
67
|
+
@property (nonatomic, weak) id<EXUtilitiesInterface> utilities;
|
|
68
68
|
|
|
69
|
-
@property (nonatomic, strong)
|
|
70
|
-
@property (nonatomic, strong)
|
|
69
|
+
@property (nonatomic, strong) EXPromiseResolveBlock resolve;
|
|
70
|
+
@property (nonatomic, strong) EXPromiseRejectBlock reject;
|
|
71
71
|
|
|
72
72
|
@property (nonatomic, assign) BOOL shouldCopyToCacheDirectory;
|
|
73
73
|
|
|
@@ -75,49 +75,60 @@ static NSString * EXConvertMimeTypeToUTI(NSString *mimeType)
|
|
|
75
75
|
|
|
76
76
|
@implementation EXDocumentPickerModule
|
|
77
77
|
|
|
78
|
-
|
|
78
|
+
EX_EXPORT_MODULE(ExpoDocumentPicker);
|
|
79
79
|
|
|
80
|
-
- (void)setModuleRegistry:(
|
|
80
|
+
- (void)setModuleRegistry:(EXModuleRegistry *)moduleRegistry
|
|
81
81
|
{
|
|
82
82
|
_moduleRegistry = moduleRegistry;
|
|
83
83
|
|
|
84
84
|
if (_moduleRegistry != nil) {
|
|
85
85
|
_fileSystem = [moduleRegistry getModuleImplementingProtocol:@protocol(EXFileSystemInterface)];
|
|
86
|
-
_utilities = [moduleRegistry getModuleImplementingProtocol:@protocol(
|
|
86
|
+
_utilities = [moduleRegistry getModuleImplementingProtocol:@protocol(EXUtilitiesInterface)];
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
-
|
|
90
|
+
EX_EXPORT_METHOD_AS(getDocumentAsync,
|
|
91
91
|
options:(NSDictionary *)options
|
|
92
|
-
resolve:(
|
|
93
|
-
reject:(
|
|
92
|
+
resolve:(EXPromiseResolveBlock)resolve
|
|
93
|
+
reject:(EXPromiseRejectBlock)reject)
|
|
94
94
|
{
|
|
95
95
|
if (_resolve != nil) {
|
|
96
96
|
return reject(@"E_DOCUMENT_PICKER", @"Different document picking in progress. Await other document picking first.", nil);
|
|
97
97
|
}
|
|
98
98
|
_resolve = resolve;
|
|
99
99
|
_reject = reject;
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
100
|
+
|
|
101
|
+
NSArray *mimeTypes = options[@"type"] ?: @[@"*/*"];
|
|
102
|
+
if (mimeTypes.count == 0) {
|
|
103
|
+
reject(@"E_DOCUMENT_PICKER", @"type must be a list of strings.", nil);
|
|
104
|
+
_resolve = nil;
|
|
105
|
+
_reject = nil;
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
103
108
|
_shouldCopyToCacheDirectory = options[@"copyToCacheDirectory"] && [options[@"copyToCacheDirectory"] boolValue] == YES;
|
|
104
109
|
|
|
105
|
-
|
|
110
|
+
EX_WEAKIFY(self);
|
|
106
111
|
|
|
107
112
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
108
|
-
|
|
113
|
+
EX_ENSURE_STRONGIFY(self);
|
|
109
114
|
UIDocumentPickerViewController *documentPickerVC;
|
|
110
115
|
|
|
111
116
|
@try {
|
|
112
117
|
// TODO: drop #if macro once Xcode is updated to 12
|
|
113
118
|
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 140000
|
|
114
119
|
if (@available(iOS 14, *)) {
|
|
115
|
-
|
|
116
|
-
|
|
120
|
+
NSMutableArray *utTypes = [mimeTypes mutableCopy];
|
|
121
|
+
for (int i = 0; i < [mimeTypes count]; i++) {
|
|
122
|
+
utTypes[i] = (NSString *)EXConvertMimeTypeToUTType(mimeTypes[i]);
|
|
123
|
+
}
|
|
124
|
+
documentPickerVC = [[UIDocumentPickerViewController alloc] initForOpeningContentTypes:utTypes asCopy:true];
|
|
117
125
|
} else {
|
|
118
126
|
#endif
|
|
119
|
-
|
|
120
|
-
|
|
127
|
+
NSMutableArray *utiTypes = [mimeTypes mutableCopy];
|
|
128
|
+
for (int i = 0; i < [mimeTypes count]; i++) {
|
|
129
|
+
utiTypes[i] = (NSString *)EXConvertMimeTypeToUTI(mimeTypes[i]);
|
|
130
|
+
}
|
|
131
|
+
documentPickerVC = [[UIDocumentPickerViewController alloc] initWithDocumentTypes:utiTypes
|
|
121
132
|
inMode:UIDocumentPickerModeImport];
|
|
122
133
|
// TODO: drop #if macro once Xcode is updated to 12
|
|
123
134
|
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 140000
|
|
@@ -172,12 +183,16 @@ UM_EXPORT_METHOD_AS(getDocumentAsync,
|
|
|
172
183
|
return;
|
|
173
184
|
}
|
|
174
185
|
}
|
|
186
|
+
|
|
187
|
+
NSString *extension = [url pathExtension];
|
|
188
|
+
NSString *mimeType = [EXDocumentPickerModule getMimeType:extension];
|
|
175
189
|
|
|
176
190
|
_resolve(@{
|
|
177
191
|
@"type": @"success",
|
|
178
192
|
@"uri": [newUrl absoluteString],
|
|
179
193
|
@"name": [url lastPathComponent],
|
|
180
194
|
@"size": @(fileSize),
|
|
195
|
+
@"mimeType": mimeType
|
|
181
196
|
});
|
|
182
197
|
_resolve = nil;
|
|
183
198
|
_reject = nil;
|
|
@@ -227,4 +242,10 @@ UM_EXPORT_METHOD_AS(getDocumentAsync,
|
|
|
227
242
|
return folderSize;
|
|
228
243
|
}
|
|
229
244
|
|
|
245
|
+
+ (NSString *)getMimeType:(NSString *)fileExtension{
|
|
246
|
+
NSString *UTI = (__bridge_transfer NSString *)UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)fileExtension, NULL);
|
|
247
|
+
NSString *mimeType = (__bridge_transfer NSString *)UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)UTI, kUTTagClassMIMEType);
|
|
248
|
+
return mimeType;
|
|
249
|
+
}
|
|
250
|
+
|
|
230
251
|
@end
|
|
@@ -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-document-picker",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "10.0.2",
|
|
4
4
|
"description": "Provides access to the system's UI for selecting documents from the available providers on the user's device.",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -30,20 +30,17 @@
|
|
|
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/document-picker/",
|
|
34
34
|
"jest": {
|
|
35
35
|
"preset": "expo-module-scripts/ios"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@expo/config-plugins": "^3.
|
|
39
|
-
"expo-modules-core": "~0.
|
|
38
|
+
"@expo/config-plugins": "^3.1.0",
|
|
39
|
+
"expo-modules-core": "~0.4.3",
|
|
40
40
|
"uuid": "^3.3.2"
|
|
41
41
|
},
|
|
42
|
-
"unimodulePeerDependencies": {
|
|
43
|
-
"@unimodules/core": "*"
|
|
44
|
-
},
|
|
45
42
|
"devDependencies": {
|
|
46
43
|
"expo-module-scripts": "^2.0.0"
|
|
47
44
|
},
|
|
48
|
-
"gitHead": "
|
|
45
|
+
"gitHead": "d23e1ac491da96b51c25eb2533efcd56499ee287"
|
|
49
46
|
}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.setICloudEntitlments = exports.withDocumentPickerIOS = void 0;
|
|
4
4
|
const config_plugins_1 = require("@expo/config-plugins");
|
|
5
|
-
|
|
6
|
-
return config_plugins_1.withEntitlementsPlist(config, config => {
|
|
5
|
+
const withDocumentPickerIOS = (config, { appleTeamId }) => {
|
|
6
|
+
return config_plugins_1.withEntitlementsPlist(config, (config) => {
|
|
7
7
|
if (appleTeamId) {
|
|
8
8
|
config.modResults = setICloudEntitlments(config, appleTeamId, config.modResults);
|
|
9
9
|
}
|
|
@@ -13,6 +13,7 @@ exports.withDocumentPickerIOS = (config, { appleTeamId }) => {
|
|
|
13
13
|
return config;
|
|
14
14
|
});
|
|
15
15
|
};
|
|
16
|
+
exports.withDocumentPickerIOS = withDocumentPickerIOS;
|
|
16
17
|
function setICloudEntitlments(config, appleTeamId, entitlements) {
|
|
17
18
|
var _a;
|
|
18
19
|
if ((_a = config.ios) === null || _a === void 0 ? void 0 : _a.usesIcloudStorage) {
|
|
@@ -5,7 +5,7 @@ export const withDocumentPickerIOS: ConfigPlugin<{ appleTeamId?: string }> = (
|
|
|
5
5
|
config,
|
|
6
6
|
{ appleTeamId }
|
|
7
7
|
) => {
|
|
8
|
-
return withEntitlementsPlist(config, config => {
|
|
8
|
+
return withEntitlementsPlist(config, (config) => {
|
|
9
9
|
if (appleTeamId) {
|
|
10
10
|
config.modResults = setICloudEntitlments(config, appleTeamId, config.modResults);
|
|
11
11
|
} else {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Platform } from '
|
|
1
|
+
import { Platform } from 'expo-modules-core';
|
|
2
2
|
import { v4 as uuidv4 } from 'uuid';
|
|
3
3
|
|
|
4
4
|
import { DocumentPickerOptions, DocumentResult } from './types';
|
|
@@ -20,7 +20,7 @@ export default {
|
|
|
20
20
|
const input = document.createElement('input');
|
|
21
21
|
input.style.display = 'none';
|
|
22
22
|
input.setAttribute('type', 'file');
|
|
23
|
-
input.setAttribute('accept', type);
|
|
23
|
+
input.setAttribute('accept', Array.isArray(type) ? type.join(',') : type);
|
|
24
24
|
input.setAttribute('id', uuidv4());
|
|
25
25
|
if (multiple) {
|
|
26
26
|
input.setAttribute('multiple', 'multiple');
|
|
@@ -32,6 +32,7 @@ export default {
|
|
|
32
32
|
input.addEventListener('change', () => {
|
|
33
33
|
if (input.files) {
|
|
34
34
|
const targetFile = input.files[0];
|
|
35
|
+
const mimeType = targetFile.type;
|
|
35
36
|
const reader = new FileReader();
|
|
36
37
|
reader.onerror = () => {
|
|
37
38
|
reject(new Error(`Failed to read the selected media because the operation failed.`));
|
|
@@ -41,6 +42,7 @@ export default {
|
|
|
41
42
|
resolve({
|
|
42
43
|
type: 'success',
|
|
43
44
|
uri,
|
|
45
|
+
mimeType,
|
|
44
46
|
name: targetFile.name,
|
|
45
47
|
file: targetFile,
|
|
46
48
|
lastModified: targetFile.lastModified,
|
package/src/index.ts
CHANGED
|
@@ -2,10 +2,25 @@ import ExpoDocumentPicker from './ExpoDocumentPicker';
|
|
|
2
2
|
import { DocumentPickerOptions, DocumentResult } from './types';
|
|
3
3
|
export { DocumentPickerOptions, DocumentResult };
|
|
4
4
|
|
|
5
|
+
// @needsAudit
|
|
6
|
+
/**
|
|
7
|
+
* Display the system UI for choosing a document. By default, the chosen file is copied to [the app's internal cache directory](filesystem.md#filesystemcachedirectory).
|
|
8
|
+
* > **Notes for Web:** The system UI can only be shown after user activation (e.g. a `Button` press).
|
|
9
|
+
* Therefore, calling `getDocumentAsync` in `componentDidMount`, for example, will **not** work as
|
|
10
|
+
* intended. The `cancel` event will not be returned in the browser due to platform restrictions and
|
|
11
|
+
* inconsistencies across browsers.
|
|
12
|
+
*
|
|
13
|
+
* @return On success returns a promise that fulfils with [`DocumentResult`](#documentresult) object.
|
|
14
|
+
*
|
|
15
|
+
* If the user cancelled the document picking, the promise resolves to `{ type: 'cancel' }`.
|
|
16
|
+
*/
|
|
5
17
|
export async function getDocumentAsync({
|
|
6
18
|
type = '*/*',
|
|
7
19
|
copyToCacheDirectory = true,
|
|
8
20
|
multiple = false,
|
|
9
21
|
}: DocumentPickerOptions = {}): Promise<DocumentResult> {
|
|
22
|
+
if (typeof type === 'string') {
|
|
23
|
+
type = [type] as string[];
|
|
24
|
+
}
|
|
10
25
|
return await ExpoDocumentPicker.getDocumentAsync({ type, copyToCacheDirectory, multiple });
|
|
11
26
|
}
|
package/src/types.ts
CHANGED
|
@@ -1,16 +1,51 @@
|
|
|
1
|
+
// @needsAudit
|
|
2
|
+
/**
|
|
3
|
+
*
|
|
4
|
+
*/
|
|
1
5
|
export type DocumentPickerOptions = {
|
|
2
|
-
|
|
6
|
+
/**
|
|
7
|
+
* The [MIME type(s)](https://en.wikipedia.org/wiki/Media_type) of the documents that are available
|
|
8
|
+
* to be picked. Is also supports wildcards like `'image/*'` to choose any image. To allow any type
|
|
9
|
+
* of document you can use `'*/*'`.
|
|
10
|
+
* @default `'*/*'`
|
|
11
|
+
*/
|
|
12
|
+
type?: string | string[];
|
|
13
|
+
/**
|
|
14
|
+
* If `true`, the picked file is copied to [`FileSystem.CacheDirectory`](filesystem.md#filesystemcachedirectory),
|
|
15
|
+
* which allows other Expo APIs to read the file immediately. This may impact performance for
|
|
16
|
+
* large files, so you should consider setting this to `false` if you expect users to pick
|
|
17
|
+
* particularly large files and your app does not need immediate read access.
|
|
18
|
+
* @default `true`
|
|
19
|
+
*/
|
|
3
20
|
copyToCacheDirectory?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* __Web Only.__ Allows multiple files to be selected from the system UI.
|
|
23
|
+
* @default `false`
|
|
24
|
+
*/
|
|
4
25
|
multiple?: boolean;
|
|
5
26
|
};
|
|
6
27
|
|
|
28
|
+
// @needsAudit @docsMissing
|
|
7
29
|
export type DocumentResult =
|
|
8
30
|
| { type: 'cancel' }
|
|
9
31
|
| {
|
|
10
32
|
type: 'success';
|
|
33
|
+
/**
|
|
34
|
+
* Document original name.
|
|
35
|
+
*/
|
|
11
36
|
name: string;
|
|
12
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Document size in bytes.
|
|
39
|
+
*/
|
|
40
|
+
size?: number;
|
|
41
|
+
/**
|
|
42
|
+
* An URI to the local document file.
|
|
43
|
+
*/
|
|
13
44
|
uri: string;
|
|
45
|
+
/**
|
|
46
|
+
* Document MIME type.
|
|
47
|
+
*/
|
|
48
|
+
mimeType?: string;
|
|
14
49
|
lastModified?: number;
|
|
15
50
|
file?: File;
|
|
16
51
|
output?: FileList | null;
|