mirror of
https://github.com/kristoferssolo/traxor.git
synced 2026-02-04 06:42:04 +00:00
refactor: use derive macro
This commit is contained in:
@@ -20,8 +20,9 @@ impl Torrents {
|
||||
self.client
|
||||
.torrent_action(action, vec![id])
|
||||
.await
|
||||
.map_err(|e| color_eyre::eyre::eyre!("Transmission RPC error: {}", e.to_string()))?;
|
||||
|
||||
.map_err(|e| {
|
||||
color_eyre::eyre::eyre!("Transmission RPC error: {}", e.to_string())
|
||||
})?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
@@ -48,7 +49,9 @@ impl Torrents {
|
||||
self.client
|
||||
.torrent_action(action, vec![id])
|
||||
.await
|
||||
.map_err(|e| color_eyre::eyre::eyre!("Transmission RPC error: {}", e.to_string()))?;
|
||||
.map_err(|e| {
|
||||
color_eyre::eyre::eyre!("Transmission RPC error: {}", e.to_string())
|
||||
})?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -71,12 +74,18 @@ impl Torrents {
|
||||
self.client
|
||||
.torrent_set_location(vec![id], location.to_string_lossy().into(), move_from)
|
||||
.await
|
||||
.map_err(|e| color_eyre::eyre::eyre!("Transmission RPC error: {}", e.to_string()))?;
|
||||
.map_err(|e| {
|
||||
color_eyre::eyre::eyre!("Transmission RPC error: {}", e.to_string())
|
||||
})?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn delete(&mut self, ids: Selected, delete_local_data: bool) -> color_eyre::eyre::Result<()> {
|
||||
pub async fn delete(
|
||||
&mut self,
|
||||
ids: Selected,
|
||||
delete_local_data: bool,
|
||||
) -> color_eyre::eyre::Result<()> {
|
||||
self.client
|
||||
.torrent_remove(ids.into(), delete_local_data)
|
||||
.await
|
||||
@@ -89,7 +98,9 @@ impl Torrents {
|
||||
self.client
|
||||
.torrent_rename_path(vec![id], old_name, name.to_string_lossy().into())
|
||||
.await
|
||||
.map_err(|e| color_eyre::eyre::eyre!("Transmission RPC error: {}", e.to_string()))?;
|
||||
.map_err(|e| {
|
||||
color_eyre::eyre::eyre!("Transmission RPC error: {}", e.to_string())
|
||||
})?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
use crate::merge_fields;
|
||||
use crate::merge::Merge;
|
||||
use derive_macro::Merge;
|
||||
use ratatui::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[derive(Debug, Deserialize, Serialize, Merge)]
|
||||
pub struct ColorsConfig {
|
||||
pub highlight_background: Option<String>,
|
||||
pub highlight_foreground: Option<String>,
|
||||
@@ -32,18 +33,6 @@ impl ColorsConfig {
|
||||
None => Color::Reset,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn merge(&mut self, other: Self) {
|
||||
merge_fields!(
|
||||
self,
|
||||
other,
|
||||
highlight_background,
|
||||
highlight_foreground,
|
||||
warning_foreground,
|
||||
info_foreground,
|
||||
error_foreground
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for ColorsConfig {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use crate::merge::Merge;
|
||||
use derive_macro::Merge;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use crate::merge_fields;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[derive(Debug, Deserialize, Serialize, Merge)]
|
||||
pub struct KeybindsConfig {
|
||||
pub quit: Option<String>,
|
||||
pub next_tab: Option<String>,
|
||||
@@ -19,29 +20,6 @@ pub struct KeybindsConfig {
|
||||
pub toggle_help: Option<String>,
|
||||
}
|
||||
|
||||
impl KeybindsConfig {
|
||||
pub fn merge(&mut self, other: Self) {
|
||||
merge_fields!(
|
||||
self,
|
||||
other,
|
||||
quit,
|
||||
next_tab,
|
||||
prev_tab,
|
||||
next_torrent,
|
||||
prev_torrent,
|
||||
switch_tab_1,
|
||||
switch_tab_2,
|
||||
switch_tab_3,
|
||||
toggle_torrent,
|
||||
toggle_all,
|
||||
delete,
|
||||
delete_force,
|
||||
select,
|
||||
toggle_help
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for KeybindsConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
|
||||
@@ -1,24 +1,15 @@
|
||||
mod colors;
|
||||
mod keybinds;
|
||||
|
||||
use crate::merge::Merge;
|
||||
use color_eyre::Result;
|
||||
use colors::ColorsConfig;
|
||||
use derive_macro::Merge;
|
||||
use keybinds::KeybindsConfig;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! merge_fields {
|
||||
($self:ident, $other:ident, $($field:ident),*) => {
|
||||
$(
|
||||
if let Some($field) = $other.$field {
|
||||
$self.$field = Some($field);
|
||||
}
|
||||
)*
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Deserialize, Serialize)]
|
||||
#[derive(Debug, Default, Deserialize, Serialize, Merge)]
|
||||
pub struct Config {
|
||||
pub keybinds: KeybindsConfig,
|
||||
pub colors: ColorsConfig,
|
||||
@@ -64,9 +55,4 @@ impl Config {
|
||||
});
|
||||
Ok(config_dir.join("traxor").join("config.toml"))
|
||||
}
|
||||
|
||||
pub fn merge(&mut self, other: Self) {
|
||||
self.keybinds.merge(other.keybinds);
|
||||
self.colors.merge(other.colors);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,8 +72,12 @@ pub fn get_action(key_event: KeyEvent, app: &App) -> Option<Action> {
|
||||
_ if matches_keybind(&key_event, &config_keybinds.quit) => Some(Action::Quit),
|
||||
_ if matches_keybind(&key_event, &config_keybinds.next_tab) => Some(Action::NextTab),
|
||||
_ if matches_keybind(&key_event, &config_keybinds.prev_tab) => Some(Action::PrevTab),
|
||||
_ if matches_keybind(&key_event, &config_keybinds.next_torrent) => Some(Action::NextTorrent),
|
||||
_ if matches_keybind(&key_event, &config_keybinds.prev_torrent) => Some(Action::PrevTorrent),
|
||||
_ if matches_keybind(&key_event, &config_keybinds.next_torrent) => {
|
||||
Some(Action::NextTorrent)
|
||||
}
|
||||
_ if matches_keybind(&key_event, &config_keybinds.prev_torrent) => {
|
||||
Some(Action::PrevTorrent)
|
||||
}
|
||||
_ if matches_keybind(&key_event, &config_keybinds.switch_tab_1) => {
|
||||
Some(Action::SwitchTab(0))
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
pub mod config;
|
||||
pub mod app;
|
||||
pub mod config;
|
||||
pub mod event;
|
||||
pub mod handler;
|
||||
pub mod log;
|
||||
pub mod merge;
|
||||
pub mod tui;
|
||||
pub mod ui;
|
||||
pub mod ui;
|
||||
|
||||
@@ -53,4 +53,3 @@ async fn main() -> Result<()> {
|
||||
tui.exit()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
21
src/merge.rs
Normal file
21
src/merge.rs
Normal file
@@ -0,0 +1,21 @@
|
||||
pub trait Merge {
|
||||
fn merge(&mut self, other: Self);
|
||||
}
|
||||
|
||||
impl Merge for String {
|
||||
fn merge(&mut self, other: Self) {
|
||||
*self = other;
|
||||
}
|
||||
}
|
||||
|
||||
impl Merge for u32 {
|
||||
fn merge(&mut self, other: Self) {
|
||||
*self = other;
|
||||
}
|
||||
}
|
||||
|
||||
impl Merge for bool {
|
||||
fn merge(&mut self, other: Self) {
|
||||
*self = other;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
use ratatui::{prelude::*, widgets::*};
|
||||
use crate::app::App;
|
||||
use ratatui::{prelude::*, widgets::*};
|
||||
|
||||
pub fn render_help(frame: &mut Frame, app: &App) {
|
||||
let block = Block::default()
|
||||
@@ -11,23 +11,62 @@ pub fn render_help(frame: &mut Frame, app: &App) {
|
||||
let keybinds = &app.config.keybinds;
|
||||
|
||||
let rows = vec![
|
||||
Row::new(vec![Cell::from(keybinds.toggle_help.as_deref().unwrap_or("?")), Cell::from("Show help")]),
|
||||
Row::new(vec![Cell::from(keybinds.quit.as_deref().unwrap_or("q")), Cell::from("Quit")]),
|
||||
Row::new(vec![Cell::from(keybinds.prev_tab.as_deref().unwrap_or("h")), Cell::from("Left")]),
|
||||
Row::new(vec![Cell::from(keybinds.next_tab.as_deref().unwrap_or("l")), Cell::from("Right")]),
|
||||
Row::new(vec![Cell::from(keybinds.next_torrent.as_deref().unwrap_or("j")), Cell::from("Down")]),
|
||||
Row::new(vec![Cell::from(keybinds.prev_torrent.as_deref().unwrap_or("k")), Cell::from("Up")]),
|
||||
Row::new(vec![Cell::from(keybinds.switch_tab_1.as_deref().unwrap_or("1")), Cell::from("Switch to All tab")]),
|
||||
Row::new(vec![Cell::from(keybinds.switch_tab_2.as_deref().unwrap_or("2")), Cell::from("Switch to Active tab")]),
|
||||
Row::new(vec![
|
||||
Cell::from(keybinds.toggle_help.as_deref().unwrap_or("?")),
|
||||
Cell::from("Show help"),
|
||||
]),
|
||||
Row::new(vec![
|
||||
Cell::from(keybinds.quit.as_deref().unwrap_or("q")),
|
||||
Cell::from("Quit"),
|
||||
]),
|
||||
Row::new(vec![
|
||||
Cell::from(keybinds.prev_tab.as_deref().unwrap_or("h")),
|
||||
Cell::from("Left"),
|
||||
]),
|
||||
Row::new(vec![
|
||||
Cell::from(keybinds.next_tab.as_deref().unwrap_or("l")),
|
||||
Cell::from("Right"),
|
||||
]),
|
||||
Row::new(vec![
|
||||
Cell::from(keybinds.next_torrent.as_deref().unwrap_or("j")),
|
||||
Cell::from("Down"),
|
||||
]),
|
||||
Row::new(vec![
|
||||
Cell::from(keybinds.prev_torrent.as_deref().unwrap_or("k")),
|
||||
Cell::from("Up"),
|
||||
]),
|
||||
Row::new(vec![
|
||||
Cell::from(keybinds.switch_tab_1.as_deref().unwrap_or("1")),
|
||||
Cell::from("Switch to All tab"),
|
||||
]),
|
||||
Row::new(vec![
|
||||
Cell::from(keybinds.switch_tab_2.as_deref().unwrap_or("2")),
|
||||
Cell::from("Switch to Active tab"),
|
||||
]),
|
||||
Row::new(vec![
|
||||
Cell::from(keybinds.switch_tab_3.as_deref().unwrap_or("3")),
|
||||
Cell::from("Switch to Downloading tab"),
|
||||
]),
|
||||
Row::new(vec![Cell::from(keybinds.toggle_torrent.as_deref().unwrap_or("t")), Cell::from("Toggle torrent")]),
|
||||
Row::new(vec![Cell::from(keybinds.toggle_all.as_deref().unwrap_or("a")), Cell::from("Toggle all torrents")]),
|
||||
Row::new(vec![Cell::from(keybinds.delete.as_deref().unwrap_or("d")), Cell::from("Delete torrent")]),
|
||||
Row::new(vec![Cell::from(keybinds.delete_force.as_deref().unwrap_or("D")), Cell::from("Delete torrent and data")]),
|
||||
Row::new(vec![Cell::from(keybinds.select.as_deref().unwrap_or(" ")), Cell::from("Select torrent")]),
|
||||
Row::new(vec![
|
||||
Cell::from(keybinds.toggle_torrent.as_deref().unwrap_or("t")),
|
||||
Cell::from("Toggle torrent"),
|
||||
]),
|
||||
Row::new(vec![
|
||||
Cell::from(keybinds.toggle_all.as_deref().unwrap_or("a")),
|
||||
Cell::from("Toggle all torrents"),
|
||||
]),
|
||||
Row::new(vec![
|
||||
Cell::from(keybinds.delete.as_deref().unwrap_or("d")),
|
||||
Cell::from("Delete torrent"),
|
||||
]),
|
||||
Row::new(vec![
|
||||
Cell::from(keybinds.delete_force.as_deref().unwrap_or("D")),
|
||||
Cell::from("Delete torrent and data"),
|
||||
]),
|
||||
Row::new(vec![
|
||||
Cell::from(keybinds.select.as_deref().unwrap_or(" ")),
|
||||
Cell::from("Select torrent"),
|
||||
]),
|
||||
];
|
||||
|
||||
let table = Table::new(
|
||||
@@ -35,7 +74,12 @@ pub fn render_help(frame: &mut Frame, app: &App) {
|
||||
&[Constraint::Percentage(20), Constraint::Percentage(80)],
|
||||
)
|
||||
.block(block)
|
||||
.style(Style::default().fg(app.config.colors.get_color(&app.config.colors.info_foreground)));
|
||||
.style(
|
||||
Style::default().fg(app
|
||||
.config
|
||||
.colors
|
||||
.get_color(&app.config.colors.info_foreground)),
|
||||
);
|
||||
|
||||
let area = frame.area();
|
||||
let height = 15; // Desired height for the help menu
|
||||
@@ -51,4 +95,3 @@ pub fn render_help(frame: &mut Frame, app: &App) {
|
||||
frame.render_widget(Clear, popup_area);
|
||||
frame.render_widget(table, popup_area);
|
||||
}
|
||||
|
||||
|
||||
@@ -32,8 +32,18 @@ pub fn render(app: &mut App, frame: &mut Frame) {
|
||||
.border_type(BorderType::Rounded),
|
||||
)
|
||||
.select(app.index())
|
||||
.style(Style::default().fg(app.config.colors.get_color(&app.config.colors.info_foreground)))
|
||||
.highlight_style(Style::default().fg(app.config.colors.get_color(&app.config.colors.warning_foreground)))
|
||||
.style(
|
||||
Style::default().fg(app
|
||||
.config
|
||||
.colors
|
||||
.get_color(&app.config.colors.info_foreground)),
|
||||
)
|
||||
.highlight_style(
|
||||
Style::default().fg(app
|
||||
.config
|
||||
.colors
|
||||
.get_color(&app.config.colors.warning_foreground)),
|
||||
)
|
||||
.divider("|");
|
||||
|
||||
frame.render_widget(tabs, chunks[0]); // renders tab
|
||||
|
||||
@@ -10,8 +10,14 @@ pub fn render_table<'a>(app: &mut App, tab: Tab) -> Table<'a> {
|
||||
let selected = &app.torrents.selected.clone();
|
||||
let torrents = &app.torrents.set_fields(None).torrents;
|
||||
|
||||
let highlight_bg = app.config.colors.get_color(&app.config.colors.highlight_background);
|
||||
let highlight_fg = app.config.colors.get_color(&app.config.colors.highlight_foreground);
|
||||
let highlight_bg = app
|
||||
.config
|
||||
.colors
|
||||
.get_color(&app.config.colors.highlight_background);
|
||||
let highlight_fg = app
|
||||
.config
|
||||
.colors
|
||||
.get_color(&app.config.colors.highlight_foreground);
|
||||
let highlight_style = Style::default().bg(highlight_bg).fg(highlight_fg);
|
||||
|
||||
let rows: Vec<Row<'_>> = torrents
|
||||
@@ -38,7 +44,10 @@ pub fn render_table<'a>(app: &mut App, tab: Tab) -> Table<'a> {
|
||||
.map(|&field| Constraint::Length(field.width()))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let header_fg = app.config.colors.get_color(&app.config.colors.warning_foreground);
|
||||
let header_fg = app
|
||||
.config
|
||||
.colors
|
||||
.get_color(&app.config.colors.warning_foreground);
|
||||
let header = Row::new(
|
||||
fields
|
||||
.iter()
|
||||
@@ -47,8 +56,14 @@ pub fn render_table<'a>(app: &mut App, tab: Tab) -> Table<'a> {
|
||||
)
|
||||
.style(Style::default().fg(header_fg));
|
||||
|
||||
let row_highlight_bg = app.config.colors.get_color(&app.config.colors.info_foreground);
|
||||
let row_highlight_fg = app.config.colors.get_color(&app.config.colors.highlight_foreground);
|
||||
let row_highlight_bg = app
|
||||
.config
|
||||
.colors
|
||||
.get_color(&app.config.colors.info_foreground);
|
||||
let row_highlight_fg = app
|
||||
.config
|
||||
.colors
|
||||
.get_color(&app.config.colors.highlight_foreground);
|
||||
let row_highlight_style = Style::default().bg(row_highlight_bg).fg(row_highlight_fg);
|
||||
|
||||
Table::new(rows, widths)
|
||||
|
||||
Reference in New Issue
Block a user