@react-native-documents/picker 11.0.4 → 12.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/android/src/main/java/com/reactnativedocumentpicker/CopyDestination.kt +1 -2
- package/android/src/main/java/com/reactnativedocumentpicker/DocumentMetadataBuilder.kt +4 -3
- package/android/src/main/java/com/reactnativedocumentpicker/FileOperations.kt +2 -2
- package/android/src/main/java/com/reactnativedocumentpicker/IsKnownTypeImpl.kt +26 -28
- package/android/src/main/java/com/reactnativedocumentpicker/MetadataGetter.kt +69 -45
- package/android/src/main/java/com/reactnativedocumentpicker/PickOptions.kt +43 -23
- package/android/src/main/java/com/reactnativedocumentpicker/PromiseWrapper.kt +83 -0
- package/android/src/main/java/com/reactnativedocumentpicker/RNDocumentPickerModule.kt +5 -5
- package/ios/RNDocumentPicker.mm +19 -41
- package/ios/swift/DocPicker.swift +46 -28
- package/ios/swift/DocSaver.swift +18 -23
- package/ios/swift/DocumentMetadataBuilder.swift +1 -1
- package/ios/swift/FileOperations.swift +21 -19
- package/ios/swift/IsKnownTypeImpl.swift +16 -10
- package/ios/swift/LocalCopyResponse.swift +3 -5
- package/ios/swift/PickerBase.swift +31 -49
- package/ios/swift/PickerOptions.swift +53 -23
- package/ios/swift/PromiseWrapper.swift +71 -58
- package/ios/swift/SaverOptions.swift +39 -17
- package/jest/build/src/errors.js +2 -0
- package/lib/module/errors.js +3 -2
- package/lib/module/errors.js.map +1 -1
- package/lib/module/release.js +1 -1
- package/lib/typescript/src/errors.d.ts +6 -3
- package/lib/typescript/src/errors.d.ts.map +1 -1
- package/lib/typescript/src/release.d.ts +1 -1
- package/lib/typescript/src/saveDocuments.d.ts +1 -1
- package/lib/typescript/src/types.d.ts +3 -3
- package/package.json +3 -2
- package/react-native-document-picker.podspec +1 -0
- package/src/errors.ts +8 -4
- package/src/release.ts +1 -1
- package/src/saveDocuments.ts +1 -1
- package/src/types.ts +3 -3
- package/android/src/main/java/com/reactnativedocumentpicker/IntentFactory.kt +0 -36
- package/android/src/main/java/com/reactnativedocumentpicker/PromiseWrapper.java +0 -105
- package/ios/swift/PromiseSupport.swift +0 -2
|
@@ -1,61 +1,45 @@
|
|
|
1
1
|
// LICENSE: see License.md in the package root
|
|
2
2
|
|
|
3
3
|
import Foundation
|
|
4
|
+
import React
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
/// React Native promise blocks are safe to call from background queues, but they are not annotated
|
|
7
|
+
/// as `Sendable`. Wrap them so Swift 6 doesn't warn when captured by `@Sendable` closures
|
|
8
|
+
/// (e.g. `Task.detached`, GCD `DispatchQueue.async`).
|
|
9
|
+
struct ResolveCallback: @unchecked Sendable {
|
|
10
|
+
let resolve: RCTPromiseResolveBlock
|
|
11
|
+
}
|
|
9
12
|
|
|
10
|
-
|
|
11
|
-
|
|
13
|
+
/// React Native promise blocks are safe to call from background queues, but they are not annotated
|
|
14
|
+
/// as `Sendable`. Wrap them so Swift 6 doesn't warn when captured by `@Sendable` closures
|
|
15
|
+
/// (e.g. `Task.detached`, GCD `DispatchQueue.async`).
|
|
16
|
+
struct RejectCallback: @unchecked Sendable {
|
|
17
|
+
let reject: RCTPromiseRejectBlock
|
|
18
|
+
}
|
|
12
19
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
nameOfCallInProgress = callsite
|
|
22
|
-
}
|
|
20
|
+
/// Promise callbacks for React Native bridges.
|
|
21
|
+
///
|
|
22
|
+
/// React Native promise blocks are safe to call from background queues, but they are not annotated
|
|
23
|
+
/// as `Sendable`. We wrap them so this value can be captured by `@Sendable` closures without
|
|
24
|
+
/// Swift 6 warnings.
|
|
25
|
+
struct PromiseCallbacks: @unchecked Sendable {
|
|
26
|
+
private let resolveCallback: ResolveCallback
|
|
27
|
+
private let rejectCallback: RejectCallback
|
|
23
28
|
|
|
24
|
-
|
|
25
|
-
rejecter reject: @escaping RNDPPromiseRejectBlock,
|
|
26
|
-
fromCallSite callsite: String) -> Bool {
|
|
27
|
-
if promiseReject != nil {
|
|
28
|
-
rejectNewPromiseBecauseOldOneIsInProgress(reject, requestedOperation: callsite)
|
|
29
|
-
return false
|
|
30
|
-
}
|
|
31
|
-
promiseResolve = resolve
|
|
32
|
-
promiseReject = reject
|
|
33
|
-
nameOfCallInProgress = callsite
|
|
34
|
-
return true
|
|
35
|
-
}
|
|
29
|
+
private let E_DOCUMENT_PICKER_CANCELED = "OPERATION_CANCELED"
|
|
36
30
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return
|
|
41
|
-
}
|
|
42
|
-
resetMembers()
|
|
43
|
-
resolver(result)
|
|
31
|
+
init(resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
|
|
32
|
+
self.resolveCallback = ResolveCallback(resolve: resolve)
|
|
33
|
+
self.rejectCallback = RejectCallback(reject: reject)
|
|
44
34
|
}
|
|
45
35
|
|
|
46
|
-
func
|
|
47
|
-
|
|
48
|
-
reject(message, withCode: errorCode, withError: error)
|
|
36
|
+
func resolve(_ result: Any?) {
|
|
37
|
+
resolveCallback.resolve(result)
|
|
49
38
|
}
|
|
50
39
|
|
|
51
|
-
func reject(_ message: String, withCode
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
return
|
|
55
|
-
}
|
|
56
|
-
let errorMessage = "RNDPPromiseWrapper: \(message), \(error.description)"
|
|
57
|
-
resetMembers()
|
|
58
|
-
rejecter(errorCode, errorMessage, error)
|
|
40
|
+
func reject(_ message: String, withCode code: String, withError error: NSError?) {
|
|
41
|
+
let errorMessage = "RNDocumentPicker: \(message)\(error.map { ", \($0.description)" } ?? "")"
|
|
42
|
+
rejectCallback.reject(code, errorMessage, error)
|
|
59
43
|
}
|
|
60
44
|
|
|
61
45
|
func rejectAsUserCancelledOperation() {
|
|
@@ -66,27 +50,56 @@ class PromiseWrapper {
|
|
|
66
50
|
withCode: E_DOCUMENT_PICKER_CANCELED,
|
|
67
51
|
withError: error)
|
|
68
52
|
}
|
|
53
|
+
}
|
|
69
54
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
55
|
+
/// Promise lifecycle manager.
|
|
56
|
+
///
|
|
57
|
+
/// **Lifecycle:** Stores the promise callbacks between the initial call and delegate callbacks.
|
|
58
|
+
/// Call `takeCallbacks()` to extract callbacks for async operations.
|
|
59
|
+
///
|
|
60
|
+
/// **Usage:** Cancellation/dismissal settles the in-flight promise (on whatever queue calls it).
|
|
61
|
+
final class PromiseWrapper {
|
|
62
|
+
private var callbacks: PromiseCallbacks?
|
|
63
|
+
private var nameOfCallInProgress: String?
|
|
64
|
+
|
|
65
|
+
private let ASYNC_OP_IN_PROGRESS = "ASYNC_OP_IN_PROGRESS"
|
|
66
|
+
|
|
67
|
+
func trySetPromiseRejectingIncoming(_ resolve: @escaping RCTPromiseResolveBlock,
|
|
68
|
+
rejecter reject: @escaping RCTPromiseRejectBlock,
|
|
69
|
+
fromCallSite callsite: String = #function) -> Bool {
|
|
70
|
+
if callbacks != nil {
|
|
71
|
+
let newCallbacks = PromiseCallbacks(resolve: resolve, reject: reject)
|
|
72
|
+
rejectNewPromiseBecauseOldOneIsInProgress(newCallbacks, requestedOperation: callsite)
|
|
73
|
+
return false
|
|
74
|
+
}
|
|
75
|
+
callbacks = PromiseCallbacks(resolve: resolve, reject: reject)
|
|
76
|
+
nameOfCallInProgress = callsite
|
|
77
|
+
return true
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/// Extract callbacks for async work (e.g. file I/O off the main thread).
|
|
81
|
+
/// After extraction, this wrapper is cleared and the callbacks are moved out.
|
|
82
|
+
func takeCallbacks(caller: String = #function) -> PromiseCallbacks? {
|
|
83
|
+
guard let cb = callbacks else {
|
|
84
|
+
NSLog("RNDocumentPicker: \(caller) called with no in-flight promise. Dropping result.")
|
|
85
|
+
return nil
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
callbacks = nil
|
|
73
89
|
nameOfCallInProgress = nil
|
|
90
|
+
return cb
|
|
74
91
|
}
|
|
75
92
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
requestedOperation callSiteName: String) {
|
|
79
|
-
let msg = "Warning: previous promise did not settle and was overwritten. " +
|
|
80
|
-
"You've called \"\(callSiteName)\" while \"\(nameOfCallInProgress ?? "")\" " +
|
|
81
|
-
"was already in progress and has not completed yet."
|
|
82
|
-
reject(ASYNC_OP_IN_PROGRESS, msg, nil)
|
|
93
|
+
func rejectAsUserCancelledOperation() {
|
|
94
|
+
takeCallbacks()?.rejectAsUserCancelledOperation()
|
|
83
95
|
}
|
|
84
96
|
|
|
85
|
-
private func rejectNewPromiseBecauseOldOneIsInProgress(_
|
|
97
|
+
private func rejectNewPromiseBecauseOldOneIsInProgress(_ callbacks: PromiseCallbacks,
|
|
86
98
|
requestedOperation callSiteName: String) {
|
|
87
99
|
let msg = "Warning: previous promise did not settle and you attempted to overwrite it. " +
|
|
88
100
|
"You've called \"\(callSiteName)\" while \"\(nameOfCallInProgress ?? "")\" " +
|
|
89
101
|
"was already in progress and has not completed yet."
|
|
90
|
-
|
|
102
|
+
let error = NSError(domain: NSCocoaErrorDomain, code: 0, userInfo: [NSLocalizedDescriptionKey: msg])
|
|
103
|
+
callbacks.reject(msg, withCode: ASYNC_OP_IN_PROGRESS, withError: error)
|
|
91
104
|
}
|
|
92
105
|
}
|
|
@@ -3,28 +3,50 @@
|
|
|
3
3
|
import Foundation
|
|
4
4
|
import UIKit
|
|
5
5
|
import UniformTypeIdentifiers
|
|
6
|
+
import React
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
public struct SaverOptions: Sendable {
|
|
9
|
+
var transitionStyle: UIModalTransitionStyle?
|
|
10
|
+
var presentationStyle: UIModalPresentationStyle?
|
|
11
|
+
var initialDirectoryUri: URL?
|
|
11
12
|
let sourceUrls: [URL]
|
|
12
13
|
let shouldShowFileExtensions: Bool
|
|
13
14
|
let asCopy: Bool
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
|
|
16
|
+
public init(dictionary: NSDictionary) {
|
|
17
|
+
let sourceUrlStrings = dictionary["sourceUris"] as? [String] ?? []
|
|
18
|
+
let asCopy = dictionary["copy"] as? Bool ?? false
|
|
19
|
+
let shouldShowFileExtensions = dictionary["showFileExtensions"] as? Bool ?? false
|
|
20
|
+
|
|
21
|
+
self.sourceUrls = sourceUrlStrings.compactMap { URL(string: $0) }
|
|
19
22
|
self.asCopy = asCopy
|
|
20
|
-
self.transitionStyle = transitionStyle
|
|
21
|
-
self.presentationStyle = presentationStyle
|
|
22
|
-
if let unwrappedUrl = initialDirectoryUrl, let url = URL(string: unwrappedUrl) {
|
|
23
|
-
self.initialDirectoryUrl = url
|
|
24
|
-
} else {
|
|
25
|
-
self.initialDirectoryUrl = nil
|
|
26
|
-
}
|
|
27
23
|
self.shouldShowFileExtensions = shouldShowFileExtensions
|
|
24
|
+
|
|
25
|
+
if let transitionStyle = dictionary["transitionStyle"] as? String {
|
|
26
|
+
self.transitionStyle = RCTConvert.uiModalTransitionStyle(transitionStyle)
|
|
27
|
+
}
|
|
28
|
+
if let presentationStyle = dictionary["presentationStyle"] as? String {
|
|
29
|
+
self.presentationStyle = RCTConvert.uiModalPresentationStyle(presentationStyle)
|
|
30
|
+
}
|
|
31
|
+
if let initialDirectoryUri = dictionary["initialDirectoryUri"] as? String, let url = URL(string: initialDirectoryUri) {
|
|
32
|
+
self.initialDirectoryUri = url
|
|
33
|
+
}
|
|
28
34
|
}
|
|
29
|
-
|
|
35
|
+
|
|
36
|
+
@MainActor
|
|
37
|
+
public func createDocumentPicker() -> UIDocumentPickerViewController {
|
|
38
|
+
let picker = UIDocumentPickerViewController(forExporting: sourceUrls, asCopy: asCopy)
|
|
39
|
+
|
|
40
|
+
if let presentationStyle = presentationStyle {
|
|
41
|
+
picker.modalPresentationStyle = presentationStyle
|
|
42
|
+
}
|
|
43
|
+
if let transitionStyle = transitionStyle {
|
|
44
|
+
picker.modalTransitionStyle = transitionStyle
|
|
45
|
+
}
|
|
46
|
+
picker.directoryURL = initialDirectoryUri
|
|
47
|
+
picker.shouldShowFileExtensions = shouldShowFileExtensions
|
|
48
|
+
|
|
49
|
+
return picker
|
|
50
|
+
}
|
|
51
|
+
|
|
30
52
|
}
|
package/jest/build/src/errors.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.isErrorWithCode = exports.errorCodes = void 0;
|
|
|
4
4
|
const OPERATION_CANCELED = 'OPERATION_CANCELED';
|
|
5
5
|
const IN_PROGRESS = 'ASYNC_OP_IN_PROGRESS';
|
|
6
6
|
const UNABLE_TO_OPEN_FILE_TYPE = 'UNABLE_TO_OPEN_FILE_TYPE';
|
|
7
|
+
const NULL_PRESENTER = 'NULL_PRESENTER';
|
|
7
8
|
/**
|
|
8
9
|
* Error codes that can be returned by the module, and are available on the `code` property of the error.
|
|
9
10
|
*
|
|
@@ -34,6 +35,7 @@ exports.errorCodes = Object.freeze({
|
|
|
34
35
|
OPERATION_CANCELED,
|
|
35
36
|
IN_PROGRESS,
|
|
36
37
|
UNABLE_TO_OPEN_FILE_TYPE,
|
|
38
|
+
NULL_PRESENTER,
|
|
37
39
|
});
|
|
38
40
|
/**
|
|
39
41
|
* TypeScript helper to check if an object has the `code` property.
|
package/lib/module/errors.js
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
const OPERATION_CANCELED = 'OPERATION_CANCELED';
|
|
4
4
|
const IN_PROGRESS = 'ASYNC_OP_IN_PROGRESS';
|
|
5
5
|
const UNABLE_TO_OPEN_FILE_TYPE = 'UNABLE_TO_OPEN_FILE_TYPE';
|
|
6
|
+
const NULL_PRESENTER = 'NULL_PRESENTER';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* Error codes that can be returned by the module, and are available on the `code` property of the error.
|
|
@@ -33,9 +34,9 @@ const UNABLE_TO_OPEN_FILE_TYPE = 'UNABLE_TO_OPEN_FILE_TYPE';
|
|
|
33
34
|
export const errorCodes = Object.freeze({
|
|
34
35
|
OPERATION_CANCELED,
|
|
35
36
|
IN_PROGRESS,
|
|
36
|
-
UNABLE_TO_OPEN_FILE_TYPE
|
|
37
|
+
UNABLE_TO_OPEN_FILE_TYPE,
|
|
38
|
+
NULL_PRESENTER
|
|
37
39
|
});
|
|
38
|
-
|
|
39
40
|
/**
|
|
40
41
|
* TypeScript helper to check if an object has the `code` property.
|
|
41
42
|
* This is used to avoid `as` casting when you access the `code` property on errors returned by the module.
|
package/lib/module/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["OPERATION_CANCELED","IN_PROGRESS","UNABLE_TO_OPEN_FILE_TYPE","errorCodes","Object","freeze","isErrorWithCode","error","isNewArchErrorIOS","Error"],"sourceRoot":"../../src","sources":["errors.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"names":["OPERATION_CANCELED","IN_PROGRESS","UNABLE_TO_OPEN_FILE_TYPE","NULL_PRESENTER","errorCodes","Object","freeze","isErrorWithCode","error","isNewArchErrorIOS","Error"],"sourceRoot":"../../src","sources":["errors.ts"],"mappings":";;AAAA,MAAMA,kBAAkB,GAAG,oBAAoB;AAC/C,MAAMC,WAAW,GAAG,sBAAsB;AAC1C,MAAMC,wBAAwB,GAAG,0BAA0B;AAC3D,MAAMC,cAAc,GAAG,gBAAgB;;AAEvC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,UAAU,GAAGC,MAAM,CAACC,MAAM,CAAC;EACtCN,kBAAkB;EAClBC,WAAW;EACXC,wBAAwB;EACxBC;AACF,CAAC,CAAC;AAQF;AACA;AACA;AACA;AACA,OAAO,MAAMI,eAAe,GAAIC,KAAU,IAAiC;EACzE;EACA,MAAMC,iBAAiB,GAAG,OAAOD,KAAK,KAAK,QAAQ,IAAIA,KAAK,IAAI,IAAI;EACpE,OAAO,CAACA,KAAK,YAAYE,KAAK,IAAID,iBAAiB,KAAK,MAAM,IAAID,KAAK;AACzE,CAAC","ignoreList":[]}
|
package/lib/module/release.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import { NativeDocumentPicker } from "./spec/NativeDocumentPicker.js";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
* For each uri whose release was requested, the result
|
|
6
|
+
* For each uri whose release was requested, the result contains an object with the uri and a status.
|
|
7
7
|
* */
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
export interface NativeModuleError extends Error {
|
|
2
|
-
code: string;
|
|
3
|
-
}
|
|
4
1
|
/**
|
|
5
2
|
* Error codes that can be returned by the module, and are available on the `code` property of the error.
|
|
6
3
|
*
|
|
@@ -31,10 +28,16 @@ export declare const errorCodes: Readonly<{
|
|
|
31
28
|
OPERATION_CANCELED: "OPERATION_CANCELED";
|
|
32
29
|
IN_PROGRESS: "ASYNC_OP_IN_PROGRESS";
|
|
33
30
|
UNABLE_TO_OPEN_FILE_TYPE: "UNABLE_TO_OPEN_FILE_TYPE";
|
|
31
|
+
NULL_PRESENTER: "NULL_PRESENTER";
|
|
34
32
|
}>;
|
|
33
|
+
type ErrorCodes = (typeof errorCodes)[keyof typeof errorCodes];
|
|
34
|
+
export interface NativeModuleError extends Error {
|
|
35
|
+
code: ErrorCodes | (string & {});
|
|
36
|
+
}
|
|
35
37
|
/**
|
|
36
38
|
* TypeScript helper to check if an object has the `code` property.
|
|
37
39
|
* This is used to avoid `as` casting when you access the `code` property on errors returned by the module.
|
|
38
40
|
*/
|
|
39
41
|
export declare const isErrorWithCode: (error: any) => error is NativeModuleError;
|
|
42
|
+
export {};
|
|
40
43
|
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/errors.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/errors.ts"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;;;;;;;KAyBK;AACL,eAAO,MAAM,UAAU;;;;;EAKrB,CAAA;AAEF,KAAK,UAAU,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,OAAO,UAAU,CAAC,CAAA;AAE9D,MAAM,WAAW,iBAAkB,SAAQ,KAAK;IAC9C,IAAI,EAAE,UAAU,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAA;CACjC;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe,UAAW,GAAG,KAAG,KAAK,IAAI,iBAIrD,CAAA"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* For each uri whose release was requested, the result
|
|
2
|
+
* For each uri whose release was requested, the result contains an object with the uri and a status.
|
|
3
3
|
* */
|
|
4
4
|
export type ReleaseLongTermAccessResult = Array<{
|
|
5
5
|
uri: string;
|
|
@@ -11,7 +11,7 @@ export type SaveDocumentsOptions = {
|
|
|
11
11
|
sourceUris: string[];
|
|
12
12
|
/**
|
|
13
13
|
* Android-only: The MIME type of the file to be stored.
|
|
14
|
-
* It is recommended to provide this value, otherwise the system
|
|
14
|
+
* It is recommended to provide this value, otherwise the system tries to infer it from the sourceUri using ContentResolver.
|
|
15
15
|
* */
|
|
16
16
|
mimeType?: string;
|
|
17
17
|
/**
|
|
@@ -21,7 +21,7 @@ export type VirtualFileMeta = {
|
|
|
21
21
|
/**
|
|
22
22
|
* The registered extension for the given MIME type. Note that some MIME types map to multiple extensions.
|
|
23
23
|
*
|
|
24
|
-
* This call
|
|
24
|
+
* This call returns the most common extension for the given MIME type.
|
|
25
25
|
*
|
|
26
26
|
* Example: `pdf`
|
|
27
27
|
*/
|
|
@@ -62,7 +62,7 @@ export type DocumentPickerResponse = {
|
|
|
62
62
|
* */
|
|
63
63
|
size: number | null;
|
|
64
64
|
/**
|
|
65
|
-
* Android: whether the file is a virtual file (such as Google docs or sheets).
|
|
65
|
+
* Android: whether the file is a virtual file (such as Google docs or sheets). This is `null` on pre-Android 7.0 devices. On iOS, it's always `false`.
|
|
66
66
|
* */
|
|
67
67
|
isVirtual: boolean | null;
|
|
68
68
|
/**
|
|
@@ -73,7 +73,7 @@ export type DocumentPickerResponse = {
|
|
|
73
73
|
/**
|
|
74
74
|
* Android: Some document providers on Android (especially those popular in Asia, it seems)
|
|
75
75
|
* do not respect the request for limiting selectable file types.
|
|
76
|
-
* `hasRequestedType`
|
|
76
|
+
* `hasRequestedType` is false if the user picked a file that does not have one of the requested types.
|
|
77
77
|
*
|
|
78
78
|
* You need to do your own post-processing and display an error to the user if this is important to your app.
|
|
79
79
|
*
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@react-native-documents/picker",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "12.0.0",
|
|
4
4
|
"description": "A react native interface to access documents from dropbox, google drive, iCloud...",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|
|
@@ -61,7 +61,8 @@
|
|
|
61
61
|
},
|
|
62
62
|
"homepage": "https://github.com/react-native-documents/document-picker#readme",
|
|
63
63
|
"publishConfig": {
|
|
64
|
-
"access": "public"
|
|
64
|
+
"access": "public",
|
|
65
|
+
"provenance": true
|
|
65
66
|
},
|
|
66
67
|
"devDependencies": {
|
|
67
68
|
"@tsconfig/node18": "^18.2.4",
|
|
@@ -14,6 +14,7 @@ Pod::Spec.new do |s|
|
|
|
14
14
|
s.source = { :git => "https://github.com/react-native-documents/sponsors-only.git", :tag => "v#{s.version}" }
|
|
15
15
|
|
|
16
16
|
s.source_files = ["ios/**/*.{h,m,mm,swift}"]
|
|
17
|
+
s.swift_version = '6.0'
|
|
17
18
|
|
|
18
19
|
# Swift/Objective-C compatibility
|
|
19
20
|
s.pod_target_xcconfig = {
|
package/src/errors.ts
CHANGED
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
export interface NativeModuleError extends Error {
|
|
2
|
-
code: string
|
|
3
|
-
}
|
|
4
|
-
|
|
5
1
|
const OPERATION_CANCELED = 'OPERATION_CANCELED'
|
|
6
2
|
const IN_PROGRESS = 'ASYNC_OP_IN_PROGRESS'
|
|
7
3
|
const UNABLE_TO_OPEN_FILE_TYPE = 'UNABLE_TO_OPEN_FILE_TYPE'
|
|
4
|
+
const NULL_PRESENTER = 'NULL_PRESENTER'
|
|
8
5
|
|
|
9
6
|
/**
|
|
10
7
|
* Error codes that can be returned by the module, and are available on the `code` property of the error.
|
|
@@ -36,8 +33,15 @@ export const errorCodes = Object.freeze({
|
|
|
36
33
|
OPERATION_CANCELED,
|
|
37
34
|
IN_PROGRESS,
|
|
38
35
|
UNABLE_TO_OPEN_FILE_TYPE,
|
|
36
|
+
NULL_PRESENTER,
|
|
39
37
|
})
|
|
40
38
|
|
|
39
|
+
type ErrorCodes = (typeof errorCodes)[keyof typeof errorCodes]
|
|
40
|
+
|
|
41
|
+
export interface NativeModuleError extends Error {
|
|
42
|
+
code: ErrorCodes | (string & {})
|
|
43
|
+
}
|
|
44
|
+
|
|
41
45
|
/**
|
|
42
46
|
* TypeScript helper to check if an object has the `code` property.
|
|
43
47
|
* This is used to avoid `as` casting when you access the `code` property on errors returned by the module.
|
package/src/release.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { NativeDocumentPicker } from './spec/NativeDocumentPicker'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* For each uri whose release was requested, the result
|
|
4
|
+
* For each uri whose release was requested, the result contains an object with the uri and a status.
|
|
5
5
|
* */
|
|
6
6
|
export type ReleaseLongTermAccessResult = Array<
|
|
7
7
|
| {
|
package/src/saveDocuments.ts
CHANGED
|
@@ -15,7 +15,7 @@ export type SaveDocumentsOptions = {
|
|
|
15
15
|
sourceUris: string[]
|
|
16
16
|
/**
|
|
17
17
|
* Android-only: The MIME type of the file to be stored.
|
|
18
|
-
* It is recommended to provide this value, otherwise the system
|
|
18
|
+
* It is recommended to provide this value, otherwise the system tries to infer it from the sourceUri using ContentResolver.
|
|
19
19
|
* */
|
|
20
20
|
mimeType?: string
|
|
21
21
|
/**
|
package/src/types.ts
CHANGED
|
@@ -25,7 +25,7 @@ export type VirtualFileMeta = {
|
|
|
25
25
|
/**
|
|
26
26
|
* The registered extension for the given MIME type. Note that some MIME types map to multiple extensions.
|
|
27
27
|
*
|
|
28
|
-
* This call
|
|
28
|
+
* This call returns the most common extension for the given MIME type.
|
|
29
29
|
*
|
|
30
30
|
* Example: `pdf`
|
|
31
31
|
*/
|
|
@@ -68,7 +68,7 @@ export type DocumentPickerResponse = {
|
|
|
68
68
|
size: number | null
|
|
69
69
|
|
|
70
70
|
/**
|
|
71
|
-
* Android: whether the file is a virtual file (such as Google docs or sheets).
|
|
71
|
+
* Android: whether the file is a virtual file (such as Google docs or sheets). This is `null` on pre-Android 7.0 devices. On iOS, it's always `false`.
|
|
72
72
|
* */
|
|
73
73
|
isVirtual: boolean | null
|
|
74
74
|
/**
|
|
@@ -80,7 +80,7 @@ export type DocumentPickerResponse = {
|
|
|
80
80
|
/**
|
|
81
81
|
* Android: Some document providers on Android (especially those popular in Asia, it seems)
|
|
82
82
|
* do not respect the request for limiting selectable file types.
|
|
83
|
-
* `hasRequestedType`
|
|
83
|
+
* `hasRequestedType` is false if the user picked a file that does not have one of the requested types.
|
|
84
84
|
*
|
|
85
85
|
* You need to do your own post-processing and display an error to the user if this is important to your app.
|
|
86
86
|
*
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
package com.reactnativedocumentpicker
|
|
2
|
-
|
|
3
|
-
import android.content.Intent
|
|
4
|
-
import android.os.Build
|
|
5
|
-
import android.provider.DocumentsContract
|
|
6
|
-
|
|
7
|
-
object IntentFactory {
|
|
8
|
-
fun getPickIntent(options: PickOptions): Intent {
|
|
9
|
-
// TODO option for extra task on stack?
|
|
10
|
-
// reminder - flags are for granting rights to others
|
|
11
|
-
|
|
12
|
-
return Intent(options.action).apply {
|
|
13
|
-
val types = options.mimeTypes
|
|
14
|
-
|
|
15
|
-
type =
|
|
16
|
-
if (types.size > 1) {
|
|
17
|
-
putExtra(Intent.EXTRA_MIME_TYPES, types)
|
|
18
|
-
options.intentFilterTypes
|
|
19
|
-
} else {
|
|
20
|
-
types[0]
|
|
21
|
-
}
|
|
22
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O &&
|
|
23
|
-
options.initialDirectoryUrl != null
|
|
24
|
-
) {
|
|
25
|
-
// only works for ACTION_OPEN_DOCUMENT
|
|
26
|
-
// TODO must be URI
|
|
27
|
-
putExtra(DocumentsContract.EXTRA_INITIAL_URI, options.initialDirectoryUrl)
|
|
28
|
-
}
|
|
29
|
-
if (!options.allowVirtualFiles) {
|
|
30
|
-
addCategory(Intent.CATEGORY_OPENABLE)
|
|
31
|
-
}
|
|
32
|
-
putExtra(Intent.EXTRA_LOCAL_ONLY, options.localOnly)
|
|
33
|
-
putExtra(Intent.EXTRA_ALLOW_MULTIPLE, options.multiple)
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
// LICENSE: see License.md in the package root
|
|
2
|
-
package com.reactnativedocumentpicker;
|
|
3
|
-
|
|
4
|
-
import android.util.Log;
|
|
5
|
-
|
|
6
|
-
import androidx.annotation.NonNull;
|
|
7
|
-
|
|
8
|
-
import com.facebook.react.bridge.Promise;
|
|
9
|
-
|
|
10
|
-
public class PromiseWrapper {
|
|
11
|
-
|
|
12
|
-
private Promise promise;
|
|
13
|
-
private String nameOfCallInProgress;
|
|
14
|
-
public static final String ASYNC_OP_IN_PROGRESS = "ASYNC_OP_IN_PROGRESS";
|
|
15
|
-
public static final String E_DOCUMENT_PICKER_CANCELED = "OPERATION_CANCELED";
|
|
16
|
-
private final String MODULE_NAME;
|
|
17
|
-
|
|
18
|
-
public PromiseWrapper(String moduleName) {
|
|
19
|
-
MODULE_NAME = moduleName;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
public void setPromiseRejectingPrevious(Promise promise, @NonNull String fromCallsite) {
|
|
23
|
-
Promise previousPromise = this.promise;
|
|
24
|
-
if (previousPromise != null) {
|
|
25
|
-
rejectPreviousPromiseBecauseNewOneIsInProgress(previousPromise, fromCallsite);
|
|
26
|
-
}
|
|
27
|
-
this.promise = promise;
|
|
28
|
-
nameOfCallInProgress = fromCallsite;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
public boolean trySetPromiseRejectingIncoming(Promise promise, @NonNull String fromCallsite) {
|
|
32
|
-
Promise previousPromise = this.promise;
|
|
33
|
-
if (previousPromise != null) {
|
|
34
|
-
rejectNewPromiseBecauseOldOneIsInProgress(promise, fromCallsite);
|
|
35
|
-
return false;
|
|
36
|
-
}
|
|
37
|
-
this.promise = promise;
|
|
38
|
-
nameOfCallInProgress = fromCallsite;
|
|
39
|
-
return true;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
public void resolve(Object value) {
|
|
43
|
-
Promise resolver = promise;
|
|
44
|
-
if (resolver == null) {
|
|
45
|
-
Log.e(MODULE_NAME, "cannot resolve promise because it's null");
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
resetMembers();
|
|
50
|
-
resolver.resolve(value);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
public void reject(@NonNull String code, Exception e) {
|
|
54
|
-
String message = e.getLocalizedMessage() != null ? e.getLocalizedMessage() :
|
|
55
|
-
e.getMessage() != null ? e.getMessage() : "unknown error";
|
|
56
|
-
|
|
57
|
-
this.reject(code, message, e);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
public void reject(Exception e) {
|
|
61
|
-
String message = e.getLocalizedMessage() != null ? e.getLocalizedMessage() :
|
|
62
|
-
e.getMessage() != null ? e.getMessage() : "unknown error";
|
|
63
|
-
|
|
64
|
-
this.reject(nameOfCallInProgress, message, e);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
public void rejectAsUserCancelledOperation() {
|
|
68
|
-
this.reject(E_DOCUMENT_PICKER_CANCELED, "user canceled the document picker");
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
public void reject(@NonNull String code, @NonNull String message) {
|
|
72
|
-
reject(code, message, null);
|
|
73
|
-
}
|
|
74
|
-
public void reject(@NonNull String code, @NonNull String message, Exception e) {
|
|
75
|
-
Promise rejecter = promise;
|
|
76
|
-
if (rejecter == null) {
|
|
77
|
-
Log.e(MODULE_NAME, "cannot reject promise because it's null");
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
resetMembers();
|
|
82
|
-
rejecter.reject(code, message, e);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
public String getNameOfCallInProgress() {
|
|
86
|
-
return nameOfCallInProgress;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
private void resetMembers() {
|
|
90
|
-
nameOfCallInProgress = null;
|
|
91
|
-
promise = null;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
private void rejectPreviousPromiseBecauseNewOneIsInProgress(Promise promise, String requestedOperation) {
|
|
96
|
-
// TODO better message
|
|
97
|
-
promise.reject(ASYNC_OP_IN_PROGRESS, "Warning: previous promise did not settle and was overwritten. " +
|
|
98
|
-
"You've called \"" + requestedOperation + "\" while \"" + getNameOfCallInProgress() + "\" was already in progress and has not completed yet.");
|
|
99
|
-
}
|
|
100
|
-
private void rejectNewPromiseBecauseOldOneIsInProgress(Promise promise, String requestedOperation) {
|
|
101
|
-
// TODO better message
|
|
102
|
-
promise.reject(ASYNC_OP_IN_PROGRESS, "Warning: previous promise did not settle and you attempted to overwrite it. " +
|
|
103
|
-
"You've called \"" + requestedOperation + "\" while \"" + getNameOfCallInProgress() + "\" was already in progress and has not completed yet.");
|
|
104
|
-
}
|
|
105
|
-
}
|