@vali98/react-native-fs 0.2.0 → 0.2.1

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.
@@ -1,165 +1,181 @@
1
1
  package com.chatterui.reactnativelocaldownload
2
2
 
3
- import com.facebook.react.bridge.ReactApplicationContext
4
- import com.facebook.react.bridge.Promise
5
- import com.facebook.react.module.annotations.ReactModule
6
-
7
- import android.content.ContentValues
8
3
  import android.content.ContentResolver
9
- import android.net.Uri
10
- import android.system.Os
4
+ import android.content.ContentValues
11
5
  import android.content.Intent
12
- import android.provider.MediaStore
6
+ import android.net.Uri
13
7
  import android.os.ParcelFileDescriptor
8
+ import android.provider.MediaStore
9
+ import android.system.Os
10
+ import com.facebook.react.bridge.Promise
11
+ import com.facebook.react.bridge.ReactApplicationContext
12
+ import com.facebook.react.module.annotations.ReactModule
14
13
  import java.io.File
15
14
  import java.io.FileInputStream
16
15
  import java.io.FileOutputStream
17
16
  import java.net.URLConnection
18
17
 
19
18
  @ReactModule(name = ReactNativeLocalDownloadModule.NAME)
20
- class ReactNativeLocalDownloadModule(private val reactContext: ReactApplicationContext) :
21
- NativeReactNativeLocalDownloadSpec(reactContext) {
22
-
23
- override fun getName(): String {
24
- return NAME
25
- }
26
-
27
- override fun getContentFd(contentUri: String, promise: Promise) {
19
+ class ReactNativeLocalDownloadModule(
20
+ private val reactContext: ReactApplicationContext,
21
+ ) : NativeReactNativeLocalDownloadSpec(reactContext) {
22
+ override fun getName(): String = NAME
23
+
24
+ override fun getContentFd(
25
+ contentUri: String,
26
+ promise: Promise,
27
+ ) {
28
28
  try {
29
- val uri = Uri.parse(contentUri)
29
+ val uri = Uri.parse(contentUri)
30
30
 
31
- val pfd = reactContext.contentResolver
32
- .openFileDescriptor(uri, "r")
33
- ?: run {
31
+ val pfd =
32
+ reactContext.contentResolver
33
+ .openFileDescriptor(uri, "r")
34
+ ?: run {
34
35
  promise.reject("FD_OPEN_FAILED", "Unable to open content URI")
35
36
  return
36
- }
37
-
38
- val fd = pfd.detachFd()
39
- promise.resolve("/proc/self/fd/$fd")
37
+ }
40
38
 
39
+ val fd = pfd.detachFd()
40
+ promise.resolve("$fd")
41
41
  } catch (e: Exception) {
42
- promise.reject(
42
+ promise.reject(
43
43
  "GET_FD_ERROR",
44
44
  "Failed to get detached FD: ${e.message}",
45
- e
46
- )
45
+ e,
46
+ )
47
47
  }
48
48
  }
49
49
 
50
- override fun closeFd(fdOrPath: String, promise: Promise) {
50
+ override fun closeFd(
51
+ fdOrPath: String,
52
+ promise: Promise,
53
+ ) {
51
54
  try {
52
- val fdInt = when {
53
- fdOrPath.startsWith("/proc/") ->
55
+ val fdInt =
56
+ when {
57
+ fdOrPath.startsWith("/proc/") -> {
54
58
  fdOrPath.substringAfterLast("/").toInt()
55
- else ->
59
+ }
60
+
61
+ else -> {
56
62
  fdOrPath.toInt()
63
+ }
57
64
  }
58
- ParcelFileDescriptor.adoptFd(fdInt).close()
59
- promise.resolve(true)
65
+ ParcelFileDescriptor.adoptFd(fdInt).close()
66
+ promise.resolve(true)
60
67
  } catch (e: Exception) {
61
- promise.reject(
68
+ promise.reject(
62
69
  "FD_CLOSE_ERROR",
63
70
  "Failed to close FD: ${e.message}",
64
- e
65
- )
71
+ e,
72
+ )
66
73
  }
67
74
  }
68
75
 
69
- override fun persistContentPermission(uriString: String, promise: Promise) {
76
+ override fun persistContentPermission(
77
+ uriString: String,
78
+ promise: Promise,
79
+ ) {
70
80
  try {
71
- val uri = Uri.parse(uriString)
81
+ val uri = Uri.parse(uriString)
72
82
 
73
- val flags =
74
- Intent.FLAG_GRANT_READ_URI_PERMISSION or
75
- Intent.FLAG_GRANT_WRITE_URI_PERMISSION
83
+ val flags =
84
+ Intent.FLAG_GRANT_READ_URI_PERMISSION or
85
+ Intent.FLAG_GRANT_WRITE_URI_PERMISSION
76
86
 
77
- reactContext.contentResolver
87
+ reactContext.contentResolver
78
88
  .takePersistableUriPermission(uri, flags)
79
89
 
80
- promise.resolve(true)
81
-
90
+ promise.resolve(true)
82
91
  } catch (e: SecurityException) {
83
- promise.reject(
92
+ promise.reject(
84
93
  "PERSIST_PERMISSION_DENIED",
85
94
  "Persistable permission not granted for this URI",
86
- e
87
- )
95
+ e,
96
+ )
88
97
  } catch (e: Exception) {
89
- promise.reject(
98
+ promise.reject(
90
99
  "PERSIST_PERMISSION_ERROR",
91
100
  e.message,
92
- e
93
- )
101
+ e,
102
+ )
94
103
  }
95
- }
96
-
104
+ }
97
105
 
98
- override fun localDownload(uri: String, promise: Promise) {
106
+ override fun localDownload(
107
+ uri: String,
108
+ promise: Promise,
109
+ ) {
99
110
  try {
100
111
  val inputFile = File(uri)
101
112
  if (!inputFile.exists()) {
102
113
  promise.reject("FILE_NOT_FOUND", "File does not exist at path: $uri")
103
114
  return
104
115
  }
105
-
116
+
106
117
  val fileName = inputFile.name
107
118
  val mimeType = URLConnection.guessContentTypeFromName(inputFile.name) ?: "application/octet-stream"
108
- val resolver : ContentResolver = reactContext.contentResolver
119
+ val resolver: ContentResolver = reactContext.contentResolver
109
120
  val uniqueName = getUniqueFileName(resolver, fileName)
110
- val contentValues = ContentValues().apply {
111
- put(MediaStore.Downloads.DISPLAY_NAME, uniqueName)
112
- put(MediaStore.Downloads.MIME_TYPE, mimeType)
113
- put(MediaStore.Downloads.IS_PENDING, 1)
114
- }
115
-
121
+ val contentValues =
122
+ ContentValues().apply {
123
+ put(MediaStore.Downloads.DISPLAY_NAME, uniqueName)
124
+ put(MediaStore.Downloads.MIME_TYPE, mimeType)
125
+ put(MediaStore.Downloads.IS_PENDING, 1)
126
+ }
127
+
116
128
  val collection = MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
117
129
  val itemUri = resolver.insert(collection, contentValues)
118
-
130
+
119
131
  if (itemUri == null) {
120
132
  promise.reject("SAVE_ERROR", "Failed to create destination file in MediaStore.")
121
133
  return
122
134
  }
123
-
135
+
124
136
  resolver.openOutputStream(itemUri)?.use { outputStream ->
125
137
  inputFile.inputStream().use { inputStream ->
126
138
  inputStream.copyTo(outputStream)
127
139
  }
128
140
  }
129
-
141
+
130
142
  // Mark the item as not pending so it's visible to user
131
143
  contentValues.clear()
132
144
  contentValues.put(MediaStore.Downloads.IS_PENDING, 0)
133
145
  resolver.update(itemUri, contentValues, null, null)
134
-
146
+
135
147
  promise.resolve(itemUri.toString())
136
148
  } catch (e: Exception) {
137
149
  promise.reject("DOWNLOAD_ERROR", "Failed to save file via MediaStore: ${e.message}", e)
138
150
  }
139
151
  }
140
-
141
- private fun getUniqueFileName(resolver: ContentResolver, baseName: String): String {
152
+
153
+ private fun getUniqueFileName(
154
+ resolver: ContentResolver,
155
+ baseName: String,
156
+ ): String {
142
157
  var name = baseName
143
158
  val nameWithoutExtension = File(baseName).nameWithoutExtension
144
159
  val extension = File(baseName).extension
145
160
  var index = 1
146
-
161
+
147
162
  val collection = MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
148
-
163
+
149
164
  val projection = arrayOf(MediaStore.Downloads.DISPLAY_NAME)
150
165
  val selection = "${MediaStore.Downloads.DISPLAY_NAME} = ?"
151
166
  val selectionArgs = arrayOf(name)
152
-
167
+
153
168
  while (resolver.query(collection, projection, selection, selectionArgs, null)?.use { it.moveToFirst() } == true) {
154
- name = if (extension.isNotEmpty()) {
155
- "$nameWithoutExtension ($index).$extension"
156
- } else {
157
- "$nameWithoutExtension ($index)"
158
- }
169
+ name =
170
+ if (extension.isNotEmpty()) {
171
+ "$nameWithoutExtension ($index).$extension"
172
+ } else {
173
+ "$nameWithoutExtension ($index)"
174
+ }
159
175
  selectionArgs[0] = name
160
176
  index++
161
177
  }
162
-
178
+
163
179
  return name
164
180
  }
165
181
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vali98/react-native-fs",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Download folder access for react-native",
5
5
  "source": "./src/index.tsx",
6
6
  "main": "./lib/module/index.js",