Modify Chat UI
This commit is contained in:
parent
9f0213865d
commit
00113848c8
10 changed files with 1663 additions and 1572 deletions
|
@ -18,15 +18,22 @@ class Room(models.Model):
|
|||
Profile, related_name="user_two", verbose_name="user 2", on_delete=CASCADE
|
||||
)
|
||||
|
||||
@cache_wrapper(prefix="Rc")
|
||||
def contain(self, profile):
|
||||
return self.user_one == profile or self.user_two == profile
|
||||
|
||||
@cache_wrapper(prefix="Rou")
|
||||
def other_user(self, profile):
|
||||
return self.user_one if profile == self.user_two else self.user_two
|
||||
|
||||
@cache_wrapper(prefix="Rus")
|
||||
def users(self):
|
||||
return [self.user_one, self.user_two]
|
||||
|
||||
@cache_wrapper(prefix="Rlmb")
|
||||
def last_message_body(self):
|
||||
return self.message_set.first().body
|
||||
|
||||
|
||||
class Message(models.Model):
|
||||
author = models.ForeignKey(Profile, verbose_name=_("user"), on_delete=CASCADE)
|
||||
|
|
|
@ -22,6 +22,7 @@ from django.db.models import (
|
|||
Count,
|
||||
IntegerField,
|
||||
F,
|
||||
Max,
|
||||
)
|
||||
from django.db.models.functions import Coalesce
|
||||
from django.utils import timezone
|
||||
|
@ -206,6 +207,7 @@ def post_message(request):
|
|||
},
|
||||
)
|
||||
else:
|
||||
Room.last_message_body.dirty(room)
|
||||
for user in room.users():
|
||||
event.post(
|
||||
encrypt_channel("chat_" + str(user.id)),
|
||||
|
@ -342,15 +344,31 @@ def get_online_status(profile, other_profile_ids, rooms=None):
|
|||
if rooms:
|
||||
unread_count = get_unread_count(rooms, profile)
|
||||
count = {}
|
||||
last_msg = {}
|
||||
room_of_user = {}
|
||||
for i in unread_count:
|
||||
count[i["other_user"]] = i["unread_count"]
|
||||
room = Room.objects.get(id=i["room"])
|
||||
other_profile = room.other_user(profile)
|
||||
count[other_profile.id] = i["unread_count"]
|
||||
for room in rooms:
|
||||
room = Room.objects.get(id=room)
|
||||
other_profile = room.other_user(profile)
|
||||
last_msg[other_profile.id] = room.last_message_body()
|
||||
room_of_user[other_profile.id] = room.id
|
||||
|
||||
for other_profile in other_profiles:
|
||||
is_online = False
|
||||
if other_profile.last_access >= last_5_minutes:
|
||||
is_online = True
|
||||
user_dict = {"user": other_profile, "is_online": is_online}
|
||||
if rooms and other_profile.id in count:
|
||||
user_dict["unread_count"] = count[other_profile.id]
|
||||
if rooms:
|
||||
user_dict.update(
|
||||
{
|
||||
"unread_count": count.get(other_profile.id),
|
||||
"last_msg": last_msg.get(other_profile.id),
|
||||
"room": room_of_user.get(other_profile.id),
|
||||
}
|
||||
)
|
||||
user_dict["url"] = encrypt_url(profile.id, other_profile.id)
|
||||
ret.append(user_dict)
|
||||
return ret
|
||||
|
@ -386,17 +404,9 @@ def get_status_context(profile, include_ignored=False):
|
|||
|
||||
recent_profile_ids = [str(i["other_user"]) for i in recent_profile]
|
||||
recent_rooms = [int(i["id"]) for i in recent_profile]
|
||||
friend_list = (
|
||||
Friend.get_friend_profiles(profile)
|
||||
.exclude(id__in=recent_profile_ids)
|
||||
.exclude(id__in=ignored_users)
|
||||
.order_by("-last_access")
|
||||
.values_list("id", flat=True)
|
||||
)
|
||||
|
||||
admin_list = (
|
||||
queryset.filter(display_rank="admin")
|
||||
.exclude(id__in=friend_list)
|
||||
.exclude(id__in=recent_profile_ids)
|
||||
.values_list("id", flat=True)
|
||||
)
|
||||
|
@ -405,7 +415,6 @@ def get_status_context(profile, include_ignored=False):
|
|||
queryset.filter(last_access__gte=last_5_minutes)
|
||||
.annotate(is_online=Case(default=True, output_field=BooleanField()))
|
||||
.order_by("-rating")
|
||||
.exclude(id__in=friend_list)
|
||||
.exclude(id__in=admin_list)
|
||||
.exclude(id__in=recent_profile_ids)
|
||||
.values_list("id", flat=True)[:30]
|
||||
|
@ -416,10 +425,6 @@ def get_status_context(profile, include_ignored=False):
|
|||
"title": "Recent",
|
||||
"user_list": get_online_status(profile, recent_profile_ids, recent_rooms),
|
||||
},
|
||||
{
|
||||
"title": "Following",
|
||||
"user_list": get_online_status(profile, friend_list),
|
||||
},
|
||||
{
|
||||
"title": "Admin",
|
||||
"user_list": get_online_status(profile, admin_list),
|
||||
|
@ -488,18 +493,9 @@ def get_or_create_room(request):
|
|||
|
||||
def get_unread_count(rooms, user):
|
||||
if rooms:
|
||||
res = (
|
||||
UserRoom.objects.filter(user=user, room__in=rooms, unread_count__gt=0)
|
||||
.select_related("room__user_one", "room__user_two")
|
||||
.values("unread_count", "room__user_one", "room__user_two")
|
||||
)
|
||||
for ur in res:
|
||||
ur["other_user"] = (
|
||||
ur["room__user_one"]
|
||||
if ur["room__user_two"] == user.id
|
||||
else ur["room__user_two"]
|
||||
)
|
||||
return res
|
||||
return UserRoom.objects.filter(
|
||||
user=user, room__in=rooms, unread_count__gt=0
|
||||
).values("unread_count", "room")
|
||||
else: # lobby
|
||||
user_room = UserRoom.objects.filter(user=user, room__isnull=True).first()
|
||||
if not user_room:
|
||||
|
|
|
@ -5,9 +5,10 @@ from django.db.models.query import QuerySet
|
|||
import hashlib
|
||||
|
||||
MAX_NUM_CHAR = 15
|
||||
NONE_RESULT = "__None__"
|
||||
|
||||
|
||||
def cache_wrapper(prefix, timeout=86400):
|
||||
def cache_wrapper(prefix, timeout=None):
|
||||
def arg_to_str(arg):
|
||||
if hasattr(arg, "id"):
|
||||
return str(arg.id)
|
||||
|
@ -31,8 +32,11 @@ def cache_wrapper(prefix, timeout=86400):
|
|||
cache_key = get_key(func, *args, **kwargs)
|
||||
result = cache.get(cache_key)
|
||||
if result is not None:
|
||||
if result == NONE_RESULT:
|
||||
result = None
|
||||
return result
|
||||
|
||||
if result is None:
|
||||
result = NONE_RESULT
|
||||
result = func(*args, **kwargs)
|
||||
cache.set(cache_key, result, timeout)
|
||||
return result
|
||||
|
|
|
@ -47,11 +47,6 @@ else:
|
|||
"pagedown-extra/Markdown.Extra.js",
|
||||
"pagedown_init.js",
|
||||
]
|
||||
css = {
|
||||
"all": [
|
||||
"markdown.css",
|
||||
]
|
||||
}
|
||||
|
||||
class AdminPagedownWidget(PagedownWidget, admin_widgets.AdminTextareaWidget):
|
||||
class Media:
|
||||
|
@ -60,7 +55,6 @@ else:
|
|||
"pagedown_widget.css",
|
||||
"content-description.css",
|
||||
"admin/css/pagedown.css",
|
||||
"markdown.css",
|
||||
"pagedown.css",
|
||||
]
|
||||
}
|
||||
|
@ -125,7 +119,6 @@ else:
|
|||
"pygment-github.css",
|
||||
"table.css",
|
||||
"ranks.css",
|
||||
"markdown.css",
|
||||
"dmmd-preview.css",
|
||||
]
|
||||
}
|
||||
|
|
|
@ -39,15 +39,15 @@
|
|||
#chat-online {
|
||||
border-right: 1px solid #ccc;
|
||||
padding-bottom: 0 !important;
|
||||
min-width: 25%;
|
||||
border-bottom: 0;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
#chat-online-content {
|
||||
margin-bottom: 0;
|
||||
overflow: hidden;
|
||||
overflow-wrap: break-word;
|
||||
overflow-y: auto;
|
||||
max-height: calc(100% - 44px);
|
||||
max-height: 100%;
|
||||
}
|
||||
#chat-box {
|
||||
/*border: 1px solid #ccc;*/
|
||||
|
@ -75,6 +75,14 @@
|
|||
padding: 0;
|
||||
width: 100%;
|
||||
}
|
||||
.selected-status-row {
|
||||
background-color: lightgray;
|
||||
}
|
||||
.status_last_message {
|
||||
color: darkgray;
|
||||
font-size: 0.8em;
|
||||
}
|
||||
|
||||
@media (min-width: 800px) {
|
||||
#chat-container {
|
||||
display: flex;
|
||||
|
@ -86,6 +94,10 @@
|
|||
}
|
||||
#chat-online {
|
||||
margin: 0;
|
||||
width: 35%;
|
||||
}
|
||||
#chat-area {
|
||||
flex-grow: 1;
|
||||
}
|
||||
.chat-left-panel, .chat-right-panel {
|
||||
display: block !important;
|
||||
|
@ -138,29 +150,29 @@
|
|||
transition: 1.5s ease-in-out;
|
||||
}
|
||||
.status-pic {
|
||||
height: 1.3em;
|
||||
width: 1.3em;
|
||||
border-radius: 0.3em;
|
||||
height: 32px;
|
||||
width: 32px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.status-container {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
.status-circle {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
cx: 18px;
|
||||
cy: 18px;
|
||||
cx: 27px;
|
||||
cy: 27px;
|
||||
r: 4.5px;
|
||||
stroke: white;
|
||||
stroke-width: 1;
|
||||
}
|
||||
.status-row {
|
||||
display: flex;
|
||||
font-size: 15px;
|
||||
padding: 0.2em 0.2em 0.2em 1em;
|
||||
border-radius: 4px;
|
||||
padding: 15px;
|
||||
gap: 0.5em;
|
||||
}
|
||||
.status-row:hover {
|
||||
background: lightgray;
|
||||
|
@ -168,6 +180,7 @@
|
|||
}
|
||||
.status-list {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.status-section-title {
|
||||
cursor: pointer;
|
||||
|
@ -200,6 +213,7 @@
|
|||
background-color: darkcyan;
|
||||
border-radius: 2px;
|
||||
padding: 0 0.5em;
|
||||
align-self: flex-end;
|
||||
}
|
||||
#setting-content {
|
||||
display: none;
|
||||
|
@ -225,7 +239,7 @@
|
|||
|
||||
@media (max-width: 799px) {
|
||||
#chat-area {
|
||||
height: 500px;
|
||||
height: calc(100vh - 50px);
|
||||
}
|
||||
#emoji-button {
|
||||
display: none;
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -20,7 +20,6 @@
|
|||
window.lock = false;
|
||||
window.lock_click_space = false;
|
||||
window.pushed_messages = new Set();
|
||||
let isMobile = window.matchMedia("only screen and (max-width: 799px)").matches;
|
||||
|
||||
window.load_dynamic_update = function (last_msg) {
|
||||
var receiver = new EventReceiver(
|
||||
|
@ -71,25 +70,20 @@
|
|||
|
||||
<div id="chat-container">
|
||||
<div id="chat-online" class="chat-right-panel sidebox">
|
||||
<h3>
|
||||
<i class="fa fa-users"></i>{{_('Online Users')}}
|
||||
</h3>
|
||||
<div id="chat-online-content">
|
||||
<div id="search-container">
|
||||
<center>
|
||||
<form id="search-form" name="form" action="{{ url('get_or_create_room') }}" method="post">
|
||||
<form id="chat-search-form" name="form" action="{{ url('get_or_create_room') }}" method="post">
|
||||
{% csrf_token %}
|
||||
<input id="search-handle" type="text" name="search"
|
||||
placeholder="{{ _('Search by handle...') }}">
|
||||
</form>
|
||||
</center>
|
||||
</div>
|
||||
<div id="chat-online-list">
|
||||
{% include "chat/online_status.html" %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="chat-area" class="chat-left-panel" style="width:100%">
|
||||
<div id="chat-area" class="chat-left-panel">
|
||||
<div id="chat-info" style="height: 10%">
|
||||
{% include 'chat/user_online_status.html' %}
|
||||
</div>
|
||||
|
|
|
@ -102,12 +102,22 @@
|
|||
float: inherit;
|
||||
}
|
||||
#search-container {
|
||||
margin-bottom: 0.4em;
|
||||
padding: 1em;
|
||||
}
|
||||
#setting {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.status-user {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.wrapline {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
@media (min-width: 800px) {
|
||||
#page-container {
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
"{{_('Admin')}}",
|
||||
"{{_('Other')}}",
|
||||
];
|
||||
let isMobile = window.matchMedia("only screen and (max-width: 799px)").matches;
|
||||
|
||||
function load_next_page(last_id, refresh_html=false) {
|
||||
var param = {
|
||||
'last_id': last_id,
|
||||
|
@ -82,6 +84,7 @@
|
|||
register_toggle($(this));
|
||||
});
|
||||
register_click_space();
|
||||
color_selected_room();
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -207,6 +210,9 @@
|
|||
}
|
||||
|
||||
function add_message_from_template(body, tmp_id) {
|
||||
if (window.room_id) {
|
||||
$("#last_msg-" + window.room_id).html(body);
|
||||
}
|
||||
var html = message_template;
|
||||
html = html.replaceAll('$body', body).replaceAll('$id', tmp_id);
|
||||
var $html = $(html);
|
||||
|
@ -267,6 +273,11 @@
|
|||
}
|
||||
}
|
||||
|
||||
function color_selected_room() {
|
||||
$(".status-row").removeClass("selected-status-row");
|
||||
$("#click_space_" + window.other_user_id).addClass("selected-status-row");
|
||||
}
|
||||
|
||||
function load_room(encrypted_user) {
|
||||
if (window.lock_click_space) return;
|
||||
|
||||
|
@ -283,6 +294,7 @@
|
|||
.done(function(data) {
|
||||
window.room_id = data.room;
|
||||
window.other_user_id = data.other_user_id;
|
||||
color_selected_room();
|
||||
callback();
|
||||
})
|
||||
.fail(function() {
|
||||
|
@ -292,6 +304,7 @@
|
|||
else {
|
||||
window.room_id = '';
|
||||
window.other_user_id = '';
|
||||
color_selected_room();
|
||||
callback();
|
||||
}
|
||||
window.lock_click_space = false;
|
||||
|
@ -494,7 +507,7 @@
|
|||
|
||||
var in_user_redirect = false;
|
||||
$('#search-handle').select2({
|
||||
placeholder: '{{ _('Search by handle...') }}',
|
||||
placeholder: '<i class="fa fa-search"></i> {{ _('Search by handle...') }}',
|
||||
ajax: {
|
||||
url: '{{ url('chat_user_search_select2_ajax') }}'
|
||||
},
|
||||
|
@ -544,5 +557,6 @@
|
|||
})
|
||||
}
|
||||
register_setting();
|
||||
color_selected_room();
|
||||
});
|
||||
</script>
|
|
@ -27,11 +27,18 @@
|
|||
fill="{{'green' if user.is_online else 'red'}}"/>
|
||||
</svg>
|
||||
</div>
|
||||
<span style="padding-left:0.3em" class="username {{ user.user.css_class }}">
|
||||
<div class="status-user">
|
||||
<span class="username {{ user.user.css_class }} wrapline">
|
||||
{{ user.user.username }}
|
||||
</span>
|
||||
<span class="spacer">
|
||||
<span class="unread-count" id="unread-count-{{user.user.id}}">{{user.unread_count if user.unread_count}}</span>
|
||||
{% if user.last_msg %}
|
||||
<span class="status_last_message wrapline" {% if user.room %}id="last_msg-{{user.room}}"{% endif %}>
|
||||
{{ user.last_msg }}
|
||||
</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<span class="unread-count" id="unread-count-{{user.user.id}}">
|
||||
{{user.unread_count if user.unread_count}}
|
||||
</span>
|
||||
</li>
|
||||
{% endfor %}
|
||||
|
|
Loading…
Reference in a new issue