-
-
Notifications
You must be signed in to change notification settings - Fork 437
/
index.tsx
162 lines (136 loc) · 4.54 KB
/
index.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
import { Platform, ModalPropsIOS } from 'react-native'
import invariant from 'invariant'
import type { PlatformTypes } from './fileTypes'
import { perPlatformTypes } from './fileTypes'
import { NativeDocumentPicker } from './NativeDocumentPicker'
export type DocumentPickerResponse = {
uri: string
name: string | null
copyError?: string
fileCopyUri: string | null
type: string | null
size: number | null
}
export const types = perPlatformTypes[Platform.OS]
export type DirectoryPickerResponse = {
uri: string
}
export type TransitionStyle = 'coverVertical' | 'flipHorizontal' | 'crossDissolve' | 'partialCurl'
export type DocumentPickerOptions = {
type?: string | Array<PlatformTypes | string>
mode?: 'import' | 'open'
copyTo?: 'cachesDirectory' | 'documentDirectory'
allowMultiSelection?: boolean
transitionStyle?: TransitionStyle
} & Pick<ModalPropsIOS, 'presentationStyle'>
export async function pickDirectory(
params?: Pick<DocumentPickerOptions, 'presentationStyle' | 'transitionStyle'>,
): Promise<DirectoryPickerResponse | null> {
if (Platform.OS === 'ios') {
const result = await pick({
...params,
mode: 'open',
allowMultiSelection: false,
type: ['public.folder'],
})
return { uri: result[0].uri }
} else {
return NativeDocumentPicker.pickDirectory()
}
}
export function pickSingle(opts?: DocumentPickerOptions): Promise<DocumentPickerResponse> {
const options = {
...opts,
allowMultiSelection: false,
}
return pick(options).then((results) => results[0])
}
export function pick(opts?: DocumentPickerOptions): Promise<DocumentPickerResponse[]> {
const options = {
// must be false to maintain old (v5) behavior
allowMultiSelection: false,
type: [types.allFiles],
...opts,
}
const newOpts: DoPickParams = {
presentationStyle: 'formSheet',
transitionStyle: 'coverVertical',
...options,
type: Array.isArray(options.type) ? options.type : [options.type],
}
return doPick(newOpts)
}
type DoPickParams = DocumentPickerOptions & {
type: Array<PlatformTypes | string>
allowMultiSelection: boolean
presentationStyle: NonNullable<ModalPropsIOS['presentationStyle']>
transitionStyle: TransitionStyle
}
function doPick(options: DoPickParams): Promise<DocumentPickerResponse[]> {
invariant(
!('filetype' in options),
'A `filetype` option was passed to DocumentPicker.pick, the correct option is `type`',
)
invariant(
!('types' in options),
'A `types` option was passed to DocumentPicker.pick, the correct option is `type`',
)
invariant(
options.type.every((type: unknown) => typeof type === 'string'),
`Unexpected type option in ${options.type}, did you try using a DocumentPicker.types.* that does not exist?`,
)
invariant(
options.type.length > 0,
'`type` option should not be an empty array, at least one type must be passed if the `type` option is not omitted',
)
invariant(
!options.type.includes('folder'),
'RN document picker: "folder" option was removed, use "pickDirectory()"',
)
if ('mode' in options && !['import', 'open'].includes(options.mode ?? '')) {
throw new TypeError('Invalid mode option: ' + options.mode)
}
if (
'copyTo' in options &&
!['cachesDirectory', 'documentDirectory'].includes(options.copyTo ?? '')
) {
throw new TypeError('Invalid copyTo option: ' + options.copyTo)
}
return NativeDocumentPicker.pick(options)
}
export function releaseSecureAccess(uris: Array<string>): Promise<void> {
if (Platform.OS !== 'ios') {
return Promise.resolve()
}
invariant(
Array.isArray(uris) && uris.every((uri) => typeof uri === 'string'),
`"uris" should be an array of strings, was ${uris}`,
)
return NativeDocumentPicker.releaseSecureAccess(uris)
}
const E_DOCUMENT_PICKER_CANCELED = 'DOCUMENT_PICKER_CANCELED'
const E_DOCUMENT_PICKER_IN_PROGRESS = 'ASYNC_OP_IN_PROGRESS'
export type NativeModuleErrorShape = Error & { code?: string }
export function isCancel(err: unknown): boolean {
return isErrorWithCode(err, E_DOCUMENT_PICKER_CANCELED)
}
export function isInProgress(err: unknown): boolean {
return isErrorWithCode(err, E_DOCUMENT_PICKER_IN_PROGRESS)
}
function isErrorWithCode(err: unknown, errorCode: string): boolean {
if (err && typeof err === 'object' && 'code' in err) {
const nativeModuleErrorInstance = err as NativeModuleErrorShape
return nativeModuleErrorInstance?.code === errorCode
}
return false
}
export default {
isCancel,
isInProgress,
releaseSecureAccess,
pickDirectory,
pick,
pickSingle,
types,
perPlatformTypes,
}