From 073a5b0d0cc4c0bdb4081412efb5c16931558ddf Mon Sep 17 00:00:00 2001 From: Mark Veidemanis Date: Mon, 16 Feb 2026 23:28:28 +0000 Subject: [PATCH] Improve message layout --- core/templates/partials/compose-panel.html | 42 ++++++++++++++++++++-- core/views/compose.py | 13 +++++++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/core/templates/partials/compose-panel.html b/core/templates/partials/compose-panel.html index ef56c70..b7eaeee 100644 --- a/core/templates/partials/compose-panel.html +++ b/core/templates/partials/compose-panel.html @@ -257,6 +257,14 @@
{{ msg.source_label }}
+ {% if msg.block_gap_display %} +

+ + {{ msg.block_gap_display }} +

+ {% endif %} {% if msg.image_urls %} {% for image_url in msg.image_urls %}
@@ -462,6 +470,20 @@ justify-content: flex-start; margin-bottom: 0.36rem; } + #{{ panel_id }} .compose-block-gap { + margin: -0.12rem 0 0.26rem; + display: inline-flex; + align-items: center; + gap: 0.22rem; + font-size: 0.64rem; + line-height: 1.1; + color: #5f6c7d; + opacity: 0.95; + } + #{{ panel_id }} .compose-block-gap-val { + font-weight: 700; + letter-spacing: 0.01em; + } #{{ panel_id }} .compose-source-badge { font-size: 0.84rem; padding: 0.12rem 0.5rem; @@ -1815,6 +1837,22 @@ badgeWrap.appendChild(badge); bubble.appendChild(badgeWrap); } + if (msg.block_gap_display) { + const blockGap = document.createElement("p"); + blockGap.className = "compose-block-gap"; + blockGap.title = "Time since previous message in this sender block"; + const icon = document.createElement("span"); + icon.className = "icon is-small"; + const i = document.createElement("i"); + i.className = "fa-regular fa-hourglass-half"; + icon.appendChild(i); + const value = document.createElement("span"); + value.className = "compose-block-gap-val"; + value.textContent = String(msg.block_gap_display || ""); + blockGap.appendChild(icon); + blockGap.appendChild(value); + bubble.appendChild(blockGap); + } const imageCandidatesFromPayload = Array.isArray(msg.image_urls) && msg.image_urls.length ? msg.image_urls : (msg.image_url ? [msg.image_url] : []); @@ -1858,7 +1896,7 @@ icon.appendChild(i); const timeSpan = document.createElement("span"); timeSpan.className = "compose-tick-time"; - timeSpan.textContent = String(msg.read_display || ""); + timeSpan.textContent = String(msg.read_delta_display || ""); tickWrap.appendChild(icon); tickWrap.appendChild(timeSpan); meta.appendChild(document.createTextNode(" ")); @@ -1874,7 +1912,7 @@ icon.appendChild(i); const timeSpan = document.createElement("span"); timeSpan.className = "compose-tick-time"; - timeSpan.textContent = String(msg.delivered_display || ""); + timeSpan.textContent = String(msg.delivered_delta_display || ""); tickWrap.appendChild(icon); tickWrap.appendChild(timeSpan); meta.appendChild(document.createTextNode(" ")); diff --git a/core/views/compose.py b/core/views/compose.py index 60cb3d6..b5e00b2 100644 --- a/core/views/compose.py +++ b/core/views/compose.py @@ -730,6 +730,8 @@ def _serialize_messages_with_artifacts( for item in serialized: item["gap_fragments"] = [] item["metric_fragments"] = [] + item["block_gap_ms"] = None + item["block_gap_display"] = "" counterpart_identifiers = set(counterpart_identifiers or []) snapshot = ( @@ -749,6 +751,17 @@ def _serialize_messages_with_artifacts( current_outgoing = _message_is_outgoing_for_analysis( msg, counterpart_identifiers ) + if ( + prev_msg is not None + and prev_ts is not None + and prev_outgoing is not None + and current_outgoing == prev_outgoing + and current_ts >= prev_ts + ): + block_gap_ms = current_ts - prev_ts + serialized[idx]["block_gap_ms"] = int(block_gap_ms) + serialized[idx]["block_gap_display"] = _format_gap_duration(block_gap_ms) + if ( prev_msg is not None and prev_ts is not None