Files
nixos/patches/flare/0006-feat-messages-Show-This-message-was-deleted.-placeho.patch
Simon Gardling bcdfd8cdf5 flare: add patched flare-signal with five local feature patches
- patches/flare/000{1..5}-*.patch: typing indicators, formatted
  messages, edited messages, multi-select with delete-for-me, and
  in-channel message search. Mirror the matching commits in
  ~/projects/forks/flare and apply cleanly on top of upstream 0.20.4
  (which is what nixpkgs ships).
- home/profiles/gui.nix: include a flare-signal override that appends
  the patches via overrideAttrs. None of them touch Cargo.lock so the
  cargoDeps hash stays valid; signal-desktop stays alongside it.
2026-04-30 18:41:35 -04:00

176 lines
6.4 KiB
Diff

From 46765e848362129bb2d0fc34b2047e6cb2555258 Mon Sep 17 00:00:00 2001
From: Simon Gardling <titaniumtown@proton.me>
Date: Thu, 30 Apr 2026 04:25:07 -0400
Subject: [PATCH 6/6] feat(messages): Show 'This message was deleted.'
placeholder
Upstream hides the whole MessageItem when is-deleted is true via a
top-level visible bind on the template root. Replace that with a
Signal-Desktop-style behaviour: the row stays in the timeline, but the
bubble's regular content (header, quote, attachments, label, popover
trigger) and any reactions are hidden, and a single italic-dim
placeholder label takes their place.
The two pieces of imperative state set in code (media_overlay and the
floating timestamp_img indicator over media-only messages) are reset
in a small setup_deleted helper that subscribes to is-deleted, since
they are not reachable through bindings.
---
data/resources/style.css | 6 ++++++
data/resources/ui/message_item.blp | 29 +++++++++++++++++++++----
src/gui/message_item.rs | 34 ++++++++++++++++++++++++++++++
3 files changed, 65 insertions(+), 4 deletions(-)
diff --git a/data/resources/style.css b/data/resources/style.css
index 1c0cdfd..3b0de9a 100644
--- a/data/resources/style.css
+++ b/data/resources/style.css
@@ -9,6 +9,12 @@
background-color: @bubble_bg_color;
}
+/* Deletion placeholder shown in place of remotely-deleted messages. */
+.deleted-message {
+ font-style: italic;
+ opacity: 0.6;
+}
+
.message-input-bar {
border-top: 1px solid @borders;
}
diff --git a/data/resources/ui/message_item.blp b/data/resources/ui/message_item.blp
index ba3fd23..49002a5 100644
--- a/data/resources/ui/message_item.blp
+++ b/data/resources/ui/message_item.blp
@@ -71,8 +71,6 @@ template $FlMessageItem: $ContextMenuBin {
"message-item",
]
- visible: bind $not(template.message as <$FlTextMessage>.is-deleted) as <bool>;
-
Grid {
column-spacing: 12;
row-spacing: 12;
@@ -149,11 +147,32 @@ template $FlMessageItem: $ContextMenuBin {
"message-bubble",
]
+ // Deletion placeholder "This message was deleted." — visible only when
+ // the message has been remotely deleted; hides the rest of the bubble's
+ // content and any reactions/attachments via the .deleted CSS class on
+ // the message-item.
+ Label deleted_label {
+ styles [
+ "deleted-message",
+ ]
+
+ label: _("This message was deleted.");
+ visible: bind template.message as <$FlTextMessage>.is-deleted;
+ halign: start;
+ xalign: 0;
+
+ layout {
+ row: 0;
+ column: 0;
+ }
+ }
+
Label header {
styles [
"heading",
]
+ visible: bind $not(template.message as <$FlTextMessage>.is-deleted) as <bool>;
label: bind template.message as <$FlTextMessage>.sender as <$FlContact>.title;
hexpand: true;
halign: start;
@@ -177,7 +196,7 @@ template $FlMessageItem: $ContextMenuBin {
"quote",
]
- visible: bind $is_some(template.message as <$FlTextMessage>.quote) as <bool>;
+ visible: bind $and($is_some(template.message as <$FlTextMessage>.quote) as <bool>, $not(template.message as <$FlTextMessage>.is-deleted) as <bool>) as <bool>;
Label {
styles [
@@ -219,6 +238,7 @@ template $FlMessageItem: $ContextMenuBin {
}
Box box_attachments {
+ visible: bind $not(template.message as <$FlTextMessage>.is-deleted) as <bool>;
layout {
row: 2;
column: 0;
@@ -276,6 +296,7 @@ template $FlMessageItem: $ContextMenuBin {
}
$FlMessageLabel label_message {
+ visible: bind $not(template.message as <$FlTextMessage>.is-deleted) as <bool>;
label: bind $markup_urls(template.message as <$FlTextMessage>.body) as <string>;
attributes: bind template.message as <$FlTextMessage>.message-attributes;
@@ -306,7 +327,7 @@ template $FlMessageItem: $ContextMenuBin {
]
label: bind $fix_emoji(template.message as <$FlTextMessage>.reactions) as <string>;
- visible: bind template.has-reaction;
+ visible: bind $and(template.has-reaction, $not(template.message as <$FlTextMessage>.is-deleted) as <bool>) as <bool>;
wrap-mode: word;
justify: left;
vexpand: false;
diff --git a/src/gui/message_item.rs b/src/gui/message_item.rs
index d88306f..33479da 100644
--- a/src/gui/message_item.rs
+++ b/src/gui/message_item.rs
@@ -35,6 +35,7 @@ impl MessageItem {
s.setup_requires_attention();
s.setup_pending_and_error();
s.setup_selection();
+ s.setup_deleted();
s
}
@@ -325,6 +326,39 @@ impl MessageItem {
message.notify("requires-attention");
}
+ /// Reflect the message's `is-deleted` state in the UI.
+ ///
+ /// Upstream simply hid the row entirely; we instead keep the row but
+ /// show a `"This message was deleted."` placeholder (handled in the
+ /// blueprint) and clean up the bits that the deletion pseudo-message
+ /// can't reach via the bind layer: the media overlay (whose visibility
+ /// is set imperatively in `set_message`) and the standalone
+ /// `timestamp_img` indicator that floats over media-only messages.
+ pub fn setup_deleted(&self) {
+ let message = self.message();
+ let apply = clone!(
+ #[weak(rename_to = s)]
+ self,
+ move || {
+ if s.message().is_deleted() {
+ s.add_css_class("deleted");
+ s.imp().media_overlay.set_visible(false);
+ s.imp().timestamp_img.set_visible(false);
+ } else {
+ // Symmetric reset for any future code path that flips
+ // is-deleted back off (e.g. an unsend/restore flow).
+ // Today nothing does, but the asymmetry is fragile.
+ s.remove_css_class("deleted");
+ }
+ }
+ );
+ self.track_notify_local(&message, "is-deleted", {
+ let apply = apply.clone();
+ move |_, _| apply()
+ });
+ apply();
+ }
+
pub fn setup_pending_and_error(&self) {
let message = self.message();
message.connect_notify_local(
--
2.53.0