forked from Bearle/django-private-chat
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added "customize the templates" section to readme
Added django-debug-toolbar to requirements,urls,settings Added dialogs.html custom template to example project, renamed extra_css to css in it
- Loading branch information
Showing
6 changed files
with
317 additions
and
4 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,3 +3,4 @@ | |
|
||
django-private-chat>=0.1.0 | ||
Django==1.10.5 | ||
django-debug-toolbar==1.6 |
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,290 @@ | ||
{# This template is here just to demonstrate how to customize the default one. #} | ||
{# It has none to very few changes #} | ||
{% extends "base.html" %} | ||
{% load static %} | ||
{% load i18n %} | ||
{% block css %} | ||
{% endblock css %} | ||
|
||
{% block content %} | ||
<input id="owner_username" type="hidden" value="{{ request.user.username }}"> | ||
<div class="container"> | ||
<div class="col-md-3"> | ||
<div class="panel panel-default"> | ||
<div class="panel-heading"> | ||
<h3 class="panel-title">{% trans "Chat list" %}</h3> | ||
</div> | ||
<div class="panel-body"> | ||
<div class="user-list-div"> | ||
<ul style="list-style-type: none;"> | ||
{% for dialog in object_list %} | ||
<li> | ||
{% if dialog.owner == request.user %} | ||
{% with dialog.opponent.username as username %} | ||
<a href="{% url 'dialogs_detail' username %}" id="user-{{ username }}" | ||
class="btn btn-danger">{% trans "Chat with" %} {{ username }}</a> | ||
{% endwith %} | ||
{% else %} | ||
{% with dialog.owner.username as username %} | ||
<a href="{% url 'dialogs_detail' username %}" id="user-{{ username }}" | ||
class="btn btn-danger">{% trans "Chat with" %} {{ username }}</a> | ||
{% endwith %} | ||
{% endif %} | ||
</li> | ||
{% endfor %} | ||
</ul> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
<div class="col-md-9"> | ||
<div class="well well-lg"> | ||
<div class="row"> | ||
<div class="col-md-3 col-md-offset-9"> | ||
<span class="pull-right" hidden id="typing-text"> | ||
<strong>{{ opponent_username }} {% trans "is typing..." %}</strong> | ||
</span> | ||
</div> | ||
<p> | ||
{{ opponent_username }} | ||
</p> | ||
<p class="text-success" id="online-status" style="display: none">{% trans "Online" %}</p> | ||
<p class="text-danger" id="offline-status" style="display: none">{% trans "Offline" %}</p> | ||
|
||
<div class="messages-container"> | ||
<div id="messages" class="messages"> | ||
{% for msg in active_dialog.messages.all %} | ||
<div class="row"> | ||
<p class="{% if msg.sender == request.user %}pull-left{% else %}pull-right{% endif %}"> | ||
<span class="username">{{ msg.sender.username }}:</span> | ||
{{ msg.text }} | ||
<span class="timestamp">– <span | ||
data-livestamp="{{ msg.get_formatted_create_datetime }}">{{ msg.get_formatted_create_datetime }}</span></span> | ||
</p> | ||
</div> | ||
{% endfor %} | ||
</div> | ||
</div> | ||
</div> | ||
|
||
<div class="row"> | ||
<div class="add-message"> | ||
<div class="form-group"> | ||
<textarea id="chat-message" class="form-control message" | ||
placeholder="{% trans 'Write a message' %}"></textarea> | ||
</div> | ||
|
||
<div class="form-group clearfix"> | ||
<input id="btn-send-message" type="submit" class="btn btn-primary pull-right send-message" | ||
style="margin-left: 10px;" value="{% trans 'Send' %}"/> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
{% endblock %} | ||
|
||
{% block extra_js %} | ||
<script> | ||
var base_ws_server_path = "{{ ws_server_path }}"; | ||
$(document).ready(function () { | ||
var websocket = null; | ||
|
||
function getOpponnentUsername() { | ||
return "{{ opponent_username }}"; | ||
} | ||
|
||
// TODO: Use for adding new dialog | ||
function addNewUser(packet) { | ||
$('#user-list').html(''); | ||
packet.value.forEach(function (userInfo) { | ||
if (userInfo.username == getUsername()) return; | ||
var tmpl = Handlebars.compile($('#user-list-item-template').html()); | ||
$('#user-list').append(tmpl(userInfo)) | ||
}); | ||
} | ||
|
||
function addNewMessage(packet) { | ||
var msg_class = ""; | ||
if (packet['sender_name'] == $("#owner_username").val()) { | ||
msg_class = "pull-left"; | ||
} else { | ||
msg_class = "pull-right"; | ||
} | ||
var msgElem = | ||
$('<div class="row">' + | ||
'<p class="' + msg_class + '">' + | ||
'<span class="username">' + packet['sender_name'] + ': </span>' + | ||
packet['message'] + | ||
' <span class="timestamp">– <span data-livestamp="' + packet['created'] + '"> ' + packet['created'] + '</span></span> ' + | ||
'</p> ' + | ||
'</div>'); | ||
$('#messages').append(msgElem); | ||
scrollToLastMessage() | ||
} | ||
|
||
function scrollToLastMessage() { | ||
var $msgs = $('#messages'); | ||
$msgs.animate({"scrollTop": $msgs.prop('scrollHeight')}) | ||
} | ||
|
||
function generateMessage(context) { | ||
var tmpl = Handlebars.compile($('#chat-message-template').html()); | ||
return tmpl({msg: context}) | ||
} | ||
|
||
function setUserOnlineOffline(username, online) { | ||
var elem = $("#user-" + username); | ||
if (online) { | ||
elem.attr("class", "btn btn-success"); | ||
} else { | ||
elem.attr("class", "btn btn-danger"); | ||
} | ||
} | ||
|
||
function gone_online() { | ||
$("#offline-status").hide(); | ||
$("#online-status").show(); | ||
} | ||
|
||
function gone_offline() { | ||
$("#online-status").hide(); | ||
$("#offline-status").show(); | ||
} | ||
|
||
function setupChatWebSocket() { | ||
var opponent_username = getOpponnentUsername(); | ||
websocket = new WebSocket(base_ws_server_path + '{{ request.session.session_key }}/' + opponent_username); | ||
|
||
websocket.onopen = function (event) { | ||
var opponent_username = getOpponnentUsername(); | ||
|
||
var onOnlineCheckPacket = JSON.stringify({ | ||
type: "check-online", | ||
session_key: '{{ request.session.session_key }}', | ||
username: opponent_username | ||
{# Sending username because the user needs to know if his opponent is online #} | ||
}); | ||
var onConnectPacket = JSON.stringify({ | ||
type: "online", | ||
session_key: '{{ request.session.session_key }}' | ||
|
||
}); | ||
|
||
console.log('connected, sending:', onConnectPacket); | ||
websocket.send(onConnectPacket); | ||
console.log('checking online opponents with:', onOnlineCheckPacket); | ||
websocket.send(onOnlineCheckPacket); | ||
}; | ||
|
||
|
||
window.onbeforeunload = function () { | ||
|
||
var onClosePacket = JSON.stringify({ | ||
type: "offline", | ||
session_key: '{{ request.session.session_key }}', | ||
username: opponent_username, | ||
{# Sending username because to let opponnent know that the user went offline #} | ||
}); | ||
console.log('unloading, sending:', onClosePacket); | ||
websocket.send(onClosePacket); | ||
websocket.close(); | ||
}; | ||
|
||
|
||
websocket.onmessage = function (event) { | ||
var packet; | ||
|
||
try { | ||
packet = JSON.parse(event.data); | ||
console.log(packet) | ||
} catch (e) { | ||
console.log(e); | ||
} | ||
|
||
switch (packet.type) { | ||
case "new-dialog": | ||
// TODO: add new dialog to dialog_list | ||
break; | ||
case "user-not-found": | ||
// TODO: dispay some kind of an error that the user is not found | ||
break; | ||
case "gone-online": | ||
if (packet.usernames.indexOf(opponent_username) != -1) { | ||
gone_online(); | ||
} else { | ||
gone_offline(); | ||
} | ||
for (var i = 0; i < packet.usernames.length; ++i) { | ||
setUserOnlineOffline(packet.usernames[i], true); | ||
} | ||
break; | ||
case "gone-offline": | ||
if (packet.username == opponent_username) { | ||
gone_offline(); | ||
} | ||
setUserOnlineOffline(packet.username, false); | ||
break; | ||
case "new-message": | ||
addNewMessage(packet); | ||
break; | ||
case "opponent-typing": | ||
var typing_elem = $('#typing-text'); | ||
if (!typing_elem.is(":visible")) { | ||
typing_elem.fadeIn(500); | ||
} else { | ||
typing_elem.stop(true); | ||
typing_elem.fadeIn(0); | ||
} | ||
typing_elem.fadeOut(3000); | ||
break; | ||
|
||
default: | ||
console.log('error: ', event) | ||
} | ||
} | ||
} | ||
|
||
function sendMessage(message) { | ||
var opponent_username = getOpponnentUsername(); | ||
var newMessagePacket = JSON.stringify({ | ||
type: 'new-message', | ||
session_key: '{{ request.session.session_key }}', | ||
username: opponent_username, | ||
message: message | ||
}); | ||
websocket.send(newMessagePacket) | ||
} | ||
|
||
$('#chat-message').keypress(function (e) { | ||
if (e.which == 13 && this.value) { | ||
sendMessage(this.value); | ||
this.value = ""; | ||
return false | ||
} else { | ||
var opponent_username = getOpponnentUsername(); | ||
var packet = JSON.stringify({ | ||
type: 'is-typing', | ||
session_key: '{{ request.session.session_key }}', | ||
username: opponent_username, | ||
typing: true | ||
}); | ||
websocket.send(packet); | ||
} | ||
}); | ||
|
||
$('#btn-send-message').click(function (e) { | ||
var $chatInput = $('#chat-message'); | ||
var msg = $chatInput.val(); | ||
if (!msg) return; | ||
sendMessage($chatInput.val()); | ||
$chatInput.val('') | ||
}); | ||
|
||
setupChatWebSocket(); | ||
scrollToLastMessage(); | ||
}); | ||
|
||
</script> | ||
{% endblock %} |