Skip to content

Commit

Permalink
Merge pull request #269 from kevinaboos/display_emote_notice_messages
Browse files Browse the repository at this point in the history
* Display Notice and Emote messages properly  
    * Notice: username and text body color is a lighter gray than regular
      message content from real users.
    * Emote: the body prepended by a "* <username>",
      as suggested by the Matrix spec.

* Use a darker background for code/quote blocks in a selected RoomPreview
  * The default lighter gray color can be quite difficult to see due to low contrast.
  • Loading branch information
kevinaboos authored Nov 22, 2024
2 parents 4562c67 + 9f125de commit 419f522
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 24 deletions.
7 changes: 7 additions & 0 deletions src/home/room_preview.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,18 +255,21 @@ impl RoomPreviewContent {
let message_text_color;
let room_name_color;
let timestamp_color;
let code_bg_color;

// TODO: This is quite verbose, makepad should provide a way to override this at a higher level.
if is_selected {
bg_color = vec3(0.059, 0.533, 0.996); // COLOR_PRIMARY_SELECTED
message_text_color = vec3(1., 1., 1.); // COLOR_PRIMARY
room_name_color = vec3(1., 1., 1.); // COLOR_PRIMARY
timestamp_color = vec3(1., 1., 1.); // COLOR_PRIMARY
code_bg_color = vec3(0.3, 0.3, 0.3); // a darker gray, used for `code_color` and `quote_bg_color`
} else {
bg_color = vec3(1., 1., 1.); // COLOR_PRIMARY
message_text_color = vec3(0.267, 0.267, 0.267); // MESSAGE_TEXT_COLOR
room_name_color = vec3(0., 0., 0.);
timestamp_color = vec3(0.6, 0.6, 0.6);
code_bg_color = vec3(0.929, 0.929, 0.929); // #EDEDED, see `code_color` and `quote_bg_color`
}

self.view.apply_over(
Expand Down Expand Up @@ -312,6 +315,10 @@ impl RoomPreviewContent {
draw_italic: { color: (message_text_color) },
draw_bold: { color: (message_text_color) },
draw_bold_italic: { color: (message_text_color) },
draw_block: {
quote_bg_color: (code_bg_color),
code_color: (code_bg_color),
}
}
}
plaintext_view = {
Expand Down
121 changes: 108 additions & 13 deletions src/home/room_screen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use matrix_sdk::{
ruma::{
events::room::{
message::{
FormattedBody, ImageMessageEventContent, LocationMessageEventContent, MessageFormat, MessageType, NoticeMessageEventContent, RoomMessageEventContent, TextMessageEventContent
EmoteMessageEventContent, FormattedBody, ImageMessageEventContent, LocationMessageEventContent, MessageFormat, MessageType, NoticeMessageEventContent, RoomMessageEventContent, TextMessageEventContent
},
MediaSource,
}, matrix_uri::MatrixId, uint, EventId, MatrixToUri, MatrixUri, MilliSecondsSinceUnixEpoch, OwnedEventId, OwnedRoomId, UserId
Expand Down Expand Up @@ -37,6 +37,8 @@ use super::loading_modal::{LoadingModalAction, LoadingModalState};

const GEO_URI_SCHEME: &str = "geo:";

const MESSAGE_NOTICE_TEXT_COLOR: Vec3 = Vec3 { x: 0.5, y: 0.5, z: 0.5 };

live_design! {
import makepad_draw::shader::std::*;
import makepad_widgets::base::*;
Expand Down Expand Up @@ -227,7 +229,7 @@ live_design! {
height: Fit,
padding: {top: 5.0}

html_content = <RobrixHtml> {
html_content = <MessageHtml> {
width: Fill,
height: Fit,
padding: { bottom: 5.0, top: 0.0 },
Expand Down Expand Up @@ -2375,6 +2377,8 @@ fn populate_message_view(

let ts_millis = event_tl_item.timestamp();

let mut is_notice = false; // whether this message is a Notice

// Determine whether we can use a more compact UI view that hides the user's profile info
// if the previous message was sent by the same user within 10 minutes.
let use_compact_view = match prev_event.map(|p| p.kind()) {
Expand All @@ -2391,9 +2395,67 @@ fn populate_message_view(
_ => false,
};

// Sometimes we need to call this up-front, so we save the result in this variable
// to avoid having to call it twice.
let mut set_username_and_get_avatar_retval = None;

let (item, used_cached_item) = match message.msgtype() {
MessageType::Text(TextMessageEventContent { body, formatted, .. })
| MessageType::Notice(NoticeMessageEventContent { body, formatted, .. }) => {
MessageType::Text(TextMessageEventContent { body, formatted, .. }) => {
let template = if use_compact_view {
live_id!(CondensedMessage)
} else {
live_id!(Message)
};
let (item, existed) = list.item_with_existed(cx, item_id, template);
if existed && item_drawn_status.content_drawn {
(item, true)
} else {
populate_text_message_content(
&item.html_or_plaintext(id!(content.message)),
&body,
formatted.as_ref(),
);
new_drawn_status.content_drawn = true;
(item, false)
}
}
// A notice message is just a message sent by an automated bot,
// so we treat it just like a message but use a different font color.
MessageType::Notice(NoticeMessageEventContent { body, formatted, .. }) => {
is_notice = true;
let template = if use_compact_view {
live_id!(CondensedMessage)
} else {
live_id!(Message)
};
let (item, existed) = list.item_with_existed(cx, item_id, template);
if existed && item_drawn_status.content_drawn {
(item, true)
} else {
let html_or_plaintext_ref = item.html_or_plaintext(id!(content.message));
html_or_plaintext_ref.apply_over(cx, live!(
html_view = {
html = {
font_color: (MESSAGE_NOTICE_TEXT_COLOR),
draw_normal: { color: (MESSAGE_NOTICE_TEXT_COLOR), }
draw_italic: { color: (MESSAGE_NOTICE_TEXT_COLOR), }
draw_bold: { color: (MESSAGE_NOTICE_TEXT_COLOR), }
draw_bold_italic: { color: (MESSAGE_NOTICE_TEXT_COLOR), }
}
}
));
populate_text_message_content(
&html_or_plaintext_ref,
&body,
formatted.as_ref(),
);
new_drawn_status.content_drawn = true;
(item, false)
}
}
// An emote is just like a message but is prepended with the user's name
// to indicate that it's an "action" that the user is performing.
MessageType::Emote(EmoteMessageEventContent { body, formatted, .. }) => {
let template = if use_compact_view {
live_id!(CondensedMessage)
} else {
Expand All @@ -2403,11 +2465,34 @@ fn populate_message_view(
if existed && item_drawn_status.content_drawn {
(item, true)
} else {
// Draw the profile up front here because we need the username for the emote body.
let (username, profile_drawn) = set_avatar_and_get_username(
cx,
item.avatar(id!(profile.avatar)),
room_id,
event_tl_item.sender(),
event_tl_item.sender_profile(),
event_tl_item.event_id(),
);

// Prepend a "* <username> " to the emote body, as suggested by the Matrix spec.
let (body, formatted) = if let Some(fb) = formatted.as_ref() {
(
Cow::from(&fb.body),
Some(FormattedBody {
format: fb.format.clone(),
body: format!("* {} {}", &username, &fb.body),
})
)
} else {
(Cow::from(format!("* {} {}", &username, body)), None)
};
populate_text_message_content(
&item.html_or_plaintext(id!(content.message)),
&body,
formatted.as_ref(),
);
set_username_and_get_avatar_retval = Some((username, profile_drawn));
new_drawn_status.content_drawn = true;
(item, false)
}
Expand Down Expand Up @@ -2490,15 +2575,25 @@ fn populate_message_view(
new_drawn_status.profile_drawn = true;
} else {
// log!("\t --> populate_message_view(): DRAWING profile draw for item_id: {item_id}");
let (username, profile_drawn) = set_avatar_and_get_username(
cx,
item.avatar(id!(profile.avatar)),
room_id,
event_tl_item.sender(),
event_tl_item.sender_profile(),
event_tl_item.event_id(),
let (username, profile_drawn) = set_username_and_get_avatar_retval.unwrap_or_else(||
set_avatar_and_get_username(
cx,
item.avatar(id!(profile.avatar)),
room_id,
event_tl_item.sender(),
event_tl_item.sender_profile(),
event_tl_item.event_id(),
)
);
item.label(id!(content.username)).set_text(&username);
let username_label = item.label(id!(content.username));
if is_notice {
username_label.apply_over(cx, live!(
draw_text: {
color: (MESSAGE_NOTICE_TEXT_COLOR),
}
));
}
username_label.set_text(&username);
new_drawn_status.profile_drawn = profile_drawn;
}

Expand Down Expand Up @@ -2556,7 +2651,7 @@ fn populate_text_message_content(
body: &str,
formatted_body: Option<&FormattedBody>,
) {
if let Some(formatted_body) = formatted_body
if let Some(formatted_body) = formatted_body.as_ref()
.and_then(|fb| (fb.format == MessageFormat::Html).then(|| fb.body.clone()))
{
message_content_widget.show_html(utils::linkify(formatted_body.as_ref()));
Expand Down
2 changes: 1 addition & 1 deletion src/home/welcome_screen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ live_design! {
}

// Using the HTML widget to taking advantage of embedding a link within text with proper vertical alignment
<RobrixHtml> {
<MessageHtml> {
padding: {top: 12, left: 0.}
font_size: 14.
font_color: (WELCOME_TEXT_COLOR)
Expand Down
12 changes: 3 additions & 9 deletions src/shared/html_or_plaintext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ live_design! {

// A centralized widget where we define styles and custom elements for HTML
// message content. This is a wrapper around Makepad's built-in `Html` widget.
RobrixHtml = <Html> {
MessageHtml = <Html> {
padding: 0.0,
width: Fill, height: Fit, // see comment in `HtmlOrPlaintext`
font_size: (MESSAGE_FONT_SIZE),
Expand All @@ -59,19 +59,13 @@ live_design! {

a = {
padding: {left: 1.0, right: 1.5},
// draw_text: {
// text_style: <MESSAGE_TEXT_STYLE> { font_size: (MESSAGE_FONT_SIZE), height_factor: (HTML_TEXT_HEIGHT_FACTOR), line_spacing: (HTML_LINE_SPACING), top_drop: 1.2, },
// color: #00f,
// color_pressed: #f00,
// color_hover: #0f0,
// }
}

body: "[<i> HTML message placeholder</i>]",
}

// A view container that displays either plaintext s(a simple `Label`)
// or rich HTML content (an instance of `RobrixHtml`).
// or rich HTML content (an instance of `MessageHtml`).
//
// Key Usage Notes:
// * Labels need their width to be Fill *and* all of their parent views
Expand Down Expand Up @@ -101,7 +95,7 @@ live_design! {
html_view = <View> {
visible: false,
width: Fill, height: Fit, // see above comment
html = <RobrixHtml> {}
html = <MessageHtml> {}
}
}
}
Expand Down
5 changes: 4 additions & 1 deletion src/shared/styles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ live_design! {
TYPING_NOTICE_TEXT_COLOR = #121570

MESSAGE_FONT_SIZE = 11
MESSAGE_TEXT_COLOR = #x444
MESSAGE_TEXT_COLOR = #x333
// notices (automated messages from bots) use a lighter color
MESSAGE_NOTICE_TEXT_COLOR = #x888
MESSAGE_TEXT_LINE_SPACING = 1.35
MESSAGE_TEXT_HEIGHT_FACTOR = 1.55
// This font should only be used for plaintext labels. Don't use this for Html content,
Expand All @@ -44,6 +46,7 @@ live_design! {

MESSAGE_REPLY_PREVIEW_FONT_SIZE = 9.5


SMALL_STATE_FONT_SIZE = 9.0
SMALL_STATE_TEXT_COLOR = #x888
SMALL_STATE_TEXT_STYLE = <THEME_FONT_REGULAR>{
Expand Down

0 comments on commit 419f522

Please sign in to comment.