multiverse/widgets/room_view/details/
read_receipts.rs

1use matrix_sdk::Room;
2use matrix_sdk_base::read_receipts::RoomReadReceipts;
3use matrix_sdk_ui::timeline::TimelineItem;
4use ratatui::{
5    prelude::*,
6    widgets::{Block, Borders, Paragraph, Wrap},
7};
8
9use crate::{TEXT_COLOR, widgets::room_view::DetailsState};
10
11pub struct ReadReceipts<'a> {
12    state: &'a DetailsState<'a>,
13}
14
15impl<'a> ReadReceipts<'a> {
16    pub(super) fn new(state: &'a DetailsState<'a>) -> Self {
17        Self { state }
18    }
19}
20
21fn render_room_stats(room: &Room, area: Rect, buf: &mut Buffer) {
22    let RoomReadReceipts { num_unread, num_notifications, num_mentions, .. } = room.read_receipts();
23
24    let content = vec![
25        Line::from(format!("- unread: {num_unread}")),
26        Line::from(format!("- notifications: {num_notifications}")),
27        Line::from(format!("- mentions: {num_mentions}")),
28        Line::from(""),
29        Line::from("---"),
30        Line::from(format!("{:?}", room.read_receipts())),
31        Line::from("#"),
32    ];
33
34    Paragraph::new(content)
35        .fg(TEXT_COLOR)
36        .wrap(Wrap { trim: false })
37        .block(Block::new().borders(Borders::BOTTOM))
38        .render(area, buf);
39}
40
41impl Widget for &mut ReadReceipts<'_> {
42    fn render(self, area: Rect, buf: &mut Buffer)
43    where
44        Self: Sized,
45    {
46        if let Some(room) = self.state.selected_room {
47            match self.state.selected_item.as_deref() {
48                Some(selected_event) => {
49                    if let Some(item) = format_timeline_item(selected_event) {
50                        Paragraph::new(item)
51                            .fg(TEXT_COLOR)
52                            .wrap(Wrap { trim: false })
53                            .block(Block::new().borders(Borders::BOTTOM))
54                            .render(area, buf);
55                    } else {
56                        render_room_stats(room, area, buf);
57                    }
58                }
59                None => render_room_stats(room, area, buf),
60            }
61        } else {
62            let content = "(room disappeared in the room list service)";
63            Paragraph::new(content).fg(TEXT_COLOR).wrap(Wrap { trim: false }).render(area, buf);
64        }
65    }
66}
67
68fn format_timeline_item(item: &TimelineItem) -> Option<Vec<Line<'_>>> {
69    let event = item.as_event()?;
70    let receipts = event.read_receipts();
71    let sender = event.sender();
72    let event_id = event.event_id();
73
74    let first_line = Line::from(format!("{sender} - {event_id:?}"));
75    let second_line = Line::from(format!("{receipts:?}"));
76
77    Some(vec![first_line, second_line])
78}