feat: add multiple torrent select option

This commit is contained in:
Kristofers Solo 2024-02-21 16:43:09 +02:00
parent 2a3975963c
commit b0a8d64880
6 changed files with 38 additions and 10 deletions

View File

@ -14,4 +14,5 @@ pub enum Action {
Move, Move,
Delete(bool), Delete(bool),
Rename, Rename,
Select,
} }

View File

@ -134,6 +134,18 @@ impl<'a> App<'a> {
Ok(()) Ok(())
} }
pub fn select(&mut self) {
let torrent = self.selected().expect("Torrent not found");
if let Some(id) = torrent.id {
if self.torrents.selected.contains(&id) {
self.torrents.selected.remove(&id);
} else {
self.torrents.selected.insert(id);
}
}
self.next();
}
fn selected(&self) -> Option<&Torrent> { fn selected(&self) -> Option<&Torrent> {
let idx = self.state.selected()?; let idx = self.state.selected()?;
let torrent = self.torrents.torrents.get(idx)?; let torrent = self.torrents.torrents.get(idx)?;

View File

@ -1,8 +1,8 @@
use std::fmt::Debug; use std::{collections::HashSet, fmt::Debug};
use anyhow::Result; use anyhow::Result;
use transmission_rpc::{ use transmission_rpc::{
types::{Id, Torrent, TorrentGetField}, types::{Torrent, TorrentGetField},
TransClient, TransClient,
}; };
@ -13,7 +13,7 @@ pub struct Torrents {
/// Constructs a new instance of [`Torrents`]. /// Constructs a new instance of [`Torrents`].
pub client: TransClient, pub client: TransClient,
pub torrents: Vec<Torrent>, pub torrents: Vec<Torrent>,
pub ids: Option<Vec<Id>>, pub selected: HashSet<i64>, // Torrent::id
pub fields: Option<Vec<TorrentGetField>>, pub fields: Option<Vec<TorrentGetField>>,
} }
@ -24,7 +24,7 @@ impl Torrents {
Self { Self {
client: TransClient::new(url), client: TransClient::new(url),
torrents: Vec::new(), torrents: Vec::new(),
ids: None, selected: HashSet::new(),
fields: None, fields: None,
} }
} }
@ -50,7 +50,7 @@ impl Torrents {
pub async fn update(&mut self) -> &mut Self { pub async fn update(&mut self) -> &mut Self {
self.torrents = self self.torrents = self
.client .client
.torrent_get(self.fields.clone(), self.ids.clone()) .torrent_get(self.fields.clone(), None)
.await .await
.unwrap() .unwrap()
.arguments .arguments

View File

@ -63,6 +63,7 @@ impl Wrapper for TorrentGetField {
TorrentGetField::UploadedEver => String::from("Uploaded"), TorrentGetField::UploadedEver => String::from("Uploaded"),
TorrentGetField::Wanted => String::from("Wanted"), TorrentGetField::Wanted => String::from("Wanted"),
TorrentGetField::WebseedsSendingToUs => String::from("Webseeds Sending to Us"), TorrentGetField::WebseedsSendingToUs => String::from("Webseeds Sending to Us"),
TorrentGetField::FileCount => unimplemented!(),
} }
} }
@ -170,6 +171,7 @@ impl Wrapper for TorrentGetField {
None => String::from("N/A"), None => String::from("N/A"),
}, },
TorrentGetField::WebseedsSendingToUs => String::from("N/A"), TorrentGetField::WebseedsSendingToUs => String::from("N/A"),
TorrentGetField::FileCount => unimplemented!(),
} }
} }
@ -215,6 +217,7 @@ impl Wrapper for TorrentGetField {
TorrentGetField::UploadedEver => 10, TorrentGetField::UploadedEver => 10,
TorrentGetField::Wanted => 10, TorrentGetField::Wanted => 10,
TorrentGetField::WebseedsSendingToUs => 10, TorrentGetField::WebseedsSendingToUs => 10,
TorrentGetField::FileCount => unimplemented!(),
} }
} }
} }

View File

@ -19,9 +19,9 @@ pub fn get_action(key_event: KeyEvent) -> Option<Action> {
KeyCode::Char('1') => Some(Action::SwitchTab(0)), KeyCode::Char('1') => Some(Action::SwitchTab(0)),
KeyCode::Char('2') => Some(Action::SwitchTab(1)), KeyCode::Char('2') => Some(Action::SwitchTab(1)),
KeyCode::Char('3') => Some(Action::SwitchTab(2)), KeyCode::Char('3') => Some(Action::SwitchTab(2)),
KeyCode::Char('4') => Some(Action::SwitchTab(3)),
KeyCode::Char('t') | KeyCode::Enter | KeyCode::Menu => Some(Action::ToggleTorrent), KeyCode::Char('t') | KeyCode::Enter | KeyCode::Menu => Some(Action::ToggleTorrent),
KeyCode::Char('a') => Some(Action::ToggleAll), KeyCode::Char('a') => Some(Action::ToggleAll),
KeyCode::Char(' ') => Some(Action::Select),
// Other handlers you could add here. // Other handlers you could add here.
_ => None, _ => None,
} }
@ -44,6 +44,7 @@ pub async fn update(app: &mut App<'_>, action: Action) -> transmission_rpc::type
Action::Move => unimplemented!(), Action::Move => unimplemented!(),
Action::Delete(x) => app.delete(x).await?, Action::Delete(x) => app.delete(x).await?,
Action::Rename => unimplemented!(), Action::Rename => unimplemented!(),
Action::Select => app.select(),
} }
Ok(()) Ok(())
} }

View File

@ -1,6 +1,6 @@
use ratatui::{ use ratatui::{
layout::Constraint, layout::Constraint,
style::{Color, Style}, style::{Color, Style, Styled},
widgets::{Block, BorderType, Borders, Row, Table}, widgets::{Block, BorderType, Borders, Row, Table},
}; };
@ -8,7 +8,9 @@ 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 torrents = &app.torrents.set_fields(None).torrents; let torrents = &app.torrents.set_fields(None).torrents;
let highlight_style = Style::default().bg(Color::Magenta).fg(Color::Black);
let rows: Vec<Row<'_>> = torrents let rows: Vec<Row<'_>> = torrents
.iter() .iter()
@ -16,7 +18,14 @@ pub fn render_table<'a>(app: &mut App, tab: Tab) -> Table<'a> {
Row::new( Row::new(
fields fields
.iter() .iter()
.map(|&field| field.value(torrent.clone())) .map(|&field| {
if let Some(id) = &torrent.clone().id {
if selected.contains(id) {
return field.value(torrent.clone()).set_style(highlight_style);
}
}
return field.value(torrent.clone()).into();
})
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
) )
}) })
@ -34,6 +43,9 @@ pub fn render_table<'a>(app: &mut App, tab: Tab) -> Table<'a> {
.collect::<Vec<_>>(), .collect::<Vec<_>>(),
) )
.style(Style::default().fg(Color::Yellow)); .style(Style::default().fg(Color::Yellow));
let highlight_style = Style::default().bg(Color::Blue).fg(Color::Black);
Table::new(rows, widths) Table::new(rows, widths)
.block( .block(
Block::default() Block::default()
@ -41,7 +53,6 @@ pub fn render_table<'a>(app: &mut App, tab: Tab) -> Table<'a> {
.border_type(BorderType::Rounded), .border_type(BorderType::Rounded),
) )
.header(header) .header(header)
.highlight_style(Style::default().fg(Color::Red)) .highlight_style(highlight_style)
.highlight_symbol(">> ")
.column_spacing(1) .column_spacing(1)
} }