2026-05-10 07:08:12 +00:00
|
|
|
{% extends "base.html" %}
|
|
|
|
|
{% block extra_head %}
|
2026-07-23 00:02:43 +02:00
|
|
|
<link rel="stylesheet" href="{{ static_url('/static/css/chat.css') }}">
|
2026-05-10 07:08:12 +00:00
|
|
|
{% endblock %}
|
2026-06-11 13:03:16 +00:00
|
|
|
{% block footer %}{% endblock %}
|
2026-05-10 07:08:12 +00:00
|
|
|
{% block content %}
|
2026-05-11 03:30:51 +00:00
|
|
|
<h1 class="sr-only">Messages</h1>
|
|
|
|
|
<div class="page-messages">
|
2026-07-23 00:02:43 +02:00
|
|
|
<dp-chat
|
|
|
|
|
class="messages-layout"
|
|
|
|
|
mode="page"
|
|
|
|
|
self-uid="{{ user['uid'] }}"
|
|
|
|
|
{% if current_conversation %}with-uid="{{ current_conversation }}"{% endif %}
|
|
|
|
|
conversations-url="/messages/conversations"
|
|
|
|
|
search-url="/messages/search"
|
|
|
|
|
send-url="/messages/send"
|
|
|
|
|
ws-url="/messages/ws"
|
|
|
|
|
ai-indicator="true"
|
|
|
|
|
>
|
2026-06-19 08:06:09 +00:00
|
|
|
<div class="messages-list" role="navigation" aria-label="Conversations">
|
|
|
|
|
<div class="messages-list-header" role="search">
|
|
|
|
|
<input type="text" id="message-search" placeholder="Search conversations..." value="{{ search }}" aria-label="Search conversations">
|
2026-05-10 07:08:12 +00:00
|
|
|
</div>
|
|
|
|
|
|
2026-06-19 08:06:09 +00:00
|
|
|
<div class="messages-conversations" role="list" aria-label="Conversation list">
|
2026-05-10 07:08:12 +00:00
|
|
|
{% for conv in conversations %}
|
2026-06-19 08:06:09 +00:00
|
|
|
<a href="/messages?with_uid={{ conv.other_user['uid'] }}" class="conversation-item {% if current_conversation == conv.other_user['uid'] %}active{% endif %}" data-conv-uid="{{ conv.other_user['uid'] }}" role="listitem"{% if current_conversation == conv.other_user['uid'] %} aria-current="true"{% endif %}>
|
2026-07-09 02:52:54 +02:00
|
|
|
<span class="avatar-badge"><img src="{{ avatar_url('multiavatar', avatar_seed(conv.other_user), 32) }}" class="avatar-img avatar-sm" alt="{{ conv.other_user['username'] }}" loading="lazy">{% set _user = conv.other_user %}{% include "_presence_dot.html" %}{% include "_award_badge.html" %}</span>
|
2026-05-10 07:08:12 +00:00
|
|
|
<div class="conversation-info">
|
|
|
|
|
<div class="conversation-name">{{ conv.other_user['username'] }}</div>
|
2026-06-22 21:17:54 +00:00
|
|
|
<div class="conversation-preview">{{ content_preview(conv.last_message, 60) }}</div>
|
2026-05-10 07:08:12 +00:00
|
|
|
</div>
|
2026-06-19 08:06:09 +00:00
|
|
|
<span class="conversation-unread-dot"{% if not conv.unread %} hidden{% endif %}><span class="sr-only">Unread messages</span></span>
|
2026-06-16 03:32:19 +00:00
|
|
|
<span class="conversation-time">{{ dt_ago(conv.last_message_at) if conv.last_message_at else format_date(conv.last_message_at) }}</span>
|
2026-05-10 07:08:12 +00:00
|
|
|
</a>
|
|
|
|
|
{% else %}
|
2026-06-22 23:13:48 +00:00
|
|
|
<div class="empty-state empty-state-borderless">No conversations yet</div>
|
2026-05-10 07:08:12 +00:00
|
|
|
{% endfor %}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="messages-main">
|
|
|
|
|
{% if other_user %}
|
|
|
|
|
<div class="messages-main-header">
|
2026-06-06 14:31:42 +00:00
|
|
|
<button type="button" class="messages-back-btn" id="messages-back-btn" aria-label="Back to conversations">←</button>
|
2026-06-12 03:37:12 +00:00
|
|
|
{% set _user = other_user %}{% set _size = 32 %}{% set _size_class = "sm" %}{% include "_avatar_link.html" %}
|
2026-06-14 14:46:36 +00:00
|
|
|
<div class="messages-header-info">
|
|
|
|
|
<h3>{% set _user = other_user %}{% set _class = none %}{% include "_user_link.html" %}</h3>
|
2026-07-04 22:08:20 +00:00
|
|
|
<span class="messages-presence{% if is_online(other_user) %} online{% endif %}" id="messages-presence" role="status" aria-live="polite" data-presence-uid="{{ other_user['uid'] }}" data-presence-last-seen="{{ other_user.get('last_seen') or '' }}" data-presence-label>{% if is_online(other_user) %}online{% elif other_user.get('last_seen') %}last seen {{ format_date(other_user['last_seen']) }}{% else %}offline{% endif %}</span>
|
2026-06-14 14:46:36 +00:00
|
|
|
</div>
|
2026-05-10 07:08:12 +00:00
|
|
|
</div>
|
|
|
|
|
|
2026-06-19 08:06:09 +00:00
|
|
|
<div class="messages-thread" role="log" aria-label="Message transcript" aria-live="polite" aria-relevant="additions">
|
2026-05-10 07:08:12 +00:00
|
|
|
{% for msg in messages %}
|
2026-07-23 00:02:43 +02:00
|
|
|
<div class="message-bubble {% if msg.is_mine %}mine{% else %}theirs{% endif %}{% if msg.grouped %} grouped{% endif %}" data-msg-uid="{{ msg.message['uid'] }}" tabindex="0">
|
|
|
|
|
<dp-content>{{ msg.message['content'] }}</dp-content>
|
2026-05-12 13:07:34 +00:00
|
|
|
{% if msg.attachments %}
|
|
|
|
|
{% with attachments=msg.attachments %}
|
|
|
|
|
{% include "_attachment_display.html" %}
|
|
|
|
|
{% endwith %}
|
|
|
|
|
{% endif %}
|
2026-07-23 00:02:43 +02:00
|
|
|
<span class="message-time">{{ dt_ago(msg.message['created_at']) if msg.message.get('created_at') else msg.time_ago }}</span>
|
2026-06-19 08:06:09 +00:00
|
|
|
{% if msg.is_mine %}<span class="message-receipt"{% if not msg.message['read'] %} hidden{% endif %}>✓✓<span class="sr-only">Read</span></span>{% endif %}
|
2026-05-10 07:08:12 +00:00
|
|
|
</div>
|
|
|
|
|
{% endfor %}
|
2026-06-14 14:46:36 +00:00
|
|
|
<div class="typing-indicator" id="typing-indicator" hidden><span></span><span></span><span></span></div>
|
2026-05-10 07:08:12 +00:00
|
|
|
</div>
|
|
|
|
|
|
2026-06-14 14:46:36 +00:00
|
|
|
<form class="messages-input-area" method="POST" action="/messages/send" data-live-form>
|
2026-05-10 07:08:12 +00:00
|
|
|
<input type="hidden" name="receiver_uid" value="{{ other_user['uid'] }}">
|
2026-07-19 18:57:43 +02:00
|
|
|
<textarea name="content" placeholder="Type a message..." maxlength="2000" autocomplete="off" data-mention aria-label="Type a message" rows="1"></textarea>
|
2026-06-17 17:10:52 +00:00
|
|
|
<dp-upload multiple
|
2026-06-08 20:51:09 +00:00
|
|
|
max-size="{{ max_upload_size_mb() }}"
|
|
|
|
|
max-files="5"
|
|
|
|
|
allowed-types="{{ allowed_file_types() }}"></dp-upload>
|
2026-06-14 14:46:36 +00:00
|
|
|
<button type="submit" class="messages-send-btn" aria-label="Send"><span class="send-icon">➤</span><span class="send-spinner" aria-hidden="true"></span></button>
|
2026-05-10 07:08:12 +00:00
|
|
|
</form>
|
|
|
|
|
{% else %}
|
|
|
|
|
<div class="messages-empty">
|
|
|
|
|
<p>Select a conversation to start chatting</p>
|
|
|
|
|
</div>
|
|
|
|
|
{% endif %}
|
|
|
|
|
</div>
|
2026-07-23 00:02:43 +02:00
|
|
|
</dp-chat>
|
2026-05-11 03:30:51 +00:00
|
|
|
</div>
|
2026-05-16 01:02:10 +00:00
|
|
|
|
2026-05-10 07:08:12 +00:00
|
|
|
{% endblock %}
|