feat: implement audio seeking with arrow keys via ffplay restart
Seek now works by restarting ffplay with -ss offset instead of the broken player.seek() stub. MoveLeft/MoveRight added as aliases for SeekBackward/SeekForward to fix HashMap non-deterministic iteration order causing Left arrow to resolve to MoveLeft instead of SeekBackward. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -74,10 +74,10 @@ pub async fn handle_message_selection<T: TdClientTrait>(app: &mut App<T>, _key:
|
||||
Some(crate::config::Command::TogglePlayback) => {
|
||||
handle_toggle_voice_playback(app).await;
|
||||
}
|
||||
Some(crate::config::Command::SeekForward) => {
|
||||
Some(crate::config::Command::SeekForward | crate::config::Command::MoveRight) => {
|
||||
handle_voice_seek(app, 5.0);
|
||||
}
|
||||
Some(crate::config::Command::SeekBackward) => {
|
||||
Some(crate::config::Command::SeekBackward | crate::config::Command::MoveLeft) => {
|
||||
handle_voice_seek(app, -5.0);
|
||||
}
|
||||
Some(crate::config::Command::ReactMessage) => {
|
||||
@@ -540,7 +540,6 @@ async fn handle_toggle_voice_playback<T: TdClientTrait>(app: &mut App<T>) {
|
||||
/// Seek голосового сообщения на delta секунд
|
||||
fn handle_voice_seek<T: TdClientTrait>(app: &mut App<T>, delta: f32) {
|
||||
use crate::tdlib::PlaybackStatus;
|
||||
use std::time::Duration;
|
||||
|
||||
let Some(ref mut playback) = app.playback_state else {
|
||||
return;
|
||||
@@ -549,14 +548,27 @@ fn handle_voice_seek<T: TdClientTrait>(app: &mut App<T>, delta: f32) {
|
||||
return;
|
||||
};
|
||||
|
||||
if matches!(playback.status, PlaybackStatus::Playing | PlaybackStatus::Paused) {
|
||||
let was_playing = matches!(playback.status, PlaybackStatus::Playing);
|
||||
let was_paused = matches!(playback.status, PlaybackStatus::Paused);
|
||||
|
||||
if was_playing || was_paused {
|
||||
let new_position = (playback.position + delta).clamp(0.0, playback.duration);
|
||||
if player.seek(Duration::from_secs_f32(new_position)).is_ok() {
|
||||
|
||||
if was_playing {
|
||||
// Перезапускаем ffplay с новой позиции
|
||||
if player.resume_from(new_position).is_ok() {
|
||||
playback.position = new_position;
|
||||
app.last_playback_tick = Some(std::time::Instant::now());
|
||||
}
|
||||
} else {
|
||||
// На паузе — только двигаем позицию, воспроизведение начнётся при resume
|
||||
player.stop();
|
||||
playback.position = new_position;
|
||||
let arrow = if delta > 0.0 { "→" } else { "←" };
|
||||
app.status_message = Some(format!("{} {:.0}s", arrow, new_position));
|
||||
app.needs_redraw = true;
|
||||
}
|
||||
|
||||
let arrow = if delta > 0.0 { "→" } else { "←" };
|
||||
app.status_message = Some(format!("{} {:.0}s", arrow, new_position));
|
||||
app.needs_redraw = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user