react-native-cloud-storage 1.5.0 → 1.5.1
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/LICENSE +1 -1
- package/README.md +5 -6
- package/ios/CloudStorage.swift +262 -52
- package/ios/CloudStorage.xcodeproj/project.pbxproj +0 -28
- package/ios/CloudStorage.xcodeproj/project.xcworkspace/contents.xcworkspacedata +4 -0
- package/ios/CloudStorage.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/ios/CloudStorage.xcodeproj/project.xcworkspace/xcuserdata/max.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/ios/CloudStorage.xcodeproj/xcuserdata/max.xcuserdatad/xcschemes/xcschememanagement.plist +22 -0
- package/ios/CloudStorageEventEmitter.swift +4 -4
- package/lib/commonjs/RNCloudStorage.js +66 -361
- package/lib/commonjs/RNCloudStorage.js.map +1 -1
- package/lib/commonjs/createRNCloudStorage.js +48 -0
- package/lib/commonjs/createRNCloudStorage.js.map +1 -0
- package/lib/commonjs/expo-plugin/types/index.js.map +1 -1
- package/lib/commonjs/expo-plugin/withRNCloudStorage.js +3 -2
- package/lib/commonjs/expo-plugin/withRNCloudStorage.js.map +1 -1
- package/lib/commonjs/expo-plugin/withRNCloudStorageIos.js +7 -4
- package/lib/commonjs/expo-plugin/withRNCloudStorageIos.js.map +1 -1
- package/lib/commonjs/google-drive/client.js +20 -16
- package/lib/commonjs/google-drive/client.js.map +1 -1
- package/lib/commonjs/google-drive/index.js +64 -42
- package/lib/commonjs/google-drive/index.js.map +1 -1
- package/lib/commonjs/google-drive/types.js +2 -1
- package/lib/commonjs/google-drive/types.js.map +1 -1
- package/lib/commonjs/hooks/useCloudFile.js +17 -14
- package/lib/commonjs/hooks/useCloudFile.js.map +1 -1
- package/lib/commonjs/hooks/useIsCloudAvailable.js +21 -11
- package/lib/commonjs/hooks/useIsCloudAvailable.js.map +1 -1
- package/lib/commonjs/index.js +7 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/types/main.js +3 -8
- package/lib/commonjs/types/main.js.map +1 -1
- package/lib/commonjs/types/native.js +3 -3
- package/lib/commonjs/types/native.js.map +1 -1
- package/lib/commonjs/utils/CloudStorageError.js +2 -1
- package/lib/commonjs/utils/CloudStorageError.js.map +1 -1
- package/lib/commonjs/utils/helpers.js +15 -8
- package/lib/commonjs/utils/helpers.js.map +1 -1
- package/lib/module/RNCloudStorage.js +65 -362
- package/lib/module/RNCloudStorage.js.map +1 -1
- package/lib/module/createRNCloudStorage.js +41 -0
- package/lib/module/createRNCloudStorage.js.map +1 -0
- package/lib/module/expo-plugin/types/index.js +1 -1
- package/lib/module/expo-plugin/types/index.js.map +1 -1
- package/lib/module/expo-plugin/withRNCloudStorage.js +0 -2
- package/lib/module/expo-plugin/withRNCloudStorage.js.map +1 -1
- package/lib/module/expo-plugin/withRNCloudStorageIos.js +5 -5
- package/lib/module/expo-plugin/withRNCloudStorageIos.js.map +1 -1
- package/lib/module/google-drive/client.js +20 -18
- package/lib/module/google-drive/client.js.map +1 -1
- package/lib/module/google-drive/index.js +62 -41
- package/lib/module/google-drive/index.js.map +1 -1
- package/lib/module/google-drive/types.js +0 -2
- package/lib/module/google-drive/types.js.map +1 -1
- package/lib/module/hooks/useCloudFile.js +16 -15
- package/lib/module/hooks/useCloudFile.js.map +1 -1
- package/lib/module/hooks/useIsCloudAvailable.js +21 -13
- package/lib/module/hooks/useIsCloudAvailable.js.map +1 -1
- package/lib/module/index.js +5 -2
- package/lib/module/index.js.map +1 -1
- package/lib/module/types/main.js +0 -9
- package/lib/module/types/main.js.map +1 -1
- package/lib/module/types/native.js +1 -4
- package/lib/module/types/native.js.map +1 -1
- package/lib/module/utils/CloudStorageError.js +0 -2
- package/lib/module/utils/CloudStorageError.js.map +1 -1
- package/lib/module/utils/helpers.js +13 -8
- package/lib/module/utils/helpers.js.map +1 -1
- package/lib/typescript/RNCloudStorage.d.ts +39 -159
- package/lib/typescript/RNCloudStorage.d.ts.map +1 -1
- package/lib/typescript/createRNCloudStorage.d.ts +3 -0
- package/lib/typescript/createRNCloudStorage.d.ts.map +1 -0
- package/lib/typescript/google-drive/client.d.ts +3 -3
- package/lib/typescript/google-drive/client.d.ts.map +1 -1
- package/lib/typescript/google-drive/index.d.ts +18 -6
- package/lib/typescript/google-drive/index.d.ts.map +1 -1
- package/lib/typescript/hooks/useCloudFile.d.ts +7 -4
- package/lib/typescript/hooks/useCloudFile.d.ts.map +1 -1
- package/lib/typescript/hooks/useIsCloudAvailable.d.ts +2 -3
- package/lib/typescript/hooks/useIsCloudAvailable.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +4 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/types/main.d.ts +0 -33
- package/lib/typescript/types/main.d.ts.map +1 -1
- package/lib/typescript/types/native.d.ts +1 -2
- package/lib/typescript/types/native.d.ts.map +1 -1
- package/lib/typescript/utils/helpers.d.ts +9 -2
- package/lib/typescript/utils/helpers.d.ts.map +1 -1
- package/package.json +11 -9
- package/src/RNCloudStorage.ts +68 -387
- package/src/createRNCloudStorage.ts +53 -0
- package/src/google-drive/client.ts +7 -8
- package/src/google-drive/index.ts +63 -38
- package/src/hooks/useCloudFile.ts +16 -13
- package/src/hooks/useIsCloudAvailable.ts +25 -12
- package/src/index.ts +5 -0
- package/src/types/main.ts +0 -38
- package/src/types/native.ts +1 -2
- package/src/utils/helpers.ts +15 -8
- package/ios/Utils/CloudKitUtils.swift +0 -112
- package/ios/Utils/CloudStorageError.swift +0 -78
- package/ios/Utils/FileUtils.swift +0 -132
- package/ios/Utils/Promise.swift +0 -58
- package/ios/Utils/Types.swift +0 -36
- package/lib/commonjs/package.json +0 -1
- package/lib/module/package.json +0 -1
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2023
|
|
3
|
+
Copyright (c) 2023 Kuatsu Digital Agency
|
|
4
4
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
5
|
of this software and associated documentation files (the "Software"), to deal
|
|
6
6
|
in the Software without restriction, including without limitation the rights
|
package/README.md
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
  
|
|
4
4
|
|
|
5
|
-
This library provides a unified and streamlined API for accessing cloud storage services on iOS, Android and Web. It supports iCloud
|
|
5
|
+
This library provides a unified and streamlined API for accessing cloud storage services on iOS, Android and Web. It supports iCloud on iOS and Google Drive on all other platforms.
|
|
6
6
|
|
|
7
7
|
- 💾 Read and write files to the cloud
|
|
8
8
|
- 🧪 Fully compatible with Expo
|
|
9
9
|
- 📱 iOS, Android & Web support
|
|
10
10
|
- 🏎️ Lightning fast iCloud performance using native iOS APIs
|
|
11
|
-
- 🌐 Google Drive REST API implementation for
|
|
11
|
+
- 🌐 Google Drive REST API implementation for other platforms
|
|
12
12
|
- 🧬 Easy to use React Hooks API, or use the imperative `fs`-style API
|
|
13
13
|
- 👌 Zero dependencies, small bundle size
|
|
14
14
|
|
|
@@ -36,15 +36,14 @@ Afterwards, [add the provided config plugin](https://react-native-cloud-storage.
|
|
|
36
36
|
```jsx
|
|
37
37
|
import React from 'react';
|
|
38
38
|
import { Platform, View, Text, Button } from 'react-native';
|
|
39
|
-
import { CloudStorage,
|
|
39
|
+
import { CloudStorage, useIsCloudAvailable } from 'react-native-cloud-storage';
|
|
40
40
|
|
|
41
41
|
const App = () => {
|
|
42
42
|
const cloudAvailable = useIsCloudAvailable();
|
|
43
43
|
|
|
44
44
|
React.useEffect(() => {
|
|
45
|
-
if (
|
|
46
|
-
// get
|
|
47
|
-
CloudStorage.setProviderOptions({ accessToken: 'some-access-token' });
|
|
45
|
+
if (Platform.OS !== 'ios') {
|
|
46
|
+
CloudStorage.setGoogleDriveAccessToken('some-access-token'); // get via @react-native-google-signin/google-signin or similar
|
|
48
47
|
}
|
|
49
48
|
}, []);
|
|
50
49
|
|
package/ios/CloudStorage.swift
CHANGED
|
@@ -3,101 +3,311 @@ import Foundation
|
|
|
3
3
|
@objc(CloudStorage)
|
|
4
4
|
class CloudStorage: NSObject {
|
|
5
5
|
@objc(fileExists:withScope:withResolver:withRejecter:)
|
|
6
|
-
func fileExists(path: String, scope: String, resolve:
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
func fileExists(path: String, scope: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
7
|
+
let fileUrl: URL?
|
|
8
|
+
do {
|
|
9
|
+
fileUrl = try getFileURL(path, scope)
|
|
10
|
+
} catch let error as NSError {
|
|
11
|
+
reject(error.domain, error.userInfo["message"] as? String, error)
|
|
12
|
+
return
|
|
10
13
|
}
|
|
14
|
+
|
|
15
|
+
let fileManager = FileManager.default
|
|
16
|
+
let fileExists = fileManager.fileExists(atPath: fileUrl!.path)
|
|
17
|
+
resolve(fileExists)
|
|
11
18
|
}
|
|
12
19
|
|
|
13
20
|
@objc(appendToFile:withData:withScope:withResolver:withRejecter:)
|
|
14
|
-
func appendToFile(path: String, data: String, scope: String, resolve:
|
|
15
|
-
|
|
16
|
-
|
|
21
|
+
func appendToFile(path: String, data: String, scope: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
22
|
+
// Append data to the file at path. If the file doesn't exist, create it.
|
|
23
|
+
let fileUrl: URL?
|
|
24
|
+
do {
|
|
25
|
+
fileUrl = try getFileURL(path, scope)
|
|
26
|
+
} catch let error as NSError {
|
|
27
|
+
reject(error.domain, error.userInfo["message"] as? String, error)
|
|
28
|
+
return
|
|
29
|
+
}
|
|
17
30
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
31
|
+
let fileManager = FileManager.default
|
|
32
|
+
if (!fileManager.fileExists(atPath: fileUrl!.path)) {
|
|
33
|
+
do {
|
|
34
|
+
try data.write(to: fileUrl!, atomically: true, encoding: .utf8)
|
|
35
|
+
resolve(true)
|
|
36
|
+
} catch {
|
|
37
|
+
reject("ERR_WRITE_ERROR", "Error writing file \(path)", error)
|
|
38
|
+
}
|
|
39
|
+
} else {
|
|
40
|
+
do {
|
|
41
|
+
let fileHandle = try FileHandle(forWritingTo: fileUrl!)
|
|
42
|
+
fileHandle.seekToEndOfFile()
|
|
43
|
+
fileHandle.write(data.data(using: .utf8)!)
|
|
44
|
+
fileHandle.closeFile()
|
|
45
|
+
resolve(true)
|
|
46
|
+
} catch {
|
|
47
|
+
reject("ERR_WRITE_ERROR", "Error writing file \(path)", error)
|
|
21
48
|
}
|
|
22
|
-
|
|
23
|
-
let newData = existingData + data
|
|
24
|
-
return try FileUtils.writeFile(fileUrl: fileUrl, content: newData)
|
|
25
49
|
}
|
|
26
50
|
}
|
|
27
51
|
|
|
28
52
|
@objc(createFile:withData:withScope:withOverwrite:withResolver:withRejecter:)
|
|
29
|
-
func createFile(path: String, data: String, scope: String, overwrite: Bool, resolve:
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
53
|
+
func createFile(path: String, data: String, scope: String, overwrite: Bool, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
54
|
+
let fileUrl: URL?
|
|
55
|
+
do {
|
|
56
|
+
fileUrl = try getFileURL(path, scope, overwrite ? nil : false)
|
|
57
|
+
} catch let error as NSError {
|
|
58
|
+
reject(error.domain, error.userInfo["message"] as? String, error)
|
|
59
|
+
return
|
|
60
|
+
}
|
|
36
61
|
|
|
37
|
-
|
|
62
|
+
do {
|
|
63
|
+
try data.write(to: fileUrl!, atomically: true, encoding: .utf8)
|
|
64
|
+
resolve(true)
|
|
65
|
+
} catch {
|
|
66
|
+
reject("ERR_WRITE_ERROR", "Error writing file \(path)", error)
|
|
38
67
|
}
|
|
39
68
|
}
|
|
40
69
|
|
|
41
70
|
@objc(createDirectory:withScope:withResolver:withRejecter:)
|
|
42
|
-
func createDirectory(path: String, scope: String, resolve:
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
71
|
+
func createDirectory(path: String, scope: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
72
|
+
let directoryUrl: URL?
|
|
73
|
+
do {
|
|
74
|
+
directoryUrl = try getFileURL(path, scope, false)
|
|
75
|
+
} catch let error as NSError {
|
|
76
|
+
reject(error.domain, error.userInfo["message"] as? String, error)
|
|
77
|
+
return
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
let fileManager = FileManager.default
|
|
81
|
+
do {
|
|
82
|
+
try fileManager.createDirectory(at: directoryUrl!, withIntermediateDirectories: true, attributes: nil)
|
|
83
|
+
resolve(true)
|
|
84
|
+
} catch {
|
|
85
|
+
reject("ERR_WRITE_ERROR", "Error creating directory \(path)", error)
|
|
46
86
|
}
|
|
47
87
|
}
|
|
48
88
|
|
|
49
89
|
@objc(listFiles:withScope:withResolver:withRejecter:)
|
|
50
|
-
func listFiles(path: String, scope: String, resolve:
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
90
|
+
func listFiles(path: String, scope: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
91
|
+
let directoryUrl: URL?
|
|
92
|
+
do {
|
|
93
|
+
directoryUrl = try getFileURL(path, scope, true)
|
|
94
|
+
} catch let error as NSError {
|
|
95
|
+
reject(error.domain, error.userInfo["message"] as? String, error)
|
|
96
|
+
return
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
let fileManager = FileManager.default
|
|
100
|
+
do {
|
|
101
|
+
let files = try fileManager.contentsOfDirectory(atPath: directoryUrl!.path)
|
|
102
|
+
resolve(files)
|
|
103
|
+
} catch {
|
|
104
|
+
reject("ERR_READ_ERROR", "Error reading directory \(path)", error)
|
|
54
105
|
}
|
|
55
106
|
}
|
|
56
107
|
|
|
57
108
|
@objc(readFile:withScope:withResolver:withRejecter:)
|
|
58
|
-
func readFile(path: String, scope: String, resolve:
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
109
|
+
func readFile(path: String, scope: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
110
|
+
let fileUrl: URL?
|
|
111
|
+
do {
|
|
112
|
+
fileUrl = try getFileURL(path, scope, true)
|
|
113
|
+
} catch let error as NSError {
|
|
114
|
+
reject(error.domain, error.userInfo["message"] as? String, error)
|
|
115
|
+
return
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
do {
|
|
119
|
+
let fileContents = try String(contentsOf: fileUrl!, encoding: .utf8)
|
|
120
|
+
resolve(fileContents)
|
|
121
|
+
} catch {
|
|
122
|
+
reject("ERR_READ_ERROR", "Error reading file \(path)", error)
|
|
62
123
|
}
|
|
63
124
|
}
|
|
64
125
|
|
|
65
126
|
@objc(downloadFile:withScope:withResolver:withRejecter:)
|
|
66
|
-
func downloadFile(path: String, scope: String, resolve:
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
127
|
+
func downloadFile(path: String, scope: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
128
|
+
let fileManager = FileManager.default
|
|
129
|
+
|
|
130
|
+
guard let directory = getDirectory(scope) else {
|
|
131
|
+
let error = NSError(domain: "", code: 200, userInfo: [NSLocalizedDescriptionKey : "Error reading directory \(scope)"])
|
|
132
|
+
reject("ERR_READ_ERROR", "Error reading directory \(scope)", error)
|
|
133
|
+
return
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// remove leading slashes
|
|
137
|
+
let path = path.replacingOccurrences(of: "^/+", with: "", options: .regularExpression)
|
|
138
|
+
|
|
139
|
+
// append path to scope directory and return URL
|
|
140
|
+
let filePath = directory.appendingPathComponent(path)
|
|
141
|
+
|
|
142
|
+
let isDownloadable = fileManager.isUbiquitousItem(at: filePath)
|
|
143
|
+
|
|
144
|
+
if (!isDownloadable) {
|
|
145
|
+
reject("ERR_FILE_NOT_DOWNLOADABLE", "File or directory \(path) is not an iCloud file", NSError(domain: "", code: 202, userInfo: [NSLocalizedDescriptionKey : "File or directory \(path) is not an iCloud file"]))
|
|
146
|
+
return
|
|
147
|
+
}
|
|
148
|
+
do {
|
|
149
|
+
// trigger download of file
|
|
150
|
+
try fileManager.startDownloadingUbiquitousItem(at: filePath)
|
|
151
|
+
} catch {
|
|
152
|
+
let error = NSError(domain: "", code: 202, userInfo: [NSLocalizedDescriptionKey : "File or directory \(path) not downloadable"])
|
|
153
|
+
reject("ERR_FILE_NOT_DOWNLOADABLE", "File or directory \(path) not downloadable", error)
|
|
154
|
+
return
|
|
70
155
|
}
|
|
156
|
+
resolve(true)
|
|
71
157
|
}
|
|
72
158
|
|
|
159
|
+
|
|
73
160
|
@objc(deleteFile:withScope:withResolver:withRejecter:)
|
|
74
|
-
func deleteFile(path: String, scope: String, resolve:
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
161
|
+
func deleteFile(path: String, scope: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
162
|
+
let fileUrl: URL?
|
|
163
|
+
do {
|
|
164
|
+
fileUrl = try getFileURL(path, scope, true)
|
|
165
|
+
} catch let error as NSError {
|
|
166
|
+
reject(error.domain, error.userInfo["message"] as? String, error)
|
|
167
|
+
return
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (fileUrl!.hasDirectoryPath) {
|
|
171
|
+
reject("ERR_PATH_IS_DIRECTORY", "Path \(path) is a directory", nil)
|
|
172
|
+
return
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
let fileManager = FileManager.default
|
|
176
|
+
do {
|
|
177
|
+
try fileManager.removeItem(at: fileUrl!)
|
|
178
|
+
resolve(true)
|
|
179
|
+
} catch {
|
|
180
|
+
reject("ERR_DELETE_ERROR", "Error deleting file \(path)", error)
|
|
78
181
|
}
|
|
79
182
|
}
|
|
80
183
|
|
|
81
184
|
@objc(deleteDirectory:withRecursive:withScope:withResolver:withRejecter:)
|
|
82
|
-
func deleteDirectory(path: String, recursive
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
185
|
+
func deleteDirectory(path: String, recursive: Bool, scope: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
186
|
+
let fileUrl: URL?
|
|
187
|
+
do {
|
|
188
|
+
fileUrl = try getFileURL(path, scope, true)
|
|
189
|
+
} catch let error as NSError {
|
|
190
|
+
reject(error.domain, error.userInfo["message"] as? String, error)
|
|
191
|
+
return
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (!fileUrl!.hasDirectoryPath) {
|
|
195
|
+
reject("ERR_PATH_IS_FILE", "Path \(path) is a file", nil)
|
|
196
|
+
return
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if (!recursive) {
|
|
200
|
+
// check if directory is empty
|
|
201
|
+
let fileManager = FileManager.default
|
|
202
|
+
do {
|
|
203
|
+
print(fileUrl!.path)
|
|
204
|
+
let files = try fileManager.contentsOfDirectory(atPath: fileUrl!.path)
|
|
205
|
+
print(files)
|
|
206
|
+
if (files.count > 0) {
|
|
207
|
+
reject("ERR_DIRECTORY_NOT_EMPTY", "Directory \(path) is not empty", nil)
|
|
208
|
+
return
|
|
209
|
+
}
|
|
210
|
+
} catch {
|
|
211
|
+
reject("ERR_UNKNOWN", "Error reading directory \(path)", error)
|
|
212
|
+
return
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
let fileManager = FileManager.default
|
|
217
|
+
do {
|
|
218
|
+
try fileManager.removeItem(at: fileUrl!)
|
|
219
|
+
resolve(true)
|
|
220
|
+
} catch {
|
|
221
|
+
reject("ERR_DELETE_ERROR", "Error deleting directory \(path)", error)
|
|
86
222
|
}
|
|
87
223
|
}
|
|
88
224
|
|
|
89
225
|
@objc(statFile:withScope:withResolver:withRejecter:)
|
|
90
|
-
func statFile(path: String, scope: String, resolve:
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
226
|
+
func statFile(path: String, scope: String, resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
227
|
+
let fileUrl: URL?
|
|
228
|
+
do {
|
|
229
|
+
fileUrl = try getFileURL(path, scope, true)
|
|
230
|
+
} catch let error as NSError {
|
|
231
|
+
reject(error.domain, error.userInfo["message"] as? String, error)
|
|
232
|
+
return
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
let fileManager = FileManager.default
|
|
236
|
+
do {
|
|
237
|
+
let attributes = try fileManager.attributesOfItem(atPath: fileUrl!.path)
|
|
238
|
+
let size = attributes[FileAttributeKey.size] as! UInt64
|
|
239
|
+
let birthtime = attributes[FileAttributeKey.creationDate] as! Date
|
|
240
|
+
let mtime = attributes[FileAttributeKey.modificationDate] as! Date
|
|
241
|
+
let isDirectory = attributes[FileAttributeKey.type] as! FileAttributeType == FileAttributeType.typeDirectory
|
|
242
|
+
let isFile = attributes[FileAttributeKey.type] as! FileAttributeType == FileAttributeType.typeRegular
|
|
243
|
+
let result = [
|
|
244
|
+
"size": size,
|
|
245
|
+
"birthtimeMs": birthtime.timeIntervalSince1970 * 1000,
|
|
246
|
+
"mtimeMs": mtime.timeIntervalSince1970 * 1000,
|
|
247
|
+
"isDirectory": isDirectory,
|
|
248
|
+
"isFile": isFile
|
|
249
|
+
] as [String : Any]
|
|
250
|
+
resolve(result)
|
|
251
|
+
} catch {
|
|
252
|
+
reject("ERR_STAT_ERROR", "Error getting stats for file \(path)", error)
|
|
94
253
|
}
|
|
95
254
|
}
|
|
96
255
|
|
|
97
256
|
@objc(isCloudAvailable:withRejecter:)
|
|
98
|
-
func isCloudAvailable(resolve:
|
|
99
|
-
|
|
100
|
-
|
|
257
|
+
func isCloudAvailable(resolve:RCTPromiseResolveBlock,reject:RCTPromiseRejectBlock) -> Void {
|
|
258
|
+
let token = FileManager.default.ubiquityIdentityToken
|
|
259
|
+
resolve(token != nil)
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
Returns the iCloud directory URL for the given scope.
|
|
264
|
+
|
|
265
|
+
- Parameter scope: The scope of the directory. Can be either "documents" or "app_data".
|
|
266
|
+
- Returns: The URL of the iCloud directory.
|
|
267
|
+
*/
|
|
268
|
+
private func getDirectory(_ scope: String) -> URL? {
|
|
269
|
+
let fileManager = FileManager.default
|
|
270
|
+
let isDocumentDirectory = scope.caseInsensitiveCompare("documents") == .orderedSame
|
|
271
|
+
let ubiquityURL = fileManager.url(forUbiquityContainerIdentifier: nil)
|
|
272
|
+
print(ubiquityURL)
|
|
273
|
+
if (isDocumentDirectory) {
|
|
274
|
+
return fileManager.urls(for: .documentDirectory, in: .userDomainMask).first
|
|
275
|
+
} else {
|
|
276
|
+
return ubiquityURL
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
Parses a given path and directory scope to a full file URL. Does not check if the file exists.
|
|
282
|
+
|
|
283
|
+
- Parameter path: The path of the file.
|
|
284
|
+
- Parameter scope: The scope of the directory. Can be either "documents" or "app_data".
|
|
285
|
+
- Parameter shouldExist: Whether the file should exist. If true, throws an error if the file does not exist. If false, throws an error if the file exists. If nil, does not check if the file exists.
|
|
286
|
+
- Returns: The full URL of the file.
|
|
287
|
+
- Throws: An NSError if the scope directory couldn't be found or the file should exist but doesn't or vice versa.
|
|
288
|
+
*/
|
|
289
|
+
private func getFileURL(_ path: String, _ scope: String, _ shouldExist: Bool? = nil) throws -> URL? {
|
|
290
|
+
let fileManager = FileManager.default
|
|
291
|
+
|
|
292
|
+
guard let directory = getDirectory(scope) else {
|
|
293
|
+
throw NSError(domain: "ERR_DIRECTORY_NOT_FOUND", code: 0, userInfo: ["message": "Directory for scope \(scope) not found"])
|
|
101
294
|
}
|
|
295
|
+
|
|
296
|
+
// remove leading slashes
|
|
297
|
+
let path = path.replacingOccurrences(of: "^/+", with: "", options: .regularExpression)
|
|
298
|
+
|
|
299
|
+
// append path to scope directory and return URL
|
|
300
|
+
let filePath = directory.appendingPathComponent(path)
|
|
301
|
+
|
|
302
|
+
if (shouldExist != nil) {
|
|
303
|
+
let fileExists = fileManager.fileExists(atPath: filePath.path)
|
|
304
|
+
if (shouldExist! && !fileExists) {
|
|
305
|
+
throw NSError(domain: "ERR_FILE_NOT_FOUND", code: 0, userInfo: ["message": "File or directory \(path) not found"])
|
|
306
|
+
} else if (!shouldExist! && fileExists) {
|
|
307
|
+
throw NSError(domain: "ERR_FILE_EXISTS", code: 0, userInfo: ["message": "File or directory \(path) already exists"])
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
return filePath
|
|
102
312
|
}
|
|
103
313
|
}
|
|
@@ -8,11 +8,6 @@
|
|
|
8
8
|
|
|
9
9
|
/* Begin PBXBuildFile section */
|
|
10
10
|
50ADE3732B56EE1300DB5583 /* CloudStorageEventEmitter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5009AB9B2B56ECD30058E83A /* CloudStorageEventEmitter.swift */; };
|
|
11
|
-
50BC353B2CA6ED940085E8B9 /* FileUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50BC353A2CA6ED940085E8B9 /* FileUtils.swift */; };
|
|
12
|
-
50BC353F2CA6EF760085E8B9 /* Types.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50BC353E2CA6EF760085E8B9 /* Types.swift */; };
|
|
13
|
-
50BC35412CA6F0E80085E8B9 /* CloudKitUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50BC35402CA6F0E80085E8B9 /* CloudKitUtils.swift */; };
|
|
14
|
-
50BC35452CA6FA6D0085E8B9 /* CloudStorageError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50BC35442CA6FA6D0085E8B9 /* CloudStorageError.swift */; };
|
|
15
|
-
50BC35472CA6FF3F0085E8B9 /* Promise.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50BC35462CA6FF3F0085E8B9 /* Promise.swift */; };
|
|
16
11
|
F4FF95D7245B92E800C19C63 /* CloudStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4FF95D6245B92E800C19C63 /* CloudStorage.swift */; };
|
|
17
12
|
/* End PBXBuildFile section */
|
|
18
13
|
|
|
@@ -32,11 +27,6 @@
|
|
|
32
27
|
134814201AA4EA6300B7C361 /* libCloudStorage.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libCloudStorage.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
|
33
28
|
5009AB9B2B56ECD30058E83A /* CloudStorageEventEmitter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloudStorageEventEmitter.swift; sourceTree = "<group>"; };
|
|
34
29
|
50ADE3712B56EDFB00DB5583 /* CloudStorageEventEmitter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CloudStorageEventEmitter.m; sourceTree = "<group>"; };
|
|
35
|
-
50BC353A2CA6ED940085E8B9 /* FileUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileUtils.swift; sourceTree = "<group>"; };
|
|
36
|
-
50BC353E2CA6EF760085E8B9 /* Types.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Types.swift; sourceTree = "<group>"; };
|
|
37
|
-
50BC35402CA6F0E80085E8B9 /* CloudKitUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloudKitUtils.swift; sourceTree = "<group>"; };
|
|
38
|
-
50BC35442CA6FA6D0085E8B9 /* CloudStorageError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloudStorageError.swift; sourceTree = "<group>"; };
|
|
39
|
-
50BC35462CA6FF3F0085E8B9 /* Promise.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Promise.swift; sourceTree = "<group>"; };
|
|
40
30
|
B3E7B5891CC2AC0600A0062D /* CloudStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CloudStorage.m; sourceTree = "<group>"; };
|
|
41
31
|
F4FF95D5245B92E700C19C63 /* CloudStorage-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "CloudStorage-Bridging-Header.h"; sourceTree = "<group>"; };
|
|
42
32
|
F4FF95D6245B92E800C19C63 /* CloudStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloudStorage.swift; sourceTree = "<group>"; };
|
|
@@ -61,22 +51,9 @@
|
|
|
61
51
|
name = Products;
|
|
62
52
|
sourceTree = "<group>";
|
|
63
53
|
};
|
|
64
|
-
50BC35482CA704A60085E8B9 /* Utils */ = {
|
|
65
|
-
isa = PBXGroup;
|
|
66
|
-
children = (
|
|
67
|
-
50BC35402CA6F0E80085E8B9 /* CloudKitUtils.swift */,
|
|
68
|
-
50BC35442CA6FA6D0085E8B9 /* CloudStorageError.swift */,
|
|
69
|
-
50BC353A2CA6ED940085E8B9 /* FileUtils.swift */,
|
|
70
|
-
50BC35462CA6FF3F0085E8B9 /* Promise.swift */,
|
|
71
|
-
50BC353E2CA6EF760085E8B9 /* Types.swift */,
|
|
72
|
-
);
|
|
73
|
-
path = Utils;
|
|
74
|
-
sourceTree = "<group>";
|
|
75
|
-
};
|
|
76
54
|
58B511D21A9E6C8500147676 = {
|
|
77
55
|
isa = PBXGroup;
|
|
78
56
|
children = (
|
|
79
|
-
50BC35482CA704A60085E8B9 /* Utils */,
|
|
80
57
|
50ADE3712B56EDFB00DB5583 /* CloudStorageEventEmitter.m */,
|
|
81
58
|
5009AB9B2B56ECD30058E83A /* CloudStorageEventEmitter.swift */,
|
|
82
59
|
F4FF95D6245B92E800C19C63 /* CloudStorage.swift */,
|
|
@@ -143,13 +120,8 @@
|
|
|
143
120
|
isa = PBXSourcesBuildPhase;
|
|
144
121
|
buildActionMask = 2147483647;
|
|
145
122
|
files = (
|
|
146
|
-
50BC353B2CA6ED940085E8B9 /* FileUtils.swift in Sources */,
|
|
147
|
-
50BC35412CA6F0E80085E8B9 /* CloudKitUtils.swift in Sources */,
|
|
148
|
-
50BC35472CA6FF3F0085E8B9 /* Promise.swift in Sources */,
|
|
149
|
-
50BC35452CA6FA6D0085E8B9 /* CloudStorageError.swift in Sources */,
|
|
150
123
|
F4FF95D7245B92E800C19C63 /* CloudStorage.swift in Sources */,
|
|
151
124
|
50ADE3732B56EE1300DB5583 /* CloudStorageEventEmitter.swift in Sources */,
|
|
152
|
-
50BC353F2CA6EF760085E8B9 /* Types.swift in Sources */,
|
|
153
125
|
);
|
|
154
126
|
runOnlyForDeploymentPostprocessing = 0;
|
|
155
127
|
};
|
|
Binary file
|
package/ios/CloudStorage.xcodeproj/xcuserdata/max.xcuserdatad/xcschemes/xcschememanagement.plist
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
3
|
+
<plist version="1.0">
|
|
4
|
+
<dict>
|
|
5
|
+
<key>SchemeUserState</key>
|
|
6
|
+
<dict>
|
|
7
|
+
<key>CloudStorage.xcscheme_^#shared#^_</key>
|
|
8
|
+
<dict>
|
|
9
|
+
<key>orderHint</key>
|
|
10
|
+
<integer>0</integer>
|
|
11
|
+
</dict>
|
|
12
|
+
</dict>
|
|
13
|
+
<key>SuppressBuildableAutocreation</key>
|
|
14
|
+
<dict>
|
|
15
|
+
<key>58B511DA1A9E6C8500147676</key>
|
|
16
|
+
<dict>
|
|
17
|
+
<key>primary</key>
|
|
18
|
+
<true/>
|
|
19
|
+
</dict>
|
|
20
|
+
</dict>
|
|
21
|
+
</dict>
|
|
22
|
+
</plist>
|
|
@@ -10,7 +10,7 @@ class CloudStorageEventEmitter: RCTEventEmitter {
|
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
override func supportedEvents() -> [String]! {
|
|
13
|
-
["RNCloudStorage.cloud.availability-changed"]
|
|
13
|
+
return ["RNCloudStorage.cloud.availability-changed"]
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
override func startObserving() {
|
|
@@ -23,8 +23,8 @@ class CloudStorageEventEmitter: RCTEventEmitter {
|
|
|
23
23
|
NotificationCenter.default.removeObserver(self, name: NSNotification.Name.NSUbiquityIdentityDidChange, object: nil)
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
@objc func iCloudIdentityChanged(_: Notification? = nil) {
|
|
27
|
-
let
|
|
28
|
-
CloudStorageEventEmitter.shared.sendEvent(withName: "RNCloudStorage.cloud.availability-changed", body: ["available":
|
|
26
|
+
@objc func iCloudIdentityChanged(_ notification: Notification? = nil) {
|
|
27
|
+
let token = FileManager.default.ubiquityIdentityToken
|
|
28
|
+
CloudStorageEventEmitter.shared.sendEvent(withName: "RNCloudStorage.cloud.availability-changed", body: ["available": token != nil])
|
|
29
29
|
}
|
|
30
30
|
}
|