From 8121dbf66db16999653a590b1ee41c48add6dba9 Mon Sep 17 00:00:00 2001 From: Ben Hsieh Date: Mon, 27 Mar 2017 22:28:13 +0800 Subject: [PATCH 01/20] Apply possible fix to fs.readFile and fs.readStream for #287 --- .../java/com/RNFetchBlob/RNFetchBlobFS.java | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/android/src/main/java/com/RNFetchBlob/RNFetchBlobFS.java b/android/src/main/java/com/RNFetchBlob/RNFetchBlobFS.java index b7237a461..7457dba19 100644 --- a/android/src/main/java/com/RNFetchBlob/RNFetchBlobFS.java +++ b/android/src/main/java/com/RNFetchBlob/RNFetchBlobFS.java @@ -138,11 +138,13 @@ static public void writeFile(String path, ReadableArray data, final boolean appe * @param promise */ static public void readFile(String path, String encoding, final Promise promise ) { - path = normalizePath(path); + String resolved = normalizePath(path); + if(resolved != null) + path = resolved; try { byte[] bytes; - if(path.startsWith(RNFetchBlobConst.FILE_PREFIX_BUNDLE_ASSET)) { + if(resolved != null && resolved.startsWith(RNFetchBlobConst.FILE_PREFIX_BUNDLE_ASSET)) { String assetName = path.replace(RNFetchBlobConst.FILE_PREFIX_BUNDLE_ASSET, ""); long length = RNFetchBlob.RCTContext.getAssets().openFd(assetName).getLength(); bytes = new byte[(int) length]; @@ -150,6 +152,14 @@ static public void readFile(String path, String encoding, final Promise promise in.read(bytes, 0, (int) length); in.close(); } + // issue 287 + else if(resolved == null) { + InputStream in = RNFetchBlob.RCTContext.getContentResolver().openInputStream(Uri.parse(path)); + int length = (int) in.available(); + bytes = new byte[length]; + in.read(bytes); + in.close(); + } else { File f = new File(path); int length = (int) f.length(); @@ -225,7 +235,9 @@ static public String getTmpPath(ReactApplicationContext ctx, String taskId) { * @param bufferSize Buffer size of read stream, default to 4096 (4095 when encode is `base64`) */ public void readStream(String path, String encoding, int bufferSize, int tick, final String streamId) { - path = normalizePath(path); + String resolved = normalizePath(path); + if(resolved != null) + path = resolved; try { int chunkSize = encoding.equalsIgnoreCase("base64") ? 4095 : 4096; @@ -233,9 +245,13 @@ public void readStream(String path, String encoding, int bufferSize, int tick, f chunkSize = bufferSize; InputStream fs; - if(path.startsWith(RNFetchBlobConst.FILE_PREFIX_BUNDLE_ASSET)) { + if(resolved != null && path.startsWith(RNFetchBlobConst.FILE_PREFIX_BUNDLE_ASSET)) { fs = RNFetchBlob.RCTContext.getAssets().open(path.replace(RNFetchBlobConst.FILE_PREFIX_BUNDLE_ASSET, "")); } + // fix issue 287 + else if(resolved == null) { + fs = RNFetchBlob.RCTContext.getContentResolver().openInputStream(Uri.parse(path)); + } else { fs = new FileInputStream(new File(path)); } From 40fefd4b2e29bdb13c3cbf1e64e0ced2dac33da7 Mon Sep 17 00:00:00 2001 From: Ben Hsieh Date: Sun, 16 Apr 2017 16:34:11 +0800 Subject: [PATCH 02/20] Add Android fs.readFile app provider URI support #287 --- .../java/com/RNFetchBlob/Utils/PathResolver.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/android/src/main/java/com/RNFetchBlob/Utils/PathResolver.java b/android/src/main/java/com/RNFetchBlob/Utils/PathResolver.java index e5742b81e..0327c8e26 100644 --- a/android/src/main/java/com/RNFetchBlob/Utils/PathResolver.java +++ b/android/src/main/java/com/RNFetchBlob/Utils/PathResolver.java @@ -59,6 +59,14 @@ else if (isMediaDocument(uri)) { return getDataColumn(context, contentUri, selection, selectionArgs); } + else if ("content".equalsIgnoreCase(uri.getScheme())) { + + // Return the remote address + if (isGooglePhotosUri(uri)) + return uri.getLastPathSegment(); + + return getDataColumn(context, uri, null, null); + } } // MediaStore (and general) else if ("content".equalsIgnoreCase(uri.getScheme())) { @@ -103,7 +111,12 @@ public static String getDataColumn(Context context, Uri uri, String selection, final int index = cursor.getColumnIndexOrThrow(column); return cursor.getString(index); } - } finally { + } + catch (Exception ex) { + ex.printStackTrace(); + return null; + } + finally { if (cursor != null) cursor.close(); } From 08f8403dc43ad34320ee3038fa877a92b2b735c3 Mon Sep 17 00:00:00 2001 From: Ben Hsieh Date: Mon, 3 Jul 2017 08:48:44 +0800 Subject: [PATCH 03/20] Fixed a bug which causes XMLHttpRequest getting incorrect header when sending multiple requests in the same time --- polyfill/XMLHttpRequest.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polyfill/XMLHttpRequest.js b/polyfill/XMLHttpRequest.js index 89171921f..42c987704 100644 --- a/polyfill/XMLHttpRequest.js +++ b/polyfill/XMLHttpRequest.js @@ -277,7 +277,7 @@ export default class XMLHttpRequest extends XMLHttpRequestEventTarget{ _headerReceived = (e) => { log.debug('header received ', this._task.taskId, e) this.responseURL = this._url - if(e.state === "2") { + if(e.state === "2" && e.taskId === this._task.taskId) { this._responseHeaders = e.headers this._statusText = e.status this._status = Math.floor(e.status) From 8a75a9be2a613f6ce78dd6cd0e849437a9a8c41c Mon Sep 17 00:00:00 2001 From: Jon San Miguel Date: Mon, 3 Jul 2017 19:40:08 -0400 Subject: [PATCH 04/20] Set mime if set in addAndroidDownloads (#421) --- android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java b/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java index db213c1e8..56fec29b5 100644 --- a/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java +++ b/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java @@ -148,6 +148,9 @@ public void run() { if(options.addAndroidDownloads.hasKey("path")) { req.setDestinationUri(Uri.parse("file://" + options.addAndroidDownloads.getString("path"))); } + if(options.addAndroidDownloads.hasKey("mime")) { + req.setMimeType(options.addAndroidDownloads.getString("mime")); + } // set headers ReadableMapKeySetIterator it = headers.keySetIterator(); while (it.hasNextKey()) { From ed2732a47ef5b4e7748b4c7632771d6f30a12c88 Mon Sep 17 00:00:00 2001 From: Ben Hsieh Date: Wed, 5 Jul 2017 14:14:16 +0800 Subject: [PATCH 05/20] Fix Download Manager bug when the file is not a multimedia #391 --- .../java/com/RNFetchBlob/RNFetchBlobReq.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java b/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java index db213c1e8..31377650a 100644 --- a/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java +++ b/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java @@ -150,6 +150,14 @@ public void run() { } // set headers ReadableMapKeySetIterator it = headers.keySetIterator(); + // #391 Add MIME type to the request + if(options.addAndroidDownloads.hasKey("mime")) { + req.setMimeType(options.addAndroidDownloads.getString("mime")); + } + + if(options.addAndroidDownloads.hasKey("mediaScannable") && options.addAndroidDownloads.hasKey("mediaScannable") == true ) { + req.allowScanningByMediaScanner(); + } while (it.hasNextKey()) { String key = it.nextKey(); req.addRequestHeader(key, headers.getString(key)); @@ -636,16 +644,20 @@ public void onReceive(Context context, Intent intent) { return; } String contentUri = c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)); - if (contentUri != null) { + if ( contentUri != null && + options.addAndroidDownloads.hasKey("mime") && + options.addAndroidDownloads.getString("mime").contains("image")) { Uri uri = Uri.parse(contentUri); Cursor cursor = appCtx.getContentResolver().query(uri, new String[]{android.provider.MediaStore.Images.ImageColumns.DATA}, null, null, null); - // use default destination of DownloadManager + + // use default destination of DownloadManager if (cursor != null) { cursor.moveToFirst(); filePath = cursor.getString(0); } } } + // When the file is not found in media content database, check if custom path exists if (options.addAndroidDownloads.hasKey("path")) { try { From 6bb7c65161c17e4961e28dee4b8ff0d359da03ff Mon Sep 17 00:00:00 2001 From: Jeff Hellman Date: Fri, 14 Jul 2017 01:15:53 -0600 Subject: [PATCH 06/20] Add support for TLS 1.2 when running Android 4 (#430) --- .../java/com/RNFetchBlob/RNFetchBlobReq.java | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java b/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java index 34dc2887c..8a81a832e 100644 --- a/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java +++ b/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java @@ -7,10 +7,12 @@ import android.content.IntentFilter; import android.database.Cursor; import android.net.Uri; +import android.os.Build; import android.util.Base64; import com.RNFetchBlob.Response.RNFetchBlobDefaultResp; import com.RNFetchBlob.Response.RNFetchBlobFileResp; +import com.facebook.common.logging.FLog; import com.facebook.react.bridge.Arguments; import com.facebook.react.bridge.Callback; import com.facebook.react.bridge.ReactApplicationContext; @@ -21,6 +23,7 @@ import com.facebook.react.bridge.WritableMap; import com.facebook.react.modules.core.DeviceEventManagerModule; import com.facebook.react.modules.network.OkHttpClientProvider; +import com.facebook.react.modules.network.TLSSocketFactory; import java.io.File; import java.io.FileOutputStream; @@ -35,11 +38,14 @@ import java.nio.charset.Charset; import java.nio.charset.CharsetEncoder; import java.util.ArrayList; +import java.util.List; import java.util.HashMap; + import java.util.concurrent.TimeUnit; import okhttp3.Call; import okhttp3.ConnectionPool; +import okhttp3.ConnectionSpec; import okhttp3.Headers; import okhttp3.Interceptor; import okhttp3.MediaType; @@ -48,6 +54,8 @@ import okhttp3.RequestBody; import okhttp3.Response; import okhttp3.ResponseBody; +import okhttp3.TlsVersion; + public class RNFetchBlobReq extends BroadcastReceiver implements Runnable { @@ -366,9 +374,10 @@ public Response intercept(Chain chain) throws IOException { clientBuilder.retryOnConnectionFailure(false); clientBuilder.followRedirects(options.followRedirect); clientBuilder.followSslRedirects(options.followRedirect); + clientBuilder.retryOnConnectionFailure(true); + OkHttpClient client = enableTls12OnPreLollipop(clientBuilder).build(); - OkHttpClient client = clientBuilder.retryOnConnectionFailure(true).build(); Call call = client.newCall(req); taskTable.put(taskId, call); call.enqueue(new okhttp3.Callback() { @@ -683,5 +692,28 @@ public void onReceive(Context context, Intent intent) { } } + public static OkHttpClient.Builder enableTls12OnPreLollipop(OkHttpClient.Builder client) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) { + try { + client.sslSocketFactory(new TLSSocketFactory()); + + ConnectionSpec cs = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) + .tlsVersions(TlsVersion.TLS_1_2) + .build(); + + List< ConnectionSpec > specs = new ArrayList < > (); + specs.add(cs); + specs.add(ConnectionSpec.COMPATIBLE_TLS); + specs.add(ConnectionSpec.CLEARTEXT); + + client.connectionSpecs(specs); + } catch (Exception exc) { + FLog.e("OkHttpClientProvider", "Error while enabling TLS 1.2", exc); + } + } + + return client; + } + } From b70a12455dd353517dc392a65d77f43e2f1938aa Mon Sep 17 00:00:00 2001 From: Ben Hsieh Date: Fri, 14 Jul 2017 15:34:11 +0800 Subject: [PATCH 07/20] Update README.md --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index b315848b9..7680fab86 100644 --- a/README.md +++ b/README.md @@ -26,13 +26,13 @@ A project committed to making file access and data transfer easier and more effi * [Android Media Scanner, and Download Manager Support](#user-content-android-media-scanner-and-download-manager-support) * [Self-Signed SSL Server](#user-content-self-signed-ssl-server) * [Transfer Encoding](#user-content-transfer-encoding) - * [RNFetchBlob as Fetch](#user-content-rnfetchblob-as-fetch) + * [Drop-in Fetch Replacement](#user-content-drop-in-fetch-replacement) * [File System](#user-content-file-system) * [File access](#user-content-file-access) * [File stream](#user-content-file-stream) * [Manage cached files](#user-content-cache-file-management) * [Web API Polyfills](#user-content-web-api-polyfills) -* [Performance Tips](#user-content-performance-tipsd) +* [Performance Tips](#user-content-performance-tips) * [API References](https://github.com/wkh237/react-native-fetch-blob/wiki/Fetch-API) * [Caveats](#user-content-caveats) * [Development](#user-content-development) @@ -452,11 +452,11 @@ task.cancel((err) => { ... }) ``` -### RNFetchBlob as Fetch +### Drop-in Fetch Replacement 0.9.0 -If you have existing code that uses `whatwg-fetch`(the official **fetch**), you don't have to change them after 0.9.0, just use fetch replacement. The difference between Official fetch and fetch replacement is, official fetch uses [whatwg-fetch](https://github.com/github/fetch) js library which wraps XMLHttpRequest polyfill under the hood it's a great library for web developers, however that does not play very well with RN. Our implementation is simply a wrapper of RNFetchBlob.fetch and fs APIs, so you can access all the features we provide. +If you have existing code that uses `whatwg-fetch`(the official **fetch**), it's not necessary to replace them with `RNFetchblob.fetch`, you can simply use our **Fetch Replacement**. The difference between Official them is official fetch uses [whatwg-fetch](https://github.com/github/fetch) which wraps XMLHttpRequest polyfill under the hood. It's a great library for web developers, but does not play very well with RN. Our implementation is simply a wrapper of our `fetch` and `fs` APIs, so you can access all the features we provided. [See document and examples](https://github.com/wkh237/react-native-fetch-blob/wiki/Fetch-API#fetch-replacement) @@ -613,6 +613,8 @@ In `v0.5.0` we've added `writeStream` and `readStream`, which allows your app r When calling `readStream` method, you have to `open` the stream, and start to read data. When the file is large, consider using an appropriate `bufferSize` and `interval` to reduce the native event dispatching overhead (see [Performance Tips](#user-content-performance-tips)) +> The file stream event has a default throttle(10ms) and buffer size which preventing it cause too much overhead to main thread, yo can also [tweak these values](#user-content-performance-tips). + ```js let data = '' RNFetchBlob.fs.readStream( From 712c8a3a07044fb2ed9679eb5cfa010f553ad215 Mon Sep 17 00:00:00 2001 From: JoshB Date: Mon, 17 Jul 2017 05:22:33 -0700 Subject: [PATCH 08/20] [iOS] Fix for RNFetchBlob.writeChunk failing to write base64 encoded strings (#433) --- ios/RNFetchBlobFS.m | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ios/RNFetchBlobFS.m b/ios/RNFetchBlobFS.m index 9d4e00b0d..5e102d184 100644 --- a/ios/RNFetchBlobFS.m +++ b/ios/RNFetchBlobFS.m @@ -568,11 +568,11 @@ - (NSString *)openWithPath:(NSString *)destPath encode:(nullable NSString *)enco // Write file chunk into an opened stream - (void)writeEncodeChunk:(NSString *) chunk { - NSMutableData * decodedData = [NSData alloc]; + NSData * decodedData = nil; if([[self.encoding lowercaseString] isEqualToString:@"base64"]) { - decodedData = [[NSData alloc] initWithBase64EncodedData:chunk options:0]; - } - if([[self.encoding lowercaseString] isEqualToString:@"utf8"]) { + decodedData = [[NSData alloc] initWithBase64EncodedString:chunk options: NSDataBase64DecodingIgnoreUnknownCharacters]; + } + else if([[self.encoding lowercaseString] isEqualToString:@"utf8"]) { decodedData = [chunk dataUsingEncoding:NSUTF8StringEncoding]; } else if([[self.encoding lowercaseString] isEqualToString:@"ascii"]) { @@ -793,4 +793,4 @@ + (void) writeAssetToPath:(ALAssetRepresentation * )rep dest:(NSString *)dest return; } -@end +@end \ No newline at end of file From d83d8007a8e8cdddda368d78bb622a53a99b8d3b Mon Sep 17 00:00:00 2001 From: Ben Hsieh Date: Tue, 25 Jul 2017 09:57:53 +0800 Subject: [PATCH 09/20] Add missing API Blob.safeClose() --- polyfill/Blob.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/polyfill/Blob.js b/polyfill/Blob.js index 384ae8fd9..a91a897b6 100644 --- a/polyfill/Blob.js +++ b/polyfill/Blob.js @@ -130,6 +130,8 @@ export default class Blob extends EventTarget { // Blob data from file path else if(typeof data === 'string' && data.startsWith('RNFetchBlob-file://')) { log.verbose('create Blob cache file from file path', data) + // set this flag so that we know this blob is a wrapper of an existing file + this._isReference = true this._ref = String(data).replace('RNFetchBlob-file://', '') let orgPath = this._ref if(defer) @@ -282,6 +284,20 @@ export default class Blob extends EventTarget { }) } + safeClose() { + if(this._closed) + return Promise.reject('Blob has been released.) + this._closed = true + if(!this._isReference) { + return fs.unlink(this._ref).catch((err) => { + console.warn(err) + }) + } + else { + return Promise.resolve() + } + } + _invokeOnCreateEvent() { log.verbose('invoke create event', this._onCreated) this._blobCreated = true From d1d07d0922468ed812de5bc11d4ed4743589074b Mon Sep 17 00:00:00 2001 From: Hizoul Date: Wed, 2 Aug 2017 02:43:47 +0200 Subject: [PATCH 10/20] Fix Compilation Error in React Native 0.47.0 (#452) createJSModules was removedin React Native 0.47.0 and results in the attached Build Error. removing @Override fixes build (didn't remove function because I don't know if it should be kept for downard compatability?) ``` node_modules/react-native-fetch-blob/android/src/main/java/com/RNFetchBlob/RNFetchBlobPackage.java:23: error: method does not override or implement a method from a supertype @Override ^ 1 error Incremental compilation of 1 classes completed in 0.219 secs. :react-native-fetch-blob:compileReleaseJavaWithJavac FAILED FAILURE: Build failed with an exception. ``` --- android/src/main/java/com/RNFetchBlob/RNFetchBlobPackage.java | 1 - 1 file changed, 1 deletion(-) diff --git a/android/src/main/java/com/RNFetchBlob/RNFetchBlobPackage.java b/android/src/main/java/com/RNFetchBlob/RNFetchBlobPackage.java index 74e0224a7..48aac7ac3 100644 --- a/android/src/main/java/com/RNFetchBlob/RNFetchBlobPackage.java +++ b/android/src/main/java/com/RNFetchBlob/RNFetchBlobPackage.java @@ -20,7 +20,6 @@ public List createNativeModules(ReactApplicationContext reactConte return modules; } - @Override public List> createJSModules() { return Collections.emptyList(); } From 6bde5167b435e23e334377aa3bb62e8cf7c7e188 Mon Sep 17 00:00:00 2001 From: Ben Hsieh Date: Wed, 2 Aug 2017 23:03:16 +0800 Subject: [PATCH 11/20] Bump to 0.10.7 --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index a4524df60..0d88ec178 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-fetch-blob", - "version": "0.10.6", + "version": "0.10.7", "description": "A module provides upload, download, and files access API. Supports file stream read/write for process large files.", "main": "index.js", "scripts": { @@ -8,7 +8,7 @@ }, "dependencies": { "base-64": "0.1.0", - "glob": "^7.0.6" + "glob": "7.0.6" }, "keywords": [ "react-native", @@ -35,4 +35,4 @@ "Ben ", "" ] -} \ No newline at end of file +} From 50c157345f13725855e6405f91a1f544575cfd4e Mon Sep 17 00:00:00 2001 From: Ben Hsieh Date: Wed, 2 Aug 2017 23:13:10 +0800 Subject: [PATCH 12/20] Update PULL_REQUEST_TEMPLATE --- .github/PULL_REQUEST_TEMPLATE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE index edadaa9b6..cef8ed2af 100644 --- a/.github/PULL_REQUEST_TEMPLATE +++ b/.github/PULL_REQUEST_TEMPLATE @@ -1,5 +1,5 @@ Thank you for making a pull request ! Just a gentle reminder :) 1. If the PR is offering a feature please make the request to our "Feature Branch" 0.11.0 -2. Bug fix request to "Bug Fix Branch" 0.10.7 +2. Bug fix request to "Bug Fix Branch" 0.10.8 3. Correct README.md can directly to master From 55009f148288f6471e7e084db3881bbdd1d7d98a Mon Sep 17 00:00:00 2001 From: Ben Hsieh Date: Thu, 3 Aug 2017 09:34:37 +0800 Subject: [PATCH 13/20] Correct unterminated string #455 --- polyfill/Blob.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/polyfill/Blob.js b/polyfill/Blob.js index a91a897b6..53662a798 100644 --- a/polyfill/Blob.js +++ b/polyfill/Blob.js @@ -286,7 +286,7 @@ export default class Blob extends EventTarget { safeClose() { if(this._closed) - return Promise.reject('Blob has been released.) + return Promise.reject('Blob has been released.') this._closed = true if(!this._isReference) { return fs.unlink(this._ref).catch((err) => { From 9ab4ebb72e648156b2af60578de112022f856fb4 Mon Sep 17 00:00:00 2001 From: Ben Hsieh Date: Thu, 3 Aug 2017 09:37:08 +0800 Subject: [PATCH 14/20] bump to 0.10.8 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0d88ec178..a93dba81d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-fetch-blob", - "version": "0.10.7", + "version": "0.10.8", "description": "A module provides upload, download, and files access API. Supports file stream read/write for process large files.", "main": "index.js", "scripts": { From 4c133d662cd1ac8ca4b205f2115b09e5ac3c05b5 Mon Sep 17 00:00:00 2001 From: amoreno Date: Tue, 24 Oct 2017 09:43:57 +0200 Subject: [PATCH 15/20] refs #51397 Added parameters to UIDocumentInteractionController --- ios/RNFetchBlob/RNFetchBlob.m | 44 ++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/ios/RNFetchBlob/RNFetchBlob.m b/ios/RNFetchBlob/RNFetchBlob.m index d6f957195..7534e0b06 100644 --- a/ios/RNFetchBlob/RNFetchBlob.m +++ b/ios/RNFetchBlob/RNFetchBlob.m @@ -315,7 +315,6 @@ - (NSDictionary *)constantsToExport #pragma mark - fs.stat RCT_EXPORT_METHOD(stat:(NSString *)target callback:(RCTResponseSenderBlock) callback) { - [RNFetchBlobFS getPathFromUri:target completionHandler:^(NSString *path, ALAssetRepresentation *asset) { __block NSMutableArray * result; if(path != nil) @@ -536,11 +535,40 @@ - (NSDictionary *)constantsToExport # pragma mark - open file with UIDocumentInteractionController and delegate -RCT_EXPORT_METHOD(openDocument:(NSString*)uri scheme:(NSString *)scheme name:(NSString*)name resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) +- (void)openDocument:(NSString *)uri + scheme:(NSString *)scheme + resolver:(RCTPromiseResolveBlock)resolve + rejecter:(RCTPromiseRejectBlock)reject + fontFamily:(NSString *)fontFamily + fontSize:(float)fontSize + hexString:(NSString *)hexString { NSString * utf8uri = [uri stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; NSURL * url = [[NSURL alloc] initWithString:utf8uri]; // NSURL * url = [[NSURL alloc] initWithString:uri]; + if (fontFamily) { + NSMutableDictionary *titleBarAttributes = [NSMutableDictionary dictionaryWithDictionary: [[UINavigationBar appearance] titleTextAttributes]]; + [titleBarAttributes setValue:[UIFont fontWithName:fontFamily size:fontSize] forKey:NSFontAttributeName]; + unsigned rgbValue = 0; + NSScanner *scanner = [NSScanner scannerWithString:hexString]; + [scanner setScanLocation:1]; // bypass '#' character + [scanner scanHexInt:&rgbValue]; + [titleBarAttributes setValue:[UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 \ + green:((float)((rgbValue & 0x00FF00) >> 8))/255.0 \ + blue:((float)((rgbValue & 0x0000FF) >> 0))/255.0 \ + alpha:1.0] forKey:NSForegroundColorAttributeName]; + [[UINavigationBar appearance] setTitleTextAttributes:titleBarAttributes]; + + NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithDictionary: [[UIBarButtonItem appearance] titleTextAttributesForState:UIControlStateNormal]]; + [attributes setValue:[UIFont fontWithName:fontFamily size:fontSize] forKey:NSFontAttributeName]; + [[UIBarButtonItem appearance] setTitleTextAttributes:attributes forState:UIControlStateNormal]; + [[UIBarButtonItem appearance] setTintColor: [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 \ + green:((float)((rgbValue & 0x00FF00) >> 8))/255.0 \ + blue:((float)((rgbValue & 0x0000FF) >> 0))/255.0 \ + alpha:1.0]]; + [[UINavigationBar appearance] setBarTintColor: [UIColor whiteColor]]; + } + documentController = [UIDocumentInteractionController interactionControllerWithURL:url]; documentController.delegate = self; documentController.name = name; @@ -555,6 +583,16 @@ - (NSDictionary *)constantsToExport } } +RCT_EXPORT_METHOD(openDocument:(NSString*)uri scheme:(NSString*)scheme resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject fontFamily:(NSString*)fontFamily fontSize:(float)fontSize hexString:(NSString*)hexString) +{ + [self openDocument:uri scheme:scheme resolver:resolver rejecter:rejecter fontFamily:fontFamily fontSize:fontSize hexString:hexString]; +} + +RCT_EXPORT_METHOD(openDocument:(NSString*)uri scheme:(NSString *)scheme name:(NSString*)name resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) +{ + [self openDocument:uri scheme:scheme resolver:resolver rejecter:rejecter fontFamily:nil fontSize:NULL hexString:nil]; +} + # pragma mark - exclude from backup key RCT_EXPORT_METHOD(excludeFromBackupKey:(NSString *)url resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) @@ -576,7 +614,7 @@ - (NSDictionary *)constantsToExport [RNFetchBlobFS df:callback]; } -- (UIViewController *) documentInteractionControllerViewControllerForPreview: (UIDocumentInteractionController *) controller +- (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller { UIWindow *window = [UIApplication sharedApplication].keyWindow; return window.rootViewController; From 37d1e73d3a87fbbadfcd050b12b23384885c1bdd Mon Sep 17 00:00:00 2001 From: amoreno Date: Tue, 24 Oct 2017 09:46:15 +0200 Subject: [PATCH 16/20] refs #51397 Added parameters to UIDocumentInteractionController refs #51397 Added parameters to UIDocumentInteractionController refs #51397 Added parameters to UIDocumentInteractionController refs #51397 Added parameters to UIDocumentInteractionController --- ios.js | 49 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 38 insertions(+), 11 deletions(-) diff --git a/ios.js b/ios.js index 95df49f0c..9896c3b47 100644 --- a/ios.js +++ b/ios.js @@ -6,10 +6,10 @@ import { NativeModules, DeviceEventEmitter, Platform, - NativeAppEventEmitter, + NativeAppEventEmitter } from 'react-native' -const RNFetchBlob:RNFetchBlobNative = NativeModules.RNFetchBlob +const RNFetchBlob: RNFetchBlobNative = NativeModules.RNFetchBlob /** * Open a file using UIDocumentInteractionController @@ -17,11 +17,12 @@ const RNFetchBlob:RNFetchBlobNative = NativeModules.RNFetchBlob * @param {string} scheme URI scheme that needs to support, optional * @return {Promise} */ -function previewDocument(path:string, scheme:string) { - if(Platform.OS === 'ios') +function previewDocument(path: string, scheme: string) { + if (Platform.OS === 'ios') { return RNFetchBlob.previewDocument('file://' + path, scheme) - else + } else { return Promise.reject('RNFetchBlob.openDocument only supports IOS.') + } } /** @@ -31,11 +32,37 @@ function previewDocument(path:string, scheme:string) { * @param {string} name The name of the target file, optional * @return {Promise} */ -function openDocument(path:string, scheme:string, name: string) { - if(Platform.OS === 'ios') +function openDocument(path: string, scheme: string, name: string) { + if (Platform.OS === 'ios') { return RNFetchBlob.openDocument('file://' + path, scheme, name) - else - return Promise.reject('RNFetchBlob.previewDocument only supports IOS.') + } +} + +/** + * Preview a file using UIDocumentInteractionController + * @param {string]} path Path of the file to be open. + * @param {string} scheme URI scheme that needs to support, optional + * @param {string} name The name of the target file, optional + * @param + * @param + * @return {Promise} + */ +function openDocumentWithFont( + path: string, + fontFamily: string, + fontSize: number, + hexString: string, + scheme: string +) { + if (Platform.OS === 'ios') { + return RNFetchBlob.openDocument( + 'file://' + path, + fontFamily, + fontSize, + hexString, + scheme + ) + } } /** @@ -44,8 +71,8 @@ function openDocument(path:string, scheme:string, name: string) { * @param {string} url URL of the resource, only file URL is supported * @return {Promise} */ -function excludeFromBackupKey(url:string) { - return RNFetchBlob.excludeFromBackupKey('file://' + path); +function excludeFromBackupKey(url: string) { + return RNFetchBlob.excludeFromBackupKey('file://' + path) } export default { From 11d9b657e01b407dbf2ba354ad7d0ae067dc2363 Mon Sep 17 00:00:00 2001 From: amoreno Date: Tue, 24 Oct 2017 10:48:23 +0200 Subject: [PATCH 17/20] Added parameters to UIDocumentInteractionController --- ios/RNFetchBlob/RNFetchBlob.m | 195 ++++++++++++++++------------------ 1 file changed, 92 insertions(+), 103 deletions(-) diff --git a/ios/RNFetchBlob/RNFetchBlob.m b/ios/RNFetchBlob/RNFetchBlob.m index 7534e0b06..382306954 100644 --- a/ios/RNFetchBlob/RNFetchBlob.m +++ b/ios/RNFetchBlob/RNFetchBlob.m @@ -32,7 +32,7 @@ @implementation RNFetchBlob - (dispatch_queue_t) methodQueue { if(commonTaskQueue == nil) - commonTaskQueue = dispatch_queue_create("RNFetchBlob.queue", DISPATCH_QUEUE_SERIAL); + commonTaskQueue = dispatch_queue_create("RNFetchBlob.queue", DISPATCH_QUEUE_SERIAL); return commonTaskQueue; } @@ -48,9 +48,9 @@ - (id) init { self = [super init]; self.filePathPrefix = FILE_PREFIX; if(commonTaskQueue == nil) - commonTaskQueue = dispatch_queue_create("RNFetchBlob.queue", DISPATCH_QUEUE_SERIAL); + commonTaskQueue = dispatch_queue_create("RNFetchBlob.queue", DISPATCH_QUEUE_SERIAL); if(fsQueue == nil) - fsQueue = dispatch_queue_create("RNFetchBlob.fs.queue", DISPATCH_QUEUE_SERIAL); + fsQueue = dispatch_queue_create("RNFetchBlob.fs.queue", DISPATCH_QUEUE_SERIAL); BOOL isDir; // if temp folder not exists, create one if(![[NSFileManager defaultManager] fileExistsAtPath: [RNFetchBlobFS getTempPath] isDirectory:&isDir]) { @@ -66,8 +66,7 @@ - (NSDictionary *)constantsToExport return @{ @"MainBundleDir" : [RNFetchBlobFS getMainBundleDir], @"DocumentDir": [RNFetchBlobFS getDocumentDir], - @"CacheDir" : [RNFetchBlobFS getCacheDir], - @"LibraryDir" : [RNFetchBlobFS getLibraryDir] + @"CacheDir" : [RNFetchBlobFS getCacheDir] }; } @@ -80,7 +79,7 @@ - (NSDictionary *)constantsToExport form:(NSArray *)form callback:(RCTResponseSenderBlock)callback) { - + [RNFetchBlobReqBuilder buildMultipartRequest:options taskId:taskId method:method @@ -88,20 +87,20 @@ - (NSDictionary *)constantsToExport headers:headers form:form onComplete:^(__weak NSURLRequest *req, long bodyLength) - { - // something went wrong when building the request body - if(req == nil) - { - callback(@[@"RNFetchBlob.fetchBlobForm failed to create request body"]); - } - // send HTTP request - else - { - RNFetchBlobNetwork * utils = [[RNFetchBlobNetwork alloc] init]; - [utils sendRequest:options contentLength:bodyLength bridge:self.bridge taskId:taskId withRequest:req callback:callback]; - } - }]; - + { + // something went wrong when building the request body + if(req == nil) + { + callback(@[@"RNFetchBlob.fetchBlobForm failed to create request body"]); + } + // send HTTP request + else + { + RNFetchBlobNetwork * utils = [[RNFetchBlobNetwork alloc] init]; + [utils sendRequest:options contentLength:bodyLength bridge:self.bridge taskId:taskId withRequest:req callback:callback]; + } + }]; + } @@ -120,27 +119,27 @@ - (NSDictionary *)constantsToExport headers:headers body:body onComplete:^(NSURLRequest *req, long bodyLength) - { - // something went wrong when building the request body - if(req == nil) - { - callback(@[@"RNFetchBlob.fetchBlob failed to create request body"]); - } - // send HTTP request - else - { - __block RNFetchBlobNetwork * utils = [[RNFetchBlobNetwork alloc] init]; - [utils sendRequest:options contentLength:bodyLength bridge:self.bridge taskId:taskId withRequest:req callback:callback]; - } - }]; + { + // something went wrong when building the request body + if(req == nil) + { + callback(@[@"RNFetchBlob.fetchBlob failed to create request body"]); + } + // send HTTP request + else + { + __block RNFetchBlobNetwork * utils = [[RNFetchBlobNetwork alloc] init]; + [utils sendRequest:options contentLength:bodyLength bridge:self.bridge taskId:taskId withRequest:req callback:callback]; + } + }]; } #pragma mark - fs.createFile RCT_EXPORT_METHOD(createFile:(NSString *)path data:(NSString *)data encoding:(NSString *)encoding callback:(RCTResponseSenderBlock)callback) { - + NSFileManager * fm = [NSFileManager defaultManager]; NSData * fileContent = nil; - + if([[encoding lowercaseString] isEqualToString:@"utf8"]) { fileContent = [[NSData alloc] initWithData:[data dataUsingEncoding:NSUTF8StringEncoding allowLossyConversion:YES]]; } @@ -154,24 +153,24 @@ - (NSDictionary *)constantsToExport else { fileContent = [[NSData alloc] initWithData:[data dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:YES]]; } - + BOOL success = [fm createFileAtPath:path contents:fileContent attributes:NULL]; if(success == YES) - callback(@[[NSNull null]]); + callback(@[[NSNull null]]); else - callback(@[[NSString stringWithFormat:@"failed to create new file at path %@ please ensure the folder exists"]]); - + callback(@[[NSString stringWithFormat:@"failed to create new file at path %@ please ensure the folder exists"]]); + } #pragma mark - fs.createFileASCII // method for create file with ASCII content RCT_EXPORT_METHOD(createFileASCII:(NSString *)path data:(NSArray *)dataArray callback:(RCTResponseSenderBlock)callback) { - + NSFileManager * fm = [NSFileManager defaultManager]; NSMutableData * fileContent = [NSMutableData alloc]; // prevent stack overflow, alloc on heap char * bytes = (char*) malloc([dataArray count]); - + for(int i = 0; i < dataArray.count; i++) { bytes[i] = [[dataArray objectAtIndex:i] charValue]; } @@ -179,10 +178,10 @@ - (NSDictionary *)constantsToExport BOOL success = [fm createFileAtPath:path contents:fileContent attributes:NULL]; free(bytes); if(success == YES) - callback(@[[NSNull null]]); + callback(@[[NSNull null]]); else - callback(@[[NSString stringWithFormat:@"failed to create new file at path %@ please ensure the folder exists"]]); - + callback(@[[NSString stringWithFormat:@"failed to create new file at path %@ please ensure the folder exists"]]); + } #pragma mark - fs.pathForAppGroup @@ -191,7 +190,7 @@ - (NSDictionary *)constantsToExport rejecter:(RCTPromiseRejectBlock)reject) { NSString * path = [RNFetchBlobFS getPathForAppGroup:groupName]; - + if(path) { resolve(path); } else { @@ -269,9 +268,9 @@ - (NSDictionary *)constantsToExport NSString * tmpPath = nil; [[NSFileManager defaultManager] removeItemAtPath:path error:&error]; if(error == nil || [[NSFileManager defaultManager] fileExistsAtPath:path] == NO) - callback(@[[NSNull null]]); + callback(@[[NSNull null]]); else - callback(@[[NSString stringWithFormat:@"failed to unlink file or path at %@", path]]); + callback(@[[NSString stringWithFormat:@"failed to unlink file or path at %@", path]]); } #pragma mark - fs.removeSession @@ -279,7 +278,7 @@ - (NSDictionary *)constantsToExport { NSError * error = nil; NSString * tmpPath = nil; - + for(NSString * path in paths) { [[NSFileManager defaultManager] removeItemAtPath:path error:&error]; if(error != nil) { @@ -288,7 +287,7 @@ - (NSDictionary *)constantsToExport } } callback(@[[NSNull null]]); - + } #pragma mark - fs.ls @@ -304,12 +303,12 @@ - (NSDictionary *)constantsToExport } NSError * error = nil; NSArray * result = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:&error]; - + if(error == nil) - callback(@[[NSNull null], result == nil ? [NSNull null] :result ]); + callback(@[[NSNull null], result == nil ? [NSNull null] :result ]); else - callback(@[[error localizedDescription], [NSNull null]]); - + callback(@[[error localizedDescription], [NSNull null]]); + } #pragma mark - fs.stat @@ -323,19 +322,19 @@ - (NSDictionary *)constantsToExport BOOL exist = nil; BOOL isDir = nil; NSError * error = nil; - + exist = [fm fileExistsAtPath:path isDirectory:&isDir]; if(exist == NO) { callback(@[[NSString stringWithFormat:@"failed to stat path `%@` for it is not exist or it is not exist", path]]); return ; } result = [RNFetchBlobFS stat:path error:&error]; - + if(error == nil) - callback(@[[NSNull null], result]); + callback(@[[NSNull null], result]); else - callback(@[[error localizedDescription], [NSNull null]]); - + callback(@[[error localizedDescription], [NSNull null]]); + } else if(asset != nil) { @@ -357,9 +356,9 @@ - (NSDictionary *)constantsToExport NSFileManager* fm = [NSFileManager defaultManager]; BOOL exist = nil; BOOL isDir = nil; - + path = [RNFetchBlobFS getPathOfAsset:path]; - + exist = [fm fileExistsAtPath:path isDirectory:&isDir]; if(exist == NO) { callback(@[[NSString stringWithFormat:@"failed to list path `%@` for it is not exist or it is not exist", path]]); @@ -367,7 +366,7 @@ - (NSDictionary *)constantsToExport } NSError * error = nil; NSArray * files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:&error]; - + NSMutableArray * res = [[NSMutableArray alloc] init]; if(isDir == YES) { for(NSString * p in files) { @@ -378,19 +377,19 @@ - (NSDictionary *)constantsToExport else { [res addObject:[RNFetchBlobFS stat:path error:&error]]; } - + if(error == nil) - callback(@[[NSNull null], res == nil ? [NSNull null] :res ]); + callback(@[[NSNull null], res == nil ? [NSNull null] :res ]); else - callback(@[[error localizedDescription], [NSNull null]]); - + callback(@[[error localizedDescription], [NSNull null]]); + } #pragma mark - fs.cp RCT_EXPORT_METHOD(cp:(NSString*)src toPath:(NSString *)dest callback:(RCTResponseSenderBlock) callback) { - -// path = [RNFetchBlobFS getPathOfAsset:path]; + + // path = [RNFetchBlobFS getPathOfAsset:path]; [RNFetchBlobFS getPathFromUri:src completionHandler:^(NSString *path, ALAssetRepresentation *asset) { NSError * error = nil; if(path == nil) @@ -401,14 +400,14 @@ - (NSDictionary *)constantsToExport else { BOOL result = [[NSFileManager defaultManager] copyItemAtURL:[NSURL fileURLWithPath:path] toURL:[NSURL fileURLWithPath:dest] error:&error]; - + if(error == nil) - callback(@[[NSNull null], @YES]); + callback(@[[NSNull null], @YES]); else - callback(@[[error localizedDescription], @NO]); + callback(@[[error localizedDescription], @NO]); } }]; - + } @@ -417,12 +416,12 @@ - (NSDictionary *)constantsToExport { NSError * error = nil; BOOL result = [[NSFileManager defaultManager] moveItemAtURL:[NSURL fileURLWithPath:path] toURL:[NSURL fileURLWithPath:dest] error:&error]; - + if(error == nil) - callback(@[[NSNull null], @YES]); + callback(@[[NSNull null], @YES]); else - callback(@[[error localizedDescription], @NO]); - + callback(@[[error localizedDescription], @NO]); + } #pragma mark - fs.mkdir @@ -433,7 +432,7 @@ - (NSDictionary *)constantsToExport return; } else - [RNFetchBlobFS mkdir:path]; + [RNFetchBlobFS mkdir:path]; callback(@[[NSNull null]]); } @@ -443,7 +442,7 @@ - (NSDictionary *)constantsToExport resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { - + [RNFetchBlobFS readFile:path encoding:encoding onComplete:^(id content, NSString * err) { if(err != nil) { @@ -466,11 +465,11 @@ - (NSDictionary *)constantsToExport { if(bufferSize == nil) { if([[encoding lowercaseString] isEqualToString:@"base64"]) - bufferSize = 4095; + bufferSize = 4095; else - bufferSize = 4096; + bufferSize = 4096; } - + dispatch_async(fsQueue, ^{ [RNFetchBlobFS readStream:path encoding:encoding bufferSize:bufferSize tick:tick streamId:streamId bridgeRef:_bridge]; }); @@ -479,7 +478,7 @@ - (NSDictionary *)constantsToExport #pragma mark - fs.getEnvionmentDirs RCT_EXPORT_METHOD(getEnvironmentDirs:(RCTResponseSenderBlock) callback) { - + callback(@[ [RNFetchBlobFS getDocumentDir], [RNFetchBlobFS getCacheDir], @@ -490,13 +489,13 @@ - (NSDictionary *)constantsToExport RCT_EXPORT_METHOD(cancelRequest:(NSString *)taskId callback:(RCTResponseSenderBlock)callback) { [RNFetchBlobNetwork cancelRequest:taskId]; callback(@[[NSNull null], taskId]); - + } #pragma mark - net.enableProgressReport RCT_EXPORT_METHOD(enableProgressReport:(NSString *)taskId interval:(nonnull NSNumber*)interval count:(nonnull NSNumber*)count) { - + RNFetchBlobProgress * cfg = [[RNFetchBlobProgress alloc] initWithType:Download interval:interval count:count]; [RNFetchBlobNetwork enableProgressReport:taskId config:cfg]; } @@ -523,10 +522,10 @@ - (NSDictionary *)constantsToExport UIViewController *rootCtrl = [[[[UIApplication sharedApplication] delegate] window] rootViewController]; documentController.delegate = self; if(scheme == nil || [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:scheme]]) { - CGRect rect = CGRectMake(0.0, 0.0, 0.0, 0.0); - dispatch_sync(dispatch_get_main_queue(), ^{ - [documentController presentOptionsMenuFromRect:rect inView:rootCtrl.view animated:YES]; - }); + CGRect rect = CGRectMake(0.0, 0.0, 0.0, 0.0); + dispatch_sync(dispatch_get_main_queue(), ^{ + [documentController presentOptionsMenuFromRect:rect inView:rootCtrl.view animated:YES]; + }); resolve(@[[NSNull null]]); } else { reject(@"RNFetchBlob could not open document", @"scheme is not supported", nil); @@ -535,13 +534,7 @@ - (NSDictionary *)constantsToExport # pragma mark - open file with UIDocumentInteractionController and delegate -- (void)openDocument:(NSString *)uri - scheme:(NSString *)scheme - resolver:(RCTPromiseResolveBlock)resolve - rejecter:(RCTPromiseRejectBlock)reject - fontFamily:(NSString *)fontFamily - fontSize:(float)fontSize - hexString:(NSString *)hexString +RCT_EXPORT_METHOD(openDocument:(NSString*)uri scheme:(NSString*)scheme resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject fontFamily:(NSString*)fontFamily fontSize:(CGFloat)fontSize hexString:(NSString*)hexString) { NSString * utf8uri = [uri stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; NSURL * url = [[NSURL alloc] initWithString:utf8uri]; @@ -571,8 +564,7 @@ - (void)openDocument:(NSString *)uri documentController = [UIDocumentInteractionController interactionControllerWithURL:url]; documentController.delegate = self; - documentController.name = name; - + if(scheme == nil || [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:scheme]]) { dispatch_sync(dispatch_get_main_queue(), ^{ [documentController presentPreviewAnimated:YES]; @@ -583,14 +575,9 @@ - (void)openDocument:(NSString *)uri } } -RCT_EXPORT_METHOD(openDocument:(NSString*)uri scheme:(NSString*)scheme resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject fontFamily:(NSString*)fontFamily fontSize:(float)fontSize hexString:(NSString*)hexString) -{ - [self openDocument:uri scheme:scheme resolver:resolver rejecter:rejecter fontFamily:fontFamily fontSize:fontSize hexString:hexString]; -} - RCT_EXPORT_METHOD(openDocument:(NSString*)uri scheme:(NSString *)scheme name:(NSString*)name resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { - [self openDocument:uri scheme:scheme resolver:resolver rejecter:rejecter fontFamily:nil fontSize:NULL hexString:nil]; + [self openDocument:uri scheme:scheme resolver:resolve rejecter:reject fontFamily:nil fontSize:0.0f hexString:nil]; } # pragma mark - exclude from backup key @@ -605,7 +592,7 @@ - (void)openDocument:(NSString *)uri } else { reject(@"RNFetchBlob could not open document", [error description], nil); } - + } @@ -640,3 +627,5 @@ - (UIViewController *)documentInteractionControllerViewControllerForPreview:(UID @end + + From a93abc68f616647660e4ca75bad21ee03f2fd304 Mon Sep 17 00:00:00 2001 From: amorenovalls Date: Tue, 24 Oct 2017 20:40:56 +0200 Subject: [PATCH 18/20] Support to change color of navigation bar --- ios.js | 11 ++-- ios/RNFetchBlob/RNFetchBlob.m | 121 ++++++++++++++++++---------------- 2 files changed, 73 insertions(+), 59 deletions(-) diff --git a/ios.js b/ios.js index 9896c3b47..d5ccb7572 100644 --- a/ios.js +++ b/ios.js @@ -40,11 +40,12 @@ function openDocument(path: string, scheme: string, name: string) { /** * Preview a file using UIDocumentInteractionController - * @param {string]} path Path of the file to be open. + * @param {string} path Path of the file to be open. * @param {string} scheme URI scheme that needs to support, optional - * @param {string} name The name of the target file, optional - * @param - * @param + * @param {string} fontFamily The name of the font family + * @param {string} hexString The color in hex format + * @param {number} fontSize Size of the font + * @param {string} barTintColor The color of the navigation bar in hex format * @return {Promise} */ function openDocumentWithFont( @@ -52,6 +53,7 @@ function openDocumentWithFont( fontFamily: string, fontSize: number, hexString: string, + barTintColor: string, scheme: string ) { if (Platform.OS === 'ios') { @@ -60,6 +62,7 @@ function openDocumentWithFont( fontFamily, fontSize, hexString, + barTintColor, scheme ) } diff --git a/ios/RNFetchBlob/RNFetchBlob.m b/ios/RNFetchBlob/RNFetchBlob.m index 382306954..fc8d578c7 100644 --- a/ios/RNFetchBlob/RNFetchBlob.m +++ b/ios/RNFetchBlob/RNFetchBlob.m @@ -31,8 +31,9 @@ @implementation RNFetchBlob @synthesize bridge = _bridge; - (dispatch_queue_t) methodQueue { - if(commonTaskQueue == nil) - commonTaskQueue = dispatch_queue_create("RNFetchBlob.queue", DISPATCH_QUEUE_SERIAL); + if(commonTaskQueue == nil) { + commonTaskQueue = dispatch_queue_create("RNFetchBlob.queue", DISPATCH_QUEUE_SERIAL); + } return commonTaskQueue; } @@ -47,11 +48,14 @@ + (RCTBridge *)getRCTBridge - (id) init { self = [super init]; self.filePathPrefix = FILE_PREFIX; - if(commonTaskQueue == nil) - commonTaskQueue = dispatch_queue_create("RNFetchBlob.queue", DISPATCH_QUEUE_SERIAL); - if(fsQueue == nil) - fsQueue = dispatch_queue_create("RNFetchBlob.fs.queue", DISPATCH_QUEUE_SERIAL); + if(commonTaskQueue == nil) { + commonTaskQueue = dispatch_queue_create("RNFetchBlob.queue", DISPATCH_QUEUE_SERIAL); + } + if(fsQueue == nil) { + fsQueue = dispatch_queue_create("RNFetchBlob.fs.queue", DISPATCH_QUEUE_SERIAL); + } BOOL isDir; + // if temp folder not exists, create one if(![[NSFileManager defaultManager] fileExistsAtPath: [RNFetchBlobFS getTempPath] isDirectory:&isDir]) { [[NSFileManager defaultManager] createDirectoryAtPath:[RNFetchBlobFS getTempPath] withIntermediateDirectories:YES attributes:nil error:NULL]; @@ -155,11 +159,11 @@ - (NSDictionary *)constantsToExport } BOOL success = [fm createFileAtPath:path contents:fileContent attributes:NULL]; - if(success == YES) - callback(@[[NSNull null]]); - else - callback(@[[NSString stringWithFormat:@"failed to create new file at path %@ please ensure the folder exists"]]); - + if(success == YES) { + callback(@[[NSNull null]]); + } else { + callback(@[[NSString stringWithFormat:@"failed to create new file at path %@ please ensure the folder exists"]]); + } } #pragma mark - fs.createFileASCII @@ -177,11 +181,12 @@ - (NSDictionary *)constantsToExport [fileContent appendBytes:bytes length:dataArray.count]; BOOL success = [fm createFileAtPath:path contents:fileContent attributes:NULL]; free(bytes); - if(success == YES) - callback(@[[NSNull null]]); - else - callback(@[[NSString stringWithFormat:@"failed to create new file at path %@ please ensure the folder exists"]]); + if(success == YES) { + callback(@[[NSNull null]]); + } else { + callback(@[[NSString stringWithFormat:@"failed to create new file at path %@ please ensure the folder exists"]]); + } } #pragma mark - fs.pathForAppGroup @@ -267,10 +272,11 @@ - (NSDictionary *)constantsToExport NSError * error = nil; NSString * tmpPath = nil; [[NSFileManager defaultManager] removeItemAtPath:path error:&error]; - if(error == nil || [[NSFileManager defaultManager] fileExistsAtPath:path] == NO) - callback(@[[NSNull null]]); - else - callback(@[[NSString stringWithFormat:@"failed to unlink file or path at %@", path]]); + if(error == nil || [[NSFileManager defaultManager] fileExistsAtPath:path] == NO) { + callback(@[[NSNull null]]); + } else { + callback(@[[NSString stringWithFormat:@"failed to unlink file or path at %@", path]]); + } } #pragma mark - fs.removeSession @@ -299,16 +305,16 @@ - (NSDictionary *)constantsToExport exist = [fm fileExistsAtPath:path isDirectory:&isDir]; if(exist == NO || isDir == NO) { callback(@[[NSString stringWithFormat:@"failed to list path `%@` for it is not exist or it is not a folder", path]]); - return ; + return; } NSError * error = nil; NSArray * result = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:&error]; - if(error == nil) - callback(@[[NSNull null], result == nil ? [NSNull null] :result ]); - else - callback(@[[error localizedDescription], [NSNull null]]); - + if(error == nil) { + callback(@[[NSNull null], result == nil ? [NSNull null] :result ]); + } else { + callback(@[[error localizedDescription], [NSNull null]]); + } } #pragma mark - fs.stat @@ -330,11 +336,11 @@ - (NSDictionary *)constantsToExport } result = [RNFetchBlobFS stat:path error:&error]; - if(error == nil) - callback(@[[NSNull null], result]); - else - callback(@[[error localizedDescription], [NSNull null]]); - + if(error == nil) { + callback(@[[NSNull null], result]); + } else { + callback(@[[error localizedDescription], [NSNull null]]); + } } else if(asset != nil) { @@ -362,7 +368,7 @@ - (NSDictionary *)constantsToExport exist = [fm fileExistsAtPath:path isDirectory:&isDir]; if(exist == NO) { callback(@[[NSString stringWithFormat:@"failed to list path `%@` for it is not exist or it is not exist", path]]); - return ; + return; } NSError * error = nil; NSArray * files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:path error:&error]; @@ -378,11 +384,11 @@ - (NSDictionary *)constantsToExport [res addObject:[RNFetchBlobFS stat:path error:&error]]; } - if(error == nil) - callback(@[[NSNull null], res == nil ? [NSNull null] :res ]); - else - callback(@[[error localizedDescription], [NSNull null]]); - + if(error == nil) { + callback(@[[NSNull null], res == nil ? [NSNull null] :res ]); + } else { + callback(@[[error localizedDescription], [NSNull null]]); + } } #pragma mark - fs.cp @@ -401,10 +407,11 @@ - (NSDictionary *)constantsToExport { BOOL result = [[NSFileManager defaultManager] copyItemAtURL:[NSURL fileURLWithPath:path] toURL:[NSURL fileURLWithPath:dest] error:&error]; - if(error == nil) - callback(@[[NSNull null], @YES]); - else - callback(@[[error localizedDescription], @NO]); + if(error == nil) { + callback(@[[NSNull null], @YES]); + } else { + callback(@[[error localizedDescription], @NO]); + } } }]; @@ -417,11 +424,11 @@ - (NSDictionary *)constantsToExport NSError * error = nil; BOOL result = [[NSFileManager defaultManager] moveItemAtURL:[NSURL fileURLWithPath:path] toURL:[NSURL fileURLWithPath:dest] error:&error]; - if(error == nil) - callback(@[[NSNull null], @YES]); - else - callback(@[[error localizedDescription], @NO]); - + if(error == nil) { + callback(@[[NSNull null], @YES]); + } else { + callback(@[[error localizedDescription], @NO]); + } } #pragma mark - fs.mkdir @@ -430,10 +437,10 @@ - (NSDictionary *)constantsToExport if([[NSFileManager defaultManager] fileExistsAtPath:path]) { callback(@[@"mkdir failed, folder already exists"]); return; + } else { + [RNFetchBlobFS mkdir:path]; + callback(@[[NSNull null]]); } - else - [RNFetchBlobFS mkdir:path]; - callback(@[[NSNull null]]); } #pragma mark - fs.readFile @@ -464,10 +471,11 @@ - (NSDictionary *)constantsToExport RCT_EXPORT_METHOD(readStream:(NSString *)path withEncoding:(NSString *)encoding bufferSize:(int)bufferSize tick:(int)tick streamId:(NSString *)streamId) { if(bufferSize == nil) { - if([[encoding lowercaseString] isEqualToString:@"base64"]) - bufferSize = 4095; - else - bufferSize = 4096; + if([[encoding lowercaseString] isEqualToString:@"base64"]) { + bufferSize = 4095; + } else { + bufferSize = 4096; + } } dispatch_async(fsQueue, ^{ @@ -534,7 +542,7 @@ - (NSDictionary *)constantsToExport # pragma mark - open file with UIDocumentInteractionController and delegate -RCT_EXPORT_METHOD(openDocument:(NSString*)uri scheme:(NSString*)scheme resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject fontFamily:(NSString*)fontFamily fontSize:(CGFloat)fontSize hexString:(NSString*)hexString) +RCT_EXPORT_METHOD(openDocument:(NSString*)uri scheme:(NSString*)scheme resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject fontFamily:(NSString*)fontFamily fontSize:(CGFloat)fontSize hexString:(NSString*)hexString barTintColor:(NSString*)barTintColor) { NSString * utf8uri = [uri stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; NSURL * url = [[NSURL alloc] initWithString:utf8uri]; @@ -559,7 +567,10 @@ - (NSDictionary *)constantsToExport green:((float)((rgbValue & 0x00FF00) >> 8))/255.0 \ blue:((float)((rgbValue & 0x0000FF) >> 0))/255.0 \ alpha:1.0]]; - [[UINavigationBar appearance] setBarTintColor: [UIColor whiteColor]]; + [[UINavigationBar appearance] setBarTintColor: [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 \ + green:((float)((rgbValue & 0x00FF00) >> 8))/255.0 \ + blue:((float)((rgbValue & 0x0000FF) >> 0))/255.0 \ + alpha:1.0]]]; } documentController = [UIDocumentInteractionController interactionControllerWithURL:url]; @@ -577,7 +588,7 @@ - (NSDictionary *)constantsToExport RCT_EXPORT_METHOD(openDocument:(NSString*)uri scheme:(NSString *)scheme name:(NSString*)name resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { - [self openDocument:uri scheme:scheme resolver:resolve rejecter:reject fontFamily:nil fontSize:0.0f hexString:nil]; + [self openDocument:uri scheme:scheme resolver:resolve rejecter:reject fontFamily:nil fontSize:0.0f hexString:nil, barTintColor:nil]; } # pragma mark - exclude from backup key From 45c200f1668ad19b28481f227e9965bc575e6e7b Mon Sep 17 00:00:00 2001 From: amoreno Date: Tue, 31 Oct 2017 10:18:54 +0100 Subject: [PATCH 19/20] Support to change background color of the navigation bar on iOS --- ios.js | 16 ++++++------ ios/RNFetchBlob/RNFetchBlob.m | 49 ++++++++++++++++++++++++----------- 2 files changed, 42 insertions(+), 23 deletions(-) diff --git a/ios.js b/ios.js index d5ccb7572..db8354c33 100644 --- a/ios.js +++ b/ios.js @@ -29,23 +29,22 @@ function previewDocument(path: string, scheme: string) { * Preview a file using UIDocumentInteractionController * @param {string]} path Path of the file to be open. * @param {string} scheme URI scheme that needs to support, optional - * @param {string} name The name of the target file, optional * @return {Promise} */ -function openDocument(path: string, scheme: string, name: string) { +function openDocument(path: string, scheme: string) { if (Platform.OS === 'ios') { - return RNFetchBlob.openDocument('file://' + path, scheme, name) + return RNFetchBlob.openDocument('file://' + path, scheme) } } /** * Preview a file using UIDocumentInteractionController * @param {string} path Path of the file to be open. - * @param {string} scheme URI scheme that needs to support, optional * @param {string} fontFamily The name of the font family * @param {string} hexString The color in hex format * @param {number} fontSize Size of the font - * @param {string} barTintColor The color of the navigation bar in hex format + * @param {string} backgroundColor The color of the navigation bar in hex format + * @param {string} scheme URI scheme that needs to support, optional * @return {Promise} */ function openDocumentWithFont( @@ -53,16 +52,16 @@ function openDocumentWithFont( fontFamily: string, fontSize: number, hexString: string, - barTintColor: string, + backgroundColor: string, scheme: string ) { if (Platform.OS === 'ios') { - return RNFetchBlob.openDocument( + return RNFetchBlob.openDocumentWithFont( 'file://' + path, fontFamily, fontSize, hexString, - barTintColor, + backgroundColor, scheme ) } @@ -80,6 +79,7 @@ function excludeFromBackupKey(url: string) { export default { openDocument, + openDocumentWithFont, previewDocument, excludeFromBackupKey } diff --git a/ios/RNFetchBlob/RNFetchBlob.m b/ios/RNFetchBlob/RNFetchBlob.m index fc8d578c7..0eb997960 100644 --- a/ios/RNFetchBlob/RNFetchBlob.m +++ b/ios/RNFetchBlob/RNFetchBlob.m @@ -11,7 +11,6 @@ #import "RNFetchBlobReqBuilder.h" #import "RNFetchBlobProgress.h" - __strong RCTBridge * bridgeRef; dispatch_queue_t commonTaskQueue; dispatch_queue_t fsQueue; @@ -32,7 +31,7 @@ @implementation RNFetchBlob - (dispatch_queue_t) methodQueue { if(commonTaskQueue == nil) { - commonTaskQueue = dispatch_queue_create("RNFetchBlob.queue", DISPATCH_QUEUE_SERIAL); + commonTaskQueue = dispatch_queue_create("RNFetchBlob.queue", DISPATCH_QUEUE_SERIAL); } return commonTaskQueue; } @@ -160,7 +159,7 @@ - (NSDictionary *)constantsToExport BOOL success = [fm createFileAtPath:path contents:fileContent attributes:NULL]; if(success == YES) { - callback(@[[NSNull null]]); + callback(@[[NSNull null]]); } else { callback(@[[NSString stringWithFormat:@"failed to create new file at path %@ please ensure the folder exists"]]); } @@ -542,18 +541,36 @@ - (NSDictionary *)constantsToExport # pragma mark - open file with UIDocumentInteractionController and delegate -RCT_EXPORT_METHOD(openDocument:(NSString*)uri scheme:(NSString*)scheme resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject fontFamily:(NSString*)fontFamily fontSize:(CGFloat)fontSize hexString:(NSString*)hexString barTintColor:(NSString*)barTintColor) +RCT_EXPORT_METHOD(openDocument:(NSString*)uri scheme:(NSString*)scheme resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) +{ + NSString * utf8uri = [uri stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + NSURL * url = [[NSURL alloc] initWithString:utf8uri]; + documentController = [UIDocumentInteractionController interactionControllerWithURL:url]; + documentController.delegate = self; + + if(scheme == nil || [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:scheme]]) { + dispatch_sync(dispatch_get_main_queue(), ^{ + [documentController presentPreviewAnimated:YES]; + }); + resolve(@[[NSNull null]]); + } else { + reject(@"RNFetchBlob could not open document", @"scheme is not supported", nil); + } +} + +RCT_EXPORT_METHOD(openDocumentWithFont:(NSString*)uri fontFamily:(NSString*)fontFamily fontSize:(CGFloat)fontSize hexString:(NSString*)hexString backgroundColor:(NSString*)backgroundColor scheme:(NSString*)scheme resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { NSString * utf8uri = [uri stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; NSURL * url = [[NSURL alloc] initWithString:utf8uri]; // NSURL * url = [[NSURL alloc] initWithString:uri]; + unsigned rgbValue = 0; + NSScanner *scanner = [NSScanner scannerWithString:hexString]; if (fontFamily) { NSMutableDictionary *titleBarAttributes = [NSMutableDictionary dictionaryWithDictionary: [[UINavigationBar appearance] titleTextAttributes]]; [titleBarAttributes setValue:[UIFont fontWithName:fontFamily size:fontSize] forKey:NSFontAttributeName]; - unsigned rgbValue = 0; - NSScanner *scanner = [NSScanner scannerWithString:hexString]; [scanner setScanLocation:1]; // bypass '#' character [scanner scanHexInt:&rgbValue]; + [titleBarAttributes setValue:[UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 \ green:((float)((rgbValue & 0x00FF00) >> 8))/255.0 \ blue:((float)((rgbValue & 0x0000FF) >> 0))/255.0 \ @@ -567,10 +584,17 @@ - (NSDictionary *)constantsToExport green:((float)((rgbValue & 0x00FF00) >> 8))/255.0 \ blue:((float)((rgbValue & 0x0000FF) >> 0))/255.0 \ alpha:1.0]]; - [[UINavigationBar appearance] setBarTintColor: [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 \ - green:((float)((rgbValue & 0x00FF00) >> 8))/255.0 \ - blue:((float)((rgbValue & 0x0000FF) >> 0))/255.0 \ - alpha:1.0]]]; + } + + if (backgroundColor) { + scanner = [NSScanner scannerWithString:backgroundColor]; + [scanner setScanLocation:1]; + [scanner scanHexInt:&rgbValue]; + + [[UINavigationBar appearance] setBackgroundColor:[UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 \ + green:((float)((rgbValue & 0x00FF00) >> 8))/255.0 \ + blue:((float)((rgbValue & 0x0000FF) >> 0))/255.0 \ + alpha:1.0]]; } documentController = [UIDocumentInteractionController interactionControllerWithURL:url]; @@ -586,11 +610,6 @@ - (NSDictionary *)constantsToExport } } -RCT_EXPORT_METHOD(openDocument:(NSString*)uri scheme:(NSString *)scheme name:(NSString*)name resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) -{ - [self openDocument:uri scheme:scheme resolver:resolve rejecter:reject fontFamily:nil fontSize:0.0f hexString:nil, barTintColor:nil]; -} - # pragma mark - exclude from backup key RCT_EXPORT_METHOD(excludeFromBackupKey:(NSString *)url resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) From 8b0aa72b7fa46498fc051bb3270f257a1d682b47 Mon Sep 17 00:00:00 2001 From: alvaromb Date: Fri, 17 Nov 2017 17:35:58 +0100 Subject: [PATCH 20/20] Solved merge issue --- android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java | 1 + 1 file changed, 1 insertion(+) diff --git a/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java b/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java index 738b792cd..15835cd85 100644 --- a/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java +++ b/android/src/main/java/com/RNFetchBlob/RNFetchBlobReq.java @@ -8,6 +8,7 @@ import android.database.Cursor; import android.net.Uri; import android.os.Build; +import android.os.Bundle; import android.util.Base64; import com.RNFetchBlob.Response.RNFetchBlobDefaultResp;