@onekeyfe/react-native-cloud-fs 2.6.4 → 3.0.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/CloudFs.podspec +19 -0
- package/android/build.gradle +64 -42
- package/android/src/main/java/com/rncloudfs/RNCloudFsModule.kt +50 -0
- package/android/src/main/java/com/rncloudfs/RNCloudFsPackage.kt +33 -0
- package/ios/CloudFs.h +7 -0
- package/ios/{RNCloudFs.m → CloudFs.mm} +174 -225
- package/lib/module/NativeCloudFs.js +5 -0
- package/lib/module/NativeCloudFs.js.map +1 -0
- package/lib/module/index.js +5 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/NativeCloudFs.d.ts +14 -0
- package/lib/typescript/src/NativeCloudFs.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +3 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/package.json +80 -7
- package/src/NativeCloudFs.ts +15 -0
- package/src/index.tsx +4 -0
- package/.github/workflows/package-publish.yml +0 -19
- package/README.md +0 -146
- package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +0 -6
- package/android/gradle.properties +0 -16
- package/android/gradlew +0 -160
- package/android/gradlew.bat +0 -90
- package/android/src/main/AndroidManifest.xml +0 -6
- package/android/src/main/java/org/rncloudfs/DriveServiceHelper.java +0 -214
- package/android/src/main/java/org/rncloudfs/RNCloudFsModule.java +0 -511
- package/android/src/main/java/org/rncloudfs/RNCloudFsPackage.java +0 -28
- package/docs/getting-started.md +0 -61
- package/docs/todo.md +0 -34
- package/docs/xcode.png +0 -0
- package/index.js +0 -7
- package/ios/RNCloudFs.h +0 -10
- package/ios/RNCloudFs.xcodeproj/project.pbxproj +0 -252
- package/ios/RNCloudFs.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
- package/licesnse.txt +0 -21
- package/react-native-cloud-fs.podspec +0 -17
|
@@ -1,511 +0,0 @@
|
|
|
1
|
-
package org.rncloudfs;
|
|
2
|
-
|
|
3
|
-
import android.app.Activity;
|
|
4
|
-
import android.content.Intent;
|
|
5
|
-
import androidx.annotation.Nullable;
|
|
6
|
-
|
|
7
|
-
import android.net.Uri;
|
|
8
|
-
import android.util.Log;
|
|
9
|
-
import android.webkit.MimeTypeMap;
|
|
10
|
-
import com.facebook.react.bridge.ActivityEventListener;
|
|
11
|
-
import com.facebook.react.bridge.LifecycleEventListener;
|
|
12
|
-
import com.facebook.react.bridge.Promise;
|
|
13
|
-
import com.facebook.react.bridge.ReactApplicationContext;
|
|
14
|
-
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
|
15
|
-
import com.facebook.react.bridge.ReactMethod;
|
|
16
|
-
import com.facebook.react.bridge.ReadableMap;
|
|
17
|
-
import com.facebook.react.bridge.WritableArray;
|
|
18
|
-
import com.facebook.react.bridge.WritableMap;
|
|
19
|
-
import com.facebook.react.bridge.WritableNativeArray;
|
|
20
|
-
import com.facebook.react.bridge.WritableNativeMap;
|
|
21
|
-
import com.google.android.gms.auth.api.signin.GoogleSignInOptions;
|
|
22
|
-
import com.google.android.gms.common.ConnectionResult;
|
|
23
|
-
import com.google.android.gms.common.api.ApiException;
|
|
24
|
-
import com.google.android.gms.common.api.GoogleApiClient;
|
|
25
|
-
import com.google.android.gms.common.api.Scope;
|
|
26
|
-
|
|
27
|
-
import com.google.android.gms.auth.api.signin.GoogleSignIn;
|
|
28
|
-
import com.google.android.gms.auth.api.signin.GoogleSignInAccount;
|
|
29
|
-
import com.google.android.gms.auth.api.signin.GoogleSignInClient;
|
|
30
|
-
import com.google.android.gms.tasks.Task;
|
|
31
|
-
import com.google.android.gms.tasks.Tasks;
|
|
32
|
-
import com.google.api.client.extensions.android.http.AndroidHttp;
|
|
33
|
-
import com.google.api.client.googleapis.extensions.android.gms.auth.GoogleAccountCredential;
|
|
34
|
-
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;
|
|
35
|
-
import com.google.api.client.json.gson.GsonFactory;
|
|
36
|
-
import com.google.api.services.drive.Drive;
|
|
37
|
-
import com.google.api.services.drive.DriveScopes;
|
|
38
|
-
import com.google.api.services.drive.model.File;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
import java.io.FileInputStream;
|
|
42
|
-
import java.io.FileNotFoundException;
|
|
43
|
-
import java.io.IOException;
|
|
44
|
-
import java.io.InputStream;
|
|
45
|
-
import java.io.InputStreamReader;
|
|
46
|
-
import java.io.OutputStream;
|
|
47
|
-
import java.net.HttpURLConnection;
|
|
48
|
-
import java.net.URL;
|
|
49
|
-
import java.util.Collections;
|
|
50
|
-
import java.util.concurrent.ExecutionException;
|
|
51
|
-
|
|
52
|
-
public class RNCloudFsModule extends ReactContextBaseJavaModule implements GoogleApiClient.OnConnectionFailedListener, LifecycleEventListener, ActivityEventListener {
|
|
53
|
-
public static final String TAG = "RNCloudFs";
|
|
54
|
-
private static final int REQUEST_CODE_SIGN_IN = 1;
|
|
55
|
-
private static final int REQUEST_CODE_OPEN_DOCUMENT = 2;
|
|
56
|
-
private static final int REQUEST_AUTHORIZATION = 11;
|
|
57
|
-
private DriveServiceHelper mDriveServiceHelper;
|
|
58
|
-
|
|
59
|
-
private Promise signInPromise;
|
|
60
|
-
private @Nullable Promise mPendingPromise; // we use it for calling again copyToCloud after obtaining authorisation
|
|
61
|
-
private @Nullable ReadableMap mPendingOptions;
|
|
62
|
-
private static final String COPY_TO_CLOUD = "CopyToCloud";
|
|
63
|
-
private static final String LIST_FILES = "ListFiles";
|
|
64
|
-
private @Nullable String mPendingOperation = null;
|
|
65
|
-
private final ReactApplicationContext reactContext;
|
|
66
|
-
private GoogleApiClient googleApiClient;
|
|
67
|
-
|
|
68
|
-
public RNCloudFsModule(ReactApplicationContext reactContext) {
|
|
69
|
-
super(reactContext);
|
|
70
|
-
this.reactContext = reactContext;
|
|
71
|
-
|
|
72
|
-
reactContext.addLifecycleEventListener(this);
|
|
73
|
-
reactContext.addActivityEventListener(this);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
@Override
|
|
77
|
-
public String getName() {
|
|
78
|
-
return "RNCloudFs";
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* android only method. Just here to test the connection logic
|
|
83
|
-
*/
|
|
84
|
-
@ReactMethod
|
|
85
|
-
public void reset(final Promise promise) {
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
@ReactMethod
|
|
90
|
-
public void fileExists(ReadableMap options, final Promise promise) {
|
|
91
|
-
if (mDriveServiceHelper != null) {
|
|
92
|
-
String fileId = options.getString("fileId");
|
|
93
|
-
Log.d(TAG, "Reading file " + fileId);
|
|
94
|
-
|
|
95
|
-
mDriveServiceHelper.checkIfFileExists(fileId)
|
|
96
|
-
.addOnSuccessListener(exists -> {
|
|
97
|
-
promise.resolve(exists);
|
|
98
|
-
|
|
99
|
-
})
|
|
100
|
-
.addOnFailureListener(exception ->{
|
|
101
|
-
try{
|
|
102
|
-
UserRecoverableAuthIOException e = (UserRecoverableAuthIOException)exception;
|
|
103
|
-
this.reactContext.startActivityForResult(e.getIntent(), REQUEST_AUTHORIZATION, null);
|
|
104
|
-
} catch(Exception e){
|
|
105
|
-
Log.e(TAG, "Couldn't read file.", exception);
|
|
106
|
-
promise.reject(exception);
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
@ReactMethod
|
|
113
|
-
public void deleteFromCloud(ReadableMap options, final Promise promise) {
|
|
114
|
-
if (mDriveServiceHelper != null) {
|
|
115
|
-
String fileId = options.getString("id");
|
|
116
|
-
Log.d(TAG, "Deleting file " + fileId);
|
|
117
|
-
|
|
118
|
-
mDriveServiceHelper.deleteFile(fileId)
|
|
119
|
-
.addOnSuccessListener(deleted -> {
|
|
120
|
-
promise.resolve(deleted);
|
|
121
|
-
|
|
122
|
-
})
|
|
123
|
-
.addOnFailureListener(exception ->{
|
|
124
|
-
try{
|
|
125
|
-
UserRecoverableAuthIOException e = (UserRecoverableAuthIOException)exception;
|
|
126
|
-
this.reactContext.startActivityForResult(e.getIntent(), REQUEST_AUTHORIZATION, null);
|
|
127
|
-
} catch(Exception e){
|
|
128
|
-
Log.e(TAG, "Couldn't delete file.", exception);
|
|
129
|
-
promise.reject(exception);
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
@ReactMethod
|
|
136
|
-
public void loginIfNeeded(final Promise promise){
|
|
137
|
-
if (mDriveServiceHelper == null) {
|
|
138
|
-
// Check for already logged in account
|
|
139
|
-
GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this.reactContext);
|
|
140
|
-
|
|
141
|
-
// Not signed in - request sign in
|
|
142
|
-
if (account == null) {
|
|
143
|
-
this.signInPromise = promise;
|
|
144
|
-
requestSignIn();
|
|
145
|
-
} else {
|
|
146
|
-
// Restore mDriveServiceHelper
|
|
147
|
-
// Use the authenticated account to sign in to the Drive service.
|
|
148
|
-
GoogleAccountCredential credential =
|
|
149
|
-
GoogleAccountCredential.usingOAuth2(
|
|
150
|
-
this.reactContext, Collections.singleton(DriveScopes.DRIVE_APPDATA));
|
|
151
|
-
credential.setSelectedAccount(account.getAccount());
|
|
152
|
-
Drive googleDriveService =
|
|
153
|
-
new Drive.Builder(
|
|
154
|
-
AndroidHttp.newCompatibleTransport(),
|
|
155
|
-
new GsonFactory(),
|
|
156
|
-
credential)
|
|
157
|
-
.build();
|
|
158
|
-
|
|
159
|
-
// The DriveServiceHelper encapsulates all REST API and SAF functionality.
|
|
160
|
-
// Its instantiation is required before handling any onClick actions.
|
|
161
|
-
mDriveServiceHelper = new DriveServiceHelper(googleDriveService);
|
|
162
|
-
promise.resolve(true);
|
|
163
|
-
}
|
|
164
|
-
} else {
|
|
165
|
-
promise.resolve(true);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
@ReactMethod
|
|
170
|
-
public void listFiles(ReadableMap options, final Promise promise) {
|
|
171
|
-
if (mDriveServiceHelper != null) {
|
|
172
|
-
Log.d(TAG, "Querying for files.");
|
|
173
|
-
WritableArray files = new WritableNativeArray();
|
|
174
|
-
WritableMap result = new WritableNativeMap();
|
|
175
|
-
|
|
176
|
-
boolean useDocumentsFolder = options.hasKey("scope") ? options.getString("scope").toLowerCase().equals("visible") : true;
|
|
177
|
-
try {
|
|
178
|
-
|
|
179
|
-
mDriveServiceHelper.queryFiles(useDocumentsFolder)
|
|
180
|
-
.addOnSuccessListener(fileList -> {
|
|
181
|
-
for (File file : fileList.getFiles()) {
|
|
182
|
-
WritableMap fileInfo = new WritableNativeMap();
|
|
183
|
-
fileInfo.putString("name", file.getName());
|
|
184
|
-
fileInfo.putString("id", file.getId());
|
|
185
|
-
fileInfo.putString("lastModified", file.getModifiedTime().toString());
|
|
186
|
-
files.pushMap(fileInfo);
|
|
187
|
-
}
|
|
188
|
-
result.putArray("files", files);
|
|
189
|
-
promise.resolve(result);
|
|
190
|
-
clearPendingOperations();
|
|
191
|
-
})
|
|
192
|
-
.addOnFailureListener(exception -> {
|
|
193
|
-
clearPendingOperations();
|
|
194
|
-
try {
|
|
195
|
-
Log.e(TAG, "Unable to query files: " + exception.getCause().getMessage());
|
|
196
|
-
UserRecoverableAuthIOException e = (UserRecoverableAuthIOException) exception;
|
|
197
|
-
mPendingPromise = promise;
|
|
198
|
-
mPendingOptions = options;
|
|
199
|
-
mPendingOperation = LIST_FILES;
|
|
200
|
-
this.reactContext.startActivityForResult(e.getIntent(), REQUEST_AUTHORIZATION, null);
|
|
201
|
-
} catch (Exception e) {
|
|
202
|
-
// throw e;
|
|
203
|
-
promise.reject(e);
|
|
204
|
-
}
|
|
205
|
-
});
|
|
206
|
-
} catch (Exception exception) {
|
|
207
|
-
try {
|
|
208
|
-
ExecutionException e = (ExecutionException) exception;
|
|
209
|
-
mPendingPromise = promise;
|
|
210
|
-
mPendingOptions = options;
|
|
211
|
-
mPendingOperation = LIST_FILES;
|
|
212
|
-
Intent intent = ((UserRecoverableAuthIOException) e.getCause()).getIntent();
|
|
213
|
-
this.reactContext.startActivityForResult(intent, REQUEST_AUTHORIZATION, null);
|
|
214
|
-
} catch (Exception e) {
|
|
215
|
-
promise.reject(exception);
|
|
216
|
-
Log.e(TAG, "Unable to query files: " + exception.getCause().getMessage());
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
/**
|
|
223
|
-
* Copy the source into the google drive database
|
|
224
|
-
*/
|
|
225
|
-
@ReactMethod
|
|
226
|
-
public void copyToCloud(ReadableMap options, final Promise promise) throws ExecutionException, InterruptedException {
|
|
227
|
-
if(mDriveServiceHelper != null){
|
|
228
|
-
if (!options.hasKey("sourcePath")) {
|
|
229
|
-
promise.reject("error", "sourcePath not specified");
|
|
230
|
-
}
|
|
231
|
-
ReadableMap source = options.getMap("sourcePath");
|
|
232
|
-
String uriOrPath = source.hasKey("uri") ? source.getString("uri") : null;
|
|
233
|
-
|
|
234
|
-
if (uriOrPath == null) {
|
|
235
|
-
uriOrPath = source.hasKey("path") ? source.getString("path") : null;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
if (uriOrPath == null) {
|
|
239
|
-
promise.reject("no path", "no source uri or path was specified");
|
|
240
|
-
return;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
if (!options.hasKey("targetPath")) {
|
|
244
|
-
promise.reject("error", "targetPath not specified");
|
|
245
|
-
}
|
|
246
|
-
final String destinationPath = options.getString("targetPath");
|
|
247
|
-
|
|
248
|
-
String mimeType = null;
|
|
249
|
-
if (options.hasKey("mimetype")) {
|
|
250
|
-
mimeType = options.getString("mimetype");
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
boolean useDocumentsFolder = options.hasKey("scope") ? options.getString("scope").toLowerCase().equals("visible") : true;
|
|
254
|
-
|
|
255
|
-
String actualMimeType;
|
|
256
|
-
if (mimeType == null) {
|
|
257
|
-
actualMimeType = guessMimeType(uriOrPath);
|
|
258
|
-
} else {
|
|
259
|
-
actualMimeType = null;
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
try {
|
|
263
|
-
mDriveServiceHelper.saveFile(uriOrPath, destinationPath, actualMimeType, useDocumentsFolder)
|
|
264
|
-
.addOnSuccessListener(fileId -> {
|
|
265
|
-
Log.d(TAG, "Saving " + fileId);
|
|
266
|
-
promise.resolve(fileId);
|
|
267
|
-
clearPendingOperations();
|
|
268
|
-
}).addOnFailureListener(exception -> {
|
|
269
|
-
clearPendingOperations();
|
|
270
|
-
try {
|
|
271
|
-
UserRecoverableAuthIOException e = (UserRecoverableAuthIOException) exception;
|
|
272
|
-
this.reactContext.startActivityForResult(e.getIntent(), REQUEST_AUTHORIZATION, null);
|
|
273
|
-
} catch (Exception e) {
|
|
274
|
-
Log.e(TAG, "Couldn't create file.", exception);
|
|
275
|
-
} finally {
|
|
276
|
-
promise.reject(exception);
|
|
277
|
-
}
|
|
278
|
-
});
|
|
279
|
-
} catch (Exception exception) {
|
|
280
|
-
try {
|
|
281
|
-
ExecutionException e = (ExecutionException) exception;
|
|
282
|
-
mPendingPromise = promise;
|
|
283
|
-
mPendingOptions = options;
|
|
284
|
-
mPendingOperation = COPY_TO_CLOUD;
|
|
285
|
-
Intent intent = ((UserRecoverableAuthIOException) e.getCause()).getIntent();
|
|
286
|
-
this.reactContext.startActivityForResult(intent, REQUEST_AUTHORIZATION, null);
|
|
287
|
-
} catch (Exception e) {
|
|
288
|
-
promise.reject(exception);
|
|
289
|
-
Log.e(TAG, "Couldn't create file.", exception);
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
@Nullable
|
|
296
|
-
private static String guessMimeType(String url) {
|
|
297
|
-
String extension = MimeTypeMap.getFileExtensionFromUrl(url);
|
|
298
|
-
if (extension != null) {
|
|
299
|
-
return MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
|
|
300
|
-
} else {
|
|
301
|
-
return null;
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
@Override
|
|
306
|
-
public void onHostResume() {
|
|
307
|
-
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
@Override
|
|
311
|
-
public void onHostPause() {
|
|
312
|
-
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
@Override
|
|
316
|
-
public void onHostDestroy() {
|
|
317
|
-
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
@Override
|
|
321
|
-
public void onNewIntent(Intent intent) {
|
|
322
|
-
System.out.println("RNCloudFsModule.onNewIntent");
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
public void clearPendingOperations(){
|
|
326
|
-
mPendingOperation = null;
|
|
327
|
-
mPendingPromise = null;
|
|
328
|
-
mPendingOptions = null;
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
@Override
|
|
332
|
-
public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent data) {
|
|
333
|
-
switch (requestCode) {
|
|
334
|
-
case REQUEST_CODE_SIGN_IN:
|
|
335
|
-
// The Task returned from this call is always completed, no need to attach
|
|
336
|
-
// a listener.
|
|
337
|
-
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
|
|
338
|
-
handleSignInResult(task);
|
|
339
|
-
break;
|
|
340
|
-
case REQUEST_AUTHORIZATION:
|
|
341
|
-
if (resultCode == Activity.RESULT_OK && data != null) {
|
|
342
|
-
// we want to make the operation again after obtaining right permissions
|
|
343
|
-
if (mPendingOperation != null) {
|
|
344
|
-
final String copiedPendingOperation = mPendingOperation;
|
|
345
|
-
reactContext.runOnNativeModulesQueueThread(() -> {
|
|
346
|
-
mPendingOperation = null;
|
|
347
|
-
switch (copiedPendingOperation) {
|
|
348
|
-
case COPY_TO_CLOUD:
|
|
349
|
-
try {
|
|
350
|
-
copyToCloud(mPendingOptions, mPendingPromise);
|
|
351
|
-
} catch (ExecutionException | InterruptedException ignore) {
|
|
352
|
-
mPendingPromise.reject(ignore);
|
|
353
|
-
clearPendingOperations();
|
|
354
|
-
}
|
|
355
|
-
break;
|
|
356
|
-
case LIST_FILES:
|
|
357
|
-
try {
|
|
358
|
-
listFiles(mPendingOptions, mPendingPromise);
|
|
359
|
-
} catch (Exception e) {
|
|
360
|
-
mPendingPromise.reject(e);
|
|
361
|
-
clearPendingOperations();
|
|
362
|
-
}
|
|
363
|
-
break;
|
|
364
|
-
}
|
|
365
|
-
});
|
|
366
|
-
}
|
|
367
|
-
} else if (resultCode == Activity.RESULT_CANCELED && mPendingPromise != null) {
|
|
368
|
-
mPendingPromise.reject("canceled", "User canceled");
|
|
369
|
-
} else if (mPendingPromise != null) {
|
|
370
|
-
mPendingPromise.reject("unknown error", "Operation failed: " + mPendingOperation + " result code " + resultCode);
|
|
371
|
-
}
|
|
372
|
-
break;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
@Override
|
|
378
|
-
public void onConnectionFailed(ConnectionResult result) {
|
|
379
|
-
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
/**
|
|
383
|
-
* Copy the source into the google drive database
|
|
384
|
-
*/
|
|
385
|
-
|
|
386
|
-
/**
|
|
387
|
-
* Starts a sign-in activity using {@link #REQUEST_CODE_SIGN_IN}.
|
|
388
|
-
*/
|
|
389
|
-
@ReactMethod
|
|
390
|
-
public void requestSignIn() {
|
|
391
|
-
Log.d(TAG, "Requesting sign-in");
|
|
392
|
-
|
|
393
|
-
GoogleSignInOptions signInOptions =
|
|
394
|
-
new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
|
|
395
|
-
.requestEmail()
|
|
396
|
-
// .requestScopes(new Scope(DriveScopes.DRIVE_FILE))
|
|
397
|
-
.requestScopes(new Scope(DriveScopes.DRIVE_APPDATA))
|
|
398
|
-
.build();
|
|
399
|
-
GoogleSignInClient client = GoogleSignIn.getClient(this.reactContext, signInOptions);
|
|
400
|
-
|
|
401
|
-
// The result of the sign-in Intent is handled in onActivityResult.
|
|
402
|
-
this.reactContext.startActivityForResult(client.getSignInIntent(), REQUEST_CODE_SIGN_IN, null);
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
@ReactMethod
|
|
406
|
-
public void getCurrentlySignedInUserData(Promise promise) {
|
|
407
|
-
Log.d(TAG, "Logging out");
|
|
408
|
-
|
|
409
|
-
GoogleSignInAccount account = GoogleSignIn.getLastSignedInAccount(this.reactContext);
|
|
410
|
-
if (account == null) {
|
|
411
|
-
promise.resolve(null);
|
|
412
|
-
} else {
|
|
413
|
-
Uri photoUrl = account.getPhotoUrl();
|
|
414
|
-
WritableMap resultData = new WritableNativeMap();
|
|
415
|
-
resultData.putString("email", account.getEmail());
|
|
416
|
-
resultData.putString("name", account.getDisplayName());
|
|
417
|
-
resultData.putString("avatarUrl", photoUrl != null ? photoUrl.toString() : null);
|
|
418
|
-
promise.resolve(resultData);
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
|
|
422
|
-
@ReactMethod
|
|
423
|
-
public void logout(Promise promise) {
|
|
424
|
-
|
|
425
|
-
Log.d(TAG, "Requesting sign-in");
|
|
426
|
-
|
|
427
|
-
GoogleSignInOptions signInOptions =
|
|
428
|
-
new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
|
|
429
|
-
.requestEmail()
|
|
430
|
-
// .requestScopes(new Scope(DriveScopes.DRIVE_FILE))
|
|
431
|
-
.requestScopes(new Scope(DriveScopes.DRIVE_APPDATA))
|
|
432
|
-
.build();
|
|
433
|
-
GoogleSignInClient client = GoogleSignIn.getClient(this.reactContext, signInOptions);
|
|
434
|
-
mDriveServiceHelper = null;
|
|
435
|
-
client.signOut()
|
|
436
|
-
.addOnSuccessListener( result -> {
|
|
437
|
-
promise.resolve(true);
|
|
438
|
-
})
|
|
439
|
-
.addOnFailureListener(exception ->{
|
|
440
|
-
Log.e(TAG, "Couldn't log out.", exception);
|
|
441
|
-
promise.reject(exception);
|
|
442
|
-
});
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
/**
|
|
446
|
-
* Handles the {@code result} of a completed sign-in activity initiated from {@link
|
|
447
|
-
* #requestSignIn()} ()}.
|
|
448
|
-
*/
|
|
449
|
-
private void handleSignInResult(Task<GoogleSignInAccount> completedTask) {
|
|
450
|
-
try {
|
|
451
|
-
GoogleSignInAccount googleAccount = completedTask.getResult(ApiException.class);
|
|
452
|
-
Log.d(TAG, "Signed in as " + googleAccount.getEmail());
|
|
453
|
-
|
|
454
|
-
// Use the authenticated account to sign in to the Drive service.
|
|
455
|
-
GoogleAccountCredential credential =
|
|
456
|
-
GoogleAccountCredential.usingOAuth2(
|
|
457
|
-
this.reactContext, Collections.singleton(DriveScopes.DRIVE_APPDATA));
|
|
458
|
-
credential.setSelectedAccount(googleAccount.getAccount());
|
|
459
|
-
Drive googleDriveService =
|
|
460
|
-
new Drive.Builder(
|
|
461
|
-
AndroidHttp.newCompatibleTransport(),
|
|
462
|
-
new GsonFactory(),
|
|
463
|
-
credential)
|
|
464
|
-
.build();
|
|
465
|
-
|
|
466
|
-
// The DriveServiceHelper encapsulates all REST API and SAF functionality.
|
|
467
|
-
// Its instantiation is required before handling any onClick actions.
|
|
468
|
-
mDriveServiceHelper = new DriveServiceHelper(googleDriveService);
|
|
469
|
-
|
|
470
|
-
if(this.signInPromise != null){
|
|
471
|
-
this.signInPromise.resolve(true);
|
|
472
|
-
this.signInPromise = null;
|
|
473
|
-
}
|
|
474
|
-
} catch (ApiException e) {
|
|
475
|
-
// The ApiException status code indicates the detailed failure reason.
|
|
476
|
-
// Please refer to the GoogleSignInStatusCodes class reference for more information.
|
|
477
|
-
Log.w(TAG, "signInResult:failed code=" + e.getStatusCode());
|
|
478
|
-
if(this.signInPromise != null){
|
|
479
|
-
this.signInPromise.reject("signInResult:" + e.getStatusCode(), e.getMessage());
|
|
480
|
-
this.signInPromise = null;
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
/**
|
|
486
|
-
* Retrieves the title and content of a file identified by {@code fileId} and populates the UI.
|
|
487
|
-
*/
|
|
488
|
-
@ReactMethod
|
|
489
|
-
public void getGoogleDriveDocument(String fileId, Promise promise) {
|
|
490
|
-
if (mDriveServiceHelper != null) {
|
|
491
|
-
Log.d(TAG, "Reading file " + fileId);
|
|
492
|
-
|
|
493
|
-
mDriveServiceHelper.readFile(fileId)
|
|
494
|
-
.addOnSuccessListener(content -> {
|
|
495
|
-
promise.resolve(content);
|
|
496
|
-
|
|
497
|
-
})
|
|
498
|
-
.addOnFailureListener(exception ->{
|
|
499
|
-
try{
|
|
500
|
-
UserRecoverableAuthIOException e = (UserRecoverableAuthIOException)exception;
|
|
501
|
-
this.reactContext.startActivityForResult(e.getIntent(), REQUEST_AUTHORIZATION, null);
|
|
502
|
-
} catch(Exception e){
|
|
503
|
-
Log.e(TAG, "Couldn't read file.", exception);
|
|
504
|
-
promise.reject(exception);
|
|
505
|
-
}
|
|
506
|
-
});
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
}
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
package org.rncloudfs;
|
|
2
|
-
|
|
3
|
-
import java.util.*;
|
|
4
|
-
|
|
5
|
-
import com.facebook.react.ReactPackage;
|
|
6
|
-
import com.facebook.react.bridge.NativeModule;
|
|
7
|
-
import com.facebook.react.bridge.JavaScriptModule;
|
|
8
|
-
import com.facebook.react.bridge.ReactApplicationContext;
|
|
9
|
-
import com.facebook.react.uimanager.ViewManager;
|
|
10
|
-
|
|
11
|
-
public class RNCloudFsPackage implements ReactPackage {
|
|
12
|
-
@Override
|
|
13
|
-
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
|
|
14
|
-
List<NativeModule> modules = new ArrayList<>();
|
|
15
|
-
modules.add(new RNCloudFsModule(reactContext));
|
|
16
|
-
return modules;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// deprecated >= RN 0.47.0
|
|
20
|
-
public List<Class<? extends JavaScriptModule>> createJSModules() {
|
|
21
|
-
return Collections.emptyList();
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
@Override
|
|
25
|
-
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
|
|
26
|
-
return Arrays.<ViewManager>asList();
|
|
27
|
-
}
|
|
28
|
-
}
|
package/docs/getting-started.md
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
## Getting started
|
|
2
|
-
|
|
3
|
-
An example project can be found at [react-native-cloud-fs-example](https://github.com/npomfret/react-native-cloud-fs-example).
|
|
4
|
-
|
|
5
|
-
This package is not released to npm (yet)...
|
|
6
|
-
|
|
7
|
-
npm install react-native-cloud-fs@https://github.com/npomfret/react-native-cloud-fs.git --save
|
|
8
|
-
react-native link react-native-cloud-fs
|
|
9
|
-
|
|
10
|
-
### iOS
|
|
11
|
-
|
|
12
|
-
On the device, make sure iCloud Drive is enabled. And it's helpful to have the iClound Drive app available.
|
|
13
|
-
|
|
14
|
-
In xCode...
|
|
15
|
-
|
|
16
|
-
* Add the following to `ios/app-name/Info.plist` (replacing _app-name_ and _package-name_ as appropriate):
|
|
17
|
-
|
|
18
|
-
```xml
|
|
19
|
-
<key>NSUbiquitousContainers</key>
|
|
20
|
-
<dict>
|
|
21
|
-
<key>iCloud.package-name</key>
|
|
22
|
-
<dict>
|
|
23
|
-
<key>NSUbiquitousContainerIsDocumentScopePublic</key>
|
|
24
|
-
<true/>
|
|
25
|
-
<key>NSUbiquitousContainerSupportedFolderLevels</key>
|
|
26
|
-
<string>One</string>
|
|
27
|
-
<key>NSUbiquitousContainerName</key>
|
|
28
|
-
<string>app-name</string>
|
|
29
|
-
</dict>
|
|
30
|
-
</dict>
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
* Enable iCloud:
|
|
34
|
-
|
|
35
|
-

|
|
36
|
-
|
|
37
|
-
### Android
|
|
38
|
-
|
|
39
|
-
Enable Google Drive API:
|
|
40
|
-
|
|
41
|
-
It's complicated! Here's a [video](https://www.youtube.com/watch?v=RezC1XP6jcs&feature=youtu.be&t=3m55s) of someone doing a similar thing for the Google Drive API demo.
|
|
42
|
-
|
|
43
|
-
- Create a [new project](https://console.developers.google.com/apis/dashboard) for your app (if you don't already have one)
|
|
44
|
-
- Under `Credentials`, choose `Create Credentials` > `OAth client ID`
|
|
45
|
-
- Choose `Android` and enter a name
|
|
46
|
-
- enter your SHA1 fingerprint (use the keytool to find it, eg: `keytool -exportcert -keystore path-to-debug-or-production-keystore -list -v`)
|
|
47
|
-
- enter your package name (found in your manifest file)
|
|
48
|
-
- copy the _OAuth client ID_
|
|
49
|
-
- Click Library, choose `Drive API` and enable it
|
|
50
|
-
- Click `Drive UI Integration`
|
|
51
|
-
- add the mandatory application icons
|
|
52
|
-
- under `Drive integration` > `Authentication`
|
|
53
|
-
- check `Automatically show OAuth 2.0 consent screen when users open my application from Google Drive` and enter your _OAuth client ID_
|
|
54
|
-
- enter an _Open URL_
|
|
55
|
-
|
|
56
|
-
Add the following to your `app/build.gradle` in the `dependecies` section (you can change the version to suit your application):
|
|
57
|
-
|
|
58
|
-
compile ('com.google.android.gms:play-services-drive:10.2.0') {
|
|
59
|
-
force = true;
|
|
60
|
-
}
|
|
61
|
-
|
package/docs/todo.md
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
# todo
|
|
2
|
-
|
|
3
|
-
## In progress
|
|
4
|
-
|
|
5
|
-
## API
|
|
6
|
-
|
|
7
|
-
* get user to sign into icloud: https://developer.apple.com/library/content/documentation/DataManagement/Conceptual/CloudKitQuickStart/CreatingaSchemabySavingRecords/CreatingaSchemabySavingRecords.html#//apple_ref/doc/uid/TP40014987-CH3-SW8
|
|
8
|
-
* download docs from icloud? https://github.com/iRareMedia/iCloudDocumentSync/blob/master/iCloud/iCloud.m#L751
|
|
9
|
-
* send event when the files change
|
|
10
|
-
* add method: `moveFile` / `renameFile`
|
|
11
|
-
* add method: `createCouldDirectory`
|
|
12
|
-
* add method: `copyFromCloud`
|
|
13
|
-
* single file
|
|
14
|
-
* to local file system
|
|
15
|
-
* put (to rest endpoint)
|
|
16
|
-
* post (mutipart form post)
|
|
17
|
-
* add method: `deleteFromCloud`
|
|
18
|
-
* single file
|
|
19
|
-
* entire directory
|
|
20
|
-
* option to save images to
|
|
21
|
-
* ios photos
|
|
22
|
-
* android clound images..?
|
|
23
|
-
* `copyToCloud`
|
|
24
|
-
* add option to overwrite existing file
|
|
25
|
-
* add option to fail silently if the file already exists
|
|
26
|
-
* add optional http headers (done for android)
|
|
27
|
-
* check what happens (and fix) if a destination path contains non-filename safe characters ('#', '<', '$', '+', '%', '>', '!', '`', '&', '*', '‘', '|', '{', '?', '“', '=', '}', '/', ':', '\\', '@') [source](http://www.mtu.edu/umc/services/digital/writing/characters-avoid/). _iOS only_
|
|
28
|
-
* sensible & descriptive error messages for all error scenarios
|
|
29
|
-
* add method: `searchForCloudFiles`
|
|
30
|
-
|
|
31
|
-
## Other implementations
|
|
32
|
-
|
|
33
|
-
* Dropbox
|
|
34
|
-
* google drive on iOS
|
package/docs/xcode.png
DELETED
|
Binary file
|
package/index.js
DELETED
package/ios/RNCloudFs.h
DELETED