chore: update dependency version

This commit is contained in:
Kristofers Solo 2025-06-30 21:09:15 +03:00
parent ad2cccb908
commit b450d3abcf
Signed by: kristoferssolo
GPG Key ID: 8687F2D3EEE6F0ED
5 changed files with 1365 additions and 669 deletions

1639
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -5,12 +5,11 @@ authors = ["Kristofers Solo <dev@kristofers.xyz>"]
license = "GPLv3" license = "GPLv3"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
crossterm = "0.27" crossterm = "0.29"
ratatui = { version = "0.26" } ratatui = { version = "0.29" }
transmission-rpc = "0.4" transmission-rpc = "0.5"
url = "2.4" url = "2.5"
anyhow = "1.0" anyhow = "1.0"
tokio = { version = "1", features = ["full"] } tokio = { version = "1", features = ["full"] }
tracing = "0.1" tracing = "0.1"

View File

@ -1,10 +1,9 @@
use transmission_rpc::types::{ErrorType, Torrent, TorrentGetField, TorrentStatus};
mod filesize;
mod netspeed; mod netspeed;
use filesize::FileSize;
use self::netspeed::NetSpeed; use transmission_rpc::types::{ErrorType, Torrent, TorrentGetField, TorrentStatus};
mod filesize;
use filesize::FileSize;
use netspeed::NetSpeed;
pub trait Wrapper { pub trait Wrapper {
fn title(&self) -> String { fn title(&self) -> String {
@ -23,58 +22,104 @@ pub trait Wrapper {
impl Wrapper for TorrentGetField { impl Wrapper for TorrentGetField {
fn title(&self) -> String { fn title(&self) -> String {
match self { match self {
TorrentGetField::ActivityDate => String::from("Activity Date"), Self::ActivityDate => String::from("Activity Date"),
TorrentGetField::AddedDate => String::from("Added Date"), Self::AddedDate => String::from("Added Date"),
TorrentGetField::DoneDate => String::from("Done Date"), Self::Availability => todo!(),
TorrentGetField::DownloadDir => String::from("Path"), Self::BandwidthPriority => todo!(),
TorrentGetField::EditDate => String::from("Edit Date"), Self::Comment => todo!(),
TorrentGetField::Error => String::from("Error Type"), Self::CorruptEver => todo!(),
TorrentGetField::ErrorString => String::from("Error String"), Self::Creator => todo!(),
TorrentGetField::Eta => String::from("ETA"), Self::DateCreated => todo!(),
TorrentGetField::FileStats => String::from("File Stats"), Self::DesiredAvailable => todo!(),
TorrentGetField::Files => String::from("Files"), Self::DoneDate => String::from("Done Date"),
TorrentGetField::HashString => String::from("Hash String"), Self::DownloadDir => String::from("Path"),
TorrentGetField::Id => String::from("Id"), Self::DownloadLimit => todo!(),
TorrentGetField::IsFinished => String::from("Finished"), Self::DownloadLimited => todo!(),
TorrentGetField::IsPrivate => String::from("Private"), Self::DownloadedEver => todo!(),
TorrentGetField::IsStalled => String::from("Stalled"), Self::EditDate => String::from("Edit Date"),
TorrentGetField::Labels => String::from("Labels"), Self::Error => String::from("Error Type"),
TorrentGetField::LeftUntilDone => String::from("Left Until Done"), Self::ErrorString => String::from("Error String"),
TorrentGetField::MetadataPercentComplete => String::from("Metadata Percent Complete"), Self::Eta => String::from("ETA"),
TorrentGetField::Name => String::from("Name"), Self::EtaIdle => todo!(),
TorrentGetField::PeersConnected => String::from("Connected"), Self::FileCount => todo!(),
TorrentGetField::PeersGettingFromUs => String::from("Peers"), Self::FileStats => String::from("File Stats"),
TorrentGetField::PeersSendingToUs => String::from("Seeds"), Self::Files => String::from("Files"),
TorrentGetField::PercentDone => String::from("%"), Self::Group => todo!(),
TorrentGetField::Priorities => String::from("Priorities"), Self::HashString => String::from("Hash String"),
TorrentGetField::QueuePosition => String::from("Queue"), Self::HaveUnchecked => todo!(),
TorrentGetField::RateDownload => String::from("Download Speed"), Self::HaveValid => todo!(),
TorrentGetField::RateUpload => String::from("Upload Speed"), Self::HonorsSessionLimits => todo!(),
TorrentGetField::RecheckProgress => String::from("Progress"), Self::Id => String::from("Id"),
TorrentGetField::SecondsSeeding => String::from("Seconds Seeding"), Self::IsFinished => String::from("Finished"),
TorrentGetField::SeedRatioLimit => String::from("Seed Ratio Limit"), Self::IsPrivate => String::from("Private"),
TorrentGetField::SeedRatioMode => String::from("Seed Ratio Mode"), Self::IsStalled => String::from("Stalled"),
TorrentGetField::SizeWhenDone => String::from("Size"), Self::Labels => String::from("Labels"),
TorrentGetField::Status => String::from("Status"), Self::LeftUntilDone => String::from("Left Until Done"),
TorrentGetField::TorrentFile => String::from("Torrent File"), Self::MagnetLink => todo!(),
TorrentGetField::TotalSize => String::from("Total Size"), Self::ManualAnnounceTime => todo!(),
TorrentGetField::Trackers => String::from("Trackers"), Self::MaxConnectedPeers => todo!(),
TorrentGetField::UploadRatio => String::from("Ratio"), Self::MetadataPercentComplete => String::from("Metadata Percent Complete"),
TorrentGetField::UploadedEver => String::from("Uploaded"), Self::Name => String::from("Name"),
TorrentGetField::Wanted => String::from("Wanted"), Self::PeerLimit => todo!(),
TorrentGetField::WebseedsSendingToUs => String::from("Webseeds Sending to Us"), Self::Peers => todo!(),
TorrentGetField::FileCount => unimplemented!(), Self::PeersConnected => String::from("Connected"),
Self::PeersFrom => todo!(),
Self::PeersGettingFromUs => String::from("Peers"),
Self::PeersSendingToUs => String::from("Seeds"),
Self::PercentComplete => todo!(),
Self::PercentDone => String::from("%"),
Self::PieceCount => todo!(),
Self::PieceSize => todo!(),
Self::Pieces => todo!(),
Self::PrimaryMimeType => todo!(),
Self::Priorities => String::from("Priorities"),
Self::QueuePosition => String::from("Queue"),
Self::RateDownload => String::from("Download Speed"),
Self::RateUpload => String::from("Upload Speed"),
Self::RecheckProgress => String::from("Progress"),
Self::SecondsDownloading => todo!(),
Self::SecondsSeeding => String::from("Seconds Seeding"),
Self::SeedIdleLimit => todo!(),
Self::SeedIdleMode => todo!(),
Self::SeedRatioLimit => String::from("Seed Ratio Limit"),
Self::SeedRatioMode => String::from("Seed Ratio Mode"),
Self::SequentialDownload => todo!(),
Self::SizeWhenDone => String::from("Size"),
Self::StartDate => todo!(),
Self::Status => String::from("Status"),
Self::TorrentFile => String::from("Torrent File"),
Self::TotalSize => String::from("Total Size"),
Self::TrackerList => todo!(),
Self::TrackerStats => todo!(),
Self::Trackers => String::from("Trackers"),
Self::UploadLimit => todo!(),
Self::UploadLimited => todo!(),
Self::UploadRatio => String::from("Ratio"),
Self::UploadedEver => String::from("Uploaded"),
Self::Wanted => String::from("Wanted"),
Self::Webseeds => todo!(),
Self::WebseedsSendingToUs => String::from("Webseeds Sending to Us"),
} }
} }
fn value(&self, torrent: Torrent) -> String { fn value(&self, torrent: Torrent) -> String {
match self { match self {
TorrentGetField::ActivityDate => optional_to_string(torrent.activity_date), Self::ActivityDate => optional_to_string(torrent.activity_date),
TorrentGetField::AddedDate => optional_to_string(torrent.added_date), Self::AddedDate => optional_to_string(torrent.added_date),
TorrentGetField::DoneDate => optional_to_string(torrent.done_date), Self::Availability => todo!(),
TorrentGetField::DownloadDir => optional_to_string(torrent.download_dir), Self::BandwidthPriority => todo!(),
TorrentGetField::EditDate => optional_to_string(torrent.edit_date), Self::Comment => todo!(),
TorrentGetField::Error => match torrent.error { Self::CorruptEver => todo!(),
Self::Creator => todo!(),
Self::DateCreated => todo!(),
Self::DesiredAvailable => todo!(),
Self::DoneDate => optional_to_string(torrent.done_date),
Self::DownloadDir => optional_to_string(torrent.download_dir),
Self::DownloadLimit => todo!(),
Self::DownloadLimited => todo!(),
Self::DownloadedEver => todo!(),
Self::EditDate => optional_to_string(torrent.edit_date),
Self::Error => match torrent.error {
Some(error) => match error { Some(error) => match error {
ErrorType::Ok => String::from("Ok"), ErrorType::Ok => String::from("Ok"),
ErrorType::LocalError => String::from("LocalError"), ErrorType::LocalError => String::from("LocalError"),
@ -83,8 +128,8 @@ impl Wrapper for TorrentGetField {
}, },
None => String::from("N/A"), None => String::from("N/A"),
}, },
TorrentGetField::ErrorString => optional_to_string(torrent.error_string), Self::ErrorString => optional_to_string(torrent.error_string),
TorrentGetField::Eta => match torrent.eta { Self::Eta => match torrent.eta {
Some(eta) => match eta { Some(eta) => match eta {
-1 => "".into(), -1 => "".into(),
-2 => "?".into(), -2 => "?".into(),
@ -92,56 +137,71 @@ impl Wrapper for TorrentGetField {
}, },
None => String::from(""), None => String::from(""),
}, },
TorrentGetField::FileStats => match torrent.file_stats { Self::EtaIdle => todo!(),
Some(file_stats) => file_stats.iter().map(|x| x.priority.to_string()).collect(), Self::FileCount => todo!(),
Self::FileStats => match torrent.file_stats {
Some(file_stats) => file_stats
.iter()
.map(|x| format!("{:?}", x.priority))
.collect(),
None => String::from("N/A"), None => String::from("N/A"),
}, },
TorrentGetField::Files => match torrent.files { Self::Files => match torrent.files {
Some(files) => files.iter().map(|x| x.name.to_owned()).collect(), Some(files) => files.iter().map(|x| x.name.to_owned()).collect(),
None => String::from("N/A"), None => String::from("N/A"),
}, },
TorrentGetField::HashString => optional_to_string(torrent.hash_string), Self::Group => todo!(),
TorrentGetField::Id => optional_to_string(torrent.id), Self::HashString => optional_to_string(torrent.hash_string),
TorrentGetField::IsFinished => optional_to_string(torrent.is_finished), Self::HaveUnchecked => todo!(),
TorrentGetField::IsPrivate => optional_to_string(torrent.is_private), Self::HaveValid => todo!(),
TorrentGetField::IsStalled => optional_to_string(torrent.is_stalled), Self::HonorsSessionLimits => todo!(),
TorrentGetField::Labels => match torrent.labels { Self::Id => optional_to_string(torrent.id),
Self::IsFinished => optional_to_string(torrent.is_finished),
Self::IsPrivate => optional_to_string(torrent.is_private),
Self::IsStalled => optional_to_string(torrent.is_stalled),
Self::Labels => match torrent.labels {
Some(labels) => labels.join(" "), Some(labels) => labels.join(" "),
None => String::from("N/A"), None => String::from("N/A"),
}, },
TorrentGetField::LeftUntilDone => { Self::LeftUntilDone => FileSize(torrent.left_until_done.unwrap_or(0)).to_string(),
FileSize(torrent.left_until_done.unwrap_or(0)).to_string() Self::MagnetLink => todo!(),
} Self::ManualAnnounceTime => todo!(),
TorrentGetField::MetadataPercentComplete => { Self::MaxConnectedPeers => todo!(),
optional_to_string(torrent.metadata_percent_complete) Self::MetadataPercentComplete => optional_to_string(torrent.metadata_percent_complete),
} Self::Name => optional_to_string(torrent.name),
TorrentGetField::Name => optional_to_string(torrent.name), Self::PeerLimit => todo!(),
TorrentGetField::PeersConnected => optional_to_string(torrent.peers_connected), Self::Peers => todo!(),
TorrentGetField::PeersGettingFromUs => { Self::PeersConnected => optional_to_string(torrent.peers_connected),
optional_to_string(torrent.peers_getting_from_us) Self::PeersFrom => todo!(),
} Self::PeersGettingFromUs => optional_to_string(torrent.peers_getting_from_us),
TorrentGetField::PeersSendingToUs => optional_to_string(torrent.peers_sending_to_us), Self::PeersSendingToUs => optional_to_string(torrent.peers_sending_to_us),
TorrentGetField::PercentDone => match torrent.percent_done { Self::PercentComplete => todo!(),
Self::PercentDone => match torrent.percent_done {
Some(percent_done) => format!("{:.0}", percent_done * 100.0), Some(percent_done) => format!("{:.0}", percent_done * 100.0),
None => String::from("N/A"), None => String::from("N/A"),
}, },
TorrentGetField::Priorities => match torrent.priorities { Self::PieceCount => todo!(),
Some(priorities) => priorities.iter().map(|x| x.to_string()).collect(), Self::PieceSize => todo!(),
Self::Pieces => todo!(),
Self::PrimaryMimeType => todo!(),
Self::Priorities => match torrent.priorities {
Some(priorities) => priorities.iter().map(|x| format!("{:?}", x)).collect(),
None => String::from("N/A"), None => String::from("N/A"),
}, },
TorrentGetField::QueuePosition => String::from("N/A"), Self::QueuePosition => String::from("N/A"),
TorrentGetField::RateDownload => { Self::RateDownload => NetSpeed(torrent.rate_download.unwrap_or(0)).to_string(),
NetSpeed(torrent.rate_download.unwrap_or(0)).to_string() Self::RateUpload => NetSpeed(torrent.rate_upload.unwrap_or(0)).to_string(),
} Self::RecheckProgress => optional_to_string(torrent.recheck_progress),
TorrentGetField::RateUpload => NetSpeed(torrent.rate_upload.unwrap_or(0)).to_string(), Self::SecondsDownloading => todo!(),
TorrentGetField::RecheckProgress => optional_to_string(torrent.recheck_progress), Self::SecondsSeeding => optional_to_string(torrent.seconds_seeding),
TorrentGetField::SecondsSeeding => optional_to_string(torrent.seconds_seeding), Self::SeedIdleLimit => todo!(),
TorrentGetField::SeedRatioLimit => optional_to_string(torrent.seed_ratio_limit), Self::SeedIdleMode => todo!(),
TorrentGetField::SeedRatioMode => String::from("N/A"), Self::SeedRatioLimit => optional_to_string(torrent.seed_ratio_limit),
TorrentGetField::SizeWhenDone => { Self::SeedRatioMode => String::from("N/A"),
FileSize(torrent.size_when_done.unwrap_or(0)).to_string() Self::SequentialDownload => todo!(),
} Self::SizeWhenDone => FileSize(torrent.size_when_done.unwrap_or(0)).to_string(),
TorrentGetField::Status => match torrent.status { Self::StartDate => todo!(),
Self::Status => match torrent.status {
Some(status) => match status { Some(status) => match status {
TorrentStatus::Stopped => String::from("Stopped"), TorrentStatus::Stopped => String::from("Stopped"),
TorrentStatus::Seeding => String::from("Seeding"), TorrentStatus::Seeding => String::from("Seeding"),
@ -153,71 +213,109 @@ impl Wrapper for TorrentGetField {
}, },
None => String::from("N/A"), None => String::from("N/A"),
}, },
TorrentGetField::TorrentFile => optional_to_string(torrent.torrent_file), Self::TorrentFile => optional_to_string(torrent.torrent_file),
TorrentGetField::TotalSize => FileSize(torrent.total_size.unwrap_or(0)).to_string(), Self::TotalSize => FileSize(torrent.total_size.unwrap_or(0)).to_string(),
TorrentGetField::Trackers => match torrent.trackers { Self::TrackerList => todo!(),
Self::TrackerStats => todo!(),
Self::Trackers => match torrent.trackers {
Some(trackers) => trackers.iter().map(|x| x.announce.to_string()).collect(), Some(trackers) => trackers.iter().map(|x| x.announce.to_string()).collect(),
None => String::from("N/A"), None => String::from("N/A"),
}, },
TorrentGetField::UploadRatio => match torrent.upload_ratio { Self::UploadLimit => todo!(),
Self::UploadLimited => todo!(),
Self::UploadRatio => match torrent.upload_ratio {
Some(upload_ratio) => format!("{:.2}", upload_ratio), Some(upload_ratio) => format!("{:.2}", upload_ratio),
None => String::from("N/A"), None => String::from("N/A"),
}, },
TorrentGetField::UploadedEver => { Self::UploadedEver => FileSize(torrent.uploaded_ever.unwrap_or(0)).to_string(),
FileSize(torrent.uploaded_ever.unwrap_or(0)).to_string() Self::Wanted => match torrent.wanted {
}
TorrentGetField::Wanted => match torrent.wanted {
Some(wanted) => wanted.iter().map(|x| x.to_string()).collect(), Some(wanted) => wanted.iter().map(|x| x.to_string()).collect(),
None => String::from("N/A"), None => String::from("N/A"),
}, },
TorrentGetField::WebseedsSendingToUs => String::from("N/A"), Self::Webseeds => todo!(),
TorrentGetField::FileCount => unimplemented!(), Self::WebseedsSendingToUs => String::from("N/A"),
} }
} }
fn width(&self) -> u16 { fn width(&self) -> u16 {
match self { match self {
TorrentGetField::ActivityDate => 10, Self::ActivityDate => 10,
TorrentGetField::AddedDate => 10, Self::AddedDate => 10,
TorrentGetField::DoneDate => 10, Self::Availability => todo!(),
TorrentGetField::DownloadDir => 30, Self::BandwidthPriority => todo!(),
TorrentGetField::EditDate => 10, Self::Comment => todo!(),
TorrentGetField::Error => 10, Self::CorruptEver => todo!(),
TorrentGetField::ErrorString => 10, Self::Creator => todo!(),
TorrentGetField::Eta => 10, Self::DateCreated => todo!(),
TorrentGetField::FileStats => 10, Self::DesiredAvailable => todo!(),
TorrentGetField::Files => 10, Self::DoneDate => 10,
TorrentGetField::HashString => 10, Self::DownloadDir => 30,
TorrentGetField::Id => 10, Self::DownloadLimit => todo!(),
TorrentGetField::IsFinished => 10, Self::DownloadLimited => todo!(),
TorrentGetField::IsPrivate => 10, Self::DownloadedEver => todo!(),
TorrentGetField::IsStalled => 10, Self::EditDate => 10,
TorrentGetField::Labels => 10, Self::Error => 10,
TorrentGetField::LeftUntilDone => 10, Self::ErrorString => 10,
TorrentGetField::MetadataPercentComplete => 10, Self::Eta => 10,
TorrentGetField::Name => 70, Self::EtaIdle => todo!(),
TorrentGetField::PeersConnected => 10, Self::FileCount => todo!(),
TorrentGetField::PeersGettingFromUs => 10, Self::FileStats => 10,
TorrentGetField::PeersSendingToUs => 10, Self::Files => 10,
TorrentGetField::PercentDone => 10, Self::Group => todo!(),
TorrentGetField::Priorities => 10, Self::HashString => 10,
TorrentGetField::QueuePosition => 10, Self::HaveUnchecked => todo!(),
TorrentGetField::RateDownload => 10, Self::HaveValid => todo!(),
TorrentGetField::RateUpload => 10, Self::HonorsSessionLimits => todo!(),
TorrentGetField::RecheckProgress => 10, Self::Id => 10,
TorrentGetField::SecondsSeeding => 10, Self::IsFinished => 10,
TorrentGetField::SeedRatioLimit => 10, Self::IsPrivate => 10,
TorrentGetField::SeedRatioMode => 10, Self::IsStalled => 10,
TorrentGetField::SizeWhenDone => 10, Self::Labels => 10,
TorrentGetField::Status => 15, Self::LeftUntilDone => 10,
TorrentGetField::TorrentFile => 10, Self::MagnetLink => todo!(),
TorrentGetField::TotalSize => 10, Self::ManualAnnounceTime => todo!(),
TorrentGetField::Trackers => 10, Self::MaxConnectedPeers => todo!(),
TorrentGetField::UploadRatio => 10, Self::MetadataPercentComplete => 10,
TorrentGetField::UploadedEver => 10, Self::Name => 70,
TorrentGetField::Wanted => 10, Self::PeerLimit => todo!(),
TorrentGetField::WebseedsSendingToUs => 10, Self::Peers => todo!(),
TorrentGetField::FileCount => unimplemented!(), Self::PeersConnected => 10,
Self::PeersFrom => todo!(),
Self::PeersGettingFromUs => 10,
Self::PeersSendingToUs => 10,
Self::PercentComplete => todo!(),
Self::PercentDone => 10,
Self::PieceCount => todo!(),
Self::PieceSize => todo!(),
Self::Pieces => todo!(),
Self::PrimaryMimeType => todo!(),
Self::Priorities => 10,
Self::QueuePosition => 10,
Self::RateDownload => 10,
Self::RateUpload => 10,
Self::RecheckProgress => 10,
Self::SecondsDownloading => todo!(),
Self::SecondsSeeding => 10,
Self::SeedIdleLimit => todo!(),
Self::SeedIdleMode => todo!(),
Self::SeedRatioLimit => 10,
Self::SeedRatioMode => 10,
Self::SequentialDownload => todo!(),
Self::SizeWhenDone => 10,
Self::StartDate => todo!(),
Self::Status => 15,
Self::TorrentFile => 10,
Self::TotalSize => 10,
Self::TrackerList => todo!(),
Self::TrackerStats => todo!(),
Self::Trackers => 10,
Self::UploadLimit => todo!(),
Self::UploadLimited => todo!(),
Self::UploadRatio => 10,
Self::UploadedEver => 10,
Self::Wanted => 10,
Self::Webseeds => todo!(),
Self::WebseedsSendingToUs => 10,
} }
} }
} }

View File

@ -20,7 +20,7 @@ pub fn render(app: &mut App, frame: &mut Frame) {
// - https://docs.rs/ratatui/latest/ratatui/widgets/index.html // - https://docs.rs/ratatui/latest/ratatui/widgets/index.html
// - https://github.com/ratatui-org/ratatui/tree/master/examples // - https://github.com/ratatui-org/ratatui/tree/master/examples
let size = frame.size(); let size = frame.area();
let chunks = Layout::default() let chunks = Layout::default()
.direction(Direction::Vertical) .direction(Direction::Vertical)
.constraints([Constraint::Length(3), Constraint::Min(0)].as_ref()) .constraints([Constraint::Length(3), Constraint::Min(0)].as_ref())

View File

@ -53,6 +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(highlight_style) .row_highlight_style(highlight_style)
.column_spacing(1) .column_spacing(1)
} }