Support configuring user gutter width (#223)

This commit is contained in:
mordquist 2024-03-24 02:54:26 +01:00 committed by GitHub
parent 23a729e565
commit 46e081b1e4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 30 additions and 18 deletions

View file

@ -111,6 +111,10 @@ overridden as described in *PROFILES*.
> *protocol.font_size* is an optional list of two numbers representing font > *protocol.font_size* is an optional list of two numbers representing font
> width and height in pixels. > width and height in pixels.
**user_gutter_width** (type: usize)
> Specify the width of the column where usernames are displayed in a room.
> Usernames that are too long are truncated.
## USER OVERRIDES ## USER OVERRIDES
Overrides are mapped onto matrix User IDs such as _@user:matrix.org_ and are Overrides are mapped onto matrix User IDs such as _@user:matrix.org_ and are

View file

@ -485,6 +485,7 @@ pub struct TunableValues {
pub open_command: Option<Vec<String>>, pub open_command: Option<Vec<String>>,
pub notifications: Notifications, pub notifications: Notifications,
pub image_preview: Option<ImagePreviewValues>, pub image_preview: Option<ImagePreviewValues>,
pub user_gutter_width: usize,
} }
#[derive(Clone, Default, Deserialize)] #[derive(Clone, Default, Deserialize)]
@ -507,6 +508,7 @@ pub struct Tunables {
pub open_command: Option<Vec<String>>, pub open_command: Option<Vec<String>>,
pub notifications: Option<Notifications>, pub notifications: Option<Notifications>,
pub image_preview: Option<ImagePreview>, pub image_preview: Option<ImagePreview>,
pub user_gutter_width: Option<usize>,
} }
impl Tunables { impl Tunables {
@ -533,6 +535,7 @@ impl Tunables {
open_command: self.open_command.or(other.open_command), open_command: self.open_command.or(other.open_command),
notifications: self.notifications.or(other.notifications), notifications: self.notifications.or(other.notifications),
image_preview: self.image_preview.or(other.image_preview), image_preview: self.image_preview.or(other.image_preview),
user_gutter_width: self.user_gutter_width.or(other.user_gutter_width),
} }
} }
@ -555,6 +558,7 @@ impl Tunables {
open_command: self.open_command, open_command: self.open_command,
notifications: self.notifications.unwrap_or_default(), notifications: self.notifications.unwrap_or_default(),
image_preview: self.image_preview.map(ImagePreview::values), image_preview: self.image_preview.map(ImagePreview::values),
user_gutter_width: self.user_gutter_width.unwrap_or(30),
} }
} }
} }

View file

@ -120,14 +120,10 @@ const BOLD_STYLE: Style = Style {
underline_color: None, underline_color: None,
}; };
const USER_GUTTER: usize = 30;
const TIME_GUTTER: usize = 12; const TIME_GUTTER: usize = 12;
const READ_GUTTER: usize = 5; const READ_GUTTER: usize = 5;
const MIN_MSG_LEN: usize = 30; const MIN_MSG_LEN: usize = 30;
const USER_GUTTER_EMPTY: &str = " ";
const USER_GUTTER_EMPTY_SPAN: Span<'static> = span_static(USER_GUTTER_EMPTY);
const TIME_GUTTER_EMPTY: &str = " "; const TIME_GUTTER_EMPTY: &str = " ";
const TIME_GUTTER_EMPTY_SPAN: Span<'static> = span_static(TIME_GUTTER_EMPTY); const TIME_GUTTER_EMPTY_SPAN: Span<'static> = span_static(TIME_GUTTER_EMPTY);
@ -576,10 +572,13 @@ impl<'a> MessageFormatter<'a> {
text.lines.push(Line::from(vec![leading, date, trailing])); text.lines.push(Line::from(vec![leading, date, trailing]));
} }
let user_gutter_empty_span =
space_span(self.settings.tunables.user_gutter_width, Style::default());
match self.cols { match self.cols {
MessageColumns::Four => { MessageColumns::Four => {
let settings = self.settings; let settings = self.settings;
let user = self.user.take().unwrap_or(USER_GUTTER_EMPTY_SPAN); let user = self.user.take().unwrap_or(user_gutter_empty_span);
let time = self.time.take().unwrap_or(TIME_GUTTER_EMPTY_SPAN); let time = self.time.take().unwrap_or(TIME_GUTTER_EMPTY_SPAN);
let mut line = vec![user]; let mut line = vec![user];
@ -604,7 +603,7 @@ impl<'a> MessageFormatter<'a> {
text.lines.push(Line::from(line)) text.lines.push(Line::from(line))
}, },
MessageColumns::Three => { MessageColumns::Three => {
let user = self.user.take().unwrap_or(USER_GUTTER_EMPTY_SPAN); let user = self.user.take().unwrap_or(user_gutter_empty_span);
let time = self.time.take().unwrap_or_else(|| Span::from("")); let time = self.time.take().unwrap_or_else(|| Span::from(""));
let mut line = vec![user]; let mut line = vec![user];
@ -614,7 +613,7 @@ impl<'a> MessageFormatter<'a> {
text.lines.push(Line::from(line)) text.lines.push(Line::from(line))
}, },
MessageColumns::Two => { MessageColumns::Two => {
let user = self.user.take().unwrap_or(USER_GUTTER_EMPTY_SPAN); let user = self.user.take().unwrap_or(user_gutter_empty_span);
let mut line = vec![user]; let mut line = vec![user];
line.extend(prev_line.spans); line.extend(prev_line.spans);
@ -743,28 +742,29 @@ impl Message {
Some(prev) if prev.timestamp.same_day(&self.timestamp) => None, Some(prev) if prev.timestamp.same_day(&self.timestamp) => None,
_ => self.timestamp.show_date(), _ => self.timestamp.show_date(),
}; };
let user_gutter = settings.tunables.user_gutter_width;
if USER_GUTTER + TIME_GUTTER + READ_GUTTER + MIN_MSG_LEN <= width && if user_gutter + TIME_GUTTER + READ_GUTTER + MIN_MSG_LEN <= width &&
settings.tunables.read_receipt_display settings.tunables.read_receipt_display
{ {
let cols = MessageColumns::Four; let cols = MessageColumns::Four;
let fill = width - USER_GUTTER - TIME_GUTTER - READ_GUTTER; let fill = width - user_gutter - TIME_GUTTER - READ_GUTTER;
let user = self.show_sender(prev, true, info, settings); let user = self.show_sender(prev, true, info, settings);
let time = self.timestamp.show_time(); let time = self.timestamp.show_time();
let read = info.event_receipts.get(self.event.event_id()).map(|read| read.iter()); let read = info.event_receipts.get(self.event.event_id()).map(|read| read.iter());
MessageFormatter { settings, cols, orig, fill, user, date, time, read } MessageFormatter { settings, cols, orig, fill, user, date, time, read }
} else if USER_GUTTER + TIME_GUTTER + MIN_MSG_LEN <= width { } else if user_gutter + TIME_GUTTER + MIN_MSG_LEN <= width {
let cols = MessageColumns::Three; let cols = MessageColumns::Three;
let fill = width - USER_GUTTER - TIME_GUTTER; let fill = width - user_gutter - TIME_GUTTER;
let user = self.show_sender(prev, true, info, settings); let user = self.show_sender(prev, true, info, settings);
let time = self.timestamp.show_time(); let time = self.timestamp.show_time();
let read = None; let read = None;
MessageFormatter { settings, cols, orig, fill, user, date, time, read } MessageFormatter { settings, cols, orig, fill, user, date, time, read }
} else if USER_GUTTER + MIN_MSG_LEN <= width { } else if user_gutter + MIN_MSG_LEN <= width {
let cols = MessageColumns::Two; let cols = MessageColumns::Two;
let fill = width - USER_GUTTER; let fill = width - user_gutter;
let user = self.show_sender(prev, true, info, settings); let user = self.show_sender(prev, true, info, settings);
let time = None; let time = None;
let read = None; let read = None;
@ -787,11 +787,13 @@ impl Message {
prev: Option<&Message>, prev: Option<&Message>,
vwctx: &ViewportContext<MessageCursor>, vwctx: &ViewportContext<MessageCursor>,
info: &'a RoomInfo, info: &'a RoomInfo,
settings: &'a ApplicationSettings,
) -> Option<(&dyn Protocol, u16, u16)> { ) -> Option<(&dyn Protocol, u16, u16)> {
let width = vwctx.get_width(); let width = vwctx.get_width();
let user_gutter = settings.tunables.user_gutter_width;
// The x position where get_render_format would render the text. // The x position where get_render_format would render the text.
let x = (if USER_GUTTER + MIN_MSG_LEN <= width { let x = (if user_gutter + MIN_MSG_LEN <= width {
USER_GUTTER user_gutter
} else { } else {
0 0
}) as u16; }) as u16;
@ -1029,8 +1031,9 @@ impl Message {
} }
let Span { content, style } = self.sender_span(info, settings); let Span { content, style } = self.sender_span(info, settings);
let ((truncated, width), _) = take_width(content, 28); let user_gutter = settings.tunables.user_gutter_width;
let padding = 28 - width; let ((truncated, width), _) = take_width(content, user_gutter - 2);
let padding = user_gutter - 2 - width;
let sender = if align_right { let sender = if align_right {
space(padding) + &truncated + " " space(padding) + &truncated + " "

View file

@ -203,6 +203,7 @@ pub fn mock_tunables() -> TunableValues {
message_user_color: false, message_user_color: false,
notifications: Notifications { enabled: false, show_message: None }, notifications: Notifications { enabled: false, show_message: None },
image_preview: None, image_preview: None,
user_gutter_width: 30,
} }
} }

View file

@ -1352,7 +1352,7 @@ impl<'a> StatefulWidget for Scrollback<'a> {
let txt = item.show(prev, foc && sel, &state.viewctx, info, settings); let txt = item.show(prev, foc && sel, &state.viewctx, info, settings);
let mut msg_preview = if picker.is_some() { let mut msg_preview = if picker.is_some() {
item.line_preview(prev, &state.viewctx, info) item.line_preview(prev, &state.viewctx, info, settings)
} else { } else {
None None
}; };