#484: Enable flips each selected clip on its own

With one enabled and one disabled clip selected, Clip > Enable (Shift+E) set every
selected clip to the same state: the first press enabled both, the next disabled both.
Premiere flips each clip separately (confirmed by the reporter in #484), so a mixed
selection swaps. Each clip in the selection (with its linked clips) now flips on its
own; a clip named twice in the parameters still flips once.

Test: enable_flips_each_selected_clip (fails before the fix: the mixed press left
both clips enabled).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Qq8BK1LmohzE1ga4NgAdWM
This commit is contained in:
liangforstudyandClaude Opus 5.5 committed 2026-10-10 09:23:38 +08:00
1 parent 7b6c134472
commit fcaa6bbdf4
2 files changed
+41 -3

No files matched your search

+7 -3
View File
@@ -1325,13 +1325,17 @@ fn build() -> Vec<CommandSpec> {
Ok(Value::Null)
}
),
// Each clip flips on its own, as in Premiere (#484): with one enabled and one disabled clip
// selected, Enable swaps them rather than first making both the same.
cmd!("clip.enable", "Enable", ["Clip"], Some("Shift+E"), r#"{"clips":[id]?}"#, has_selection, |s, p| {
let sel = with_links(s, &clips_p(s, p));
let mut sel = with_links(s, &clips_p(s, p));
// a clip named twice must still flip once
sel.sort();
sel.dedup();
s.edit_sequence("Enable", |q, _, _| {
let target = !sel.iter().all(|c| q.find_item(*c).is_some_and(|(_, i)| i.enabled));
for c in &sel {
if let Some((_, i)) = q.find_item_mut(*c) {
i.enabled = target;
i.enabled = !i.enabled;
}
}
Ok(())
+34
View File
@@ -641,3 +641,37 @@ fn dragging_an_effect_parameter_is_one_undo_step() {
s.undo();
assert_eq!(opacity(&s), start, "and then the whole first one");
}
/// #484: Enable flips each selected clip on its own, as in Premiere. With one enabled and one
/// disabled clip selected it swaps them, instead of first making both the same.
#[test]
fn enable_flips_each_selected_clip() {
let mut s = demo();
let enabled = |s: &Session, c: u64| s.active_sequence().unwrap().find_item(ClipId(c)).unwrap().1.enabled;
let partner = |s: &Session, c: u64| {
let q = s.active_sequence().unwrap();
let link = q.find_item(ClipId(c)).unwrap().1.link?;
q.all_tracks().flat_map(|t| t.items.iter()).find(|i| i.link == Some(link) && i.id != ClipId(c)).map(|i| i.id.0)
};
let (a, b) = (v1(&s)[0].0, v1(&s)[1].0);
s.execute("clip.enable", json!({"clips": [a]})).unwrap();
assert_eq!((enabled(&s, a), enabled(&s, b)), (false, true));
// mixed selection: each flips
s.execute("clip.enable", json!({"clips": [a, b]})).unwrap();
assert_eq!((enabled(&s, a), enabled(&s, b)), (true, false));
s.execute("clip.enable", json!({"clips": [a, b]})).unwrap();
assert_eq!((enabled(&s, a), enabled(&s, b)), (false, true));
// a clip named twice still flips once, and one press is one undo step
s.execute("clip.enable", json!({"clips": [a, a]})).unwrap();
assert!(enabled(&s, a));
s.undo();
assert_eq!((enabled(&s, a), enabled(&s, b)), (false, true));
// with linked selection on, a clip's linked audio flips with it
if let Some(au) = partner(&s, a) {
assert_eq!(enabled(&s, au), enabled(&s, a));
}
// a uniform selection still toggles as before
s.execute("clip.enable", json!({"clips": [b]})).unwrap();
s.execute("clip.enable", json!({"clips": [a, b]})).unwrap();
assert_eq!((enabled(&s, a), enabled(&s, b)), (true, true));
}