react-native-my-uploader-android 1.0.21

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/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Yaren Coskun
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy
5
+ of this software and associated documentation files (the "Software"), to deal
6
+ in the Software without restriction, including without limitation the rights
7
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8
+ copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20
+ SOFTWARE.
@@ -0,0 +1,21 @@
1
+ require "json"
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = "MyUploader"
7
+ s.version = package["version"]
8
+ s.summary = package["description"]
9
+ s.homepage = package["homepage"]
10
+ s.license = package["license"]
11
+ s.authors = package["author"]
12
+
13
+ s.platforms = { :ios => min_ios_version_supported }
14
+ s.source = { :git => "https://www.npmjs.com/~yrncskn.git", :tag => "#{s.version}" }
15
+
16
+ s.source_files = "ios/**/*.{h,m,mm,cpp,swift}"
17
+ s.private_header_files = "ios/**/*.h"
18
+
19
+
20
+ install_modules_dependencies(s)
21
+ end
package/README.md ADDED
@@ -0,0 +1,205 @@
1
+ # react-native-my-uploader
2
+
3
+ file uploader
4
+
5
+ ## Installation
6
+
7
+
8
+ ```sh
9
+ npm install react-native-my-uploader
10
+ ```
11
+
12
+
13
+ ## Usage
14
+
15
+
16
+ ```js
17
+ import React, {useState} from 'react';
18
+ import {
19
+ StyleSheet,
20
+ View,
21
+ Button,
22
+ Text,
23
+ Alert,
24
+ ScrollView,
25
+ StatusBar,
26
+ } from 'react-native';
27
+
28
+ import {
29
+ pickFile,
30
+ FileInfo,
31
+ DocumentPickerOptions,
32
+ } from 'react-native-my-uploader';
33
+
34
+ const App = () => {
35
+ const [selectedFiles, setSelectedFiles] = useState<FileInfo[]>([]);
36
+
37
+ const handlePickFile = async (options: DocumentPickerOptions) => {
38
+ try {
39
+ console.log('Dosya seçici şu seçeneklerle başlatılıyor:', options);
40
+ const files = await pickFile(options);
41
+ console.log('Başarıyla seçilen dosyalar:', files);
42
+
43
+ if (options.multipleFiles) {
44
+ setSelectedFiles(prevFiles => [...prevFiles, ...files]);
45
+ Alert.alert(
46
+ 'Başarılı!',
47
+ `${files.length} adet yeni dosya listeye eklendi.`,
48
+ );
49
+ } else {
50
+ setSelectedFiles(files);
51
+ Alert.alert('Başarılı!', `1 adet dosya başarıyla seçildi.`);
52
+ }
53
+
54
+ } catch (error: any) {
55
+ if (error.code === 'E_PICKER_CANCELLED') {
56
+ console.log('Kullanıcı seçimi iptal etti.');
57
+ return;
58
+ }
59
+ console.error('Dosya seçme hatası:', error);
60
+ Alert.alert('Bir Hata Oluştu', error.message || 'Bilinmeyen bir hata.');
61
+ }
62
+ };
63
+
64
+ return (
65
+ <View style={styles.container}>
66
+ <StatusBar barStyle="dark-content" />
67
+ <View style={styles.header}>
68
+ <Text style={styles.title}>Dosya Yükleyici Paket Testi</Text>
69
+ </View>
70
+
71
+ <View style={styles.buttonGrid}>
72
+ <Button
73
+ title="Tek Bir Görüntü Seç"
74
+ onPress={() =>
75
+ handlePickFile({
76
+ multipleFiles: false,
77
+ fileTypes: ['image/*'],
78
+ })
79
+ }
80
+ />
81
+ <Button
82
+ title="birden Fazla Dosya Seç (Maks 2MB)"
83
+ onPress={() =>
84
+ handlePickFile({
85
+ multipleFiles: true,
86
+ fileTypes: ['application/*'],
87
+ maxSize: 2,
88
+ })
89
+ }
90
+ />
91
+ <Button
92
+ title="Listeyi Temizle"
93
+ color="#c0392b"
94
+ onPress={() => setSelectedFiles([])}
95
+ />
96
+ </View>
97
+
98
+ <View style={styles.resultsArea}>
99
+ <Text style={styles.resultsTitle}>
100
+ Seçilen Dosyalar ({selectedFiles.length} adet)
101
+ </Text>
102
+ <ScrollView contentContainerStyle={styles.scrollViewContent}>
103
+ {selectedFiles.length > 0 ? (
104
+ selectedFiles.map((file, index) => (
105
+ <View key={`${file.fileUri}-${index}`} style={styles.fileCard}>
106
+ <Text style={styles.fileName} numberOfLines={1}>
107
+ {file.fileName}
108
+ </Text>
109
+ <Text style={styles.fileDetail}>
110
+ Boyut: {(file.fileSize / 1024).toFixed(2)} KB
111
+ </Text>
112
+ </View>
113
+ ))
114
+ ) : (
115
+ <Text style={styles.noFilesText}>
116
+ Seçilen dosya yok.
117
+ </Text>
118
+ )}
119
+ </ScrollView>
120
+ </View>
121
+ </View>
122
+ );
123
+ };
124
+
125
+ const styles = StyleSheet.create({
126
+ container: {
127
+ flex: 1,
128
+ backgroundColor: '#f0f2f5',
129
+ },
130
+ header: {
131
+ padding: 20,
132
+ alignItems: 'center',
133
+ },
134
+ title: {
135
+ fontSize: 22,
136
+ fontWeight: 'bold',
137
+ color: '#1c1e21',
138
+ },
139
+ buttonGrid: {
140
+ paddingHorizontal: 20,
141
+ gap: 10,
142
+ },
143
+ resultsArea: {
144
+ flex: 1,
145
+ marginTop: 20,
146
+ borderTopWidth: 1,
147
+ borderTopColor: '#dddfe2',
148
+ paddingHorizontal: 20,
149
+ },
150
+ resultsTitle: {
151
+ fontSize: 18,
152
+ fontWeight: '600',
153
+ paddingVertical: 15,
154
+ color: '#1c1e21',
155
+ },
156
+ scrollViewContent: {
157
+ paddingBottom: 20,
158
+ },
159
+ fileCard: {
160
+ backgroundColor: '#ffffff',
161
+ padding: 15,
162
+ borderRadius: 8,
163
+ marginBottom: 10,
164
+ shadowColor: '#000',
165
+ shadowOffset: {width: 0, height: 1},
166
+ shadowOpacity: 0.2,
167
+ shadowRadius: 1.41,
168
+ elevation: 2,
169
+ },
170
+ fileName: {
171
+ fontSize: 16,
172
+ fontWeight: 'bold',
173
+ color: '#000',
174
+ },
175
+ fileDetail: {
176
+ fontSize: 13,
177
+ color: '#555',
178
+ marginTop: 4,
179
+ },
180
+ noFilesText: {
181
+ textAlign: 'center',
182
+ color: '#888',
183
+ marginTop: 30,
184
+ fontStyle: 'italic',
185
+ },
186
+ });
187
+
188
+
189
+ export default App;
190
+ ```
191
+
192
+
193
+ ## Contributing
194
+
195
+ - [Development workflow](CONTRIBUTING.md#development-workflow)
196
+ - [Sending a pull request](CONTRIBUTING.md#sending-a-pull-request)
197
+ - [Code of conduct](CODE_OF_CONDUCT.md)
198
+
199
+ ## License
200
+
201
+ MIT
202
+
203
+ ---
204
+
205
+ Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob)
@@ -0,0 +1,40 @@
1
+ apply plugin: "com.android.library"
2
+ apply plugin: "kotlin-android"
3
+
4
+ def getExtOrDefault(name) {
5
+ return rootProject.hasProperty(name) ? rootProject.ext[name] : project.properties[name]
6
+ }
7
+
8
+ android {
9
+ namespace "com.myuploader"
10
+
11
+ compileSdkVersion getExtOrDefault('compileSdkVersion')
12
+
13
+ defaultConfig {
14
+ minSdkVersion getExtOrDefault('minSdkVersion')
15
+ targetSdkVersion getExtOrDefault('targetSdkVersion')
16
+ }
17
+
18
+ compileOptions {
19
+ sourceCompatibility JavaVersion.VERSION_1_8
20
+ targetCompatibility JavaVersion.VERSION_1_8
21
+ }
22
+
23
+ sourceSets {
24
+ main {
25
+ java.srcDirs = ['src/main/java']
26
+ }
27
+ }
28
+ }
29
+
30
+ repositories {
31
+ mavenCentral()
32
+ google()
33
+ }
34
+
35
+ def kotlin_version = getExtOrDefault("kotlinVersion")
36
+
37
+ dependencies {
38
+ implementation "com.facebook.react:react-native:+"
39
+ implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
40
+ }
@@ -0,0 +1,5 @@
1
+ MyUploader_kotlinVersion=2.0.21
2
+ MyUploader_minSdkVersion=24
3
+ MyUploader_targetSdkVersion=34
4
+ MyUploader_compileSdkVersion=35
5
+ MyUploader_ndkVersion=27.1.12297006
@@ -0,0 +1,2 @@
1
+ <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
+ </manifest>
@@ -0,0 +1,173 @@
1
+ package com.myuploader
2
+
3
+ import android.app.Activity
4
+ import android.content.Intent
5
+ import android.net.Uri
6
+ import android.provider.OpenableColumns
7
+ import android.util.Base64
8
+ import com.facebook.react.bridge.*
9
+ import java.io.ByteArrayOutputStream
10
+ import java.net.URLConnection
11
+
12
+ class MyUploaderModule(private val reactContext: ReactApplicationContext) :
13
+ ReactContextBaseJavaModule(reactContext), ActivityEventListener {
14
+
15
+ private var pickerPromise: Promise? = null
16
+ private var maxSize: Double = 0.0
17
+ private var maxFiles: Int = 0
18
+ private var excludedUris: List<String> = emptyList()
19
+
20
+ init {
21
+ reactContext.addActivityEventListener(this)
22
+ }
23
+
24
+ override fun getName(): String = "DocumentPicker"
25
+
26
+ companion object {
27
+ private const val REQUEST_CODE = 9900
28
+ private const val E_ACTIVITY_DOES_NOT_EXIST = "E_ACTIVITY_DOES_NOT_EXIST"
29
+ private const val E_PICKER_CANCELLED = "E_PICKER_CANCELLED"
30
+ private const val E_FAILED_TO_OPEN_DOCUMENT = "E_FAILED_TO_OPEN_DOCUMENT"
31
+ private const val E_FILE_TOO_LARGE = "E_FILE_TOO_LARGE"
32
+ private const val E_MAX_FILES_EXCEEDED = "E_MAX_FILES_EXCEEDED"
33
+ private const val E_INVALID_OPTIONS = "E_INVALID_OPTIONS"
34
+ }
35
+
36
+ @ReactMethod
37
+ fun openDocument(options: ReadableMap, promise: Promise) {
38
+ if (pickerPromise != null) {
39
+ promise.reject(E_FAILED_TO_OPEN_DOCUMENT, "Başka bir dosya seçme işlemi zaten devam ediyor.")
40
+ return
41
+ }
42
+
43
+ this.pickerPromise = promise
44
+
45
+ val multipleFiles = options.takeIf { it.hasKey("multipleFiles") }?.getBoolean("multipleFiles") ?: false
46
+ val jsMaxFiles = options.takeIf { it.hasKey("maxFiles") }?.getInt("maxFiles") ?: 0
47
+
48
+ // KURAL KONTROLÜ (NATIVE): JS tarafındaki kontrolü burada da yaparak güvenliği artır.
49
+ if (!multipleFiles && jsMaxFiles > 1) {
50
+ promise.reject(E_INVALID_OPTIONS, "`maxFiles` değeri, `multipleFiles` false iken 1'den büyük olamaz.")
51
+ return
52
+ }
53
+
54
+ // KURAL UYGULAMA (NATIVE): `maxFiles` için nihai değeri hesapla.
55
+ val effectiveMaxFiles = when {
56
+ multipleFiles && jsMaxFiles == 0 -> 3 // Varsayılan: 3
57
+ !multipleFiles -> 1 // Tekli seçimde her zaman 1
58
+ else -> jsMaxFiles // Belirtilen değeri kullan
59
+ }
60
+
61
+ // Değerleri sınıf değişkenlerine ata
62
+ this.maxFiles = effectiveMaxFiles
63
+ this.maxSize = options.takeIf { it.hasKey("maxSize") }?.getDouble("maxSize") ?: 0.0
64
+ this.excludedUris = options.takeIf { it.hasKey("excludedUris") }
65
+ ?.getArray("excludedUris")?.toArrayList()?.mapNotNull { it.toString() } ?: emptyList()
66
+
67
+ val currentActivity = reactContext.currentActivity
68
+ if (currentActivity == null) {
69
+ pickerPromise?.reject(E_ACTIVITY_DOES_NOT_EXIST, "Activity mevcut değil.")
70
+ pickerPromise = null
71
+ return
72
+ }
73
+
74
+ val fileTypes = options.takeIf { it.hasKey("fileTypes") }
75
+ ?.getArray("fileTypes")?.toArrayList()?.mapNotNull { it.toString() } ?: listOf("*/*")
76
+ val mimeTypes = if (fileTypes.isEmpty()) arrayOf("*/*") else fileTypes.toTypedArray()
77
+
78
+ try {
79
+ // ANAHTAR: ACTION_GET_CONTENT, güvenilir çoklu seçimi etkinleştirir.
80
+ val intent = Intent(Intent.ACTION_GET_CONTENT).apply {
81
+ type = "*/*"
82
+ addCategory(Intent.CATEGORY_OPENABLE)
83
+ putExtra(Intent.EXTRA_MIME_TYPES, mimeTypes)
84
+
85
+ if (multipleFiles) {
86
+ putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
87
+ }
88
+ }
89
+ currentActivity.startActivityForResult(Intent.createChooser(intent, "Dosya Seçin"), REQUEST_CODE)
90
+ } catch (e: Exception) {
91
+ pickerPromise?.reject(E_FAILED_TO_OPEN_DOCUMENT, e)
92
+ pickerPromise = null
93
+ }
94
+ }
95
+
96
+ override fun onActivityResult(activity: Activity, requestCode: Int, resultCode: Int, data: Intent?) {
97
+ if (requestCode != REQUEST_CODE || pickerPromise == null) { return }
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()) }
110
+
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
115
+ }
116
+
117
+ try {
118
+ val fileInfoArray = processSelectedFiles(newSelectedUris)
119
+ pickerPromise?.resolve(fileInfoArray)
120
+ } catch (e: Exception) {
121
+ pickerPromise?.reject(E_FILE_TOO_LARGE, e.message)
122
+ }
123
+ } else {
124
+ pickerPromise?.reject(E_PICKER_CANCELLED, "Dosya seçimi iptal edildi.")
125
+ }
126
+ pickerPromise = null
127
+ }
128
+
129
+ override fun onNewIntent(intent: Intent) {}
130
+
131
+ private fun processSelectedFiles(uris: List<Uri>): WritableArray {
132
+ val fileObjects = WritableNativeArray()
133
+ val maxSizeBytes = (maxSize * 1024 * 1024).toLong()
134
+
135
+ for (uri in uris) {
136
+ reactContext.contentResolver.query(uri, null, null, null, null)?.use { cursor ->
137
+ 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)
142
+
143
+ if (maxSizeBytes > 0 && fileSize > maxSizeBytes) {
144
+ throw Exception("Seçilen dosya ($fileName) belirtilen ${maxSize}MB boyutundan büyük.")
145
+ }
146
+
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)
154
+ }
155
+ Base64.encodeToString(byteBuffer.toByteArray(), Base64.NO_WRAP)
156
+ }
157
+
158
+ val fileMap = WritableNativeMap().apply {
159
+ putString("fileName", fileName)
160
+ putDouble("fileSize", fileSize.toDouble())
161
+ putString("fileType", mimeType)
162
+ putString("fileUri", uri.toString())
163
+ putString("base64", base64)
164
+ }
165
+ fileObjects.pushMap(fileMap)
166
+ }
167
+ }
168
+ }
169
+ return fileObjects
170
+ }
171
+
172
+ private fun getMimeType(fileName: String): String? = URLConnection.guessContentTypeFromName(fileName)
173
+ }
@@ -0,0 +1,16 @@
1
+ package com.myuploader
2
+
3
+ import com.facebook.react.ReactPackage
4
+ import com.facebook.react.bridge.NativeModule
5
+ import com.facebook.react.bridge.ReactApplicationContext
6
+ import com.facebook.react.uimanager.ViewManager
7
+
8
+ class MyUploaderPackage : ReactPackage {
9
+ override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
10
+ return listOf(MyUploaderModule(reactContext))
11
+ }
12
+
13
+ override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
14
+ return emptyList()
15
+ }
16
+ }
@@ -0,0 +1,8 @@
1
+
2
+ #ifndef MuhasebeonayMain_Bridging_Header_h
3
+ #define MuhasebeonayMain_Bridging_Header_h
4
+ #import "React/RCTBridgeModule.h"
5
+ #import "React/RCTViewManager.h"
6
+ #import "React/RCTEventEmitter.h"
7
+
8
+
@@ -0,0 +1,11 @@
1
+
2
+ #import <Foundation/Foundation.h>
3
+ #import <React/RCTBridgeModule.h>
4
+
5
+ @interface RCT_EXTERN_MODULE(MyUploader, NSObject)
6
+
7
+ RCT_EXTERN_METHOD(openDocument:(NSDictionary)options
8
+ successCallback:(RCTResponseSenderBlock)successCallback
9
+ failureCallback:(RCTResponseSenderBlock)failureCallback)
10
+
11
+ @end
@@ -0,0 +1,98 @@
1
+ import Foundation
2
+ import MobileCoreServices
3
+ import UIKit
4
+ import UniformTypeIdentifiers
5
+ import React
6
+
7
+ @objc(MyUploader)
8
+ class MyUploader: NSObject, UIDocumentPickerDelegate {
9
+
10
+ private var resolveCallback: RCTResponseSenderBlock?
11
+ private var rejectCallback: RCTResponseSenderBlock?
12
+ private var maxFileSize: Int64 = 3 * 1024 * 1024 // 3 MB
13
+ private var currentPicker: UIDocumentPickerViewController?
14
+
15
+ @objc static func requiresMainQueueSetup() -> Bool {
16
+ return true
17
+ }
18
+
19
+ @objc(openDocument:successCallback:failureCallback:)
20
+ func openDocument(_ options: NSDictionary,
21
+ successCallback: @escaping RCTResponseSenderBlock,
22
+ failureCallback: @escaping RCTResponseSenderBlock) {
23
+
24
+ self.resolveCallback = successCallback
25
+ self.rejectCallback = failureCallback
26
+
27
+ let multipleFiles = options["multipleFiles"] as? Bool ?? false
28
+ let fileTypes = options["fileTypes"] as? [String] ?? ["public.data"]
29
+
30
+ let supportedTypes: [UTType] = fileTypes.compactMap { mime in
31
+ switch mime {
32
+ case "application/pdf": return .pdf
33
+ case "image/*": return .image
34
+ case "application/msword": return UTType(importedAs: "com.microsoft.word.doc")
35
+ case "application/vnd.openxmlformats-officedocument.wordprocessingml.document": return UTType(importedAs: "org.openxmlformats.wordprocessingml.document")
36
+ case "application/vnd.ms-excel": return UTType(importedAs: "com.microsoft.excel.xls")
37
+ case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": return UTType(importedAs: "org.openxmlformats.spreadsheetml.sheet")
38
+ case "application/vnd.ms-powerpoint": return UTType(importedAs: "com.microsoft.powerpoint.ppt")
39
+ case "application/vnd.openxmlformats-officedocument.presentationml.presentation": return UTType(importedAs: "org.openxmlformats.presentationml.presentation")
40
+ default: return nil
41
+ }
42
+ }
43
+
44
+ let picker = UIDocumentPickerViewController(forOpeningContentTypes: supportedTypes, asCopy: true)
45
+ picker.allowsMultipleSelection = multipleFiles
46
+ picker.delegate = self
47
+
48
+ DispatchQueue.main.async {
49
+ if let rootVC = UIApplication.shared.windows.first?.rootViewController {
50
+ var topVC = rootVC
51
+ while let presented = topVC.presentedViewController {
52
+ topVC = presented
53
+ }
54
+ topVC.present(picker, animated: true, completion: nil)
55
+ } else {
56
+ failureCallback(["{\"code\":\"NO_ROOT\", \"message\":\"Root view controller bulunamadı.\"}"])
57
+ }
58
+ }
59
+ }
60
+
61
+ func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
62
+ var results: [[String: Any]] = []
63
+
64
+ for url in urls {
65
+ do {
66
+ let fileData = try Data(contentsOf: url)
67
+ let fileSize = Int64(fileData.count)
68
+
69
+ if fileSize > maxFileSize {
70
+ rejectCallback?(["{\"code\":\"TOO_LARGE\", \"message\":\"Seçilen dosya 3 MB'dan büyük olamaz.\"}"])
71
+ return
72
+ }
73
+
74
+ let base64String = fileData.base64EncodedString()
75
+ let fileName = url.lastPathComponent
76
+ let fileType = url.pathExtension
77
+
78
+ let dict: [String: Any] = [
79
+ "fileName": fileName,
80
+ "fileSize": fileSize,
81
+ "fileType": fileType,
82
+ "fileUri": url.absoluteString,
83
+ "base64": base64String
84
+ ]
85
+ results.append(dict)
86
+ } catch {
87
+ rejectCallback?(["{\"code\":\"READ_ERROR\", \"message\":\"Dosya okunamadı: \(error.localizedDescription)\"}"])
88
+ return
89
+ }
90
+ }
91
+
92
+ resolveCallback?(results)
93
+ }
94
+
95
+ func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
96
+ rejectCallback?(["{\"code\":\"CANCELLED\", \"message\":\"Kullanıcı iptal etti\"}"])
97
+ }
98
+ }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _reactNative = require("react-native");
8
+ // Native modülün tip tanımı
9
+
10
+ const LINKING_ERROR = `The package 'react--native-my-uploader' doesn't seem to be linked. Make sure: \n\n` + '- You rebuilt the app after installing the package\n' + '- You are not using Expo Go\n';
11
+ const DocumentPicker = _reactNative.NativeModules.DocumentPicker ? _reactNative.NativeModules.DocumentPicker : new Proxy({}, {
12
+ get() {
13
+ throw new Error(LINKING_ERROR);
14
+ }
15
+ });
16
+ var _default = exports.default = DocumentPicker;
17
+ //# sourceMappingURL=NativeMyUploader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_reactNative","require","LINKING_ERROR","DocumentPicker","NativeModules","Proxy","get","Error","_default","exports","default"],"sources":["NativeMyUploader.ts"],"sourcesContent":["import { NativeModules } from 'react-native';\nimport type { FileInfo, DocumentPickerOptions } from './types';\n\n\n// Native modülün tip tanımı\ninterface MyUploaderType {\n openDocument(options: DocumentPickerOptions): Promise<FileInfo[]>;\n}\n\nconst LINKING_ERROR =\n `The package 'react--native-my-uploader' doesn't seem to be linked. Make sure: \\n\\n` +\n '- You rebuilt the app after installing the package\\n' +\n '- You are not using Expo Go\\n';\n \n\nconst DocumentPicker = NativeModules.DocumentPicker\n ? (NativeModules.DocumentPicker as MyUploaderType)\n : new Proxy(\n {},\n {\n get() {\n throw new Error(LINKING_ERROR);\n },\n }\n );\n\nexport default DocumentPicker;"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAIA;;AAKA,MAAMC,aAAa,GACjB,oFAAoF,GACpF,sDAAsD,GACtD,+BAA+B;AAGjC,MAAMC,cAAc,GAAGC,0BAAa,CAACD,cAAc,GAC9CC,0BAAa,CAACD,cAAc,GAC7B,IAAIE,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACL,aAAa,CAAC;EAChC;AACF,CACF,CAAC;AAAC,IAAAM,QAAA,GAAAC,OAAA,CAAAC,OAAA,GAESP,cAAc","ignoreList":[]}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ //# sourceMappingURL=index.d.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sources":["index.d.ts"],"sourcesContent":["// Dosya: index.d.ts\n\n// ADIM 1: Tipleri DIŞA AKTARARAK (export) doğrudan burada tanımla.\n// (Artık 'import' kullanmıyoruz)\n\n/**\n * Native modülden dönen tek bir dosyanın yapısını tanımlar.\n * Bu tip, paket kullanıcıları tarafından import edilebilir.\n */\nexport interface FileInfo {\n fileName: string;\n fileSize: number; // in bytes\n fileType: string | null;\n fileUri: string;\n base64: string;\n}\n\n/**\n * `pickFile` fonksiyonuna gönderilebilecek tüm opsiyonları tanımlar.\n * Bu tip, paket kullanıcıları tarafından import edilebilir.\n */\nexport interface DocumentPickerOptions {\n /**\n * Birden fazla dosya seçimine izin ver.\n * @default false\n */\n multipleFiles?: boolean;\n\n /**\n * Filtrelenecek dosya tipleri (MIME types).\n * @default ['* / *']\n */\n fileTypes?: string[];\n\n /**\n * MB cinsinden maksimum dosya boyutu.\n * @default 0 (limitsiz)\n */\n maxSize?: number;\n\n /**\n * Seçilebilecek maksimum dosya sayısı. `multipleFiles: true` olmalıdır.\n * Belirtilmezse ve `multipleFiles: true` ise varsayılan olarak 3'tür.\n */\n maxFiles?: number;\n\n /**\n * Zaten seçilmiş olduğu için tekrar seçilmesi engellenecek dosyaların URI listesi.\n */\n excludedUris?: string[];\n}\n\n// ADIM 2: Fonksiyonu da DIŞA AKTARARAK (export) tanımla.\n\n/**\n * Dosya seçiciyi açar ve seçilen dosyaların bilgilerini döndürür.\n * @param options Dosya seçici için yapılandırma ayarları.\n * @returns Seçilen dosya bilgilerini içeren bir Promise<FileInfo[]> döner.\n */\nexport function pickFile(options?: DocumentPickerOptions): Promise<FileInfo[]>;"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.pickFile = pickFile;
7
+ var _reactNative = require("react-native");
8
+ // Gerekli tipleri ve arayüzleri import et
9
+
10
+ // Native modülün düzgün bir şekilde bağlanıp bağlanmadığını kontrol eden güvenlik mekanizması
11
+ const LINKING_ERROR = `The package 'react-native-my-uploader' doesn't seem to be linked.`;
12
+ const DocumentPicker = _reactNative.NativeModules.DocumentPicker ? _reactNative.NativeModules.DocumentPicker : new Proxy({}, {
13
+ get() {
14
+ throw new Error(LINKING_ERROR);
15
+ }
16
+ });
17
+
18
+ /**
19
+ * Dosya seçiciyi açar ve seçilen dosyaların bilgilerini döndürür.
20
+ * @param options Dosya seçici için yapılandırma ayarları.
21
+ * @returns Seçilen dosya bilgilerini içeren bir Promise<FileInfo[]> döner.
22
+ */
23
+ async function pickFile(options = {}) {
24
+ var _options$excludedUris, _options$fileTypes, _options$maxSize;
25
+ // Gelen opsiyonları varsayılan değerlerle birleştir
26
+ const {
27
+ multipleFiles = false,
28
+ maxFiles = 0,
29
+ ...rest
30
+ } = options;
31
+ if (!multipleFiles && maxFiles > 1) {
32
+ throw new Error('`maxFiles` cannot be greater than 1 when `multipleFiles` is false.');
33
+ }
34
+
35
+ // KURAL: `multipleFiles: true` iken `maxFiles` belirtilmemişse, varsayılan olarak 3 ata.
36
+ let effectiveMaxFiles = maxFiles;
37
+ if (multipleFiles && maxFiles === 0) {
38
+ effectiveMaxFiles = 3;
39
+ }
40
+
41
+ // Native koda gönderilecek nihai, temizlenmiş ve varsayılanları atanmış opsiyonları oluştur.
42
+ const finalOptions = {
43
+ ...rest,
44
+ multipleFiles,
45
+ maxFiles: effectiveMaxFiles,
46
+ // Diğer opsiyonlar için de null/undefined kontrolü yap
47
+ excludedUris: (_options$excludedUris = options.excludedUris) !== null && _options$excludedUris !== void 0 ? _options$excludedUris : [],
48
+ fileTypes: (_options$fileTypes = options.fileTypes) !== null && _options$fileTypes !== void 0 ? _options$fileTypes : ['*/*'],
49
+ maxSize: (_options$maxSize = options.maxSize) !== null && _options$maxSize !== void 0 ? _options$maxSize : 0
50
+ };
51
+
52
+ // Nihai opsiyonlarla native modülü çağır
53
+ return DocumentPicker.openDocument(finalOptions);
54
+ }
55
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["_reactNative","require","LINKING_ERROR","DocumentPicker","NativeModules","Proxy","get","Error","pickFile","options","_options$excludedUris","_options$fileTypes","_options$maxSize","multipleFiles","maxFiles","rest","effectiveMaxFiles","finalOptions","excludedUris","fileTypes","maxSize","openDocument"],"sources":["index.tsx"],"sourcesContent":["import { NativeModules } from 'react-native';\n\n// Gerekli tipleri ve arayüzleri import et\nimport type { FileInfo, DocumentPickerOptions } from './types';\n\n// Native modülün düzgün bir şekilde bağlanıp bağlanmadığını kontrol eden güvenlik mekanizması\nconst LINKING_ERROR = `The package 'react-native-my-uploader' doesn't seem to be linked.`;\n\nconst DocumentPicker = NativeModules.DocumentPicker\n ? NativeModules.DocumentPicker\n : new Proxy(\n {},\n {\n get() {\n throw new Error(LINKING_ERROR);\n },\n }\n );\n\n/**\n * Dosya seçiciyi açar ve seçilen dosyaların bilgilerini döndürür.\n * @param options Dosya seçici için yapılandırma ayarları.\n * @returns Seçilen dosya bilgilerini içeren bir Promise<FileInfo[]> döner.\n */\nexport async function pickFile(\n options: DocumentPickerOptions = {}\n): Promise<FileInfo[]> {\n // Gelen opsiyonları varsayılan değerlerle birleştir\n const { multipleFiles = false, maxFiles = 0, ...rest } = options;\n\n if (!multipleFiles && maxFiles > 1) {\n throw new Error(\n '`maxFiles` cannot be greater than 1 when `multipleFiles` is false.'\n );\n }\n\n // KURAL: `multipleFiles: true` iken `maxFiles` belirtilmemişse, varsayılan olarak 3 ata.\n let effectiveMaxFiles = maxFiles;\n if (multipleFiles && maxFiles === 0) {\n effectiveMaxFiles = 3;\n }\n\n // Native koda gönderilecek nihai, temizlenmiş ve varsayılanları atanmış opsiyonları oluştur.\n const finalOptions: DocumentPickerOptions = {\n ...rest,\n multipleFiles,\n maxFiles: effectiveMaxFiles,\n // Diğer opsiyonlar için de null/undefined kontrolü yap\n excludedUris: options.excludedUris ?? [],\n fileTypes: options.fileTypes ?? ['*/*'],\n maxSize: options.maxSize ?? 0,\n };\n\n // Nihai opsiyonlarla native modülü çağır\n return DocumentPicker.openDocument(finalOptions);\n}\n\nexport type { FileInfo, DocumentPickerOptions };"],"mappings":";;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAEA;;AAGA;AACA,MAAMC,aAAa,GAAG,mEAAmE;AAEzF,MAAMC,cAAc,GAAGC,0BAAa,CAACD,cAAc,GAC/CC,0BAAa,CAACD,cAAc,GAC5B,IAAIE,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACL,aAAa,CAAC;EAChC;AACF,CACF,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACO,eAAeM,QAAQA,CAC5BC,OAA8B,GAAG,CAAC,CAAC,EACd;EAAA,IAAAC,qBAAA,EAAAC,kBAAA,EAAAC,gBAAA;EACrB;EACA,MAAM;IAAEC,aAAa,GAAG,KAAK;IAAEC,QAAQ,GAAG,CAAC;IAAE,GAAGC;EAAK,CAAC,GAAGN,OAAO;EAEhE,IAAI,CAACI,aAAa,IAAIC,QAAQ,GAAG,CAAC,EAAE;IAClC,MAAM,IAAIP,KAAK,CACb,oEACF,CAAC;EACH;;EAEA;EACA,IAAIS,iBAAiB,GAAGF,QAAQ;EAChC,IAAID,aAAa,IAAIC,QAAQ,KAAK,CAAC,EAAE;IACnCE,iBAAiB,GAAG,CAAC;EACvB;;EAEA;EACA,MAAMC,YAAmC,GAAG;IAC1C,GAAGF,IAAI;IACPF,aAAa;IACbC,QAAQ,EAAEE,iBAAiB;IAC3B;IACAE,YAAY,GAAAR,qBAAA,GAAED,OAAO,CAACS,YAAY,cAAAR,qBAAA,cAAAA,qBAAA,GAAI,EAAE;IACxCS,SAAS,GAAAR,kBAAA,GAAEF,OAAO,CAACU,SAAS,cAAAR,kBAAA,cAAAA,kBAAA,GAAI,CAAC,KAAK,CAAC;IACvCS,OAAO,GAAAR,gBAAA,GAAEH,OAAO,CAACW,OAAO,cAAAR,gBAAA,cAAAA,gBAAA,GAAI;EAC9B,CAAC;;EAED;EACA,OAAOT,cAAc,CAACkB,YAAY,CAACJ,YAAY,CAAC;AAClD","ignoreList":[]}
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sources":["types.ts"],"sourcesContent":["// Dosya: src/types.ts\n\n/**\n * Native modülden dönen tek bir dosyanın yapısını tanımlar.\n */\nexport interface FileInfo {\n fileName: string;\n fileSize: number; // in bytes\n fileType: string | null;\n fileUri: string;\n base64: string;\n}\n\n/**\n * `pickFile` fonksiyonuna gönderilebilecek tüm opsiyonları tanımlar.\n */\nexport interface DocumentPickerOptions {\n /**\n * Birden fazla dosya seçimine izin ver.\n * @default false\n */\n multipleFiles?: boolean;\n\n /**\n * Filtrelenecek dosya tipleri (MIME types).\n * @default ['* / *'] (tüm dosyalar)\n * @example ['image/jpeg', 'application/pdf']\n */\n fileTypes?: string[];\n\n /**\n * MB cinsinden maksimum dosya boyutu.\n * @default 0 (limitsiz)\n */\n maxSize?: number;\n\n /**\n * Seçilebilecek maksimum dosya sayısı. `multipleFiles: true` olmalıdır.\n * Belirtilmezse ve `multipleFiles: true` ise varsayılan olarak 3'tür.\n * @default 0 (limitsiz, ama varsayılan mantığı uygulanır)\n */\n maxFiles?: number;\n\n /**\n * Zaten seçilmiş olduğu için tekrar seçilmesi engellenecek dosyaların URI listesi.\n */\n excludedUris?: string[];\n}"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,12 @@
1
+ import { NativeModules } from 'react-native';
2
+
3
+ // Native modülün tip tanımı
4
+
5
+ const LINKING_ERROR = `The package 'react--native-my-uploader' doesn't seem to be linked. Make sure: \n\n` + '- You rebuilt the app after installing the package\n' + '- You are not using Expo Go\n';
6
+ const DocumentPicker = NativeModules.DocumentPicker ? NativeModules.DocumentPicker : new Proxy({}, {
7
+ get() {
8
+ throw new Error(LINKING_ERROR);
9
+ }
10
+ });
11
+ export default DocumentPicker;
12
+ //# sourceMappingURL=NativeMyUploader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["NativeModules","LINKING_ERROR","DocumentPicker","Proxy","get","Error"],"sources":["NativeMyUploader.ts"],"sourcesContent":["import { NativeModules } from 'react-native';\nimport type { FileInfo, DocumentPickerOptions } from './types';\n\n\n// Native modülün tip tanımı\ninterface MyUploaderType {\n openDocument(options: DocumentPickerOptions): Promise<FileInfo[]>;\n}\n\nconst LINKING_ERROR =\n `The package 'react--native-my-uploader' doesn't seem to be linked. Make sure: \\n\\n` +\n '- You rebuilt the app after installing the package\\n' +\n '- You are not using Expo Go\\n';\n \n\nconst DocumentPicker = NativeModules.DocumentPicker\n ? (NativeModules.DocumentPicker as MyUploaderType)\n : new Proxy(\n {},\n {\n get() {\n throw new Error(LINKING_ERROR);\n },\n }\n );\n\nexport default DocumentPicker;"],"mappings":"AAAA,SAASA,aAAa,QAAQ,cAAc;;AAI5C;;AAKA,MAAMC,aAAa,GACjB,oFAAoF,GACpF,sDAAsD,GACtD,+BAA+B;AAGjC,MAAMC,cAAc,GAAGF,aAAa,CAACE,cAAc,GAC9CF,aAAa,CAACE,cAAc,GAC7B,IAAIC,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACJ,aAAa,CAAC;EAChC;AACF,CACF,CAAC;AAEL,eAAeC,cAAc","ignoreList":[]}
@@ -0,0 +1,2 @@
1
+
2
+ //# sourceMappingURL=index.d.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sources":["index.d.ts"],"sourcesContent":["// Dosya: index.d.ts\n\n// ADIM 1: Tipleri DIŞA AKTARARAK (export) doğrudan burada tanımla.\n// (Artık 'import' kullanmıyoruz)\n\n/**\n * Native modülden dönen tek bir dosyanın yapısını tanımlar.\n * Bu tip, paket kullanıcıları tarafından import edilebilir.\n */\nexport interface FileInfo {\n fileName: string;\n fileSize: number; // in bytes\n fileType: string | null;\n fileUri: string;\n base64: string;\n}\n\n/**\n * `pickFile` fonksiyonuna gönderilebilecek tüm opsiyonları tanımlar.\n * Bu tip, paket kullanıcıları tarafından import edilebilir.\n */\nexport interface DocumentPickerOptions {\n /**\n * Birden fazla dosya seçimine izin ver.\n * @default false\n */\n multipleFiles?: boolean;\n\n /**\n * Filtrelenecek dosya tipleri (MIME types).\n * @default ['* / *']\n */\n fileTypes?: string[];\n\n /**\n * MB cinsinden maksimum dosya boyutu.\n * @default 0 (limitsiz)\n */\n maxSize?: number;\n\n /**\n * Seçilebilecek maksimum dosya sayısı. `multipleFiles: true` olmalıdır.\n * Belirtilmezse ve `multipleFiles: true` ise varsayılan olarak 3'tür.\n */\n maxFiles?: number;\n\n /**\n * Zaten seçilmiş olduğu için tekrar seçilmesi engellenecek dosyaların URI listesi.\n */\n excludedUris?: string[];\n}\n\n// ADIM 2: Fonksiyonu da DIŞA AKTARARAK (export) tanımla.\n\n/**\n * Dosya seçiciyi açar ve seçilen dosyaların bilgilerini döndürür.\n * @param options Dosya seçici için yapılandırma ayarları.\n * @returns Seçilen dosya bilgilerini içeren bir Promise<FileInfo[]> döner.\n */\nexport function pickFile(options?: DocumentPickerOptions): Promise<FileInfo[]>;"],"mappings":"","ignoreList":[]}
@@ -0,0 +1,50 @@
1
+ import { NativeModules } from 'react-native';
2
+
3
+ // Gerekli tipleri ve arayüzleri import et
4
+
5
+ // Native modülün düzgün bir şekilde bağlanıp bağlanmadığını kontrol eden güvenlik mekanizması
6
+ const LINKING_ERROR = `The package 'react-native-my-uploader' doesn't seem to be linked.`;
7
+ const DocumentPicker = NativeModules.DocumentPicker ? NativeModules.DocumentPicker : new Proxy({}, {
8
+ get() {
9
+ throw new Error(LINKING_ERROR);
10
+ }
11
+ });
12
+
13
+ /**
14
+ * Dosya seçiciyi açar ve seçilen dosyaların bilgilerini döndürür.
15
+ * @param options Dosya seçici için yapılandırma ayarları.
16
+ * @returns Seçilen dosya bilgilerini içeren bir Promise<FileInfo[]> döner.
17
+ */
18
+ export async function pickFile(options = {}) {
19
+ var _options$excludedUris, _options$fileTypes, _options$maxSize;
20
+ // Gelen opsiyonları varsayılan değerlerle birleştir
21
+ const {
22
+ multipleFiles = false,
23
+ maxFiles = 0,
24
+ ...rest
25
+ } = options;
26
+ if (!multipleFiles && maxFiles > 1) {
27
+ throw new Error('`maxFiles` cannot be greater than 1 when `multipleFiles` is false.');
28
+ }
29
+
30
+ // KURAL: `multipleFiles: true` iken `maxFiles` belirtilmemişse, varsayılan olarak 3 ata.
31
+ let effectiveMaxFiles = maxFiles;
32
+ if (multipleFiles && maxFiles === 0) {
33
+ effectiveMaxFiles = 3;
34
+ }
35
+
36
+ // Native koda gönderilecek nihai, temizlenmiş ve varsayılanları atanmış opsiyonları oluştur.
37
+ const finalOptions = {
38
+ ...rest,
39
+ multipleFiles,
40
+ maxFiles: effectiveMaxFiles,
41
+ // Diğer opsiyonlar için de null/undefined kontrolü yap
42
+ excludedUris: (_options$excludedUris = options.excludedUris) !== null && _options$excludedUris !== void 0 ? _options$excludedUris : [],
43
+ fileTypes: (_options$fileTypes = options.fileTypes) !== null && _options$fileTypes !== void 0 ? _options$fileTypes : ['*/*'],
44
+ maxSize: (_options$maxSize = options.maxSize) !== null && _options$maxSize !== void 0 ? _options$maxSize : 0
45
+ };
46
+
47
+ // Nihai opsiyonlarla native modülü çağır
48
+ return DocumentPicker.openDocument(finalOptions);
49
+ }
50
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["NativeModules","LINKING_ERROR","DocumentPicker","Proxy","get","Error","pickFile","options","_options$excludedUris","_options$fileTypes","_options$maxSize","multipleFiles","maxFiles","rest","effectiveMaxFiles","finalOptions","excludedUris","fileTypes","maxSize","openDocument"],"sources":["index.tsx"],"sourcesContent":["import { NativeModules } from 'react-native';\n\n// Gerekli tipleri ve arayüzleri import et\nimport type { FileInfo, DocumentPickerOptions } from './types';\n\n// Native modülün düzgün bir şekilde bağlanıp bağlanmadığını kontrol eden güvenlik mekanizması\nconst LINKING_ERROR = `The package 'react-native-my-uploader' doesn't seem to be linked.`;\n\nconst DocumentPicker = NativeModules.DocumentPicker\n ? NativeModules.DocumentPicker\n : new Proxy(\n {},\n {\n get() {\n throw new Error(LINKING_ERROR);\n },\n }\n );\n\n/**\n * Dosya seçiciyi açar ve seçilen dosyaların bilgilerini döndürür.\n * @param options Dosya seçici için yapılandırma ayarları.\n * @returns Seçilen dosya bilgilerini içeren bir Promise<FileInfo[]> döner.\n */\nexport async function pickFile(\n options: DocumentPickerOptions = {}\n): Promise<FileInfo[]> {\n // Gelen opsiyonları varsayılan değerlerle birleştir\n const { multipleFiles = false, maxFiles = 0, ...rest } = options;\n\n if (!multipleFiles && maxFiles > 1) {\n throw new Error(\n '`maxFiles` cannot be greater than 1 when `multipleFiles` is false.'\n );\n }\n\n // KURAL: `multipleFiles: true` iken `maxFiles` belirtilmemişse, varsayılan olarak 3 ata.\n let effectiveMaxFiles = maxFiles;\n if (multipleFiles && maxFiles === 0) {\n effectiveMaxFiles = 3;\n }\n\n // Native koda gönderilecek nihai, temizlenmiş ve varsayılanları atanmış opsiyonları oluştur.\n const finalOptions: DocumentPickerOptions = {\n ...rest,\n multipleFiles,\n maxFiles: effectiveMaxFiles,\n // Diğer opsiyonlar için de null/undefined kontrolü yap\n excludedUris: options.excludedUris ?? [],\n fileTypes: options.fileTypes ?? ['*/*'],\n maxSize: options.maxSize ?? 0,\n };\n\n // Nihai opsiyonlarla native modülü çağır\n return DocumentPicker.openDocument(finalOptions);\n}\n\nexport type { FileInfo, DocumentPickerOptions };"],"mappings":"AAAA,SAASA,aAAa,QAAQ,cAAc;;AAE5C;;AAGA;AACA,MAAMC,aAAa,GAAG,mEAAmE;AAEzF,MAAMC,cAAc,GAAGF,aAAa,CAACE,cAAc,GAC/CF,aAAa,CAACE,cAAc,GAC5B,IAAIC,KAAK,CACP,CAAC,CAAC,EACF;EACEC,GAAGA,CAAA,EAAG;IACJ,MAAM,IAAIC,KAAK,CAACJ,aAAa,CAAC;EAChC;AACF,CACF,CAAC;;AAEL;AACA;AACA;AACA;AACA;AACA,OAAO,eAAeK,QAAQA,CAC5BC,OAA8B,GAAG,CAAC,CAAC,EACd;EAAA,IAAAC,qBAAA,EAAAC,kBAAA,EAAAC,gBAAA;EACrB;EACA,MAAM;IAAEC,aAAa,GAAG,KAAK;IAAEC,QAAQ,GAAG,CAAC;IAAE,GAAGC;EAAK,CAAC,GAAGN,OAAO;EAEhE,IAAI,CAACI,aAAa,IAAIC,QAAQ,GAAG,CAAC,EAAE;IAClC,MAAM,IAAIP,KAAK,CACb,oEACF,CAAC;EACH;;EAEA;EACA,IAAIS,iBAAiB,GAAGF,QAAQ;EAChC,IAAID,aAAa,IAAIC,QAAQ,KAAK,CAAC,EAAE;IACnCE,iBAAiB,GAAG,CAAC;EACvB;;EAEA;EACA,MAAMC,YAAmC,GAAG;IAC1C,GAAGF,IAAI;IACPF,aAAa;IACbC,QAAQ,EAAEE,iBAAiB;IAC3B;IACAE,YAAY,GAAAR,qBAAA,GAAED,OAAO,CAACS,YAAY,cAAAR,qBAAA,cAAAA,qBAAA,GAAI,EAAE;IACxCS,SAAS,GAAAR,kBAAA,GAAEF,OAAO,CAACU,SAAS,cAAAR,kBAAA,cAAAA,kBAAA,GAAI,CAAC,KAAK,CAAC;IACvCS,OAAO,GAAAR,gBAAA,GAAEH,OAAO,CAACW,OAAO,cAAAR,gBAAA,cAAAA,gBAAA,GAAI;EAC9B,CAAC;;EAED;EACA,OAAOR,cAAc,CAACiB,YAAY,CAACJ,YAAY,CAAC;AAClD","ignoreList":[]}
@@ -0,0 +1,2 @@
1
+
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":[],"sources":["types.ts"],"sourcesContent":["// Dosya: src/types.ts\n\n/**\n * Native modülden dönen tek bir dosyanın yapısını tanımlar.\n */\nexport interface FileInfo {\n fileName: string;\n fileSize: number; // in bytes\n fileType: string | null;\n fileUri: string;\n base64: string;\n}\n\n/**\n * `pickFile` fonksiyonuna gönderilebilecek tüm opsiyonları tanımlar.\n */\nexport interface DocumentPickerOptions {\n /**\n * Birden fazla dosya seçimine izin ver.\n * @default false\n */\n multipleFiles?: boolean;\n\n /**\n * Filtrelenecek dosya tipleri (MIME types).\n * @default ['* / *'] (tüm dosyalar)\n * @example ['image/jpeg', 'application/pdf']\n */\n fileTypes?: string[];\n\n /**\n * MB cinsinden maksimum dosya boyutu.\n * @default 0 (limitsiz)\n */\n maxSize?: number;\n\n /**\n * Seçilebilecek maksimum dosya sayısı. `multipleFiles: true` olmalıdır.\n * Belirtilmezse ve `multipleFiles: true` ise varsayılan olarak 3'tür.\n * @default 0 (limitsiz, ama varsayılan mantığı uygulanır)\n */\n maxFiles?: number;\n\n /**\n * Zaten seçilmiş olduğu için tekrar seçilmesi engellenecek dosyaların URI listesi.\n */\n excludedUris?: string[];\n}"],"mappings":"","ignoreList":[]}
package/package.json ADDED
@@ -0,0 +1,161 @@
1
+ {
2
+ "name": "react-native-my-uploader-android",
3
+ "version": "1.0.21",
4
+ "description": "file uploader",
5
+ "main": "./lib/module/index.js",
6
+ "types": "./src/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "source": "./src/index.tsx",
10
+ "types": "./src/index.d.ts",
11
+ "default": "./lib/module/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "src",
16
+ "lib",
17
+ "android",
18
+ "ios",
19
+ "cpp",
20
+ "*.podspec",
21
+ "react-native.config.js",
22
+ "!ios/build",
23
+ "!android/build",
24
+ "!android/gradle",
25
+ "!android/gradlew",
26
+ "!android/gradlew.bat",
27
+ "!android/local.properties",
28
+ "!**/__tests__",
29
+ "!**/__fixtures__",
30
+ "!**/__mocks__",
31
+ "!**/.*"
32
+ ],
33
+ "scripts": {
34
+ "example": "yarn workspace react-native-my-uploader-example",
35
+ "test": "jest",
36
+ "typecheck": "tsc",
37
+ "lint": "eslint \"**/*.{js,ts,tsx}\"",
38
+ "clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
39
+ "prepare": "bob build",
40
+ "release": "release-it --only-version"
41
+ },
42
+ "keywords": [
43
+ "react-native",
44
+ "ios",
45
+ "android"
46
+ ],
47
+ "repository": {
48
+ "type": "git",
49
+ "url": "git+https://www.npmjs.com/~yrncskn.git"
50
+ },
51
+ "author": "Yaren Coskun <yarencoskunceng@gmail.com> (https://www.npmjs.com/~yrncskn)",
52
+ "license": "MIT",
53
+ "bugs": {
54
+ "url": "https://www.npmjs.com/~yrncskn/issues"
55
+ },
56
+ "homepage": "https://www.npmjs.com/~yrncskn#readme",
57
+ "publishConfig": {
58
+ "registry": "https://registry.npmjs.org/"
59
+ },
60
+ "devDependencies": {
61
+ "@commitlint/config-conventional": "^19.8.1",
62
+ "@eslint/compat": "^1.3.2",
63
+ "@eslint/eslintrc": "^3.3.1",
64
+ "@eslint/js": "^9.35.0",
65
+ "@evilmartians/lefthook": "^1.12.3",
66
+ "@react-native-community/bob": "^0.17.1",
67
+ "@react-native-community/cli": "20.0.1",
68
+ "@react-native/babel-preset": "0.81.1",
69
+ "@react-native/eslint-config": "^0.81.1",
70
+ "@release-it/conventional-changelog": "^10.0.1",
71
+ "@types/jest": "^29.5.14",
72
+ "@types/react": "^19.1.0",
73
+ "@typescript-eslint/eslint-plugin": "^8.46.4",
74
+ "@typescript-eslint/parser": "^8.46.4",
75
+ "commitlint": "^19.8.1",
76
+ "del-cli": "^6.0.0",
77
+ "eslint": "^9.35.0",
78
+ "eslint-config-prettier": "^10.1.8",
79
+ "eslint-plugin-ft-flow": "^3.0.11",
80
+ "eslint-plugin-jest": "^29.0.1",
81
+ "eslint-plugin-prettier": "^5.5.4",
82
+ "eslint-plugin-react-native": "^5.0.0",
83
+ "jest": "^29.7.0",
84
+ "prettier": "^3.6.2",
85
+ "react": "19.1.0",
86
+ "react-native": "0.81.1",
87
+ "react-native-builder-bob": "^0.40.14",
88
+ "release-it": "^19.0.4",
89
+ "turbo": "^2.5.6",
90
+ "typescript": "^5.9.2"
91
+ },
92
+ "peerDependencies": {
93
+ "react": "*",
94
+ "react-native": "*"
95
+ },
96
+ "workspaces": [
97
+ "example"
98
+ ],
99
+ "packageManager": "yarn@3.6.1",
100
+ "jest": {
101
+ "preset": "react-native",
102
+ "modulePathIgnorePatterns": [
103
+ "<rootDir>/example/node_modules",
104
+ "<rootDir>/lib/"
105
+ ]
106
+ },
107
+ "commitlint": {
108
+ "extends": [
109
+ "@commitlint/config-conventional"
110
+ ]
111
+ },
112
+ "release-it": {
113
+ "git": {
114
+ "commitMessage": "chore: release ${version}",
115
+ "tagName": "v${version}"
116
+ },
117
+ "npm": {
118
+ "publish": true
119
+ },
120
+ "github": {
121
+ "release": true
122
+ },
123
+ "plugins": {
124
+ "@release-it/conventional-changelog": {
125
+ "preset": {
126
+ "name": "angular"
127
+ }
128
+ }
129
+ }
130
+ },
131
+ "prettier": {
132
+ "quoteProps": "consistent",
133
+ "singleQuote": true,
134
+ "tabWidth": 2,
135
+ "trailingComma": "es5",
136
+ "useTabs": false
137
+ },
138
+ "react-native-builder-bob": {
139
+ "source": "src",
140
+ "output": "lib",
141
+ "targets": [
142
+ [
143
+ "module",
144
+ {
145
+ "esm": true
146
+ }
147
+ ],
148
+ [
149
+ "typescript",
150
+ {
151
+ "project": "tsconfig.build.json"
152
+ }
153
+ ]
154
+ ]
155
+ },
156
+ "create-react-native-library": {
157
+ "languages": "kotlin-objc",
158
+ "type": "turbo-module",
159
+ "version": "0.54.8"
160
+ }
161
+ }
@@ -0,0 +1,27 @@
1
+ import { NativeModules } from 'react-native';
2
+ import type { FileInfo, DocumentPickerOptions } from './types';
3
+
4
+
5
+ // Native modülün tip tanımı
6
+ interface MyUploaderType {
7
+ openDocument(options: DocumentPickerOptions): Promise<FileInfo[]>;
8
+ }
9
+
10
+ const LINKING_ERROR =
11
+ `The package 'react--native-my-uploader' doesn't seem to be linked. Make sure: \n\n` +
12
+ '- You rebuilt the app after installing the package\n' +
13
+ '- You are not using Expo Go\n';
14
+
15
+
16
+ const DocumentPicker = NativeModules.DocumentPicker
17
+ ? (NativeModules.DocumentPicker as MyUploaderType)
18
+ : new Proxy(
19
+ {},
20
+ {
21
+ get() {
22
+ throw new Error(LINKING_ERROR);
23
+ },
24
+ }
25
+ );
26
+
27
+ export default DocumentPicker;
package/src/index.d.ts ADDED
@@ -0,0 +1,60 @@
1
+ // Dosya: index.d.ts
2
+
3
+ // ADIM 1: Tipleri DIŞA AKTARARAK (export) doğrudan burada tanımla.
4
+ // (Artık 'import' kullanmıyoruz)
5
+
6
+ /**
7
+ * Native modülden dönen tek bir dosyanın yapısını tanımlar.
8
+ * Bu tip, paket kullanıcıları tarafından import edilebilir.
9
+ */
10
+ export interface FileInfo {
11
+ fileName: string;
12
+ fileSize: number; // in bytes
13
+ fileType: string | null;
14
+ fileUri: string;
15
+ base64: string;
16
+ }
17
+
18
+ /**
19
+ * `pickFile` fonksiyonuna gönderilebilecek tüm opsiyonları tanımlar.
20
+ * Bu tip, paket kullanıcıları tarafından import edilebilir.
21
+ */
22
+ export interface DocumentPickerOptions {
23
+ /**
24
+ * Birden fazla dosya seçimine izin ver.
25
+ * @default false
26
+ */
27
+ multipleFiles?: boolean;
28
+
29
+ /**
30
+ * Filtrelenecek dosya tipleri (MIME types).
31
+ * @default ['* / *']
32
+ */
33
+ fileTypes?: string[];
34
+
35
+ /**
36
+ * MB cinsinden maksimum dosya boyutu.
37
+ * @default 0 (limitsiz)
38
+ */
39
+ maxSize?: number;
40
+
41
+ /**
42
+ * Seçilebilecek maksimum dosya sayısı. `multipleFiles: true` olmalıdır.
43
+ * Belirtilmezse ve `multipleFiles: true` ise varsayılan olarak 3'tür.
44
+ */
45
+ maxFiles?: number;
46
+
47
+ /**
48
+ * Zaten seçilmiş olduğu için tekrar seçilmesi engellenecek dosyaların URI listesi.
49
+ */
50
+ excludedUris?: string[];
51
+ }
52
+
53
+ // ADIM 2: Fonksiyonu da DIŞA AKTARARAK (export) tanımla.
54
+
55
+ /**
56
+ * Dosya seçiciyi açar ve seçilen dosyaların bilgilerini döndürür.
57
+ * @param options Dosya seçici için yapılandırma ayarları.
58
+ * @returns Seçilen dosya bilgilerini içeren bir Promise<FileInfo[]> döner.
59
+ */
60
+ export function pickFile(options?: DocumentPickerOptions): Promise<FileInfo[]>;
package/src/index.tsx ADDED
@@ -0,0 +1,58 @@
1
+ import { NativeModules } from 'react-native';
2
+
3
+ // Gerekli tipleri ve arayüzleri import et
4
+ import type { FileInfo, DocumentPickerOptions } from './types';
5
+
6
+ // Native modülün düzgün bir şekilde bağlanıp bağlanmadığını kontrol eden güvenlik mekanizması
7
+ const LINKING_ERROR = `The package 'react-native-my-uploader' doesn't seem to be linked.`;
8
+
9
+ const DocumentPicker = NativeModules.DocumentPicker
10
+ ? NativeModules.DocumentPicker
11
+ : new Proxy(
12
+ {},
13
+ {
14
+ get() {
15
+ throw new Error(LINKING_ERROR);
16
+ },
17
+ }
18
+ );
19
+
20
+ /**
21
+ * Dosya seçiciyi açar ve seçilen dosyaların bilgilerini döndürür.
22
+ * @param options Dosya seçici için yapılandırma ayarları.
23
+ * @returns Seçilen dosya bilgilerini içeren bir Promise<FileInfo[]> döner.
24
+ */
25
+ export async function pickFile(
26
+ options: DocumentPickerOptions = {}
27
+ ): Promise<FileInfo[]> {
28
+ // Gelen opsiyonları varsayılan değerlerle birleştir
29
+ const { multipleFiles = false, maxFiles = 0, ...rest } = options;
30
+
31
+ if (!multipleFiles && maxFiles > 1) {
32
+ throw new Error(
33
+ '`maxFiles` cannot be greater than 1 when `multipleFiles` is false.'
34
+ );
35
+ }
36
+
37
+ // KURAL: `multipleFiles: true` iken `maxFiles` belirtilmemişse, varsayılan olarak 3 ata.
38
+ let effectiveMaxFiles = maxFiles;
39
+ if (multipleFiles && maxFiles === 0) {
40
+ effectiveMaxFiles = 3;
41
+ }
42
+
43
+ // Native koda gönderilecek nihai, temizlenmiş ve varsayılanları atanmış opsiyonları oluştur.
44
+ const finalOptions: DocumentPickerOptions = {
45
+ ...rest,
46
+ multipleFiles,
47
+ maxFiles: effectiveMaxFiles,
48
+ // Diğer opsiyonlar için de null/undefined kontrolü yap
49
+ excludedUris: options.excludedUris ?? [],
50
+ fileTypes: options.fileTypes ?? ['*/*'],
51
+ maxSize: options.maxSize ?? 0,
52
+ };
53
+
54
+ // Nihai opsiyonlarla native modülü çağır
55
+ return DocumentPicker.openDocument(finalOptions);
56
+ }
57
+
58
+ export type { FileInfo, DocumentPickerOptions };
package/src/types.ts ADDED
@@ -0,0 +1,48 @@
1
+ // Dosya: src/types.ts
2
+
3
+ /**
4
+ * Native modülden dönen tek bir dosyanın yapısını tanımlar.
5
+ */
6
+ export interface FileInfo {
7
+ fileName: string;
8
+ fileSize: number; // in bytes
9
+ fileType: string | null;
10
+ fileUri: string;
11
+ base64: string;
12
+ }
13
+
14
+ /**
15
+ * `pickFile` fonksiyonuna gönderilebilecek tüm opsiyonları tanımlar.
16
+ */
17
+ export interface DocumentPickerOptions {
18
+ /**
19
+ * Birden fazla dosya seçimine izin ver.
20
+ * @default false
21
+ */
22
+ multipleFiles?: boolean;
23
+
24
+ /**
25
+ * Filtrelenecek dosya tipleri (MIME types).
26
+ * @default ['* / *'] (tüm dosyalar)
27
+ * @example ['image/jpeg', 'application/pdf']
28
+ */
29
+ fileTypes?: string[];
30
+
31
+ /**
32
+ * MB cinsinden maksimum dosya boyutu.
33
+ * @default 0 (limitsiz)
34
+ */
35
+ maxSize?: number;
36
+
37
+ /**
38
+ * Seçilebilecek maksimum dosya sayısı. `multipleFiles: true` olmalıdır.
39
+ * Belirtilmezse ve `multipleFiles: true` ise varsayılan olarak 3'tür.
40
+ * @default 0 (limitsiz, ama varsayılan mantığı uygulanır)
41
+ */
42
+ maxFiles?: number;
43
+
44
+ /**
45
+ * Zaten seçilmiş olduğu için tekrar seçilmesi engellenecek dosyaların URI listesi.
46
+ */
47
+ excludedUris?: string[];
48
+ }