Skip to content

Commit ae2d5b1

Browse files
author
HuyDo
committed
feat: [FC-13] custom document message
1 parent fac6cd4 commit ae2d5b1

28 files changed

+1099
-120
lines changed

package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,15 +144,21 @@
144144
]
145145
},
146146
"dependencies": {
147+
"@react-native-community/slider": "^4.5.2",
147148
"@react-native-firebase/app": "^20.1.0",
148149
"@react-native-firebase/firestore": "^20.1.0",
149150
"@react-native-firebase/storage": "^20.1.0",
151+
"@types/react-native-doc-viewer": "^2.7.6",
150152
"@types/uuid": "^9.0.8",
151153
"randomcolor": "^0.6.2",
152154
"react-native-aes-crypto": "^2.1.1",
155+
"react-native-doc-viewer": "^2.7.8",
156+
"react-native-document-picker": "^9.3.0",
153157
"react-native-fast-image": "^8.6.3",
158+
"react-native-fs": "^2.20.0",
154159
"react-native-gifted-chat": "^2.4.0",
155160
"react-native-image-picker": "^7.1.2",
161+
"react-native-uuid": "^2.0.2",
156162
"react-native-video": "^6.2.0",
157163
"react-native-vision-camera": "^4.1.0",
158164
"uuid": "^10.0.0"

src/chat/ChatScreen.tsx

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,29 @@ import {
1717
type ComposerProps,
1818
GiftedChat,
1919
type GiftedChatProps,
20+
Bubble,
2021
} from 'react-native-gifted-chat';
2122
import TypingIndicator from 'react-native-gifted-chat/lib/TypingIndicator';
2223
import { FirestoreServices } from '../services/firebase';
2324
import { useChatContext, useChatSelector } from '../hooks';
25+
26+
import { formatMessageData } from '../utilities';
27+
import { getConversation } from '../reducer/selectors';
28+
import InputToolbar, { IInputToolbar } from './components/InputToolbar';
29+
import { CameraView, CameraViewRef } from '../chat_obs/components/CameraView';
30+
import SelectedBubbleModal from './components/SelectedBubbleModal';
31+
import FileAttachmentModal, {
32+
FileAttachmentModalRef,
33+
} from './components/FileAttachmentModal';
2434
import type {
2535
ConversationProps,
2636
CustomConversationInfo,
2737
IUserInfo,
2838
MessageProps,
2939
} from '../interfaces';
30-
import { formatMessageData } from '../utilities';
31-
import { getConversation } from '../reducer/selectors';
32-
import InputToolbar, { IInputToolbar } from './components/InputToolbar';
33-
import { CameraView, CameraViewRef } from '../chat_obs/components/CameraView';
34-
import SelectedImageModal from './components/SelectedImage';
3540
import { useCameraPermission } from 'react-native-vision-camera';
41+
import type { CustomImageVideoBubbleProps } from './components/bubble/CustomImageVideoBubble';
42+
import { CustomBubble } from './components/bubble';
3643

3744
interface ChatScreenProps extends GiftedChatProps {
3845
style?: StyleProp<ViewStyle>;
@@ -46,6 +53,7 @@ interface ChatScreenProps extends GiftedChatProps {
4653
hasGallery?: boolean;
4754
onPressCamera?: () => void;
4855
customConversationInfo?: CustomConversationInfo;
56+
customImageVideoBubbleProps: CustomImageVideoBubbleProps;
4957
}
5058

5159
export const ChatScreen: React.FC<ChatScreenProps> = ({
@@ -58,6 +66,7 @@ export const ChatScreen: React.FC<ChatScreenProps> = ({
5866
renderComposer,
5967
inputToolbarProps,
6068
customConversationInfo,
69+
customImageVideoBubbleProps,
6170
...props
6271
}) => {
6372
const { userInfo } = useChatContext();
@@ -70,10 +79,15 @@ export const ChatScreen: React.FC<ChatScreenProps> = ({
7079
const firebaseInstance = useRef(FirestoreServices.getInstance()).current;
7180
const [messagesList, setMessagesList] = useState<MessageProps[]>([]);
7281
const [hasMoreMessages, setHasMoreMessages] = useState(false);
82+
7383
const isLoadingRef = useRef(false);
7484
const cameraViewRef = useRef<CameraViewRef>(null);
75-
const [isImgVideoUrl, setImgVideoUrl] = useState('');
85+
const fileAttachmentRef = useRef<FileAttachmentModalRef>(null);
86+
7687
const { hasPermission, requestPermission } = useCameraPermission();
88+
const [selectedMessage, setSelectedMessage] = useState<MessageProps | null>(
89+
null
90+
);
7791

7892
const conversationRef = useRef<ConversationProps | undefined>(
7993
conversationInfo
@@ -205,6 +219,7 @@ export const ChatScreen: React.FC<ChatScreenProps> = ({
205219
hasCamera={props.hasCamera}
206220
hasGallery={props.hasGallery}
207221
{...inputToolbarProps}
222+
documentRef={fileAttachmentRef.current}
208223
/>
209224
);
210225
},
@@ -218,6 +233,18 @@ export const ChatScreen: React.FC<ChatScreenProps> = ({
218233
]
219234
);
220235

236+
const renderBubble = (bubble: Bubble<MessageProps>['props']) => {
237+
if (props.renderBubble) return props.renderBubble(bubble);
238+
return (
239+
<CustomBubble
240+
bubbleMessage={bubble}
241+
onSelectedMessage={setSelectedMessage}
242+
customImageVideoBubbleProps={customImageVideoBubbleProps}
243+
position={bubble.position}
244+
/>
245+
);
246+
};
247+
221248
return (
222249
<View style={[styles.container, style]}>
223250
<KeyboardAvoidingView style={styles.container}>
@@ -234,14 +261,20 @@ export const ChatScreen: React.FC<ChatScreenProps> = ({
234261
renderChatFooter={() => <TypingIndicator />}
235262
onLoadEarlier={onLoadEarlier}
236263
renderComposer={inputToolbar}
264+
renderBubble={renderBubble}
237265
{...props}
238266
/>
239267
</KeyboardAvoidingView>
240-
<SelectedImageModal
241-
imageUrl={isImgVideoUrl}
242-
onClose={() => setImgVideoUrl('')}
268+
<SelectedBubbleModal
269+
message={selectedMessage}
270+
onClose={() => setSelectedMessage(null)}
243271
/>
244272
<CameraView onSend={onSend} userInfo={userInfo} ref={cameraViewRef} />
273+
<FileAttachmentModal
274+
userInfo={userInfo}
275+
ref={fileAttachmentRef}
276+
onSend={onSend}
277+
/>
245278
</View>
246279
);
247280
};

src/chat/components/ConversationItem.tsx

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,19 @@ export const ConversationItem: React.FC<IConversationItemProps> = ({
3838
return undefined;
3939
}, [data.image, data.name]);
4040

41+
const getLatestTextMessage = () => {
42+
switch (data.latestMessage?.type) {
43+
case MessageTypes.image:
44+
return 'Image';
45+
case MessageTypes.video:
46+
return 'Video';
47+
case MessageTypes.document:
48+
return 'File Attachment';
49+
default:
50+
return data?.latestMessage?.text;
51+
}
52+
};
53+
4154
return (
4255
<TouchableOpacity onPress={() => onPress?.(data)} style={styles.container}>
4356
<View style={styles.row}>
@@ -58,11 +71,7 @@ export const ConversationItem: React.FC<IConversationItemProps> = ({
5871
{data?.name}
5972
</Text>
6073
<Text style={[styles.message, lastMessageStyle]} numberOfLines={1}>
61-
{data?.latestMessage?.type === MessageTypes.text
62-
? data?.latestMessage?.text
63-
: data?.latestMessage?.type === MessageTypes.image
64-
? 'Photo'
65-
: 'Video'}
74+
{getLatestTextMessage()}
6675
</Text>
6776
</View>
6877
)}

0 commit comments

Comments
 (0)