diff --git a/frontend/src/components/torrent/details.rs b/frontend/src/components/torrent/details.rs index 44ca654..92cdda7 100644 --- a/frontend/src/components/torrent/details.rs +++ b/frontend/src/components/torrent/details.rs @@ -165,10 +165,19 @@ pub fn TorrentDetailsSheet() -> impl IntoView { -
- -

"İzleyici listesi yakında eklenecek"

-
+ {move || match selected_torrent.get() { + Some(t) => leptos::either::Either::Left(view! { +
+ +
+ }), + None => leptos::either::Either::Right(view! { +
+ +

"İzleyici yükleniyor..."

+
+ }), + }}
diff --git a/frontend/src/components/torrent/mod.rs b/frontend/src/components/torrent/mod.rs index cb09710..19b39f9 100644 --- a/frontend/src/components/torrent/mod.rs +++ b/frontend/src/components/torrent/mod.rs @@ -2,3 +2,4 @@ pub mod table; pub mod add_torrent; pub mod details; pub mod files; +pub mod trackers; diff --git a/frontend/src/components/torrent/trackers.rs b/frontend/src/components/torrent/trackers.rs new file mode 100644 index 0000000..54db592 --- /dev/null +++ b/frontend/src/components/torrent/trackers.rs @@ -0,0 +1,121 @@ +use leptos::prelude::*; +use crate::components::ui::table::*; +use crate::components::ui::shimmer::*; +use shared::TorrentTracker; + +#[component] +pub fn TorrentTrackersTab(hash: String) -> impl IntoView { + let hash_clone = hash.clone(); + + let trackers_resource = Resource::new( + move || hash_clone.clone(), + |h| async move { shared::server_fns::torrent::get_trackers(h).await.unwrap_or_default() } + ); + + view! { + }> + {move || { + let trackers = trackers_resource.get().unwrap_or_default(); + + if trackers.is_empty() { + return view! { +
+ +

"Bu torrent için izleyici bulunamadı."

+
+ }.into_any(); + } + + view! { +
+ + + + + "İsim" + "Tür" + "Etkin" + "Grup" + "Ortaklar" + "Eşler" + "İndirilen" + "Son Güncelleme" + "Sıklık" + "Özel" + + + + = 0 { + format_duration_short(diff) + } else { + "N/A".to_string() + }; + + let url_clone = t.url.clone(); + view! { + + + {t.url.clone()} + + {t_type} + {is_enabled} + {t.group} + {t.seeders} + {t.peers} + {t.downloaded} + {last_update_str} + {format_duration_short(t.interval)} + "bilinmiyor" // Özel flag isn't cleanly via XMLRPC per tracker usually + + } + } + /> + +
+
+
+ }.into_any() + }} +
+ } +} + +#[component] +fn TrackersFallback() -> impl IntoView { + view! { + +
+
+
+
+
+ } +} + +fn format_duration_short(seconds: i64) -> String { + if seconds <= 0 { return "0sn".to_string(); } + let days = seconds / 86400; + let hours = (seconds % 86400) / 3600; + let minutes = (seconds % 3600) / 60; + let secs = seconds % 60; + + if days > 0 { format!("{}g {}s", days, hours) } + else if hours > 0 { format!("{}s {}dk", hours, minutes) } + else if minutes > 0 { format!("{}dk {}sn", minutes, secs) } + else { format!("{}sn", secs) } +} diff --git a/shared/src/lib.rs b/shared/src/lib.rs index 89fb188..fc36803 100644 --- a/shared/src/lib.rs +++ b/shared/src/lib.rs @@ -126,6 +126,13 @@ pub struct TorrentTracker { pub url: String, pub status: String, pub message: String, + pub is_enabled: bool, + pub group: i64, + pub seeders: i64, + pub peers: i64, + pub downloaded: i64, + pub last_updated: i64, + pub interval: i64, } #[derive(Debug, Serialize, Deserialize, Clone, ToSchema)] diff --git a/shared/src/server_fns/torrent.rs b/shared/src/server_fns/torrent.rs index 3edb8d3..1c6e754 100644 --- a/shared/src/server_fns/torrent.rs +++ b/shared/src/server_fns/torrent.rs @@ -193,7 +193,13 @@ pub async fn get_trackers(hash: String) -> Result, ServerFnE RpcParam::from(hash.as_str()), RpcParam::from(""), RpcParam::from("t.url="), + RpcParam::from("t.is_enabled="), + RpcParam::from("t.group="), + RpcParam::from("t.scrape_complete="), + RpcParam::from("t.scrape_incomplete="), + RpcParam::from("t.scrape_downloaded="), RpcParam::from("t.activity_date_last="), + RpcParam::from("t.normal_interval="), RpcParam::from("t.message="), ]; @@ -209,8 +215,15 @@ pub async fn get_trackers(hash: String) -> Result, ServerFnE .into_iter() .map(|row| TorrentTracker { url: row.get(0).cloned().unwrap_or_default(), - status: "Unknown".to_string(), - message: row.get(2).cloned().unwrap_or_default(), + is_enabled: row.get(1).and_then(|s| s.parse::().ok()).unwrap_or(0) != 0, + group: row.get(2).and_then(|s| s.parse().ok()).unwrap_or(0), + seeders: row.get(3).and_then(|s| s.parse().ok()).unwrap_or(0), + peers: row.get(4).and_then(|s| s.parse().ok()).unwrap_or(0), + downloaded: row.get(5).and_then(|s| s.parse().ok()).unwrap_or(0), + last_updated: row.get(6).and_then(|s| s.parse().ok()).unwrap_or(0), + interval: row.get(7).and_then(|s| s.parse().ok()).unwrap_or(0), + status: "Unknown".to_string(), // Can derive from message or activity later, or keep unknown + message: row.get(8).cloned().unwrap_or_default(), }) .collect()) }