Skip to content

Commit 42e52a4

Browse files
committed
show display name and pronouns in buffer
1 parent 39346b9 commit 42e52a4

File tree

11 files changed

+220
-98
lines changed

11 files changed

+220
-98
lines changed

data/src/client.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,6 @@ pub struct Client {
174174
mode_requests: Vec<ModeRequest>,
175175
channel_discovery_manager: channel_discovery::Manager,
176176
http_client: Option<Arc<reqwest::Client>>, // Only Some if config.proxy.is_some()
177-
preview_proxy_client: Option<Arc<reqwest::Client>>,
178177
registry: metadata::ServerRegistry,
179178
}
180179

data/src/config/display.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
11
use serde::Deserialize;
22

3-
#[derive(Debug, Clone, Deserialize, Default)]
3+
pub mod nickname;
4+
5+
#[derive(Debug, Clone, Deserialize)]
46
#[serde(default)]
57
pub struct Display {
68
pub direction_arrows: DirectionArrows,
9+
pub nickname: Vec<nickname::Metadata>,
10+
}
11+
12+
impl Default for Display {
13+
fn default() -> Self {
14+
Self {
15+
direction_arrows: DirectionArrows::default(),
16+
nickname: vec![nickname::Metadata::DisplayName],
17+
}
18+
}
719
}
820

921
#[derive(Debug, Clone, Deserialize)]
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
use serde::Deserialize;
2+
3+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize)]
4+
#[serde(rename_all = "kebab-case")]
5+
pub enum Metadata {
6+
DisplayName,
7+
Pronouns,
8+
}
9+
10+
pub fn format(
11+
nickname: &str,
12+
enabled: &[Metadata],
13+
display_name: Option<&str>,
14+
pronouns: Option<&str>,
15+
) -> String {
16+
let display_name = enabled
17+
.contains(&Metadata::DisplayName)
18+
.then_some(display_name)
19+
.flatten()
20+
.filter(|s| !s.is_empty());
21+
let pronouns = enabled
22+
.contains(&Metadata::Pronouns)
23+
.then_some(pronouns)
24+
.flatten()
25+
.filter(|s| !s.is_empty());
26+
27+
match (display_name, pronouns) {
28+
(Some(display_name), Some(pronouns)) => {
29+
format!("{display_name} ({nickname}, {pronouns})")
30+
}
31+
(Some(display_name), None) => format!("{display_name} ({nickname})"),
32+
(None, Some(pronouns)) => format!("{nickname} ({pronouns})"),
33+
(None, None) => nickname.to_string(),
34+
}
35+
}
36+
37+
#[cfg(test)]
38+
mod tests {
39+
use super::{Metadata, format};
40+
41+
#[test]
42+
fn keeps_plain_nickname_when_no_metadata_enabled() {
43+
assert_eq!(
44+
format("storm", &[], Some("Casper"), Some("he/him")),
45+
"storm"
46+
);
47+
}
48+
49+
#[test]
50+
fn formats_display_name_when_present() {
51+
assert_eq!(
52+
format("storm", &[Metadata::DisplayName], Some("Casper"), None),
53+
"Casper (storm)"
54+
);
55+
}
56+
57+
#[test]
58+
fn skips_missing_display_name() {
59+
assert_eq!(
60+
format("storm", &[Metadata::DisplayName], None, None),
61+
"storm"
62+
);
63+
}
64+
65+
#[test]
66+
fn formats_pronouns_when_present() {
67+
assert_eq!(
68+
format("storm", &[Metadata::Pronouns], None, Some("he/him")),
69+
"storm (he/him)"
70+
);
71+
}
72+
73+
#[test]
74+
fn combines_display_name_and_pronouns() {
75+
assert_eq!(
76+
format(
77+
"storm",
78+
&[Metadata::Pronouns, Metadata::DisplayName],
79+
Some("Casper"),
80+
Some("he/him"),
81+
),
82+
"Casper (storm, he/him)"
83+
);
84+
}
85+
}

data/src/history.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1284,7 +1284,6 @@ pub struct View<'a> {
12841284
pub has_more_newer_messages: bool,
12851285
pub old_messages: Vec<&'a Message>,
12861286
pub new_messages: Vec<&'a Message>,
1287-
pub max_nick_chars: Option<usize>,
12881287
pub max_prefix_chars: Option<usize>,
12891288
pub range_end_timestamp_chars: Option<usize>,
12901289
pub cleared: bool,

data/src/history/manager.rs

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1383,38 +1383,6 @@ impl Data {
13831383
.collect::<Vec<_>>();
13841384

13851385
let total = processed.len();
1386-
let with_access_levels = buffer_config.nickname.show_access_levels;
1387-
let truncate = buffer_config.nickname.truncate;
1388-
1389-
let max_nick_chars =
1390-
buffer_config.nickname.alignment.is_right().then(|| {
1391-
processed
1392-
.iter()
1393-
.filter_map(|message| {
1394-
if let message::Source::User(user) =
1395-
message.target.source()
1396-
{
1397-
Some(
1398-
buffer_config
1399-
.nickname
1400-
.brackets
1401-
.format(
1402-
user.display(
1403-
with_access_levels,
1404-
truncate,
1405-
),
1406-
)
1407-
.chars()
1408-
.count(),
1409-
)
1410-
} else {
1411-
None
1412-
}
1413-
})
1414-
.max()
1415-
.unwrap_or_default()
1416-
});
1417-
14181386
let max_prefix_chars =
14191387
buffer_config.nickname.alignment.is_right().then(|| {
14201388
if matches!(kind, history::Kind::Channel(..)) {
@@ -1507,7 +1475,6 @@ impl Data {
15071475
has_more_newer_messages,
15081476
old_messages: old.to_vec(),
15091477
new_messages: new.to_vec(),
1510-
max_nick_chars,
15111478
max_prefix_chars,
15121479
range_end_timestamp_chars,
15131480
cleared: *cleared,

data/src/user.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,14 @@ impl User {
207207
self.display_with_truncated(with_access_levels, truncate).0
208208
}
209209

210+
pub fn display_truncated(
211+
&self,
212+
with_access_levels: AccessLevelFormat,
213+
truncate: Option<u16>,
214+
) -> bool {
215+
self.display_with_truncated(with_access_levels, truncate).1
216+
}
217+
210218
pub fn display_with_truncated(
211219
&self,
212220
with_access_levels: AccessLevelFormat,

docs/configuration/display.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,28 @@ Arrow shown for right-facing events.
3131
[display]
3232
direction_arrows = { right = ">" }
3333
```
34+
35+
## `nickname`
36+
37+
Metadata to include when rendering user nicknames in message buffers.
38+
39+
```toml
40+
# Type: array of strings
41+
# Values: "display-name", "pronouns"
42+
# Default: ["display-name"]
43+
44+
[display]
45+
nickname = ["display-name"]
46+
```
47+
48+
Examples:
49+
50+
```toml
51+
[display]
52+
nickname = ["display-name", "pronouns"]
53+
```
54+
55+
This renders as:
56+
- `["display-name"]` -> `Casper (casperstorm)` when display name (`Casper`) is set, otherwise `casperstorm`
57+
- `["pronouns"]` -> `casperstorm (he/him)` when pronouns are set, otherwise `storm`
58+
- `["display-name", "pronouns"]` -> `Casper (casperstorm, he/him)`, omitting missing metadata

src/buffer/highlights.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use iced::widget::{container, row, span};
99
use iced::{Color, Length, Size, Task};
1010

1111
use super::context_menu::{self, Context};
12+
use super::message_view::formatted_buffer_nickname;
1213
use super::scroll_view;
1314
use crate::widget::{
1415
Element, message_content, selectable_rich_text, selectable_text, tooltip,
@@ -109,11 +110,14 @@ pub fn view<'a>(
109110
ShownStatus::Historical => false,
110111
};
111112

112-
let (user_display, show_nickname_tooltip) = user
113-
.display_with_truncated(with_access_levels, truncate);
113+
let show_nickname_tooltip =
114+
user.display_truncated(with_access_levels, truncate);
114115

115-
let nick_text =
116-
config.buffer.nickname.brackets.format(user_display);
116+
let nick_text = formatted_buffer_nickname(
117+
user,
118+
config,
119+
clients.get_registry(server),
120+
);
117121

118122
let text = selectable_text(nick_text)
119123
.font_maybe(

src/buffer/message_view.rs

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,27 @@ use crate::widget::{
2121
};
2222
use crate::{Theme, font, icon, theme};
2323

24+
pub(crate) fn formatted_buffer_nickname(
25+
user: &User,
26+
config: &Config,
27+
registry: &dyn metadata::Registry,
28+
) -> String {
29+
let with_access_levels = config.buffer.nickname.show_access_levels;
30+
let truncate = config.buffer.nickname.truncate;
31+
let nickname = config
32+
.buffer
33+
.nickname
34+
.brackets
35+
.format(user.display(with_access_levels, truncate));
36+
37+
data::config::display::nickname::format(
38+
&nickname,
39+
&config.display.nickname,
40+
registry.display_name(TargetRef::Query(&Query::from(user))),
41+
registry.pronouns(&Query::from(user)),
42+
)
43+
}
44+
2445
#[derive(Clone, Copy)]
2546
pub enum TargetInfo<'a> {
2647
Channel {
@@ -403,10 +424,9 @@ impl<'a> ChannelQueryLayout<'a> {
403424
dimmed_background_tuple,
404425
);
405426

406-
let (user_display, show_nickname_tooltip) =
407-
user.display_with_truncated(with_access_levels, truncate);
408-
let mut nick_text =
409-
self.config.buffer.nickname.brackets.format(user_display);
427+
let show_nickname_tooltip =
428+
user.display_truncated(with_access_levels, truncate);
429+
let nick_text = formatted_buffer_nickname(user, self.config, registry);
410430

411431
let nick_element: Element<_> = if hide_nickname {
412432
let width = match self.config.buffer.nickname.alignment {
@@ -421,11 +441,6 @@ impl<'a> ChannelQueryLayout<'a> {
421441
};
422442
Space::new().width(width).into()
423443
} else {
424-
if let Some(display_name) =
425-
registry.display_name(TargetRef::Query(&Query::from(user)))
426-
{
427-
nick_text = format!("{display_name} ({nick_text})");
428-
}
429444
let mut nick_text = selectable_text(nick_text)
430445
.style(move |_| nickname_style)
431446
.font_maybe(

0 commit comments

Comments
 (0)