react-native-fs-turbo 0.2.0 → 0.3.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.
package/README.md CHANGED
@@ -278,61 +278,175 @@ type ReadDirItem = {
278
278
 
279
279
  Node.js style version of `readDir` that returns only the names. Note the lowercase `d`.
280
280
 
281
- ### `readFile(filepath: string, encoding?: 'utf8' | 'ascii' | 'base64' | 'uint8' | 'float32'): string | number[]`
281
+ ### `readFile(filepath: string, options?: ReadOptions): string | number[]`
282
282
 
283
- Reads the file at `path` and return contents. `encoding` can be one of `utf8` (default), `ascii`, `base64`, `uint8`. Use `base64` or `uint8` or `float32` for reading binary files.
283
+ Reads the file at `path` and return contents. `options` can be string of encrypted types or object, default is `utf8`. Use `base64` or `uint8` or `float32` encoding for reading binary files.
284
+
285
+ ```ts
286
+ type ReadOptions =
287
+ | 'utf8' | 'ascii' | 'base64' | 'uint8' | 'float32'
288
+ | { encoding: 'utf8' | 'ascii' | 'base64' | 'uint8' | 'float32' };
289
+ ```
284
290
 
285
291
  Note: you will take quite a performance hit if you are reading big files
286
292
 
287
- ### `read(filepath: string, length: number, position: number, encoding?: 'utf8' | 'ascii' | 'base64' | 'uint8' | 'float32'): string | number[]`
293
+ ### `read(filepath: string, length: number, position: number, options?: ReadOptions): string | number[]`
288
294
 
289
- Reads `length` bytes from the given `position` of the file at `path` and returns contents. `encoding` can be one of `utf8` (default), `ascii`, `base64`, `uint8`, `float32`. Use `base64` or `uint8` or `float32` for reading binary files.
295
+ Reads `length` bytes from the given `position` of the file at `path` and returns contents. `options` can be string of encrypted types or object, default is `utf8`. Use `base64` or `uint8` or `float32` encoding for reading binary files.
296
+
297
+ ```ts
298
+ type ReadOptions =
299
+ | 'utf8' | 'ascii' | 'base64' | 'uint8' | 'float32'
300
+ | { encoding: 'utf8' | 'ascii' | 'base64' | 'uint8' | 'float32' };
301
+ ```
290
302
 
291
303
  Note: reading big files piece by piece using this method may be useful in terms of performance.
292
304
  Note: `float32` size is 4 bytes, so `position` and `length` should be specified in bytes (multiplied by 4)
293
305
 
294
- ### (Android only) `readFileAssets(filepath: string, encoding?: "utf8" | 'ascii' | "base64") => string[]`
306
+ ### (Android only) `readFileAssets(filepath: string, options?: ReadOptions) => string[]`
295
307
 
296
- Reads the file at `path` in the Android app's assets folder and return contents. `encoding` can be one of `utf8` (default), `ascii`, `base64`. Use `base64` or `uint8` for reading binary files.
308
+ Reads the file at `path` in the Android app's assets folder and return contents. `options` can be string of encrypted types or object, default is `utf8`. Use `base64` encoding for reading binary files.
297
309
 
298
310
  `filepath` is the relative path to the file from the root of the `assets` folder.
299
311
 
300
- ### (Android only) `readFileRes: (filepath: string, encoding?: "utf8" | 'ascii' | "base64") => string[]`
312
+ ```ts
313
+ type ReadOptions =
314
+ | 'utf8' | 'ascii' | 'base64'
315
+ | { encoding: 'utf8' | 'ascii' | 'base64' };
316
+ ```
301
317
 
302
- Reads the file named `filename` in the Android app's `res` folder and return contents. Only the file name (not folder) needs to be specified. The file type will be detected from the extension and automatically located within `res/drawable` (for image files) or `res/raw` (for everything else). `encoding` can be one of `utf8` (default), `ascii`, `base64`. Use `base64` for reading binary files.
318
+ ### (Android only) `readFileRes: (filepath: string, options?: ReadOptions) => string[]`
303
319
 
304
- ### `writeFile(filepath: string, contents: string | number[], encoding?: "utf8" | 'ascii' | "base64" | "uint8" | "float32"): void`
320
+ Reads the file named `filename` in the Android app's `res` folder and return contents. Only the file name (not folder) needs to be specified. The file type will be detected from the extension and automatically located within `res/drawable` (for image files) or `res/raw` (for everything else). `options` can be string of encrypted types or object, default is `utf8`. Use `base64` encoding for reading binary files.
305
321
 
306
- Write the `contents` to `filepath`. `encoding` can be one of `utf8` (default), `ascii`, `base64`, `uint8`, `float32`. `options` optionally takes an object specifying the file's properties, like mode etc.
322
+ ```ts
323
+ type ReadOptions =
324
+ | 'utf8' | 'ascii' | 'base64'
325
+ | { encoding: 'utf8' | 'ascii' };
326
+ ```
307
327
 
308
- ### `appendFile(filepath: string, contents: string | number[], encoding?: "utf8" | 'ascii' | "base64" | "uint8" | "float32"): void`
328
+ ### `writeFile(filepath: string, contents: string | number[], options?: WriteOptions): void`
309
329
 
310
- Append the `contents` to `filepath`. `encoding` can be one of `utf8` (default), `ascii`, `base64`, `uint8`, `float32`.
330
+ Write the `contents` to `filepath`. `options` can be string of encrypted types or object, default is `utf8`
331
+
332
+ ```ts
333
+ type WriteOptions =
334
+ | 'utf8' | 'ascii' | 'base64' | 'uint8' | 'float32'
335
+ | {
336
+ encoding?: 'utf8' | 'ascii' | 'base64' | 'uint8' | 'float32',
337
+ NSFileProtectionKey?:
338
+ |"NSFileProtectionNone"
339
+ | "NSFileProtectionComplete"
340
+ | "NSFileProtectionCompleteUnlessOpen"
341
+ | "NSFileProtectionCompleteUntilFirstUserAuthentication"
342
+ | "NSFileProtectionCompleteWhenUserInactive" // iOS 17+ only
343
+ };
344
+ ```
345
+
346
+ (IOS only): `options.NSFileProtectionKey` property can be provided to set this attribute on iOS platforms.
347
+
348
+ ### `appendFile(filepath: string, contents: string | number[], options?: WriteOptions): void`
349
+
350
+ Append the `contents` to `filepath`. `encoding` can be string of encrypted types or object, default is `utf8`.
351
+
352
+ ```ts
353
+ type WriteOptions =
354
+ | 'utf8' | 'ascii' | 'base64' | 'uint8' | 'float32'
355
+ | {
356
+ encoding?: 'utf8' | 'ascii' | 'base64' | 'uint8' | 'float32',
357
+ NSFileProtectionKey?:
358
+ |"NSFileProtectionNone"
359
+ | "NSFileProtectionComplete"
360
+ | "NSFileProtectionCompleteUnlessOpen"
361
+ | "NSFileProtectionCompleteUntilFirstUserAuthentication"
362
+ | "NSFileProtectionCompleteWhenUserInactive" // iOS 17+ only
363
+ };
364
+ ```
311
365
 
312
- ### `write(filepath: string, contents: string | number[], position?: number, encoding?: "utf8" | "base64" | "uint8" | "float32"): void`
366
+ (IOS only): `options.NSFileProtectionKey` property can be provided to set this attribute on iOS platforms.
313
367
 
314
- Write the `contents` to `filepath` at the given random access position. When `position` is `undefined` or `-1` the contents is appended to the end of the file. `encoding` can be one of `utf8` (default), `ascii`, `base64`, `uint8`, `float32`.
368
+ ### `write(filepath: string, contents: string | number[], position?: number, options?: WriteOptions): void`
369
+
370
+ Write the `contents` to `filepath` at the given random access position. When `position` is `undefined` or `-1` the contents is appended to the end of the file. `encoding` can be string of encrypted types or object, default is `utf8`.
371
+
372
+ ```ts
373
+ type WriteOptions =
374
+ | 'utf8' | 'ascii' | 'base64' | 'uint8' | 'float32'
375
+ | {
376
+ encoding?: 'utf8' | 'ascii' | 'base64' | 'uint8' | 'float32',
377
+ NSFileProtectionKey?:
378
+ |"NSFileProtectionNone"
379
+ | "NSFileProtectionComplete"
380
+ | "NSFileProtectionCompleteUnlessOpen"
381
+ | "NSFileProtectionCompleteUntilFirstUserAuthentication"
382
+ | "NSFileProtectionCompleteWhenUserInactive" // iOS 17+ only
383
+ };
384
+ ```
315
385
 
316
386
  Note: `float32` size is 4 bytes, so `position` should be specified in bytes (multiplied by 4)
317
387
 
318
- ### `moveFile(filepath: string, destPath: string): void`
388
+ (IOS only): `options.NSFileProtectionKey` property can be provided to set this attribute on iOS platforms.
389
+
390
+ ### `moveFile(filepath: string, destPath: string, options?: MoveCopyOptions): void`
319
391
 
320
392
  Moves the file located at `filepath` to `destPath`. This is more performant than reading and then re-writing the file data because the move is done natively and the data doesn't have to be copied or cross the bridge.
321
393
 
394
+ ```ts
395
+ type MoveCopyOptions =
396
+ | {
397
+ NSFileProtectionKey?:
398
+ |"NSFileProtectionNone"
399
+ | "NSFileProtectionComplete"
400
+ | "NSFileProtectionCompleteUnlessOpen"
401
+ | "NSFileProtectionCompleteUntilFirstUserAuthentication"
402
+ | "NSFileProtectionCompleteWhenUserInactive" // iOS 17+ only
403
+ };
404
+ ```
405
+
322
406
  Note: Overwrites existing file
323
407
 
324
- ### `copyFolder(srcFolderPath: string, destFolderPath: string): void`
408
+ (IOS only): `options.NSFileProtectionKey` property can be provided to set this attribute on iOS platforms.
409
+
410
+ ### `copyFolder(srcFolderPath: string, destFolderPath: string, options?: MoveCopyOptions): void`
325
411
 
326
412
  Copies the contents located at `srcFolderPath` to `destFolderPath`.
327
413
 
414
+ ```ts
415
+ type MoveCopyOptions =
416
+ | {
417
+ NSFileProtectionKey?:
418
+ |"NSFileProtectionNone"
419
+ | "NSFileProtectionComplete"
420
+ | "NSFileProtectionCompleteUnlessOpen"
421
+ | "NSFileProtectionCompleteUntilFirstUserAuthentication"
422
+ | "NSFileProtectionCompleteWhenUserInactive" // iOS 17+ only
423
+ };
424
+ ```
425
+
328
426
  Note: Recursively replaces all files and folders
329
427
 
330
- ### `copyFile(filepath: string, destPath: string): void`
428
+ (IOS only): `options.NSFileProtectionKey` property can be provided to set this attribute on iOS platforms.
429
+
430
+ ### `copyFile(filepath: string, destPath: string, options?: MoveCopyOptions): void`
331
431
 
332
432
  Copies the file located at `filepath` to `destPath`.
333
433
 
434
+ ```ts
435
+ type MoveCopyOptions =
436
+ | {
437
+ NSFileProtectionKey?:
438
+ |"NSFileProtectionNone"
439
+ | "NSFileProtectionComplete"
440
+ | "NSFileProtectionCompleteUnlessOpen"
441
+ | "NSFileProtectionCompleteUntilFirstUserAuthentication"
442
+ | "NSFileProtectionCompleteWhenUserInactive" // iOS 17+ only
443
+ };
444
+ ```
445
+
334
446
  Note: Error will be thrown if the file already exists.
335
447
 
448
+ (IOS only): `options.NSFileProtectionKey` property can be provided to set this attribute on iOS platforms.
449
+
336
450
  ### (Android only) `copyFileAssets(filepath: string, destPath: string): void`
337
451
 
338
452
  Copies the file at `filepath` in the Android app's assets folder and copies it to the given `destPath ` path.
@@ -449,12 +563,20 @@ Note: `ctime` no longer supported
449
563
  Create a directory at `filepath`. Automatically creates parents and does not throw if already exists (works like Linux `mkdir -p`).
450
564
 
451
565
  ```ts
452
- type MkdirOptions = {
453
- NSURLIsExcludedFromBackupKey?: boolean; // iOS only
454
- };
566
+ type MkdirOptions =
567
+ | {
568
+ NSFileProtectionKey?:
569
+ |"NSFileProtectionNone"
570
+ | "NSFileProtectionComplete"
571
+ | "NSFileProtectionCompleteUnlessOpen"
572
+ | "NSFileProtectionCompleteUntilFirstUserAuthentication"
573
+ | "NSFileProtectionCompleteWhenUserInactive"; // iOS 17+ only
574
+ NSURLIsExcludedFromBackupKey?: boolean;
575
+ };
455
576
  ```
456
577
 
457
- (IOS only): The `NSURLIsExcludedFromBackupKey` property can be provided to set this attribute on iOS platforms. Apple will *reject* apps for storing offline cache data that does not have this attribute.
578
+ (IOS only): `options.NSFileProtectionKey` property can be provided to set this attribute on iOS platforms.
579
+ (IOS only): The `options.NSURLIsExcludedFromBackupKey` property can be provided to set this attribute on iOS platforms. Apple will *reject* apps for storing offline cache data that does not have this attribute.
458
580
 
459
581
  ### `downloadFile(options: DownloadFileOptions, completeCallback?: DownloadResultFunc, errorCallback?: DownloadErrorFunc): DownloadResult | Promise<DownloadResult>`
460
582
 
@@ -13,58 +13,92 @@ void JavaHashMapToStlStringStringMap(JNIEnv *env, jobject hashMap, std::map<std:
13
13
  // Get the Map's entry Set.
14
14
  jclass mapClass = env->FindClass("java/util/Map");
15
15
  if (mapClass == nullptr) {
16
- return;
16
+ env->DeleteLocalRef(hashMap);
17
+ return;
17
18
  }
18
19
  jmethodID entrySet =
19
- env->GetMethodID(mapClass, "entrySet", "()Ljava/util/Set;");
20
+ env->GetMethodID(mapClass, "entrySet", "()Ljava/util/Set;");
20
21
  if (entrySet == nullptr) {
22
+ env->DeleteLocalRef(hashMap);
23
+ env->DeleteLocalRef(mapClass);
21
24
  return;
22
25
  }
23
26
  jobject set = env->CallObjectMethod(hashMap, entrySet);
24
27
  if (set == nullptr) {
28
+ env->DeleteLocalRef(hashMap);
29
+ env->DeleteLocalRef(mapClass);
25
30
  return;
26
31
  }
27
32
  // Obtain an iterator over the Set
28
33
  jclass setClass = env->FindClass("java/util/Set");
29
34
  if (setClass == nullptr) {
35
+ env->DeleteLocalRef(hashMap);
36
+ env->DeleteLocalRef(mapClass);
37
+ env->DeleteLocalRef(set);
30
38
  return;
31
39
  }
32
40
  jmethodID iterator =
33
- env->GetMethodID(setClass, "iterator", "()Ljava/util/Iterator;");
41
+ env->GetMethodID(setClass, "iterator", "()Ljava/util/Iterator;");
34
42
  if (iterator == nullptr) {
43
+ env->DeleteLocalRef(hashMap);
44
+ env->DeleteLocalRef(mapClass);
45
+ env->DeleteLocalRef(set);
46
+ env->DeleteLocalRef(setClass);
35
47
  return;
36
48
  }
37
49
  jobject iter = env->CallObjectMethod(set, iterator);
38
50
  if (iter == nullptr) {
51
+ env->DeleteLocalRef(hashMap);
52
+ env->DeleteLocalRef(mapClass);
53
+ env->DeleteLocalRef(set);
54
+ env->DeleteLocalRef(setClass);
39
55
  return;
40
56
  }
41
57
  // Get the Iterator method IDs
42
58
  jclass iteratorClass = env->FindClass("java/util/Iterator");
43
59
  if (iteratorClass == nullptr) {
60
+ env->DeleteLocalRef(hashMap);
61
+ env->DeleteLocalRef(mapClass);
62
+ env->DeleteLocalRef(set);
63
+ env->DeleteLocalRef(setClass);
64
+ env->DeleteLocalRef(iter);
44
65
  return;
45
66
  }
46
67
  jmethodID hasNext = env->GetMethodID(iteratorClass, "hasNext", "()Z");
47
- if (hasNext == nullptr) {
48
- return;
49
- }
50
68
  jmethodID next =
51
- env->GetMethodID(iteratorClass, "next", "()Ljava/lang/Object;");
52
- if (next == nullptr) {
69
+ env->GetMethodID(iteratorClass, "next", "()Ljava/lang/Object;");
70
+ if (hasNext == nullptr || next == nullptr) {
71
+ env->DeleteLocalRef(hashMap);
72
+ env->DeleteLocalRef(mapClass);
73
+ env->DeleteLocalRef(set);
74
+ env->DeleteLocalRef(setClass);
75
+ env->DeleteLocalRef(iter);
76
+ env->DeleteLocalRef(iteratorClass);
53
77
  return;
54
78
  }
55
79
  // Get the Entry class method IDs
56
80
  jclass entryClass = env->FindClass("java/util/Map$Entry");
57
81
  if (entryClass == nullptr) {
82
+ env->DeleteLocalRef(hashMap);
83
+ env->DeleteLocalRef(mapClass);
84
+ env->DeleteLocalRef(set);
85
+ env->DeleteLocalRef(setClass);
86
+ env->DeleteLocalRef(iter);
87
+ env->DeleteLocalRef(iteratorClass);
58
88
  return;
59
89
  }
60
90
  jmethodID getKey =
61
- env->GetMethodID(entryClass, "getKey", "()Ljava/lang/Object;");
62
- if (getKey == nullptr) {
63
- return;
64
- }
91
+ env->GetMethodID(entryClass, "getKey", "()Ljava/lang/Object;");
65
92
  jmethodID getValue =
66
- env->GetMethodID(entryClass, "getValue", "()Ljava/lang/Object;");
67
- if (getValue == nullptr) {
93
+ env->GetMethodID(entryClass, "getValue", "()Ljava/lang/Object;");
94
+ if (getKey == nullptr || getValue == nullptr) {
95
+ env->DeleteLocalRef(hashMap);
96
+ env->DeleteLocalRef(mapClass);
97
+ env->DeleteLocalRef(set);
98
+ env->DeleteLocalRef(setClass);
99
+ env->DeleteLocalRef(iter);
100
+ env->DeleteLocalRef(iteratorClass);
101
+ env->DeleteLocalRef(entryClass);
68
102
  return;
69
103
  }
70
104
  // Iterate over the entry Set
@@ -90,6 +124,13 @@ void JavaHashMapToStlStringStringMap(JNIEnv *env, jobject hashMap, std::map<std:
90
124
  env->ReleaseStringUTFChars(value, valueStr);
91
125
  env->DeleteLocalRef(value);
92
126
  }
127
+ env->DeleteLocalRef(hashMap);
128
+ env->DeleteLocalRef(mapClass);
129
+ env->DeleteLocalRef(set);
130
+ env->DeleteLocalRef(setClass);
131
+ env->DeleteLocalRef(iter);
132
+ env->DeleteLocalRef(iteratorClass);
133
+ env->DeleteLocalRef(entryClass);
93
134
  }
94
135
 
95
136
  extern "C"
@@ -102,14 +143,6 @@ JNIEXPORT void JNICALL Java_com_cmpayc_rnfsturbo_RNFSTurboPlatformHelper_downloa
102
143
  ) {
103
144
  std::map<int, DownloadCallbacks>::iterator it = RNFSTurboPlatformHelper::downloadCallbacks.find(jobId);
104
145
  if (it != RNFSTurboPlatformHelper::downloadCallbacks.end()) {
105
- const auto now = std::chrono::steady_clock::now();
106
- const auto elapsedTime = std::chrono::duration_cast<std::chrono::milliseconds>(
107
- now - RNFSTurboPlatformHelper::downloadCallbacks[jobId].lastProgressCall
108
- ).count();
109
- RNFSTurboPlatformHelper::downloadCallbacks[jobId].lastProgressCall = now - std::chrono::seconds(1);
110
- if (elapsedTime < 50) {
111
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
112
- }
113
146
  RNFSTurboPlatformHelper::downloadCallbacks[jobId].completeCallback(
114
147
  jobId,
115
148
  statusCode,
@@ -168,20 +201,13 @@ JNIEXPORT void JNICALL Java_com_cmpayc_rnfsturbo_RNFSTurboPlatformHelper_downloa
168
201
  double contentLength,
169
202
  double bytesWritten
170
203
  ) {
171
- std::map<int, DownloadCallbacks>::iterator callback = RNFSTurboPlatformHelper::downloadCallbacks.find(jobId);
172
- if (callback != RNFSTurboPlatformHelper::downloadCallbacks.end()) {
173
- const auto now = std::chrono::steady_clock::now();
174
- const auto elapsedTime = std::chrono::duration_cast<std::chrono::milliseconds>(
175
- now - RNFSTurboPlatformHelper::downloadCallbacks[jobId].lastProgressCall
176
- ).count();
177
- if (elapsedTime > 50) {
178
- RNFSTurboPlatformHelper::downloadCallbacks[jobId].progressCallback(
179
- jobId,
180
- static_cast<float>(contentLength),
181
- static_cast<float>(bytesWritten)
182
- );
183
- RNFSTurboPlatformHelper::downloadCallbacks[jobId].lastProgressCall = now;
184
- }
204
+ std::map<int, DownloadCallbacks>::iterator it = RNFSTurboPlatformHelper::downloadCallbacks.find(jobId);
205
+ if (it != RNFSTurboPlatformHelper::downloadCallbacks.end()) {
206
+ RNFSTurboPlatformHelper::downloadCallbacks[jobId].progressCallback(
207
+ jobId,
208
+ static_cast<float>(contentLength),
209
+ static_cast<float>(bytesWritten)
210
+ );
185
211
  }
186
212
  }
187
213
 
@@ -196,12 +222,6 @@ JNIEXPORT void JNICALL Java_com_cmpayc_rnfsturbo_RNFSTurboPlatformHelper_uploadC
196
222
  ) {
197
223
  std::map<int, UploadCallbacks>::iterator it = RNFSTurboPlatformHelper::uploadCallbacks.find(jobId);
198
224
  if (it != RNFSTurboPlatformHelper::uploadCallbacks.end()) {
199
- const auto now = std::chrono::steady_clock::now();
200
- const auto elapsedTime = std::chrono::duration_cast<std::chrono::milliseconds>(now - RNFSTurboPlatformHelper::uploadCallbacks[jobId].lastProgressCall).count();
201
- RNFSTurboPlatformHelper::uploadCallbacks[jobId].lastProgressCall = now - std::chrono::seconds(1);
202
- if (elapsedTime < 50) {
203
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
204
- }
205
225
  std::map<std::string, std::string> headers;
206
226
  JavaHashMapToStlStringStringMap(env, headersObj, headers);
207
227
  const char *body = env->GetStringUTFChars(bodyStr, nullptr);
@@ -233,20 +253,13 @@ JNIEXPORT void JNICALL Java_com_cmpayc_rnfsturbo_RNFSTurboPlatformHelper_uploadP
233
253
  double totalBytesExpectedToSend,
234
254
  double totalBytesSent
235
255
  ) {
236
- std::map<int, UploadCallbacks>::iterator callback = RNFSTurboPlatformHelper::uploadCallbacks.find(jobId);
237
- if (callback != RNFSTurboPlatformHelper::uploadCallbacks.end()) {
238
- const auto now = std::chrono::steady_clock::now();
239
- const auto elapsedTime = std::chrono::duration_cast<std::chrono::milliseconds>(
240
- now - RNFSTurboPlatformHelper::uploadCallbacks[jobId].lastProgressCall
241
- ).count();
242
- if (elapsedTime > 50) {
243
- RNFSTurboPlatformHelper::uploadCallbacks[jobId].progressCallback(
244
- jobId,
245
- static_cast<float>(totalBytesExpectedToSend),
246
- static_cast<float>(totalBytesSent)
247
- );
248
- RNFSTurboPlatformHelper::uploadCallbacks[jobId].lastProgressCall = now;
249
- }
256
+ std::map<int, UploadCallbacks>::iterator it = RNFSTurboPlatformHelper::uploadCallbacks.find(jobId);
257
+ if (it != RNFSTurboPlatformHelper::uploadCallbacks.end()) {
258
+ RNFSTurboPlatformHelper::uploadCallbacks[jobId].progressCallback(
259
+ jobId,
260
+ static_cast<float>(totalBytesExpectedToSend),
261
+ static_cast<float>(totalBytesSent)
262
+ );
250
263
  }
251
264
  }
252
265
 
@@ -312,7 +325,7 @@ std::vector<ReadDirItem> RNFSTurboPlatformHelper::readDirAssets(const char* dirP
312
325
  jniObj,
313
326
  mid,
314
327
  jniEnv->NewStringUTF(dirPath)
315
- );
328
+ );
316
329
  if (jniEnv->ExceptionCheck()) {
317
330
  jniEnv->ExceptionClear();
318
331
  throw "Dir not exists or access denied";
@@ -341,8 +354,8 @@ std::vector<ReadDirItem> RNFSTurboPlatformHelper::readDirAssets(const char* dirP
341
354
  jniEnv->ReleaseStringUTFChars(isDirectoryStr, isDirectoryChr);
342
355
  jniEnv->DeleteLocalRef(isDirectoryStr);
343
356
  }
344
- jniEnv->DeleteLocalRef(filesObject);
345
357
  jniEnv->DeleteLocalRef(jniCls);
358
+ jniEnv->DeleteLocalRef(filesObject);
346
359
 
347
360
  return files;
348
361
  }
@@ -369,6 +382,9 @@ std::string RNFSTurboPlatformHelper::readFileAssetsOrRes(const char* filePath, b
369
382
  std::string fileData = (char*) fileJBytes;
370
383
  jniEnv->ReleaseByteArrayElements(fileBytesArr, fileJBytes, 0);
371
384
 
385
+ jniEnv->DeleteLocalRef(jniCls);
386
+ jniEnv->DeleteLocalRef(fileBytesArr);
387
+
372
388
  return fileData;
373
389
  }
374
390
 
@@ -387,6 +403,7 @@ void RNFSTurboPlatformHelper::copyFileAssetsOrRes(const char *filePath, const ch
387
403
  jniEnv->NewStringUTF(destPath),
388
404
  isRes
389
405
  );
406
+ jniEnv->DeleteLocalRef(jniCls);
390
407
  if (jniEnv->ExceptionCheck()) {
391
408
  jniEnv->ExceptionClear();
392
409
  throw isRes ? "Failed to copy res" : "Failed to copy asset";
@@ -407,6 +424,7 @@ bool RNFSTurboPlatformHelper::existsAssetsOrRes(const char *filePath, bool isRes
407
424
  jniEnv->NewStringUTF(filePath),
408
425
  isRes
409
426
  );
427
+ jniEnv->DeleteLocalRef(jniCls);
410
428
  if (jniEnv->ExceptionCheck()) {
411
429
  jniEnv->ExceptionClear();
412
430
  throw isRes ? "Failed to open asset" : "Failed to open res";
@@ -469,7 +487,7 @@ void RNFSTurboPlatformHelper::downloadFile(
469
487
  }
470
488
 
471
489
  jniEnv->CallVoidMethod(
472
- jniCls,
490
+ jniObj,
473
491
  mid,
474
492
  jobId,
475
493
  jniEnv->NewStringUTF(fromUrl),
@@ -482,9 +500,9 @@ void RNFSTurboPlatformHelper::downloadFile(
482
500
  hasBeginCallback,
483
501
  hasProgressCallback
484
502
  );
503
+ jniEnv->DeleteLocalRef(jniCls);
485
504
  jniEnv->DeleteLocalRef(mapClass);
486
505
  jniEnv->DeleteLocalRef(headersMap);
487
- jniEnv->DeleteLocalRef(headersMap);
488
506
  }
489
507
 
490
508
  void RNFSTurboPlatformHelper::stopDownload(int jobId) {
@@ -496,7 +514,7 @@ void RNFSTurboPlatformHelper::stopDownload(int jobId) {
496
514
  );
497
515
 
498
516
  jniEnv->CallVoidMethod(
499
- jniCls,
517
+ jniObj,
500
518
  mid,
501
519
  jobId
502
520
  );
@@ -588,7 +606,7 @@ void RNFSTurboPlatformHelper::uploadFiles(
588
606
  }
589
607
 
590
608
  jniEnv->CallVoidMethod(
591
- jniCls,
609
+ jniObj,
592
610
  mid,
593
611
  jobId,
594
612
  jniEnv->NewStringUTF(toUrl),
@@ -618,7 +636,7 @@ void RNFSTurboPlatformHelper::stopUpload(int jobId) {
618
636
  );
619
637
 
620
638
  jniEnv->CallVoidMethod(
621
- jniCls,
639
+ jniObj,
622
640
  mid,
623
641
  jobId
624
642
  );
@@ -627,8 +645,8 @@ void RNFSTurboPlatformHelper::stopUpload(int jobId) {
627
645
 
628
646
  FSInfo RNFSTurboPlatformHelper::getFSInfo() {
629
647
  jclass jniCls = jniEnv->GetObjectClass(jniObj);
630
- jmethodID mid = jniEnv->GetStaticMethodID(jniCls, "getFSInfo", "()[J");
631
- jobject infoArr = jniEnv->CallObjectMethod(jniCls, mid);
648
+ jmethodID mid = jniEnv->GetMethodID(jniCls, "getFSInfo", "()[J");
649
+ jobject infoArr = jniEnv->CallObjectMethod(jniObj, mid);
632
650
  jlongArray *infoLongArr = reinterpret_cast<jlongArray*>(&infoArr);
633
651
  jlong* infoData = jniEnv->GetLongArrayElements(*infoLongArr, NULL);
634
652
 
@@ -640,8 +658,8 @@ FSInfo RNFSTurboPlatformHelper::getFSInfo() {
640
658
  };
641
659
 
642
660
  jniEnv->ReleaseLongArrayElements(*infoLongArr, infoData, 0);
643
- jniEnv->DeleteLocalRef(infoArr);
644
661
  jniEnv->DeleteLocalRef(jniCls);
662
+ jniEnv->DeleteLocalRef(infoArr);
645
663
 
646
664
  return fsInfo;
647
665
  }
@@ -661,6 +679,7 @@ void RNFSTurboPlatformHelper::scanFile(int jobId, const char *path, RNFSTurboSca
661
679
  jobId,
662
680
  jniEnv->NewStringUTF(path)
663
681
  );
682
+ jniEnv->DeleteLocalRef(jniCls);
664
683
  if (jniEnv->ExceptionCheck()) {
665
684
  jniEnv->ExceptionClear();
666
685
  std::map<int, RNFSTurboScanCallback>::iterator it = RNFSTurboPlatformHelper::scanCallbacks.find(jobId);
@@ -669,7 +688,6 @@ void RNFSTurboPlatformHelper::scanFile(int jobId, const char *path, RNFSTurboSca
669
688
  }
670
689
  throw "Scan error";
671
690
  }
672
- jniEnv->DeleteLocalRef(jniCls);
673
691
  }
674
692
 
675
693
  std::vector<std::string> RNFSTurboPlatformHelper::getAllExternalFilesDirs() {
@@ -223,12 +223,15 @@ public class RNFSTurboPlatformHelper {
223
223
 
224
224
  params.onTaskCompleted = new RNFSTurboDownloadParams.OnTaskCompleted() {
225
225
  public void onTaskCompleted(RNFSTurboDownloadResult res) {
226
- if (res.exception == null) {
227
- downloadCompleteCallback(jobId, res.statusCode, (double)res.bytesWritten);
228
- } else {
229
- downloadErrorCallback(jobId, res.exception.toString());
226
+ RNFSTurboDownloader downloader = downloaders.get(jobId);
227
+ if (downloader != null) {
228
+ if (res.exception == null) {
229
+ downloadCompleteCallback(jobId, res.statusCode, (double)res.bytesWritten);
230
+ } else {
231
+ downloadErrorCallback(jobId, res.exception.toString());
232
+ }
233
+ downloaders.remove(jobId);
230
234
  }
231
- downloaders.remove(jobId);
232
235
  }
233
236
  };
234
237
 
@@ -236,7 +239,10 @@ public class RNFSTurboPlatformHelper {
236
239
  params.onDownloadBegin = new RNFSTurboDownloadParams.OnDownloadBegin() {
237
240
  @Override
238
241
  public void onDownloadBegin(int statusCode, long contentLength, Map<String, String> headers) {
239
- downloadBeginCallback(jobId, statusCode, (double)contentLength, new HashMap<String, String>(headers));
242
+ RNFSTurboDownloader downloader = downloaders.get(jobId);
243
+ if (downloader != null) {
244
+ downloadBeginCallback(jobId, statusCode, (double)contentLength, new HashMap<String, String>(headers));
245
+ }
240
246
  }
241
247
  };
242
248
  }
@@ -244,7 +250,10 @@ public class RNFSTurboPlatformHelper {
244
250
  if (hasProgressCallback) {
245
251
  params.onDownloadProgress = new RNFSTurboDownloadParams.OnDownloadProgress() {
246
252
  public void onDownloadProgress(long contentLength, long bytesWritten) {
247
- downloadProgressCallback(jobId, (double)contentLength, (double)bytesWritten);
253
+ RNFSTurboDownloader downloader = downloaders.get(jobId);
254
+ if (downloader != null) {
255
+ downloadProgressCallback(jobId, (double)contentLength, (double)bytesWritten);
256
+ }
248
257
  }
249
258
  };
250
259
  }
@@ -11,12 +11,13 @@
11
11
  namespace facebook::react {
12
12
 
13
13
  NativeRNFSTurboModule::NativeRNFSTurboModule(std::shared_ptr<CallInvoker> jsInvoker)
14
- : NativeRNFSTurboModuleCxxSpec(jsInvoker) {}
14
+ : NativeRNFSTurboModuleCxxSpec(std::move(jsInvoker)) {}
15
15
 
16
16
  NativeRNFSTurboModule::~NativeRNFSTurboModule() {}
17
17
 
18
18
  jsi::Object NativeRNFSTurboModule::createRNFSTurbo(jsi::Runtime& runtime) {
19
19
  auto instance = std::make_shared<RNFSTurboHostObject>();
20
+ instance->jsInvoker = jsInvoker_;
20
21
  return jsi::Object::createFromHostObject(runtime, instance);
21
22
  }
22
23