Skip to main content

rusticity_term/session/
ui.rs

1use super::Session;
2use crate::common::SortDirection;
3use crate::ui::filter_area;
4use crate::ui::table::{self};
5use ratatui::prelude::{Color, Constraint, Direction, Layout, Span, Style};
6use ratatui::widgets::Clear;
7
8enum SessionColumn {
9    Timestamp,
10    Profile,
11    Region,
12    Account,
13    Tabs,
14}
15
16impl table::Column<Session> for SessionColumn {
17    fn name(&self) -> &str {
18        match self {
19            Self::Timestamp => "Timestamp",
20            Self::Profile => "Profile",
21            Self::Region => "Region",
22            Self::Account => "Account",
23            Self::Tabs => "Tabs",
24        }
25    }
26
27    fn width(&self) -> u16 {
28        match self {
29            Self::Timestamp => 25,
30            Self::Profile => 25,
31            Self::Region => 15,
32            Self::Account => 15,
33            Self::Tabs => 8,
34        }
35    }
36
37    fn render(&self, item: &Session) -> (String, Style) {
38        let text = match self {
39            Self::Timestamp => item.timestamp.clone(),
40            Self::Profile => item.profile.clone(),
41            Self::Region => item.region.clone(),
42            Self::Account => item.account_id.clone(),
43            Self::Tabs => item.tabs.len().to_string(),
44        };
45        (text, Style::default())
46    }
47}
48
49pub fn render_session_picker(
50    frame: &mut ratatui::Frame,
51    app: &crate::app::App,
52    area: ratatui::prelude::Rect,
53    centered_rect: fn(u16, u16, ratatui::prelude::Rect) -> ratatui::prelude::Rect,
54) {
55    let popup_area = centered_rect(80, 70, area);
56
57    let chunks = Layout::default()
58        .direction(Direction::Vertical)
59        .constraints([Constraint::Length(3), Constraint::Min(0)])
60        .split(popup_area);
61
62    let filter_text = if app.session_filter_active {
63        vec![
64            Span::raw(&app.session_filter),
65            Span::styled("█", Style::default().fg(Color::Green)),
66        ]
67    } else {
68        vec![Span::raw(&app.session_filter)]
69    };
70    let filter = filter_area(filter_text, app.session_filter_active);
71
72    frame.render_widget(Clear, popup_area);
73    frame.render_widget(filter, chunks[0]);
74
75    let columns: Vec<Box<dyn table::Column<Session>>> = vec![
76        Box::new(SessionColumn::Timestamp),
77        Box::new(SessionColumn::Profile),
78        Box::new(SessionColumn::Region),
79        Box::new(SessionColumn::Account),
80        Box::new(SessionColumn::Tabs),
81    ];
82
83    let filtered = app.get_filtered_sessions();
84    let config = table::TableConfig {
85        items: filtered,
86        selected_index: app.session_picker_selected,
87        expanded_index: None,
88        columns: &columns,
89        sort_column: "Timestamp",
90        sort_direction: SortDirection::Desc,
91        title: "Sessions".to_string(),
92        area: chunks[1],
93        get_expanded_content: None,
94        is_active: true,
95    };
96
97    table::render_table(frame, config);
98}