diff --git a/src/cast.rs b/src/cast.rs index 41ab49f..06d5064 100644 --- a/src/cast.rs +++ b/src/cast.rs @@ -340,37 +340,15 @@ pub async fn play_interactive( Ok(()) } -async fn seek_to( +async fn send_data( handle: &Handle, channel: ChannelId, - events: &[(f64, String, String)], - target: Duration, - next_idx: &mut usize, - current_time: &mut Duration, + data: &[u8], ) -> Result<()> { handle - .data(channel, CryptoVec::from_slice(b"\x1b[2J\x1b[H")) + .data(channel, CryptoVec::from_slice(data)) .await - .map_err(|_| anyhow::anyhow!("send error"))?; - - for (i, (time, code, data)) in events.iter().enumerate() { - if code != "o" { - continue; - } - if Duration::from_secs_f64(*time) > target { - *next_idx = i; - *current_time = target; - return Ok(()); - } - handle - .data(channel, CryptoVec::from_slice(data.as_bytes())) - .await - .map_err(|_| anyhow::anyhow!("send error"))?; - } - - *next_idx = events.len(); - *current_time = target; - Ok(()) + .map_err(|_| anyhow::anyhow!("send error")) } async fn restore_screen( @@ -379,24 +357,40 @@ async fn restore_screen( events: &[(f64, String, String)], up_to_idx: usize, ) -> Result<()> { - handle - .data(channel, CryptoVec::from_slice(b"\x1b[2J\x1b[H")) - .await - .map_err(|_| anyhow::anyhow!("send error"))?; + send_data(handle, channel, b"\x1b[2J\x1b[H").await?; for (_, code, data) in &events[..up_to_idx] { if code != "o" { continue; } - handle - .data(channel, CryptoVec::from_slice(data.as_bytes())) - .await - .map_err(|_| anyhow::anyhow!("send error"))?; + send_data(handle, channel, data.as_bytes()).await?; } Ok(()) } +async fn seek_to( + handle: &Handle, + channel: ChannelId, + events: &[(f64, String, String)], + target: Duration, + next_idx: &mut usize, + current_time: &mut Duration, +) -> Result<()> { + let idx = events + .iter() + .enumerate() + .filter(|(_, (_, code, _))| code == "o") + .find(|(_, (time, _, _))| Duration::from_secs_f64(*time) > target) + .map(|(i, _)| i) + .unwrap_or(events.len()); + + restore_screen(handle, channel, events, idx).await?; + *next_idx = idx; + *current_time = target; + Ok(()) +} + fn render_overlay( term_handle: &mut TerminalHandle, cols: u16, diff --git a/src/main.rs b/src/main.rs index 859cbe7..8d94b0b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -98,6 +98,22 @@ struct TailpipeHandler { pty_size: Option<(u16, u16)>, } +async fn play_optional_cast( + label: &str, + path: Option<&str>, + channel: ChannelId, + handle: &russh::server::Handle, + user: &str, +) { + let Some(path) = path else { return }; + if path == "none" { + return; + } + if let Err(e) = cast::play(&PathBuf::from(path), channel, handle.clone()).await { + log::error!("{label} playback error for {user}: {e:#}"); + } +} + impl server::Handler for TailpipeHandler { type Error = anyhow::Error; @@ -186,19 +202,14 @@ impl server::Handler for TailpipeHandler { tokio::spawn(async move { if let Some(user_config) = user_config { // Play header cast (user override or server default) - let header = user_config - .header - .as_deref() - .or(server_config_header.as_deref()); - if let Some(path) = header { - if path != "none" { - if let Err(e) = - cast::play(&PathBuf::from(path), channel, handle.clone()).await - { - log::error!("header playback error for {user}: {e:#}"); - } - } - } + play_optional_cast( + "header", + user_config.header.as_deref().or(server_config_header.as_deref()), + channel, + &handle, + &user, + ) + .await; // Play the main cast file (interactive) let castfile = PathBuf::from(&user_config.castfile); @@ -210,19 +221,14 @@ impl server::Handler for TailpipeHandler { } // Play footer cast (user override or server default) - let footer = user_config - .footer - .as_deref() - .or(server_config_footer.as_deref()); - if let Some(path) = footer { - if path != "none" { - if let Err(e) = - cast::play(&PathBuf::from(path), channel, handle.clone()).await - { - log::error!("footer playback error for {user}: {e:#}"); - } - } - } + play_optional_cast( + "footer", + user_config.footer.as_deref().or(server_config_footer.as_deref()), + channel, + &handle, + &user, + ) + .await; } let _ = handle.eof(channel).await;