diff --git a/files/assets/css/chat.css b/files/assets/css/chat.css index f52e564b3..02231ef2e 100644 --- a/files/assets/css/chat.css +++ b/files/assets/css/chat.css @@ -26,7 +26,7 @@ } .chat-mention { - background-color: #{{v.themecolor}}55; + background-color: #ffffff44; border-radius: 3px; } @@ -68,7 +68,7 @@ p { width: 100%; } -.cdiv { +.chat-line { overflow: hidden; margin-left: 27px; } diff --git a/files/assets/images/WPD/alert.ico b/files/assets/images/WPD/alert.ico new file mode 100644 index 000000000..0125fe6cc Binary files /dev/null and b/files/assets/images/WPD/alert.ico differ diff --git a/files/assets/images/WPD/alert.webp b/files/assets/images/WPD/alert.webp deleted file mode 100644 index 608c681f9..000000000 Binary files a/files/assets/images/WPD/alert.webp and /dev/null differ diff --git a/files/assets/images/rDrama/alert.ico b/files/assets/images/rDrama/alert.ico new file mode 100644 index 000000000..02c723bef Binary files /dev/null and b/files/assets/images/rDrama/alert.ico differ diff --git a/files/assets/images/rDrama/alert.webp b/files/assets/images/rDrama/alert.webp deleted file mode 100644 index cbb93f396..000000000 Binary files a/files/assets/images/rDrama/alert.webp and /dev/null differ diff --git a/files/assets/js/chat.js b/files/assets/js/chat.js index dd8260b6c..8c3631e2c 100644 --- a/files/assets/js/chat.js +++ b/files/assets/js/chat.js @@ -26,7 +26,8 @@ socket=io() const chatline = document.getElementsByClassName('chat-line')[0] const box = document.getElementById('chat-window') const textbox = document.getElementById('input-text') -const icon = document.getElementById('icon') +const icon = document.querySelector("link[rel~='icon']") + const vid = document.getElementById('vid').value const vusername = document.getElementById('vusername').value const site_name = document.getElementById('site_name').value @@ -42,17 +43,17 @@ function flash(){ if (notifs >= 1 && !focused){ title.innerHTML = `[+${notifs}] Chat`; if (alert) { - icon.href = escapeHTML(`/assets/images/${site_name}/alert.webp?v=3`) + icon.href = `/i/${site_name}/alert.ico?v=3009` alert=false; } else { - icon.href = escapeHTML(`/assets/images/${site_name}/icon.webp?v=3009`) + icon.href = `/i/${site_name}/icon.webp?v=3009` alert=true; } setTimeout(flash, 500) } else { - icon.href = escapeHTML(`/assets/images/${site_name}/icon.webp?v=3009`) + icon.href = `/i/${site_name}/icon.webp?v=3009` notifs = 0 title.innerHTML = 'Chat'; } @@ -64,11 +65,11 @@ function flash(){ } -function handle_message(json) { +socket.on('speak', function(json) { let text = json['text'] let text_html - if (slurreplacer == 'True') text_html = json['text_censored'] + if (slurreplacer != '0') text_html = json['text_censored'] else text_html = json['text_html'] if (text_html.includes(``)){ @@ -87,15 +88,9 @@ function handle_message(json) { const last_user = users[users.length-1].innerHTML; const scrolled_down = (box.scrollHeight - box.scrollTop <= window.innerHeight) - if (last_user == json['username']) { - document.getElementsByClassName('userlink')[0].classList.add('d-none') - document.getElementsByClassName('avatar')[0].classList.add('d-none') - document.getElementsByClassName('time')[0].classList.add('d-none') - } - else { - document.getElementsByClassName('userlink')[0].classList.remove('d-none') - document.getElementsByClassName('avatar')[0].classList.remove('d-none') + if (last_user != json['username']) { document.getElementsByClassName('avatar-pic')[0].src = '/pp/' + json["user_id"] + if (json['hat']) document.getElementsByClassName('avatar-hat')[0].src = json['hat'] + "?h=7" else @@ -103,7 +98,8 @@ function handle_message(json) { document.getElementsByClassName('userlink')[0].href = '/@' + json['username'] document.getElementsByClassName('userlink')[0].style.color = '#' + json['namecolor'] - document.getElementsByClassName('time')[0].classList.remove('d-none') + document.getElementsByClassName('userlink')[0].innerHTML = json['username'] + if (Date.now() - json['time']*1000 > 5000) document.getElementsByClassName('time')[0].innerHTML = timeSince(json['time']*1000) + ' ago' else @@ -111,7 +107,6 @@ function handle_message(json) { } document.getElementsByClassName('chat-line')[0].id = json['id'] - document.getElementsByClassName('userlink')[0].innerHTML = json['username'] document.getElementsByClassName('text')[0].innerHTML = escapeHTML(text) document.getElementsByClassName('chat-message')[0].innerHTML = text_html.replace(/data-src/g, 'src').replace(/data-cfsrc/g, 'src').replace(/style="display:none;visibility:hidden;"/g, '') @@ -121,7 +116,7 @@ function handle_message(json) { if (quoted) { document.getElementsByClassName('quotes')[0].classList.remove("d-none") document.getElementsByClassName('QuotedMessageLink')[0].href = '#' + json['quotes'] - document.getElementsByClassName('QuotedUser')[0].innerHTML = quoted.querySelector('.userlink').innerHTML + document.getElementsByClassName('QuotedUser')[0].innerHTML = quoted.parentElement.querySelector('.userlink').innerHTML document.getElementsByClassName('QuotedMessage')[0].innerHTML = quoted.querySelector('.text').innerHTML } } @@ -133,26 +128,13 @@ function handle_message(json) { box.querySelector('.chat-group:last-child').append(line) } else { - const chatgroup = document.createElement("div"); - chatgroup.className = "chat-group"; + const chatgroup = document.getElementsByClassName('chat-group')[0].cloneNode(true) chatgroup.append(line) box.append(chatgroup) } if (scrolled_down || json['username'] == vusername) box.scrollTo(0, box.scrollHeight) -} - -socket.on('speak', function(json) { - handle_message(json) -}) - -socket.on('catchup', function(json) { - for (const message of json) { - const existing = document.getElementById(message['id']) - if (existing) break - handle_message(message) - } }) function send() { @@ -190,10 +172,10 @@ function quote(t) { const text = t.parentElement.getElementsByClassName("text")[0].innerHTML.replace(/\*/g,"\\*").split('\n').pop() document.getElementById('QuotedMessage').innerHTML = text - const username = t.parentElement.parentElement.getElementsByClassName('userlink')[0].innerHTML + const username = t.parentElement.parentElement.parentElement.parentElement.getElementsByClassName('userlink')[0].innerHTML document.getElementById('QuotedUser').innerHTML = username - const id = t.parentElement.parentElement.parentElement.parentElement.id + const id = t.parentElement.parentElement.parentElement.id document.getElementById('quotes_id').value = id document.getElementById('QuotedMessageLink').href = `#${id}` diff --git a/files/routes/chat.py b/files/routes/chat.py index 485eb05f9..6f6b1bba9 100644 --- a/files/routes/chat.py +++ b/files/routes/chat.py @@ -31,8 +31,8 @@ muted = cache.get(f'muted') or { f'{SITE_FULL}/admin/chat': {} } messages = cache.get(f'messages') or { - f'{SITE_FULL}/chat': [], - f'{SITE_FULL}/admin/chat': [] + f'{SITE_FULL}/chat': {}, + f'{SITE_FULL}/admin/chat': {} } @app.get("/chat") @@ -41,12 +41,12 @@ messages = cache.get(f'messages') or { def chat(v): if not v.admin_level and TRUESCORE_CHAT_MINIMUM and v.truescore < TRUESCORE_CHAT_MINIMUM: abort(403, f"Need at least {TRUESCORE_CHAT_MINIMUM} truescore for access to chat.") - return render_template("chat.html", v=v) + return render_template("chat.html", v=v, messages=messages[request.url]) @app.get("/admin/chat") @admin_level_required(2) def admin_chat(v): - return render_template("chat.html", v=v) + return render_template("chat.html", v=v, messages=messages[request.url]) @socketio.on('speak') @limiter.limit("3/second;10/minute") @@ -78,8 +78,8 @@ def speak(data, v): text_html = sanitize(text, count_marseys=True) quotes = data['quotes'] + id = str(uuid.uuid4()) data = { - "id": str(uuid.uuid4()), "quotes": quotes, "hat": v.hat_active(v)[0], "user_id": v.id, @@ -95,7 +95,7 @@ def speak(data, v): emit('speak', data) else: emit('speak', data, room=request.referrer, broadcast=True) - messages[request.referrer].append(data) + messages[request.referrer][id] = data messages[request.referrer] = messages[request.referrer][-500:] if v.admin_level >= PERMS['USER_BAN']: @@ -136,7 +136,6 @@ def connect(v): online.append(v.username) refresh_online() - emit('catchup', messages[request.referrer], room=request.referrer) emit('typing', typing[request.referrer], room=request.referrer) return '', 204 @@ -174,9 +173,9 @@ def typing_indicator(data, v): @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @admin_level_required(PERMS['POST_COMMENT_MODERATION']) def delete(id, v): - for message in messages[request.referrer]: - if message['id'] == id: - messages[request.referrer].remove(message) + for k, val in messages[request.referrer].items(): + if k == id: + del messages[request.referrer][k] break emit('delete', id, room=request.referrer, broadcast=True) diff --git a/files/templates/chat.html b/files/templates/chat.html index 66c27e080..c4aea118b 100644 --- a/files/templates/chat.html +++ b/files/templates/chat.html @@ -22,37 +22,79 @@ -
-
-
-
-
- - -
-
- just now -
- + {% macro chat_group_template(id, m) %} +
+
+ + +
+ + {% if m %}{{m['username']}}{% endif %} + + {% if m %}{{m['time'] | timestamp}}{% else %}just now{% endif %} + {% endmacro %} - - - {% if v.admin_level > 1 %} - - - {% endif %} - + {% macro chat_line_template(id, m) %} +
+
+
+ + + + {% if m %} + {% if v.slurreplacer %} + {{m['text_censored'] | safe}} + {% else %} + {{m['text_html'] | safe}} + {% endif %} + {% endif %} + + {% if m %}{{m['text']}}{% endif %} + {% if v.admin_level > 1 %} + + + {% endif %} +
+ {% endmacro %} + + +
+ {{chat_group_template()}} +
+ +
+ {{chat_line_template()}} +
+
+ {% for id, m in messages.items() %} + {% set previous = m %} + {% if not (loop.index > 1 and m['user_id'] == previous['user_id']) %} + {% if loop.index > 1 %} +
+ {% endif %} + {{chat_group_template(id, m)}} + {% endif %} + {{chat_line_template(id, m)}} + {% endfor %} +
@@ -80,7 +122,7 @@ - +
diff --git a/files/templates/util/html_head.html b/files/templates/util/html_head.html index cb1a0ed9b..936bd4bc8 100644 --- a/files/templates/util/html_head.html +++ b/files/templates/util/html_head.html @@ -59,7 +59,7 @@ '/h/'+sub.name, sub.sidebar if sub.sidebar %} {% endif %} - +