Skip to content
Snippets Groups Projects
MessagesScreen.js 6.57 KiB
import React from 'react';
import { View, Text, StyleSheet, ActivityIndicator } from 'react-native';
import { GiftedChat, utils, Bubble, Send } from 'react-native-gifted-chat';
import AsyncStorage from '@react-native-async-storage/async-storage';
import FontAwesome5 from 'react-native-vector-icons/FontAwesome5';

const { isSameUser, isSameDay } = utils

require('dayjs/locale/fr');

class MessagesScreen extends React.Component {

  constructor(props) {

    super(props);

    this.state = {
      messages: [],
      user: null,
      isLoading: true
    }

    this.onSend = this.onSend.bind(this);
  }

  async getMessages() {
    let status = null;

    //get user from asyncStorage
    try {
      const user = await AsyncStorage.getItem('@user');
      if (user !== null) {
        await this.setState({ user: JSON.parse(user) });
      }
      else {
        this.props.logoutAuthentication();
      }
    } catch (error) {
      console.warn(error);
    }

    //get messages from API
    try {
      const token = await AsyncStorage.getItem('@token');
      //if token is stored, user is logged in
      if (token !== null) {
        fetch("http://163.172.178.146:3000/rooms/" + this.props.route.params.item._id + "/messages", {
          method: 'GET',
          headers: {
            Authorization: "Bearer " + token
          }
        })
          .then(response => {
            status = response.status;
            return response.json();
          })
          .then(async (json) => {

            //OK Status : we update message state with room messages from API
            if (status == 200) {
              let messages = [];

              json.forEach(message => {
                messages.push(
                  {
                    _id: message._id,
                    text: message.body,
                    createdAt: message.date,
                    user: {
                      _id: message.author._id,
                      name: message.author.username,
                      avatar: 'https://placeimg.com/140/140/any',
                    },
                  },
                );
              });

              this.setState({ messages: messages });
            }

            //Unauthorized status : token has expired, we force user to login to continue
            else if (status == 401) {
              this.props.logoutAuthentication();
            }

            //Handled error status
            else if ("error" in json) {
              console.warn(json.error);
            }

            //Unhandled error status
            else {
              console.warn("Unhandled error");
            }

          })
          .catch(async (error) => {
            //Error fetching url
          });
      }
      //token is not stored, user is not logged in
      else {
        this.props.logoutAuthentication();
      }
    } catch (error) {
      //Error fetching data
    }

    this.setState({ isLoading: false })
  }

  componentDidMount() {

    this.getMessages();

    const { navigation } = this.props;

    this.focusListener = navigation.addListener("focus", async () => {

      this.getMessages();

    });
  }

  async onSend(messages = []) {
    let status = null;

    //post message in room with API
    try {
      const token = await AsyncStorage.getItem('@token');
      //if token is stored, user is logged in
      if (token !== null) {
        fetch('http://163.172.178.146:3000/messages', {
          method: 'POST',
          headers: {
            Accept: 'application/json',
            Authorization: "Bearer " + token,
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({
            body: messages[0].text,
            roomId: this.props.route.params.item._id,
          })
        })
          .then(response => {
            status = response.status;
            return response.json();
          })
          .then(async (json) => {

            //OK Status : we update messages state with the message we post
            if (status == 200) {
              this.setState((previousState) => {
                return {
                  messages: GiftedChat.append(previousState.messages, messages),
                };
              });
            }

            //Unauthorized status : token has expired, we force user to login to continue
            else if (status == 401) {
              this.props.logoutAuthentication();
            }

            //Handled error status
            else if ("error" in json) {
              console.warn(json.error);
            }

            //Unhandled error status
            else {
              console.warn("Unhandled error");
            }

          })
          .catch(async (error) => {
            //Error fetching url
          });
      }
      //token is not stored, user is not logged in
      else {
        this.props.logoutAuthentication();
      }
    } catch (error) {
      //Error fetching data
    }
  }

  renderBubble(props) {
    if (props.position == "right" || (isSameUser(props.currentMessage, props.previousMessage) && isSameDay(props.currentMessage, props.previousMessage))) {
      return (
        <Bubble
          {...props}
          wrapperStyle={{
            left: {
              backgroundColor: '#fff',
            }
          }}
        />
      );
    }
    else {
      return (
        <View>
          <Text style={styles.username}>{props.currentMessage.user.name}</Text>
          <Bubble
            {...props}
            wrapperStyle={{
              left: {
                backgroundColor: '#fff',
              }
            }}
          />
        </View>
      );
    }
  }

  renderSend(props) {
      return (
        <Send
          {...props}
          containerStyle={{
            height: 45,
            width: 45,
            justifyContent: 'center',
            alignItems: 'center',
          }}
        >
          <FontAwesome5 name={'paper-plane'} solid color={'dodgerblue'} size={25} />
      </Send>
    );
  }

  render() {
    if (this.state.isLoading)
      return (
        <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
          <ActivityIndicator size="large" />
        </View>
      )
    else
      return (
        <GiftedChat
          renderBubble={this.renderBubble}
          messages={this.state.messages}
          onSend={this.onSend}
          user={{
            _id: this.state.user.id,
          }}
          locale={'fr'}
          placeholder="Écrivez un message..."
          renderSend={this.renderSend}
        />
      )
  }
};

const styles = StyleSheet.create({
  username: {
    color: '#aaa'
  }
});

export default MessagesScreen;