Skip to content

Commit b4b4263

Browse files
authored
Merge pull request #101 from sendbird/fix/expo-modules
fix(CLNP-286): expo modules update
2 parents 4acfeca + 6fc18b9 commit b4b4263

File tree

9 files changed

+173
-119
lines changed

9 files changed

+173
-119
lines changed

packages/uikit-react-native/package.json

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,15 @@
7575
"@types/react-native": "*",
7676
"@types/react-native-video": "^5.0.14",
7777
"date-fns": "^2.28.0",
78-
"expo-av": "^12.0.4",
79-
"expo-clipboard": "^2.1.1",
80-
"expo-document-picker": "^10.1.3",
81-
"expo-file-system": "^13.1.4",
82-
"expo-image-manipulator": "^11.0.0",
83-
"expo-image-picker": "^12.0.2",
84-
"expo-media-library": "^14.0.1",
85-
"expo-notifications": "^0.14.1",
86-
"expo-video-thumbnails": "^6.4.0",
78+
"expo-av": "^13.2.1",
79+
"expo-clipboard": "^4.1.2",
80+
"expo-document-picker": "^11.2.2",
81+
"expo-file-system": "^15.2.2",
82+
"expo-image-manipulator": "^11.1.1",
83+
"expo-image-picker": "^14.1.1",
84+
"expo-media-library": "^15.2.3",
85+
"expo-notifications": "^0.18.1",
86+
"expo-video-thumbnails": "^7.2.1",
8787
"glob": "^7.2.0",
8888
"inquirer": "^8.2.0",
8989
"js-convert-case": "^4.2.0",

packages/uikit-react-native/src/components/ChatFlatList/FlatListInternal.tsx

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
/**
2-
* */
31
import type { ForwardedRef, ReactElement } from 'react';
42
import type { FlatListProps, FlatList as RNFlatList, ScrollViewProps } from 'react-native';
53
import { Platform } from 'react-native';
@@ -19,8 +17,8 @@ type BidirectionalProps<T> = {
1917
function shouldUseScrollViewEnhancer() {
2018
if (Platform.OS !== 'android') return false;
2119

22-
if (Platform.constants.reactNativeVersion.major < 1) {
23-
if (Platform.constants.reactNativeVersion.minor < 72) {
20+
if (Platform.constants.reactNativeVersion?.major < 1) {
21+
if (Platform.constants.reactNativeVersion?.minor < 72) {
2422
return true;
2523
}
2624
}

packages/uikit-react-native/src/components/ChatFlatList/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ type Props = Omit<FlatListProps<SendbirdMessage>, 'onEndReached'> & {
1616
onScrolledAwayFromBottom: (value: boolean) => void;
1717
};
1818
// FIXME: Inverted FlatList performance issue on Android {@link https://github.com/facebook/react-native/issues/30034}
19-
const ChatFlatList = forwardRef<RNFlatList, Props>(function CustomFlatList(
19+
const ChatFlatList = forwardRef<RNFlatList, Props>(function ChatFlatList(
2020
{ onTopReached, onBottomReached, onScrolledAwayFromBottom, onScroll, ...props },
2121
ref,
2222
) {

packages/uikit-react-native/src/platform/createFileService.expo.ts

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type * as ExpoMediaLibrary from 'expo-media-library';
66
import { getFileType } from '@sendbird/uikit-utils';
77

88
import SBUError from '../libs/SBUError';
9+
import expoBackwardUtils from '../utils/expoBackwardUtils';
910
import type { ExpoMediaLibraryPermissionResponse, ExpoPermissionResponse } from '../utils/expoPermissionGranted';
1011
import expoPermissionGranted from '../utils/expoPermissionGranted';
1112
import normalizeFile from '../utils/normalizeFile';
@@ -76,12 +77,10 @@ const createExpoFileService = ({
7677
})(),
7778
});
7879

79-
if (response.cancelled) return null;
80+
if (expoBackwardUtils.toCanceled(response)) return null;
8081

81-
const { uri } = response;
82-
const { size } = await fsModule.getInfoAsync(response.uri);
83-
84-
return normalizeFile({ uri, size });
82+
const filePickerRes = await expoBackwardUtils.toFilePickerResponses(response, fsModule);
83+
return filePickerRes[0];
8584
}
8685
async openMediaLibrary(options: OpenMediaLibraryOptions) {
8786
const hasPermission = await this.hasMediaLibraryPermission('read');
@@ -93,7 +92,9 @@ const createExpoFileService = ({
9392
}
9493
}
9594

95+
const selectionLimit = options?.selectionLimit || 1;
9696
const response = await imagePickerModule.launchImageLibraryAsync({
97+
selectionLimit,
9798
mediaTypes: (() => {
9899
switch (options?.mediaType) {
99100
case 'photo':
@@ -107,10 +108,8 @@ const createExpoFileService = ({
107108
}
108109
})(),
109110
});
110-
if (response.cancelled) return null;
111-
const { uri } = response;
112-
const { size } = await fsModule.getInfoAsync(uri);
113-
return [await normalizeFile({ uri, size })];
111+
if (expoBackwardUtils.toCanceled(response)) return null;
112+
return expoBackwardUtils.toFilePickerResponses(response, fsModule);
114113
}
115114

116115
async openDocument(options?: OpenDocumentOptions): Promise<FilePickerResponse> {

packages/uikit-react-native/src/platform/createMediaService.expo.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import React from 'react';
77
import { getDownscaleSize } from '@sendbird/uikit-utils';
88

99
import SBUUtils from '../libs/SBUUtils';
10+
import expoBackwardUtils from '../utils/expoBackwardUtils';
1011
import type { MediaServiceInterface } from './types';
1112

1213
type Modules = {
@@ -43,9 +44,9 @@ const createExpoMediaService = ({
4344
const { uri: compressedURI } = await imageManipulator.manipulateAsync(uri, [{ resize: resizingSize }], {
4445
compress: Math.min(Math.max(0, compressionRate), 1),
4546
});
46-
const { size = 0 } = await fsModule.getInfoAsync(uri);
47+
const fileInfo = await fsModule.getInfoAsync(uri);
4748

48-
return { uri: compressedURI, size };
49+
return { uri: compressedURI, size: expoBackwardUtils.toFileSize(fileInfo) };
4950
},
5051
};
5152
};
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import type * as ExpoFs from 'expo-file-system';
2+
import type * as ExpoImagePicker from 'expo-image-picker';
3+
4+
import type { FilePickerResponse } from '../platform/types';
5+
import normalizeFile from './normalizeFile';
6+
7+
const expoBackwardUtils = {
8+
toCanceled(result: ExpoImagePicker.ImagePickerResult) {
9+
// @ts-expect-error backward compatibility
10+
return result.canceled ?? result.cancelled;
11+
},
12+
toFileSize(info: ExpoFs.FileInfo) {
13+
if ('size' in info) {
14+
return info.size;
15+
} else {
16+
return 0;
17+
}
18+
},
19+
async toFilePickerResponses(
20+
result: ExpoImagePicker.ImagePickerResult,
21+
fsModule: typeof ExpoFs,
22+
): Promise<FilePickerResponse[]> {
23+
if (result.assets) {
24+
const assets = result.assets || [];
25+
const promises = assets.map(({ fileName: name, fileSize: size, type, uri }) =>
26+
normalizeFile({ uri, size, name, type }),
27+
);
28+
29+
return Promise.all(promises);
30+
} else if ('uri' in result && typeof result.uri === 'string') {
31+
const fileInfo = await fsModule.getInfoAsync(result.uri);
32+
const response = await normalizeFile({ uri: result.uri, size: this.toFileSize(fileInfo) });
33+
return [response];
34+
} else {
35+
return [];
36+
}
37+
},
38+
};
39+
40+
export default expoBackwardUtils;

packages/uikit-react-native/src/utils/normalizeFile.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,16 @@ const normalizeFile = async ({ uri, size, name, type }: PartialNullable<FileType
2121

2222
if (extension) {
2323
filename = normalizeFileName(filename, extension);
24-
if (!filetype) {
24+
if (!filetype || !isNotMimeType(filetype)) {
2525
filetype = getMimeFromFileExtension(extension);
2626
}
2727
}
2828

2929
return { uri, name: filename, type: filetype, size: size ?? 0 };
3030
};
3131

32+
function isNotMimeType(str: string) {
33+
return str.indexOf('/') === -1;
34+
}
35+
3236
export default normalizeFile;

packages/uikit-utils/src/shared/file.ts

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,28 @@ const EXTENSION_MIME_MAP = {
4141
export const imageExtRegex = /jpeg|jpg|png|webp|gif/i;
4242
export const audioExtRegex = /3gp|aac|aax|act|aiff|flac|gsm|m4a|m4b|m4p|tta|wma|mp3|webm|wav/i;
4343
export const videoExtRegex = /mov|vod|mp4|avi/i;
44-
export const getFileType = (extOrType: string) => {
45-
if (extOrType.indexOf('/') > -1) {
46-
const type = extOrType.split('/')[0];
44+
export const getFileType = (extensionOrType: string) => {
45+
const lowerCased = extensionOrType.toLowerCase();
46+
47+
// mime type
48+
if (lowerCased.indexOf('/') > -1) {
49+
const type = lowerCased.split('/')[0];
4750
if (type === 'video') return 'video';
4851
if (type === 'audio') return 'audio';
4952
if (type === 'image') return 'image';
5053
return 'file';
5154
}
5255

53-
if (extOrType.match(imageExtRegex)) return 'image';
54-
if (extOrType.match(audioExtRegex)) return 'audio';
55-
if (extOrType.match(videoExtRegex)) return 'video';
56+
// extensions
57+
if (lowerCased.match(imageExtRegex)) return 'image';
58+
if (lowerCased.match(audioExtRegex)) return 'audio';
59+
if (lowerCased.match(videoExtRegex)) return 'video';
60+
61+
// others
62+
if (lowerCased.startsWith('image')) return 'image';
63+
if (lowerCased.startsWith('audio')) return 'audio';
64+
if (lowerCased.startsWith('video')) return 'video';
65+
5666
return 'file';
5767
};
5868

0 commit comments

Comments
 (0)