react-native-my-uploader-android 1.0.28 → 1.0.30

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.
Files changed (32) hide show
  1. package/android/src/main/java/com/myuploaderandroid/DownloadFileModule.kt +91 -58
  2. package/android/src/main/java/com/myuploaderandroid/MyUploaderModule.kt +93 -42
  3. package/lib/commonjs/components/DownloadFile.js +37 -47
  4. package/lib/commonjs/components/DownloadFile.js.map +1 -1
  5. package/lib/commonjs/components/MyUploader.js +57 -80
  6. package/lib/commonjs/components/MyUploader.js.map +1 -1
  7. package/lib/commonjs/index.d.js.map +1 -1
  8. package/lib/commonjs/index.js +9 -7
  9. package/lib/commonjs/index.js.map +1 -1
  10. package/lib/commonjs/types.js.map +1 -1
  11. package/lib/module/components/DownloadFile.js +38 -48
  12. package/lib/module/components/DownloadFile.js.map +1 -1
  13. package/lib/module/components/MyUploader.js +55 -79
  14. package/lib/module/components/MyUploader.js.map +1 -1
  15. package/lib/module/index.d.js +10 -0
  16. package/lib/module/index.d.js.map +1 -1
  17. package/lib/module/index.js +10 -6
  18. package/lib/module/index.js.map +1 -1
  19. package/lib/module/types.js.map +1 -1
  20. package/package.json +1 -1
  21. package/src/components/DownloadFile.tsx +40 -61
  22. package/src/components/MyUploader.tsx +59 -89
  23. package/src/index.d.ts +12 -5
  24. package/src/index.ts +12 -6
  25. package/src/types.ts +98 -41
  26. package/android/src/main/java/com/myuploader/MyUploaderModule.kt +0 -173
  27. package/android/src/main/java/com/myuploader/MyUploaderPackage.kt +0 -16
  28. package/lib/commonjs/NativeMyUploader.js +0 -15
  29. package/lib/commonjs/NativeMyUploader.js.map +0 -1
  30. package/lib/module/NativeMyUploader.js +0 -9
  31. package/lib/module/NativeMyUploader.js.map +0 -1
  32. package/src/NativeMyUploader.ts +0 -25
@@ -12,54 +12,70 @@ import android.util.Log
12
12
  import android.webkit.CookieManager
13
13
  import android.webkit.URLUtil
14
14
  import com.facebook.react.bridge.*
15
- import com.myuploaderandroid.BuildConfig
15
+ import java.io.File
16
16
  import java.net.HttpURLConnection
17
17
  import java.net.URL
18
+ import java.util.concurrent.ConcurrentHashMap
18
19
 
19
20
  class DownloadFileModule(private val reactContext: ReactApplicationContext) :
20
21
  ReactContextBaseJavaModule(reactContext) {
21
22
 
22
23
  private val TAG = "DownloadFileModule"
23
- private val downloadPromises = mutableMapOf<Long, Promise>()
24
+ private val downloadPromises = ConcurrentHashMap<Long, Promise>()
24
25
 
25
- override fun getName(): String = "DownloadFile"
26
-
27
- init {
28
- val receiver = object : BroadcastReceiver() {
29
- override fun onReceive(context: Context, intent: Intent) {
30
- val downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
31
- if (downloadPromises.containsKey(downloadId)) {
32
- val promise = downloadPromises[downloadId]
26
+ private val receiver: BroadcastReceiver = object : BroadcastReceiver() {
27
+ override fun onReceive(context: Context, intent: Intent) {
28
+ val downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
29
+ if (downloadId != -1L) {
30
+ downloadPromises.remove(downloadId)?.let { promise ->
33
31
  checkDownloadStatus(downloadId, promise)
34
- downloadPromises.remove(downloadId)
35
32
  }
36
33
  }
37
34
  }
35
+ }
36
+
37
+ override fun getName(): String = "DownloadFile"
38
+
39
+ init {
38
40
  val intentFilter = IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
39
41
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
40
- reactContext.registerReceiver(receiver, intentFilter, Context.RECEIVER_NOT_EXPORTED)
42
+ reactContext.registerReceiver(receiver, intentFilter, Context.RECEIVER_NOT_EXPORTED)
41
43
  } else {
42
- reactContext.registerReceiver(receiver, intentFilter)
44
+ reactContext.registerReceiver(receiver, intentFilter)
43
45
  }
44
46
  }
45
47
 
48
+ override fun onCatalystInstanceDestroy() {
49
+ try {
50
+ reactContext.unregisterReceiver(receiver)
51
+ } catch (e: Exception) {
52
+ Log.w(TAG, "Receiver unregister warning: ${e.message}")
53
+ }
54
+ super.onCatalystInstanceDestroy()
55
+ }
56
+
46
57
  @ReactMethod
47
58
  fun downloadFile(fileUrl: String, options: ReadableMap, promise: Promise) {
48
59
  val isDebug = if (options.hasKey("debug")) options.getBoolean("debug") else false
49
- val shouldLog = BuildConfig.DEBUG && isDebug
50
60
  val maxSizeMB = if (options.hasKey("maxSize")) options.getDouble("maxSize") else 0.0
61
+
62
+ // Allowed File Types (Mime Types)
63
+ val allowedTypes = if (options.hasKey("fileTypes")) {
64
+ options.getArray("fileTypes")?.toArrayList()?.mapNotNull { it.toString() } ?: emptyList()
65
+ } else emptyList()
51
66
 
52
- if (shouldLog) Log.d(TAG, "İndirme isteği alındı. URL: $fileUrl")
67
+ if (isDebug) Log.d(TAG, "İndirme başlatılıyor: $fileUrl")
53
68
 
54
69
  Thread {
70
+ var connection: HttpURLConnection? = null
55
71
  try {
56
72
  val url = URL(fileUrl)
57
- val connection = url.openConnection() as HttpURLConnection
73
+ connection = url.openConnection() as HttpURLConnection
58
74
  val cookie = CookieManager.getInstance().getCookie(fileUrl)
59
75
  if (cookie != null) connection.setRequestProperty("Cookie", cookie)
60
- connection.requestMethod = "HEAD"
76
+ connection.requestMethod = "HEAD" // Sadece başlıkları çek
61
77
  connection.connect()
62
-
78
+
63
79
  val responseCode = connection.responseCode
64
80
  if (responseCode !in 200..299) {
65
81
  promise.reject("E_HTTP_ERROR", "Sunucu hatası: $responseCode")
@@ -68,22 +84,49 @@ class DownloadFileModule(private val reactContext: ReactApplicationContext) :
68
84
 
69
85
  val fileSize = connection.contentLengthLong
70
86
  val contentType = connection.contentType
71
- val contentDisposition = connection.getHeaderField("Content-Disposition")
72
87
  val cleanContentType = contentType?.split(";")?.get(0)?.trim() ?: "*/*"
88
+
89
+ // 1. Content-Type Kontrolü
90
+ if (allowedTypes.isNotEmpty() && !allowedTypes.contains("*/*")) {
91
+ var isAllowed = false
92
+ for (type in allowedTypes) {
93
+ if (type == "*/*" || cleanContentType.equals(type, ignoreCase = true) || cleanContentType.startsWith(type.replace("*", ""))) {
94
+ isAllowed = true
95
+ break
96
+ }
97
+ }
98
+ if (!isAllowed) {
99
+ promise.reject("E_INVALID_FILE_TYPE", "Dosya türü ($cleanContentType) izin verilenler listesinde yok.")
100
+ return@Thread
101
+ }
102
+ }
103
+
104
+ // 2. Boyut Kontrolü
105
+ if (maxSizeMB > 0 && fileSize > 0 && fileSize > maxSizeMB * 1024 * 1024) {
106
+ promise.reject("E_FILE_TOO_LARGE", "Dosya boyutu (${(fileSize / 1024.0 / 1024.0).toInt()}MB) limitin (${maxSizeMB}MB) üzerinde.")
107
+ return@Thread
108
+ }
109
+
110
+ val contentDisposition = connection.getHeaderField("Content-Disposition")
73
111
  val fileName = URLUtil.guessFileName(fileUrl, contentDisposition, cleanContentType)
74
112
 
75
- if (shouldLog) Log.d(TAG, "Dosya: $fileName, Boyut: $fileSize bytes, Tip: $cleanContentType")
113
+ // Dosya Adı Çakışma Önleme
114
+ val downloadsDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
115
+ val baseName = fileName.substringBeforeLast(".")
116
+ val ext = fileName.substringAfterLast(".", "")
117
+ var counter = 1
118
+ var finalFileName = fileName
76
119
 
77
- if (maxSizeMB > 0 && fileSize > maxSizeMB * 1024 * 1024) {
78
- promise.reject("E_FILE_TOO_LARGE", "Dosya boyutu (${(fileSize / 1024.0 / 1024.0).toInt()}MB) belirtilen limitten (${maxSizeMB}MB) büyük.")
79
- return@Thread
120
+ while (File(downloadsDir, finalFileName).exists()) {
121
+ finalFileName = if (ext.isNotEmpty()) "$baseName($counter).$ext" else "$baseName($counter)"
122
+ counter++
80
123
  }
81
124
 
82
125
  val request = DownloadManager.Request(Uri.parse(fileUrl))
83
- .setTitle(fileName)
84
- .setDescription("İndiriliyor...")
126
+ .setTitle(finalFileName)
127
+ .setDescription("Dosya indiriliyor...")
85
128
  .setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
86
- .setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName)
129
+ .setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, finalFileName)
87
130
  .setAllowedOverMetered(true)
88
131
 
89
132
  if (cookie != null) request.addRequestHeader("Cookie", cookie)
@@ -91,13 +134,13 @@ class DownloadFileModule(private val reactContext: ReactApplicationContext) :
91
134
 
92
135
  val downloadManager = reactContext.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
93
136
  val downloadId = downloadManager.enqueue(request)
94
-
95
- if (BuildConfig.DEBUG) Log.i(TAG, "İndirme sıraya eklendi. ID: #$downloadId")
137
+
96
138
  downloadPromises[downloadId] = promise
97
139
 
98
140
  } catch (e: Exception) {
99
- if (BuildConfig.DEBUG) Log.e(TAG, "İndirme başlatılırken hata!", e)
100
141
  promise.reject("E_DOWNLOAD_SETUP_FAILED", e.message)
142
+ } finally {
143
+ connection?.disconnect()
101
144
  }
102
145
  }.start()
103
146
  }
@@ -107,38 +150,28 @@ class DownloadFileModule(private val reactContext: ReactApplicationContext) :
107
150
  val query = DownloadManager.Query().setFilterById(id)
108
151
  val cursor = downloadManager.query(query)
109
152
 
110
- if (cursor.moveToFirst()) {
111
- val statusIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)
112
- val status = cursor.getInt(statusIndex)
153
+ if (cursor == null) {
154
+ promise?.reject("E_DB_CURSOR_NULL", "Download cursor null")
155
+ return
156
+ }
113
157
 
114
- if (status == DownloadManager.STATUS_SUCCESSFUL) {
115
- val uriIndex = cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)
116
- val localUri = cursor.getString(uriIndex)
117
- promise?.resolve(localUri)
158
+ cursor.use {
159
+ if (it.moveToFirst()) {
160
+ val statusIndex = it.getColumnIndex(DownloadManager.COLUMN_STATUS)
161
+ val status = if (statusIndex >= 0) it.getInt(statusIndex) else DownloadManager.STATUS_FAILED
162
+
163
+ if (status == DownloadManager.STATUS_SUCCESSFUL) {
164
+ val uriIndex = it.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)
165
+ val localUri = if (uriIndex >= 0) it.getString(uriIndex) else null
166
+ promise?.resolve(localUri)
167
+ } else {
168
+ val reasonIndex = it.getColumnIndex(DownloadManager.COLUMN_REASON)
169
+ val reason = if (reasonIndex >= 0) it.getInt(reasonIndex) else -1
170
+ promise?.reject("E_DOWNLOAD_FAILED", "İndirme başarısız kod: $reason")
171
+ }
118
172
  } else {
119
- val reasonIndex = cursor.getColumnIndex(DownloadManager.COLUMN_REASON)
120
- val reason = cursor.getInt(reasonIndex)
121
- val reasonText = getDownloadErrorReason(reason)
122
- promise?.reject("E_DOWNLOAD_FAILED", "İndirme başarısız. Sebep: $reasonText (Kod: $reason)")
173
+ promise?.reject("E_DOWNLOAD_NOT_FOUND", "İndirme kaydı bulunamadı.")
123
174
  }
124
- } else {
125
- promise?.reject("E_DOWNLOAD_NOT_FOUND", "İndirme işlemi bulunamadı.")
126
- }
127
- cursor.close()
128
- }
129
-
130
- private fun getDownloadErrorReason(reasonCode: Int): String {
131
- return when (reasonCode) {
132
- DownloadManager.ERROR_CANNOT_RESUME -> "İndirme devam ettirilemiyor."
133
- DownloadManager.ERROR_DEVICE_NOT_FOUND -> "Harici depolama bulunamadı."
134
- DownloadManager.ERROR_FILE_ALREADY_EXISTS -> "Aynı isimde bir dosya zaten var."
135
- DownloadManager.ERROR_FILE_ERROR -> "Dosya sistemi hatası."
136
- DownloadManager.ERROR_HTTP_DATA_ERROR -> "Sunucu ile veri alışverişinde hata."
137
- DownloadManager.ERROR_INSUFFICIENT_SPACE -> "Cihazda yeterli alan yok."
138
- DownloadManager.ERROR_TOO_MANY_REDIRECTS -> "Çok fazla yönlendirme yapıldı."
139
- DownloadManager.ERROR_UNHANDLED_HTTP_CODE -> "Sunucudan beklenmeyen HTTP kodu alındı."
140
- DownloadManager.ERROR_UNKNOWN -> "Bilinmeyen bir hata oluştu."
141
- else -> "Bilinmeyen hata."
142
175
  }
143
176
  }
144
177
  }
@@ -21,7 +21,7 @@ class MyUploaderModule(private val reactContext: ReactApplicationContext) :
21
21
  reactContext.addActivityEventListener(this)
22
22
  }
23
23
 
24
- override fun getName(): String = "DocumentPicker"
24
+ override fun getName(): String = "UploadDocumentPicker"
25
25
 
26
26
  companion object {
27
27
  private const val REQUEST_CODE = 9900
@@ -94,37 +94,51 @@ class MyUploaderModule(private val reactContext: ReactApplicationContext) :
94
94
  }
95
95
 
96
96
  override fun onActivityResult(activity: Activity, requestCode: Int, resultCode: Int, data: Intent?) {
97
- if (requestCode != REQUEST_CODE || pickerPromise == null) { return }
97
+ if (requestCode != REQUEST_CODE || pickerPromise == null) { return }
98
98
 
99
- if (resultCode == Activity.RESULT_OK && data != null) {
100
- val allSelectedUris = mutableListOf<Uri>()
101
- data.clipData?.let { clip ->
102
- for (i in 0 until clip.itemCount) {
103
- allSelectedUris.add(clip.getItemAt(i).uri)
104
- }
105
- } ?: data.data?.let { uri ->
106
- allSelectedUris.add(uri)
107
- }
108
-
109
- val newSelectedUris = allSelectedUris.filter { uri -> !excludedUris.contains(uri.toString()) }
99
+ val currentPromise = pickerPromise
100
+ pickerPromise = null
110
101
 
111
- if (this.maxFiles > 0 && newSelectedUris.size > this.maxFiles) {
112
- pickerPromise?.reject(E_MAX_FILES_EXCEEDED, "En fazla ${this.maxFiles} adet yeni dosya seçebilirsiniz.")
113
- pickerPromise = null
114
- return
102
+ if (resultCode == Activity.RESULT_OK && data != null) {
103
+ val allSelectedUris = mutableListOf<Uri>()
104
+ data.clipData?.let { clip ->
105
+ for (i in 0 until clip.itemCount) {
106
+ allSelectedUris.add(clip.getItemAt(i).uri)
115
107
  }
108
+ } ?: data.data?.let { uri ->
109
+ allSelectedUris.add(uri)
110
+ }
111
+
112
+ val newSelectedUris = allSelectedUris.filter { uri -> !excludedUris.contains(uri.toString()) }
113
+
114
+ if (this.maxFiles > 0 && newSelectedUris.size > this.maxFiles) {
115
+ currentPromise?.reject(E_MAX_FILES_EXCEEDED, "En fazla ${this.maxFiles} adet yeni dosya seçebilirsiniz.")
116
+ return
117
+ }
116
118
 
119
+ Thread {
117
120
  try {
118
121
  val fileInfoArray = processSelectedFiles(newSelectedUris)
119
- pickerPromise?.resolve(fileInfoArray)
122
+ // Sonucu UI thread'inde Promise'e gönder
123
+ reactContext.runOnUiQueueThread {
124
+ currentPromise?.resolve(fileInfoArray)
125
+ }
120
126
  } catch (e: Exception) {
121
- pickerPromise?.reject(E_FILE_TOO_LARGE, e.message)
127
+ // Hataları UI thread'inde Promise'e gönder
128
+ reactContext.runOnUiQueueThread {
129
+ when (e) {
130
+ is FileTooLargeException -> currentPromise?.reject(E_FILE_TOO_LARGE, e.message)
131
+ is FileNotFoundException -> currentPromise?.reject(E_FAILED_TO_OPEN_DOCUMENT, "Dosya bulunamadı veya erişilemedi.")
132
+ else -> currentPromise?.reject(E_FAILED_TO_OPEN_DOCUMENT, e.message)
133
+ }
134
+ }
122
135
  }
123
- } else {
124
- pickerPromise?.reject(E_PICKER_CANCELLED, "Dosya seçimi iptal edildi.")
125
- }
126
- pickerPromise = null
136
+ }.start()
137
+ } else {
138
+ currentPromise?.reject(E_PICKER_CANCELLED, "Dosya seçimi iptal edildi.")
127
139
  }
140
+ }
141
+
128
142
 
129
143
  override fun onNewIntent(intent: Intent) {}
130
144
 
@@ -135,39 +149,76 @@ class MyUploaderModule(private val reactContext: ReactApplicationContext) :
135
149
  for (uri in uris) {
136
150
  reactContext.contentResolver.query(uri, null, null, null, null)?.use { cursor ->
137
151
  if (cursor.moveToFirst()) {
138
- val fileNameIndex = cursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME)
139
- val fileSizeIndex = cursor.getColumnIndexOrThrow(OpenableColumns.SIZE)
140
- val fileName = cursor.getString(fileNameIndex)
141
- val fileSize = cursor.getLong(fileSizeIndex)
152
+ val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
153
+ val sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE)
142
154
 
143
- if (maxSizeBytes > 0 && fileSize > maxSizeBytes) {
144
- throw Exception("Seçilen dosya ($fileName) belirtilen ${maxSize}MB boyutundan büyük.")
145
- }
155
+ val fileName = if (nameIndex != -1) cursor.getString(nameIndex) else guessFileNameFromUri(uri)
156
+ val fileSize = if (sizeIndex != -1) cursor.getLong(sizeIndex) else -1L
146
157
 
147
- val mimeType = getMimeType(fileName)
148
- val base64 = reactContext.contentResolver.openInputStream(uri)?.use { inputStream ->
149
- val byteBuffer = ByteArrayOutputStream()
150
- val buffer = ByteArray(1024)
151
- var len: Int
152
- while (inputStream.read(buffer).also { len = it } != -1) {
153
- byteBuffer.write(buffer, 0, len)
158
+ var trueSize = -1L
159
+ try {
160
+ reactContext.contentResolver.openAssetFileDescriptor(uri, "r")?.use { afd ->
161
+ trueSize = afd.length
154
162
  }
155
- Base64.encodeToString(byteBuffer.toByteArray(), Base64.NO_WRAP)
163
+ } catch (e: FileNotFoundException) {
164
+ // Bazı durumlarda bu metod hata verebilir, görmezden gel ve devam et
165
+ }
166
+
167
+ if (trueSize <= 0) trueSize = fileSize
168
+
169
+ if (maxSizeBytes > 0 && trueSize > 0 && trueSize > maxSizeBytes) {
170
+ throw FileTooLargeException("Seçilen dosya ($fileName) belirtilen ${maxSize}MB boyutundan büyük.")
156
171
  }
157
172
 
173
+ val mimeType = reactContext.contentResolver.getType(uri) ?: URLConnection.guessContentTypeFromName(fileName) ?: "application/octet-stream"
174
+ val base64 = encodeFileToBase64(uri)
175
+
158
176
  val fileMap = WritableNativeMap().apply {
159
177
  putString("fileName", fileName)
160
- putDouble("fileSize", fileSize.toDouble())
178
+ putDouble("fileSize", if (trueSize > 0) trueSize.toDouble() else fileSize.toDouble())
161
179
  putString("fileType", mimeType)
162
180
  putString("fileUri", uri.toString())
163
181
  putString("base64", base64)
164
182
  }
165
183
  fileObjects.pushMap(fileMap)
166
184
  }
167
- }
185
+ } ?:throw FileNotFoundException("Content ile dosya bilgisi alınamadı:$uri")
168
186
  }
169
187
  return fileObjects
170
188
  }
171
-
172
- private fun getMimeType(fileName: String): String? = URLConnection.guessContentTypeFromName(fileName)
189
+
190
+ private fun guessFileNameFromUri (uri:Uri):String{
191
+ return uri.lastPathSegment?.substringBefore("?") ?: "unknown_file"
192
+ }
193
+
194
+ // OOM riskini azaltan, streaming tabanlı Base64 çevrimi
195
+ private fun encodeFileToBase64(uri: Uri): String? {
196
+ return try {
197
+ reactContext.contentResolver.openInputStream(uri)?.use { input ->
198
+ val output = ByteArrayOutputStream()
199
+ val encoder = Base64OutputStream(output, Base64.NO_WRAP)
200
+
201
+ // Dosyayı parça parça oku ve anlık olarak Base64'e çevir
202
+ input.copyTo(encoder)
203
+ // .copyTo() encoder'ı otomatik olarak kapatır (flush eder).
204
+
205
+ // DÜZELTME: Doğrudan `output.toString()` değil,
206
+ // `Base64.encodeToString` kullan. Ancak bu gereksiz bir adımdır,
207
+ // çünkü `output` zaten Base64'tür. En basit yol:
208
+ String(output.toByteArray(), Charsets.US_ASCII)
209
+ }
210
+ } catch (e: Exception) {
211
+ null
212
+ }
213
+ }
214
+
215
+ override fun onCatalystInstanceDestroy() {
216
+ // Bellek sızıntısını önlemek için event listener'ı kaldır.
217
+ reactContext.removeActivityEventListener(this)
218
+ super.onCatalystInstanceDestroy()
219
+ }
220
+
221
+ // Özel Exception sınıfınız doğru
222
+ class FileTooLargeException(message: String) : Exception(message)
223
+
173
224
  }
@@ -8,11 +8,11 @@ var _react = _interopRequireWildcard(require("react"));
8
8
  var _reactNative = require("react-native");
9
9
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
10
10
  const {
11
- DownloadFile: DownloadFileModule
11
+ DownloadFile: NativeDownload
12
12
  } = _reactNative.NativeModules;
13
13
  const DownloadFile = ({
14
14
  files,
15
- multipleLoad = false,
15
+ multipleDownload = false,
16
16
  disabled = false,
17
17
  debug = false,
18
18
  maxSize = 0,
@@ -21,82 +21,72 @@ const DownloadFile = ({
21
21
  buttonIcon,
22
22
  ButtonStyle,
23
23
  ButtonTextStyle,
24
- onSuccess = () => {},
25
- onError = error => console.error('DownloadFile Error:', error)
24
+ onSuccess,
25
+ onError
26
26
  }) => {
27
27
  const [isLoading, setIsLoading] = (0, _react.useState)(false);
28
28
  const handlePress = async () => {
29
- if (!DownloadFileModule) {
30
- onError(new Error("DownloadFile native module is not available."));
31
- return;
32
- }
29
+ if (disabled || isLoading || !files.length) return;
33
30
  setIsLoading(true);
34
- const downloadOptions = {
31
+ const options = {
32
+ debug,
35
33
  maxSize,
36
- fileTypes,
37
- debug
34
+ fileTypes
38
35
  };
36
+ const targetFiles = multipleDownload ? files : [files[0]];
39
37
  try {
40
- const filesToProcess = multipleLoad ? files : files.slice(0, 1);
41
- const downloadPromises = filesToProcess.map(url => DownloadFileModule.downloadFile(url, downloadOptions));
42
- const settledResults = await Promise.allSettled(downloadPromises);
43
- const finalResult = {
38
+ const promises = targetFiles.map(url => NativeDownload.downloadFile(url, options));
39
+ const results = await Promise.allSettled(promises);
40
+ const final = {
44
41
  successful: [],
45
42
  skipped: []
46
43
  };
47
- settledResults.forEach((result, index) => {
48
- // DÜZELTME: `filesToProcess[index]` ifadesinin sonuna `!` ekleyerek
49
- // TypeScript'e bu değerin asla undefined olmayacağını bildiriyoruz.
50
- const originalUrl = filesToProcess[index];
51
- if (result.status === 'fulfilled') {
52
- finalResult.successful.push({
44
+ results.forEach((res, index) => {
45
+ var _targetFiles$index;
46
+ const originalUrl = (_targetFiles$index = targetFiles[index]) !== null && _targetFiles$index !== void 0 ? _targetFiles$index : "";
47
+ if (res.status === 'fulfilled') {
48
+ final.successful.push({
53
49
  originalUrl,
54
- // Artık hata vermeyecek
55
- localUri: result.value
50
+ localUri: res.value
56
51
  });
57
52
  } else {
58
- finalResult.skipped.push({
53
+ var _res$reason;
54
+ final.skipped.push({
59
55
  originalUrl,
60
- // Artık hata vermeyecek
61
- reason: result.reason.message
56
+ reason: ((_res$reason = res.reason) === null || _res$reason === void 0 ? void 0 : _res$reason.message) || "Bilinmeyen Hata"
62
57
  });
63
58
  }
64
59
  });
65
- onSuccess(finalResult);
66
- } catch (error) {
67
- onError(error);
60
+ if (onSuccess) onSuccess(final);
61
+ } catch (e) {
62
+ if (onError) onError(e);else console.error(e);
68
63
  } finally {
69
64
  setIsLoading(false);
70
65
  }
71
66
  };
72
- const content = isLoading ? /*#__PURE__*/_react.default.createElement(_reactNative.ActivityIndicator, {
73
- color: "#FFFFFF"
74
- }) : buttonIcon || /*#__PURE__*/_react.default.createElement(_reactNative.Text, {
75
- style: [styles.buttonText, ButtonTextStyle]
76
- }, buttonPlaceHolder);
77
67
  return /*#__PURE__*/_react.default.createElement(_reactNative.TouchableOpacity, {
78
- style: [styles.button, ButtonStyle, (disabled || isLoading) && styles.disabledButton],
68
+ style: [styles.button, ButtonStyle, (disabled || isLoading) && styles.disabled],
79
69
  onPress: handlePress,
80
70
  disabled: disabled || isLoading
81
- }, content);
71
+ }, isLoading ? /*#__PURE__*/_react.default.createElement(_reactNative.ActivityIndicator, {
72
+ color: "#FFF"
73
+ }) : buttonIcon ? buttonIcon : /*#__PURE__*/_react.default.createElement(_reactNative.Text, {
74
+ style: [styles.text, ButtonTextStyle]
75
+ }, buttonPlaceHolder));
82
76
  };
83
77
  const styles = _reactNative.StyleSheet.create({
84
78
  button: {
85
- backgroundColor: '#008CBA',
86
- paddingHorizontal: 20,
87
- paddingVertical: 10,
79
+ backgroundColor: '#03DAC6',
80
+ padding: 12,
88
81
  borderRadius: 8,
89
- alignItems: 'center',
90
- justifyContent: 'center',
91
- flexDirection: 'row'
82
+ alignItems: 'center'
92
83
  },
93
- buttonText: {
94
- color: '#FFFFFF',
95
- fontSize: 16,
84
+ text: {
85
+ color: '#000',
96
86
  fontWeight: 'bold'
97
87
  },
98
- disabledButton: {
99
- backgroundColor: '#A9A9A9'
88
+ disabled: {
89
+ backgroundColor: '#AAA'
100
90
  }
101
91
  });
102
92
  var _default = exports.default = DownloadFile;
@@ -1 +1 @@
1
- {"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","DownloadFile","DownloadFileModule","NativeModules","files","multipleLoad","disabled","debug","maxSize","fileTypes","buttonPlaceHolder","buttonIcon","ButtonStyle","ButtonTextStyle","onSuccess","onError","error","console","isLoading","setIsLoading","useState","handlePress","Error","downloadOptions","filesToProcess","slice","downloadPromises","map","url","downloadFile","settledResults","Promise","allSettled","finalResult","successful","skipped","forEach","result","index","originalUrl","status","push","localUri","value","reason","message","content","createElement","ActivityIndicator","color","Text","style","styles","buttonText","TouchableOpacity","button","disabledButton","onPress","StyleSheet","create","backgroundColor","paddingHorizontal","paddingVertical","borderRadius","alignItems","justifyContent","flexDirection","fontSize","fontWeight","_default","exports"],"sources":["DownloadFile.tsx"],"sourcesContent":["import React, { useState } from 'react';\r\nimport { NativeModules, TouchableOpacity, Text, StyleSheet, ActivityIndicator } from 'react-native';\r\nimport type { DownloadFileProps, DownloadResult } from '../types';\r\n\r\nconst { DownloadFile: DownloadFileModule } = NativeModules;\r\n\r\nconst DownloadFile: React.FC<DownloadFileProps> = ({\r\n files,\r\n multipleLoad = false,\r\n disabled = false,\r\n debug = false,\r\n maxSize = 0,\r\n fileTypes = ['*/*'],\r\n buttonPlaceHolder = 'Dosyaları İndir',\r\n buttonIcon,\r\n ButtonStyle,\r\n ButtonTextStyle,\r\n onSuccess = () => {},\r\n onError = (error) => console.error('DownloadFile Error:', error),\r\n}) => {\r\n const [isLoading, setIsLoading] = useState(false);\r\n\r\n const handlePress = async () => {\r\n if (!DownloadFileModule) {\r\n onError(new Error(\"DownloadFile native module is not available.\"));\r\n return;\r\n }\r\n\r\n setIsLoading(true);\r\n const downloadOptions = { maxSize, fileTypes, debug };\r\n\r\n try {\r\n const filesToProcess = multipleLoad ? files : files.slice(0, 1);\r\n const downloadPromises = filesToProcess.map(url => \r\n DownloadFileModule.downloadFile(url, downloadOptions)\r\n );\r\n\r\n const settledResults = await Promise.allSettled(downloadPromises);\r\n\r\n const finalResult: DownloadResult = { successful: [], skipped: [] };\r\n\r\n settledResults.forEach((result, index) => {\r\n // DÜZELTME: `filesToProcess[index]` ifadesinin sonuna `!` ekleyerek\r\n // TypeScript'e bu değerin asla undefined olmayacağını bildiriyoruz.\r\n const originalUrl = filesToProcess[index]!;\r\n\r\n if (result.status === 'fulfilled') {\r\n finalResult.successful.push({\r\n originalUrl, // Artık hata vermeyecek\r\n localUri: result.value,\r\n });\r\n } else {\r\n finalResult.skipped.push({\r\n originalUrl, // Artık hata vermeyecek\r\n reason: result.reason.message,\r\n });\r\n }\r\n });\r\n \r\n onSuccess(finalResult);\r\n\r\n } catch (error: any) {\r\n onError(error);\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n };\r\n\r\n const content = isLoading ? (\r\n <ActivityIndicator color=\"#FFFFFF\" />\r\n ) : (\r\n buttonIcon || <Text style={[styles.buttonText, ButtonTextStyle]}>{buttonPlaceHolder}</Text>\r\n );\r\n\r\n return (\r\n <TouchableOpacity\r\n style={[styles.button, ButtonStyle, (disabled || isLoading) && styles.disabledButton]}\r\n onPress={handlePress}\r\n disabled={disabled || isLoading}\r\n >\r\n {content}\r\n </TouchableOpacity>\r\n );\r\n};\r\n\r\nconst styles = StyleSheet.create({\r\n button: {\r\n backgroundColor: '#008CBA',\r\n paddingHorizontal: 20,\r\n paddingVertical: 10,\r\n borderRadius: 8,\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n flexDirection: 'row',\r\n },\r\n buttonText: {\r\n color: '#FFFFFF',\r\n fontSize: 16,\r\n fontWeight: 'bold',\r\n },\r\n disabledButton: {\r\n backgroundColor: '#A9A9A9',\r\n },\r\n});\r\n\r\nexport default DownloadFile;"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_react","_interopRequireWildcard","require","_reactNative","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","DownloadFile","NativeDownload","NativeModules","files","multipleDownload","disabled","debug","maxSize","fileTypes","buttonPlaceHolder","buttonIcon","ButtonStyle","ButtonTextStyle","onSuccess","onError","isLoading","setIsLoading","useState","handlePress","length","options","targetFiles","promises","map","url","downloadFile","results","Promise","allSettled","final","successful","skipped","forEach","res","index","_targetFiles$index","originalUrl","status","push","localUri","value","_res$reason","reason","message","console","error","createElement","TouchableOpacity","style","styles","button","onPress","ActivityIndicator","color","Text","text","StyleSheet","create","backgroundColor","padding","borderRadius","alignItems","fontWeight","_default","exports"],"sources":["DownloadFile.tsx"],"sourcesContent":["import React, { useState } from 'react';\r\nimport { TouchableOpacity, Text, StyleSheet, ActivityIndicator,NativeModules } from 'react-native';\r\nimport type { DownloadFileProps, DownloadResult } from '../types';\r\n\r\n\r\nconst { DownloadFile: NativeDownload } = NativeModules;\r\n\r\n\r\nconst DownloadFile: React.FC<DownloadFileProps> = ({\r\n files,\r\n multipleDownload = false,\r\n disabled = false,\r\n debug = false,\r\n maxSize = 0,\r\n fileTypes = ['*/*'],\r\n buttonPlaceHolder = 'Dosyaları İndir',\r\n buttonIcon,\r\n ButtonStyle,\r\n ButtonTextStyle,\r\n onSuccess,\r\n onError,\r\n}) => {\r\n const [isLoading, setIsLoading] = useState(false);\r\n\r\n const handlePress = async () => {\r\n if (disabled || isLoading || !files.length) return;\r\n setIsLoading(true);\r\n\r\n const options = { debug, maxSize, fileTypes };\r\n const targetFiles = multipleDownload ? files : [files[0]];\r\n\r\n try {\r\n const promises = targetFiles.map(url => NativeDownload.downloadFile(url, options));\r\n const results = await Promise.allSettled(promises);\r\n \r\n const final: DownloadResult = { successful: [], skipped: [] };\r\n\r\n results.forEach((res, index) => {\r\n const originalUrl = targetFiles[index] ?? \"\";\r\n if (res.status === 'fulfilled') {\r\n final.successful.push({ originalUrl, localUri: res.value });\r\n } else {\r\n final.skipped.push({ \r\n originalUrl, \r\n reason: res.reason?.message || \"Bilinmeyen Hata\" \r\n });\r\n }\r\n });\r\n\r\n if (onSuccess) onSuccess(final);\r\n } catch (e) {\r\n if (onError) onError(e);\r\n else console.error(e);\r\n } finally {\r\n setIsLoading(false);\r\n }\r\n };\r\n\r\n return (\r\n <TouchableOpacity\r\n style={[styles.button, ButtonStyle, (disabled || isLoading) && styles.disabled]}\r\n onPress={handlePress}\r\n disabled={disabled || isLoading}\r\n >\r\n {isLoading ? (\r\n <ActivityIndicator color=\"#FFF\" />\r\n ) : (\r\n buttonIcon ? buttonIcon : <Text style={[styles.text, ButtonTextStyle]}>{buttonPlaceHolder}</Text>\r\n )}\r\n </TouchableOpacity>\r\n );\r\n};\r\n\r\nconst styles = StyleSheet.create({\r\n button: {\r\n backgroundColor: '#03DAC6',\r\n padding: 12,\r\n borderRadius: 8,\r\n alignItems: 'center',\r\n },\r\n text: { color: '#000', fontWeight: 'bold' },\r\n disabled: { backgroundColor: '#AAA' }\r\n});\r\n\r\nexport default DownloadFile;"],"mappings":"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","ignoreList":[]}