|
@@ -28,69 +28,83 @@ RCT_EXPORT_METHOD(takeSnapshot:(nonnull NSNumber *)target
|
28
|
28
|
resolve:(RCTPromiseResolveBlock)resolve
|
29
|
29
|
reject:(RCTPromiseRejectBlock)reject)
|
30
|
30
|
{
|
31
|
|
- [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
|
32
|
|
-
|
33
|
|
- // Get view
|
34
|
|
- UIView *view;
|
35
|
|
- view = viewRegistry[target];
|
36
|
|
- if (!view) {
|
37
|
|
- reject(RCTErrorUnspecified, [NSString stringWithFormat:@"No view found with reactTag: %@", target], nil);
|
38
|
|
- return;
|
39
|
|
- }
|
40
|
|
-
|
41
|
|
- // Get options
|
42
|
|
- CGSize size = [RCTConvert CGSize:options];
|
43
|
|
- NSString *format = [RCTConvert NSString:options[@"format"] ?: @"png"];
|
44
|
|
-
|
45
|
|
- // Capture image
|
46
|
|
- if (size.width < 0.1 || size.height < 0.1) {
|
47
|
|
- size = view.bounds.size;
|
48
|
|
- }
|
49
|
|
- UIGraphicsBeginImageContextWithOptions(size, NO, 0);
|
50
|
|
- BOOL success = [view drawViewHierarchyInRect:(CGRect){CGPointZero, size} afterScreenUpdates:YES];
|
51
|
|
- UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
52
|
|
- UIGraphicsEndImageContext();
|
53
|
|
-
|
54
|
|
- if (!success || !image) {
|
55
|
|
- reject(RCTErrorUnspecified, @"Failed to capture view snapshot.", nil);
|
56
|
|
- return;
|
|
31
|
+ [self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
|
|
32
|
+
|
|
33
|
+ // Get view
|
|
34
|
+ UIView *view;
|
|
35
|
+ view = viewRegistry[target];
|
|
36
|
+ if (!view) {
|
|
37
|
+ reject(RCTErrorUnspecified, [NSString stringWithFormat:@"No view found with reactTag: %@", target], nil);
|
|
38
|
+ return;
|
|
39
|
+ }
|
|
40
|
+
|
|
41
|
+ // Get options
|
|
42
|
+ CGSize size = [RCTConvert CGSize:options];
|
|
43
|
+ NSString *format = [RCTConvert NSString:options[@"format"] ?: @"png"];
|
|
44
|
+ NSString *result = [RCTConvert NSString:options[@"result"] ?: @"file"];
|
|
45
|
+
|
|
46
|
+ // Capture image
|
|
47
|
+ if (size.width < 0.1 || size.height < 0.1) {
|
|
48
|
+ size = view.bounds.size;
|
|
49
|
+ }
|
|
50
|
+ UIGraphicsBeginImageContextWithOptions(size, NO, 0);
|
|
51
|
+ BOOL success = [view drawViewHierarchyInRect:(CGRect){CGPointZero, size} afterScreenUpdates:YES];
|
|
52
|
+ UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
|
|
53
|
+ UIGraphicsEndImageContext();
|
|
54
|
+
|
|
55
|
+ if (!success || !image) {
|
|
56
|
+ reject(RCTErrorUnspecified, @"Failed to capture view snapshot", nil);
|
|
57
|
+ return;
|
|
58
|
+ }
|
|
59
|
+
|
|
60
|
+ // Convert image to data (on a background thread)
|
|
61
|
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
|
62
|
+
|
|
63
|
+ NSData *data;
|
|
64
|
+ if ([format isEqualToString:@"png"]) {
|
|
65
|
+ data = UIImagePNGRepresentation(image);
|
|
66
|
+ } else if ([format isEqualToString:@"jpeg"] || [format isEqualToString:@"jpg"]) {
|
|
67
|
+ CGFloat quality = [RCTConvert CGFloat:options[@"quality"] ?: @1];
|
|
68
|
+ data = UIImageJPEGRepresentation(image, quality);
|
|
69
|
+ } else {
|
|
70
|
+ reject(RCTErrorUnspecified, [NSString stringWithFormat:@"Unsupported image format: %@. Try one of: png | jpg | jpeg", format], nil);
|
|
71
|
+ return;
|
|
72
|
+ }
|
|
73
|
+
|
|
74
|
+ NSError *error = nil;
|
|
75
|
+ NSString *res = nil;
|
|
76
|
+ if ([result isEqualToString:@"file"]) {
|
|
77
|
+ // Save to a temp file
|
|
78
|
+ NSString *tempFilePath = RCTTempFilePath(format, &error);
|
|
79
|
+ if (tempFilePath) {
|
|
80
|
+ if ([data writeToFile:tempFilePath options:(NSDataWritingOptions)0 error:&error]) {
|
|
81
|
+ res = tempFilePath;
|
|
82
|
+ }
|
57
|
83
|
}
|
58
|
|
-
|
59
|
|
- // Convert image to data (on a background thread)
|
60
|
|
- dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
61
|
|
-
|
62
|
|
- NSData *data;
|
63
|
|
- if ([format isEqualToString:@"png"]) {
|
64
|
|
- data = UIImagePNGRepresentation(image);
|
65
|
|
- } else if ([format isEqualToString:@"jpeg"] || [format isEqualToString:@"jpg"]) {
|
66
|
|
- CGFloat quality = [RCTConvert CGFloat:options[@"quality"] ?: @1];
|
67
|
|
- data = UIImageJPEGRepresentation(image, quality);
|
68
|
|
- } else {
|
69
|
|
- reject(RCTErrorUnspecified, [NSString stringWithFormat:@"Unsupported image format: %@", format], nil);
|
70
|
|
- return;
|
71
|
|
- }
|
72
|
|
-
|
73
|
|
- NSError *error = nil;
|
74
|
|
- if ([[options objectForKey:@"base64"] boolValue]) {
|
75
|
|
- // Return as a base64'd string
|
76
|
|
- NSString *dataString = [data base64EncodedStringWithOptions:0];
|
77
|
|
- resolve(dataString);
|
78
|
|
- return;
|
79
|
|
- } else {
|
80
|
|
- // Save to a temp file
|
81
|
|
- NSString *tempFilePath = RCTTempFilePath(format, &error);
|
82
|
|
- if (tempFilePath) {
|
83
|
|
- if ([data writeToFile:tempFilePath options:(NSDataWritingOptions)0 error:&error]) {
|
84
|
|
- resolve(tempFilePath);
|
85
|
|
- return;
|
86
|
|
- }
|
87
|
|
- }
|
88
|
|
- }
|
89
|
|
-
|
90
|
|
- // If we reached here, something went wrong
|
91
|
|
- reject(RCTErrorUnspecified, error.localizedDescription, error);
|
92
|
|
- });
|
93
|
|
- }];
|
|
84
|
+ }
|
|
85
|
+ else if ([result isEqualToString:@"base64"]) {
|
|
86
|
+ // Return as a base64 raw string
|
|
87
|
+ res = [data base64EncodedStringWithOptions: NSDataBase64Encoding64CharacterLineLength];
|
|
88
|
+ }
|
|
89
|
+ else if ([result isEqualToString:@"data-uri"]) {
|
|
90
|
+ // Return as a base64 data uri string
|
|
91
|
+ NSString *base64 = [data base64EncodedStringWithOptions: NSDataBase64Encoding64CharacterLineLength];
|
|
92
|
+ res = [NSString stringWithFormat:@"data:image/%@;base64,%@", format, base64];
|
|
93
|
+ }
|
|
94
|
+ else {
|
|
95
|
+ reject(RCTErrorUnspecified, [NSString stringWithFormat:@"Unsupported result: %@. Try one of: file | base64 | data-uri", result], nil);
|
|
96
|
+ return;
|
|
97
|
+ }
|
|
98
|
+ if (res != nil) {
|
|
99
|
+ resolve(res);
|
|
100
|
+ return;
|
|
101
|
+ }
|
|
102
|
+
|
|
103
|
+ // If we reached here, something went wrong
|
|
104
|
+ if (error != nil) reject(RCTErrorUnspecified, error.localizedDescription, error);
|
|
105
|
+ else reject(RCTErrorUnspecified, @"viewshot unknown error", nil);
|
|
106
|
+ });
|
|
107
|
+ }];
|
94
|
108
|
}
|
95
|
109
|
|
96
|
110
|
|