Skip to content

Commit 2382b8e

Browse files
committed
fix(mcp): refuse a camera crop and pan that place the framing in two spots
Part of #1180
1 parent 9226140 commit 2382b8e

2 files changed

Lines changed: 27 additions & 0 deletions

File tree

‎electron/ai-edition/editor-settings-tool.test.ts‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,19 @@ describe("setEditorSettings", () => {
184184
expect(set(document, { webcamCropRegion: { x: 0, y: 0, width: 0.5, height: 0.6 } }).ok).toBe(
185185
false,
186186
);
187+
// A rect and a pan that disagree are refused; at full size any pan agrees.
188+
expect(
189+
set(framed, {
190+
webcamCropRegion: { x: 0, y: 0, width: 0.5, height: 0.5 },
191+
webcamCropPan: { x: 1, y: 0 },
192+
}).ok,
193+
).toBe(false);
194+
expect(
195+
set(framed, {
196+
webcamCropRegion: { x: 0, y: 0, width: 1, height: 1 },
197+
webcamCropPan: { x: 1, y: 0 },
198+
}).ok,
199+
).toBe(true);
187200
});
188201

189202
it("says which of the settings it wrote change nothing in the current state", () => {

‎electron/ai-edition/editor-settings-tool.ts‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,18 @@ function editorPatch(document: AxcutDocument, args: SetEditorSettingsArgs): Edit
388388
return patch;
389389
}
390390

391+
/** A rect and a pan sent together that place the window in two different spots. At full size
392+
* there is no room to place it in, so any pan agrees with the rect there. */
393+
function cropFramingConflict(args: SetEditorSettingsArgs): string | null {
394+
const { webcamCropRegion: region, webcamCropPan: pan } = args;
395+
if (!region || !pan) return null;
396+
const agrees = (offset: number, size: number, share: number) =>
397+
Math.abs(offset - share * (1 - size)) < 1e-6;
398+
return agrees(region.x, region.width, pan.x) && agrees(region.y, region.height, pan.y)
399+
? null
400+
: "webcamCropRegion and webcamCropPan place the framing in two different spots: send one of them, or both as getCurrentDocument returns them.";
401+
}
402+
391403
/** Every key a patch sets, `cursor.*` for the cursor's: what the result reports as applied. */
392404
function patchKeys(patch: EditorSettingsPatch): string[] {
393405
const { cursor, ...rest } = patch;
@@ -406,6 +418,8 @@ export function executeSetEditorSettings(
406418
if (!parsed.success) {
407419
return { ok: false, resultJson: JSON.stringify({ error: parsed.error.message }) };
408420
}
421+
const conflict = cropFramingConflict(parsed.data);
422+
if (conflict) return { ok: false, resultJson: JSON.stringify({ error: conflict }) };
409423
const patch = editorPatch(document, parsed.data);
410424
const keys = patchKeys(patch);
411425
if (keys.length === 0) {

0 commit comments

Comments
 (0)