mirror of
https://github.com/kristoferssolo/traxor.git
synced 2025-10-21 20:10:35 +00:00
feat(help): add help popup
This commit is contained in:
parent
cad0ac00e2
commit
98ad8efd3a
@ -6,7 +6,7 @@ pub enum Action {
|
|||||||
NextTorrent,
|
NextTorrent,
|
||||||
PrevTorrent,
|
PrevTorrent,
|
||||||
SwitchTab(u8),
|
SwitchTab(u8),
|
||||||
TogglePopup,
|
ToggleHelp, // Add this line
|
||||||
ToggleTorrent,
|
ToggleTorrent,
|
||||||
ToggleAll,
|
ToggleAll,
|
||||||
PauseAll,
|
PauseAll,
|
||||||
|
|||||||
@ -17,7 +17,7 @@ pub struct App<'a> {
|
|||||||
tabs: &'a [Tab],
|
tabs: &'a [Tab],
|
||||||
pub state: TableState,
|
pub state: TableState,
|
||||||
pub torrents: Torrents,
|
pub torrents: Torrents,
|
||||||
pub show_popup: bool,
|
pub show_help: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> App<'a> {
|
impl<'a> App<'a> {
|
||||||
@ -30,7 +30,7 @@ impl<'a> App<'a> {
|
|||||||
index: 0,
|
index: 0,
|
||||||
state: TableState::default(),
|
state: TableState::default(),
|
||||||
torrents: Torrents::new()?, // Handle the Result here
|
torrents: Torrents::new()?, // Handle the Result here
|
||||||
show_popup: false,
|
show_help: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ impl<'a> App<'a> {
|
|||||||
}
|
}
|
||||||
None => 0,
|
None => 0,
|
||||||
};
|
};
|
||||||
self.close_popup();
|
self.close_help();
|
||||||
self.state.select(Some(i));
|
self.state.select(Some(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,19 +71,19 @@ impl<'a> App<'a> {
|
|||||||
}
|
}
|
||||||
None => 0,
|
None => 0,
|
||||||
};
|
};
|
||||||
self.close_popup();
|
self.close_help();
|
||||||
self.state.select(Some(i));
|
self.state.select(Some(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Switches to the next tab.
|
/// Switches to the next tab.
|
||||||
pub fn next_tab(&mut self) {
|
pub fn next_tab(&mut self) {
|
||||||
self.close_popup();
|
self.close_help();
|
||||||
self.index = (self.index + 1) % self.tabs.len();
|
self.index = (self.index + 1) % self.tabs.len();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Switches to the previous tab.
|
/// Switches to the previous tab.
|
||||||
pub fn prev_tab(&mut self) {
|
pub fn prev_tab(&mut self) {
|
||||||
self.close_popup();
|
self.close_help();
|
||||||
if self.index > 0 {
|
if self.index > 0 {
|
||||||
self.index -= 1;
|
self.index -= 1;
|
||||||
} else {
|
} else {
|
||||||
@ -93,7 +93,7 @@ impl<'a> App<'a> {
|
|||||||
|
|
||||||
/// Switches to the tab whose index is `idx`.
|
/// Switches to the tab whose index is `idx`.
|
||||||
pub fn switch_tab(&mut self, idx: usize) {
|
pub fn switch_tab(&mut self, idx: usize) {
|
||||||
self.close_popup();
|
self.close_help();
|
||||||
self.index = idx
|
self.index = idx
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,29 +107,29 @@ impl<'a> App<'a> {
|
|||||||
self.tabs
|
self.tabs
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn toggle_popup(&mut self) {
|
pub fn toggle_help(&mut self) {
|
||||||
self.show_popup = !self.show_popup;
|
self.show_help = !self.show_help;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn close_popup(&mut self) {
|
pub fn close_help(&mut self) {
|
||||||
self.show_popup = false;
|
self.show_help = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open_popup(&mut self) {
|
pub fn open_help(&mut self) {
|
||||||
self.show_popup = true;
|
self.show_help = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn toggle_torrents(&mut self) -> anyhow::Result<()> {
|
pub async fn toggle_torrents(&mut self) -> anyhow::Result<()> {
|
||||||
let ids = self.selected(false);
|
let ids = self.selected(false);
|
||||||
self.torrents.toggle(ids).await?;
|
self.torrents.toggle(ids).await?;
|
||||||
self.close_popup();
|
self.close_help();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn delete(&mut self, delete_local_data: bool) -> anyhow::Result<()> {
|
pub async fn delete(&mut self, delete_local_data: bool) -> anyhow::Result<()> {
|
||||||
let ids = self.selected(false);
|
let ids = self.selected(false);
|
||||||
self.torrents.delete(ids, delete_local_data).await?;
|
self.torrents.delete(ids, delete_local_data).await?;
|
||||||
self.close_popup();
|
self.close_help();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,7 +24,7 @@ pub fn get_action(key_event: KeyEvent) -> Option<Action> {
|
|||||||
KeyCode::Char('d') => Some(Action::Delete(false)),
|
KeyCode::Char('d') => Some(Action::Delete(false)),
|
||||||
KeyCode::Char('D') => Some(Action::Delete(true)),
|
KeyCode::Char('D') => Some(Action::Delete(true)),
|
||||||
KeyCode::Char(' ') => Some(Action::Select),
|
KeyCode::Char(' ') => Some(Action::Select),
|
||||||
// Other handlers you could add here.
|
KeyCode::Char('?') => Some(Action::ToggleHelp),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -38,7 +38,7 @@ pub async fn update(app: &mut App<'_>, action: Action) -> anyhow::Result<()> {
|
|||||||
Action::NextTorrent => app.next(),
|
Action::NextTorrent => app.next(),
|
||||||
Action::PrevTorrent => app.previous(),
|
Action::PrevTorrent => app.previous(),
|
||||||
Action::SwitchTab(x) => app.switch_tab(x as usize),
|
Action::SwitchTab(x) => app.switch_tab(x as usize),
|
||||||
Action::TogglePopup => app.toggle_popup(),
|
Action::ToggleHelp => app.toggle_help(),
|
||||||
Action::ToggleTorrent => app.toggle_torrents().await?,
|
Action::ToggleTorrent => app.toggle_torrents().await?,
|
||||||
Action::ToggleAll => app.torrents.toggle_all().await?,
|
Action::ToggleAll => app.torrents.toggle_all().await?,
|
||||||
Action::PauseAll => app.torrents.stop_all().await?,
|
Action::PauseAll => app.torrents.stop_all().await?,
|
||||||
|
|||||||
@ -12,7 +12,3 @@ pub mod tui;
|
|||||||
|
|
||||||
/// Event handler.
|
/// Event handler.
|
||||||
pub mod handler;
|
pub mod handler;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
51
src/ui/help.rs
Normal file
51
src/ui/help.rs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
use ratatui::{prelude::*, widgets::*};
|
||||||
|
|
||||||
|
pub fn render_help(frame: &mut Frame) {
|
||||||
|
let block = Block::default()
|
||||||
|
.title("Help")
|
||||||
|
.title_alignment(Alignment::Center)
|
||||||
|
.borders(Borders::ALL)
|
||||||
|
.border_type(BorderType::Rounded);
|
||||||
|
|
||||||
|
let rows = vec![
|
||||||
|
Row::new(vec![Cell::from("?"), Cell::from("Show help")]),
|
||||||
|
Row::new(vec![Cell::from("q"), Cell::from("Quit")]),
|
||||||
|
Row::new(vec![Cell::from("h"), Cell::from("Left")]),
|
||||||
|
Row::new(vec![Cell::from("l"), Cell::from("Right")]),
|
||||||
|
Row::new(vec![Cell::from("j"), Cell::from("Down")]),
|
||||||
|
Row::new(vec![Cell::from("k"), Cell::from("Up")]),
|
||||||
|
Row::new(vec![Cell::from("1"), Cell::from("Switch to All tab")]),
|
||||||
|
Row::new(vec![Cell::from("2"), Cell::from("Switch to Active tab")]),
|
||||||
|
Row::new(vec![
|
||||||
|
Cell::from("3"),
|
||||||
|
Cell::from("Switch to Downloading tab"),
|
||||||
|
]),
|
||||||
|
Row::new(vec![Cell::from("t"), Cell::from("Toggle torrent")]),
|
||||||
|
Row::new(vec![Cell::from("a"), Cell::from("Toggle all torrents")]),
|
||||||
|
Row::new(vec![Cell::from("d"), Cell::from("Delete torrent")]),
|
||||||
|
Row::new(vec![Cell::from("D"), Cell::from("Delete torrent and data")]),
|
||||||
|
Row::new(vec![Cell::from(" "), Cell::from("Select torrent")]),
|
||||||
|
];
|
||||||
|
|
||||||
|
let table = Table::new(
|
||||||
|
rows,
|
||||||
|
&[Constraint::Percentage(20), Constraint::Percentage(80)],
|
||||||
|
)
|
||||||
|
.block(block)
|
||||||
|
.style(Style::default().fg(Color::Green));
|
||||||
|
|
||||||
|
let area = frame.area();
|
||||||
|
let height = 15; // Desired height for the help menu
|
||||||
|
let width = area.width; // Full width of the screen
|
||||||
|
|
||||||
|
let popup_area = Rect::new(
|
||||||
|
area.x + (area.width - width) / 2, // Center horizontally
|
||||||
|
area.y + area.height - height, // Position at the very bottom
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
);
|
||||||
|
|
||||||
|
frame.render_widget(Clear, popup_area);
|
||||||
|
frame.render_widget(table, popup_area);
|
||||||
|
}
|
||||||
|
|
||||||
@ -1,16 +1,9 @@
|
|||||||
mod popup;
|
mod help;
|
||||||
mod table;
|
mod table;
|
||||||
|
|
||||||
use crate::app::{App, Tab};
|
use crate::app::{App, Tab};
|
||||||
use popup::render_popup;
|
use help::render_help;
|
||||||
use ratatui::{
|
use ratatui::{prelude::*, widgets::*};
|
||||||
layout::Alignment,
|
|
||||||
prelude::{Constraint, Direction, Layout},
|
|
||||||
style::{Color, Style},
|
|
||||||
text::Line,
|
|
||||||
widgets::{Block, BorderType, Borders, Clear, Tabs},
|
|
||||||
Frame,
|
|
||||||
};
|
|
||||||
use table::render_table;
|
use table::render_table;
|
||||||
|
|
||||||
/// Renders the user interface widgets.
|
/// Renders the user interface widgets.
|
||||||
@ -57,10 +50,7 @@ pub fn render(app: &mut App, frame: &mut Frame) {
|
|||||||
};
|
};
|
||||||
frame.render_stateful_widget(table, chunks[1], &mut app.state); // renders table
|
frame.render_stateful_widget(table, chunks[1], &mut app.state); // renders table
|
||||||
|
|
||||||
if app.show_popup {
|
if app.show_help {
|
||||||
let block = Block::default().borders(Borders::ALL);
|
render_help(frame);
|
||||||
let size = render_popup(size);
|
|
||||||
frame.render_widget(Clear, size);
|
|
||||||
frame.render_widget(block, size);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +0,0 @@
|
|||||||
use ratatui::layout::Rect;
|
|
||||||
|
|
||||||
pub fn render_popup(r: Rect) -> Rect {
|
|
||||||
let vertical_margin = r.height / 5;
|
|
||||||
let horizontal_margin = r.width / 5;
|
|
||||||
|
|
||||||
Rect::new(
|
|
||||||
r.x + horizontal_margin,
|
|
||||||
r.y + vertical_margin,
|
|
||||||
r.width - (2 * horizontal_margin),
|
|
||||||
r.height - (2 * vertical_margin),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -1,11 +1,10 @@
|
|||||||
|
use crate::app::{utils::Wrapper, App, Tab};
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
layout::Constraint,
|
layout::Constraint,
|
||||||
style::{Color, Style, Styled},
|
style::{Color, Style, Styled},
|
||||||
widgets::{Block, BorderType, Borders, Row, Table},
|
widgets::{Block, BorderType, Borders, Row, Table},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::app::{utils::Wrapper, App, Tab};
|
|
||||||
|
|
||||||
pub fn render_table<'a>(app: &mut App, tab: Tab) -> Table<'a> {
|
pub fn render_table<'a>(app: &mut App, tab: Tab) -> Table<'a> {
|
||||||
let fields = tab.fields();
|
let fields = tab.fields();
|
||||||
let selected = &app.torrents.selected.clone();
|
let selected = &app.torrents.selected.clone();
|
||||||
|
|||||||
20
tests/app.rs
20
tests/app.rs
@ -48,19 +48,19 @@ fn test_app_switch_tab() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_app_toggle_popup() {
|
fn test_app_toggle_popup() {
|
||||||
let mut app = App::new().unwrap();
|
let mut app = App::new().unwrap();
|
||||||
assert!(!app.show_popup);
|
assert!(!app.show_help);
|
||||||
app.toggle_popup();
|
app.toggle_help();
|
||||||
assert!(app.show_popup);
|
assert!(app.show_help);
|
||||||
app.toggle_popup();
|
app.toggle_help();
|
||||||
assert!(!app.show_popup);
|
assert!(!app.show_help);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_app_open_close_popup() {
|
fn test_app_open_close_popup() {
|
||||||
let mut app = App::new().unwrap();
|
let mut app = App::new().unwrap();
|
||||||
assert!(!app.show_popup);
|
assert!(!app.show_help);
|
||||||
app.open_popup();
|
app.open_help();
|
||||||
assert!(app.show_popup);
|
assert!(app.show_help);
|
||||||
app.close_popup();
|
app.close_help();
|
||||||
assert!(!app.show_popup);
|
assert!(!app.show_help);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user