Last active
October 27, 2021 12:58
-
-
Save hieptl/d2a98acf03042b148ee49eb6e4796742 to your computer and use it in GitHub Desktop.
Chat.tsx - Send Media Message - Ionic Chat App
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
... | |
import { Chooser } from '@ionic-native/chooser' | |
import { ImagePicker } from '@ionic-native/image-picker'; | |
... | |
import imageIcon from '../images/image.png'; | |
const Chat: React.FC = () => { | |
const history = useHistory(); | |
const { cometChat, user, selectedConversation, setCallType } = useContext(Context); | |
const [messages, setMessages] = useState<any>([]); | |
... | |
const [selectedFile, setSelectedFile] = useState<any>(null); | |
const [isActionSheetShown, setIsActionSheetShown] = useState<any>(false); | |
const messageRef = useRef<any>(null); | |
const messageBottomRef = useRef<any>(null); | |
... | |
useEffect(() => { | |
if (messages && messages.length !== 0) { | |
// scroll to bottom. | |
scrollToBottom(); | |
} | |
}, [messages]); | |
useEffect(() => { | |
if (selectedFile) { | |
sendMediaMessage(); | |
} | |
}, [selectedFile]); | |
const scrollToBottom = () => { | |
if (messageBottomRef && messageBottomRef.current) { | |
messageBottomRef.current.parentNode.scrollTop = messageBottomRef.current.offsetTop; | |
} | |
} | |
... | |
const getReceiverId = () => { | |
if (selectedConversation && selectedConversation.guid) { | |
return selectedConversation.guid; | |
} | |
if (selectedConversation && selectedConversation.uid) { | |
return selectedConversation.uid; | |
} | |
return null; | |
}; | |
const getReceiverType = () => { | |
if (selectedConversation && selectedConversation.guid) { | |
return cometChat.RECEIVER_TYPE.GROUP; | |
} | |
return cometChat.RECEIVER_TYPE.USER; | |
}; | |
const sendMediaMessage = () => { | |
const receiverId = getReceiverId(); | |
const receiverType = getReceiverType(); | |
let messageType = cometChat.MESSAGE_TYPE.IMAGE; | |
if (selectedFile.type.split('/')[0] === 'image') { | |
messageType = cometChat.MESSAGE_TYPE.IMAGE; | |
} else if (selectedFile.type.split('/')[0] === 'video') { | |
messageType = cometChat.MESSAGE_TYPE.VIDEO; | |
} else { | |
messageType = cometChat.MESSAGE_TYPE.FILE; | |
} | |
const mediaMessage = new cometChat.MediaMessage(receiverId, selectedFile.file, messageType, receiverType); | |
cometChat.sendMessage(mediaMessage).then((message: any) => { | |
// append the new message to "messages" state. | |
setMessages((prevMessages: any) => [...prevMessages, { | |
id: uuidv4(), | |
text: message.data.url, | |
sender: { | |
uid: user.uid, | |
avatar: user.avatar | |
}, | |
isRight: true, | |
type: message.type | |
}]); | |
// scroll to bottom. | |
scrollToBottom(); | |
}, (error: any) => { | |
} | |
); | |
}; | |
... | |
const isRight = (message: any) => { | |
if (message.isRight !== null && message.isRight !== undefined) { | |
return message.isRight; | |
} | |
return message.sender.uid === user.uid; | |
} | |
... | |
if (!selectedConversation) { | |
history.push('/'); | |
} | |
const dataURItoBlob = (dataURI: any) => { | |
const byteString = atob(dataURI.split(',')[1]); | |
const mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]; | |
const ab = new ArrayBuffer(byteString.length); | |
const ia = new Uint8Array(ab); | |
for (let i = 0; i < byteString.length; i++) { | |
ia[i] = byteString.charCodeAt(i); | |
} | |
const bb = new Blob([ab], { type: mimeString }); | |
return bb; | |
} | |
const selectDocument = () => { | |
Chooser.getFile('all') | |
.then((response: any) => { | |
const blob_nw = dataURItoBlob(response.dataURI); | |
const file = { | |
file: blob_nw, | |
type: response.mediaType, | |
name: response.name | |
}; | |
setSelectedFile(() => file); | |
}) | |
.catch((error: any) => console.error(error)); | |
}; | |
const selectImage = () => { | |
const options = { | |
outputType: 1 | |
}; | |
ImagePicker.getPictures(options) | |
.then((results: any) => { | |
results[0] = 'data:image/jpeg;base64,' + results[0]; | |
const blob_nw = dataURItoBlob(results[0]); | |
const date = new Date(); | |
const file = { | |
file: blob_nw, | |
type: 'image/jpeg', | |
name: 'temp_img' + date.getTime() | |
}; | |
setSelectedFile(() => file); | |
}, (err) => { | |
}); | |
}; | |
const toggleActionsSheet = (isActionsSheetShown: any) => () => { | |
setIsActionSheetShown(() => isActionsSheetShown); | |
} | |
... | |
return ( | |
<> | |
<IonHeader> | |
<IonToolbar> | |
<IonButtons slot="start"> | |
<IonBackButton defaultHref="/" /> | |
</IonButtons> | |
<IonButtons slot="end"> | |
<IonButton onClick={startAudioCall}> | |
<IonIcon slot="icon-only" icon={callOutline} /> | |
</IonButton> | |
</IonButtons> | |
<IonButtons slot="end"> | |
<IonButton onClick={startVideoCall}> | |
<IonIcon slot="icon-only" icon={videocamOutline} /> | |
</IonButton> | |
</IonButtons> | |
{selectedConversation && selectedConversation.contactType === 1 && <IonButtons slot="end"> | |
<IonButton onClick={goToManageGroup} > | |
<IonIcon slot="icon-only" icon={settings} /> | |
</IonButton> | |
</IonButtons>} | |
<div className='chatbox__title'> | |
<div className='chatbox__title-avatar-container'> | |
<img src={selectedConversation?.avatar ? selectedConversation?.avatar : selectedConversation?.icon ? selectedConversation?.icon : ''} alt={selectedConversation?.name} /> | |
{selectedConversation && selectedConversation.contactType === 0 && <span className={`chatbox__title-status ${isUserOnline ? 'chatbox__title-status--online' : 'chatbox__title-status--offline'}`}></span>} | |
</div> | |
<span>{selectedConversation?.name}</span> | |
</div> | |
</IonToolbar> | |
</IonHeader> | |
<div className="chatbox"> | |
<div className="message__container"> | |
{messages && messages.length !== 0 && messages.map((message: any) => ( | |
<Message key={message.id} message={message.text} messageType={message.type} deliveredAt={message.deliveredAt} readAt={message.readAt} senderId={message.sender.uid} avatar={message.sender.avatar} isRight={isRight(message)} /> | |
))} | |
<div ref={messageBottomRef} id="message-bottom"></div> | |
</div> | |
<div className="chatbox__input"> | |
<span ref={typingRef} className='hide'>Someone is typing...</span> | |
<div> | |
<img src={imageIcon} alt='file-chooser' className='chatbox__file-chooser' onClick={toggleActionsSheet(true)} /> | |
<input type="url" placeholder="Message..." onKeyDown={sendMessage} ref={messageRef} onChange={onInputChanged} onBlur={onInputBlured} /> | |
<svg fill="#2563EB" className="crt8y2ji" width="20px" height="20px" viewBox="0 0 24 24"><path d="M16.6915026,12.4744748 L3.50612381,13.2599618 C3.19218622,13.2599618 3.03521743,13.4170592 3.03521743,13.5741566 L1.15159189,20.0151496 C0.8376543,20.8006365 0.99,21.89 1.77946707,22.52 C2.41,22.99 3.50612381,23.1 4.13399899,22.8429026 L21.714504,14.0454487 C22.6563168,13.5741566 23.1272231,12.6315722 22.9702544,11.6889879 C22.8132856,11.0605983 22.3423792,10.4322088 21.714504,10.118014 L4.13399899,1.16346272 C3.34915502,0.9 2.40734225,1.00636533 1.77946707,1.4776575 C0.994623095,2.10604706 0.8376543,3.0486314 1.15159189,3.99121575 L3.03521743,10.4322088 C3.03521743,10.5893061 3.34915502,10.7464035 3.50612381,10.7464035 L16.6915026,11.5318905 C16.6915026,11.5318905 17.1624089,11.5318905 17.1624089,12.0031827 C17.1624089,12.4744748 16.6915026,12.4744748 16.6915026,12.4744748 Z" fillRule="evenodd" stroke="none"></path></svg> | |
</div> | |
</div> | |
</div> | |
<IonActionSheet | |
isOpen={isActionSheetShown} | |
onDidDismiss={toggleActionsSheet(false)} | |
buttons={[{ | |
text: 'Select Image', | |
handler: () => { | |
selectImage(); | |
} | |
}, { | |
text: 'Select Document', | |
handler: () => { | |
selectDocument(); | |
} | |
}]} | |
> | |
</IonActionSheet> | |
</> | |
); | |
}; | |
... |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment