1-
2- <div id =" chat-container" >
3- <div id =" search-container" >
4- <input type =" text" placeholder =" Search" />
5- </div >
6-
7- <div class =" new-message-container" onclick =" openModal()" >
8- <a href =" #" >+</a >
9- </div >
10-
11- <div id =" chat-title" >
12- <span id =" conversation-partner" ></span >
13- <img src =" ./images/trash.png" alt =" Delete Conversation" />
14- </div >
15-
16- <!-- placeholder div if no messages are in messages area -->
17- <div id =" chat-message-list" >
18- <div class =" nothing" >select a conversation</div >
19- </div >
20-
21- <!-- send message form -->
22- <form id =" chat-form" method =" post" enctype =" multipart/form-data" >
23- <label for =" attachment" ><img src =" ./images/attachment.png" alt =" Add Attachment" /></label >
24- <input type =" file" multiple name =" attachment" class =" hide" id =" attachment" />
25- <input type =" text" name =" message" placeholder =" Type a message" autocomplete =" off" />
26- </form >
27-
28- </div >
29- <% - include (' ./partials/add-conversation-modal.ejs' ); %>
30-
31- <!-- import socket io client from cdn -->
32- <script src =" https://cdnjs.cloudflare.com/ajax/libs/socket.io/3.1.3/socket.io.min.js" ></script >
33-
34- <script >
35- const form = document .querySelector (' #chat-form' );
36- const messageContainer = document .querySelector (' #chat-message-list' );
37- const chatTitleContainer = document .querySelector (' #conversation-partner' );
38- const loggedinUserId = ' <%= loggedInUser.userid %>' ;
39- const loggedinUserName = ' <%= loggedInUser.username %>' ;
40- let participant = null ; // selected conversation participant object
41- let current_conversation_id; // selected conversation id
42-
43- // socket initialization
44- const socket = io (' <%= process.env.APP_URL %>' );
45-
46- // handle new/live incoming message from socket
47- socket .on (" new_message" , data => {
48- // only respond if current conversation is open in any client
49- if (data .message .conversation_id == current_conversation_id) {
50- // message class
51- const messageClass = data .message .sender .id === loggedinUserId ? ' you-message' : ' other-message' ;
52-
53- const senderAvatar = data .message .sender .avatar ? ` <img src="./uploads/avatars/${ data .message .sender .avatar } " alt="${ data .message .sender .name } " />` : ` <img src="./images/nophoto.png" alt="${ data .message .sender .name } " />` ;
54- // message attachments
55- let attachments = ' <div class="attachments">' ;
56- if (data .message .attachment && data .message .attachment .length > 0 ) {
57- data .message .attachment .forEach (attachment => {
58- attachments += ` <img src="./uploads/attachments/${ attachment} " /> ` ;
59- });
60- }
61- attachments += ' </div>' ;
62- let messageHTML;
63- // do not show avatar for loggedin user
64- if (data .message .sender .id == loggedinUserId) {
65- messageHTML = ` <div class="message-row ${ messageClass} "><div class="message-content">
66- <div class="message-text">${ data .message .message } </div>
67- ${ attachments}
68- <div class="message-time">${ moment (data .message .date_time ).fromNow ()} </div>
69- </div></div>` ;
70- } else {
71- messageHTML = ` <div class="message-row ${ messageClass} "><div class="message-content">
72- ${ senderAvatar}
73- <div class="message-text">${ data .message .message } </div>
74- ${ attachments}
75- <div class="message-time">${ moment (data .message .date_time ).fromNow ()} </div>
76- </div></div>` ;
77- }
78- // append the inoming message to message area as last item
79- document .querySelector (' #chat-message-list > .message-row:first-child' ).insertAdjacentHTML (' beforeBegin' , messageHTML);
80- }
81- });
82-
83- // get messages of a conversation
84- async function getMessages (conversation_id , current_conversation_name ){
85- // messages failure toast
86- const messagesFailureToast = Toastify ({
87- text: " Error loading messages!" ,
88- duration: 1000 ,
89- });
90- let response = await fetch (` /inbox/messages/${ conversation_id} ` );
91- const result = await response .json ();
92- if (! result .errors && result .data ) {
93- form .style .visibility = ' visible' ;
94-
95- const {data , user , conversation_id } = result;
96- participant = data .participant ;
97- current_conversation_id = conversation_id;
98- if (data .messages ) {
99- let allMessages = ' ' ;
100- if (data .messages .length > 0 ) {
101- data .messages .forEach ((message ) => {
102- let senderAvatar = message .sender .avatar ? ` ./uploads/avatars/${ message .sender .avatar } ` : ' ./images/nophoto.png' ;
103- const messageClass = message .sender .id === loggedinUserId ? ' you-message' : ' other-message' ;
104- const showAvatar = message .sender .id === loggedinUserId ? ' ' : ` <img src="${ senderAvatar} " alt="${ message .sender .name } " />` ;
105- // message attachments
106- let attachments = ' <div class="attachments">' ;
107- if (message .attachment && message .attachment .length > 0 ) {
108- message .attachment .forEach (attachment => {
109- attachments += ` <img src="./uploads/attachments/${ attachment} " /> ` ;
110- });
111- }
112- attachments += ' </div>' ;
113- // final message html
114- let messageHTML = ` <div class="message-row ${ messageClass} "><div class="message-content">
115- ${ showAvatar}
116- <div class="message-text">${ message .text } </div>
117- ${ attachments}
118- <div class="message-time">${ moment (message .date_time ).fromNow ()} </div>
119- </div></div>` ;
120- allMessages += messageHTML;
121- messageContainer .innerHTML = allMessages;
122- });
123- } else if (data .messages .length === 0 ) {
124- messageContainer .innerHTML = ' <div class="message-row"></div>' ;
125- }
126- chatTitleContainer .textContent = current_conversation_name;
127- }
128- } else {
129- messagesFailureToast .showToast ();
130- }
131- }
132-
133- // message sending
134- form .onsubmit = async function (event ) {
135- event .preventDefault ();
136- const sendMessageFailureToast = Toastify ({
137- text: " Error sending message" ,
138- duration: 1000 ,
139- });
140- // prepare the form data
141- const formData = new FormData (form);
142- formData .append (' receiverId' , participant .id );
143- formData .append (' receiverName' , participant .name );
144- formData .append (' avatar' , participant .avatar || ' ' );
145- formData .append (' conversationId' , current_conversation_id);
146-
147- // send the request to server
148- let response = await fetch (" /inbox/message" , {
149- method: " POST" ,
150- body: formData,
151- });
152- // get response
153- let result = await response .json ();
154- if (! result .errors ) {
155- form .reset (); // reset the form
156- } else {
157- sendMessageFailureToast .showToast ();
158- }
159- }
160-
161- </script >
162- </body >
163- </html >
0 commit comments