UNPKG

@react-native-ohos/react-native-document-picker

Version:

A react native interface to access documents from dropbox, google drive, iCloud...

181 lines (152 loc) 5.49 kB
/* * Copyright (c) 2024 Huawei Device Co., Ltd. All rights reserved * Use of this source code is governed by a MIT license that can be * found in the LICENSE file */ import { Platform, ModalPropsIOS } from 'react-native' import invariant from 'invariant' import type { PlatformTypes, SupportedPlatforms } 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<OS extends SupportedPlatforms> = { type?: | string | PlatformTypes[OS][keyof PlatformTypes[OS]] | Array<PlatformTypes[OS][keyof PlatformTypes[OS]] | string> mode?: 'import' | 'open' copyTo?: 'cachesDirectory' | 'documentDirectory' allowMultiSelection?: boolean transitionStyle?: TransitionStyle } & Pick<ModalPropsIOS, 'presentationStyle'> export async function pickDirectory<OS extends SupportedPlatforms>( params?: Pick<DocumentPickerOptions<OS>, '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<OS extends SupportedPlatforms>( opts?: DocumentPickerOptions<OS>, ): Promise<DocumentPickerResponse> { const options = { ...opts, allowMultiSelection: false, } return pick(options).then((results) => results[0]) } export function pick<OS extends SupportedPlatforms>( opts?: DocumentPickerOptions<OS>, ): Promise<DocumentPickerResponse[]> { const options = { // must be false to maintain old (v5) behavior allowMultiSelection: false, type: [types.allFiles], ...opts, } const newOpts: DoPickParams<OS> = { presentationStyle: 'formSheet', transitionStyle: 'coverVertical', ...options, type: Array.isArray(options.type) ? options.type : [options.type], } return doPick(newOpts) } type DoPickParams<OS extends SupportedPlatforms> = DocumentPickerOptions<OS> & { type: Array<PlatformTypes[OS][keyof PlatformTypes[OS]] | string> allowMultiSelection: boolean presentationStyle: NonNullable<ModalPropsIOS['presentationStyle']> transitionStyle: TransitionStyle } function doPick<OS extends SupportedPlatforms>( options: DoPickParams<OS>, ): 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> { return Promise.resolve() } 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 isErrorWithMessage(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 } function isErrorWithMessage(err: unknown, errorCode: string): boolean { if (err && typeof err === 'object' && 'message' in err) { const nativeModuleErrorInstance = err as NativeModuleErrorShape return nativeModuleErrorInstance?.message === errorCode } return false } const exportObj = { isCancel, isInProgress, releaseSecureAccess, pickDirectory, pick, pickSingle, types, perPlatformTypes, }; export type DocPickerModuleType = typeof exportObj; export default exportObj;