fix: Resolve UI reactivity issues by including name, status, and size in partial updates

This commit is contained in:
spinline
2026-01-30 18:54:54 +03:00
parent 203a436a04
commit 16fbf7306a
3 changed files with 24 additions and 3 deletions

View File

@@ -32,16 +32,27 @@ pub fn diff_torrents(old: &[Torrent], new: &[Torrent]) -> Vec<AppEvent> {
let mut update = TorrentUpdate { let mut update = TorrentUpdate {
hash: new_t.hash.clone(), hash: new_t.hash.clone(),
name: None,
size: None,
down_rate: None, down_rate: None,
up_rate: None, up_rate: None,
percent_complete: None, percent_complete: None,
completed: None, completed: None,
eta: None, eta: None,
status: None, status: None,
error_message: None,
}; };
let mut has_changes = false; let mut has_changes = false;
if old_t.name != new_t.name {
update.name = Some(new_t.name.clone());
has_changes = true;
}
if old_t.size != new_t.size {
update.size = Some(new_t.size);
has_changes = true;
}
if old_t.down_rate != new_t.down_rate { if old_t.down_rate != new_t.down_rate {
update.down_rate = Some(new_t.down_rate); update.down_rate = Some(new_t.down_rate);
has_changes = true; has_changes = true;
@@ -67,6 +78,10 @@ pub fn diff_torrents(old: &[Torrent], new: &[Torrent]) -> Vec<AppEvent> {
update.status = Some(new_t.status.clone()); update.status = Some(new_t.status.clone());
has_changes = true; has_changes = true;
} }
if old_t.error_message != new_t.error_message {
update.error_message = Some(new_t.error_message.clone());
has_changes = true;
}
if has_changes { if has_changes {
events.push(AppEvent::Update(update)); events.push(AppEvent::Update(update));

View File

@@ -128,12 +128,15 @@ pub fn App() -> impl IntoView {
AppEvent::Update(diff) => { AppEvent::Update(diff) => {
set_torrents.update(|list| { set_torrents.update(|list| {
if let Some(target) = list.iter_mut().find(|t| t.hash == diff.hash) { if let Some(target) = list.iter_mut().find(|t| t.hash == diff.hash) {
if let Some(v) = diff.name { target.name = v; }
if let Some(v) = diff.size { target.size = v; }
if let Some(v) = diff.down_rate { target.down_rate = v; } if let Some(v) = diff.down_rate { target.down_rate = v; }
if let Some(v) = diff.up_rate { target.up_rate = v; } if let Some(v) = diff.up_rate { target.up_rate = v; }
if let Some(v) = diff.percent_complete { target.percent_complete = v; } if let Some(v) = diff.percent_complete { target.percent_complete = v; }
if let Some(v) = diff.completed { target.completed = v; } if let Some(v) = diff.completed { target.completed = v; }
if let Some(v) = diff.eta { target.eta = v; } if let Some(v) = diff.eta { target.eta = v; }
if let Some(v) = diff.status { target.status = v; } if let Some(v) = diff.status { target.status = v; }
if let Some(v) = diff.error_message { target.error_message = v; }
} }
}); });
} }
@@ -435,8 +438,8 @@ pub fn App() -> impl IntoView {
</thead> </thead>
<tbody class={format!("divide-y {}", border)}> <tbody class={format!("divide-y {}", border)}>
<For <For
each=move || processed_torrents.get() each=move || processed_torrents.get()
key=|t| format!("{}-{}-{}-{}-{}-{}", t.hash, t.down_rate, t.up_rate, t.percent_complete, t.eta, t.error_message) key=|t| format!("{}-{}-{:?}-{}-{}-{}-{}", t.hash, t.name, t.status, t.down_rate, t.up_rate, t.percent_complete, t.error_message)
children=move |torrent| { children=move |torrent| {
let status_color = match torrent.status { let status_color = match torrent.status {
TorrentStatus::Downloading => "text-blue-500 bg-blue-500/10 border-blue-500/20", TorrentStatus::Downloading => "text-blue-500 bg-blue-500/10 border-blue-500/20",
@@ -515,7 +518,7 @@ pub fn App() -> impl IntoView {
<div class="md:hidden space-y-4"> <div class="md:hidden space-y-4">
<For <For
each=move || processed_torrents.get() each=move || processed_torrents.get()
key=|t| format!("{}-{}-{}-{}-{}-{}", t.hash, t.down_rate, t.up_rate, t.percent_complete, t.eta, t.error_message) key=|t| format!("{}-{}-{:?}-{}-{}-{}-{}", t.hash, t.name, t.status, t.down_rate, t.up_rate, t.percent_complete, t.error_message)
children=move |torrent| { children=move |torrent| {
let status_color = match torrent.status { let status_color = match torrent.status {
TorrentStatus::Downloading => "text-blue-500", TorrentStatus::Downloading => "text-blue-500",

View File

@@ -35,12 +35,15 @@ pub enum AppEvent {
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
pub struct TorrentUpdate { pub struct TorrentUpdate {
pub hash: String, pub hash: String,
pub name: Option<String>,
pub size: Option<i64>,
pub down_rate: Option<i64>, pub down_rate: Option<i64>,
pub up_rate: Option<i64>, pub up_rate: Option<i64>,
pub percent_complete: Option<f64>, pub percent_complete: Option<f64>,
pub completed: Option<i64>, pub completed: Option<i64>,
pub eta: Option<i64>, pub eta: Option<i64>,
pub status: Option<TorrentStatus>, pub status: Option<TorrentStatus>,
pub error_message: Option<String>,
} }
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]