Skip to content

Commit 05758c5

Browse files
authored
Merge branch 'master' into rn-win-0.47-fixes
2 parents d38493c + 7b95002 commit 05758c5

File tree

5 files changed

+320
-27
lines changed

5 files changed

+320
-27
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ For RN < 0.57 and/or Gradle < 3 you MUST install react-native-fs at version @2.1
99
For RN >= 0.57 and/or Gradle >= 3 you MUST install react-native-fs at version @2.12!
1010

1111
## Changes for v2.12
12+
- #601 [iOS] Another fix for copyAssetsVideoIOS
13+
- #599 [iOS] Fix for copyAssetsVideoIOS regarding iCloud-Files
1214
- #564 [Android] Upgrade to Gradle 3 (BREAKING compatiblity for < RN 0.57)
1315
- #571 [Android] Fix issue #566 android progress callback not sync and handle uppercase file extension mimetype
1416

RNFSManager.m

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -811,10 +811,18 @@ + (BOOL)requiresMainQueueSetup
811811
__block NSError *error = nil;
812812
PHFetchResult *phAssetFetchResult = [PHAsset fetchAssetsWithALAssetURLs:@[url] options:nil];
813813
PHAsset *phAsset = [phAssetFetchResult firstObject];
814+
PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc] init];
815+
options.networkAccessAllowed = YES;
816+
814817
dispatch_group_t group = dispatch_group_create();
815818
dispatch_group_enter(group);
819+
820+
PHVideoRequestOptions *options = [[PHVideoRequestOptions alloc]init];
821+
options.version = PHVideoRequestOptionsVersionOriginal;
822+
options.deliveryMode = PHVideoRequestOptionsDeliveryModeAutomatic;
823+
options.networkAccessAllowed = YES;
816824

817-
[[PHImageManager defaultManager] requestAVAssetForVideo:phAsset options:nil resultHandler:^(AVAsset *asset, AVAudioMix *audioMix, NSDictionary *info) {
825+
[[PHImageManager defaultManager] requestAVAssetForVideo:phAsset options:options resultHandler:^(AVAsset *asset, AVAudioMix *audioMix, NSDictionary *info) {
818826

819827
if ([asset isKindOfClass:[AVURLAsset class]]) {
820828
NSURL *url = [(AVURLAsset *)asset URL];

android/src/main/java/com/rnfs/RNFSManager.java

Lines changed: 49 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import android.content.res.AssetManager;
55
import android.database.Cursor;
66
import android.net.Uri;
7+
import android.os.AsyncTask;
78
import android.os.Environment;
89
import android.os.StatFs;
910
import android.provider.MediaStore;
@@ -316,46 +317,69 @@ public void hash(String filepath, String algorithm, Promise promise) {
316317
}
317318

318319
@ReactMethod
319-
public void moveFile(String filepath, String destPath, ReadableMap options, Promise promise) {
320+
public void moveFile(final String filepath, String destPath, ReadableMap options, final Promise promise) {
320321
try {
321-
File inFile = new File(filepath);
322+
final File inFile = new File(filepath);
322323

323324
if (!inFile.renameTo(new File(destPath))) {
324-
copyFile(filepath, destPath);
325-
326-
inFile.delete();
325+
new CopyFileTask() {
326+
@Override
327+
protected void onPostExecute (Exception ex) {
328+
if (ex == null) {
329+
inFile.delete();
330+
promise.resolve(true);
331+
} else {
332+
ex.printStackTrace();
333+
reject(promise, filepath, ex);
334+
}
335+
}
336+
}.execute(filepath, destPath);
337+
} else {
338+
promise.resolve(true);
327339
}
328-
329-
promise.resolve(true);
330340
} catch (Exception ex) {
331341
ex.printStackTrace();
332342
reject(promise, filepath, ex);
333343
}
334344
}
335345

336346
@ReactMethod
337-
public void copyFile(String filepath, String destPath, ReadableMap options, Promise promise) {
338-
try {
339-
copyFile(filepath, destPath);
340-
341-
promise.resolve(null);
342-
} catch (Exception ex) {
343-
ex.printStackTrace();
344-
reject(promise, filepath, ex);
345-
}
347+
public void copyFile(final String filepath, final String destPath, ReadableMap options, final Promise promise) {
348+
new CopyFileTask() {
349+
@Override
350+
protected void onPostExecute (Exception ex) {
351+
if (ex == null) {
352+
promise.resolve(null);
353+
} else {
354+
ex.printStackTrace();
355+
reject(promise, filepath, ex);
356+
}
357+
}
358+
}.execute(filepath, destPath);
346359
}
347360

348-
private void copyFile(String filepath, String destPath) throws IOException, IORejectionException {
349-
InputStream in = getInputStream(filepath);
350-
OutputStream out = getOutputStream(destPath, false);
361+
private class CopyFileTask extends AsyncTask<String, Void, Exception> {
362+
protected Exception doInBackground(String... paths) {
363+
try {
364+
String filepath = paths[0];
365+
String destPath = paths[1];
366+
367+
InputStream in = getInputStream(filepath);
368+
OutputStream out = getOutputStream(destPath, false);
351369

352-
byte[] buffer = new byte[1024];
353-
int length;
354-
while ((length = in.read(buffer)) > 0) {
355-
out.write(buffer, 0, length);
370+
byte[] buffer = new byte[1024];
371+
int length;
372+
while ((length = in.read(buffer)) > 0) {
373+
out.write(buffer, 0, length);
374+
Thread.yield();
375+
}
376+
in.close();
377+
out.close();
378+
return null;
379+
} catch (Exception ex) {
380+
return ex;
381+
}
356382
}
357-
in.close();
358-
out.close();
359383
}
360384

361385
@ReactMethod

index.d.ts

Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
type MkdirOptions = {
2+
NSURLIsExcludedFromBackupKey?: boolean // iOS only
3+
NSFileProtectionKey?: string // IOS only
4+
}
5+
6+
type FileOptions = {
7+
NSFileProtectionKey?: string // IOS only
8+
}
9+
10+
type ReadDirItem = {
11+
ctime: Date | undefined // The creation date of the file (iOS only)
12+
mtime: Date | undefined // The last modified date of the file
13+
name: string // The name of the item
14+
path: string // The absolute path to the item
15+
size: string // Size in bytes
16+
isFile: () => boolean // Is the file just a file?
17+
isDirectory: () => boolean // Is the file a directory?
18+
}
19+
20+
type StatResult = {
21+
name: string | undefined // The name of the item TODO: why is this not documented?
22+
path: string // The absolute path to the item
23+
size: string // Size in bytes
24+
mode: number // UNIX file mode
25+
ctime: number // Created date
26+
mtime: number // Last modified date
27+
originalFilepath: string // In case of content uri this is the pointed file path, otherwise is the same as path
28+
isFile: () => boolean // Is the file just a file?
29+
isDirectory: () => boolean // Is the file a directory?
30+
}
31+
32+
type Headers = { [name: string]: string }
33+
type Fields = { [name: string]: string }
34+
35+
type DownloadFileOptions = {
36+
fromUrl: string // URL to download file from
37+
toFile: string // Local filesystem path to save the file to
38+
headers?: Headers // An object of headers to be passed to the server
39+
background?: boolean // Continue the download in the background after the app terminates (iOS only)
40+
discretionary?: boolean // Allow the OS to control the timing and speed of the download to improve perceived performance (iOS only)
41+
cacheable?: boolean // Whether the download can be stored in the shared NSURLCache (iOS only)
42+
progressDivider?: number
43+
begin?: (res: DownloadBeginCallbackResult) => void
44+
progress?: (res: DownloadProgressCallbackResult) => void
45+
resumable?: () => void // only supported on iOS yet
46+
connectionTimeout?: number // only supported on Android yet
47+
readTimeout?: number // supported on Android and iOS
48+
}
49+
50+
type DownloadBeginCallbackResult = {
51+
jobId: number // The download job ID, required if one wishes to cancel the download. See `stopDownload`.
52+
statusCode: number // The HTTP status code
53+
contentLength: number // The total size in bytes of the download resource
54+
headers: Headers // The HTTP response headers from the server
55+
}
56+
57+
type DownloadProgressCallbackResult = {
58+
jobId: number // The download job ID, required if one wishes to cancel the download. See `stopDownload`.
59+
contentLength: number // The total size in bytes of the download resource
60+
bytesWritten: number // The number of bytes written to the file so far
61+
}
62+
63+
type DownloadResult = {
64+
jobId: number // The download job ID, required if one wishes to cancel the download. See `stopDownload`.
65+
statusCode: number // The HTTP status code
66+
bytesWritten: number // The number of bytes written to the file
67+
}
68+
69+
type UploadFileOptions = {
70+
toUrl: string // URL to upload file to
71+
files: UploadFileItem[] // An array of objects with the file information to be uploaded.
72+
headers?: Headers // An object of headers to be passed to the server
73+
fields?: Fields // An object of fields to be passed to the server
74+
method?: string // Default is 'POST', supports 'POST' and 'PUT'
75+
beginCallback?: (res: UploadBeginCallbackResult) => void // deprecated
76+
progressCallback?: (res: UploadProgressCallbackResult) => void // deprecated
77+
begin?: (res: UploadBeginCallbackResult) => void
78+
progress?: (res: UploadProgressCallbackResult) => void
79+
}
80+
81+
type UploadFileItem = {
82+
name: string // Name of the file, if not defined then filename is used
83+
filename: string // Name of file
84+
filepath: string // Path to file
85+
filetype: string // The mimetype of the file to be uploaded, if not defined it will get mimetype from `filepath` extension
86+
}
87+
88+
type UploadBeginCallbackResult = {
89+
jobId: number // The upload job ID, required if one wishes to cancel the upload. See `stopUpload`.
90+
}
91+
92+
type UploadProgressCallbackResult = {
93+
jobId: number // The upload job ID, required if one wishes to cancel the upload. See `stopUpload`.
94+
totalBytesExpectedToSend: number // The total number of bytes that will be sent to the server
95+
totalBytesSent: number // The number of bytes sent to the server
96+
}
97+
98+
type UploadResult = {
99+
jobId: number // The upload job ID, required if one wishes to cancel the upload. See `stopUpload`.
100+
statusCode: number // The HTTP status code
101+
headers: Headers // The HTTP response headers from the server
102+
body: string // The HTTP response body
103+
}
104+
105+
type FSInfoResult = {
106+
totalSpace: number // The total amount of storage space on the device (in bytes).
107+
freeSpace: number // The amount of available storage space on the device (in bytes).
108+
}
109+
110+
export function mkdir(filepath: string, options?: MkdirOptions): Promise<void>
111+
export function moveFile(
112+
filepath: string,
113+
destPath: string,
114+
options?: FileOptions
115+
): Promise<void>
116+
export function copyFile(
117+
filepath: string,
118+
destPath: string,
119+
options?: FileOptions
120+
): Promise<void>
121+
export function pathForBundle(bundleNamed: string): Promise<string>
122+
export function pathForGroup(groupName: string): Promise<string>
123+
export function getFSInfo(): Promise<FSInfoResult>
124+
export function getAllExternalFilesDirs(): Promise<string>
125+
export function unlink(filepath: string): Promise<void>
126+
export function exists(filepath: string): Promise<boolean>
127+
128+
export function stopDownload(jobId: number): void
129+
130+
export function resumeDownload(jobId: number): void
131+
132+
export function isResumable(jobId: number): Promise<boolean>
133+
134+
export function stopUpload(jobId: number): void
135+
136+
export function completeHandlerIOS(jobId: number): void
137+
138+
export function readDir(dirpath: string): Promise<ReadDirItem[]>
139+
140+
/**
141+
* Android-only
142+
*/
143+
export function readDirAssets(dirpath: string): Promise<ReadDirItem[]>
144+
145+
/**
146+
* Android-only
147+
*/
148+
export function existsAssets(filepath: string): Promise<boolean>
149+
150+
/**
151+
* Node style version (lowercase d). Returns just the names
152+
*/
153+
export function readdir(dirpath: string): Promise<string[]>
154+
155+
/**
156+
* Android-only
157+
*/
158+
export function setReadable(
159+
filepath: string,
160+
readable: boolean,
161+
ownerOnly: boolean
162+
): Promise<boolean>
163+
164+
export function stat(filepath: string): Promise<StatResult>
165+
166+
export function readFile(
167+
filepath: string,
168+
encodingOrOptions?: any
169+
): Promise<string>
170+
export function read(
171+
filepath: string,
172+
length?: number,
173+
position?: number,
174+
encodingOrOptions?: any
175+
): Promise<string>
176+
177+
/**
178+
* Android only
179+
*/
180+
export function readFileAssets(
181+
filepath: string,
182+
encodingOrOptions?: any
183+
): Promise<string>
184+
185+
export function hash(filepath: string, algorithm: string): Promise<string>
186+
187+
/**
188+
* Android only
189+
*/
190+
export function copyFileAssets(
191+
filepath: string,
192+
destPath: string
193+
): Promise<void>
194+
195+
/**
196+
* iOS only
197+
* Copies fotos from asset-library (camera-roll) to a specific location
198+
* with a given width or height
199+
* @see: https://developer.apple.com/reference/photos/phimagemanager/1616964-requestimageforasset
200+
*/
201+
export function copyAssetsFileIOS(
202+
imageUri: string,
203+
destPath: string,
204+
width: number,
205+
height: number,
206+
scale?: number,
207+
compression?: number,
208+
resizeMode?: string
209+
): Promise<string>
210+
211+
/**
212+
* iOS only
213+
* Copies fotos from asset-library (camera-roll) to a specific location
214+
* with a given width or height
215+
* @see: https://developer.apple.com/reference/photos/phimagemanager/1616964-requestimageforasset
216+
*/
217+
export function copyAssetsVideoIOS(
218+
imageUri: string,
219+
destPath: string
220+
): Promise<string>
221+
222+
export function writeFile(
223+
filepath: string,
224+
contents: string,
225+
encodingOrOptions?: any
226+
): Promise<void>
227+
228+
export function write(
229+
filepath: string,
230+
contents: string,
231+
position?: number,
232+
encodingOrOptions?: any
233+
): Promise<void>
234+
235+
export function downloadFile(
236+
options: DownloadFileOptions
237+
): { jobId: number; promise: Promise<DownloadResult> }
238+
239+
export function uploadFiles(
240+
options: UploadFileOptions
241+
): { jobId: number; promise: Promise<UploadResult> }
242+
243+
export function touch(
244+
filepath: string,
245+
mtime?: Date,
246+
ctime?: Date
247+
): Promise<void>
248+
249+
export const MainBundlePath: string
250+
export const CachesDirectoryPath: string
251+
export const ExternalCachesDirectoryPath: string
252+
export const DocumentDirectoryPath: string
253+
export const ExternalDirectoryPath: string
254+
export const ExternalStorageDirectoryPath: string
255+
export const TemporaryDirectoryPath: string
256+
export const LibraryDirectoryPath: string
257+
export const PicturesDirectoryPath: string
258+
export const FileProtectionKeys: string

0 commit comments

Comments
 (0)