Message Notification

Dishank Poddar
Yodaplus
Published in
4 min readOct 15, 2021

What is it, and why is it needed?

In case your application is more than just chat, it is a good idea to notify the users when they have received a new message. So we will create a simple notification icon and populate and update it with the number of unread messages

Prerequisites

Steps

  • Add the following view to views.py
def get_unread_message_count(request):
user = request.user
response = {}
established_connections_as_user1 = ConnectionEstablished.objects.filter(
user1=user,
status=ConnectionEstablished.OPEN
)
established_connections_as_user2 = ConnectionEstablished.objects.filter(
user2=user,
status=ConnectionEstablished.OPEN
)
unread_messages_count = 0
for established_connection in established_connections_as_user1:
unread_messages_count += Message.objects.filter(
connection_established=established_connection,
author=user2,
read=False).count()
for established_connection in established_connections_as_user2:
unread_messages_count += Message.objects.filter(
connection_established=established_connection,
author=user1,
read=False).count()
response['unread_messages_count'] = unread_messages_count
return JsonResponse(response)
return JsonResponse(response)

This is just a util API created to provide with the number of unread messages a user has

  • Ensure a similar HTML exists in your base.html
<div class="topbar-item" data-offset="10px,0px">
<a href="{% url 'chat:default' %}" id="chat-icon" class="btn btn-icon btn-hover-transparent-white btn-dropdown btn-lg mr-2 "><!-- chat:default is a link to a generic page where one can access the sidebar -->
<span class="fa-layers fa-fw fa-2x">
<i class="far fa-comment-alt text-dark"></i>
<span id="chat-count" style="background:Tomato"></span>
</span>
<span class="pulse-ring"></span>
</a>
</div>
<!-- This is made using the theme, you will need something which fits your theme -->
  • Add the following JS to base.html

Get Count Unread Messages JS

<script>    
function get_unread_message_count(){
fetch("{% url 'chat:unread_message_count' %}", {
method: "GET",
})
.then((response) => {
if (response.ok != true) {
toastr.error(response.statusText);
return null
}
else {
return response.json()
}
})
.then((data) => {
if(data.unread_messages_count){ //All classes here a part of the theme, you will have to add these animations yourself
$("#chat-icon").addClass("pulse pulse-danger");
$("#chat-count").addClass("fa-layers-counter fa-lg");
$("#chat-count").html(`${data.unread_messages_count}`)
}else{
$("#chat-icon").removeClass("pulse pulse-danger");
$("#chat-count").removeClass("fa-layers-counter");
$("#chat-count").html(``)
}
});
return null
}
get_unread_message_count()
</script>
  • Remove the Message Received Socket JS from Dynamic Sidebar and add this version to your base.html

Message Received Socket JS

var url = window.location.href
var websocket_scheme = 'ws'
if(url.includes('https')){
websocket_scheme = 'wss'
}
const messageRecievedSocket = new WebSocket(
`${websocket_scheme}://`
+ window.location.host
+ '/ws/chat/message_recieved/'
);
messageRecievedSocket.onmessage = function(e) {
const data = JSON.parse(e.data);
get_unread_message_count();
if (typeof get_connections_list === "function") {
get_connections_list();
}
};
messageRecievedSocket.onclose = function(e) {
console.error('Message Recieved socket closed unexpectedly with error:', e);
};

If not on chat page, then the notification icon gets the unread count updated, if it is, the sidebar gets updated as well

  • Update the Chat Socket JS from Upgrading Chat to include the following
    Update the chatSocket.onmessage function to this
chatSocket.onmessage = function(e) {
const data = JSON.parse(e.data);
var message = draw_message(data,'scroll_bottom_chat()')
let chat_box = document.querySelector('#chat-log');
chat_box.innerHTML += message;
scroll_bottom_chat()
let read_messages_url = "{% url 'chat:mark_as_read' connection_id %}"
fetch(read_messages_url, {
method: "GET",
headers: {
"Content-type": "application/json; charset=UTF-8",
},
})
.then((response) => {
if (response.ok != true) {
toastr.error(response.statusText);
}
else {
get_unread_message_count(); //part added
get_connections_list()
}
})
};

Once a message is read, the notification icon iis updated to reflect the correct unread count

  • Update the Get Messages JS from Infinite Chat Scrollbar to include the following
    Update the IntersectionObserver function to this
var observer = new IntersectionObserver(function(entries) {
if(entries[0].isIntersecting === true){
url = `
{% url 'chat:get_messages' connection_id %}?page=${page}
`
fetch(url, {
method: "GET",
headers: {
"Content-type": "application/json; charset=UTF-8",
},
})
.then((response) => {
if (response.ok != true) {
toastr.error(response.statusText);
return null
}
else {
return response.json()
}
})
.then(function (data) {
if(data.success === true){
var add_messages = ``
if(data.messages.length==0){
add_messages = `
<div class="text-center">
No conversation yet
</div>
`
{% endif %}
}
for(message of data.messages){
var add_message = draw_message(message,`scroll_top_load(${page})`)
add_messages += add_message
}
add_messages += `<div id='messages-page-${page}'></div>`;
let chat_box = document.querySelector('#chat-log');
chat_box.innerHTML = add_messages + chat_box.innerHTML;
scroll_top_load(page++);
let read_messages_url = "{% url 'chat:mark_as_read' connection_id %}"
fetch(read_messages_url, {
method: "GET",
headers: {
"Content-type": "application/json; charset=UTF-8",
},
})
.then((response) => {
if (response.ok != true) {
toastr.error(response.statusText);
}
else {
get_unread_message_count(); //part added
}
})
}
})
}
observer.observe(document.querySelector("#message-loader"));
}, { root: null });

Once messages are loaded, the notification icon is updated to reflect the correct unread count

  • Update urls.py with your API
urlpatterns += [
path('unread_message_count/', views.get_unread_message_count,
name='unread_message_count'),
]

Related Articles

--

--