Skip to content

Commit 63d2819

Browse files
committed
deprecate "path", replace "file" by "tmpfile"
ctx #67
1 parent 0c77779 commit 63d2819

File tree

5 files changed

+45
-44
lines changed

5 files changed

+45
-44
lines changed

README.md

Lines changed: 10 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -34,38 +34,24 @@ Returns a Promise of the image URI.
3434

3535
- **`view`** is a reference to a React Native component.
3636
- **`options`** may include:
37-
- **`width`** / **`height`** *(number)*: the width and height of the final image (resized from the View bound. don't provide it if you want the original pixel size).
38-
- **`format`** *(string)*: either `png` or `jpg`/`jpeg` or `webm` (Android). Defaults to `png`.
39-
- **`quality`** *(number)*: the quality. 0.0 - 1.0 (default). (only available on lossy formats like jpeg)
40-
- **`result`** *(string)*, the method you want to use to save the snapshot, one of:
37+
- **`width`** / **`height`** *(number)*: the width and height of the final image (resized from the View bound. don't provide it if you want the original pixel size).
38+
- **`format`** *(string)*: either `png` or `jpg`/`jpeg` or `webm` (Android). Defaults to `png`.
39+
- **`quality`** *(number)*: the quality. 0.0 - 1.0 (default). (only available on lossy formats like jpeg)
40+
- **`result`** *(string)*, the method you want to use to save the snapshot, one of:
4141
- `"file"` (default): save to a temporary file *(that will only exist for as long as the app is running)*.
4242
- `"base64"`: encode as base64 and returns the raw string. Use only with small images as this may result of lags (the string is sent over the bridge). *N.B. This is not a data uri, use `data-uri` instead*.
4343
- `"data-uri"`: same as `base64` but also includes the [Data URI scheme](https://en.wikipedia.org/wiki/Data_URI_scheme) header.
44-
- **`path`** *(string)*: The absolute path where the file get generated. **Read below before using it!**
4544
- **`snapshotContentContainer`** *(bool)*: if true and when view is a ScrollView, the "content container" height will be evaluated instead of the container height.
4645

47-
### `path` option and `dirs` constants
46+
### DEPRECATED `path` option and `dirs` constants
4847

49-
**IMPORTANT: We might actually drop the path feature because of its complexity in the current codebase (and bugs that are not fixed), please consider using react-native-view-shot with https://github.com/itinance/react-native-fs to solve this.**
48+
> A feature used to allow to set an arbitrary file path. This has become tricky to maintain because all the edge cases and use-cases of file management so we have decided to drop it, making this library focusing more on solving snapshotting and not file system.
5049
51-
By default, takeSnapshot will export in a temporary folder and the snapshot file will be deleted as soon as the app leaves.
52-
But if you use the `path` option, you make the snapshot file more permanent and at a specific file location. it is up to you to manage the image file lifecycle, the library won't clean it for you (which might result of leaking files on user's phone if you are not careful). There is also no guarantee the file will be successfully saved: you can reach permissions problem, this also is platform specific.
50+
To migrate from this old feature, you have a few solutions:
5351

54-
If you still want to do this, we expose a few somewhat universal "constants" to ease the work.
55-
56-
```js
57-
import { takeSnapshot, dirs } from "react-native-view-shot";
58-
// cross platform dirs:
59-
const { CacheDir, DocumentDir, MainBundleDir, MovieDir, MusicDir, PictureDir } = dirs;
60-
// only available Android:
61-
const { DCIMDir, DownloadDir, RingtoneDir, SDCardDir } = dirs;
62-
63-
takeSnapshot(viewRef, { path: PictureDir+"/foo.png" })
64-
.then(
65-
uri => console.log("Image saved to", uri),
66-
error => console.error("Oops, snapshot failed", error)
67-
);
68-
```
52+
- If you want to save the snapshotted image result to the CameraRoll, just use https://facebook.github.io/react-native/docs/cameraroll.html#savetocameraroll
53+
- If you want to save it to an arbitrary file path, use something like https://github.com/itinance/react-native-fs
54+
- For any more advanced needs, you can write your own (or find another) native module that would solve your use-case.
6955

7056
## Interoperability Table
7157

android/src/main/java/fr/greweb/reactnativeviewshot/RNViewShotModule.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public void takeSnapshot(int tag, ReadableMap options, Promise promise) {
7171
DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
7272
Integer width = options.hasKey("width") ? (int)(displayMetrics.density * options.getDouble("width")) : null;
7373
Integer height = options.hasKey("height") ? (int)(displayMetrics.density * options.getDouble("height")) : null;
74-
String result = options.hasKey("result") ? options.getString("result") : "file";
74+
String result = options.hasKey("result") ? options.getString("result") : "tmpfile";
7575
Boolean snapshotContentContainer = options.hasKey("snapshotContentContainer") ? options.getBoolean("snapshotContentContainer") : false;
7676
try {
7777
File file = null;
@@ -85,6 +85,9 @@ public void takeSnapshot(int tag, ReadableMap options, Promise promise) {
8585
file = createTempFile(getReactApplicationContext(), format);
8686
}
8787
}
88+
else if ("tmpfile".equals(result)) {
89+
file = createTempFile(getReactApplicationContext(), format);
90+
}
8891
UIManagerModule uiManager = this.reactContext.getNativeModule(UIManagerModule.class);
8992
uiManager.addUIBlock(new ViewShot(tag, format, compressFormat, quality, width, height, file, result, snapshotContentContainer,reactContext, promise));
9093
}

android/src/main/java/fr/greweb/reactnativeviewshot/ViewShot.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public void execute(NativeViewHierarchyManager nativeViewHierarchyManager) {
7979
return;
8080
}
8181
try {
82-
if ("file".equals(result)) {
82+
if ("file".equals(result) || "tmpfile".equals(result)) {
8383
os = new FileOutputStream(output);
8484
captureView(view, os);
8585
String uri = Uri.fromFile(output).toString();

index.js

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export const dirs = {
1414
DCIMDir: RNViewShot.DCIMDir,
1515
DownloadDir: RNViewShot.DownloadDir,
1616
RingtoneDir: RNViewShot.RingtoneDir,
17-
SDCardDir: RNViewShot.SDCardDir,
17+
SDCardDir: RNViewShot.SDCardDir
1818
};
1919

2020
export function takeSnapshot(
@@ -25,13 +25,25 @@ export function takeSnapshot(
2525
path?: string,
2626
format?: "png" | "jpg" | "jpeg" | "webm",
2727
quality?: number,
28-
result?: "file" | "base64" | "data-uri",
29-
snapshotContentContainer?: bool
28+
result?: "tmpfile" | "file" | "base64" | "data-uri",
29+
snapshotContentContainer?: boolean
3030
} = {}
3131
): Promise<string> {
32+
if (options.result === "file") {
33+
console.warn(
34+
"react-native-view-shot: result='file' is deprecated, has been renamed to 'tmpfile' and no longer support any 'path' option. See README for more information"
35+
);
36+
} else if ("path" in options) {
37+
console.warn(
38+
"react-native-view-shot: path option is deprecated. See README for more information"
39+
);
40+
}
3241
if (typeof view !== "number") {
3342
const node = findNodeHandle(view);
34-
if (!node) return Promise.reject(new Error("findNodeHandle failed to resolve view="+String(view)));
43+
if (!node)
44+
return Promise.reject(
45+
new Error("findNodeHandle failed to resolve view=" + String(view))
46+
);
3547
view = node;
3648
}
3749
return RNViewShot.takeSnapshot(view, options);

ios/RNViewShot.m

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -42,24 +42,24 @@ - (NSDictionary *)constantsToExport
4242
reject:(RCTPromiseRejectBlock)reject)
4343
{
4444
[self.bridge.uiManager addUIBlock:^(__unused RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
45-
45+
4646
// Get view
4747
UIView *view;
4848
view = viewRegistry[target];
4949
if (!view) {
5050
reject(RCTErrorUnspecified, [NSString stringWithFormat:@"No view found with reactTag: %@", target], nil);
5151
return;
5252
}
53-
53+
5454
// Get options
5555
CGSize size = [RCTConvert CGSize:options];
5656
NSString *format = [RCTConvert NSString:options[@"format"] ?: @"png"];
57-
NSString *result = [RCTConvert NSString:options[@"result"] ?: @"file"];
57+
NSString *result = [RCTConvert NSString:options[@"result"] ?: @"tmpfile"];
5858
BOOL snapshotContentContainer = [RCTConvert BOOL:options[@"snapshotContentContainer"] ?: @"false"];
5959

6060
// Capture image
6161
BOOL success;
62-
62+
6363
UIView* rendered;
6464
UIScrollView* scrollView;
6565
if (snapshotContentContainer) {
@@ -74,15 +74,15 @@ - (NSDictionary *)constantsToExport
7474
else {
7575
rendered = view;
7676
}
77-
77+
7878
if (size.width < 0.1 || size.height < 0.1) {
7979
size = snapshotContentContainer ? scrollView.contentSize : view.bounds.size;
8080
}
8181
if (size.width < 0.1 || size.height < 0.1) {
8282
reject(RCTErrorUnspecified, [NSString stringWithFormat:@"The content size must not be zero or negative. Got: (%g, %g)", size.width, size.height], nil);
8383
return;
8484
}
85-
85+
8686
CGPoint savedContentOffset;
8787
CGRect savedFrame;
8888
if (snapshotContentContainer) {
@@ -96,13 +96,13 @@ - (NSDictionary *)constantsToExport
9696
success = [rendered drawViewHierarchyInRect:(CGRect){CGPointZero, size} afterScreenUpdates:YES];
9797
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
9898
UIGraphicsEndImageContext();
99-
99+
100100
if (snapshotContentContainer) {
101101
// Restore scroll & frame
102102
scrollView.contentOffset = savedContentOffset;
103103
scrollView.frame = savedFrame;
104104
}
105-
105+
106106
if (!success) {
107107
reject(RCTErrorUnspecified, @"The view cannot be captured. drawViewHierarchyInRect was not successful. This is a potential technical or security limitation.", nil);
108108
return;
@@ -112,10 +112,10 @@ - (NSDictionary *)constantsToExport
112112
reject(RCTErrorUnspecified, @"Failed to capture view snapshot. UIGraphicsGetImageFromCurrentImageContext() returned nil!", nil);
113113
return;
114114
}
115-
115+
116116
// Convert image to data (on a background thread)
117117
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
118-
118+
119119
NSData *data;
120120
if ([format isEqualToString:@"png"]) {
121121
data = UIImagePNGRepresentation(image);
@@ -126,13 +126,13 @@ - (NSDictionary *)constantsToExport
126126
reject(RCTErrorUnspecified, [NSString stringWithFormat:@"Unsupported image format: %@. Try one of: png | jpg | jpeg", format], nil);
127127
return;
128128
}
129-
129+
130130
NSError *error = nil;
131131
NSString *res = nil;
132-
if ([result isEqualToString:@"file"]) {
132+
if ([result isEqualToString:@"file"] || [result isEqualToString:@"tmpfile"] ) {
133133
// Save to a temp file
134134
NSString *path;
135-
if (options[@"path"]) {
135+
if (options[@"path"] && [result isEqualToString:@"file"]) {
136136
path = options[@"path"];
137137
NSString * folder = [path stringByDeletingLastPathComponent];
138138
NSFileManager * fm = [NSFileManager defaultManager];
@@ -167,7 +167,7 @@ - (NSDictionary *)constantsToExport
167167
resolve(res);
168168
return;
169169
}
170-
170+
171171
// If we reached here, something went wrong
172172
if (error) reject(RCTErrorUnspecified, error.localizedDescription, error);
173173
else reject(RCTErrorUnspecified, @"viewshot unknown error", nil);

0 commit comments

Comments
 (0)