mirror of
https://github.com/storytold/soundcraft.git
synced 2026-10-24 10:36:46 -06:00
Keep merging fader gestures once the undo history is full
Found while testing crates/engine/src/lib.rs:368-381 (Engine::execute_merged, with push_undo at 280-291) Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com> Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Haiku 5.5
parent
f3a19480d8
commit
055ddbee7a
@@ -369,7 +369,15 @@ impl Engine {
|
||||
let key = self.merge_hold.clone().unwrap_or_else(|| key.to_string());
|
||||
let continuing = self.merge_key.as_ref() == Some(&key);
|
||||
let before_len = self.undo.len();
|
||||
let r = self.execute(id, params)?;
|
||||
// The step pushed for a continuing tick is dropped again below, so it must not trim the
|
||||
// oldest entry first when the history is full.
|
||||
let limit = self.history_limit;
|
||||
if continuing && before_len > 0 {
|
||||
self.history_limit = limit.max(before_len.saturating_add(1));
|
||||
}
|
||||
let r = self.execute(id, params);
|
||||
self.history_limit = limit;
|
||||
let r = r?;
|
||||
if continuing && self.undo.len() == before_len + 1 && before_len > 0 {
|
||||
// Drop the step just pushed; the earlier one still holds the pre-gesture document.
|
||||
self.undo.pop();
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
use serde_json::json;
|
||||
use soundcraft_engine::Engine;
|
||||
use soundcraft_model::{ChannelFormat, TrackKind};
|
||||
|
||||
fn engine_with_full_history(limit: usize) -> (Engine, u64) {
|
||||
let mut e = Engine::default();
|
||||
let t = e.session_mut().add_track(TrackKind::Audio, ChannelFormat::Mono, None).0;
|
||||
e.history_limit = limit;
|
||||
for i in 0..limit + 1 {
|
||||
e.execute("mix.pan", &json!({"track": t, "pan": 0.1 * (i as f64 + 1.0)})).unwrap();
|
||||
}
|
||||
assert_eq!(e.undo_history().len(), limit);
|
||||
(e, t)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_fader_gesture_is_one_undo_step_when_the_history_is_full() {
|
||||
let (mut e, t) = engine_with_full_history(3);
|
||||
for db in [-1.0, -2.0, -3.0, -4.0, -5.0] {
|
||||
e.execute_merged("mix.volume", &json!({"track": t, "db": db}), "fader").unwrap();
|
||||
}
|
||||
e.end_merge();
|
||||
let volume = |e: &Engine| e.session().tracks.iter().find(|x| x.id.0 == t).map(|x| x.mixer.volume_db);
|
||||
assert_eq!(volume(&e), Some(-5.0));
|
||||
// The gesture costs one step; it must not push further real edits out of the history.
|
||||
assert_eq!(e.undo_history().len(), 3, "history: {:?}", e.undo_history());
|
||||
assert_eq!(e.undo_history().iter().filter(|l| l.as_str() == "Set Volume").count(), 1, "history: {:?}", e.undo_history());
|
||||
assert!(e.undo());
|
||||
assert_eq!(volume(&e), Some(0.0), "one undo should undo the whole fader gesture; history: {:?}", e.undo_history());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_zero_history_limit_keeps_no_undo_entry_for_a_gesture() {
|
||||
let mut e = Engine::default();
|
||||
let t = e.session_mut().add_track(TrackKind::Audio, ChannelFormat::Mono, None).0;
|
||||
e.history_limit = 0;
|
||||
for db in [-1.0, -2.0, -3.0] {
|
||||
e.execute_merged("mix.volume", &json!({"track": t, "db": db}), "fader").unwrap();
|
||||
}
|
||||
e.end_merge();
|
||||
assert!(e.undo_history().is_empty(), "history: {:?}", e.undo_history());
|
||||
}
|
||||
Reference in New Issue
Block a user