rns-mediapicker 0.0.5 → 0.0.6

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.
@@ -50,7 +50,7 @@ class FastMediaPickerModule(
50
50
 
51
51
  // -------------------- PUBLIC API --------------------
52
52
 
53
- @ReactMethod
53
+ @ReactMethod
54
54
  fun pick(
55
55
  useCamera: Boolean,
56
56
  mediaType: String,
@@ -72,18 +72,60 @@ class FastMediaPickerModule(
72
72
  val permissions = mutableListOf<String>()
73
73
 
74
74
  if (useCamera) {
75
+ // Camera always needs permission
75
76
  permissions.add(Manifest.permission.CAMERA)
77
+ } else {
78
+ // GALLERY LOGIC:
79
+ // Android 13 (API 33) and above use the Photo Picker which REQUIRES NO PERMISSIONS.
80
+ // We only request storage permissions for older devices (API 32 and below).
81
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
82
+ permissions.add(Manifest.permission.READ_EXTERNAL_STORAGE)
83
+ }
76
84
  }
77
85
 
78
- if (Build.VERSION.SDK_INT >= 33) {
79
- permissions.add(
80
- if (mediaType == "video") {
81
- Manifest.permission.READ_MEDIA_VIDEO
82
- } else {
83
- Manifest.permission.READ_MEDIA_IMAGES
84
- },
86
+ // Filter out permissions that are already granted
87
+ val missing = permissions.filter {
88
+ activity.checkSelfPermission(it) != android.content.pm.PackageManager.PERMISSION_GRANTED
89
+ }
90
+
91
+ if (missing.isNotEmpty()) {
92
+ val pa = activity as? PermissionAwareActivity ?: run {
93
+ promise.reject("E_NOT_PERMISSION_AWARE", "Activity not PermissionAware")
94
+ cleanup()
95
+ return
96
+ }
97
+
98
+ pa.requestPermissions(
99
+ missing.toTypedArray(),
100
+ PERMISSION_REQUEST,
101
+ this,
85
102
  )
86
- } else {
103
+ return
104
+ }
105
+
106
+ // All permissions granted (or none needed), launch the picker/camera
107
+ launch(activity)
108
+ }
109
+
110
+ // Android 14 (API 34+) introduces Partial Access
111
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
112
+ permissions.add(Manifest.permission.READ_MEDIA_IMAGES)
113
+ permissions.add(Manifest.permission.READ_MEDIA_VIDEO)
114
+ permissions.add(Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED)
115
+ }
116
+ // Android 13 (API 33)
117
+ else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
118
+ if (mediaType == "video") {
119
+ permissions.add(Manifest.permission.READ_MEDIA_VIDEO)
120
+ } else if (mediaType == "image") {
121
+ permissions.add(Manifest.permission.READ_MEDIA_IMAGES)
122
+ } else {
123
+ permissions.add(Manifest.permission.READ_MEDIA_IMAGES)
124
+ permissions.add(Manifest.permission.READ_MEDIA_VIDEO)
125
+ }
126
+ }
127
+ // Android 12 and below
128
+ else {
87
129
  permissions.add(Manifest.permission.READ_EXTERNAL_STORAGE)
88
130
  }
89
131
 
@@ -145,23 +187,46 @@ class FastMediaPickerModule(
145
187
  activity: Activity,
146
188
  type: String,
147
189
  ) {
190
+ // 1. Try the Modern Photo Picker (Android 13+ or backported to 11+)
191
+ // We check for the action string directly to handle backported devices
148
192
  val intent =
149
- if (Build.VERSION.SDK_INT >= 33) {
150
- Intent(MediaStore.ACTION_PICK_IMAGES)
151
- } else {
152
- Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
153
- addCategory(Intent.CATEGORY_OPENABLE)
193
+ Intent("android.provider.action.PICK_IMAGES").apply {
194
+ when (type) {
195
+ "video" -> this.type = "video/*"
196
+ "image" -> this.type = "image/*"
197
+ // For 'both', we leave the type null or specify multiple if needed
154
198
  }
155
199
  }
156
200
 
157
- intent.type =
158
- when (type) {
159
- "video" -> "video/*"
160
- else -> "image/*"
161
- }
201
+ try {
202
+ activity.startActivityForResult(intent, PICKER_REQUEST_CODE)
203
+ } catch (e: Exception) {
204
+ // 2. Fallback: Legacy ACTION_GET_CONTENT (Android 10 and below, or failed 13+)
205
+ val fallbackIntent =
206
+ Intent(Intent.ACTION_GET_CONTENT).apply {
207
+ addCategory(Intent.CATEGORY_OPENABLE)
208
+ this.type =
209
+ when (type) {
210
+ "video" -> "video/*"
211
+ "image" -> "image/*"
212
+ else -> "*/*" // 'both' case
213
+ }
214
+ // Allow both images and videos in the legacy picker if 'both' is selected
215
+ if (type == "both") {
216
+ putExtra(Intent.EXTRA_MIME_TYPES, arrayOf("image/*", "video/*"))
217
+ }
218
+ }
162
219
 
163
- intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
164
- activity.startActivityForResult(intent, PICKER_REQUEST_CODE)
220
+ try {
221
+ activity.startActivityForResult(
222
+ Intent.createChooser(fallbackIntent, "Select Media"),
223
+ PICKER_REQUEST_CODE,
224
+ )
225
+ } catch (fallbackEx: Exception) {
226
+ pickerPromise?.reject("E_NO_PICKER", "No app available to pick media")
227
+ cleanup()
228
+ }
229
+ }
165
230
  }
166
231
 
167
232
  private fun launchCamera(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rns-mediapicker",
3
- "version": "0.0.5",
3
+ "version": "0.0.6",
4
4
  "description": "High-performance React Native module for picking media on Android and iOS.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",