Reimplement compose and add tiling windows
This commit is contained in:
@@ -1,5 +1,3 @@
|
||||
{% load static %}
|
||||
<link rel="stylesheet" href="{% static 'css/compose-panel.css' %}">
|
||||
<div
|
||||
id="{{ panel_id }}"
|
||||
class="compose-shell box"
|
||||
@@ -10,57 +8,63 @@
|
||||
data-initial-typing="{{ typing_state_json|default:'{}'|escape }}"
|
||||
data-cancel-send-url="{% url 'compose_cancel_send' %}"
|
||||
data-command-result-url="{% url 'compose_command_result' %}">
|
||||
<div class="compose-shell-head is-flex is-justify-content-space-between is-align-items-flex-start is-flex-wrap-wrap is-gap-2 mb-3">
|
||||
<div class="compose-shell-head is-flex is-justify-content-space-between is-align-items-flex-start is-flex-wrap-wrap is-gap-2 mb-2">
|
||||
<div>
|
||||
<p class="compose-shell-eyebrow is-size-7 has-text-weight-semibold mb-1">Manual Text Mode</p>
|
||||
{% if recent_contacts %}
|
||||
<div class="compose-contact-switch">
|
||||
<div class="select is-small">
|
||||
<select id="{{ panel_id }}-contact-select" class="compose-contact-select">
|
||||
{% for option in recent_contacts %}
|
||||
<option
|
||||
value="{{ option.identifier }}"
|
||||
data-service="{{ option.service }}"
|
||||
{% if option.person_id %}data-person="{{ option.person_id }}"{% endif %}
|
||||
data-service-map='{{ option.service_identifiers_json|escape }}'
|
||||
{% if option.is_active %}selected{% endif %}>
|
||||
{{ option.person_name }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<p class="is-size-6 mb-0">
|
||||
{% if person %}
|
||||
{{ person.name }}
|
||||
{% elif group_name %}
|
||||
{{ group_name }}
|
||||
<div class="compose-context-row">
|
||||
<div class="compose-context-primary">
|
||||
{% if recent_contacts %}
|
||||
<div class="compose-contact-switch">
|
||||
<div class="select is-small is-fullwidth">
|
||||
<select id="{{ panel_id }}-contact-select" class="compose-contact-select">
|
||||
{% for option in recent_contacts %}
|
||||
<option
|
||||
value="{{ option.identifier }}"
|
||||
data-service="{{ option.service }}"
|
||||
{% if option.person_id %}data-person="{{ option.person_id }}"{% endif %}
|
||||
data-service-map='{{ option.service_identifiers_json|escape }}'
|
||||
{% if option.is_active %}selected{% endif %}>
|
||||
{{ option.person_name }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
{{ identifier }}
|
||||
<p class="is-size-6 mb-0">
|
||||
{% if person %}
|
||||
{{ person.name }}
|
||||
{% elif group_name %}
|
||||
{{ group_name }}
|
||||
{% else %}
|
||||
{{ identifier }}
|
||||
{% endif %}
|
||||
</p>
|
||||
{% endif %}
|
||||
</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if platform_options %}
|
||||
<div class="compose-context-secondary">
|
||||
<div class="compose-platform-switch">
|
||||
<div class="select is-small is-fullwidth">
|
||||
<select id="{{ panel_id }}-platform-select" class="compose-platform-select">
|
||||
{% for option in platform_options %}
|
||||
<option
|
||||
value="{{ option.service }}"
|
||||
data-identifier="{{ option.identifier }}"
|
||||
data-person="{{ option.person_id }}"
|
||||
{% if option.is_active %}selected{% endif %}>
|
||||
{{ option.service_label }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<p id="{{ panel_id }}-meta-line" class="is-size-7 compose-meta-line mb-0">
|
||||
{{ service|title }} · {{ identifier }}
|
||||
</p>
|
||||
{% if platform_options %}
|
||||
<div class="compose-platform-switch">
|
||||
<div class="select is-small">
|
||||
<select id="{{ panel_id }}-platform-select" class="compose-platform-select">
|
||||
{% for option in platform_options %}
|
||||
<option
|
||||
value="{{ option.service }}"
|
||||
data-identifier="{{ option.identifier }}"
|
||||
data-person="{{ option.person_id }}"
|
||||
{% if option.is_active %}selected{% endif %}>
|
||||
{{ option.service_label }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -86,96 +90,7 @@
|
||||
data-limit="{{ limit }}"
|
||||
data-last-ts="{{ last_ts }}"
|
||||
data-ws-url="{{ compose_ws_url }}">
|
||||
{% for msg in serialized_messages %}
|
||||
<div class="compose-row {% if msg.outgoing %}is-out{% else %}is-in{% endif %}{% if msg.is_deleted %} is-deleted{% endif %}" data-ts="{{ msg.ts }}" data-message-id="{{ msg.id }}"{% if msg.reply_to_id %} data-reply-to-id="{{ msg.reply_to_id }}"{% endif %} data-reply-snippet="{{ msg.display_text|default:msg.text|default:''|truncatechars:120|escape }}">
|
||||
<article class="compose-bubble {% if msg.outgoing %}is-out{% else %}is-in{% endif %}">
|
||||
{% if msg.reply_to_id %}
|
||||
<div class="compose-reply-ref" data-reply-target-id="{{ msg.reply_to_id }}" data-reply-preview="{{ msg.reply_preview|default:''|escape }}">
|
||||
<button type="button" class="compose-reply-link" title="Jump to referenced message"></button>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="compose-source-badge-wrap">
|
||||
<span class="tag is-light compose-source-badge source-{{ msg.source_service|default:'web'|lower }}">{{ msg.source_label }}</span>
|
||||
</div>
|
||||
{% if msg.image_urls %}
|
||||
{% for image_url in msg.image_urls %}
|
||||
<figure class="compose-media">
|
||||
<img
|
||||
class="compose-image"
|
||||
src="{{ image_url }}"
|
||||
alt="Attachment"
|
||||
referrerpolicy="no-referrer"
|
||||
loading="lazy"
|
||||
decoding="async">
|
||||
</figure>
|
||||
{% endfor %}
|
||||
{% elif msg.image_url %}
|
||||
<figure class="compose-media">
|
||||
<img
|
||||
class="compose-image"
|
||||
src="{{ msg.image_url }}"
|
||||
alt="Attachment"
|
||||
referrerpolicy="no-referrer"
|
||||
loading="lazy"
|
||||
decoding="async">
|
||||
</figure>
|
||||
{% endif %}
|
||||
{% if not msg.hide_text %}
|
||||
<p class="compose-body">{{ msg.display_text|default:"(no text)" }}</p>
|
||||
{% else %}
|
||||
<p class="compose-body compose-image-fallback is-hidden">(no text)</p>
|
||||
{% endif %}
|
||||
{% if msg.edit_count %}
|
||||
<details class="compose-edit-history">
|
||||
<summary>Edited {{ msg.edit_count }} time{% if msg.edit_count != 1 %}s{% endif %}</summary>
|
||||
<ul>
|
||||
{% for edit in msg.edit_history %}
|
||||
<li>
|
||||
{% if edit.edited_display %}{{ edit.edited_display }}{% else %}Unknown time{% endif %}
|
||||
{% if edit.actor %} · {{ edit.actor }}{% endif %}
|
||||
{% if edit.source_service %} · {{ edit.source_service|upper }}{% endif %}
|
||||
<div class="compose-edit-diff">
|
||||
<span class="compose-edit-old">{{ edit.previous_text|default:"(empty)" }}</span>
|
||||
<span class="compose-edit-arrow">→</span>
|
||||
<span class="compose-edit-new">{{ edit.new_text|default:"(empty)" }}</span>
|
||||
</div>
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</details>
|
||||
{% endif %}
|
||||
{% if msg.reactions %}
|
||||
<div class="compose-reactions" aria-label="Message reactions">
|
||||
{% for reaction in msg.reactions %}
|
||||
<span
|
||||
class="tag is-light compose-reaction-chip"
|
||||
data-emoji="{{ reaction.emoji|escape }}"
|
||||
data-actor="{{ reaction.actor|default:''|escape }}"
|
||||
data-source-service="{{ reaction.source_service|default:''|escape }}"
|
||||
title="{{ reaction.actor|default:'Unknown' }} via {{ reaction.source_service|default:'unknown'|upper }}">
|
||||
{{ reaction.emoji }}
|
||||
</span>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
<p class="compose-msg-meta">
|
||||
{{ msg.display_ts }}{% if msg.author %} · {{ msg.author }}{% endif %}
|
||||
{% if msg.is_edited %}
|
||||
<span class="tag is-light compose-msg-flag is-edited" title="Message edited{% if msg.last_edit_display %} at {{ msg.last_edit_display }}{% endif %}">edited</span>
|
||||
{% endif %}
|
||||
{% if msg.is_deleted %}
|
||||
<span class="tag is-light compose-msg-flag is-deleted" title="Deleted{% if msg.deleted_display %} at {{ msg.deleted_display }}{% endif %}{% if msg.deleted_actor %} by {{ msg.deleted_actor }}{% endif %}">deleted</span>
|
||||
{% endif %}
|
||||
</p>
|
||||
<button type="button" class="button is-white is-small compose-reply-btn" title="Reply to this message" aria-label="Reply to this message">
|
||||
<span class="icon is-small"><i class="fa-solid fa-reply"></i></span>
|
||||
<span class="compose-reply-btn-label">Reply</span>
|
||||
</button>
|
||||
</article>
|
||||
</div>
|
||||
{% empty %}
|
||||
<p class="compose-empty">No stored messages for this contact yet.</p>
|
||||
{% endfor %}
|
||||
{% include "partials/compose-message-rows.html" with message_rows=serialized_messages show_empty_state=True empty_message="No stored messages for this contact yet." %}
|
||||
</div>
|
||||
<p id="{{ panel_id }}-typing" class="compose-typing is-hidden">
|
||||
{% if person %}{{ person.name }}{% else %}Contact{% endif %} is typing...
|
||||
@@ -198,8 +113,15 @@
|
||||
<input type="hidden" name="failsafe_arm" value="0">
|
||||
<input type="hidden" name="failsafe_confirm" value="0">
|
||||
<div class="compose-send-safety">
|
||||
<label class="checkbox is-size-7">
|
||||
<input type="checkbox" class="manual-confirm"{% if not capability_send %} disabled{% endif %}> Confirm Send
|
||||
<label class="checkbox is-size-7" for="{{ panel_id }}-manual-confirm">
|
||||
<input
|
||||
id="{{ panel_id }}-manual-confirm"
|
||||
type="checkbox"
|
||||
class="manual-confirm"
|
||||
name="manual_confirm"
|
||||
value="1"
|
||||
{% if not capability_send %}disabled{% endif %}>
|
||||
Confirm Send
|
||||
</label>
|
||||
{% if not capability_send %}
|
||||
<p class="help is-size-7 has-text-grey">Send disabled: {{ capability_send_reason }}</p>
|
||||
@@ -210,19 +132,6 @@
|
||||
<span id="{{ panel_id }}-reply-text" class="compose-reply-banner-text"></span>
|
||||
<button type="button" id="{{ panel_id }}-reply-clear" class="button is-white is-small compose-reply-clear-btn">Clear</button>
|
||||
</div>
|
||||
<div class="compose-composer-capsule box is-shadowless">
|
||||
<textarea
|
||||
id="{{ panel_id }}-textarea"
|
||||
class="textarea compose-textarea"
|
||||
name="text"
|
||||
rows="1"
|
||||
placeholder="Type a message. Enter to send, Shift+Enter for newline."></textarea>
|
||||
<button class="button is-link is-light compose-send-btn" type="submit" disabled{% if not capability_send %} title="{{ capability_send_reason }}"{% endif %}>
|
||||
<span class="icon is-small"><i class="{{ manual_icon_class }}"></i></span>
|
||||
<span>Send</span>
|
||||
</button>
|
||||
</div>
|
||||
{% include "partials/bulma-send-composer.html" with composer_class="compose-composer-capsule" textarea_id=panel_id|add:"-textarea" textarea_class="compose-textarea" textarea_name="text" textarea_rows="1" textarea_placeholder="Type a message. Enter to send, Shift+Enter for newline." button_class="is-link is-light compose-send-btn" button_type="submit" button_disabled=True button_title=capability_send_reason|default_if_none:"" button_label="Send" button_icon_class=manual_icon_class %}
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script src="{% static 'js/compose-panel.js' %}"></script>
|
||||
|
||||
Reference in New Issue
Block a user