UNPKG

@sendbird/uikit-react-native

Version:

Sendbird UIKit for React Native: A feature-rich and customizable chat UI kit with messaging, channel management, and user authentication.

252 lines 10.1 kB
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } import { Platform } from 'react-native'; import { Logger, getFileExtension, getFileExtensionFromMime, getFileExtensionFromUri, getFileType, normalizeFileName } from '@sendbird/uikit-utils'; import SBUError from '../libs/SBUError'; import nativePermissionGranted from '../utils/nativePermissionGranted'; import normalizeFile from '../utils/normalizeFile'; import { openDocument } from './openDocument.native'; function getAndroidStoragePermissionsByAPILevel(permissionModule) { if (Platform.OS !== 'android') return []; if (Platform.Version > 32) { return []; } if (Platform.Version > 28) { return [permissionModule.PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE]; } return [permissionModule.PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE, permissionModule.PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE]; } const createNativeFileService = ({ imagePickerModule, documentPickerModule, permissionModule, mediaLibraryModule, fsModule }) => { const requiredPermissions = Platform.select({ ios: [permissionModule.PERMISSIONS.IOS.CAMERA], android: [permissionModule.PERMISSIONS.ANDROID.CAMERA], default: [] }); const optionalPermissions = Platform.select({ ios: [permissionModule.PERMISSIONS.IOS.MICROPHONE], android: [], default: [] }); const mediaLibraryPermissions = Platform.select({ ios: [permissionModule.PERMISSIONS.IOS.PHOTO_LIBRARY, permissionModule.PERMISSIONS.IOS.PHOTO_LIBRARY_ADD_ONLY], android: getAndroidStoragePermissionsByAPILevel(permissionModule), default: [] }); class NativeFileService { constructor() { _defineProperty(this, "buildDownloadPath", async options => { const dirname = Platform.select({ android: fsModule.Dirs.CacheDir, default: fsModule.Dirs.DocumentDir }); const context = { dirname, filename: options.fileName }; const extension = getFileExtension(options.fileName) || getFileExtensionFromMime(options.fileType) || getFileExtension(options.fileUrl) || (await getFileExtensionFromUri(options.fileUrl)); if (extension) context.filename = normalizeFileName(context.filename, extension); return { path: `${context.dirname}/${context.filename}`, ...context }; }); _defineProperty(this, "downloadFile", async options => { const { path, filename } = await this.buildDownloadPath(options); await fsModule.FileSystem.fetch(options.fileUrl, { path }); return { downloadedPath: path, file: { name: filename, type: getFileType(getFileExtension(path)) } }; }); } async hasCameraPermission() { const status = await permissionModule.checkMultiple(requiredPermissions); return nativePermissionGranted(status); } async requestCameraPermission() { const requiredPermissionsStatus = await permissionModule.requestMultiple(requiredPermissions); if (!nativePermissionGranted(requiredPermissionsStatus)) return false; await permissionModule.requestMultiple(optionalPermissions); return true; } async hasMediaLibraryPermission() { const status = await permissionModule.checkMultiple(mediaLibraryPermissions); return nativePermissionGranted(status); } async requestMediaLibraryPermission() { const status = await permissionModule.requestMultiple(mediaLibraryPermissions); return nativePermissionGranted(status); } async openCamera(options) { var _response$assets; const hasPermission = await this.hasCameraPermission(); if (!hasPermission) { const granted = await this.requestCameraPermission(); if (!granted) { var _options$onOpenFailur; options === null || options === void 0 || (_options$onOpenFailur = options.onOpenFailure) === null || _options$onOpenFailur === void 0 || _options$onOpenFailur.call(options, SBUError.PERMISSIONS_DENIED); return null; } } const response = await imagePickerModule.launchCamera({ presentationStyle: 'fullScreen', cameraType: (options === null || options === void 0 ? void 0 : options.cameraType) ?? 'back', mediaType: (() => { switch (options === null || options === void 0 ? void 0 : options.mediaType) { case 'photo': return 'photo'; case 'video': return 'video'; case 'all': return 'mixed'; default: return 'photo'; } })() }); if (response.didCancel) return null; if (response.errorCode === 'camera_unavailable') { var _options$onOpenFailur2; options === null || options === void 0 || (_options$onOpenFailur2 = options.onOpenFailure) === null || _options$onOpenFailur2 === void 0 || _options$onOpenFailur2.call(options, SBUError.DEVICE_UNAVAILABLE, new Error(response.errorMessage)); return null; } const { fileName: name, fileSize: size, type, uri } = ((_response$assets = response.assets) === null || _response$assets === void 0 ? void 0 : _response$assets[0]) ?? {}; return normalizeFile({ uri, size, name, type }); } async openMediaLibrary(options) { /** * NOTE: options.selectionLimit {@link https://github.com/react-native-image-picker/react-native-image-picker#options} * We do not support 0 (any number of files) **/ const selectionLimit = (options === null || options === void 0 ? void 0 : options.selectionLimit) || 1; const hasPermission = await this.hasMediaLibraryPermission(); if (!hasPermission) { const granted = await this.requestMediaLibraryPermission(); if (!granted) { var _options$onOpenFailur3; options === null || options === void 0 || (_options$onOpenFailur3 = options.onOpenFailure) === null || _options$onOpenFailur3 === void 0 || _options$onOpenFailur3.call(options, SBUError.PERMISSIONS_DENIED); return null; } } const response = await imagePickerModule.launchImageLibrary({ presentationStyle: 'fullScreen', selectionLimit, mediaType: (() => { switch (options === null || options === void 0 ? void 0 : options.mediaType) { case 'photo': return 'photo'; case 'video': return 'video'; case 'all': return 'mixed'; default: return 'photo'; } })() }); if (response.didCancel) return null; if (response.errorCode === 'camera_unavailable') { var _options$onOpenFailur4; options === null || options === void 0 || (_options$onOpenFailur4 = options.onOpenFailure) === null || _options$onOpenFailur4 === void 0 || _options$onOpenFailur4.call(options, SBUError.DEVICE_UNAVAILABLE, new Error(response.errorMessage)); return null; } return Promise.all((response.assets || []).slice(0, selectionLimit).map(({ fileName: name, fileSize: size, type, uri }) => normalizeFile({ uri, size, name, type }))); } async openDocument(options) { return await openDocument(documentPickerModule, options); } async save(options) { const hasPermission = await this.hasMediaLibraryPermission(); if (!hasPermission) { const granted = await this.requestMediaLibraryPermission(); if (!granted) throw new Error('Permission not granted'); } const { downloadedPath, file } = await this.downloadFile(options); if (Platform.OS === 'ios') { if (file.type === 'image' || file.type === 'video') { const mediaTypeMap = { 'image': 'photo', 'video': 'video' }; const mediaType = mediaTypeMap[file.type]; await mediaLibraryModule.save(downloadedPath, { type: mediaType }); } } if (Platform.OS === 'android') { const externalDirMap = { 'file': 'downloads', 'audio': 'audio', 'image': 'images', 'video': 'video' }; const externalDir = externalDirMap[file.type]; await fsModule.FileSystem.cpExternal(downloadedPath, file.name, externalDir).catch(() => { Logger.error('Failed to save file to external storage. Retry saving to downloads directory instead.'); return fsModule.FileSystem.cpExternal(downloadedPath, file.name, 'downloads'); }); } return downloadedPath; } createRecordFilePath(customExtension = 'm4a') { const filename = `record-${Date.now()}.${customExtension}`; const path = `${fsModule.Dirs.CacheDir}/${filename}`; return Platform.select({ ios: { uri: path, recordFilePath: filename }, android: { uri: path.startsWith('file://') ? path : 'file://' + path, recordFilePath: path }, default: { uri: path, recordFilePath: path } }); } } return new NativeFileService(); }; export default createNativeFileService; //# sourceMappingURL=createFileService.native.js.map