Skip to main content

max / makenotwork

3.6 KB · 82 lines History Blame Raw
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 {# The name mentions are written against, which is the username and not
38 the display name: docengine matches `@username`, so highlighting on
39 a display name would find the wrong person or nobody. #}
40 {% if let Some(user) = session_user %}data-viewer-name="{{ user.username }}"{% endif %}>
41
42 <ol class="chat-log" id="chat-log" aria-live="polite" aria-label="Chat messages">
43 {% for message in messages %}
44 <li class="chat-message" data-id="{{ message.id }}" data-author="{{ message.author_id }}">
45 {% if let Some(avatar) = message.avatar_url %}
46 <img class="chat-avatar" src="{{ avatar }}" alt="" width="24" height="24">
47 {% endif %}
48 <span class="chat-author">{{ message.author_name }}</span>
49 <time class="chat-time" datetime="{{ message.created_at }}"></time>
50 <span class="chat-body">{{ message.body_html|safe }}</span>
51 </li>
52 {% endfor %}
53 </ol>
54
55 {% if messages.is_empty() %}
56 <div class="empty-state" id="chat-empty">Nothing said yet.</div>
57 {% endif %}
58
59 {% if read_only %}
60 <div class="chat-notice">This community is read-only, so chat is too.</div>
61 {% elif can_send %}
62 <form class="chat-composer" id="chat-composer" method="post"
63 action="/p/{{ community_slug }}/chat/send">
64 {% if let Some(token) = csrf_token %}
65 <input type="hidden" name="csrf_token" value="{{ token }}">
66 {% endif %}
67 <label class="sr-only" for="chat-input">Message</label>
68 <input type="text" id="chat-input" name="body" autocomplete="off"
69 maxlength="{{ max_message_len }}" placeholder="Say something">
70 <button type="submit">Send</button>
71 </form>
72 {% elif session_user.is_some() %}
73 <div class="chat-notice">You cannot send messages in this room.</div>
74 {% else %}
75 <div class="chat-notice"><a href="/auth/login">Sign in</a> to join the conversation.</div>
76 {% endif %}
77 </mt-chat-room>
78 </div>
79 {% endblock %}
80
81 {% block scripts %}{% call island::island("chat") %}{% endcall %}{% endblock %}
82