@setoelkahfi / sigit / commits / 172a214

fix(tui): show checkmark once model download completes

The in-chat model-switch line kept spinning at "switching model … (100%)" while the weights loaded into memory, which looked stuck. Once the download has fully landed on disk, swap the spinner for a green checkmark and switch the label to "model downloaded — loading into memory…". Also cap the displayed downloaded size at the expected size so it no longer reads e.g. "9.36 GB / 4.78 GB". Fixes #4 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

keypair34 committed Jun 24, 2026 at 15:45 UTC 172a214c7a7a5217509951c6af7f3b457581dec4
1 file changed +38 -17
src/chat.rs
+38 -17
index d2807d9..df35406 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -872,25 +872,46 @@ mod tui { Style::default().fg(Color::DarkGray), ))); } else if app.switching_model { - let frame_str = app.switching_frame(); - let progress_str = if let Some((downloaded, expected)) = app.download_progress { - if expected > 0 { - let pct = (downloaded as f64 / expected as f64 * 100.0).min(100.0) as u8; - let dl_str = format_size_human(downloaded); - let ex_str = format_size_human(expected); - format!(" — {dl_str} / {ex_str} ({pct}%)") - } else if downloaded > 0 { - format!(" — {} downloaded", format_size_human(downloaded)) + // Once the weights have fully landed on disk, swap the spinner for a + // checkmark so it's clear the download finished and we're now loading + // the model into memory (which can still take a while). + let download_complete = matches!( + app.download_progress, + Some((downloaded, expected)) if expected > 0 && downloaded >= expected + ); + + if download_complete { + let size_str = app + .download_progress + .map(|(_, expected)| format!(" ({})", format_size_human(expected))) + .unwrap_or_default(); + lines.push(Line::from(vec![ + Span::styled(" ✓ ", Style::default().fg(Color::Green)), + Span::styled( + format!("model downloaded{size_str} — loading into memory…"), + Style::default().fg(Color::DarkGray), + ), + ])); + } else { + let progress_str = if let Some((downloaded, expected)) = app.download_progress { + if expected > 0 { + let pct = (downloaded as f64 / expected as f64 * 100.0).min(100.0) as u8; + let dl_str = format_size_human(downloaded.min(expected)); + let ex_str = format_size_human(expected); + format!(" — {dl_str} / {ex_str} ({pct}%)") + } else if downloaded > 0 { + format!(" — {} downloaded", format_size_human(downloaded)) + } else { + String::new() + } } else { String::new() - } - } else { - String::new() - }; - lines.push(Line::from(Span::styled( - format!(" {frame_str} switching model{progress_str}…"), - Style::default().fg(Color::DarkGray), - ))); + }; + lines.push(Line::from(Span::styled( + format!(" {} switching model{progress_str}…", app.switching_frame()), + Style::default().fg(Color::DarkGray), + ))); + } } let total_lines = lines.len() as u16;