rns-mediapicker 0.1.1 → 0.1.3

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/README.md CHANGED
@@ -1,13 +1,13 @@
1
- # rns-mediapicker
1
+ # 🎵 / 🖼️ / 🎥 rns-mediapicker
2
2
 
3
3
  A **high-performance native media picker** for **React Native** and **Expo**.
4
- Supports **audio, image, and video** selection from **camera or library** with native efficiency, automatic JPEG compression, EXIF-safe dimensions, and transparent-image flattening.
4
+ Supports **audio, image, and video** selection from **camera or library**, automatic JPEG compression, EXIF-safe dimensions, and transparent-image flattening.
5
5
 
6
6
  ---
7
7
 
8
8
  ## 🚀 Installation
9
9
 
10
- Choose one method:
10
+ Choose any method:
11
11
 
12
12
  ```bash
13
13
  yarn add rns-mediapicker
@@ -123,7 +123,8 @@ class FastMediaPickerModule(
123
123
  val fallback =
124
124
  Intent(Intent.ACTION_GET_CONTENT).apply {
125
125
  addCategory(Intent.CATEGORY_OPENABLE)
126
- type =
126
+ // FIXED: Explicitly use this.type to refer to Intent property
127
+ this.type =
127
128
  when (type) {
128
129
  "video" -> "video/*"
129
130
  "image" -> "image/*"
@@ -190,7 +191,8 @@ class FastMediaPickerModule(
190
191
  processMedia(uri)
191
192
  }
192
193
 
193
- override fun onActivityResult(
194
+ // FIXED: Removed 'override' as this signature is no longer in ActivityEventListener
195
+ fun onActivityResult(
194
196
  requestCode: Int,
195
197
  resultCode: Int,
196
198
  data: Intent?,
@@ -33,7 +33,6 @@ class FastMediaPicker: NSObject,
33
33
  let typeLower = mediaType.lowercased()
34
34
 
35
35
  DispatchQueue.main.async {
36
-
37
36
  // 1. AUDIO (Document Picker)
38
37
  if typeLower == "audio" {
39
38
  let picker = UIDocumentPickerViewController(forOpeningContentTypes: [.audio])
@@ -89,7 +88,9 @@ class FastMediaPicker: NSObject,
89
88
 
90
89
  // MARK: - PHPicker
91
90
  func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
92
- picker.dismiss(animated: true)
91
+ DispatchQueue.main.async {
92
+ picker.dismiss(animated: true)
93
+ }
93
94
 
94
95
  guard let result = results.first else {
95
96
  safeReject("E_CANCELLED", "User cancelled")
@@ -98,24 +99,31 @@ class FastMediaPicker: NSObject,
98
99
 
99
100
  let provider = result.itemProvider
100
101
 
102
+ // Check for Video
101
103
  if provider.hasItemConformingToTypeIdentifier(UTType.movie.identifier) {
102
104
  provider.loadFileRepresentation(forTypeIdentifier: UTType.movie.identifier) { [weak self] url, error in
103
- guard let self = self else { return }
104
105
  if let url = url {
105
- self.handlePickedVideo(url: url)
106
+ self?.handlePickedVideo(url: url)
106
107
  } else {
107
- self.safeReject("E_LOAD", error?.localizedDescription ?? "Video load failed")
108
+ self?.safeReject("E_LOAD", error?.localizedDescription ?? "Video load failed")
108
109
  }
109
110
  }
110
111
  return
111
112
  }
112
113
 
114
+ // Check for Image
113
115
  if provider.canLoadObject(ofClass: UIImage.self) {
114
- provider.loadObject(ofClass: UIImage.self) { [weak self] image, _ in
115
- guard let self = self, let img = image as? UIImage else { return }
116
- self.processPickedImage(img)
116
+ provider.loadObject(ofClass: UIImage.self) { [weak self] image, error in
117
+ if let img = image as? UIImage {
118
+ self?.processPickedImage(img)
119
+ } else {
120
+ self?.safeReject("E_LOAD", error?.localizedDescription ?? "Image load failed")
121
+ }
117
122
  }
123
+ return
118
124
  }
125
+
126
+ safeReject("E_NO_MEDIA", "Unsupported media type")
119
127
  }
120
128
 
121
129
  // MARK: - Document Picker (Audio)
@@ -137,15 +145,12 @@ class FastMediaPicker: NSObject,
137
145
  }
138
146
  try FileManager.default.copyItem(at: url, to: fileURL)
139
147
 
140
- DispatchQueue.main.async {
141
- self.resolve?([
142
- "uri": fileURL.absoluteString,
143
- "type": "audio",
144
- "isAudio": true,
145
- "isVideo": false
146
- ])
147
- self.cleanupPromise()
148
- }
148
+ self.safeResolve([
149
+ "uri": fileURL.absoluteString,
150
+ "type": "audio",
151
+ "isAudio": true,
152
+ "isVideo": false
153
+ ])
149
154
  } catch {
150
155
  safeReject("E_AUDIO_COPY", error.localizedDescription)
151
156
  }
@@ -183,34 +188,22 @@ class FastMediaPicker: NSObject,
183
188
  private func processPickedImage(_ image: UIImage) {
184
189
  let fileURL = makeTempURL(ext: "jpg")
185
190
 
186
- let format = UIGraphicsImageRendererFormat()
187
- format.scale = image.scale
188
- format.opaque = true
189
-
190
- let renderer = UIGraphicsImageRenderer(size: image.size, format: format)
191
- let output = renderer.image { ctx in
192
- UIColor.white.setFill()
193
- ctx.fill(CGRect(origin: .zero, size: image.size))
194
- image.draw(at: .zero)
195
- }
196
-
197
- guard let data = output.jpegData(compressionQuality: 0.8) else {
191
+ // Standardize image orientation and convert to Data
192
+ guard let data = image.jpegData(compressionQuality: 0.8) else {
198
193
  safeReject("E_IMAGE_WRITE", "Image encoding failed")
199
194
  return
200
195
  }
201
196
 
202
197
  do {
203
198
  try data.write(to: fileURL)
204
- DispatchQueue.main.async {
205
- self.resolve?([
206
- "uri": fileURL.absoluteString,
207
- "width": image.size.width,
208
- "height": image.size.height,
209
- "type": "image",
210
- "isVideo": false
211
- ])
212
- self.cleanupPromise()
213
- }
199
+ self.safeResolve([
200
+ "uri": fileURL.absoluteString,
201
+ "width": image.size.width,
202
+ "height": image.size.height,
203
+ "type": "image",
204
+ "isAudio": false,
205
+ "isVideo": false
206
+ ])
214
207
  } catch {
215
208
  safeReject("E_IMAGE_WRITE", error.localizedDescription)
216
209
  }
@@ -224,19 +217,18 @@ class FastMediaPicker: NSObject,
224
217
  if FileManager.default.fileExists(atPath: fileURL.path) {
225
218
  try FileManager.default.removeItem(at: fileURL)
226
219
  }
220
+ // PHPicker provides a temporary URL that may be deleted; we MUST copy it
227
221
  try FileManager.default.copyItem(at: url, to: fileURL)
228
222
 
229
223
  let dims = videoDimensions(for: fileURL)
230
- DispatchQueue.main.async {
231
- self.resolve?([
232
- "uri": fileURL.absoluteString,
233
- "width": dims.width,
234
- "height": dims.height,
235
- "type": "video",
236
- "isVideo": true
237
- ])
238
- self.cleanupPromise()
239
- }
224
+ self.safeResolve([
225
+ "uri": fileURL.absoluteString,
226
+ "width": dims.width,
227
+ "height": dims.height,
228
+ "type": "video",
229
+ "isAudio": false,
230
+ "isVideo": true
231
+ ])
240
232
  } catch {
241
233
  safeReject("E_VIDEO_COPY", error.localizedDescription)
242
234
  }
@@ -247,6 +239,13 @@ class FastMediaPicker: NSObject,
247
239
  safeReject("E_CANCELLED", "User cancelled via swipe")
248
240
  }
249
241
 
242
+ private func safeResolve(_ result: [String: Any]) {
243
+ DispatchQueue.main.async {
244
+ self.resolve?(result)
245
+ self.cleanupPromise()
246
+ }
247
+ }
248
+
250
249
  private func safeReject(_ code: String, _ message: String) {
251
250
  DispatchQueue.main.async {
252
251
  self.reject?(code, message, nil)
@@ -285,4 +284,4 @@ class FastMediaPicker: NSObject,
285
284
  let size = track.naturalSize.applying(track.preferredTransform)
286
285
  return (abs(size.width), abs(size.height))
287
286
  }
288
- }
287
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rns-mediapicker",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
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",