Make chat faster

This commit is contained in:
cuom1999 2023-11-01 20:54:09 -05:00
parent 58f3807b8d
commit e5b2481345
10 changed files with 135 additions and 102 deletions

View file

@ -0,0 +1,33 @@
# Generated by Django 3.2.18 on 2023-11-02 01:41
from django.db import migrations, models
def migrate(apps, schema_editor):
Room = apps.get_model("chat_box", "Room")
Message = apps.get_model("chat_box", "Message")
for room in Room.objects.all():
messages = room.message_set
last_msg = messages.first()
if last_msg:
room.last_msg_time = last_msg.time
room.save()
class Migration(migrations.Migration):
dependencies = [
("chat_box", "0014_userroom_unread_count"),
]
operations = [
migrations.AddField(
model_name="room",
name="last_msg_time",
field=models.DateTimeField(
db_index=True, null=True, verbose_name="last seen"
),
),
migrations.RunPython(migrate, migrations.RunPython.noop, atomic=True),
]

View file

@ -1,6 +1,7 @@
from django.db import models from django.db import models
from django.db.models import CASCADE, Q from django.db.models import CASCADE, Q
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django.utils.functional import cached_property
from judge.models.profile import Profile from judge.models.profile import Profile
@ -17,25 +18,39 @@ class Room(models.Model):
user_two = models.ForeignKey( user_two = models.ForeignKey(
Profile, related_name="user_two", verbose_name="user 2", on_delete=CASCADE Profile, related_name="user_two", verbose_name="user 2", on_delete=CASCADE
) )
last_msg_time = models.DateTimeField(
verbose_name=_("last seen"), null=True, db_index=True
)
class Meta: class Meta:
app_label = "chat_box" app_label = "chat_box"
@cache_wrapper(prefix="Rc") @cache_wrapper(prefix="Rinfo")
def contain(self, profile): def _info(self):
return self.user_one == profile or self.user_two == profile return {
"user_ids": [self.user_one.id, self.user_two.id],
"last_message": self.message_set.first().body,
}
@cached_property
def _cached_info(self):
return self._info()
def contain(self, profile):
return profile.id in self._cached_info["user_ids"]
@cache_wrapper(prefix="Rou")
def other_user(self, profile): def other_user(self, profile):
return self.user_one if profile == self.user_two else self.user_two return self.user_one if profile == self.user_two else self.user_two
@cache_wrapper(prefix="Rus") def other_user_id(self, profile):
user_ids = self._cached_info["user_ids"]
return sum(user_ids) - profile.id
def users(self): def users(self):
return [self.user_one, self.user_two] return [self.user_one, self.user_two]
@cache_wrapper(prefix="Rlmb")
def last_message_body(self): def last_message_body(self):
return self.message_set.first().body return self._cached_info["last_message"]
class Message(models.Model): class Message(models.Model):

View file

@ -84,8 +84,8 @@ class ChatView(ListView):
self.room_id = request_room self.room_id = request_room
self.messages = ( self.messages = (
Message.objects.filter(hidden=False, room=self.room_id, id__lt=last_id) Message.objects.filter(hidden=False, room=self.room_id, id__lt=last_id)
.select_related("author", "author__user") .select_related("author")
.defer("author__about", "author__user_script")[:page_size] .only("body", "time", "author__rating", "author__display_rank")[:page_size]
) )
if not only_messages: if not only_messages:
return super().get(request, *args, **kwargs) return super().get(request, *args, **kwargs)
@ -204,7 +204,9 @@ def post_message(request):
}, },
) )
else: else:
Room.last_message_body.dirty(room) Room._info.dirty(room)
room.last_msg_time = new_message.time
room.save()
for user in room.users(): for user in room.users():
event.post( event.post(
@ -351,11 +353,11 @@ def get_online_status(profile, other_profile_ids, rooms=None):
room = Room.objects.get(id=i["room"]) room = Room.objects.get(id=i["room"])
other_profile = room.other_user(profile) other_profile = room.other_user(profile)
count[other_profile.id] = i["unread_count"] count[other_profile.id] = i["unread_count"]
rooms = Room.objects.filter(id__in=rooms)
for room in rooms: for room in rooms:
room = Room.objects.get(id=room) other_profile_id = room.other_user_id(profile)
other_profile = room.other_user(profile) last_msg[other_profile_id] = room.last_message_body()
last_msg[other_profile.id] = room.last_message_body() room_of_user[other_profile_id] = room.id
room_of_user[other_profile.id] = room.id
for other_profile in other_profiles: for other_profile in other_profiles:
is_online = False is_online = False
@ -389,9 +391,6 @@ def get_status_context(profile, include_ignored=False):
recent_profile = ( recent_profile = (
Room.objects.filter(Q(user_one=profile) | Q(user_two=profile)) Room.objects.filter(Q(user_one=profile) | Q(user_two=profile))
.annotate( .annotate(
last_msg_time=Subquery(
Message.objects.filter(room=OuterRef("pk")).values("time")[:1]
),
other_user=Case( other_user=Case(
When(user_one=profile, then="user_two"), When(user_one=profile, then="user_two"),
default="user_one", default="user_one",
@ -412,28 +411,15 @@ def get_status_context(profile, include_ignored=False):
.values_list("id", flat=True) .values_list("id", flat=True)
) )
all_user_status = (
queryset.filter(last_access__gte=last_5_minutes)
.annotate(is_online=Case(default=True, output_field=BooleanField()))
.order_by("-rating")
.exclude(id__in=admin_list)
.exclude(id__in=recent_profile_ids)
.values_list("id", flat=True)[:30]
)
return [ return [
{ {
"title": "Recent", "title": _("Recent"),
"user_list": get_online_status(profile, recent_profile_ids, recent_rooms), "user_list": get_online_status(profile, recent_profile_ids, recent_rooms),
}, },
{ {
"title": "Admin", "title": _("Admin"),
"user_list": get_online_status(profile, admin_list), "user_list": get_online_status(profile, admin_list),
}, },
{
"title": "Other",
"user_list": get_online_status(profile, all_user_status),
},
] ]

View file

@ -2,7 +2,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: lqdoj2\n" "Project-Id-Version: lqdoj2\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-11-01 13:59+0700\n" "POT-Creation-Date: 2023-11-02 08:11+0700\n"
"PO-Revision-Date: 2021-07-20 03:44\n" "PO-Revision-Date: 2021-07-20 03:44\n"
"Last-Translator: Icyene\n" "Last-Translator: Icyene\n"
"Language-Team: Vietnamese\n" "Language-Team: Vietnamese\n"
@ -18,23 +18,23 @@ msgstr ""
"X-Crowdin-Project-ID: 466004\n" "X-Crowdin-Project-ID: 466004\n"
"X-Crowdin-File-ID: 5\n" "X-Crowdin-File-ID: 5\n"
#: chat_box/models.py:42 chat_box/models.py:68 chat_box/models.py:84 #: chat_box/models.py:54 chat_box/models.py:80 chat_box/models.py:96
#: judge/admin/interface.py:150 judge/models/contest.py:647 #: judge/admin/interface.py:150 judge/models/contest.py:647
#: judge/models/contest.py:853 judge/models/course.py:115 #: judge/models/contest.py:853 judge/models/course.py:115
#: judge/models/profile.py:433 judge/models/profile.py:511 #: judge/models/profile.py:433 judge/models/profile.py:511
msgid "user" msgid "user"
msgstr "người dùng" msgstr "người dùng"
#: chat_box/models.py:44 judge/models/comment.py:44 #: chat_box/models.py:56 judge/models/comment.py:44
#: judge/models/notification.py:17 #: judge/models/notification.py:17
msgid "posted time" msgid "posted time"
msgstr "thời gian đăng" msgstr "thời gian đăng"
#: chat_box/models.py:46 judge/models/comment.py:49 #: chat_box/models.py:58 judge/models/comment.py:49
msgid "body of comment" msgid "body of comment"
msgstr "nội dung bình luận" msgstr "nội dung bình luận"
#: chat_box/models.py:72 #: chat_box/models.py:84
msgid "last seen" msgid "last seen"
msgstr "xem lần cuối" msgstr "xem lần cuối"
@ -42,6 +42,22 @@ msgstr "xem lần cuối"
msgid "LQDOJ Chat" msgid "LQDOJ Chat"
msgstr "" msgstr ""
#: chat_box/views.py:417
msgid "Recent"
msgstr "Gần đây"
#: chat_box/views.py:421 templates/base.html:187
#: templates/comments/content-list.html:78
#: templates/contest/contest-list-tabs.html:4
#: templates/contest/ranking-table.html:47 templates/internal/problem.html:62
#: templates/organization/org-left-sidebar.html:12
#: templates/problem/left-sidebar.html:6
#: templates/problem/problem-list-tabs.html:6
#: templates/submission/info-base.html:12 templates/submission/list.html:395
#: templates/submission/submission-list-tabs.html:15
msgid "Admin"
msgstr "Admin"
#: dmoj/settings.py:364 #: dmoj/settings.py:364
msgid "Vietnamese" msgid "Vietnamese"
msgstr "Tiếng Việt" msgstr "Tiếng Việt"
@ -70,7 +86,7 @@ msgstr "Đăng ký không thành công"
msgid "Login" msgid "Login"
msgstr "Đăng nhập" msgstr "Đăng nhập"
#: dmoj/urls.py:225 templates/base.html:217 #: dmoj/urls.py:225 templates/base.html:111
#: templates/organization/org-left-sidebar.html:2 #: templates/organization/org-left-sidebar.html:2
msgid "Home" msgid "Home"
msgstr "Trang chủ" msgstr "Trang chủ"
@ -179,7 +195,7 @@ msgstr "Tính toán lại kết quả"
msgid "username" msgid "username"
msgstr "tên đăng nhập" msgstr "tên đăng nhập"
#: judge/admin/contest.py:503 templates/base.html:345 #: judge/admin/contest.py:503 templates/base.html:239
msgid "virtual" msgid "virtual"
msgstr "ảo" msgstr "ảo"
@ -242,7 +258,7 @@ msgid "Limits"
msgstr "Giới hạn" msgstr "Giới hạn"
#: judge/admin/problem.py:219 judge/admin/submission.py:351 #: judge/admin/problem.py:219 judge/admin/submission.py:351
#: templates/base.html:261 templates/stats/tab.html:4 #: templates/base.html:155 templates/stats/tab.html:4
#: templates/submission/list.html:347 #: templates/submission/list.html:347
msgid "Language" msgid "Language"
msgstr "Ngôn ngữ" msgstr "Ngôn ngữ"
@ -3553,7 +3569,7 @@ msgid "Updated on site"
msgstr "Được cập nhật trên web" msgstr "Được cập nhật trên web"
#: judge/views/user.py:431 templates/admin/auth/user/change_form.html:14 #: judge/views/user.py:431 templates/admin/auth/user/change_form.html:14
#: templates/admin/auth/user/change_form.html:17 templates/base.html:305 #: templates/admin/auth/user/change_form.html:17 templates/base.html:199
#: templates/user/user-tabs.html:11 #: templates/user/user-tabs.html:11
msgid "Edit profile" msgid "Edit profile"
msgstr "Chỉnh sửa thông tin" msgstr "Chỉnh sửa thông tin"
@ -3648,68 +3664,56 @@ msgstr "Chỉnh sửa thông tin"
msgid "Rejudge" msgid "Rejudge"
msgstr "Chấm lại" msgstr "Chấm lại"
#: templates/base.html:243 #: templates/base.html:137
msgid "Chat" msgid "Chat"
msgstr "Chat" msgstr "Chat"
#: templates/base.html:253 #: templates/base.html:147
msgid "Notification" msgid "Notification"
msgstr "Thông báo" msgstr "Thông báo"
#: templates/base.html:279 #: templates/base.html:173
msgid "Dark Mode" msgid "Dark Mode"
msgstr "" msgstr ""
#: templates/base.html:289 #: templates/base.html:183
msgid "Profile" msgid "Profile"
msgstr "Trang cá nhân" msgstr "Trang cá nhân"
#: templates/base.html:293 templates/chat/chat_js.html:5 #: templates/base.html:192
#: templates/comments/content-list.html:78
#: templates/contest/contest-list-tabs.html:4
#: templates/contest/ranking-table.html:47 templates/internal/problem.html:62
#: templates/organization/org-left-sidebar.html:12
#: templates/problem/left-sidebar.html:6
#: templates/problem/problem-list-tabs.html:6
#: templates/submission/info-base.html:12 templates/submission/list.html:395
#: templates/submission/submission-list-tabs.html:15
msgid "Admin"
msgstr "Admin"
#: templates/base.html:298
msgid "Internal" msgid "Internal"
msgstr "Nội bộ" msgstr "Nội bộ"
#: templates/base.html:301 #: templates/base.html:195
msgid "Stats" msgid "Stats"
msgstr "Thống kê" msgstr "Thống kê"
#: templates/base.html:314 #: templates/base.html:208
msgid "Log out" msgid "Log out"
msgstr "Đăng xuất" msgstr "Đăng xuất"
#: templates/base.html:324 #: templates/base.html:218
#: templates/registration/password_reset_complete.html:4 #: templates/registration/password_reset_complete.html:4
msgid "Log in" msgid "Log in"
msgstr "Đăng nhập" msgstr "Đăng nhập"
#: templates/base.html:325 #: templates/base.html:219
msgid "Sign up" msgid "Sign up"
msgstr "Đăng ký" msgstr "Đăng ký"
#: templates/base.html:339 #: templates/base.html:233
msgid "spectating" msgid "spectating"
msgstr "đang theo dõi" msgstr "đang theo dõi"
#: templates/base.html:351 #: templates/base.html:245
msgid "Compete" msgid "Compete"
msgstr "Thi" msgstr "Thi"
#: templates/base.html:353 #: templates/base.html:247
msgid "General" msgid "General"
msgstr "Chung" msgstr "Chung"
#: templates/base.html:360 #: templates/base.html:254
msgid "This site works best with JavaScript enabled." msgid "This site works best with JavaScript enabled."
msgstr "" msgstr ""
@ -3772,41 +3776,29 @@ msgstr "Thêm mới"
msgid "No clarifications have been made at this time." msgid "No clarifications have been made at this time."
msgstr "Không có thông báo nào." msgstr "Không có thông báo nào."
#: templates/chat/chat.html:5 templates/chat/chat_js.html:545 #: templates/chat/chat.html:5 templates/chat/chat_js.html:539
msgid "Chat Box" msgid "Chat Box"
msgstr "Chat Box" msgstr "Chat Box"
#: templates/chat/chat.html:69 templates/chat/chat_js.html:507 #: templates/chat/chat.html:72 templates/chat/chat_js.html:501
#: templates/user/base-users-js.html:10 #: templates/user/base-users-js.html:10
#: templates/user/base-users-two-col.html:19 #: templates/user/base-users-two-col.html:19
msgid "Search by handle..." msgid "Search by handle..."
msgstr "Tìm kiếm theo tên..." msgstr "Tìm kiếm theo tên..."
#: templates/chat/chat.html:88 #: templates/chat/chat.html:91
msgid "Enter your message" msgid "Enter your message"
msgstr "Nhập tin nhắn" msgstr "Nhập tin nhắn"
#: templates/chat/chat.html:89 #: templates/chat/chat.html:92
msgid "Emoji" msgid "Emoji"
msgstr "" msgstr ""
#: templates/chat/chat_js.html:3 #: templates/chat/chat_js.html:118
msgid "Recent"
msgstr "Gần đây"
#: templates/chat/chat_js.html:4
msgid "Following"
msgstr "Bạn bè"
#: templates/chat/chat_js.html:6
msgid "Other"
msgstr "Thành viên khác"
#: templates/chat/chat_js.html:124
msgid "New message(s)" msgid "New message(s)"
msgstr "Tin nhắn mới" msgstr "Tin nhắn mới"
#: templates/chat/chat_js.html:418 #: templates/chat/chat_js.html:412
msgid "Mute this user and delete all messages?" msgid "Mute this user and delete all messages?"
msgstr "Mute người dùng này và xóa tất cả tin nhắn chung?" msgstr "Mute người dùng này và xóa tất cả tin nhắn chung?"
@ -5969,6 +5961,12 @@ msgstr "Thông tin"
msgid "Check all" msgid "Check all"
msgstr "Chọn tất cả" msgstr "Chọn tất cả"
#~ msgid "Following"
#~ msgstr "Bạn bè"
#~ msgid "Other"
#~ msgstr "Thành viên khác"
#~ msgid "Online Users" #~ msgid "Online Users"
#~ msgstr "Trực tuyến" #~ msgstr "Trực tuyến"

View file

@ -295,7 +295,6 @@
$(function () { $(function () {
$('img.unveil').unveil(200); $('img.unveil').unveil(200);
}); });
const loading_page = `{% include "loading-page.html" %}`;
</script> </script>
{% endcompress %} {% endcompress %}
@ -379,10 +378,10 @@
<script type="text/javascript">{{ request.profile.user_script|safe }}</script> <script type="text/javascript">{{ request.profile.user_script|safe }}</script>
{% endif %} {% endif %}
<div id="bodyend"> <div id="extra_js">
{% block bodyend %}{% endblock %} {% block extra_js %}{% endblock %}
</div> </div>
{% block bodyend %}{% endblock %}
{% block footer %} {% block footer %}
<footer> <footer>
<span id="footer-content"> <span id="footer-content">

View file

@ -82,7 +82,7 @@
{% include 'chat/user_online_status.html' %} {% include 'chat/user_online_status.html' %}
</div> </div>
<div id="chat-box"> <div id="chat-box">
<img src="{{static('loading.gif')}}" id="loader"> <img src="{{static('loading.gif')}}" id="loader" style="display: none;">
<ul id="chat-log"> <ul id="chat-log">
{% include 'chat/message_list.html' %} {% include 'chat/message_list.html' %}
</ul> </ul>

View file

@ -1,10 +1,4 @@
<script type="text/javascript"> <script type="text/javascript">
let META_HEADER = [
"{{_('Recent')}}",
"{{_('Following')}}",
"{{_('Admin')}}",
"{{_('Other')}}",
];
let isMobile = window.matchMedia("only screen and (max-width: 799px)").matches; let isMobile = window.matchMedia("only screen and (max-width: 799px)").matches;
function load_next_page(last_id, refresh_html=false) { function load_next_page(last_id, refresh_html=false) {

View file

@ -1,12 +1,12 @@
<li class="message" id="message-{{ message.id }}" message-id="{{ message.id }}"> <li class="message" id="message-{{ message.id }}" message-id="{{ message.id }}">
<a href="{{ url('user_page', message.author.user.username) }}"> <a href="{{ url('user_page', message.author.username) }}">
<img src="{{ gravatar(message.author, 135) }}" class="profile-pic"> <img src="{{ gravatar(message.author, 135) }}" class="profile-pic">
</a> </a>
<div class="body-message"> <div class="body-message">
<div class="user-time"> <div class="user-time">
<span class="username {{ message.author.css_class }}"> <span class="username {{ message.author.css_class }}">
<a href="{{ url('user_page', message.author.user.username) }}"> <a href="{{ url('user_page', message.author.username) }}">
{{ message.author }} {{ message.author.username }}
</a> </a>
</span> </span>
<span class="time"> <span class="time">

View file

@ -28,6 +28,8 @@
{% block js_media %} {% block js_media %}
<script type="text/javascript"> <script type="text/javascript">
let loadingPage;
function activateBlogBoxOnClick() { function activateBlogBoxOnClick() {
$('.blog-box').on('click', function () { $('.blog-box').on('click', function () {
var $description = $(this).children('.blog-description'); var $description = $(this).children('.blog-description');
@ -64,15 +66,15 @@
$elem.addClass('active'); $elem.addClass('active');
} }
$(window).off("scroll"); $(window).off("scroll");
$('.middle-right-content').html(loading_page); $('.middle-right-content').html(loadingPage);
$.get(url, function (data) { $.get(url, function (data) {
var reload_content = $(data).find('.middle-right-content'); var reload_content = $(data).find('.middle-right-content');
var bodyend_script = $(data).find('#bodyend'); var bodyend_script = $(data).find('#extra_js');
if (reload_content.length) { if (reload_content.length) {
window.history.pushState("", "", url); window.history.pushState("", "", url);
$('html, body').animate({scrollTop: 0}, 'fast'); $('html, body').animate({scrollTop: 0}, 'fast');
$('.middle-right-content').html(reload_content.first().html()); $('.middle-right-content').html(reload_content.first().html());
$('#bodyend').html(bodyend_script.first().html()); $('#extra_js').html(bodyend_script.first().html());
$("#loading-bar").hide().css({ width: 0}); $("#loading-bar").hide().css({ width: 0});
if (reload_content.hasClass("wrapper")) { if (reload_content.hasClass("wrapper")) {
$('.middle-right-content').addClass("wrapper"); $('.middle-right-content').addClass("wrapper");
@ -114,6 +116,9 @@
navigateTo($(this), true); navigateTo($(this), true);
}); });
registerNavigation(); registerNavigation();
$.get("{{static('html/loading-page.html')}}", function(data) {
loadingPage = data;
});
}); });
</script> </script>
{% endblock %} {% endblock %}
@ -141,11 +146,14 @@
{% block after_posts %}{% endblock %} {% block after_posts %}{% endblock %}
{% endblock %} {% endblock %}
{% block extra_js %}
{% block three_col_js %}{% endblock %}
{% endblock %}
{% block bodyend %} {% block bodyend %}
{{ super() }} {{ super() }}
{% if REQUIRE_JAX %} {% if REQUIRE_JAX %}
{% include "mathjax-load.html" %} {% include "mathjax-load.html" %}
{% endif %} {% endif %}
{% include "comments/math.html" %} {% include "comments/math.html" %}
{% block three_col_js %}{% endblock %}
{% endblock %} {% endblock %}