@sendbird/uikit-react-native 2.4.0 → 2.4.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/lib/commonjs/components/ChannelInput/SendInput.js +3 -3
- package/lib/commonjs/components/ChannelInput/SendInput.js.map +1 -1
- package/lib/commonjs/containers/SendbirdUIKitContainer.js +19 -1
- package/lib/commonjs/containers/SendbirdUIKitContainer.js.map +1 -1
- package/lib/commonjs/platform/createFileService.expo.js +6 -14
- package/lib/commonjs/platform/createFileService.expo.js.map +1 -1
- package/lib/commonjs/platform/createFileService.native.js +65 -37
- package/lib/commonjs/platform/createFileService.native.js.map +1 -1
- package/lib/commonjs/utils/normalizeFile.js +41 -0
- package/lib/commonjs/utils/normalizeFile.js.map +1 -0
- package/lib/commonjs/version.js +1 -1
- package/lib/commonjs/version.js.map +1 -1
- package/lib/module/components/ChannelInput/SendInput.js +3 -3
- package/lib/module/components/ChannelInput/SendInput.js.map +1 -1
- package/lib/module/containers/SendbirdUIKitContainer.js +20 -2
- package/lib/module/containers/SendbirdUIKitContainer.js.map +1 -1
- package/lib/module/platform/createFileService.expo.js +7 -15
- package/lib/module/platform/createFileService.expo.js.map +1 -1
- package/lib/module/platform/createFileService.native.js +64 -36
- package/lib/module/platform/createFileService.native.js.map +1 -1
- package/lib/module/utils/normalizeFile.js +33 -0
- package/lib/module/utils/normalizeFile.js.map +1 -0
- package/lib/module/version.js +1 -1
- package/lib/module/version.js.map +1 -1
- package/lib/typescript/src/containers/SendbirdUIKitContainer.d.ts +1 -1
- package/lib/typescript/src/utils/normalizeFile.d.ts +4 -0
- package/lib/typescript/src/version.d.ts +1 -1
- package/package.json +5 -5
- package/src/components/ChannelInput/SendInput.tsx +3 -3
- package/src/containers/SendbirdUIKitContainer.tsx +20 -1
- package/src/platform/createFileService.expo.ts +5 -10
- package/src/platform/createFileService.native.ts +53 -28
- package/src/utils/normalizeFile.ts +32 -0
- package/src/version.ts +1 -1
- package/lib/commonjs/utils/fileTypeGuard.js +0 -26
- package/lib/commonjs/utils/fileTypeGuard.js.map +0 -1
- package/lib/module/utils/fileTypeGuard.js +0 -18
- package/lib/module/utils/fileTypeGuard.js.map +0 -1
- package/lib/typescript/src/utils/fileTypeGuard.d.ts +0 -4
- package/src/utils/fileTypeGuard.ts +0 -10
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
2
|
+
|
|
1
3
|
import { Platform } from 'react-native';
|
|
2
|
-
import { getFileExtension, getFileType, normalizeFileName } from '@sendbird/uikit-utils';
|
|
4
|
+
import { getFileExtension, getFileExtensionFromMime, getFileExtensionFromUri, getFileType, normalizeFileName } from '@sendbird/uikit-utils';
|
|
3
5
|
import SBUError from '../libs/SBUError';
|
|
4
|
-
import fileTypeGuard from '../utils/fileTypeGuard';
|
|
5
6
|
import nativePermissionGranted from '../utils/nativePermissionGranted';
|
|
7
|
+
import normalizeFile from '../utils/normalizeFile';
|
|
6
8
|
|
|
7
9
|
function getAndroidStoragePermissionsByAPILevel(permissionModule) {
|
|
8
10
|
if (Platform.OS !== 'android') return [];
|
|
@@ -38,6 +40,42 @@ const createNativeFileService = _ref => {
|
|
|
38
40
|
});
|
|
39
41
|
|
|
40
42
|
class NativeFileService {
|
|
43
|
+
constructor() {
|
|
44
|
+
_defineProperty(this, "buildDownloadPath", async options => {
|
|
45
|
+
const dirname = Platform.select({
|
|
46
|
+
android: fsModule.Dirs.CacheDir,
|
|
47
|
+
default: fsModule.Dirs.DocumentDir
|
|
48
|
+
});
|
|
49
|
+
const context = {
|
|
50
|
+
dirname,
|
|
51
|
+
filename: options.fileName
|
|
52
|
+
};
|
|
53
|
+
const extension = getFileExtension(options.fileName) || getFileExtensionFromMime(options.fileType) || getFileExtension(options.fileUrl) || (await getFileExtensionFromUri(options.fileUrl));
|
|
54
|
+
if (extension) context.filename = normalizeFileName(context.filename, extension);
|
|
55
|
+
return {
|
|
56
|
+
path: `${context.dirname}/${context.filename}`,
|
|
57
|
+
...context
|
|
58
|
+
};
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
_defineProperty(this, "downloadFile", async options => {
|
|
62
|
+
const {
|
|
63
|
+
path,
|
|
64
|
+
filename
|
|
65
|
+
} = await this.buildDownloadPath(options);
|
|
66
|
+
await fsModule.FileSystem.fetch(options.fileUrl, {
|
|
67
|
+
path
|
|
68
|
+
});
|
|
69
|
+
return {
|
|
70
|
+
downloadedPath: path,
|
|
71
|
+
file: {
|
|
72
|
+
name: filename,
|
|
73
|
+
type: getFileType(getFileExtension(path))
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
41
79
|
async hasCameraPermission() {
|
|
42
80
|
const status = await permissionModule.checkMultiple(cameraPermissions);
|
|
43
81
|
return nativePermissionGranted(status);
|
|
@@ -113,7 +151,7 @@ const createNativeFileService = _ref => {
|
|
|
113
151
|
type,
|
|
114
152
|
uri
|
|
115
153
|
} = ((_response$assets = response.assets) === null || _response$assets === void 0 ? void 0 : _response$assets[0]) ?? {};
|
|
116
|
-
return
|
|
154
|
+
return normalizeFile({
|
|
117
155
|
uri,
|
|
118
156
|
size,
|
|
119
157
|
name,
|
|
@@ -168,20 +206,20 @@ const createNativeFileService = _ref => {
|
|
|
168
206
|
return null;
|
|
169
207
|
}
|
|
170
208
|
|
|
171
|
-
return (response.assets || []).slice(0, selectionLimit).map(_ref2 => {
|
|
209
|
+
return Promise.all((response.assets || []).slice(0, selectionLimit).map(_ref2 => {
|
|
172
210
|
let {
|
|
173
211
|
fileName: name,
|
|
174
212
|
fileSize: size,
|
|
175
213
|
type,
|
|
176
214
|
uri
|
|
177
215
|
} = _ref2;
|
|
178
|
-
return
|
|
216
|
+
return normalizeFile({
|
|
179
217
|
uri,
|
|
180
218
|
size,
|
|
181
219
|
name,
|
|
182
220
|
type
|
|
183
221
|
});
|
|
184
|
-
});
|
|
222
|
+
}));
|
|
185
223
|
}
|
|
186
224
|
|
|
187
225
|
async openDocument(options) {
|
|
@@ -192,7 +230,7 @@ const createNativeFileService = _ref => {
|
|
|
192
230
|
name,
|
|
193
231
|
type
|
|
194
232
|
} = await documentPickerModule.pickSingle();
|
|
195
|
-
return
|
|
233
|
+
return normalizeFile({
|
|
196
234
|
uri,
|
|
197
235
|
size,
|
|
198
236
|
name,
|
|
@@ -217,46 +255,36 @@ const createNativeFileService = _ref => {
|
|
|
217
255
|
if (!granted) throw new Error('Permission not granted');
|
|
218
256
|
}
|
|
219
257
|
|
|
220
|
-
const
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
258
|
+
const {
|
|
259
|
+
downloadedPath,
|
|
260
|
+
file
|
|
261
|
+
} = await this.downloadFile(options);
|
|
262
|
+
|
|
263
|
+
if (Platform.OS === 'ios') {
|
|
264
|
+
if (file.type === 'image' || file.type === 'video') {
|
|
265
|
+
const mediaTypeMap = {
|
|
266
|
+
'image': 'photo',
|
|
267
|
+
'video': 'video'
|
|
268
|
+
};
|
|
269
|
+
const mediaType = mediaTypeMap[file.type];
|
|
270
|
+
await mediaLibraryModule.save(downloadedPath, {
|
|
271
|
+
type: mediaType
|
|
272
|
+
});
|
|
231
273
|
}
|
|
232
274
|
}
|
|
233
275
|
|
|
234
|
-
await fsModule.FileSystem.fetch(options.fileUrl, {
|
|
235
|
-
path: downloadPath
|
|
236
|
-
});
|
|
237
|
-
const fileType = getFileType(getFileExtension(options.fileUrl));
|
|
238
|
-
|
|
239
|
-
if (Platform.OS === 'ios' && (fileType === 'image' || fileType === 'video')) {
|
|
240
|
-
const type = {
|
|
241
|
-
'image': 'photo',
|
|
242
|
-
'video': 'video'
|
|
243
|
-
}[fileType];
|
|
244
|
-
await mediaLibraryModule.save(downloadPath, {
|
|
245
|
-
type
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
|
|
249
276
|
if (Platform.OS === 'android') {
|
|
250
|
-
const
|
|
277
|
+
const externalDirMap = {
|
|
251
278
|
'file': 'downloads',
|
|
252
279
|
'audio': 'audio',
|
|
253
280
|
'image': 'images',
|
|
254
281
|
'video': 'video'
|
|
255
282
|
};
|
|
256
|
-
|
|
283
|
+
const externalDir = externalDirMap[file.type];
|
|
284
|
+
await fsModule.FileSystem.cpExternal(downloadedPath, file.name, externalDir);
|
|
257
285
|
}
|
|
258
286
|
|
|
259
|
-
return
|
|
287
|
+
return downloadedPath;
|
|
260
288
|
}
|
|
261
289
|
|
|
262
290
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["Platform","getFileExtension","getFileType","normalizeFileName","SBUError","fileTypeGuard","nativePermissionGranted","getAndroidStoragePermissionsByAPILevel","permissionModule","OS","Version","PERMISSIONS","ANDROID","READ_MEDIA_AUDIO","READ_MEDIA_IMAGES","READ_MEDIA_VIDEO","READ_EXTERNAL_STORAGE","WRITE_EXTERNAL_STORAGE","createNativeFileService","imagePickerModule","documentPickerModule","mediaLibraryModule","fsModule","cameraPermissions","select","ios","IOS","CAMERA","MICROPHONE","android","default","mediaLibraryPermissions","MEDIA_LIBRARY","PHOTO_LIBRARY","NativeFileService","hasCameraPermission","status","checkMultiple","requestCameraPermission","requestMultiple","hasMediaLibraryPermission","__DEV__","requestMediaLibraryPermission","openCamera","options","hasPermission","granted","onOpenFailure","PERMISSIONS_DENIED","response","launchCamera","presentationStyle","cameraType","mediaType","didCancel","errorCode","DEVICE_UNAVAILABLE","Error","errorMessage","fileName","name","fileSize","size","type","uri","assets","openMediaLibrary","selectionLimit","launchImageLibrary","slice","map","openDocument","pickSingle","e","isCancel","isInProgress","UNKNOWN","save","basePath","Dirs","CacheDir","DocumentDir","downloadPath","extensionFromUrl","fileUrl","match","FileSystem","fetch","path","fileType","dirType","cpExternal"],"sources":["createFileService.native.ts"],"sourcesContent":["import type { CameraRoll } from '@react-native-camera-roll/camera-roll';\nimport { Platform } from 'react-native';\nimport type * as DocumentPicker from 'react-native-document-picker';\nimport type * as FileAccess from 'react-native-file-access';\nimport type * as ImagePicker from 'react-native-image-picker';\nimport type * as Permissions from 'react-native-permissions';\nimport type { Permission } from 'react-native-permissions';\n\nimport { getFileExtension, getFileType, normalizeFileName } from '@sendbird/uikit-utils';\n\nimport SBUError from '../libs/SBUError';\nimport fileTypeGuard from '../utils/fileTypeGuard';\nimport nativePermissionGranted from '../utils/nativePermissionGranted';\nimport type {\n FilePickerResponse,\n FileServiceInterface,\n OpenCameraOptions,\n OpenDocumentOptions,\n OpenMediaLibraryOptions,\n SaveOptions,\n} from './types';\n\nfunction getAndroidStoragePermissionsByAPILevel(permissionModule: typeof Permissions): Permission[] {\n if (Platform.OS !== 'android') return [];\n\n if (Platform.Version > 32) {\n return [\n permissionModule.PERMISSIONS.ANDROID.READ_MEDIA_AUDIO,\n permissionModule.PERMISSIONS.ANDROID.READ_MEDIA_IMAGES,\n permissionModule.PERMISSIONS.ANDROID.READ_MEDIA_VIDEO,\n ];\n }\n\n if (Platform.Version > 28) {\n return [permissionModule.PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE];\n }\n\n return [\n permissionModule.PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE,\n permissionModule.PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE,\n ];\n}\n\nconst createNativeFileService = ({\n imagePickerModule,\n documentPickerModule,\n permissionModule,\n mediaLibraryModule,\n fsModule,\n}: {\n imagePickerModule: typeof ImagePicker;\n documentPickerModule: typeof DocumentPicker;\n permissionModule: typeof Permissions;\n mediaLibraryModule: typeof CameraRoll;\n fsModule: typeof FileAccess;\n}): FileServiceInterface => {\n const cameraPermissions: Permission[] = Platform.select({\n ios: [permissionModule.PERMISSIONS.IOS.CAMERA, permissionModule.PERMISSIONS.IOS.MICROPHONE],\n android: [permissionModule.PERMISSIONS.ANDROID.CAMERA],\n default: [],\n });\n const mediaLibraryPermissions: Permission[] = Platform.select({\n ios: [permissionModule.PERMISSIONS.IOS.MEDIA_LIBRARY, permissionModule.PERMISSIONS.IOS.PHOTO_LIBRARY],\n android: getAndroidStoragePermissionsByAPILevel(permissionModule),\n default: [],\n });\n\n class NativeFileService implements FileServiceInterface {\n async hasCameraPermission(): Promise<boolean> {\n const status = await permissionModule.checkMultiple(cameraPermissions);\n return nativePermissionGranted(status);\n }\n async requestCameraPermission(): Promise<boolean> {\n const status = await permissionModule.requestMultiple(cameraPermissions);\n return nativePermissionGranted(status);\n }\n async hasMediaLibraryPermission(): Promise<boolean> {\n const status = await permissionModule.checkMultiple(mediaLibraryPermissions);\n if (\n __DEV__ &&\n Platform.OS === 'ios' &&\n status['ios.permission.MEDIA_LIBRARY'] === 'unavailable' &&\n status['ios.permission.PHOTO_LIBRARY'] === 'granted'\n ) {\n return true;\n }\n return nativePermissionGranted(status);\n }\n async requestMediaLibraryPermission(): Promise<boolean> {\n const status = await permissionModule.requestMultiple(mediaLibraryPermissions);\n return nativePermissionGranted(status);\n }\n\n async openCamera(options?: OpenCameraOptions): Promise<FilePickerResponse> {\n const hasPermission = await this.hasCameraPermission();\n if (!hasPermission) {\n const granted = await this.requestCameraPermission();\n if (!granted) {\n options?.onOpenFailure?.(SBUError.PERMISSIONS_DENIED);\n return null;\n }\n }\n\n const response = await imagePickerModule.launchCamera({\n presentationStyle: 'fullScreen',\n cameraType: options?.cameraType ?? 'back',\n mediaType: (() => {\n switch (options?.mediaType) {\n case 'photo':\n return 'photo';\n case 'video':\n return 'video';\n case 'all':\n return 'mixed';\n default:\n return 'photo';\n }\n })(),\n });\n if (response.didCancel) return null;\n if (response.errorCode === 'camera_unavailable') {\n options?.onOpenFailure?.(SBUError.DEVICE_UNAVAILABLE, new Error(response.errorMessage));\n return null;\n }\n\n const { fileName: name, fileSize: size, type, uri } = response.assets?.[0] ?? {};\n return fileTypeGuard({ uri, size, name, type });\n }\n async openMediaLibrary(options?: OpenMediaLibraryOptions): Promise<FilePickerResponse[] | null> {\n /**\n * NOTE: options.selectionLimit {@link https://github.com/react-native-image-picker/react-native-image-picker#options}\n * We do not support 0 (any number of files)\n **/\n const selectionLimit = options?.selectionLimit || 1;\n const hasPermission = await this.hasMediaLibraryPermission();\n if (!hasPermission) {\n const granted = await this.requestMediaLibraryPermission();\n if (!granted) {\n options?.onOpenFailure?.(SBUError.PERMISSIONS_DENIED);\n return null;\n }\n }\n\n const response = await imagePickerModule.launchImageLibrary({\n presentationStyle: 'fullScreen',\n selectionLimit,\n mediaType: (() => {\n switch (options?.mediaType) {\n case 'photo':\n return 'photo';\n case 'video':\n return 'video';\n case 'all':\n return 'mixed';\n default:\n return 'photo';\n }\n })(),\n });\n if (response.didCancel) return null;\n if (response.errorCode === 'camera_unavailable') {\n options?.onOpenFailure?.(SBUError.DEVICE_UNAVAILABLE, new Error(response.errorMessage));\n return null;\n }\n\n return (response.assets || [])\n .slice(0, selectionLimit)\n .map(({ fileName: name, fileSize: size, type, uri }) => fileTypeGuard({ uri, size, name, type }));\n }\n async openDocument(options?: OpenDocumentOptions): Promise<FilePickerResponse> {\n try {\n const { uri, size, name, type } = await documentPickerModule.pickSingle();\n return fileTypeGuard({ uri, size, name, type });\n } catch (e) {\n if (!documentPickerModule.isCancel(e) && documentPickerModule.isInProgress(e)) {\n options?.onOpenFailure?.(SBUError.UNKNOWN, e);\n }\n return null;\n }\n }\n async save(options: SaveOptions): Promise<string> {\n const hasPermission = await this.hasMediaLibraryPermission();\n if (!hasPermission) {\n const granted = await this.requestMediaLibraryPermission();\n if (!granted) throw new Error('Permission not granted');\n }\n\n const basePath = Platform.select({ android: fsModule.Dirs.CacheDir, default: fsModule.Dirs.DocumentDir });\n let downloadPath = `${basePath}/${options.fileName}`;\n if (!getFileExtension(options.fileName)) {\n const extensionFromUrl = getFileExtension(options.fileUrl);\n if (getFileType(extensionFromUrl).match(/image|video/)) {\n downloadPath += extensionFromUrl;\n }\n }\n\n await fsModule.FileSystem.fetch(options.fileUrl, { path: downloadPath });\n const fileType = getFileType(getFileExtension(options.fileUrl));\n\n if (Platform.OS === 'ios' && (fileType === 'image' || fileType === 'video')) {\n const type = ({ 'image': 'photo', 'video': 'video' } as const)[fileType];\n await mediaLibraryModule.save(downloadPath, { type });\n }\n\n if (Platform.OS === 'android') {\n const dirType = { 'file': 'downloads', 'audio': 'audio', 'image': 'images', 'video': 'video' } as const;\n await fsModule.FileSystem.cpExternal(\n downloadPath,\n normalizeFileName(options.fileName, getFileExtension(options.fileUrl)),\n dirType[fileType],\n );\n }\n return downloadPath;\n }\n }\n\n return new NativeFileService();\n};\n\nexport default createNativeFileService;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["Platform","getFileExtension","getFileExtensionFromMime","getFileExtensionFromUri","getFileType","normalizeFileName","SBUError","nativePermissionGranted","normalizeFile","getAndroidStoragePermissionsByAPILevel","permissionModule","OS","Version","PERMISSIONS","ANDROID","READ_MEDIA_AUDIO","READ_MEDIA_IMAGES","READ_MEDIA_VIDEO","READ_EXTERNAL_STORAGE","WRITE_EXTERNAL_STORAGE","createNativeFileService","imagePickerModule","documentPickerModule","mediaLibraryModule","fsModule","cameraPermissions","select","ios","IOS","CAMERA","MICROPHONE","android","default","mediaLibraryPermissions","MEDIA_LIBRARY","PHOTO_LIBRARY","NativeFileService","options","dirname","Dirs","CacheDir","DocumentDir","context","filename","fileName","extension","fileType","fileUrl","path","buildDownloadPath","FileSystem","fetch","downloadedPath","file","name","type","hasCameraPermission","status","checkMultiple","requestCameraPermission","requestMultiple","hasMediaLibraryPermission","__DEV__","requestMediaLibraryPermission","openCamera","hasPermission","granted","onOpenFailure","PERMISSIONS_DENIED","response","launchCamera","presentationStyle","cameraType","mediaType","didCancel","errorCode","DEVICE_UNAVAILABLE","Error","errorMessage","fileSize","size","uri","assets","openMediaLibrary","selectionLimit","launchImageLibrary","Promise","all","slice","map","openDocument","pickSingle","e","isCancel","isInProgress","UNKNOWN","save","downloadFile","mediaTypeMap","externalDirMap","externalDir","cpExternal"],"sources":["createFileService.native.ts"],"sourcesContent":["import type { CameraRoll } from '@react-native-camera-roll/camera-roll';\nimport { Platform } from 'react-native';\nimport type * as DocumentPicker from 'react-native-document-picker';\nimport type * as FileAccess from 'react-native-file-access';\nimport type * as ImagePicker from 'react-native-image-picker';\nimport type * as Permissions from 'react-native-permissions';\nimport type { Permission } from 'react-native-permissions';\n\nimport {\n getFileExtension,\n getFileExtensionFromMime,\n getFileExtensionFromUri,\n getFileType,\n normalizeFileName,\n} from '@sendbird/uikit-utils';\n\nimport SBUError from '../libs/SBUError';\nimport nativePermissionGranted from '../utils/nativePermissionGranted';\nimport normalizeFile from '../utils/normalizeFile';\nimport type {\n FilePickerResponse,\n FileServiceInterface,\n OpenCameraOptions,\n OpenDocumentOptions,\n OpenMediaLibraryOptions,\n SaveOptions,\n} from './types';\n\nfunction getAndroidStoragePermissionsByAPILevel(permissionModule: typeof Permissions): Permission[] {\n if (Platform.OS !== 'android') return [];\n\n if (Platform.Version > 32) {\n return [\n permissionModule.PERMISSIONS.ANDROID.READ_MEDIA_AUDIO,\n permissionModule.PERMISSIONS.ANDROID.READ_MEDIA_IMAGES,\n permissionModule.PERMISSIONS.ANDROID.READ_MEDIA_VIDEO,\n ];\n }\n\n if (Platform.Version > 28) {\n return [permissionModule.PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE];\n }\n\n return [\n permissionModule.PERMISSIONS.ANDROID.WRITE_EXTERNAL_STORAGE,\n permissionModule.PERMISSIONS.ANDROID.READ_EXTERNAL_STORAGE,\n ];\n}\n\nconst createNativeFileService = ({\n imagePickerModule,\n documentPickerModule,\n permissionModule,\n mediaLibraryModule,\n fsModule,\n}: {\n imagePickerModule: typeof ImagePicker;\n documentPickerModule: typeof DocumentPicker;\n permissionModule: typeof Permissions;\n mediaLibraryModule: typeof CameraRoll;\n fsModule: typeof FileAccess;\n}): FileServiceInterface => {\n const cameraPermissions: Permission[] = Platform.select({\n ios: [permissionModule.PERMISSIONS.IOS.CAMERA, permissionModule.PERMISSIONS.IOS.MICROPHONE],\n android: [permissionModule.PERMISSIONS.ANDROID.CAMERA],\n default: [],\n });\n const mediaLibraryPermissions: Permission[] = Platform.select({\n ios: [permissionModule.PERMISSIONS.IOS.MEDIA_LIBRARY, permissionModule.PERMISSIONS.IOS.PHOTO_LIBRARY],\n android: getAndroidStoragePermissionsByAPILevel(permissionModule),\n default: [],\n });\n\n class NativeFileService implements FileServiceInterface {\n async hasCameraPermission(): Promise<boolean> {\n const status = await permissionModule.checkMultiple(cameraPermissions);\n return nativePermissionGranted(status);\n }\n async requestCameraPermission(): Promise<boolean> {\n const status = await permissionModule.requestMultiple(cameraPermissions);\n return nativePermissionGranted(status);\n }\n async hasMediaLibraryPermission(): Promise<boolean> {\n const status = await permissionModule.checkMultiple(mediaLibraryPermissions);\n if (\n __DEV__ &&\n Platform.OS === 'ios' &&\n status['ios.permission.MEDIA_LIBRARY'] === 'unavailable' &&\n status['ios.permission.PHOTO_LIBRARY'] === 'granted'\n ) {\n return true;\n }\n return nativePermissionGranted(status);\n }\n async requestMediaLibraryPermission(): Promise<boolean> {\n const status = await permissionModule.requestMultiple(mediaLibraryPermissions);\n return nativePermissionGranted(status);\n }\n\n async openCamera(options?: OpenCameraOptions): Promise<FilePickerResponse> {\n const hasPermission = await this.hasCameraPermission();\n if (!hasPermission) {\n const granted = await this.requestCameraPermission();\n if (!granted) {\n options?.onOpenFailure?.(SBUError.PERMISSIONS_DENIED);\n return null;\n }\n }\n\n const response = await imagePickerModule.launchCamera({\n presentationStyle: 'fullScreen',\n cameraType: options?.cameraType ?? 'back',\n mediaType: (() => {\n switch (options?.mediaType) {\n case 'photo':\n return 'photo';\n case 'video':\n return 'video';\n case 'all':\n return 'mixed';\n default:\n return 'photo';\n }\n })(),\n });\n if (response.didCancel) return null;\n if (response.errorCode === 'camera_unavailable') {\n options?.onOpenFailure?.(SBUError.DEVICE_UNAVAILABLE, new Error(response.errorMessage));\n return null;\n }\n\n const { fileName: name, fileSize: size, type, uri } = response.assets?.[0] ?? {};\n return normalizeFile({ uri, size, name, type });\n }\n async openMediaLibrary(options?: OpenMediaLibraryOptions): Promise<FilePickerResponse[] | null> {\n /**\n * NOTE: options.selectionLimit {@link https://github.com/react-native-image-picker/react-native-image-picker#options}\n * We do not support 0 (any number of files)\n **/\n const selectionLimit = options?.selectionLimit || 1;\n const hasPermission = await this.hasMediaLibraryPermission();\n if (!hasPermission) {\n const granted = await this.requestMediaLibraryPermission();\n if (!granted) {\n options?.onOpenFailure?.(SBUError.PERMISSIONS_DENIED);\n return null;\n }\n }\n\n const response = await imagePickerModule.launchImageLibrary({\n presentationStyle: 'fullScreen',\n selectionLimit,\n mediaType: (() => {\n switch (options?.mediaType) {\n case 'photo':\n return 'photo';\n case 'video':\n return 'video';\n case 'all':\n return 'mixed';\n default:\n return 'photo';\n }\n })(),\n });\n if (response.didCancel) return null;\n if (response.errorCode === 'camera_unavailable') {\n options?.onOpenFailure?.(SBUError.DEVICE_UNAVAILABLE, new Error(response.errorMessage));\n return null;\n }\n\n return Promise.all(\n (response.assets || [])\n .slice(0, selectionLimit)\n .map(({ fileName: name, fileSize: size, type, uri }) => normalizeFile({ uri, size, name, type })),\n );\n }\n async openDocument(options?: OpenDocumentOptions): Promise<FilePickerResponse> {\n try {\n const { uri, size, name, type } = await documentPickerModule.pickSingle();\n return normalizeFile({ uri, size, name, type });\n } catch (e) {\n if (!documentPickerModule.isCancel(e) && documentPickerModule.isInProgress(e)) {\n options?.onOpenFailure?.(SBUError.UNKNOWN, e);\n }\n return null;\n }\n }\n async save(options: SaveOptions): Promise<string> {\n const hasPermission = await this.hasMediaLibraryPermission();\n if (!hasPermission) {\n const granted = await this.requestMediaLibraryPermission();\n if (!granted) throw new Error('Permission not granted');\n }\n\n const { downloadedPath, file } = await this.downloadFile(options);\n\n if (Platform.OS === 'ios') {\n if (file.type === 'image' || file.type === 'video') {\n const mediaTypeMap = { 'image': 'photo', 'video': 'video' } as const;\n const mediaType = mediaTypeMap[file.type];\n await mediaLibraryModule.save(downloadedPath, { type: mediaType });\n }\n }\n\n if (Platform.OS === 'android') {\n const externalDirMap = { 'file': 'downloads', 'audio': 'audio', 'image': 'images', 'video': 'video' } as const;\n const externalDir = externalDirMap[file.type];\n await fsModule.FileSystem.cpExternal(downloadedPath, file.name, externalDir);\n }\n\n return downloadedPath;\n }\n\n private buildDownloadPath = async (options: SaveOptions) => {\n const dirname = Platform.select({ android: fsModule.Dirs.CacheDir, default: fsModule.Dirs.DocumentDir });\n const context = { dirname, filename: options.fileName };\n const extension =\n getFileExtension(options.fileName) ||\n getFileExtensionFromMime(options.fileType) ||\n getFileExtension(options.fileUrl) ||\n (await getFileExtensionFromUri(options.fileUrl));\n\n if (extension) context.filename = normalizeFileName(context.filename, extension);\n\n return { path: `${context.dirname}/${context.filename}`, ...context };\n };\n\n private downloadFile = async (options: SaveOptions) => {\n const { path, filename } = await this.buildDownloadPath(options);\n await fsModule.FileSystem.fetch(options.fileUrl, { path });\n return {\n downloadedPath: path,\n file: {\n name: filename,\n type: getFileType(getFileExtension(path)),\n } as const,\n };\n };\n }\n\n return new NativeFileService();\n};\n\nexport default createNativeFileService;\n"],"mappings":";;AACA,SAASA,QAAT,QAAyB,cAAzB;AAOA,SACEC,gBADF,EAEEC,wBAFF,EAGEC,uBAHF,EAIEC,WAJF,EAKEC,iBALF,QAMO,uBANP;AAQA,OAAOC,QAAP,MAAqB,kBAArB;AACA,OAAOC,uBAAP,MAAoC,kCAApC;AACA,OAAOC,aAAP,MAA0B,wBAA1B;;AAUA,SAASC,sCAAT,CAAgDC,gBAAhD,EAAoG;EAClG,IAAIV,QAAQ,CAACW,EAAT,KAAgB,SAApB,EAA+B,OAAO,EAAP;;EAE/B,IAAIX,QAAQ,CAACY,OAAT,GAAmB,EAAvB,EAA2B;IACzB,OAAO,CACLF,gBAAgB,CAACG,WAAjB,CAA6BC,OAA7B,CAAqCC,gBADhC,EAELL,gBAAgB,CAACG,WAAjB,CAA6BC,OAA7B,CAAqCE,iBAFhC,EAGLN,gBAAgB,CAACG,WAAjB,CAA6BC,OAA7B,CAAqCG,gBAHhC,CAAP;EAKD;;EAED,IAAIjB,QAAQ,CAACY,OAAT,GAAmB,EAAvB,EAA2B;IACzB,OAAO,CAACF,gBAAgB,CAACG,WAAjB,CAA6BC,OAA7B,CAAqCI,qBAAtC,CAAP;EACD;;EAED,OAAO,CACLR,gBAAgB,CAACG,WAAjB,CAA6BC,OAA7B,CAAqCK,sBADhC,EAELT,gBAAgB,CAACG,WAAjB,CAA6BC,OAA7B,CAAqCI,qBAFhC,CAAP;AAID;;AAED,MAAME,uBAAuB,GAAG,QAYJ;EAAA,IAZK;IAC/BC,iBAD+B;IAE/BC,oBAF+B;IAG/BZ,gBAH+B;IAI/Ba,kBAJ+B;IAK/BC;EAL+B,CAYL;EAC1B,MAAMC,iBAA+B,GAAGzB,QAAQ,CAAC0B,MAAT,CAAgB;IACtDC,GAAG,EAAE,CAACjB,gBAAgB,CAACG,WAAjB,CAA6Be,GAA7B,CAAiCC,MAAlC,EAA0CnB,gBAAgB,CAACG,WAAjB,CAA6Be,GAA7B,CAAiCE,UAA3E,CADiD;IAEtDC,OAAO,EAAE,CAACrB,gBAAgB,CAACG,WAAjB,CAA6BC,OAA7B,CAAqCe,MAAtC,CAF6C;IAGtDG,OAAO,EAAE;EAH6C,CAAhB,CAAxC;EAKA,MAAMC,uBAAqC,GAAGjC,QAAQ,CAAC0B,MAAT,CAAgB;IAC5DC,GAAG,EAAE,CAACjB,gBAAgB,CAACG,WAAjB,CAA6Be,GAA7B,CAAiCM,aAAlC,EAAiDxB,gBAAgB,CAACG,WAAjB,CAA6Be,GAA7B,CAAiCO,aAAlF,CADuD;IAE5DJ,OAAO,EAAEtB,sCAAsC,CAACC,gBAAD,CAFa;IAG5DsB,OAAO,EAAE;EAHmD,CAAhB,CAA9C;;EAMA,MAAMI,iBAAN,CAAwD;IAAA;MAAA,2CA6I1B,MAAOC,OAAP,IAAgC;QAC1D,MAAMC,OAAO,GAAGtC,QAAQ,CAAC0B,MAAT,CAAgB;UAAEK,OAAO,EAAEP,QAAQ,CAACe,IAAT,CAAcC,QAAzB;UAAmCR,OAAO,EAAER,QAAQ,CAACe,IAAT,CAAcE;QAA1D,CAAhB,CAAhB;QACA,MAAMC,OAAO,GAAG;UAAEJ,OAAF;UAAWK,QAAQ,EAAEN,OAAO,CAACO;QAA7B,CAAhB;QACA,MAAMC,SAAS,GACb5C,gBAAgB,CAACoC,OAAO,CAACO,QAAT,CAAhB,IACA1C,wBAAwB,CAACmC,OAAO,CAACS,QAAT,CADxB,IAEA7C,gBAAgB,CAACoC,OAAO,CAACU,OAAT,CAFhB,KAGC,MAAM5C,uBAAuB,CAACkC,OAAO,CAACU,OAAT,CAH9B,CADF;QAMA,IAAIF,SAAJ,EAAeH,OAAO,CAACC,QAAR,GAAmBtC,iBAAiB,CAACqC,OAAO,CAACC,QAAT,EAAmBE,SAAnB,CAApC;QAEf,OAAO;UAAEG,IAAI,EAAG,GAAEN,OAAO,CAACJ,OAAQ,IAAGI,OAAO,CAACC,QAAS,EAA/C;UAAkD,GAAGD;QAArD,CAAP;MACD,CAzJqD;;MAAA,sCA2J/B,MAAOL,OAAP,IAAgC;QACrD,MAAM;UAAEW,IAAF;UAAQL;QAAR,IAAqB,MAAM,KAAKM,iBAAL,CAAuBZ,OAAvB,CAAjC;QACA,MAAMb,QAAQ,CAAC0B,UAAT,CAAoBC,KAApB,CAA0Bd,OAAO,CAACU,OAAlC,EAA2C;UAAEC;QAAF,CAA3C,CAAN;QACA,OAAO;UACLI,cAAc,EAAEJ,IADX;UAELK,IAAI,EAAE;YACJC,IAAI,EAAEX,QADF;YAEJY,IAAI,EAAEnD,WAAW,CAACH,gBAAgB,CAAC+C,IAAD,CAAjB;UAFb;QAFD,CAAP;MAOD,CArKqD;IAAA;;IAC7B,MAAnBQ,mBAAmB,GAAqB;MAC5C,MAAMC,MAAM,GAAG,MAAM/C,gBAAgB,CAACgD,aAAjB,CAA+BjC,iBAA/B,CAArB;MACA,OAAOlB,uBAAuB,CAACkD,MAAD,CAA9B;IACD;;IAC4B,MAAvBE,uBAAuB,GAAqB;MAChD,MAAMF,MAAM,GAAG,MAAM/C,gBAAgB,CAACkD,eAAjB,CAAiCnC,iBAAjC,CAArB;MACA,OAAOlB,uBAAuB,CAACkD,MAAD,CAA9B;IACD;;IAC8B,MAAzBI,yBAAyB,GAAqB;MAClD,MAAMJ,MAAM,GAAG,MAAM/C,gBAAgB,CAACgD,aAAjB,CAA+BzB,uBAA/B,CAArB;;MACA,IACE6B,OAAO,IACP9D,QAAQ,CAACW,EAAT,KAAgB,KADhB,IAEA8C,MAAM,CAAC,8BAAD,CAAN,KAA2C,aAF3C,IAGAA,MAAM,CAAC,8BAAD,CAAN,KAA2C,SAJ7C,EAKE;QACA,OAAO,IAAP;MACD;;MACD,OAAOlD,uBAAuB,CAACkD,MAAD,CAA9B;IACD;;IACkC,MAA7BM,6BAA6B,GAAqB;MACtD,MAAMN,MAAM,GAAG,MAAM/C,gBAAgB,CAACkD,eAAjB,CAAiC3B,uBAAjC,CAArB;MACA,OAAO1B,uBAAuB,CAACkD,MAAD,CAA9B;IACD;;IAEe,MAAVO,UAAU,CAAC3B,OAAD,EAA2D;MAAA;;MACzE,MAAM4B,aAAa,GAAG,MAAM,KAAKT,mBAAL,EAA5B;;MACA,IAAI,CAACS,aAAL,EAAoB;QAClB,MAAMC,OAAO,GAAG,MAAM,KAAKP,uBAAL,EAAtB;;QACA,IAAI,CAACO,OAAL,EAAc;UAAA;;UACZ7B,OAAO,SAAP,IAAAA,OAAO,WAAP,qCAAAA,OAAO,CAAE8B,aAAT,qFAAA9B,OAAO,EAAkB/B,QAAQ,CAAC8D,kBAA3B,CAAP;UACA,OAAO,IAAP;QACD;MACF;;MAED,MAAMC,QAAQ,GAAG,MAAMhD,iBAAiB,CAACiD,YAAlB,CAA+B;QACpDC,iBAAiB,EAAE,YADiC;QAEpDC,UAAU,EAAE,CAAAnC,OAAO,SAAP,IAAAA,OAAO,WAAP,YAAAA,OAAO,CAAEmC,UAAT,KAAuB,MAFiB;QAGpDC,SAAS,EAAE,CAAC,MAAM;UAChB,QAAQpC,OAAR,aAAQA,OAAR,uBAAQA,OAAO,CAAEoC,SAAjB;YACE,KAAK,OAAL;cACE,OAAO,OAAP;;YACF,KAAK,OAAL;cACE,OAAO,OAAP;;YACF,KAAK,KAAL;cACE,OAAO,OAAP;;YACF;cACE,OAAO,OAAP;UARJ;QAUD,CAXU;MAHyC,CAA/B,CAAvB;MAgBA,IAAIJ,QAAQ,CAACK,SAAb,EAAwB,OAAO,IAAP;;MACxB,IAAIL,QAAQ,CAACM,SAAT,KAAuB,oBAA3B,EAAiD;QAAA;;QAC/CtC,OAAO,SAAP,IAAAA,OAAO,WAAP,sCAAAA,OAAO,CAAE8B,aAAT,uFAAA9B,OAAO,EAAkB/B,QAAQ,CAACsE,kBAA3B,EAA+C,IAAIC,KAAJ,CAAUR,QAAQ,CAACS,YAAnB,CAA/C,CAAP;QACA,OAAO,IAAP;MACD;;MAED,MAAM;QAAElC,QAAQ,EAAEU,IAAZ;QAAkByB,QAAQ,EAAEC,IAA5B;QAAkCzB,IAAlC;QAAwC0B;MAAxC,IAAgD,qBAAAZ,QAAQ,CAACa,MAAT,sEAAkB,CAAlB,MAAwB,EAA9E;MACA,OAAO1E,aAAa,CAAC;QAAEyE,GAAF;QAAOD,IAAP;QAAa1B,IAAb;QAAmBC;MAAnB,CAAD,CAApB;IACD;;IACqB,MAAhB4B,gBAAgB,CAAC9C,OAAD,EAA0E;MAC9F;AACN;AACA;AACA;MACM,MAAM+C,cAAc,GAAG,CAAA/C,OAAO,SAAP,IAAAA,OAAO,WAAP,YAAAA,OAAO,CAAE+C,cAAT,KAA2B,CAAlD;MACA,MAAMnB,aAAa,GAAG,MAAM,KAAKJ,yBAAL,EAA5B;;MACA,IAAI,CAACI,aAAL,EAAoB;QAClB,MAAMC,OAAO,GAAG,MAAM,KAAKH,6BAAL,EAAtB;;QACA,IAAI,CAACG,OAAL,EAAc;UAAA;;UACZ7B,OAAO,SAAP,IAAAA,OAAO,WAAP,sCAAAA,OAAO,CAAE8B,aAAT,uFAAA9B,OAAO,EAAkB/B,QAAQ,CAAC8D,kBAA3B,CAAP;UACA,OAAO,IAAP;QACD;MACF;;MAED,MAAMC,QAAQ,GAAG,MAAMhD,iBAAiB,CAACgE,kBAAlB,CAAqC;QAC1Dd,iBAAiB,EAAE,YADuC;QAE1Da,cAF0D;QAG1DX,SAAS,EAAE,CAAC,MAAM;UAChB,QAAQpC,OAAR,aAAQA,OAAR,uBAAQA,OAAO,CAAEoC,SAAjB;YACE,KAAK,OAAL;cACE,OAAO,OAAP;;YACF,KAAK,OAAL;cACE,OAAO,OAAP;;YACF,KAAK,KAAL;cACE,OAAO,OAAP;;YACF;cACE,OAAO,OAAP;UARJ;QAUD,CAXU;MAH+C,CAArC,CAAvB;MAgBA,IAAIJ,QAAQ,CAACK,SAAb,EAAwB,OAAO,IAAP;;MACxB,IAAIL,QAAQ,CAACM,SAAT,KAAuB,oBAA3B,EAAiD;QAAA;;QAC/CtC,OAAO,SAAP,IAAAA,OAAO,WAAP,sCAAAA,OAAO,CAAE8B,aAAT,uFAAA9B,OAAO,EAAkB/B,QAAQ,CAACsE,kBAA3B,EAA+C,IAAIC,KAAJ,CAAUR,QAAQ,CAACS,YAAnB,CAA/C,CAAP;QACA,OAAO,IAAP;MACD;;MAED,OAAOQ,OAAO,CAACC,GAAR,CACL,CAAClB,QAAQ,CAACa,MAAT,IAAmB,EAApB,EACGM,KADH,CACS,CADT,EACYJ,cADZ,EAEGK,GAFH,CAEO;QAAA,IAAC;UAAE7C,QAAQ,EAAEU,IAAZ;UAAkByB,QAAQ,EAAEC,IAA5B;UAAkCzB,IAAlC;UAAwC0B;QAAxC,CAAD;QAAA,OAAmDzE,aAAa,CAAC;UAAEyE,GAAF;UAAOD,IAAP;UAAa1B,IAAb;UAAmBC;QAAnB,CAAD,CAAhE;MAAA,CAFP,CADK,CAAP;IAKD;;IACiB,MAAZmC,YAAY,CAACrD,OAAD,EAA6D;MAC7E,IAAI;QACF,MAAM;UAAE4C,GAAF;UAAOD,IAAP;UAAa1B,IAAb;UAAmBC;QAAnB,IAA4B,MAAMjC,oBAAoB,CAACqE,UAArB,EAAxC;QACA,OAAOnF,aAAa,CAAC;UAAEyE,GAAF;UAAOD,IAAP;UAAa1B,IAAb;UAAmBC;QAAnB,CAAD,CAApB;MACD,CAHD,CAGE,OAAOqC,CAAP,EAAU;QACV,IAAI,CAACtE,oBAAoB,CAACuE,QAArB,CAA8BD,CAA9B,CAAD,IAAqCtE,oBAAoB,CAACwE,YAArB,CAAkCF,CAAlC,CAAzC,EAA+E;UAAA;;UAC7EvD,OAAO,SAAP,IAAAA,OAAO,WAAP,sCAAAA,OAAO,CAAE8B,aAAT,uFAAA9B,OAAO,EAAkB/B,QAAQ,CAACyF,OAA3B,EAAoCH,CAApC,CAAP;QACD;;QACD,OAAO,IAAP;MACD;IACF;;IACS,MAAJI,IAAI,CAAC3D,OAAD,EAAwC;MAChD,MAAM4B,aAAa,GAAG,MAAM,KAAKJ,yBAAL,EAA5B;;MACA,IAAI,CAACI,aAAL,EAAoB;QAClB,MAAMC,OAAO,GAAG,MAAM,KAAKH,6BAAL,EAAtB;QACA,IAAI,CAACG,OAAL,EAAc,MAAM,IAAIW,KAAJ,CAAU,wBAAV,CAAN;MACf;;MAED,MAAM;QAAEzB,cAAF;QAAkBC;MAAlB,IAA2B,MAAM,KAAK4C,YAAL,CAAkB5D,OAAlB,CAAvC;;MAEA,IAAIrC,QAAQ,CAACW,EAAT,KAAgB,KAApB,EAA2B;QACzB,IAAI0C,IAAI,CAACE,IAAL,KAAc,OAAd,IAAyBF,IAAI,CAACE,IAAL,KAAc,OAA3C,EAAoD;UAClD,MAAM2C,YAAY,GAAG;YAAE,SAAS,OAAX;YAAoB,SAAS;UAA7B,CAArB;UACA,MAAMzB,SAAS,GAAGyB,YAAY,CAAC7C,IAAI,CAACE,IAAN,CAA9B;UACA,MAAMhC,kBAAkB,CAACyE,IAAnB,CAAwB5C,cAAxB,EAAwC;YAAEG,IAAI,EAAEkB;UAAR,CAAxC,CAAN;QACD;MACF;;MAED,IAAIzE,QAAQ,CAACW,EAAT,KAAgB,SAApB,EAA+B;QAC7B,MAAMwF,cAAc,GAAG;UAAE,QAAQ,WAAV;UAAuB,SAAS,OAAhC;UAAyC,SAAS,QAAlD;UAA4D,SAAS;QAArE,CAAvB;QACA,MAAMC,WAAW,GAAGD,cAAc,CAAC9C,IAAI,CAACE,IAAN,CAAlC;QACA,MAAM/B,QAAQ,CAAC0B,UAAT,CAAoBmD,UAApB,CAA+BjD,cAA/B,EAA+CC,IAAI,CAACC,IAApD,EAA0D8C,WAA1D,CAAN;MACD;;MAED,OAAOhD,cAAP;IACD;;EA3IqD;;EAwKxD,OAAO,IAAIhB,iBAAJ,EAAP;AACD,CAjMD;;AAmMA,eAAehB,uBAAf"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { getFileExtension, getFileExtensionFromMime, getFileExtensionFromUri, getMimeFromFileExtension, normalizeFileName } from '@sendbird/uikit-utils';
|
|
2
|
+
|
|
3
|
+
const normalizeFile = async _ref => {
|
|
4
|
+
let {
|
|
5
|
+
uri,
|
|
6
|
+
size,
|
|
7
|
+
name,
|
|
8
|
+
type
|
|
9
|
+
} = _ref;
|
|
10
|
+
// URI is required property
|
|
11
|
+
if (!uri) return null;
|
|
12
|
+
let filename = name || String(Date.now());
|
|
13
|
+
let filetype = type || '';
|
|
14
|
+
const extension = getFileExtension(filename) || getFileExtensionFromMime(filetype) || (await getFileExtensionFromUri(uri));
|
|
15
|
+
|
|
16
|
+
if (extension) {
|
|
17
|
+
filename = normalizeFileName(filename, extension);
|
|
18
|
+
|
|
19
|
+
if (!filetype) {
|
|
20
|
+
filetype = getMimeFromFileExtension(extension);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
uri,
|
|
26
|
+
name: filename,
|
|
27
|
+
type: filetype,
|
|
28
|
+
size: size ?? 0
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export default normalizeFile;
|
|
33
|
+
//# sourceMappingURL=normalizeFile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["getFileExtension","getFileExtensionFromMime","getFileExtensionFromUri","getMimeFromFileExtension","normalizeFileName","normalizeFile","uri","size","name","type","filename","String","Date","now","filetype","extension"],"sources":["normalizeFile.ts"],"sourcesContent":["import type { PartialNullable } from '@sendbird/uikit-utils';\nimport {\n getFileExtension,\n getFileExtensionFromMime,\n getFileExtensionFromUri,\n getMimeFromFileExtension,\n normalizeFileName,\n} from '@sendbird/uikit-utils';\n\nimport type { FilePickerResponse, FileType } from '../platform/types';\n\nconst normalizeFile = async ({ uri, size, name, type }: PartialNullable<FileType>): Promise<FilePickerResponse> => {\n // URI is required property\n if (!uri) return null;\n\n let filename = name || String(Date.now());\n let filetype = type || '';\n\n const extension =\n getFileExtension(filename) || getFileExtensionFromMime(filetype) || (await getFileExtensionFromUri(uri));\n\n if (extension) {\n filename = normalizeFileName(filename, extension);\n if (!filetype) {\n filetype = getMimeFromFileExtension(extension);\n }\n }\n\n return { uri, name: filename, type: filetype, size: size ?? 0 };\n};\n\nexport default normalizeFile;\n"],"mappings":"AACA,SACEA,gBADF,EAEEC,wBAFF,EAGEC,uBAHF,EAIEC,wBAJF,EAKEC,iBALF,QAMO,uBANP;;AAUA,MAAMC,aAAa,GAAG,cAA6F;EAAA,IAAtF;IAAEC,GAAF;IAAOC,IAAP;IAAaC,IAAb;IAAmBC;EAAnB,CAAsF;EACjH;EACA,IAAI,CAACH,GAAL,EAAU,OAAO,IAAP;EAEV,IAAII,QAAQ,GAAGF,IAAI,IAAIG,MAAM,CAACC,IAAI,CAACC,GAAL,EAAD,CAA7B;EACA,IAAIC,QAAQ,GAAGL,IAAI,IAAI,EAAvB;EAEA,MAAMM,SAAS,GACbf,gBAAgB,CAACU,QAAD,CAAhB,IAA8BT,wBAAwB,CAACa,QAAD,CAAtD,KAAqE,MAAMZ,uBAAuB,CAACI,GAAD,CAAlG,CADF;;EAGA,IAAIS,SAAJ,EAAe;IACbL,QAAQ,GAAGN,iBAAiB,CAACM,QAAD,EAAWK,SAAX,CAA5B;;IACA,IAAI,CAACD,QAAL,EAAe;MACbA,QAAQ,GAAGX,wBAAwB,CAACY,SAAD,CAAnC;IACD;EACF;;EAED,OAAO;IAAET,GAAF;IAAOE,IAAI,EAAEE,QAAb;IAAuBD,IAAI,EAAEK,QAA7B;IAAuCP,IAAI,EAAEA,IAAI,IAAI;EAArD,CAAP;AACD,CAlBD;;AAoBA,eAAeF,aAAf"}
|
package/lib/module/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["VERSION"],"sources":["version.ts"],"sourcesContent":["const VERSION = '2.4.
|
|
1
|
+
{"version":3,"names":["VERSION"],"sources":["version.ts"],"sourcesContent":["const VERSION = '2.4.1';\nexport default VERSION;\n"],"mappings":"AAAA,MAAMA,OAAO,GAAG,OAAhB;AACA,eAAeA,OAAf"}
|
|
@@ -8,7 +8,7 @@ import type { StringSet } from '../localization/StringSet.type';
|
|
|
8
8
|
import type { ClipboardServiceInterface, FileServiceInterface, MediaServiceInterface, NotificationServiceInterface } from '../platform/types';
|
|
9
9
|
import type { ErrorBoundaryProps, LocalCacheStorage } from '../types';
|
|
10
10
|
export declare const SendbirdUIKit: Readonly<{
|
|
11
|
-
VERSION: "2.4.
|
|
11
|
+
VERSION: "2.4.1";
|
|
12
12
|
PLATFORM: string;
|
|
13
13
|
DEFAULT: {
|
|
14
14
|
AUTO_PUSH_TOKEN_REGISTRATION: boolean;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { PartialNullable } from '@sendbird/uikit-utils';
|
|
2
|
+
import type { FilePickerResponse, FileType } from '../platform/types';
|
|
3
|
+
declare const normalizeFile: ({ uri, size, name, type }: PartialNullable<FileType>) => Promise<FilePickerResponse>;
|
|
4
|
+
export default normalizeFile;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const VERSION = "2.4.
|
|
1
|
+
declare const VERSION = "2.4.1";
|
|
2
2
|
export default VERSION;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sendbird/uikit-react-native",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.1",
|
|
4
4
|
"description": "react-native-uikit",
|
|
5
5
|
"main": "lib/commonjs/index",
|
|
6
6
|
"module": "lib/module/index",
|
|
@@ -42,9 +42,9 @@
|
|
|
42
42
|
"access": "public"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@sendbird/uikit-chat-hooks": "2.4.
|
|
46
|
-
"@sendbird/uikit-react-native-foundation": "2.4.
|
|
47
|
-
"@sendbird/uikit-utils": "2.4.
|
|
45
|
+
"@sendbird/uikit-chat-hooks": "2.4.1",
|
|
46
|
+
"@sendbird/uikit-react-native-foundation": "2.4.1",
|
|
47
|
+
"@sendbird/uikit-utils": "2.4.1"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
50
|
"@bam.tech/react-native-image-resizer": "^3.0.4",
|
|
@@ -182,5 +182,5 @@
|
|
|
182
182
|
"readmeFile": "./README.md",
|
|
183
183
|
"displayName": "@sendbird/uikit-react-native"
|
|
184
184
|
},
|
|
185
|
-
"gitHead": "
|
|
185
|
+
"gitHead": "9ba7a005c941a3edd5b0f78d88d8cd1df6c280fc"
|
|
186
186
|
}
|
|
@@ -120,7 +120,7 @@ const SendInput = forwardRef<RNTextInput, SendInputProps>(function SendInput(
|
|
|
120
120
|
// Image compression
|
|
121
121
|
if (
|
|
122
122
|
isImage(mediaFile.uri, mediaFile.type) &&
|
|
123
|
-
shouldCompressImage(mediaFile.
|
|
123
|
+
shouldCompressImage(mediaFile.type, features.imageCompressionEnabled)
|
|
124
124
|
) {
|
|
125
125
|
await SBUUtils.safeRun(async () => {
|
|
126
126
|
const compressed = await mediaService.compressImage({
|
|
@@ -170,7 +170,7 @@ const SendInput = forwardRef<RNTextInput, SendInputProps>(function SendInput(
|
|
|
170
170
|
// Image compression
|
|
171
171
|
if (
|
|
172
172
|
isImage(mediaFile.uri, mediaFile.type) &&
|
|
173
|
-
shouldCompressImage(mediaFile.
|
|
173
|
+
shouldCompressImage(mediaFile.type, features.imageCompressionEnabled)
|
|
174
174
|
) {
|
|
175
175
|
await SBUUtils.safeRun(async () => {
|
|
176
176
|
const compressed = await mediaService.compressImage({
|
|
@@ -203,7 +203,7 @@ const SendInput = forwardRef<RNTextInput, SendInputProps>(function SendInput(
|
|
|
203
203
|
// Image compression
|
|
204
204
|
if (
|
|
205
205
|
isImage(documentFile.uri, documentFile.type) &&
|
|
206
|
-
shouldCompressImage(documentFile.
|
|
206
|
+
shouldCompressImage(documentFile.type, features.imageCompressionEnabled)
|
|
207
207
|
) {
|
|
208
208
|
await SBUUtils.safeRun(async () => {
|
|
209
209
|
const compressed = await mediaService.compressImage({
|
|
@@ -21,7 +21,7 @@ import type {
|
|
|
21
21
|
SendbirdMember,
|
|
22
22
|
SendbirdUser,
|
|
23
23
|
} from '@sendbird/uikit-utils';
|
|
24
|
-
import { useIsFirstMount } from '@sendbird/uikit-utils';
|
|
24
|
+
import { NOOP, useIsFirstMount } from '@sendbird/uikit-utils';
|
|
25
25
|
|
|
26
26
|
import { LocalizationContext, LocalizationProvider } from '../contexts/LocalizationCtx';
|
|
27
27
|
import { PlatformServiceProvider } from '../contexts/PlatformServiceCtx';
|
|
@@ -287,9 +287,28 @@ const initializeSendbird = (
|
|
|
287
287
|
}
|
|
288
288
|
|
|
289
289
|
if (NetInfo?.addEventListener) {
|
|
290
|
+
try {
|
|
291
|
+
// NOTE: For removing buggy behavior of NetInfo.addEventListener
|
|
292
|
+
// When you first add an event listener, it is assumed that the initialization of the internal event detector is done simultaneously.
|
|
293
|
+
// In other words, when you call the first event listener two events are triggered immediately
|
|
294
|
+
// - the one that is called when adding the event listener
|
|
295
|
+
// - and the internal initialization event
|
|
296
|
+
NetInfo.addEventListener(NOOP)();
|
|
297
|
+
} catch {}
|
|
298
|
+
|
|
290
299
|
const listener = (callback: () => void, callbackType: 'online' | 'offline') => {
|
|
300
|
+
let callCount = 0;
|
|
291
301
|
const unsubscribe = NetInfo.addEventListener((state) => {
|
|
292
302
|
const online = Boolean(state.isConnected) || Boolean(state.isInternetReachable);
|
|
303
|
+
|
|
304
|
+
// NOTE: When NetInfo.addEventListener is called
|
|
305
|
+
// the event is immediately triggered regardless of whether the event actually occurred.
|
|
306
|
+
// This is why it filters the first event.
|
|
307
|
+
if (callCount === 0) {
|
|
308
|
+
callCount++;
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
|
|
293
312
|
if (online && callbackType === 'online') callback();
|
|
294
313
|
if (!online && callbackType === 'offline') callback();
|
|
295
314
|
});
|
|
@@ -3,12 +3,12 @@ import type * as ExpoFs from 'expo-file-system';
|
|
|
3
3
|
import type * as ExpoImagePicker from 'expo-image-picker';
|
|
4
4
|
import type * as ExpoMediaLibrary from 'expo-media-library';
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { getFileType } from '@sendbird/uikit-utils';
|
|
7
7
|
|
|
8
8
|
import SBUError from '../libs/SBUError';
|
|
9
9
|
import type { ExpoMediaLibraryPermissionResponse, ExpoPermissionResponse } from '../utils/expoPermissionGranted';
|
|
10
10
|
import expoPermissionGranted from '../utils/expoPermissionGranted';
|
|
11
|
-
import
|
|
11
|
+
import normalizeFile from '../utils/normalizeFile';
|
|
12
12
|
import type {
|
|
13
13
|
FilePickerResponse,
|
|
14
14
|
FileServiceInterface,
|
|
@@ -80,10 +80,8 @@ const createExpoFileService = ({
|
|
|
80
80
|
|
|
81
81
|
const { uri } = response;
|
|
82
82
|
const { size } = await fsModule.getInfoAsync(response.uri);
|
|
83
|
-
const ext = getFileExtension(uri);
|
|
84
|
-
const type = getFileType(ext);
|
|
85
83
|
|
|
86
|
-
return
|
|
84
|
+
return normalizeFile({ uri, size });
|
|
87
85
|
}
|
|
88
86
|
async openMediaLibrary(options: OpenMediaLibraryOptions) {
|
|
89
87
|
const hasPermission = await this.hasMediaLibraryPermission('read');
|
|
@@ -111,11 +109,8 @@ const createExpoFileService = ({
|
|
|
111
109
|
});
|
|
112
110
|
if (response.cancelled) return null;
|
|
113
111
|
const { uri } = response;
|
|
114
|
-
|
|
115
112
|
const { size } = await fsModule.getInfoAsync(uri);
|
|
116
|
-
|
|
117
|
-
const type = getFileType(ext);
|
|
118
|
-
return [fileTypeGuard({ uri, size, type: `${type}/${ext.slice(1)}`, name: Date.now() + ext })];
|
|
113
|
+
return [await normalizeFile({ uri, size })];
|
|
119
114
|
}
|
|
120
115
|
|
|
121
116
|
async openDocument(options?: OpenDocumentOptions): Promise<FilePickerResponse> {
|
|
@@ -123,7 +118,7 @@ const createExpoFileService = ({
|
|
|
123
118
|
const response = await documentPickerModule.getDocumentAsync({ type: '*/*' });
|
|
124
119
|
if (response.type === 'cancel') return null;
|
|
125
120
|
const { mimeType, uri, size, name } = response;
|
|
126
|
-
return
|
|
121
|
+
return normalizeFile({ uri, size, name, type: mimeType });
|
|
127
122
|
} catch (e) {
|
|
128
123
|
options?.onOpenFailure?.(SBUError.UNKNOWN, e);
|
|
129
124
|
return null;
|
|
@@ -6,11 +6,17 @@ import type * as ImagePicker from 'react-native-image-picker';
|
|
|
6
6
|
import type * as Permissions from 'react-native-permissions';
|
|
7
7
|
import type { Permission } from 'react-native-permissions';
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
getFileExtension,
|
|
11
|
+
getFileExtensionFromMime,
|
|
12
|
+
getFileExtensionFromUri,
|
|
13
|
+
getFileType,
|
|
14
|
+
normalizeFileName,
|
|
15
|
+
} from '@sendbird/uikit-utils';
|
|
10
16
|
|
|
11
17
|
import SBUError from '../libs/SBUError';
|
|
12
|
-
import fileTypeGuard from '../utils/fileTypeGuard';
|
|
13
18
|
import nativePermissionGranted from '../utils/nativePermissionGranted';
|
|
19
|
+
import normalizeFile from '../utils/normalizeFile';
|
|
14
20
|
import type {
|
|
15
21
|
FilePickerResponse,
|
|
16
22
|
FileServiceInterface,
|
|
@@ -124,7 +130,7 @@ const createNativeFileService = ({
|
|
|
124
130
|
}
|
|
125
131
|
|
|
126
132
|
const { fileName: name, fileSize: size, type, uri } = response.assets?.[0] ?? {};
|
|
127
|
-
return
|
|
133
|
+
return normalizeFile({ uri, size, name, type });
|
|
128
134
|
}
|
|
129
135
|
async openMediaLibrary(options?: OpenMediaLibraryOptions): Promise<FilePickerResponse[] | null> {
|
|
130
136
|
/**
|
|
@@ -163,14 +169,16 @@ const createNativeFileService = ({
|
|
|
163
169
|
return null;
|
|
164
170
|
}
|
|
165
171
|
|
|
166
|
-
return (
|
|
167
|
-
.
|
|
168
|
-
|
|
172
|
+
return Promise.all(
|
|
173
|
+
(response.assets || [])
|
|
174
|
+
.slice(0, selectionLimit)
|
|
175
|
+
.map(({ fileName: name, fileSize: size, type, uri }) => normalizeFile({ uri, size, name, type })),
|
|
176
|
+
);
|
|
169
177
|
}
|
|
170
178
|
async openDocument(options?: OpenDocumentOptions): Promise<FilePickerResponse> {
|
|
171
179
|
try {
|
|
172
180
|
const { uri, size, name, type } = await documentPickerModule.pickSingle();
|
|
173
|
-
return
|
|
181
|
+
return normalizeFile({ uri, size, name, type });
|
|
174
182
|
} catch (e) {
|
|
175
183
|
if (!documentPickerModule.isCancel(e) && documentPickerModule.isInProgress(e)) {
|
|
176
184
|
options?.onOpenFailure?.(SBUError.UNKNOWN, e);
|
|
@@ -185,33 +193,50 @@ const createNativeFileService = ({
|
|
|
185
193
|
if (!granted) throw new Error('Permission not granted');
|
|
186
194
|
}
|
|
187
195
|
|
|
188
|
-
const
|
|
189
|
-
let downloadPath = `${basePath}/${options.fileName}`;
|
|
190
|
-
if (!getFileExtension(options.fileName)) {
|
|
191
|
-
const extensionFromUrl = getFileExtension(options.fileUrl);
|
|
192
|
-
if (getFileType(extensionFromUrl).match(/image|video/)) {
|
|
193
|
-
downloadPath += extensionFromUrl;
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
await fsModule.FileSystem.fetch(options.fileUrl, { path: downloadPath });
|
|
198
|
-
const fileType = getFileType(getFileExtension(options.fileUrl));
|
|
196
|
+
const { downloadedPath, file } = await this.downloadFile(options);
|
|
199
197
|
|
|
200
|
-
if (Platform.OS === 'ios'
|
|
201
|
-
|
|
202
|
-
|
|
198
|
+
if (Platform.OS === 'ios') {
|
|
199
|
+
if (file.type === 'image' || file.type === 'video') {
|
|
200
|
+
const mediaTypeMap = { 'image': 'photo', 'video': 'video' } as const;
|
|
201
|
+
const mediaType = mediaTypeMap[file.type];
|
|
202
|
+
await mediaLibraryModule.save(downloadedPath, { type: mediaType });
|
|
203
|
+
}
|
|
203
204
|
}
|
|
204
205
|
|
|
205
206
|
if (Platform.OS === 'android') {
|
|
206
|
-
const
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
normalizeFileName(options.fileName, getFileExtension(options.fileUrl)),
|
|
210
|
-
dirType[fileType],
|
|
211
|
-
);
|
|
207
|
+
const externalDirMap = { 'file': 'downloads', 'audio': 'audio', 'image': 'images', 'video': 'video' } as const;
|
|
208
|
+
const externalDir = externalDirMap[file.type];
|
|
209
|
+
await fsModule.FileSystem.cpExternal(downloadedPath, file.name, externalDir);
|
|
212
210
|
}
|
|
213
|
-
|
|
211
|
+
|
|
212
|
+
return downloadedPath;
|
|
214
213
|
}
|
|
214
|
+
|
|
215
|
+
private buildDownloadPath = async (options: SaveOptions) => {
|
|
216
|
+
const dirname = Platform.select({ android: fsModule.Dirs.CacheDir, default: fsModule.Dirs.DocumentDir });
|
|
217
|
+
const context = { dirname, filename: options.fileName };
|
|
218
|
+
const extension =
|
|
219
|
+
getFileExtension(options.fileName) ||
|
|
220
|
+
getFileExtensionFromMime(options.fileType) ||
|
|
221
|
+
getFileExtension(options.fileUrl) ||
|
|
222
|
+
(await getFileExtensionFromUri(options.fileUrl));
|
|
223
|
+
|
|
224
|
+
if (extension) context.filename = normalizeFileName(context.filename, extension);
|
|
225
|
+
|
|
226
|
+
return { path: `${context.dirname}/${context.filename}`, ...context };
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
private downloadFile = async (options: SaveOptions) => {
|
|
230
|
+
const { path, filename } = await this.buildDownloadPath(options);
|
|
231
|
+
await fsModule.FileSystem.fetch(options.fileUrl, { path });
|
|
232
|
+
return {
|
|
233
|
+
downloadedPath: path,
|
|
234
|
+
file: {
|
|
235
|
+
name: filename,
|
|
236
|
+
type: getFileType(getFileExtension(path)),
|
|
237
|
+
} as const,
|
|
238
|
+
};
|
|
239
|
+
};
|
|
215
240
|
}
|
|
216
241
|
|
|
217
242
|
return new NativeFileService();
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { PartialNullable } from '@sendbird/uikit-utils';
|
|
2
|
+
import {
|
|
3
|
+
getFileExtension,
|
|
4
|
+
getFileExtensionFromMime,
|
|
5
|
+
getFileExtensionFromUri,
|
|
6
|
+
getMimeFromFileExtension,
|
|
7
|
+
normalizeFileName,
|
|
8
|
+
} from '@sendbird/uikit-utils';
|
|
9
|
+
|
|
10
|
+
import type { FilePickerResponse, FileType } from '../platform/types';
|
|
11
|
+
|
|
12
|
+
const normalizeFile = async ({ uri, size, name, type }: PartialNullable<FileType>): Promise<FilePickerResponse> => {
|
|
13
|
+
// URI is required property
|
|
14
|
+
if (!uri) return null;
|
|
15
|
+
|
|
16
|
+
let filename = name || String(Date.now());
|
|
17
|
+
let filetype = type || '';
|
|
18
|
+
|
|
19
|
+
const extension =
|
|
20
|
+
getFileExtension(filename) || getFileExtensionFromMime(filetype) || (await getFileExtensionFromUri(uri));
|
|
21
|
+
|
|
22
|
+
if (extension) {
|
|
23
|
+
filename = normalizeFileName(filename, extension);
|
|
24
|
+
if (!filetype) {
|
|
25
|
+
filetype = getMimeFromFileExtension(extension);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return { uri, name: filename, type: filetype, size: size ?? 0 };
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export default normalizeFile;
|
package/src/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const VERSION = '2.4.
|
|
1
|
+
const VERSION = '2.4.1';
|
|
2
2
|
export default VERSION;
|