| 1 |
{% extends "base.html" %} |
| 2 |
{% import "_island.html" as island %} |
| 3 |
|
| 4 |
{% block title %}Chat — {{ community_name }} — Multithreaded{% endblock %} |
| 5 |
|
| 6 |
{# Chat is ephemeral by design, so there is nothing here worth indexing and a |
| 7 |
crawler holding an SSE connection open is a connection slot spent on nobody. #} |
| 8 |
{% block head %}<meta name="robots" content="noindex">{% endblock %} |
| 9 |
|
| 10 |
{% block header %}{% include "partials/site_header.html" %}{% endblock %} |
| 11 |
|
| 12 |
{% block content %} |
| 13 |
<div class="container"> |
| 14 |
<div class="breadcrumb"> |
| 15 |
<a href="/">Forums</a> |
| 16 |
<span class="sep">/</span> |
| 17 |
<a href="/p/{{ community_slug }}">{{ community_name }}</a> |
| 18 |
<span class="sep">/</span> |
| 19 |
Chat |
| 20 |
</div> |
| 21 |
<div class="page-header"> |
| 22 |
<h1>Chat</h1> |
| 23 |
</div> |
| 24 |
|
| 25 |
{# The island reads its configuration from data attributes rather than an |
| 26 |
inline script, so the page needs no script-src exception. Everything |
| 27 |
inside is server-rendered and stays rendered: the element adds arriving |
| 28 |
messages and sends without a page load, and adds nothing else. #} |
| 29 |
<mt-chat-room id="chat-room" |
| 30 |
class="chat-room" |
| 31 |
data-slug="{{ community_slug }}" |
| 32 |
data-cursor="{{ cursor }}" |
| 33 |
data-max-length="{{ max_message_len }}" |
| 34 |
data-can-send="{{ can_send }}" |
| 35 |
data-moderator="{{ is_moderator }}" |
| 36 |
{% if let Some(viewer) = viewer_id %}data-viewer="{{ viewer }}"{% endif %}> |
| 37 |
|
| 38 |
<ol class="chat-log" id="chat-log" aria-live="polite" aria-label="Chat messages"> |
| 39 |
{% for message in messages %} |
| 40 |
<li class="chat-message" data-id="{{ message.id }}" data-author="{{ message.author_id }}"> |
| 41 |
{% if let Some(avatar) = message.avatar_url %} |
| 42 |
<img class="chat-avatar" src="{{ avatar }}" alt="" width="24" height="24"> |
| 43 |
{% endif %} |
| 44 |
<span class="chat-author">{{ message.author_name }}</span> |
| 45 |
<time class="chat-time" datetime="{{ message.created_at }}"></time> |
| 46 |
<span class="chat-body">{{ message.body_html|safe }}</span> |
| 47 |
</li> |
| 48 |
{% endfor %} |
| 49 |
</ol> |
| 50 |
|
| 51 |
{% if messages.is_empty() %} |
| 52 |
<div class="empty-state" id="chat-empty">Nothing said yet.</div> |
| 53 |
{% endif %} |
| 54 |
|
| 55 |
{% if read_only %} |
| 56 |
<div class="chat-notice">This community is read-only, so chat is too.</div> |
| 57 |
{% elif can_send %} |
| 58 |
<form class="chat-composer" id="chat-composer" method="post" |
| 59 |
action="/p/{{ community_slug }}/chat/send"> |
| 60 |
{% if let Some(token) = csrf_token %} |
| 61 |
<input type="hidden" name="csrf_token" value="{{ token }}"> |
| 62 |
{% endif %} |
| 63 |
<label class="sr-only" for="chat-input">Message</label> |
| 64 |
<input type="text" id="chat-input" name="body" autocomplete="off" |
| 65 |
maxlength="{{ max_message_len }}" placeholder="Say something"> |
| 66 |
<button type="submit">Send</button> |
| 67 |
</form> |
| 68 |
{% elif session_user.is_some() %} |
| 69 |
<div class="chat-notice">You cannot send messages in this room.</div> |
| 70 |
{% else %} |
| 71 |
<div class="chat-notice"><a href="/auth/login">Sign in</a> to join the conversation.</div> |
| 72 |
{% endif %} |
| 73 |
</mt-chat-room> |
| 74 |
</div> |
| 75 |
{% endblock %} |
| 76 |
|
| 77 |
{% block scripts %}{% call island::island("chat") %}{% endcall %}{% endblock %} |
| 78 |
|