Skip to content

Commit

Permalink
Merge branch 'dev-2.22'
Browse files Browse the repository at this point in the history
  • Loading branch information
birdofpreyru committed Jan 29, 2024
2 parents 4512e1e + 8db8b52 commit db61327
Show file tree
Hide file tree
Showing 10 changed files with 284 additions and 102 deletions.
22 changes: 19 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,17 @@ Background downloads in iOS require a bit of a setup.
First, in your `AppDelegate.m` file add the following:

```js
#import <RNFSManager.h>
#import <RNFSBackgroundDownloads.h>

...

- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler
- (void)application:(UIApplication *)application
handleEventsForBackgroundURLSession:(NSString *)identifier
completionHandler:(void (^)())completionHandler
{
[RNFSManager setCompletionHandlerForIdentifier:identifier completionHandler:completionHandler];
[RNFSBackgroundDownloads
setCompletionHandlerForIdentifier:identifier
completionHandler:completionHandler];
}

```
Expand Down Expand Up @@ -855,6 +859,18 @@ crash the app.
allowing a direct access to them with other methods in this library
(_e.g._ [readFile()]), even if the file is outside the app sandbox.

**NOTE:** On **iOS** & **macOS** it resolve to special values with the format
&laquo;`bookmark://<BASE64_ENCODED_STRING>`&raquo;, rather than normal URIs.
It is necessary for the support of security scopes
(see [Bookmarks and Security Scopes](https://developer.apple.com/documentation/foundation/nsurl#1663783)) in library methods. The &laquo;`<BASE64_ENCODED_STRING>`&raquo;
in this case is a Base64-encoded binary representation of the URL bookmark,
along with its security scope data. Other methods of the library are expected
to automatically handle such special URIs as needed.

**BEWARE:** It has not been thoroughly verified yet that all library methods
support these &laquo;Bookmark URLs&raquo; correctly. The expected error in
such case is a failure to access the URLs as non-existing.

### read()
[read()]: #read
```ts
Expand Down
6 changes: 3 additions & 3 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ PODS:
- boost (1.83.0)
- CocoaAsyncSocket (7.6.5)
- DoubleConversion (1.1.6)
- dr-pogodin-react-native-fs (2.22.1):
- dr-pogodin-react-native-fs (2.22.2):
- glog
- hermes-engine
- RCT-Folly (= 2022.05.16.00)
Expand Down Expand Up @@ -1402,7 +1402,7 @@ SPEC CHECKSUMS:
boost: d3f49c53809116a5d38da093a8aa78bf551aed09
CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99
DoubleConversion: fea03f2699887d960129cc54bba7e52542b6f953
dr-pogodin-react-native-fs: 60d98fc542ed310f57d9b497628f6e72fa2d5e2a
dr-pogodin-react-native-fs: 6aaacfa553d2a4be14cf32e4053725b7057155ee
dr-pogodin-react-native-static-server: a0ab88663817dfc8791b3e88295d0d9b6d212c5f
FBLazyVector: fbc4957d9aa695250b55d879c1d86f79d7e69ab4
Flipper: c7a0093234c4bdd456e363f2f19b2e4b27652d44
Expand Down Expand Up @@ -1468,4 +1468,4 @@ SPEC CHECKSUMS:

PODFILE CHECKSUM: 2673e1121fca9666d2df5c7ba3b5b287e79ba95f

COCOAPODS: 1.14.3
COCOAPODS: 1.15.0
9 changes: 9 additions & 0 deletions example/ios/ReactNativeFsExample/AppDelegate.mm
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#import "AppDelegate.h"

#import <React/RCTBundleURLProvider.h>
#import <RNFSBackgroundDownloads.h>

@implementation AppDelegate

Expand All @@ -14,6 +15,14 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

- (void)application:(UIApplication *)application
handleEventsForBackgroundURLSession:(NSString *)identifier
completionHandler:(void (^)())completionHandler
{
[RNFSBackgroundDownloads setCompletionHandlerForIdentifier:identifier
completionHandler:completionHandler];
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
return [self getBundleURL];
Expand Down
55 changes: 53 additions & 2 deletions example/src/TestBaseMethods.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { isEqual, isMatch } from 'lodash';
import React from 'react';
import { Platform, Text, View } from 'react-native';
import { AppState, Platform, Text, View } from 'react-native';

import {
appendFile,
completeHandlerIOS,
// copyAssetsFileIOS,
// copyAssetsVideoIOS,
// completeHandlerIOS,
Expand Down Expand Up @@ -326,6 +327,56 @@ const tests: { [name: string]: StatusOrEvaluator } = {
return 'fail';
}
},
// FOR THIS TEST TO RUN THE EXAMPLE APP SHOULD BE SENT TO THE BACKGROUND!
'[iOS] Background downloadFile()': async () => {
if (Platform.OS !== 'ios') return 'fail';

const url =
'https://raw.githubusercontent.com/birdofpreyru/react-native-fs/master/example/assets/test/good-utf8.txt';
const path = `${TemporaryDirectoryPath}/background-download-file-01`;
const good = 'GÖÖÐ\n';
try {
await unlink(path);
} catch {}
try {
console.info(
'Send the app to background to run the iOS background download test',
);
const promise = new Promise<'fail' | 'pass'>((resolve) => {
const sub = AppState.addEventListener('change', async (state) => {
if (state === 'background') {
const { jobId, promise: downloadPromise } = downloadFile({
fromUrl: url,
toFile: path,
});
sub.remove();
const res = await downloadPromise;
completeHandlerIOS(jobId);
if (
typeof jobId !== 'number' ||
res.bytesWritten !== 8 ||
res.statusCode !== 200
) {
console.info('Background download test failed');
resolve('fail');
return;
}
const file = await readFile(path);
if (file !== good) {
console.info('Background download test failed');
resolve('fail');
return;
}
console.info('Background download test passed');
resolve('pass');
}
});
});
return promise;
} catch {
return 'fail';
}
},
'exists()': async () => {
const path = `${TemporaryDirectoryPath}/test-exists-file`;
try {
Expand Down Expand Up @@ -919,7 +970,7 @@ const tests: { [name: string]: StatusOrEvaluator } = {
} else {
if (
!isMatch(e, {
code: 'ENSCOCOAERRORDOMAIN260',
code: 'NSCocoaErrorDomain:260',
message:
'The file “non-existing-file.txt” couldn’t be opened because there is no such file.',
})
Expand Down
21 changes: 21 additions & 0 deletions ios/RNFSBackgroundDownloads.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// RNFSBackgroundDownloads.h
// Pods
//
// Created by Sergey Pogodin on 29/1/24.
//

#ifndef RNFSBackgroundDownloads_h
#define RNFSBackgroundDownloads_h

typedef void (^CompletionHandler)(void);

@interface RNFSBackgroundDownloads: NSObject

+ (void) complete:(NSString*)uuid;

+ (void) setCompletionHandlerForIdentifier:(NSString*)identifier
completionHandler:(CompletionHandler)completionHandler;
@end

#endif /* RNFSBackgroundDownloads_h */
29 changes: 29 additions & 0 deletions ios/RNFSBackgroundDownloads.mm
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//
// RNFSBackgroundDownloads.m
// dr-pogodin-react-native-fs
//
// Created by Sergey Pogodin on 29/1/24.
//

#import "RNFSBackgroundDownloads.h"

@implementation RNFSBackgroundDownloads;

static NSMutableDictionary *completionHandlers;

+ (void)complete:(NSString *)uuid
{
CompletionHandler completionHandler = [completionHandlers objectForKey:uuid];
if (completionHandler) {
completionHandler();
[completionHandlers removeObjectForKey:uuid];
}
}

+ (void)setCompletionHandlerForIdentifier:(NSString *)identifier completionHandler:(__strong CompletionHandler)completionHandler
{
if (!completionHandlers) completionHandlers = [[NSMutableDictionary alloc] init];
[completionHandlers setValue:completionHandler forKey:identifier];
}

@end;
5 changes: 4 additions & 1 deletion ios/RNFSException.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
- (RNFSException*) log;
- (void) reject:(RCTPromiseRejectBlock)reject;
- (void) reject:(RCTPromiseRejectBlock)reject details:(NSString*)details;
+ (RNFSException*) from: (NSException*)exception;

+ (RNFSException*) fromError:(NSError*)error;
+ (RNFSException*) fromException:(NSException*)exception;

+ (RNFSException*) name: (NSString*)name;
+ (RNFSException*) name: (NSString*)name details: (NSString*)details;

Expand Down
15 changes: 12 additions & 3 deletions ios/RNFSException.mm
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,22 @@ - (void) reject: (RCTPromiseRejectBlock)reject details: (NSString*) details
reject(self.name, reason, [self error]);
}

+ (RNFSException*) from: (NSException*)exception
+ (RNFSException*) fromError:(NSError *)error
{
NSString *name = [NSString stringWithFormat:@"%@:%ld",
error.domain, error.code];
return [[RNFSException alloc]
initWithName:name
reason:error.localizedDescription
userInfo:error.userInfo];
}

+ (RNFSException*) fromException:(NSException *)exception
{
return [[RNFSException alloc]
initWithName: exception.name
reason: exception.reason
userInfo: exception.userInfo
];
userInfo: exception.userInfo];
}

+ (RNFSException*) name: (NSString*)name
Expand Down
Loading

0 comments on commit db61327

Please sign in to comment.