Skip to content

Commit

Permalink
feat: display torrent location + move torrent location
Browse files Browse the repository at this point in the history
  • Loading branch information
aidanaden committed Jun 22, 2024
1 parent e4f0a63 commit d3a70e5
Show file tree
Hide file tree
Showing 8 changed files with 130 additions and 11 deletions.
2 changes: 2 additions & 0 deletions rm-main/src/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ pub(crate) enum Action {
SwitchToNormalMode,
ChangeFocus,
AddMagnet,
MoveTorrent,
ChangeTab(u8),
Input(KeyEvent),
Error(Box<ErrorPopup>),
Expand Down Expand Up @@ -104,6 +105,7 @@ fn keycode_to_action(key: KeyCode) -> Option<Action> {
KeyCode::Char('f') => Some(A::ShowFiles),
KeyCode::Char('/') => Some(A::Search),
KeyCode::Char('a') => Some(A::AddMagnet),
KeyCode::Char('m') => Some(A::MoveTorrent),
KeyCode::Char('p') => Some(A::Pause),
KeyCode::Char('d') => Some(A::DeleteWithoutFiles),
KeyCode::Char('D') => Some(A::DeleteWithFiles),
Expand Down
19 changes: 19 additions & 0 deletions rm-main/src/transmission/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ pub enum TorrentAction {
GetTorrentInfo(Id, Arc<Mutex<Option<Torrent>>>),
GetSessionGet(oneshot::Sender<SessionGet>),
SetArgs(Box<TorrentSetArgs>, Option<Vec<Id>>),
// Torrent ID, Directory to move to
Move(Vec<Id>, String),
}

// TODO: make all the options use the same type of interface. Probably use a sender everywhere
Expand Down Expand Up @@ -106,6 +108,23 @@ pub async fn action_handler(ctx: app::Ctx, mut trans_rx: UnboundedReceiver<Torre
.arguments;
sender.send(session_get).unwrap();
}
TorrentAction::Move(ids, new_directory) => {
if let Err(e) = ctx
.client
.lock()
.await
.torrent_set_location(ids, new_directory.clone(), Option::from(true))
.await
{
let error_title = "Failed to move torrent";
let msg = "Failed to move torrent to new directory:\n\"".to_owned()
+ new_directory.as_str()
+ "\"\n"
+ &e.to_string();
let error_popup = Box::new(ErrorPopup::new(error_title, msg));
ctx.send_action(Action::Error(error_popup));
}
}
}
}
}
1 change: 1 addition & 0 deletions rm-main/src/transmission/fetchers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ pub async fn torrents(ctx: app::Ctx, table_manager: Arc<Mutex<TableManager>>) {
TorrentGetField::RateUpload,
TorrentGetField::RateDownload,
TorrentGetField::Status,
TorrentGetField::DownloadDir,
];
let rpc_response = ctx
.client
Expand Down
9 changes: 9 additions & 0 deletions rm-main/src/ui/tabs/torrents/rustmission_torrent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub struct RustmissionTorrent {
status: TorrentStatus,
pub style: Style,
pub id: Id,
pub download_dir: String,
}

impl RustmissionTorrent {
Expand All @@ -29,6 +30,7 @@ impl RustmissionTorrent {
self.eta_secs.as_str(),
self.download_speed.as_str(),
self.upload_speed.as_str(),
self.download_dir.as_str(),
])
.style(self.style)
}
Expand All @@ -55,6 +57,7 @@ impl RustmissionTorrent {
Line::from(self.eta_secs.as_str()),
Line::from(self.download_speed.as_str()),
Line::from(self.upload_speed.as_str()),
Line::from(self.download_dir.as_str()),
])
}

Expand Down Expand Up @@ -109,6 +112,11 @@ impl From<&Torrent> for RustmissionTorrent {
_ => Style::default(),
};

let download_dir = t
.download_dir
.clone()
.expect("torrent download directory requested");

Self {
torrent_name,
size_when_done,
Expand All @@ -119,6 +127,7 @@ impl From<&Torrent> for RustmissionTorrent {
status,
style,
id,
download_dir,
}
}
}
26 changes: 17 additions & 9 deletions rm-main/src/ui/tabs/torrents/table_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use super::rustmission_torrent::RustmissionTorrent;
pub struct TableManager {
ctx: app::Ctx,
pub table: GenericTable<RustmissionTorrent>,
pub widths: [Constraint; 6],
pub widths: [Constraint; 7],
pub filter: Arc<Mutex<Option<String>>>,
pub torrents_displaying_no: u16,
header: Vec<String>,
Expand All @@ -31,6 +31,7 @@ impl TableManager {
"ETA".to_owned(),
"Download".to_owned(),
"Upload".to_owned(),
"Directory".to_owned(),
],
}
}
Expand Down Expand Up @@ -100,18 +101,19 @@ impl TableManager {
rows
}

const fn default_widths() -> [Constraint; 6] {
const fn default_widths() -> [Constraint; 7] {
[
Constraint::Max(70), // Name
Constraint::Length(10), // Size
Constraint::Length(10), // Progress
Constraint::Length(10), // ETA
Constraint::Length(10), // Download
Constraint::Length(10), // Upload
Constraint::Length(20), // Download directory
]
}

fn header_widths(&self, rows: &[RustmissionTorrent]) -> [Constraint; 6] {
fn header_widths(&self, rows: &[RustmissionTorrent]) -> [Constraint; 7] {
if !self.ctx.config.general.auto_hide {
return Self::default_widths();
}
Expand All @@ -120,6 +122,7 @@ impl TableManager {
let mut upload_width = 0;
let mut progress_width = 0;
let mut eta_width = 0;
let mut download_dir_width = 0;

for row in rows {
if !row.download_speed.is_empty() {
Expand All @@ -135,15 +138,20 @@ impl TableManager {
if !row.eta_secs.is_empty() {
eta_width = 9;
}

if !row.download_dir.is_empty() {
download_dir_width = 18;
}
}

[
Constraint::Max(70), // Name
Constraint::Length(9), // Size
Constraint::Length(progress_width), // Progress
Constraint::Length(eta_width), // ETA
Constraint::Length(download_width), // Download
Constraint::Length(upload_width), // Upload
Constraint::Max(70), // Name
Constraint::Length(9), // Size
Constraint::Length(progress_width), // Progress
Constraint::Length(eta_width), // ETA
Constraint::Length(download_width), // Download
Constraint::Length(upload_width), // Upload
Constraint::Length(download_dir_width), // Download directory
]
}
}
21 changes: 19 additions & 2 deletions rm-main/src/ui/tabs/torrents/task_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use super::{
default::DefaultBar,
delete_torrent::{self, DeleteBar},
filter::FilterBar,
move_torrent::MoveBar,
},
TableManager,
};
Expand All @@ -34,6 +35,7 @@ enum CurrentTask {
AddMagnetBar(AddMagnetBar),
DeleteBar(DeleteBar),
FilterBar(FilterBar),
MoveBar(MoveBar),
Default(DefaultBar),
}

Expand All @@ -53,13 +55,16 @@ impl Component for TaskManager {
Some(A::Render) => Some(A::Render),
_ => None,
},

CurrentTask::MoveBar(move_bar) => match move_bar.handle_actions(action) {
Some(A::Quit) => self.finish_task(),
Some(A::Render) => Some(A::Render),
_ => None,
},
CurrentTask::FilterBar(filter_bar) => match filter_bar.handle_actions(action) {
Some(A::Quit) => self.finish_task(),
Some(A::Render) => Some(A::Render),
_ => None,
},

CurrentTask::Default(_) => self.handle_events_to_manager(&action),
}
}
Expand All @@ -68,6 +73,7 @@ impl Component for TaskManager {
match &mut self.current_task {
CurrentTask::AddMagnetBar(magnet_bar) => magnet_bar.render(f, rect),
CurrentTask::DeleteBar(delete_bar) => delete_bar.render(f, rect),
CurrentTask::MoveBar(move_bar) => move_bar.render(f, rect),
CurrentTask::FilterBar(filter_bar) => filter_bar.render(f, rect),
CurrentTask::Default(default_bar) => default_bar.render(f, rect),
}
Expand All @@ -84,6 +90,7 @@ impl TaskManager {
}
Action::DeleteWithFiles => self.delete_torrent(delete_torrent::Mode::WithFiles),
Action::DeleteWithoutFiles => self.delete_torrent(delete_torrent::Mode::WithoutFiles),
Action::MoveTorrent => self.move_torrent(),
Action::Search => {
self.current_task = CurrentTask::FilterBar(FilterBar::new(
self.ctx.clone(),
Expand All @@ -108,6 +115,16 @@ impl TaskManager {
}
}

fn move_torrent(&mut self) -> Option<Action> {
if let Some(torrent) = self.table_manager.lock().unwrap().current_torrent() {
self.current_task =
CurrentTask::MoveBar(MoveBar::new(self.ctx.clone(), vec![torrent.id.clone()]));
Some(Action::SwitchToInputMode)
} else {
None
}
}

fn finish_task(&mut self) -> Option<Action> {
if !matches!(self.current_task, CurrentTask::Default(_)) {
self.current_task = CurrentTask::Default(DefaultBar::new(self.ctx.clone()));
Expand Down
1 change: 1 addition & 0 deletions rm-main/src/ui/tabs/torrents/tasks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ pub mod add_magnet;
pub mod default;
pub mod delete_torrent;
pub mod filter;
pub mod move_torrent;
62 changes: 62 additions & 0 deletions rm-main/src/ui/tabs/torrents/tasks/move_torrent.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use crossterm::event::{KeyCode, KeyEvent};
use ratatui::prelude::*;
use transmission_rpc::types::Id;

use crate::{
action::Action,
app,
transmission::TorrentAction,
ui::{components::Component, tabs::torrents::input_manager::InputManager, to_input_request},
};

pub struct MoveBar {
torrents_to_move: Vec<Id>,
ctx: app::Ctx,
input_mgr: InputManager,
}

impl MoveBar {
pub fn new(ctx: app::Ctx, to_move: Vec<Id>) -> Self {
let prompt = format!("New directory: ");

Self {
torrents_to_move: to_move,
input_mgr: InputManager::new(ctx.clone(), prompt),
ctx,
}
}

fn handle_input(&mut self, input: KeyEvent) -> Option<Action> {
if input.code == KeyCode::Enter {
let new_location = self.input_mgr.text().to_lowercase();
let torrents_to_move = self.torrents_to_move.clone();
self.ctx
.send_torrent_action(TorrentAction::Move(torrents_to_move, new_location));
return Some(Action::Quit);
}

if input.code == KeyCode::Esc {
return Some(Action::Quit);
}

if let Some(req) = to_input_request(input) {
self.input_mgr.handle(req);
return Some(Action::Render);
}

None
}
}

impl Component for MoveBar {
fn handle_actions(&mut self, action: Action) -> Option<Action> {
match action {
Action::Input(input) => self.handle_input(input),
_ => None,
}
}

fn render(&mut self, f: &mut Frame, rect: Rect) {
self.input_mgr.render(f, rect)
}
}

0 comments on commit d3a70e5

Please sign in to comment.