Update chat screen and add a StubMessageService ✅
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
parent
d2421812e2
commit
b746fbf7d2
Binary file not shown.
@ -0,0 +1,47 @@
|
|||||||
|
import Message from "./Message";
|
||||||
|
|
||||||
|
export default class Conversation {
|
||||||
|
private _id: string;
|
||||||
|
private _name: string;
|
||||||
|
private _image: string;
|
||||||
|
private _lastMessage: Message;
|
||||||
|
|
||||||
|
constructor(id: string, name: string, image: string, lastMessage: Message) {
|
||||||
|
this._id = id;
|
||||||
|
this._name = name;
|
||||||
|
this._image = image;
|
||||||
|
this._lastMessage = lastMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
get id(): string {
|
||||||
|
return this._id;
|
||||||
|
}
|
||||||
|
|
||||||
|
set id(value: string) {
|
||||||
|
this._id = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
get name(): string {
|
||||||
|
return this._name;
|
||||||
|
}
|
||||||
|
|
||||||
|
set name(value: string) {
|
||||||
|
this._name = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
get image(): string {
|
||||||
|
return this._image;
|
||||||
|
}
|
||||||
|
|
||||||
|
set image(value: string) {
|
||||||
|
this._image = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
get lastMessage(): Message {
|
||||||
|
return this._lastMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
set lastMessage(value: Message) {
|
||||||
|
this._lastMessage = value;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,55 @@
|
|||||||
|
export default class Message {
|
||||||
|
private _id: string;
|
||||||
|
private _content: string;
|
||||||
|
private _sender: string;
|
||||||
|
private _date: Date;
|
||||||
|
private _audio: string;
|
||||||
|
|
||||||
|
constructor(id: string, content: string, sender: string, date: Date, audio: string = '') {
|
||||||
|
this._id = id;
|
||||||
|
this._content = content;
|
||||||
|
this._sender = sender;
|
||||||
|
this._date = date;
|
||||||
|
this._audio = audio;
|
||||||
|
}
|
||||||
|
|
||||||
|
get id(): string {
|
||||||
|
return this._id;
|
||||||
|
}
|
||||||
|
|
||||||
|
set id(value: string) {
|
||||||
|
this._id = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
get content(): string {
|
||||||
|
return this._content;
|
||||||
|
}
|
||||||
|
|
||||||
|
set content(value: string) {
|
||||||
|
this._content = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
get sender(): string {
|
||||||
|
return this._sender;
|
||||||
|
}
|
||||||
|
|
||||||
|
set sender(value: string) {
|
||||||
|
this._sender = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
get date(): Date {
|
||||||
|
return this._date;
|
||||||
|
}
|
||||||
|
|
||||||
|
set date(value: Date) {
|
||||||
|
this._date = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
get audio(): string {
|
||||||
|
return this._audio;
|
||||||
|
}
|
||||||
|
|
||||||
|
set audio(value: string) {
|
||||||
|
this._audio = value;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
import Message from "../../models/Message";
|
||||||
|
import IMessageService from "../../services/messages/interfaces/IMessageService"
|
||||||
|
import StubMessageService from "../../services/messages/stub/StubMessageService";
|
||||||
|
import { setConversations, setMessages } from "../actions/appActions";
|
||||||
|
|
||||||
|
const chatService: IMessageService = new StubMessageService();
|
||||||
|
|
||||||
|
export const getConversations = () => {
|
||||||
|
//@ts-ignore
|
||||||
|
return async dispatch => {
|
||||||
|
try {
|
||||||
|
const conversations = await chatService.getConversations();
|
||||||
|
dispatch(setConversations(conversations));
|
||||||
|
} catch (error: any) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getMessages = (id: string) => {
|
||||||
|
//@ts-ignore
|
||||||
|
return async dispatch => {
|
||||||
|
try {
|
||||||
|
const messages = await chatService.getMessagesWithIdConversation(id);
|
||||||
|
dispatch(setMessages(messages));
|
||||||
|
} catch (error: any) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const sendMessage = (id: string, message: Message) => {
|
||||||
|
//@ts-ignore
|
||||||
|
return async dispatch => {
|
||||||
|
try {
|
||||||
|
await chatService.sendMessage(id, message);
|
||||||
|
dispatch(getMessages(id));
|
||||||
|
} catch (error: any) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
export const chatTypes = {
|
||||||
|
FETCH_CONVERSATIONS: 'FETCH_CONVERSATIONS',
|
||||||
|
FETCH_MESSAGES: 'FETCH_MESSAGES',
|
||||||
|
}
|
@ -1,22 +1,178 @@
|
|||||||
import { useNavigation } from "@react-navigation/native";
|
import React, { useCallback, useEffect, useState } from "react";
|
||||||
import React, { useEffect } from "react";
|
import { Bubble, GiftedChat, IMessage, InputToolbar, Send } from "react-native-gifted-chat";
|
||||||
import { GiftedChat } from "react-native-gifted-chat";
|
import { faFileImage, faMicrophone } from "@fortawesome/free-solid-svg-icons"
|
||||||
|
import { colorsDark } from "../constants/colorsDark";
|
||||||
|
import { colorsLight } from "../constants/colorsLight";
|
||||||
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
import { SafeAreaView, TouchableOpacity, View } from "react-native";
|
||||||
|
import Icon from 'react-native-vector-icons/Ionicons';
|
||||||
|
import FontAwesome from 'react-native-vector-icons/FontAwesome';
|
||||||
|
import Message from "../models/Message";
|
||||||
|
import { getMessages, sendMessage } from "../redux/thunk/chatThunk";
|
||||||
|
import { FontAwesomeIcon } from "@fortawesome/react-native-fontawesome";
|
||||||
|
|
||||||
export default function Chat() {
|
//@ts-ignore
|
||||||
|
export default function Chat({ route }) {
|
||||||
|
const item: string = route.params.conversation;
|
||||||
|
const [messages, setMessages] = useState<IMessage[]>();
|
||||||
|
//@ts-ignore
|
||||||
|
const conversations: Message[] = useSelector(state => state.appReducer.messages);
|
||||||
|
|
||||||
const navigation = useNavigation();
|
// @ts-ignore
|
||||||
|
const isDark = useSelector(state => state.userReducer.dark);
|
||||||
|
const style = isDark ? colorsDark : colorsLight;
|
||||||
|
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
navigation.getParent()?.setOptions({
|
// @ts-ignore
|
||||||
tabBarStyle: {
|
dispatch(getMessages(item));
|
||||||
display: "none"
|
}, []);
|
||||||
}
|
|
||||||
});
|
useEffect(() => {
|
||||||
return () => navigation.getParent()?.setOptions({
|
const mappedMessages = conversations.map((msg: Message) => ({
|
||||||
tabBarStyle: undefined
|
_id: msg.id,
|
||||||
|
text: msg.content,
|
||||||
|
createdAt: msg.date,
|
||||||
|
user: {
|
||||||
|
_id: msg.sender,
|
||||||
|
name: msg.sender,
|
||||||
|
avatar: 'https://picsum.photos/536/354',
|
||||||
|
},
|
||||||
|
audio: msg.audio
|
||||||
|
}));
|
||||||
|
|
||||||
|
mappedMessages.reverse();
|
||||||
|
|
||||||
|
mappedMessages.push({
|
||||||
|
_id: "0",
|
||||||
|
text: 'Vous avez matché !!!',
|
||||||
|
system: true,
|
||||||
});
|
});
|
||||||
}, [navigation]);
|
|
||||||
|
setMessages(mappedMessages);
|
||||||
|
}, [conversations]);
|
||||||
|
|
||||||
|
const onSend = useCallback((messages: any = []) => {
|
||||||
|
|
||||||
|
const newMessage = new Message(
|
||||||
|
"-1",
|
||||||
|
messages[0].text,
|
||||||
|
"User1",
|
||||||
|
new Date()
|
||||||
|
);
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
dispatch(sendMessage(item, newMessage));
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const renderBubble = (props: any) => {
|
||||||
|
return (
|
||||||
|
<Bubble
|
||||||
|
{...props}
|
||||||
|
wrapperStyle={{
|
||||||
|
left: {
|
||||||
|
backgroundColor: style.Card,
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
textStyle={{
|
||||||
|
left: {
|
||||||
|
paddingHorizontal: 3,
|
||||||
|
color: style.Text,
|
||||||
|
},
|
||||||
|
right: {
|
||||||
|
paddingHorizontal: 3
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderInputToolbar = (props: any) => {
|
||||||
|
return (
|
||||||
|
<InputToolbar
|
||||||
|
{...props}
|
||||||
|
containerStyle={{
|
||||||
|
backgroundColor: style.Card,
|
||||||
|
borderTopWidth: 0,
|
||||||
|
}}
|
||||||
|
primaryStyle={{
|
||||||
|
alignItems: "center"
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
function handleImageIconPress(): void {
|
||||||
|
console.log("Image");
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleMicrophoneIconPress(): void {
|
||||||
|
console.log("Audio");
|
||||||
|
}
|
||||||
|
|
||||||
|
const renderActions = (props: any) => {
|
||||||
|
return (
|
||||||
|
<View style={{ flexDirection: 'row', marginLeft: 15 }}>
|
||||||
|
<TouchableOpacity onPress={handleImageIconPress}>
|
||||||
|
<FontAwesomeIcon icon={faFileImage} size={20} color={style.Line} style={{ marginRight: 10 }} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
|
||||||
|
<TouchableOpacity onPress={handleMicrophoneIconPress}>
|
||||||
|
<FontAwesomeIcon icon={faMicrophone} size={20} color={style.Line} />
|
||||||
|
</TouchableOpacity>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const renderSend = (props: any) => {
|
||||||
|
return (
|
||||||
|
<Send {...props}>
|
||||||
|
<View>
|
||||||
|
<Icon name="send" size={20} style={{ marginBottom: 12, marginHorizontal: 8 }} color="#2e64e5" />
|
||||||
|
</View>
|
||||||
|
</Send>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const scrollToBottomComponent = () => {
|
||||||
|
return (
|
||||||
|
<FontAwesome name='angle-double-down' size={22} color="#333" />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GiftedChat />
|
<SafeAreaView style={{ flex: 1, backgroundColor: style.Card }}>
|
||||||
)
|
<GiftedChat
|
||||||
|
messages={messages}
|
||||||
|
onSend={messages => onSend(messages)}
|
||||||
|
user={{
|
||||||
|
_id: "User1",
|
||||||
|
}}
|
||||||
|
listViewProps={{
|
||||||
|
style: {
|
||||||
|
backgroundColor: style.body
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
// @ts-ignore
|
||||||
|
textInputStyle={{
|
||||||
|
backgroundColor: style.Line,
|
||||||
|
borderRadius: 20,
|
||||||
|
paddingHorizontal: 15,
|
||||||
|
paddingTop: 10,
|
||||||
|
marginTop: 5,
|
||||||
|
color: style.Text
|
||||||
|
}}
|
||||||
|
renderActions={renderActions}
|
||||||
|
maxInputLength={255}
|
||||||
|
renderBubble={renderBubble}
|
||||||
|
renderInputToolbar={renderInputToolbar}
|
||||||
|
renderSend={renderSend}
|
||||||
|
scrollToBottom
|
||||||
|
scrollToBottomComponent={scrollToBottomComponent}
|
||||||
|
placeholder="Chat"
|
||||||
|
/>
|
||||||
|
</SafeAreaView>
|
||||||
|
);
|
||||||
}
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
import Conversation from "../../../models/Conversation";
|
||||||
|
import Message from "../../../models/Message";
|
||||||
|
|
||||||
|
export default interface IMessageService {
|
||||||
|
getConversations(): Promise<Conversation[]>;
|
||||||
|
getMessagesWithIdConversation(id: string): Promise<Message[]>;
|
||||||
|
sendMessage(id: string, mes: Message): Promise<void>;
|
||||||
|
}
|
File diff suppressed because one or more lines are too long
Loading…
Reference in new issue