Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: renaming torrents #123

Merged
merged 2 commits into from
Oct 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions rm-config/defaults/keymap.toml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ keybindings = [
keybindings = [
{ on = "a", action = "AddMagnet" },
{ on = "m", action = "MoveTorrent" },
{ on = "r", action = "Rename" },
{ on = "c", action = "ChangeCategory" },
{ on = "p", action = "Pause" },
{ on = "f", action = "ShowFiles" },
Expand Down
3 changes: 3 additions & 0 deletions rm-config/src/keymap/actions/torrents_tab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use serde::{Deserialize, Serialize};
pub enum TorrentsAction {
AddMagnet,
MoveTorrent,
Rename,
Pause,
Delete,
ShowFiles,
Expand All @@ -23,6 +24,7 @@ impl UserAction for TorrentsAction {
TorrentsAction::ShowFiles => "show files",
TorrentsAction::ShowStats => "show statistics",
TorrentsAction::ChangeCategory => "change category",
TorrentsAction::Rename => "rename torrent path",
}
}
}
Expand All @@ -37,6 +39,7 @@ impl From<TorrentsAction> for Action {
TorrentsAction::ShowFiles => Action::ShowFiles,
TorrentsAction::ShowStats => Action::ShowStats,
TorrentsAction::ChangeCategory => Action::ChangeCategory,
TorrentsAction::Rename => Action::Rename,
}
}
}
18 changes: 18 additions & 0 deletions rm-main/src/transmission/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ pub enum TorrentAction {
Start(Vec<Id>),
// Torrent ID, Directory to move to
Move(Vec<Id>, String),
// Torrent ID, Current name, Name to change to
Rename(Id, String, String),
// Torrent ID, Category to set
ChangeCategory(Vec<Id>, String),
// Delete Torrents with these given IDs (without files)
Expand Down Expand Up @@ -231,6 +233,22 @@ pub async fn action_handler(
}
}
}
TorrentAction::Rename(id, current_name, new_name) => {
match client
.torrent_rename_path(vec![id], current_name, new_name)
.await
{
Ok(_) => action_tx.send(UpdateAction::StatusTaskSuccess).unwrap(),
Err(err) => {
let msg = "Failed to rename a torrent";
let err_message = ErrorMessage::new(FAILED_TO_COMMUNICATE, msg, err);
action_tx
.send(UpdateAction::Error(Box::new(err_message)))
.unwrap();
action_tx.send(UpdateAction::StatusTaskFailure).unwrap();
}
}
}
}
}
}
6 changes: 6 additions & 0 deletions rm-main/src/tui/tabs/torrents/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,12 @@ impl Component for TorrentsTab {
self.task_manager.delete_torrents(torrent_selection);
}
}
A::Rename => {
if let Some(TorrentSelection::Single(id, curr_name)) = self.get_currently_selected()
{
self.task_manager.rename(id, curr_name);
}
}
A::AddMagnet => self.task_manager.add_magnet(),
A::Search => self.task_manager.search(
&self
Expand Down
16 changes: 16 additions & 0 deletions rm-main/src/tui/tabs/torrents/popups/details.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ impl Component for DetailsPopup {
self.ctx.send_action(Action::ShowFiles);
ComponentAction::Quit
}
Action::Rename => {
self.ctx.send_action(Action::Rename);
ComponentAction::Quit
}
Action::ChangeCategory => {
self.ctx.send_action(Action::ChangeCategory);
ComponentAction::Quit
Expand Down Expand Up @@ -103,6 +107,17 @@ impl Component for DetailsPopup {
keybinding_style(),
));

let mut rename_line = Line::default();
rename_line.push_span(Span::raw("Rename: "));
rename_line.push_span(Span::styled(
CONFIG
.keybindings
.torrents_tab
.get_keys_for_action_joined(TorrentsAction::Rename)
.unwrap_or_default(),
keybinding_style(),
));

let mut delete_line = Line::default();
delete_line.push_span(Span::raw("Delete: "));
delete_line.push_span(Span::styled(
Expand Down Expand Up @@ -158,6 +173,7 @@ impl Component for DetailsPopup {
lines.push(padding_line);
lines.push(delete_line);
lines.push(show_files_line);
lines.push(rename_line);
lines.push(move_location_line);
lines.push(change_category_line);

Expand Down
14 changes: 14 additions & 0 deletions rm-main/src/tui/tabs/torrents/task_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use rm_shared::{
action::{Action, UpdateAction},
status_task::StatusTask,
};
use transmission_rpc::types::Id;

use crate::tui::{
app,
Expand Down Expand Up @@ -45,6 +46,7 @@ pub enum CurrentTask {
Status(tasks::Status),
Sort(tasks::Sort),
Selection(tasks::Selection),
Rename(tasks::Rename),
}

impl CurrentTask {
Expand Down Expand Up @@ -89,6 +91,11 @@ impl Component for TaskManager {
self.cancel_task()
}
}
CurrentTask::Rename(rename_bar) => {
if rename_bar.handle_actions(action).is_quit() {
self.cancel_task()
}
}
CurrentTask::Default(_) => (),
CurrentTask::Sort(_) => (),
CurrentTask::Selection(_) => (),
Expand Down Expand Up @@ -126,6 +133,7 @@ impl Component for TaskManager {
CurrentTask::ChangeCategory(category_bar) => category_bar.render(f, rect),
CurrentTask::Sort(sort_bar) => sort_bar.render(f, rect),
CurrentTask::Selection(selection_bar) => selection_bar.render(f, rect),
CurrentTask::Rename(rename_bar) => rename_bar.render(f, rect),
}
}

Expand All @@ -146,6 +154,12 @@ impl TaskManager {
self.ctx.send_update_action(UpdateAction::SwitchToInputMode);
}

pub fn rename(&mut self, id: Id, curr_name: String) {
self.current_task =
CurrentTask::Rename(tasks::Rename::new(self.ctx.clone(), id, curr_name));
self.ctx.send_update_action(UpdateAction::SwitchToInputMode);
}

pub fn delete_torrents(&mut self, selection: TorrentSelection) {
self.current_task = CurrentTask::Delete(tasks::Delete::new(self.ctx.clone(), selection));
self.ctx.send_update_action(UpdateAction::SwitchToInputMode);
Expand Down
2 changes: 2 additions & 0 deletions rm-main/src/tui/tabs/torrents/tasks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod default;
mod delete_torrent;
mod filter;
mod move_torrent;
mod rename;
mod selection;
mod sort;
mod status;
Expand All @@ -14,6 +15,7 @@ pub use default::Default;
pub use delete_torrent::Delete;
pub use filter::Filter;
pub use move_torrent::Move;
pub use rename::Rename;
pub use selection::Selection;
pub use sort::Sort;
pub use status::{CurrentTaskState, Status};
Expand Down
80 changes: 80 additions & 0 deletions rm-main/src/tui/tabs/torrents/tasks/rename.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use crossterm::event::KeyCode;
use ratatui::{prelude::*, Frame};
use rm_shared::{
action::{Action, UpdateAction},
status_task::StatusTask,
};
use transmission_rpc::types::Id;

use crate::{
transmission::TorrentAction,
tui::{
app,
components::{Component, ComponentAction, InputManager},
},
};

pub struct Rename {
id: Id,
curr_name: String,
input_mgr: InputManager,
ctx: app::Ctx,
}

impl Rename {
pub fn new(ctx: app::Ctx, to_rename: Id, curr_name: String) -> Self {
let prompt = String::from("New name: ");

Self {
id: to_rename,
ctx,
input_mgr: InputManager::new_with_value(prompt, curr_name.clone()),
curr_name,
}
}

fn rename(&self) {
let new_name = self.input_mgr.text();

if self.curr_name == new_name {
return;
}

let task = StatusTask::new_rename(self.curr_name.clone());

self.ctx
.send_update_action(UpdateAction::StatusTaskSet(task));
self.ctx.send_torrent_action(TorrentAction::Rename(
self.id.clone(),
self.curr_name.clone(),
self.input_mgr.text(),
))
}
}

impl Component for Rename {
fn handle_actions(&mut self, action: Action) -> crate::tui::components::ComponentAction {
match action {
Action::Input(input) => {
if input.code == KeyCode::Esc {
return ComponentAction::Quit;
} else if input.code == KeyCode::Enter {
self.rename();
return ComponentAction::Quit;
}

if self.input_mgr.handle_key(input).is_some() {
self.ctx.send_action(Action::Render);
}

ComponentAction::Nothing
}

_ => ComponentAction::Nothing,
}
}

fn render(&mut self, f: &mut Frame, rect: Rect) {
self.input_mgr.render(f, rect)
}
}
1 change: 1 addition & 0 deletions rm-shared/src/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ pub enum Action {
AddMagnet,
MoveTorrent,
ChangeCategory,
Rename,
// Search Tab
ShowProvidersInfo,
}
Expand Down
11 changes: 11 additions & 0 deletions rm-shared/src/status_task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub struct StatusTask {
enum TaskType {
Add,
Delete,
Rename,
Move,
Open,
ChangeCategory,
Expand All @@ -22,6 +23,13 @@ impl StatusTask {
}
}

pub fn new_rename(what: impl Into<String>) -> Self {
StatusTask {
task_type: TaskType::Rename,
what: what.into(),
}
}

pub fn new_del(what: impl Into<String>) -> Self {
StatusTask {
task_type: TaskType::Delete,
Expand Down Expand Up @@ -65,6 +73,7 @@ impl StatusTask {
format!(" Category set to {truncated}!")
}
}
TaskType::Rename => format!("Renamed {truncated}"),
}
}

Expand All @@ -77,6 +86,7 @@ impl StatusTask {
TaskType::Move => format!(" Error moving to {truncated}"),
TaskType::Open => format!(" Error opening {truncated}"),
TaskType::ChangeCategory => format!(" Error changing category to {truncated}"),
TaskType::Rename => format!(" Error renaming {truncated}"),
}
}

Expand All @@ -89,6 +99,7 @@ impl StatusTask {
TaskType::Move => format!(" Moving {truncated}"),
TaskType::Open => format!(" Opening {truncated}"),
TaskType::ChangeCategory => format!(" Changing category to {truncated}"),
TaskType::Rename => format!(" Renaming {truncated}"),
}
}
}
Loading