react-native-compressor 1.3.5-alpha → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,9 +1,17 @@
1
1
  ### Would you like to support me?
2
2
 
3
+ <div align="center">
4
+ <a href="https://github.com/nomi9995?tab=followers">
5
+ <img src="https://img.shields.io/github/followers/nomi9995?label=Follow%20%40nomi9995&style=social" />
6
+ </a>
7
+ </br>
3
8
  <a href="https://www.buymeacoffee.com/numan.dev" target="_blank"><img src="https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png" alt="Buy Me A Coffee" style="height: auto !important;width: auto !important;" ></a>
9
+ </div>
4
10
 
5
11
  ---
6
12
 
13
+
14
+
7
15
  # react-native-compressor
8
16
 
9
17
  <!-- Title -->
@@ -26,6 +34,34 @@
26
34
 
27
35
  **If you find this package useful hit the star** 🌟
28
36
 
37
+ # Table of Contents
38
+ <details>
39
+ <summary>Open Table of Contents</summary>
40
+
41
+ * [Installation](#installation)
42
+ + [For React Native](#react-native)
43
+ - [For React Native<0.65](#for-react-native065)
44
+ - [For React Native 0.65 or greater](#for-react-native-065-or-greater)
45
+ + [Managed Expo](#managed-expo)
46
+ * [Usage](#usage)
47
+ + [Image](#image)
48
+ * [Automatic Image Compression Like Whatsapp](#automatic-image-compression-like-whatsapp)
49
+ * [Manual Image Compression](#manual-image-compression)
50
+ * [ImageCompressor API Docs](#imagecompressor)
51
+ + [Video](#video)
52
+ * [Automatic Video Compression Like Whatsapp](#automatic-video-compression-like-whatsapp)
53
+ * [Manual Video Compression](#manual-video-compression)
54
+ * [Cancel Video Compression](#cancel-video-compression)
55
+ * [Video Api Docs](#video-1)
56
+ + [Audio](#audio)
57
+ + [Background Upload](#background-upload)
58
+ - [Other Utilities](#api)
59
+ * [Background Upload](#background-upload-1)
60
+ * [Get Metadata Of Video](#get-metadata-of-video)
61
+ * [Get Real Path](#get-real-path)
62
+ * [Get Temp file Path](#get-temp-file-path)
63
+ </details>
64
+
29
65
  ## Installation
30
66
 
31
67
  ### React Native
@@ -33,7 +69,7 @@
33
69
  #### For React Native<0.65
34
70
 
35
71
  ```sh
36
- yarn add react-native-compressor@0.5.15
72
+ yarn add react-native-compressor@rnlessthan65
37
73
  ```
38
74
 
39
75
  #### For React Native 0.65 or greater
@@ -111,7 +147,7 @@ react-native link react-native-compressor
111
147
 
112
148
  ### Image
113
149
 
114
- ##### For Like Whatsapp Image Compression
150
+ ##### Automatic Image Compression Like Whatsapp
115
151
 
116
152
  ```js
117
153
  import { Image } from 'react-native-compressor';
@@ -123,7 +159,7 @@ const result = await Image.compress('file://path_of_file/image.jpg', {
123
159
 
124
160
  [Here is this package comparison of images compression with WhatsApp](https://docs.google.com/spreadsheets/d/13TsnC1c7NOC9aCjzN6wkKurJQPeGRNwDhWsQOkXQskU/edit?usp=sharing)
125
161
 
126
- ##### For manual Compression
162
+ ##### Manual Image Compression
127
163
 
128
164
  ```js
129
165
  import { Image } from 'react-native-compressor';
@@ -136,7 +172,7 @@ const result = await Image.compress('file://path_of_file/image.jpg', {
136
172
 
137
173
  ### Video
138
174
 
139
- ##### For Like Whatsapp Video Compression
175
+ ##### Automatic Video Compression Like Whatsapp
140
176
 
141
177
  ```js
142
178
  import { Video } from 'react-native-compressor';
@@ -158,7 +194,7 @@ const result = await Video.compress(
158
194
 
159
195
  [Here is this package comparison of video compression with WhatsApp](https://docs.google.com/spreadsheets/d/13TsnC1c7NOC9aCjzN6wkKurJQPeGRNwDhWsQOkXQskU/edit#gid=1055406534)
160
196
 
161
- ##### For manual Compression
197
+ ##### Manual Video Compression
162
198
 
163
199
  ```js
164
200
  import { Video } from 'react-native-compressor';
@@ -334,6 +370,57 @@ type FileSystemUploadOptions = (
334
370
  };
335
371
  ```
336
372
 
373
+ ### Get Metadata Of Video
374
+
375
+ if you want to get metadata of video than you can use this function
376
+
377
+ ```js
378
+ import { getVideoMetaData } from 'react-native-compressor';
379
+
380
+ const metaData = await getVideoMetaData(filePath);
381
+ ```
382
+
383
+ ```
384
+ {
385
+ "duration": "6",
386
+ "extension": "mp4",
387
+ "height": "1080",
388
+ "size": "16940.0",
389
+ "width": "1920"
390
+ }
391
+ ```
392
+
393
+ - ###### `getVideoMetaData(path: string)`
394
+
395
+ ### Get Real Path
396
+
397
+ if you want to convert
398
+
399
+ - `content://` to `file:///` for android
400
+ - `ph://` to `file:///` for IOS
401
+
402
+ the you can you `getRealPath` function like this
403
+
404
+ ```js
405
+ import { getRealPath } from 'react-native-compressor';
406
+
407
+ const realPath = await getRealPath(fileUri, 'video'); // file://file_path.extension
408
+ ```
409
+
410
+ - ###### `getRealPath(path: string, type: string = 'video'|'image')`
411
+
412
+ ### Get Temp file Path
413
+
414
+ if you wanna make random file path in cache folder then you can use this method like this
415
+
416
+ ```js
417
+ import { generateFilePath } from 'react-native-compressor';
418
+
419
+ const randomFilePathForSaveFile = await generateFilePath('mp4'); // file://file_path.mp4
420
+ ```
421
+
422
+ - ##### `generateFilePath(fileextension: string)`
423
+
337
424
  ## Contributing
338
425
 
339
426
  See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository and the development workflow.
@@ -57,6 +57,6 @@ dependencies {
57
57
  //noinspection GradleDynamicVersion
58
58
  implementation "com.facebook.react:react-native:+" // From node_modules
59
59
  implementation 'io.github.lizhangqu:coreprogress:1.0.2'
60
- implementation 'com.github.nomi9995:VideoCompressor:90adcba85a'
60
+ implementation 'com.github.nomi9995:VideoCompressor:715bcc16e9'
61
61
  // implementation project(path: ':videocompressor')
62
62
  }
@@ -9,6 +9,7 @@ import androidx.annotation.NonNull;
9
9
  import androidx.annotation.Nullable;
10
10
  import androidx.annotation.RequiresApi;
11
11
 
12
+ import com.facebook.react.bridge.Arguments;
12
13
  import com.facebook.react.bridge.Promise;
13
14
  import com.facebook.react.bridge.ReactApplicationContext;
14
15
  import com.facebook.react.bridge.ReactContext;
@@ -20,10 +21,15 @@ import com.facebook.react.module.annotations.ReactModule;
20
21
  import com.facebook.react.modules.core.DeviceEventManagerModule;
21
22
  import com.reactnativecompressor.Image.ImageCompressor;
22
23
  import com.reactnativecompressor.Image.utils.ImageCompressorOptions;
24
+ import com.reactnativecompressor.Utils.Utils;
23
25
  import com.reactnativecompressor.Video.VideoCompressorHelper;
24
26
  import static com.reactnativecompressor.Utils.Utils.generateCacheFilePath;
27
+ import static com.reactnativecompressor.Utils.Utils.getRealPath;
28
+
25
29
  import com.reactnativecompressor.Audio.AudioCompressor;
26
30
 
31
+ import java.io.File;
32
+
27
33
  @ReactModule(name = CompressorModule.NAME)
28
34
  public class CompressorModule extends ReactContextBaseJavaModule {
29
35
  public static final String NAME = "Compressor";
@@ -54,6 +60,7 @@ public class CompressorModule extends ReactContextBaseJavaModule {
54
60
  ReadableMap optionMap,
55
61
  Promise promise) {
56
62
  try {
63
+ imagePath=Utils.getRealPath(imagePath,reactContext);
57
64
  final ImageCompressorOptions options = ImageCompressorOptions.fromMap(optionMap);
58
65
 
59
66
  if(options.compressionMethod==ImageCompressorOptions.CompressionMethod.auto)
@@ -98,7 +105,7 @@ public class CompressorModule extends ReactContextBaseJavaModule {
98
105
 
99
106
  //General
100
107
  @ReactMethod
101
- public void generateFile(String extension, Promise promise) {
108
+ public void generateFilePath(String extension, Promise promise) {
102
109
  try {
103
110
  final String outputUri =generateCacheFilePath(extension,reactContext);
104
111
  promise.resolve(outputUri);
@@ -106,4 +113,42 @@ public class CompressorModule extends ReactContextBaseJavaModule {
106
113
  promise.reject(e);
107
114
  }
108
115
  }
116
+
117
+ @ReactMethod
118
+ public void getRealPath(String path,String type, Promise promise) {
119
+ try {
120
+ final String realPath =Utils.getRealPath(path,reactContext);
121
+ promise.resolve("file://"+realPath);
122
+ } catch (Exception e) {
123
+ promise.reject(e);
124
+ }
125
+ }
126
+
127
+ @ReactMethod
128
+ public void getVideoMetaData(String filePath, Promise promise) {
129
+ try {
130
+ filePath=Utils.getRealPath(filePath,reactContext);
131
+ Uri uri= Uri.parse(filePath);
132
+ String srcPath = uri.getPath();
133
+ MediaMetadataRetriever metaRetriever = new MediaMetadataRetriever();
134
+ metaRetriever.setDataSource(srcPath);
135
+ File file=new File(srcPath);
136
+ float sizeInKBs = file.length()/1024;
137
+ int actualHeight =Integer.parseInt(metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT));
138
+ int actualWidth = Integer.parseInt(metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH));
139
+ long duration = Long.parseLong(metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION));
140
+ String extension = filePath.substring(filePath.lastIndexOf(".")+1);
141
+
142
+ WritableMap params = Arguments.createMap();
143
+ params.putString("size", String.valueOf(sizeInKBs));
144
+ params.putString("width", String.valueOf(actualWidth));
145
+ params.putString("height", String.valueOf(actualHeight));
146
+ params.putString("duration", String.valueOf(duration/1000));
147
+ params.putString("extension", extension);
148
+
149
+ promise.resolve(params);
150
+ } catch (Exception e) {
151
+ promise.reject(e);
152
+ }
153
+ }
109
154
  }
@@ -1,5 +1,8 @@
1
1
  package com.reactnativecompressor.Utils;
2
2
 
3
+ import android.net.Uri;
4
+ import android.util.Log;
5
+
3
6
  import androidx.annotation.Nullable;
4
7
 
5
8
  import com.facebook.react.bridge.Arguments;
@@ -17,6 +20,7 @@ import java.util.UUID;
17
20
 
18
21
  public class Utils {
19
22
  static int videoCompressionThreshold=10;
23
+ private static final String TAG = "react-native-compessor";
20
24
  static Map<String, VideoCompressTask> compressorExports = new HashMap<>();
21
25
 
22
26
  public static String generateCacheFilePath(String extension, ReactApplicationContext reactContext){
@@ -43,7 +47,14 @@ public class Utils {
43
47
 
44
48
  @Override
45
49
  public void onError(String errorMessage) {
46
- promise.reject("Compression has canncelled");
50
+ if(errorMessage.equals(("class java.lang.AssertionError")))
51
+ {
52
+ promise.resolve(srcPath);
53
+ }
54
+ else
55
+ {
56
+ promise.reject("Compression has canncelled");
57
+ }
47
58
  }
48
59
 
49
60
  @Override
@@ -85,4 +96,18 @@ public class Utils {
85
96
  .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
86
97
  .emit(eventName, params);
87
98
  }
99
+
100
+ public static String getRealPath(String fileUrl,ReactApplicationContext reactContext){
101
+ if(fileUrl.startsWith("content://"))
102
+ {
103
+ try {
104
+ Uri uri= Uri.parse(fileUrl);
105
+ fileUrl= RealPathUtil.getRealPath(reactContext,uri);
106
+ }
107
+ catch (Exception ex) {
108
+ Log.d(TAG, " Please see this issue: https://github.com/Shobbak/react-native-compressor/issues/25");
109
+ }
110
+ }
111
+ return fileUrl;
112
+ }
88
113
  }
@@ -17,6 +17,7 @@ import com.facebook.react.module.annotations.ReactModule;
17
17
  import com.facebook.react.modules.core.DeviceEventManagerModule;
18
18
  import com.reactnativecompressor.Utils.RealPathUtil;
19
19
 
20
+ import static com.reactnativecompressor.Utils.Utils.getRealPath;
20
21
  import static com.reactnativecompressor.Video.VideoCompressorHelper.video_activateBackgroundTask_helper;
21
22
  import static com.reactnativecompressor.Video.VideoCompressorHelper.video_deactivateBackgroundTask_helper;
22
23
  import static com.reactnativecompressor.Video.VideoCompressorHelper.video_upload_helper;
@@ -53,17 +54,7 @@ public class VideoModule extends ReactContextBaseJavaModule {
53
54
  ReadableMap optionMap,
54
55
  Promise promise) {
55
56
  final VideoCompressorHelper options = VideoCompressorHelper.fromMap(optionMap);
56
-
57
- if(fileUrl.startsWith("content://"))
58
- {
59
- try {
60
- Uri uri= Uri.parse(fileUrl);
61
- fileUrl= RealPathUtil.getRealPath(reactContext,uri);
62
- }
63
- catch (Exception ex) {
64
- Log.d(TAG, " Please see this issue: https://github.com/Shobbak/react-native-compressor/issues/25");
65
- }
66
- }
57
+ fileUrl=getRealPath(fileUrl,reactContext);
67
58
 
68
59
  if(options.compressionMethod==VideoCompressorHelper.CompressionMethod.auto)
69
60
  {
package/ios/.DS_Store CHANGED
Binary file
@@ -3,4 +3,4 @@
3
3
  //
4
4
  #import <React/RCTBridgeModule.h>
5
5
  #import <React/RCTEventEmitter.h>
6
-
6
+ #import "ImageCompressor.h"
package/ios/Compressor.m CHANGED
@@ -9,6 +9,30 @@
9
9
  #define AlAsset_Library_Scheme @"assets-library"
10
10
  @implementation Compressor
11
11
  AVAssetWriter *assetWriter=nil;
12
+ static NSArray *metadatas;
13
+
14
+ - (NSArray *)metadatas
15
+ {
16
+ if (!metadatas) {
17
+ metadatas = @[
18
+ @"albumName",
19
+ @"artist",
20
+ @"comment",
21
+ @"copyrights",
22
+ @"creationDate",
23
+ @"date",
24
+ @"encodedby",
25
+ @"genre",
26
+ @"language",
27
+ @"location",
28
+ @"lastModifiedDate",
29
+ @"performer",
30
+ @"publisher",
31
+ @"title"
32
+ ];
33
+ }
34
+ return metadatas;
35
+ }
12
36
 
13
37
  RCT_EXPORT_MODULE()
14
38
 
@@ -20,17 +44,19 @@ RCT_EXPORT_METHOD(
20
44
  rejecter: (RCTPromiseRejectBlock) reject) {
21
45
  @try {
22
46
  ImageCompressorOptions *options = [ImageCompressorOptions fromDictionary:optionsDict];
47
+ [ImageCompressor getAbsoluteImagePath:imagePath completionHandler:^(NSString* absoluteImagePath){
48
+ if(options.autoCompress)
49
+ {
50
+ NSString *result = [ImageCompressor autoCompressHandler:absoluteImagePath options:options];
51
+ resolve(result);
52
+ }
53
+ else
54
+ {
55
+ NSString *result = [ImageCompressor manualCompressHandler:absoluteImagePath options:options];
56
+ resolve(result);
57
+ }
58
+ }];
23
59
 
24
- if(options.autoCompress)
25
- {
26
- NSString *result = [ImageCompressor autoCompressHandler:imagePath options:options];
27
- resolve(result);
28
- }
29
- else
30
- {
31
- NSString *result = [ImageCompressor manualCompressHandler:imagePath options:options];
32
- resolve(result);
33
- }
34
60
  }
35
61
  @catch (NSException *exception) {
36
62
  reject(exception.name, exception.reason, nil);
@@ -176,7 +202,7 @@ RCT_EXPORT_METHOD(
176
202
 
177
203
  //general
178
204
  RCT_EXPORT_METHOD(
179
- generateFile: (NSString*) extension
205
+ generateFilePath: (NSString*) extension
180
206
  resolver: (RCTPromiseResolveBlock) resolve
181
207
  rejecter: (RCTPromiseRejectBlock) reject) {
182
208
  @try {
@@ -188,6 +214,30 @@ RCT_EXPORT_METHOD(
188
214
  }
189
215
  }
190
216
 
217
+ RCT_EXPORT_METHOD(
218
+ getRealPath: (NSString*) path
219
+ type: (NSString*) type
220
+ resolver: (RCTPromiseResolveBlock) resolve
221
+ rejecter: (RCTPromiseRejectBlock) reject) {
222
+ @try {
223
+ if([type isEqualToString:@"video"])
224
+ {
225
+ [ImageCompressor getAbsoluteVideoPath:path completionHandler:^(NSString* absoluteImagePath){
226
+ resolve(absoluteImagePath);
227
+ }];
228
+ }
229
+ else
230
+ {
231
+ [ImageCompressor getAbsoluteImagePath:path completionHandler:^(NSString* absoluteImagePath){
232
+ resolve(absoluteImagePath);
233
+ }];
234
+ }
235
+ }
236
+ @catch (NSException *exception) {
237
+ reject(exception.name, exception.reason, nil);
238
+ }
239
+ }
240
+
191
241
  //general
192
242
  RCT_EXPORT_METHOD(
193
243
  getFileSize: (NSString*) filePath
@@ -216,6 +266,63 @@ RCT_EXPORT_METHOD(
216
266
  }
217
267
  }
218
268
 
269
+
270
+ RCT_EXPORT_METHOD(
271
+ getVideoMetaData: (NSString*) filePath
272
+ resolver: (RCTPromiseResolveBlock) resolve
273
+ rejecter: (RCTPromiseRejectBlock) reject) {
274
+ @try {
275
+ [ImageCompressor getAbsoluteVideoPath:filePath completionHandler:^(NSString *absoluteImagePath) {
276
+ if([absoluteImagePath containsString:@"file://"])
277
+ {
278
+ absoluteImagePath=[absoluteImagePath stringByReplacingOccurrencesOfString:@"file://"
279
+ withString:@""];
280
+ }
281
+ NSFileManager *fileManager = [NSFileManager defaultManager];
282
+
283
+ BOOL isDir;
284
+ if (![fileManager fileExistsAtPath:absoluteImagePath isDirectory:&isDir] || isDir){
285
+ NSError *err = [NSError errorWithDomain:@"file not found" code:-15 userInfo:nil];
286
+ reject([NSString stringWithFormat: @"%lu", (long)err.code], err.localizedDescription, err);
287
+ return;
288
+ }
289
+ NSDictionary *attrs = [fileManager attributesOfItemAtPath: absoluteImagePath error: NULL];
290
+ UInt32 fileSize = [attrs fileSize];
291
+ NSString *fileSizeString = [@(fileSize) stringValue];
292
+
293
+ NSMutableDictionary *result = [NSMutableDictionary new];
294
+ NSDictionary *assetOptions = @{AVURLAssetPreferPreciseDurationAndTimingKey: @YES};
295
+ AVURLAsset *asset = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:absoluteImagePath] options:assetOptions];\
296
+ AVAssetTrack *avAsset = [[asset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0];
297
+ CGSize size = [avAsset naturalSize];
298
+ NSString *extension = [[absoluteImagePath lastPathComponent] pathExtension];
299
+ CMTime time = [asset duration];
300
+ int seconds = ceil(time.value/time.timescale);
301
+ [result setObject:[NSString stringWithFormat: @"%.2f", size.width] forKey:@"width"];
302
+ [result setObject:[NSString stringWithFormat: @"%.2f", size.height] forKey:@"height"];
303
+ [result setObject:extension forKey:@"extension"];
304
+ [result setObject:fileSizeString forKey:@"size"];
305
+ [result setObject:[@(seconds) stringValue] forKey:@"duration"];
306
+ NSArray *keys = [NSArray arrayWithObjects:@"commonMetadata", nil];
307
+ [asset loadValuesAsynchronouslyForKeys:keys completionHandler:^{
308
+ // string keys
309
+ for (NSString *key in [self metadatas]) {
310
+ NSArray *items = [AVMetadataItem metadataItemsFromArray:asset.commonMetadata
311
+ withKey:key
312
+ keySpace:AVMetadataKeySpaceCommon];
313
+ for (AVMetadataItem *item in items) {
314
+ [result setObject:item.value forKey:key];
315
+ }
316
+ }
317
+ resolve(result);
318
+ }];
319
+ }];
320
+ }
321
+ @catch (NSException *exception) {
322
+ reject(exception.name, exception.reason, nil);
323
+ }
324
+ }
325
+
219
326
  @end
220
327
 
221
328
 
@@ -242,4 +349,3 @@ RCT_EXTERN_METHOD(deactivateBackgroundTask: (NSDictionary *)options
242
349
  RCT_EXTERN_METHOD(cancelCompression:(NSString *)uuid)
243
350
 
244
351
  @end
245
-
@@ -12,4 +12,6 @@
12
12
  +(NSString *)autoCompressHandler:(NSString *)imagePath options:(ImageCompressorOptions*)options;
13
13
  + (NSString *)manualCompress:(UIImage *)image output:(enum OutputType)output quality:(float)quality outputExtension:(NSString*)outputExtension isBase64:(Boolean)isBase64;
14
14
  + (UIImage *)scaleAndRotateImage:(UIImage *)image;
15
+ + (void)getAbsoluteImagePath:(NSString *)imagePath completionHandler:(void (^)(NSString *absoluteImagePath))completionHandler;
16
+ +(void)getAbsoluteVideoPath:(NSString *)videoPath completionHandler:(void (^)(NSString *absoluteImagePath))completionHandler;
15
17
  @end
@@ -1,7 +1,12 @@
1
1
  #import <Accelerate/Accelerate.h>
2
2
  #import <CoreGraphics/CoreGraphics.h>
3
-
3
+ #import <Photos/Photos.h>
4
+ #import <React/RCTUtils.h>
5
+ #import <React/RCTImageLoader.h>
4
6
  #import "ImageCompressor.h"
7
+ #import <React/RCTConvert.h>
8
+ #import <Foundation/Foundation.h>
9
+ #import <MobileCoreServices/MobileCoreServices.h>
5
10
 
6
11
  @implementation ImageCompressor
7
12
  + (CGSize) findTargetSize: (UIImage *) image maxWidth: (int) maxWidth maxHeight: (int) maxHeight {
@@ -288,4 +293,151 @@
288
293
  return returnablePath;
289
294
  }
290
295
 
296
+ +(void)getAbsoluteImagePath:(NSString *)imagePath completionHandler:(void (^)(NSString *absoluteImagePath))completionHandler
297
+ {
298
+ if (![imagePath containsString:@"ph://"]) {
299
+ completionHandler(imagePath);
300
+ return;
301
+ }
302
+ NSURL *imageURL = [NSURL URLWithString:[imagePath stringByReplacingOccurrencesOfString:@" " withString:@"%20"]];
303
+ CGSize size = CGSizeZero;
304
+ CGFloat scale = 1;
305
+ RCTResizeMode resizeMode = RCTResizeModeContain;
306
+ NSString *assetID = @"";
307
+ PHFetchResult *results;
308
+ if (!imageURL) {
309
+ NSString *errorText = @"Cannot load a photo library asset with no URL";
310
+ @throw([NSException exceptionWithName:errorText reason:errorText userInfo:nil]);
311
+ } else if ([imageURL.scheme caseInsensitiveCompare:@"assets-library"] == NSOrderedSame) {
312
+ assetID = [imageURL absoluteString];
313
+ results = [PHAsset fetchAssetsWithALAssetURLs:@[imageURL] options:nil];
314
+ } else {
315
+ assetID = [imageURL.absoluteString substringFromIndex:@"ph://".length];
316
+ results = [PHAsset fetchAssetsWithLocalIdentifiers:@[assetID] options:nil];
317
+ }
318
+ if (results.count == 0) {
319
+ NSString *errorText = [NSString stringWithFormat:@"Failed to fetch PHAsset with local identifier %@ with no error message.", assetID];
320
+ @throw([NSException exceptionWithName:errorText reason:errorText userInfo:nil]);
321
+ }
322
+ PHAsset *asset = [results firstObject]; // <-- WE GOT THE ASSET
323
+ PHImageRequestOptions *imageOptions = [PHImageRequestOptions new];
324
+ imageOptions.networkAccessAllowed = YES;
325
+ imageOptions.deliveryMode = PHImageRequestOptionsDeliveryModeHighQualityFormat;
326
+
327
+ BOOL useMaximumSize = CGSizeEqualToSize(size, CGSizeZero);
328
+ CGSize targetSize;
329
+ if (useMaximumSize) {
330
+ targetSize = PHImageManagerMaximumSize;
331
+ imageOptions.resizeMode = PHImageRequestOptionsResizeModeNone;
332
+ } else {
333
+ targetSize = CGSizeApplyAffineTransform(size, CGAffineTransformMakeScale(scale, scale));
334
+ imageOptions.resizeMode = PHImageRequestOptionsResizeModeFast;
335
+ }
336
+
337
+ PHImageContentMode contentMode = PHImageContentModeAspectFill;
338
+ if (resizeMode == RCTResizeModeContain) {
339
+ contentMode = PHImageContentModeAspectFit;
340
+ }
341
+ [[PHImageManager defaultManager] requestImageForAsset:asset
342
+ targetSize:targetSize
343
+ contentMode:contentMode
344
+ options:imageOptions
345
+ resultHandler:^(UIImage *result, NSDictionary<NSString *, id> *info) {
346
+ // WE GOT THE IMAGE
347
+ if (result) {
348
+ UIImage *image = result;
349
+ NSString *imageName = [assetID stringByReplacingOccurrencesOfString:@"/" withString:@"_"];
350
+ NSString *imagePath = [self saveImageIntoCache:image withName:imageName];
351
+ completionHandler(imagePath);
352
+ } else {
353
+ @throw([NSException exceptionWithName:@"image not found" reason:@"image not found" userInfo:nil]);
354
+ }
355
+ }];
356
+ }
357
+
358
+ +(NSString*) saveImageIntoCache:(UIImage *)image withName:(NSString *)name {
359
+ NSData *imageData = UIImageJPEGRepresentation(image, 1);
360
+ NSString *path =[self generateCacheFilePath:@"jpg"];
361
+ [[NSFileManager defaultManager] createFileAtPath:path contents:imageData attributes:NULL];
362
+ return path;
363
+ }
364
+
365
+ /// for video
366
+
367
+ +(void)getAbsoluteVideoPath:(NSString *)videoPath completionHandler:(void (^)(NSString *absoluteImagePath))completionHandler
368
+ {
369
+
370
+ if (![videoPath containsString:@"ph://"]) {
371
+ completionHandler(videoPath);
372
+ return;
373
+ }
374
+ NSString *assetId =[videoPath stringByReplacingOccurrencesOfString:@"ph://"
375
+ withString:@""];
376
+ AVFileType outputFileType = AVFileTypeMPEG4;
377
+ NSString *pressetType = AVAssetExportPresetPassthrough;
378
+
379
+ // Throwing some errors to the user if he is not careful enough
380
+ if ([assetId isEqualToString:@""]) {
381
+ NSError *error = [NSError errorWithDomain:@"RNGalleryManager" code: -91 userInfo:nil];
382
+ @throw([NSException exceptionWithName:error reason:error userInfo:nil]);
383
+ return;
384
+ }
385
+
386
+ // Getting Video Asset
387
+ NSArray* localIds = [NSArray arrayWithObjects: assetId, nil];
388
+ PHAsset * _Nullable videoAsset = [PHAsset fetchAssetsWithLocalIdentifiers:localIds options:nil].firstObject;
389
+
390
+ // Getting information from the asset
391
+ NSString *mimeType = (NSString *)CFBridgingRelease(UTTypeCopyPreferredTagWithClass((__bridge CFStringRef _Nonnull)(outputFileType), kUTTagClassMIMEType));
392
+ CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType, (__bridge CFStringRef _Nonnull)(mimeType), NULL);
393
+ NSString *extension = (NSString *)CFBridgingRelease(UTTypeCopyPreferredTagWithClass(uti, kUTTagClassFilenameExtension));
394
+
395
+ // Creating output url and temp file name
396
+ NSString *path =[self generateCacheFilePath:extension];
397
+ NSURL *outputUrl = [NSURL URLWithString:[@"file://" stringByAppendingString:path]];
398
+
399
+ // Setting video export session options
400
+ PHVideoRequestOptions *videoRequestOptions = [[PHVideoRequestOptions alloc] init];
401
+ videoRequestOptions.networkAccessAllowed = YES;
402
+ videoRequestOptions.deliveryMode = PHVideoRequestOptionsDeliveryModeHighQualityFormat;
403
+
404
+ // Creating new export session
405
+ [[PHImageManager defaultManager] requestExportSessionForVideo:videoAsset options:videoRequestOptions exportPreset:pressetType resultHandler:^(AVAssetExportSession * _Nullable exportSession, NSDictionary * _Nullable info) {
406
+
407
+ exportSession.shouldOptimizeForNetworkUse = YES;
408
+ exportSession.outputFileType = outputFileType;
409
+ exportSession.outputURL = outputUrl;
410
+ // Converting the video and waiting to see whats going to happen
411
+ [exportSession exportAsynchronouslyWithCompletionHandler:^{
412
+ switch ([exportSession status])
413
+ {
414
+ case AVAssetExportSessionStatusFailed:
415
+ {
416
+ NSError* error = exportSession.error;
417
+ NSString *codeWithDomain = [NSString stringWithFormat:@"E%@%zd", error.domain.uppercaseString, error.code];
418
+ @throw([NSException exceptionWithName:error reason:error userInfo:nil]);
419
+ break;
420
+ }
421
+ case AVAssetExportSessionStatusCancelled:
422
+ {
423
+ NSError *error = [NSError errorWithDomain:@"RNGalleryManager" code: -91 userInfo:nil];
424
+ @throw([NSException exceptionWithName:error reason:error userInfo:nil]);
425
+ break;
426
+ }
427
+ case AVAssetExportSessionStatusCompleted:
428
+ {
429
+ completionHandler(outputUrl.absoluteString);
430
+ break;
431
+ }
432
+ default:
433
+ {
434
+ NSError *error = [NSError errorWithDomain:@"RNGalleryManager" code: -91 userInfo:nil];
435
+ @throw([NSException exceptionWithName:@"Unknown status" reason:@"Unknown status" userInfo:nil]);
436
+ break;
437
+ }
438
+ }
439
+ }];
440
+ }];
441
+ }
442
+
291
443
  @end