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"
edition = "2021"
[dependencies]
crossterm = "0.27"
ratatui = { version = "0.26" }
transmission-rpc = "0.4"
url = "2.4"
crossterm = "0.29"
ratatui = { version = "0.29" }
transmission-rpc = "0.5"
url = "2.5"
anyhow = "1.0"
tokio = { version = "1", features = ["full"] }
tracing = "0.1"

View File

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