@onekeyfe/react-native-cloud-fs 2.6.0
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/.github/workflows/package-publish.yml +19 -0
- package/README.md +146 -0
- package/android/build.gradle +55 -0
- package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +6 -0
- package/android/gradle.properties +16 -0
- package/android/gradlew +160 -0
- package/android/gradlew.bat +90 -0
- package/android/src/main/AndroidManifest.xml +6 -0
- package/android/src/main/java/org/rncloudfs/DriveServiceHelper.java +214 -0
- package/android/src/main/java/org/rncloudfs/RNCloudFsModule.java +508 -0
- package/android/src/main/java/org/rncloudfs/RNCloudFsPackage.java +28 -0
- package/docs/getting-started.md +61 -0
- package/docs/todo.md +34 -0
- package/docs/xcode.png +0 -0
- package/index.js +7 -0
- package/ios/RNCloudFs.h +10 -0
- package/ios/RNCloudFs.m +467 -0
- package/ios/RNCloudFs.xcodeproj/project.pbxproj +252 -0
- package/ios/RNCloudFs.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- package/licesnse.txt +21 -0
- package/package.json +14 -0
- package/react-native-cloud-fs.podspec +17 -0
package/ios/RNCloudFs.m
ADDED
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
|
|
2
|
+
#import "RNCloudFs.h"
|
|
3
|
+
#import <UIKit/UIKit.h>
|
|
4
|
+
#if __has_include(<React/RCTBridgeModule.h>)
|
|
5
|
+
#import <React/RCTBridgeModule.h>
|
|
6
|
+
#else
|
|
7
|
+
#import "RCTBridgeModule.h"
|
|
8
|
+
#endif
|
|
9
|
+
#import "RCTEventDispatcher.h"
|
|
10
|
+
#import "RCTUtils.h"
|
|
11
|
+
#import <AssetsLibrary/AssetsLibrary.h>
|
|
12
|
+
#import "RCTLog.h"
|
|
13
|
+
|
|
14
|
+
@implementation RNCloudFs
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
- (dispatch_queue_t)methodQueue
|
|
19
|
+
{
|
|
20
|
+
return dispatch_queue_create("RNCloudFs.queue", DISPATCH_QUEUE_SERIAL);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
RCT_EXPORT_MODULE()
|
|
24
|
+
|
|
25
|
+
//see https://developer.apple.com/library/content/documentation/General/Conceptual/iCloudDesignGuide/Chapters/iCloudFundametals.html
|
|
26
|
+
|
|
27
|
+
RCT_EXPORT_METHOD(isAvailable:(RCTPromiseResolveBlock)resolve
|
|
28
|
+
rejecter:(RCTPromiseRejectBlock)reject) {
|
|
29
|
+
|
|
30
|
+
NSURL *ubiquityURL = [self icloudDirectory];
|
|
31
|
+
if(ubiquityURL != nil){
|
|
32
|
+
return resolve(@YES);
|
|
33
|
+
}
|
|
34
|
+
return resolve(@NO);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
RCT_EXPORT_METHOD(createFile:(NSDictionary *) options
|
|
38
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
39
|
+
rejecter:(RCTPromiseRejectBlock)reject) {
|
|
40
|
+
|
|
41
|
+
NSString *destinationPath = [options objectForKey:@"targetPath"];
|
|
42
|
+
NSString *content = [options objectForKey:@"content"];
|
|
43
|
+
NSString *scope = [options objectForKey:@"scope"];
|
|
44
|
+
bool documentsFolder = !scope || [scope caseInsensitiveCompare:@"visible"] == NSOrderedSame;
|
|
45
|
+
|
|
46
|
+
NSString *tempFile = [NSTemporaryDirectory() stringByAppendingPathComponent:[[NSUUID UUID] UUIDString]];
|
|
47
|
+
|
|
48
|
+
NSError *error;
|
|
49
|
+
[content writeToFile:tempFile atomically:YES encoding:NSUTF8StringEncoding error:&error];
|
|
50
|
+
if(error) {
|
|
51
|
+
return reject(@"error", error.description, nil);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
[self moveToICloudDirectory:documentsFolder :tempFile :destinationPath :resolve :reject];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
RCT_EXPORT_METHOD(fileExists:(NSDictionary *)options
|
|
58
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
59
|
+
rejecter:(RCTPromiseRejectBlock)reject) {
|
|
60
|
+
|
|
61
|
+
NSString *destinationPath = [options objectForKey:@"targetPath"];
|
|
62
|
+
NSString *scope = [options objectForKey:@"scope"];
|
|
63
|
+
bool documentsFolder = !scope || [scope caseInsensitiveCompare:@"visible"] == NSOrderedSame;
|
|
64
|
+
|
|
65
|
+
NSFileManager* fileManager = [NSFileManager defaultManager];
|
|
66
|
+
|
|
67
|
+
NSURL *ubiquityURL = documentsFolder ? [self icloudDocumentsDirectory] : [self icloudDirectory];
|
|
68
|
+
|
|
69
|
+
if (ubiquityURL) {
|
|
70
|
+
NSURL* dir = [ubiquityURL URLByAppendingPathComponent:destinationPath];
|
|
71
|
+
NSString* dirPath = [dir.path stringByStandardizingPath];
|
|
72
|
+
|
|
73
|
+
bool exists = [fileManager fileExistsAtPath:dirPath];
|
|
74
|
+
|
|
75
|
+
return resolve(@(exists));
|
|
76
|
+
} else {
|
|
77
|
+
RCTLogTrace(@"Could not retrieve a ubiquityURL");
|
|
78
|
+
return reject(@"error", [NSString stringWithFormat:@"could access iCloud drive '%@'", destinationPath], nil);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
RCT_EXPORT_METHOD(listFiles:(NSDictionary *)options
|
|
83
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
84
|
+
rejecter:(RCTPromiseRejectBlock)reject) {
|
|
85
|
+
|
|
86
|
+
NSString *destinationPath = [options objectForKey:@"targetPath"];
|
|
87
|
+
NSString *scope = [options objectForKey:@"scope"];
|
|
88
|
+
bool documentsFolder = !scope || [scope caseInsensitiveCompare:@"visible"] == NSOrderedSame;
|
|
89
|
+
|
|
90
|
+
NSFileManager* fileManager = [NSFileManager defaultManager];
|
|
91
|
+
|
|
92
|
+
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
|
|
93
|
+
[dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ssZZZ"];
|
|
94
|
+
|
|
95
|
+
NSURL *ubiquityURL = documentsFolder ? [self icloudDocumentsDirectory] : [self icloudDirectory];
|
|
96
|
+
|
|
97
|
+
if (ubiquityURL) {
|
|
98
|
+
NSURL* target = [ubiquityURL URLByAppendingPathComponent:destinationPath];
|
|
99
|
+
|
|
100
|
+
NSMutableArray<NSDictionary *> *fileData = [NSMutableArray new];
|
|
101
|
+
|
|
102
|
+
NSError *error = nil;
|
|
103
|
+
|
|
104
|
+
BOOL isDirectory;
|
|
105
|
+
[fileManager fileExistsAtPath:[target path] isDirectory:&isDirectory];
|
|
106
|
+
|
|
107
|
+
NSURL *dirPath;
|
|
108
|
+
NSArray *contents;
|
|
109
|
+
if(isDirectory) {
|
|
110
|
+
contents = [fileManager contentsOfDirectoryAtPath:[target path] error:&error];
|
|
111
|
+
dirPath = target;
|
|
112
|
+
} else {
|
|
113
|
+
contents = @[[target lastPathComponent]];
|
|
114
|
+
dirPath = [target URLByDeletingLastPathComponent];
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if(error) {
|
|
118
|
+
return reject(@"error", error.description, nil);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
[contents enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop) {
|
|
122
|
+
NSURL *fileUrl = [dirPath URLByAppendingPathComponent:object];
|
|
123
|
+
|
|
124
|
+
NSError *error;
|
|
125
|
+
NSDictionary *attributes = [fileManager attributesOfItemAtPath:[fileUrl path] error:&error];
|
|
126
|
+
if(error) {
|
|
127
|
+
RCTLogTrace(@"problem getting attributes for %@", [fileUrl path]);
|
|
128
|
+
//skip this one
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
NSFileAttributeType type = [attributes objectForKey:NSFileType];
|
|
133
|
+
|
|
134
|
+
bool isDir = type == NSFileTypeDirectory;
|
|
135
|
+
bool isFile = type == NSFileTypeRegular;
|
|
136
|
+
|
|
137
|
+
if(!isDir && !isFile)
|
|
138
|
+
return;
|
|
139
|
+
|
|
140
|
+
NSDate* modDate = [attributes objectForKey:NSFileModificationDate];
|
|
141
|
+
|
|
142
|
+
NSURL *shareUrl = [fileManager URLForPublishingUbiquitousItemAtURL:fileUrl expirationDate:nil error:&error];
|
|
143
|
+
|
|
144
|
+
[fileData addObject:@{
|
|
145
|
+
@"name": object,
|
|
146
|
+
@"path": [fileUrl path],
|
|
147
|
+
@"uri": shareUrl ? [shareUrl absoluteString] : [NSNull null],
|
|
148
|
+
@"size": [attributes objectForKey:NSFileSize],
|
|
149
|
+
@"lastModified": [dateFormatter stringFromDate:modDate],
|
|
150
|
+
@"isDirectory": @(isDir),
|
|
151
|
+
@"isFile": @(isFile)
|
|
152
|
+
}];
|
|
153
|
+
}];
|
|
154
|
+
|
|
155
|
+
if (error) {
|
|
156
|
+
return reject(@"error", [NSString stringWithFormat:@"could not copy to iCloud drive '%@'", destinationPath], error);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
NSString *relativePath = [[dirPath path] stringByReplacingOccurrencesOfString:[ubiquityURL path] withString:@"."];
|
|
160
|
+
|
|
161
|
+
return resolve(@{
|
|
162
|
+
@"files": fileData,
|
|
163
|
+
@"path": relativePath
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
} else {
|
|
167
|
+
NSLog(@"Could not retrieve a ubiquityURL");
|
|
168
|
+
return reject(@"error", [NSString stringWithFormat:@"could not copy to iCloud drive '%@'", destinationPath], nil);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
RCT_EXPORT_METHOD(getIcloudDocument:(NSString *)filename
|
|
174
|
+
resolver:(RCTPromiseResolveBlock)resolver
|
|
175
|
+
rejecter:(RCTPromiseRejectBlock)rejecter) {
|
|
176
|
+
__block bool resolved = NO;
|
|
177
|
+
_query = [[NSMetadataQuery alloc] init];
|
|
178
|
+
|
|
179
|
+
[_query setSearchScopes:@[NSMetadataQueryUbiquitousDocumentsScope, NSMetadataQueryUbiquitousDataScope]];
|
|
180
|
+
|
|
181
|
+
NSPredicate *pred = [NSPredicate predicateWithFormat: @"%K == %@", NSMetadataItemFSNameKey, filename];
|
|
182
|
+
[_query setPredicate:pred];
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
[[NSNotificationCenter defaultCenter] addObserverForName:
|
|
186
|
+
NSMetadataQueryDidFinishGatheringNotification
|
|
187
|
+
object:_query queue:[NSOperationQueue currentQueue]
|
|
188
|
+
usingBlock:^(NSNotification __strong *notification)
|
|
189
|
+
{
|
|
190
|
+
NSMetadataQuery *query = [notification object];
|
|
191
|
+
[query disableUpdates];
|
|
192
|
+
[query stopQuery];
|
|
193
|
+
for (NSMetadataItem *item in query.results) {
|
|
194
|
+
if([[item valueForAttribute:NSMetadataItemFSNameKey] isEqualToString:filename]){
|
|
195
|
+
resolved = YES;
|
|
196
|
+
NSURL *url = [item valueForAttribute:NSMetadataItemURLKey];
|
|
197
|
+
bool fileIsReady = [self downloadFileIfNotAvailable: item];
|
|
198
|
+
if(fileIsReady){
|
|
199
|
+
NSData *data = [NSData dataWithContentsOfURL: url];
|
|
200
|
+
NSString *content = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
|
201
|
+
return resolver(content);
|
|
202
|
+
} else {
|
|
203
|
+
// Call itself until the file it's ready
|
|
204
|
+
[self getIcloudDocument:filename resolver:resolver rejecter:rejecter];
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if(!resolved){
|
|
209
|
+
return rejecter(@"error", [NSString stringWithFormat:@"item not found '%@'", filename], nil);
|
|
210
|
+
}
|
|
211
|
+
}];
|
|
212
|
+
|
|
213
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
214
|
+
[self->_query startQuery];
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
RCT_EXPORT_METHOD(deleteFromCloud:(NSDictionary *)item
|
|
220
|
+
resolver:(RCTPromiseResolveBlock)resolver
|
|
221
|
+
rejecter:(RCTPromiseRejectBlock)rejecter) {
|
|
222
|
+
NSError *error;
|
|
223
|
+
|
|
224
|
+
NSFileManager* fileManager = [NSFileManager defaultManager];
|
|
225
|
+
[fileManager removeItemAtPath:item[@"path"] error:&error];
|
|
226
|
+
if(error) {
|
|
227
|
+
return rejecter(@"error", error.description, nil);
|
|
228
|
+
}
|
|
229
|
+
bool result = YES;
|
|
230
|
+
return resolver(@(result));
|
|
231
|
+
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
RCT_EXPORT_METHOD(copyToCloud:(NSDictionary *)options
|
|
236
|
+
resolver:(RCTPromiseResolveBlock)resolve
|
|
237
|
+
rejecter:(RCTPromiseRejectBlock)reject) {
|
|
238
|
+
|
|
239
|
+
// mimeType is ignored for iOS
|
|
240
|
+
NSDictionary *source = [options objectForKey:@"sourcePath"];
|
|
241
|
+
NSString *destinationPath = [options objectForKey:@"targetPath"];
|
|
242
|
+
NSString *scope = [options objectForKey:@"scope"];
|
|
243
|
+
bool documentsFolder = !scope || [scope caseInsensitiveCompare:@"visible"] == NSOrderedSame;
|
|
244
|
+
|
|
245
|
+
NSFileManager* fileManager = [NSFileManager defaultManager];
|
|
246
|
+
|
|
247
|
+
NSString *sourceUri = [source objectForKey:@"uri"];
|
|
248
|
+
if(!sourceUri) {
|
|
249
|
+
sourceUri = [source objectForKey:@"path"];
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if([sourceUri hasPrefix:@"assets-library"]){
|
|
253
|
+
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
|
|
254
|
+
|
|
255
|
+
[library assetForURL:[NSURL URLWithString:sourceUri] resultBlock:^(ALAsset *asset) {
|
|
256
|
+
|
|
257
|
+
ALAssetRepresentation *rep = [asset defaultRepresentation];
|
|
258
|
+
|
|
259
|
+
Byte *buffer = (Byte*)malloc(rep.size);
|
|
260
|
+
NSUInteger buffered = [rep getBytes:buffer fromOffset:0.0 length:rep.size error:nil];
|
|
261
|
+
NSData *data = [NSData dataWithBytesNoCopy:buffer length:buffered freeWhenDone:YES];
|
|
262
|
+
|
|
263
|
+
if (data) {
|
|
264
|
+
NSString *filename = [sourceUri lastPathComponent];
|
|
265
|
+
NSString *tempFile = [NSTemporaryDirectory() stringByAppendingPathComponent:filename];
|
|
266
|
+
[data writeToFile:tempFile atomically:YES];
|
|
267
|
+
[self moveToICloudDirectory:documentsFolder :tempFile :destinationPath :resolve :reject];
|
|
268
|
+
} else {
|
|
269
|
+
RCTLogTrace(@"source file does not exist %@", sourceUri);
|
|
270
|
+
return reject(@"error", [NSString stringWithFormat:@"failed to copy asset '%@'", sourceUri], nil);
|
|
271
|
+
}
|
|
272
|
+
} failureBlock:^(NSError *error) {
|
|
273
|
+
RCTLogTrace(@"source file does not exist %@", sourceUri);
|
|
274
|
+
return reject(@"error", error.description, nil);
|
|
275
|
+
}];
|
|
276
|
+
} else if ([sourceUri hasPrefix:@"file:/"] || [sourceUri hasPrefix:@"/"]) {
|
|
277
|
+
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^file:/+" options:NSRegularExpressionCaseInsensitive error:nil];
|
|
278
|
+
NSString *modifiedSourceUri = [regex stringByReplacingMatchesInString:sourceUri options:0 range:NSMakeRange(0, [sourceUri length]) withTemplate:@"/"];
|
|
279
|
+
|
|
280
|
+
if ([fileManager fileExistsAtPath:modifiedSourceUri isDirectory:nil]) {
|
|
281
|
+
NSURL *sourceURL = [NSURL fileURLWithPath:modifiedSourceUri];
|
|
282
|
+
|
|
283
|
+
// todo: figure out how to *copy* to icloud drive
|
|
284
|
+
// ...setUbiquitous will move the file instead of copying it, so as a work around lets copy it to a tmp file first
|
|
285
|
+
NSString *filename = [sourceUri lastPathComponent];
|
|
286
|
+
NSString *tempFile = [NSTemporaryDirectory() stringByAppendingPathComponent:filename];
|
|
287
|
+
|
|
288
|
+
NSError *error;
|
|
289
|
+
if([fileManager fileExistsAtPath:tempFile]){
|
|
290
|
+
[fileManager removeItemAtPath:tempFile error:&error];
|
|
291
|
+
if(error) {
|
|
292
|
+
return reject(@"error", error.description, nil);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
[fileManager copyItemAtPath:[sourceURL path] toPath:tempFile error:&error];
|
|
297
|
+
if(error) {
|
|
298
|
+
return reject(@"error", error.description, nil);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
[self moveToICloudDirectory:documentsFolder :tempFile :destinationPath :resolve :reject];
|
|
302
|
+
} else {
|
|
303
|
+
NSLog(@"source file does not exist %@", sourceUri);
|
|
304
|
+
return reject(@"error", [NSString stringWithFormat:@"no such file or directory, open '%@'", sourceUri], nil);
|
|
305
|
+
}
|
|
306
|
+
} else {
|
|
307
|
+
NSURL *url = [NSURL URLWithString:sourceUri];
|
|
308
|
+
NSData *urlData = [NSData dataWithContentsOfURL:url];
|
|
309
|
+
|
|
310
|
+
if (urlData) {
|
|
311
|
+
NSString *filename = [sourceUri lastPathComponent];
|
|
312
|
+
NSString *tempFile = [NSTemporaryDirectory() stringByAppendingPathComponent:filename];
|
|
313
|
+
[urlData writeToFile:tempFile atomically:YES];
|
|
314
|
+
[self moveToICloudDirectory:documentsFolder :tempFile :destinationPath :resolve :reject];
|
|
315
|
+
} else {
|
|
316
|
+
RCTLogTrace(@"source file does not exist %@", sourceUri);
|
|
317
|
+
return reject(@"error", [NSString stringWithFormat:@"cannot download '%@'", sourceUri], nil);
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
- (void) moveToICloudDirectory:(bool) documentsFolder :(NSString *)tempFile :(NSString *)destinationPath
|
|
323
|
+
:(RCTPromiseResolveBlock)resolver
|
|
324
|
+
:(RCTPromiseRejectBlock)rejecter {
|
|
325
|
+
|
|
326
|
+
if(documentsFolder) {
|
|
327
|
+
NSURL *ubiquityURL = [self icloudDocumentsDirectory];
|
|
328
|
+
[self moveToICloud:ubiquityURL :tempFile :destinationPath :resolver :rejecter];
|
|
329
|
+
} else {
|
|
330
|
+
NSURL *ubiquityURL = [self icloudDirectory];
|
|
331
|
+
[self moveToICloud:ubiquityURL :tempFile :destinationPath :resolver :rejecter];
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
- (void) moveToICloud:(NSURL *)ubiquityURL :(NSString *)tempFile :(NSString *)destinationPath
|
|
336
|
+
:(RCTPromiseResolveBlock)resolver
|
|
337
|
+
:(RCTPromiseRejectBlock)rejecter {
|
|
338
|
+
|
|
339
|
+
|
|
340
|
+
NSString * destPath = destinationPath;
|
|
341
|
+
while ([destPath hasPrefix:@"/"]) {
|
|
342
|
+
destPath = [destPath substringFromIndex:1];
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
RCTLogTrace(@"Moving file %@ to %@", tempFile, destPath);
|
|
346
|
+
|
|
347
|
+
NSFileManager* fileManager = [NSFileManager defaultManager];
|
|
348
|
+
|
|
349
|
+
if (ubiquityURL) {
|
|
350
|
+
|
|
351
|
+
NSURL* targetFile = [ubiquityURL URLByAppendingPathComponent:destPath];
|
|
352
|
+
NSURL *dir = [targetFile URLByDeletingLastPathComponent];
|
|
353
|
+
|
|
354
|
+
NSURL* uniqueFile = targetFile;
|
|
355
|
+
|
|
356
|
+
if([fileManager fileExistsAtPath:uniqueFile.path]){
|
|
357
|
+
NSError *error;
|
|
358
|
+
[fileManager removeItemAtPath:uniqueFile.path error:&error];
|
|
359
|
+
if(error) {
|
|
360
|
+
return rejecter(@"error", error.description, nil);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
RCTLogTrace(@"Target file: %@", uniqueFile.path);
|
|
365
|
+
|
|
366
|
+
if (![fileManager fileExistsAtPath:dir.path]) {
|
|
367
|
+
[fileManager createDirectoryAtURL:dir withIntermediateDirectories:YES attributes:nil error:nil];
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
NSError *error;
|
|
371
|
+
[fileManager setUbiquitous:YES itemAtURL:[NSURL fileURLWithPath:tempFile] destinationURL:uniqueFile error:&error];
|
|
372
|
+
if(error) {
|
|
373
|
+
return rejecter(@"error", error.description, nil);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
[fileManager removeItemAtPath:tempFile error:&error];
|
|
377
|
+
|
|
378
|
+
return resolver(uniqueFile.path);
|
|
379
|
+
} else {
|
|
380
|
+
NSError *error;
|
|
381
|
+
[fileManager removeItemAtPath:tempFile error:&error];
|
|
382
|
+
|
|
383
|
+
return rejecter(@"error", [NSString stringWithFormat:@"could not copy '%@' to iCloud drive", tempFile], nil);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
- (NSURL *)icloudDocumentsDirectory {
|
|
388
|
+
NSFileManager* fileManager = [NSFileManager defaultManager];
|
|
389
|
+
NSURL *rootDirectory = [[self icloudDirectory] URLByAppendingPathComponent:@"Documents"];
|
|
390
|
+
|
|
391
|
+
if (rootDirectory) {
|
|
392
|
+
if (![fileManager fileExistsAtPath:rootDirectory.path isDirectory:nil]) {
|
|
393
|
+
RCTLogTrace(@"Creating documents directory: %@", rootDirectory.path);
|
|
394
|
+
[fileManager createDirectoryAtURL:rootDirectory withIntermediateDirectories:YES attributes:nil error:nil];
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
return rootDirectory;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
- (NSURL *)icloudDirectory {
|
|
402
|
+
NSFileManager* fileManager = [NSFileManager defaultManager];
|
|
403
|
+
NSURL *rootDirectory = [fileManager URLForUbiquityContainerIdentifier:nil];
|
|
404
|
+
return rootDirectory;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
- (NSURL *)localPathForResource:(NSString *)resource ofType:(NSString *)type {
|
|
408
|
+
NSString *documentsDirectory = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
|
|
409
|
+
NSString *resourcePath = [[documentsDirectory stringByAppendingPathComponent:resource] stringByAppendingPathExtension:type];
|
|
410
|
+
return [NSURL fileURLWithPath:resourcePath];
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
- (BOOL)downloadFileIfNotAvailable:(NSMetadataItem*)item {
|
|
416
|
+
if ([[item valueForAttribute:NSMetadataUbiquitousItemDownloadingStatusKey] isEqualToString:NSMetadataUbiquitousItemDownloadingStatusCurrent]){
|
|
417
|
+
NSLog(@"File is ready!");
|
|
418
|
+
return YES;
|
|
419
|
+
}
|
|
420
|
+
// Download the file.
|
|
421
|
+
NSFileManager* fm = [NSFileManager defaultManager];
|
|
422
|
+
NSError *downloadError = nil;
|
|
423
|
+
[fm startDownloadingUbiquitousItemAtURL:[item valueForAttribute:NSMetadataItemURLKey] error:&downloadError];
|
|
424
|
+
if (downloadError) {
|
|
425
|
+
NSLog(@"Error occurred starting download: %@", downloadError);
|
|
426
|
+
}
|
|
427
|
+
NSLog(@"Waiting before retrying...");
|
|
428
|
+
[NSThread sleepForTimeInterval:0.3];
|
|
429
|
+
return NO;
|
|
430
|
+
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
|
|
434
|
+
RCT_EXPORT_METHOD(syncCloud:(RCTPromiseResolveBlock)resolve
|
|
435
|
+
rejecter:(RCTPromiseRejectBlock)reject) {
|
|
436
|
+
|
|
437
|
+
_query = [[NSMetadataQuery alloc] init];
|
|
438
|
+
[_query setSearchScopes:@[NSMetadataQueryUbiquitousDocumentsScope, NSMetadataQueryUbiquitousDataScope]];
|
|
439
|
+
[_query setPredicate:[NSPredicate predicateWithFormat: @"%K LIKE '*'", NSMetadataItemFSNameKey]];
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
dispatch_async(dispatch_get_main_queue(), ^{
|
|
443
|
+
|
|
444
|
+
BOOL startedQuery = [self->_query startQuery];
|
|
445
|
+
if (!startedQuery)
|
|
446
|
+
{
|
|
447
|
+
reject(@"error", @"Failed to start query.\n", nil);
|
|
448
|
+
}
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
[[NSNotificationCenter defaultCenter] addObserverForName:
|
|
452
|
+
NSMetadataQueryDidFinishGatheringNotification
|
|
453
|
+
object:_query queue:[NSOperationQueue currentQueue]
|
|
454
|
+
usingBlock:^(NSNotification __strong *notification)
|
|
455
|
+
{
|
|
456
|
+
NSMetadataQuery *query = [notification object];
|
|
457
|
+
[query disableUpdates];
|
|
458
|
+
[query stopQuery];
|
|
459
|
+
for (NSMetadataItem *item in query.results) {
|
|
460
|
+
[self downloadFileIfNotAvailable: item];
|
|
461
|
+
}
|
|
462
|
+
return resolve(@YES);
|
|
463
|
+
}];
|
|
464
|
+
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
@end
|