fix: revert draw gating; replace frame-count scroll with wall-clock timer

- Revert src/main.rs to draw-at-top-of-loop (original structure) so
  auto-scrolling is no longer coupled to event rate. Lock is released
  before blocking on recv() so the network task is never starved.

- Replace ticks_until_scroll counter in on_ui_scroll_tick() with an
  Instant + Duration (default 100ms). Scroll now advances at a fixed
  wall-clock rate (10 chars/sec) regardless of draw rate or tick rate,
  which is the correct long-term fix for the animation regression.

- Update tests: assert scroll_interval == 100ms in default/new tests;
  rewrite test_on_ui_scroll_tick to cover zero-interval (always fires)
  and long-interval (suppressed) cases.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C3FpbniZme9mJqgFkMVowz
This commit is contained in:
Jonathan McCumberandClaude Sonnet 4.6 committed 2026-06-30 20:05:00 -05:00
1 parent a72b2991fd
commit 6f697f64f4
3 files changed
+25 -21

No files matched your search

+12 -10
View File
@@ -5,6 +5,7 @@ mod tests {
use reqwest::header::{HeaderMap, HeaderName, HeaderValue};
use serde_json::Value;
use serial_test::serial;
use std::time::{Duration, Instant};
use tokio::sync::mpsc;
use crate::app::{App, AppConfig, Data, ServarrConfig, interpolate_env_vars};
@@ -80,7 +81,7 @@ mod tests {
assert_eq!(app.server_tabs.index, 0);
assert_eq!(app.server_tabs.tabs, expected_tab_routes);
assert_eq!(app.tick_until_poll, 400);
assert_eq!(app.ticks_until_scroll, 64);
assert_eq!(app.scroll_interval, Duration::from_millis(100));
assert_eq!(app.tick_count, 0);
assert_eq!(app.ui_scroll_tick_count, 0);
assert!(!app.is_loading);
@@ -101,7 +102,7 @@ mod tests {
assert_eq!(app.error, HorizontallyScrollableText::default());
assert_eq!(app.server_tabs.index, 0);
assert_eq!(app.tick_until_poll, 400);
assert_eq!(app.ticks_until_scroll, 64);
assert_eq!(app.scroll_interval, Duration::from_millis(100));
assert_eq!(app.tick_count, 0);
assert!(!app.is_loading);
assert!(!app.is_routing);
@@ -247,22 +248,23 @@ mod tests {
#[test]
fn test_on_ui_scroll_tick() {
let mut app = App {
ticks_until_scroll: 1,
scroll_interval: Duration::ZERO,
..App::default()
};
// Zero interval: elapsed() >= scroll_interval is always true, so every
// call should signal "scroll now" (ui_scroll_tick_count == 0)
app.on_ui_scroll_tick();
assert_eq!(app.ui_scroll_tick_count, 0);
assert_eq!(app.tick_count, 0);
app.on_ui_scroll_tick();
assert_eq!(app.ui_scroll_tick_count, 0);
// Long interval with a fresh timestamp: should signal "not yet" (count == 1)
app.scroll_interval = Duration::from_secs(60);
app.last_scroll = Instant::now();
app.on_ui_scroll_tick();
assert_eq!(app.ui_scroll_tick_count, 1);
assert_eq!(app.tick_count, 0);
app.on_ui_scroll_tick();
assert_eq!(app.ui_scroll_tick_count, 0);
assert_eq!(app.tick_count, 0);
}
#[tokio::test]