Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
40 lines
2.0 KiB
JavaScript
40 lines
2.0 KiB
JavaScript
// Which clips are selected: a set, one of them in focus (what the inspector shows), and an anchor for shift-ranges.
|
|
// Click picks one, cmd/ctrl toggles, shift extends from the anchor. Pure; the project says which scene is focused.
|
|
export function createSelection({ project }) {
|
|
let ids = [];
|
|
let anchor = null;
|
|
const heard = new Set();
|
|
const say = () => heard.forEach((fn) => { try { fn(); } catch { /* one listener must not stop the rest */ } });
|
|
|
|
const live = () => new Set(project.scenes.map((s) => s.id));
|
|
const heal = () => { const have = live(); ids = ids.filter((id) => have.has(id)); if (anchor && !have.has(anchor)) anchor = project.selectedId; };
|
|
|
|
return {
|
|
get ids() { heal(); return ids.length ? [...ids] : (project.selectedId ? [project.selectedId] : []); },
|
|
has(id) { return this.ids.includes(id); },
|
|
get focus() { return project.selectedId; },
|
|
on: (fn) => { heard.add(fn); return () => heard.delete(fn); },
|
|
/** `order`: scene ids as the timeline shows them, which is what a range means. */
|
|
pick(id, { additive = false, range = false } = {}, order = project.scenes.map((s) => s.id)) {
|
|
if (!project.scenes.some((s) => s.id === id)) return;
|
|
const was = this.ids;
|
|
if (range && anchor) {
|
|
const a = order.indexOf(anchor), b = order.indexOf(id);
|
|
ids = a < 0 || b < 0 ? [id] : order.slice(Math.min(a, b), Math.max(a, b) + 1);
|
|
} else if (additive) {
|
|
ids = was.includes(id) ? was.filter((x) => x !== id) : [...was, id];
|
|
anchor = ids.includes(id) ? id : ids[ids.length - 1] || null; // after un-picking, the last one still picked
|
|
} else {
|
|
ids = [id];
|
|
anchor = id;
|
|
}
|
|
const focus = ids.includes(id) ? id : ids[ids.length - 1] || null;
|
|
if (focus) project.select(focus);
|
|
say();
|
|
},
|
|
clear() { ids = []; anchor = null; say(); },
|
|
/** The project was replaced or restructured: drop what no longer exists. */
|
|
heal() { heal(); say(); },
|
|
};
|
|
}
|