Merge branch 'feat/promisify' of https://github.com/grabbou/react-native-fs into grabbou-feat/promisify

This commit is contained in:
Chris Dell 2016-07-18 22:46:13 +01:00
commit bcecac71af
5 changed files with 174 additions and 188 deletions

View File

@ -7,49 +7,49 @@
// This file supports both iOS and Android // This file supports both iOS and Android
// Stop bluebird going nuts because it can't find "self"
if (typeof self === 'undefined') {
global.self = global;
}
var RNFSManager = require('react-native').NativeModules.RNFSManager; var RNFSManager = require('react-native').NativeModules.RNFSManager;
var NativeAppEventEmitter = require('react-native').NativeAppEventEmitter; // var NativeAppEventEmitter = require('react-native').NativeAppEventEmitter;
var Promise = require('bluebird'); // var Promise = require('bluebird');
// var base64 = require('base-64');
// var utf8 = require('utf8');
// var _readDir = Promise.promisify(RNFSManager.readDir);
// var _exists = Promise.promisify(RNFSManager.exists);
// var _stat = Promise.promisify(RNFSManager.stat);
// var _readFile = Promise.promisify(RNFSManager.readFile);
// var _writeFile = Promise.promisify(RNFSManager.writeFile);
// var _appendFile = Promise.promisify(RNFSManager.appendFile);
// var _moveFile = Promise.promisify(RNFSManager.moveFile);
// var _unlink = Promise.promisify(RNFSManager.unlink);
// var _mkdir = Promise.promisify(RNFSManager.mkdir);
// var _downloadFile = Promise.promisify(RNFSManager.downloadFile);
// var _uploadFiles = RNFSManager.uploadFiles ? Promise.promisify(RNFSManager.uploadFiles) : function () { return Promise.reject('Not implemented on Android'); };
// var _pathForBundle = Promise.promisify(RNFSManager.pathForBundle);
// var _getFSInfo = Promise.promisify(RNFSManager.getFSInfo);
// class RNFSError extends Error {
// code: number;
// constructor(message) {
// super(message);
// }
// }
// var convertError = (err) => {
// if (err.isOperational && err.cause) {
// err = err.cause;
// }
// var error = new RNFSError(err.description || err.message);
// error.code = err.code;
// throw error;
// };
var NativeAppEventEmitter = require('react-native').NativeAppEventEmitter; // iOS
var DeviceEventEmitter = require('react-native').DeviceEventEmitter; // Android
var base64 = require('base-64'); var base64 = require('base-64');
var utf8 = require('utf8'); var utf8 = require('utf8');
var _readDir = Promise.promisify(RNFSManager.readDir);
var _exists = Promise.promisify(RNFSManager.exists);
var _stat = Promise.promisify(RNFSManager.stat);
var _readFile = Promise.promisify(RNFSManager.readFile);
var _writeFile = Promise.promisify(RNFSManager.writeFile);
var _appendFile = Promise.promisify(RNFSManager.appendFile);
var _moveFile = Promise.promisify(RNFSManager.moveFile);
var _unlink = Promise.promisify(RNFSManager.unlink);
var _mkdir = Promise.promisify(RNFSManager.mkdir);
var _downloadFile = Promise.promisify(RNFSManager.downloadFile);
var _uploadFiles = RNFSManager.uploadFiles ? Promise.promisify(RNFSManager.uploadFiles) : function () { return Promise.reject('Not implemented on Android'); };
var _pathForBundle = Promise.promisify(RNFSManager.pathForBundle);
var _getFSInfo = Promise.promisify(RNFSManager.getFSInfo);
class RNFSError extends Error {
code: number;
constructor(message) {
super(message);
}
}
var convertError = (err) => {
if (err.isOperational && err.cause) {
err = err.cause;
}
var error = new RNFSError(err.description || err.message);
error.code = err.code;
throw error;
};
var NSFileTypeRegular = RNFSManager.NSFileTypeRegular; var NSFileTypeRegular = RNFSManager.NSFileTypeRegular;
var NSFileTypeDirectory = RNFSManager.NSFileTypeDirectory; var NSFileTypeDirectory = RNFSManager.NSFileTypeDirectory;
@ -155,7 +155,7 @@ type FSInfoResult = {
var RNFS = { var RNFS = {
readDir(dirpath: string): Promise<ReadDirItem[]> { readDir(dirpath: string): Promise<ReadDirItem[]> {
return _readDir(dirpath).then(files => { return RNFSManager.readDir(dirpath).then(files => {
return files.map(file => ({ return files.map(file => ({
name: file.name, name: file.name,
path: file.path, path: file.path,
@ -163,7 +163,7 @@ var RNFS = {
isFile: () => file.type === NSFileTypeRegular, isFile: () => file.type === NSFileTypeRegular,
isDirectory: () => file.type === NSFileTypeDirectory, isDirectory: () => file.type === NSFileTypeDirectory,
})); }));
}).catch(convertError); });
}, },
// Node style version (lowercase d). Returns just the names // Node style version (lowercase d). Returns just the names
@ -174,7 +174,7 @@ var RNFS = {
}, },
stat(filepath: string): Promise<StatResult> { stat(filepath: string): Promise<StatResult> {
return _stat(filepath).then((result) => { return RNFSManager.stat(filepath).then((result) => {
return { return {
'ctime': new Date(result.ctime * 1000), 'ctime': new Date(result.ctime * 1000),
'mtime': new Date(result.mtime * 1000), 'mtime': new Date(result.mtime * 1000),
@ -183,17 +183,13 @@ var RNFS = {
isFile: () => result.type === NSFileTypeRegular, isFile: () => result.type === NSFileTypeRegular,
isDirectory: () => result.type === NSFileTypeDirectory, isDirectory: () => result.type === NSFileTypeDirectory,
}; };
}).catch(convertError); });
},
exists(filepath: string): Promise<boolean> {
return _exists(filepath).catch(convertError);
}, },
readFile(filepath: string, encoding?: string): Promise<string> { readFile(filepath: string, encoding?: string): Promise<string> {
if (!encoding) encoding = 'utf8'; if (!encoding) encoding = 'utf8';
return _readFile(filepath).then((b64) => { return RNFSManager.readFile(filepath).then((b64) => {
var contents; var contents;
if (encoding === 'utf8') { if (encoding === 'utf8') {
@ -207,7 +203,7 @@ var RNFS = {
} }
return contents; return contents;
}).catch(convertError); });
}, },
writeFile(filepath: string, contents: string, encoding?: string, options?: WriteFileOptions): Promise<void> { writeFile(filepath: string, contents: string, encoding?: string, options?: WriteFileOptions): Promise<void> {
@ -225,7 +221,7 @@ var RNFS = {
throw new Error('Invalid encoding type "' + encoding + '"'); throw new Error('Invalid encoding type "' + encoding + '"');
} }
return _writeFile(filepath, b64, options).catch(convertError); return RNFSManager.writeFile(filepath, b64, options);
}, },
appendFile(filepath: string, contents: string, encoding?: string, options?: WriteFileOptions): Promise<void> { appendFile(filepath: string, contents: string, encoding?: string, options?: WriteFileOptions): Promise<void> {
@ -243,29 +239,13 @@ var RNFS = {
throw new Error('Invalid encoding type "' + encoding + '"'); throw new Error('Invalid encoding type "' + encoding + '"');
} }
return _appendFile(filepath, b64, options).catch(convertError); return RNFSManager.appendFile(filepath, b64, options);
},
moveFile(filepath: string, destPath: string): Promise<void> {
return _moveFile(filepath, destPath).catch(convertError);
},
pathForBundle(bundleName: string): Promise<string> {
return _pathForBundle(bundleName);
},
getFSInfo(): Promise<FSInfoResult> {
return _getFSInfo().catch(convertError);
},
unlink(filepath: string): Promise<void> {
return _unlink(filepath).catch(convertError);
}, },
mkdir(filepath: string, excludeFromBackup?: boolean): Promise<void> { mkdir(filepath: string, excludeFromBackup?: boolean): Promise<void> {
excludeFromBackup = !!excludeFromBackup; excludeFromBackup = !!excludeFromBackup;
return _mkdir(filepath, excludeFromBackup).catch(convertError); return RNFSManager.mkdir(filepath, excludeFromBackup);
}, },
downloadFile(options: DownloadFileOptions): Promise<DownloadResult> { downloadFile(options: DownloadFileOptions): Promise<DownloadResult> {
@ -308,14 +288,10 @@ var RNFS = {
progressDivider: options.progressDivider || 0 progressDivider: options.progressDivider || 0
}; };
return _downloadFile(bridgeOptions).then(res => { return RNFSManager.downloadFile(bridgeOptions).then(res => {
subscriptions.forEach(sub => sub.remove()); subscriptions.forEach(sub => sub.remove());
return res; return res;
}).catch(convertError); });
},
stopDownload(jobId: number): Promise<void> {
RNFSManager.stopDownload(jobId);
}, },
uploadFiles(options: UploadFileOptions): Promise<UploadResult> { uploadFiles(options: UploadFileOptions): Promise<UploadResult> {
@ -354,15 +330,19 @@ var RNFS = {
method: options.method || 'POST' method: options.method || 'POST'
}; };
return _uploadFiles(bridgeOptions).then(res => { return RNFSManager.uploadFiles(bridgeOptions).then(res => {
subscriptions.forEach(sub => sub.remove()); subscriptions.forEach(sub => sub.remove());
return res; return res;
}); });
}, },
stopUpload(jobId: number): Promise<void> { moveFile: (RNFSManager.moveFile:(filepath: string, destPath: string) => Promise<void>),
RNFSManager.stopUpload(jobId); pathForBundle: (RNFSManager.pathForBundle:(bundleNamed: string) => Promise<string>),
}, getFSInfo: (RNFSManager.getFSInfo:() => Promise<FSInfoResult>),
unlink: (RNFSManager.unlink:(filepath: string) => Promise<void>),
exists: (RNFSManager.exists:(filepath: string) => Promise<boolean>),
stopDownload: (RNFSManager.stopDownload:(jobId: number) => void),
stopUpload: (RNFSManager.stopUpload:(jobId: number) => void),
MainBundlePath: RNFSManager.MainBundlePath, MainBundlePath: RNFSManager.MainBundlePath,
CachesDirectoryPath: RNFSManager.NSCachesDirectoryPath, CachesDirectoryPath: RNFSManager.NSCachesDirectoryPath,
@ -371,6 +351,7 @@ var RNFS = {
TemporaryDirectoryPath: RNFSManager.NSTemporaryDirectoryPath, TemporaryDirectoryPath: RNFSManager.NSTemporaryDirectoryPath,
LibraryDirectoryPath: RNFSManager.NSLibraryDirectoryPath, LibraryDirectoryPath: RNFSManager.NSLibraryDirectoryPath,
PicturesDirectoryPath: RNFSManager.NSPicturesDirectoryPath PicturesDirectoryPath: RNFSManager.NSPicturesDirectoryPath
}; };
module.exports = RNFS; module.exports = RNFS;

View File

@ -32,7 +32,8 @@ RCT_EXPORT_MODULE();
} }
RCT_EXPORT_METHOD(readDir:(NSString *)dirPath RCT_EXPORT_METHOD(readDir:(NSString *)dirPath
callback:(RCTResponseSenderBlock)callback) resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{ {
NSFileManager *fileManager = [NSFileManager defaultManager]; NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error = nil; NSError *error = nil;
@ -52,28 +53,30 @@ RCT_EXPORT_METHOD(readDir:(NSString *)dirPath
}]; }];
if (error) { if (error) {
return callback([self makeErrorPayload:error]); return [self reject:reject withError:error];
} }
callback(@[[NSNull null], contents]); resolve(contents);
} }
RCT_EXPORT_METHOD(exists:(NSString *)filepath RCT_EXPORT_METHOD(exists:(NSString *)filepath
callback:(RCTResponseSenderBlock)callback) resolver:(RCTPromiseResolveBlock)resolve
rejecter:(__unused RCTPromiseRejectBlock)reject)
{ {
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:filepath]; BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:filepath];
callback(@[[NSNull null], [NSNumber numberWithBool:fileExists]]); resolve([NSNumber numberWithBool:fileExists]);
} }
RCT_EXPORT_METHOD(stat:(NSString *)filepath RCT_EXPORT_METHOD(stat:(NSString *)filepath
callback:(RCTResponseSenderBlock)callback) resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{ {
NSError *error = nil; NSError *error = nil;
NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:filepath error:&error]; NSDictionary *attributes = [[NSFileManager defaultManager] attributesOfItemAtPath:filepath error:&error];
if (error) { if (error) {
return callback([self makeErrorPayload:error]); return [self reject:reject withError:error];
} }
attributes = @{ attributes = @{
@ -84,29 +87,31 @@ RCT_EXPORT_METHOD(stat:(NSString *)filepath
@"mode": @([[NSString stringWithFormat:@"%ld", (long)[(NSNumber *)[attributes objectForKey:NSFilePosixPermissions] integerValue]] integerValue]) @"mode": @([[NSString stringWithFormat:@"%ld", (long)[(NSNumber *)[attributes objectForKey:NSFilePosixPermissions] integerValue]] integerValue])
}; };
callback(@[[NSNull null], attributes]); resolve(attributes);
} }
RCT_EXPORT_METHOD(writeFile:(NSString *)filepath RCT_EXPORT_METHOD(writeFile:(NSString *)filepath
contents:(NSString *)base64Content contents:(NSString *)base64Content
attributes:(NSDictionary *)attributes attributes:(NSDictionary *)attributes
callback:(RCTResponseSenderBlock)callback) resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{ {
NSData *data = [[NSData alloc] initWithBase64EncodedString:base64Content options:NSDataBase64DecodingIgnoreUnknownCharacters]; NSData *data = [[NSData alloc] initWithBase64EncodedString:base64Content options:NSDataBase64DecodingIgnoreUnknownCharacters];
BOOL success = [[NSFileManager defaultManager] createFileAtPath:filepath contents:data attributes:attributes]; BOOL success = [[NSFileManager defaultManager] createFileAtPath:filepath contents:data attributes:attributes];
if (!success) { if (!success) {
return callback(@[[NSString stringWithFormat:@"Could not write file at path %@", filepath]]); return reject(@"ENOENT", [NSString stringWithFormat:@"ENOENT: no such file or directory, open '%@'", filepath], nil);
} }
return callback(@[[NSNull null], [NSNumber numberWithBool:success], filepath]); return resolve(nil);
} }
RCT_EXPORT_METHOD(appendFile:(NSString *)filepath RCT_EXPORT_METHOD(appendFile:(NSString *)filepath
contents:(NSString *)base64Content contents:(NSString *)base64Content
attributes:(NSDictionary *)attributes attributes:(NSDictionary *)attributes
callback:(RCTResponseSenderBlock)callback) resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{ {
NSData *data = [[NSData alloc] initWithBase64EncodedString:base64Content options:NSDataBase64DecodingIgnoreUnknownCharacters]; NSData *data = [[NSData alloc] initWithBase64EncodedString:base64Content options:NSDataBase64DecodingIgnoreUnknownCharacters];
@ -117,9 +122,9 @@ RCT_EXPORT_METHOD(appendFile:(NSString *)filepath
BOOL success = [[NSFileManager defaultManager] createFileAtPath:filepath contents:data attributes:attributes]; BOOL success = [[NSFileManager defaultManager] createFileAtPath:filepath contents:data attributes:attributes];
if (!success) { if (!success) {
return callback(@[[NSString stringWithFormat:@"Could not write file at path %@", filepath]]); return reject(@"ENOENT", [NSString stringWithFormat:@"ENOENT: no such file or directory, open '%@'", filepath], nil);
} else { } else {
return callback(@[[NSNull null], [NSNumber numberWithBool:success], filepath]); return resolve(nil);
} }
} }
@ -129,34 +134,37 @@ RCT_EXPORT_METHOD(appendFile:(NSString *)filepath
[fH seekToEndOfFile]; [fH seekToEndOfFile];
[fH writeData:data]; [fH writeData:data];
return callback(@[[NSNull null], [NSNumber numberWithBool:true], filepath]); return resolve(nil);
} @catch (NSException *e) { } @catch (NSException *e) {
return callback([self makeErrorPayload:e]); return [self reject:reject withError:e];
} }
} }
RCT_EXPORT_METHOD(unlink:(NSString*)filepath RCT_EXPORT_METHOD(unlink:(NSString*)filepath
callback:(RCTResponseSenderBlock)callback) resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{ {
NSFileManager *manager = [NSFileManager defaultManager]; NSFileManager *manager = [NSFileManager defaultManager];
BOOL exists = [manager fileExistsAtPath:filepath isDirectory:false]; BOOL exists = [manager fileExistsAtPath:filepath isDirectory:false];
if (!exists) { if (!exists) {
return callback(@[[NSString stringWithFormat:@"File at path %@ does not exist", filepath]]); return reject(@"ENOENT", [NSString stringWithFormat:@"ENOENT: no such file or directory, open '%@'", filepath], nil);
} }
NSError *error = nil; NSError *error = nil;
BOOL success = [manager removeItemAtPath:filepath error:&error]; BOOL success = [manager removeItemAtPath:filepath error:&error];
if (!success) { if (!success) {
return callback([self makeErrorPayload:error]); return [self reject:reject withError:error];
} }
callback(@[[NSNull null], [NSNumber numberWithBool:success], filepath]); resolve(nil);
} }
RCT_EXPORT_METHOD(mkdir:(NSString*)filepath RCT_EXPORT_METHOD(mkdir:(NSString*)filepath
excludeFromBackup:(BOOL)excludeFromBackup excludeFromBackup:(BOOL)excludeFromBackup
callback:(RCTResponseSenderBlock)callback) resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{ {
NSFileManager *manager = [NSFileManager defaultManager]; NSFileManager *manager = [NSFileManager defaultManager];
@ -164,7 +172,7 @@ RCT_EXPORT_METHOD(mkdir:(NSString*)filepath
BOOL success = [manager createDirectoryAtPath:filepath withIntermediateDirectories:YES attributes:nil error:&error]; BOOL success = [manager createDirectoryAtPath:filepath withIntermediateDirectories:YES attributes:nil error:&error];
if (!success) { if (!success) {
return callback([self makeErrorPayload:error]); return [self reject:reject withError:error];
} }
NSURL *url = [NSURL fileURLWithPath:filepath]; NSURL *url = [NSURL fileURLWithPath:filepath];
@ -172,28 +180,30 @@ RCT_EXPORT_METHOD(mkdir:(NSString*)filepath
success = [url setResourceValue: [NSNumber numberWithBool: excludeFromBackup] forKey: NSURLIsExcludedFromBackupKey error: &error]; success = [url setResourceValue: [NSNumber numberWithBool: excludeFromBackup] forKey: NSURLIsExcludedFromBackupKey error: &error];
if (!success) { if (!success) {
return callback([self makeErrorPayload:error]); return [self reject:reject withError:error];
} }
callback(@[[NSNull null], [NSNumber numberWithBool:success], filepath]); resolve(nil);
} }
RCT_EXPORT_METHOD(readFile:(NSString *)filepath RCT_EXPORT_METHOD(readFile:(NSString *)filepath
callback:(RCTResponseSenderBlock)callback) resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{ {
NSData *content = [[NSFileManager defaultManager] contentsAtPath:filepath]; NSData *content = [[NSFileManager defaultManager] contentsAtPath:filepath];
NSString *base64Content = [content base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed]; NSString *base64Content = [content base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
if (!base64Content) { if (!base64Content) {
return callback(@[[NSString stringWithFormat:@"Could not read file at path %@", filepath]]); return reject(@"ENOENT", [NSString stringWithFormat:@"ENOENT: no such file or directory, open '%@'", filepath], nil);
} }
callback(@[[NSNull null], base64Content]); resolve(base64Content);
} }
RCT_EXPORT_METHOD(moveFile:(NSString *)filepath RCT_EXPORT_METHOD(moveFile:(NSString *)filepath
destPath:(NSString *)destPath destPath:(NSString *)destPath
callback:(RCTResponseSenderBlock)callback) resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{ {
NSFileManager *manager = [NSFileManager defaultManager]; NSFileManager *manager = [NSFileManager defaultManager];
@ -201,14 +211,15 @@ RCT_EXPORT_METHOD(moveFile:(NSString *)filepath
BOOL success = [manager moveItemAtPath:filepath toPath:destPath error:&error]; BOOL success = [manager moveItemAtPath:filepath toPath:destPath error:&error];
if (!success) { if (!success) {
return callback([self makeErrorPayload:error]); return [self reject:reject withError:error];
} }
callback(@[[NSNull null], [NSNumber numberWithBool:success], destPath]); resolve(nil);
} }
RCT_EXPORT_METHOD(downloadFile:(NSDictionary *)options RCT_EXPORT_METHOD(downloadFile:(NSDictionary *)options
callback:(RCTResponseSenderBlock)callback) resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{ {
DownloadParams* params = [DownloadParams alloc]; DownloadParams* params = [DownloadParams alloc];
@ -228,11 +239,11 @@ RCT_EXPORT_METHOD(downloadFile:(NSDictionary *)options
if (bytesWritten) { if (bytesWritten) {
[result setObject:bytesWritten forKey: @"bytesWritten"]; [result setObject:bytesWritten forKey: @"bytesWritten"];
} }
return callback(@[[NSNull null], result]); return resolve(result);
}; };
params.errorCallback = ^(NSError* error) { params.errorCallback = ^(NSError* error) {
return callback([self makeErrorPayload:error]); return [self reject:reject withError:error];
}; };
params.beginCallback = ^(NSNumber* statusCode, NSNumber* contentLength, NSDictionary* headers) { params.beginCallback = ^(NSNumber* statusCode, NSNumber* contentLength, NSDictionary* headers) {
@ -269,7 +280,8 @@ RCT_EXPORT_METHOD(stopDownload:(nonnull NSNumber *)jobId)
} }
RCT_EXPORT_METHOD(uploadFiles:(NSDictionary *)options RCT_EXPORT_METHOD(uploadFiles:(NSDictionary *)options
callback:(RCTResponseSenderBlock)callback) resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{ {
UploadParams* params = [UploadParams alloc]; UploadParams* params = [UploadParams alloc];
@ -292,11 +304,11 @@ RCT_EXPORT_METHOD(uploadFiles:(NSDictionary *)options
[result setValue:((NSHTTPURLResponse *)resp).allHeaderFields forKey:@"headers"]; [result setValue:((NSHTTPURLResponse *)resp).allHeaderFields forKey:@"headers"];
[result setValue:[NSNumber numberWithUnsignedInteger:((NSHTTPURLResponse *)resp).statusCode] forKey:@"statusCode"]; [result setValue:[NSNumber numberWithUnsignedInteger:((NSHTTPURLResponse *)resp).statusCode] forKey:@"statusCode"];
} }
return callback(@[[NSNull null], result]); return resolve(result);
}; };
params.errorCallback = ^(NSError* error) { params.errorCallback = ^(NSError* error) {
return callback([self makeErrorPayload:error]); return [self reject:reject withError:error];
}; };
params.beginCallback = ^() { params.beginCallback = ^() {
@ -330,7 +342,8 @@ RCT_EXPORT_METHOD(stopUpload:(nonnull NSNumber *)jobId)
} }
RCT_EXPORT_METHOD(pathForBundle:(NSString *)bundleNamed RCT_EXPORT_METHOD(pathForBundle:(NSString *)bundleNamed
callback:(RCTResponseSenderBlock)callback) resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
{ {
NSString *path = [[NSBundle mainBundle].bundlePath stringByAppendingFormat:@"/%@.bundle", bundleNamed]; NSString *path = [[NSBundle mainBundle].bundlePath stringByAppendingFormat:@"/%@.bundle", bundleNamed];
NSBundle *bundle = [NSBundle bundleWithPath:path]; NSBundle *bundle = [NSBundle bundleWithPath:path];
@ -345,16 +358,17 @@ RCT_EXPORT_METHOD(pathForBundle:(NSString *)bundleNamed
} }
if (path) { if (path) {
callback(@[[NSNull null], path]); resolve(path);
} else { } else {
callback(@[[NSError errorWithDomain:NSPOSIXErrorDomain NSError *error = [NSError errorWithDomain:NSPOSIXErrorDomain
code:NSFileNoSuchFileError code:NSFileNoSuchFileError
userInfo:nil].localizedDescription, userInfo:nil];
[NSNull null]]);
[self reject:reject withError:error];
} }
} }
RCT_EXPORT_METHOD(getFSInfo:(RCTResponseSenderBlock)callback) RCT_EXPORT_METHOD(getFSInfo:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
{ {
unsigned long long totalSpace = 0; unsigned long long totalSpace = 0;
unsigned long long totalFreeSpace = 0; unsigned long long totalFreeSpace = 0;
@ -369,14 +383,12 @@ RCT_EXPORT_METHOD(getFSInfo:(RCTResponseSenderBlock)callback)
totalSpace = [fileSystemSizeInBytes unsignedLongLongValue]; totalSpace = [fileSystemSizeInBytes unsignedLongLongValue];
totalFreeSpace = [freeFileSystemSizeInBytes unsignedLongLongValue]; totalFreeSpace = [freeFileSystemSizeInBytes unsignedLongLongValue];
callback(@[[NSNull null], resolve(@{
@{
@"totalSpace": [NSNumber numberWithUnsignedLongLong:totalSpace], @"totalSpace": [NSNumber numberWithUnsignedLongLong:totalSpace],
@"freeSpace": [NSNumber numberWithUnsignedLongLong:totalFreeSpace] @"freeSpace": [NSNumber numberWithUnsignedLongLong:totalFreeSpace]
} });
]);
} else { } else {
callback(@[error, [NSNull null]]); [self reject:reject withError:error];
} }
} }
@ -385,12 +397,10 @@ RCT_EXPORT_METHOD(getFSInfo:(RCTResponseSenderBlock)callback)
return @([date timeIntervalSince1970]); return @([date timeIntervalSince1970]);
} }
- (NSArray *)makeErrorPayload:(NSError *)error - (void)reject:(RCTPromiseRejectBlock)reject withError:(NSError *)error
{ {
return @[@{ NSString *codeWithDomain = [NSString stringWithFormat:@"E%@%zd", error.domain.uppercaseString, error.code];
@"description": error.localizedDescription, reject(codeWithDomain, error.localizedDescription, error);
@"code": @(error.code)
}];
} }
- (NSString *)getPathForDirectory:(int)directory - (NSString *)getPathForDirectory:(int)directory

View File

@ -4,7 +4,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:1.1.3' classpath 'com.android.tools.build:gradle:1.5.0'
} }
} }

View File

@ -1,35 +1,25 @@
package com.rnfs; package com.rnfs;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.HashMap; import java.util.HashMap;
import java.util.ArrayList;
import android.os.Environment; import android.os.Environment;
import android.os.AsyncTask;
import android.os.StatFs; import android.os.StatFs;
import android.util.Base64; import android.util.Base64;
import android.content.Context;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.util.SparseArray; import android.util.SparseArray;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.BufferedInputStream; import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.net.URLConnection;
import java.net.HttpURLConnection;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext; import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule; import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap; import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.Arguments;
@ -60,7 +50,7 @@ public class RNFSManager extends ReactContextBaseJavaModule {
} }
@ReactMethod @ReactMethod
public void writeFile(String filepath, String base64Content, ReadableMap options, Callback callback) { public void writeFile(String filepath, String base64Content, ReadableMap options, Promise promise) {
try { try {
byte[] bytes = Base64.decode(base64Content, Base64.DEFAULT); byte[] bytes = Base64.decode(base64Content, Base64.DEFAULT);
@ -68,10 +58,10 @@ public class RNFSManager extends ReactContextBaseJavaModule {
outputStream.write(bytes); outputStream.write(bytes);
outputStream.close(); outputStream.close();
callback.invoke(null, true, filepath); promise.resolve(null);
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();
callback.invoke(makeErrorPayload(ex)); reject(promise, ex);
} }
} }
@ -84,26 +74,26 @@ public class RNFSManager extends ReactContextBaseJavaModule {
outputStream.write(bytes); outputStream.write(bytes);
outputStream.close(); outputStream.close();
callback.invoke(null, true, filepath); promise.resolve(true);
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();
callback.invoke(makeErrorPayload(ex)); reject(promise, ex);
} }
} }
@ReactMethod @ReactMethod
public void exists(String filepath, Callback callback) { public void exists(String filepath, Promise promise) {
try { try {
File file = new File(filepath); File file = new File(filepath);
callback.invoke(null, file.exists()); promise.resolve(file.exists());
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();
callback.invoke(makeErrorPayload(ex)); reject(promise, ex);
} }
} }
@ReactMethod @ReactMethod
public void readFile(String filepath, Callback callback) { public void readFile(String filepath, Promise promise) {
try { try {
File file = new File(filepath); File file = new File(filepath);
@ -115,29 +105,29 @@ public class RNFSManager extends ReactContextBaseJavaModule {
String base64Content = Base64.encodeToString(buffer, Base64.NO_WRAP); String base64Content = Base64.encodeToString(buffer, Base64.NO_WRAP);
callback.invoke(null, base64Content); promise.resolve(base64Content);
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();
callback.invoke(makeErrorPayload(ex)); reject(promise, ex);
} }
} }
@ReactMethod @ReactMethod
public void moveFile(String filepath, String destPath, Callback callback) { public void moveFile(String filepath, String destPath, Promise promise) {
try { try {
File from = new File(filepath); File from = new File(filepath);
File to = new File(destPath); File to = new File(destPath);
from.renameTo(to); from.renameTo(to);
callback.invoke(null, true, destPath); promise.resolve(true);
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();
callback.invoke(makeErrorPayload(ex)); reject(promise, ex);
} }
} }
@ReactMethod @ReactMethod
public void readDir(String directory, Callback callback) { public void readDir(String directory, Promise promise) {
try { try {
File file = new File(directory); File file = new File(directory);
@ -158,16 +148,15 @@ public class RNFSManager extends ReactContextBaseJavaModule {
fileMaps.pushMap(fileMap); fileMaps.pushMap(fileMap);
} }
callback.invoke(null, fileMaps); promise.resolve(fileMaps);
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();
callback.invoke(makeErrorPayload(ex)); reject(promise, ex);
} }
} }
@ReactMethod @ReactMethod
public void stat(String filepath, Callback callback) { public void stat(String filepath, Promise promise) {
try { try {
File file = new File(filepath); File file = new File(filepath);
@ -180,15 +169,15 @@ public class RNFSManager extends ReactContextBaseJavaModule {
statMap.putInt("size", (int)file.length()); statMap.putInt("size", (int)file.length());
statMap.putInt("type", file.isDirectory() ? 1 : 0); statMap.putInt("type", file.isDirectory() ? 1 : 0);
callback.invoke(null, statMap); promise.resolve(statMap);
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();
callback.invoke(makeErrorPayload(ex)); reject(promise, ex);
} }
} }
@ReactMethod @ReactMethod
public void unlink(String filepath, Callback callback) { public void unlink(String filepath, Promise promise) {
try { try {
File file = new File(filepath); File file = new File(filepath);
@ -196,10 +185,10 @@ public class RNFSManager extends ReactContextBaseJavaModule {
boolean success = DeleteRecursive(file); boolean success = DeleteRecursive(file);
callback.invoke(null, success, filepath); promise.resolve(success);
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();
callback.invoke(makeErrorPayload(ex)); reject(promise, ex);
} }
} }
@ -214,7 +203,7 @@ public class RNFSManager extends ReactContextBaseJavaModule {
} }
@ReactMethod @ReactMethod
public void mkdir(String filepath, Boolean excludeFromBackup, Callback callback) { public void mkdir(String filepath, Boolean excludeFromBackup, Promise promise) {
try { try {
File file = new File(filepath); File file = new File(filepath);
@ -222,10 +211,10 @@ public class RNFSManager extends ReactContextBaseJavaModule {
boolean success = file.exists(); boolean success = file.exists();
callback.invoke(null, success, filepath); promise.resolve(success);
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();
callback.invoke(makeErrorPayload(ex)); reject(promise, ex);
} }
} }
@ -236,7 +225,7 @@ public class RNFSManager extends ReactContextBaseJavaModule {
} }
@ReactMethod @ReactMethod
public void downloadFile(ReadableMap options, final Callback callback) { public void downloadFile(ReadableMap options, final Promise promise) {
try { try {
File file = new File(options.getString("toFile")); File file = new File(options.getString("toFile"));
URL url = new URL(options.getString("fromUrl")); URL url = new URL(options.getString("fromUrl"));
@ -260,9 +249,9 @@ public class RNFSManager extends ReactContextBaseJavaModule {
infoMap.putInt("statusCode", res.statusCode); infoMap.putInt("statusCode", res.statusCode);
infoMap.putInt("bytesWritten", res.bytesWritten); infoMap.putInt("bytesWritten", res.bytesWritten);
callback.invoke(null, infoMap); promise.resolve(infoMap);
} else { } else {
callback.invoke(makeErrorPayload(res.exception)); reject(promise, res.exception);
} }
} }
}; };
@ -305,7 +294,7 @@ public class RNFSManager extends ReactContextBaseJavaModule {
this.downloaders.put(jobId, downloader); this.downloaders.put(jobId, downloader);
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); ex.printStackTrace();
callback.invoke(makeErrorPayload(ex)); reject(promise, ex);
} }
} }
@ -319,12 +308,12 @@ public class RNFSManager extends ReactContextBaseJavaModule {
} }
@ReactMethod @ReactMethod
public void pathForBundle(String bundleNamed, Callback callback) { public void pathForBundle(String bundleNamed, Promise promise) {
// TODO: Not sure what equilivent would be? // TODO: Not sure what equilivent would be?
} }
@ReactMethod @ReactMethod
public void getFSInfo(Callback callback) { public void getFSInfo(Promise promise) {
File path = Environment.getDataDirectory(); File path = Environment.getDataDirectory();
StatFs stat = new StatFs(path.getPath()); StatFs stat = new StatFs(path.getPath());
long totalSpace; long totalSpace;
@ -340,13 +329,20 @@ public class RNFSManager extends ReactContextBaseJavaModule {
WritableMap info = Arguments.createMap(); WritableMap info = Arguments.createMap();
info.putDouble("totalSpace", (double)totalSpace); // Int32 too small, must use Double info.putDouble("totalSpace", (double)totalSpace); // Int32 too small, must use Double
info.putDouble("freeSpace", (double)freeSpace); info.putDouble("freeSpace", (double)freeSpace);
callback.invoke(null, info); promise.resolve(info);
} }
private WritableMap makeErrorPayload(Exception ex) { private void reject(Promise promise, String filepath, Exception ex) {
WritableMap error = Arguments.createMap(); if (ex instanceof FileNotFoundException) {
error.putString("message", ex.getMessage()); rejectFileNotFound(promise, filepath);
return error; return;
}
promise.reject(null, ex.getMessage());
}
private void rejectFileNotFound(Promise promise, String filepath) {
promise.reject("ENOENT", "ENOENT: no such file or directory, open '" + filepath + "'");
} }
@Override @Override

View File

@ -22,7 +22,6 @@
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"base-64": "^0.1.0", "base-64": "^0.1.0",
"bluebird": "^2.9.25",
"utf8": "^2.1.1" "utf8": "^2.1.1"
}, },
"devDependencies": { "devDependencies": {