diff --git a/apps/desktop/src/routes/capture-area.tsx b/apps/desktop/src/routes/capture-area.tsx index 0a2a3feeb17..2c62a6adaca 100644 --- a/apps/desktop/src/routes/capture-area.tsx +++ b/apps/desktop/src/routes/capture-area.tsx @@ -72,13 +72,27 @@ export default function CaptureArea() { const { rawOptions, setOptions } = createOptionsQuery(); + const activeScreenId = createMemo(() => { + const target = rawOptions.captureTarget; + if (target.variant === "display") return target.id; + if (target.variant === "area") return target.screen; + return null; + }); + + const screenId = activeScreenId; + const hasStoredSelection = createMemo(() => { + const id = screenId(); + if (!id) return false; + + if (state.lastSelectedBounds?.some((entry) => entry.screenId === id)) + return true; + const target = rawOptions.captureTarget; - if (target.variant !== "display") return false; - return ( - state.lastSelectedBounds?.some((entry) => entry.screenId === target.id) ?? - false - ); + if (target.variant === "area" && target.screen === id) { + return target.bounds.size.width > 1 && target.bounds.size.height > 1; + } + return false; }); async function handleConfirm() { @@ -90,22 +104,22 @@ export default function CaptureArea() { ) return; - const target = rawOptions.captureTarget; - if (target.variant !== "display") return; + const id = screenId(); + if (!id) return; const existingIndex = state.lastSelectedBounds?.findIndex( - (item) => item.screenId === target.id, + (item) => item.screenId === id, ); if (existingIndex >= 0) { setState("lastSelectedBounds", existingIndex, { - screenId: target.id, + screenId: id, bounds: currentBounds, }); } else { setState("lastSelectedBounds", [ ...state.lastSelectedBounds, - { screenId: target.id, bounds: currentBounds }, + { screenId: id, bounds: currentBounds }, ]); } @@ -114,7 +128,7 @@ export default function CaptureArea() { "captureTarget", reconcile({ variant: "area", - screen: target.id, + screen: id, bounds: { position: { x: b.x, y: b.y }, size: { width: b.width, height: b.height }, @@ -145,14 +159,20 @@ export default function CaptureArea() { const [aspect, setAspect] = createSignal(null); function reset() { - cropperRef?.reset(); setAspect(null); - const target = rawOptions.captureTarget; - if (target.variant !== "display") return; + const id = screenId(); + if (!id) return; setState("lastSelectedBounds", (values) => - values?.filter((v) => v.screenId !== target.id), + values?.filter((v) => v.screenId !== id), ); + + const target = rawOptions.captureTarget; + if (target.variant === "area" && target.screen === id) { + setOptions("captureTarget", reconcile({ variant: "display", id })); + } + + cropperRef?.reset(); } async function showCropOptionsMenu(e: UIEvent, positionAtCursor = false) { @@ -287,14 +307,26 @@ export default function CaptureArea() { onCropChange={setCrop} snapToRatioEnabled={state.snapToRatio} initialCrop={() => { + const id = screenId(); + if (!id) return CROP_ZERO; + const target = rawOptions.captureTarget; - if (target.variant === "display") - return ( - state.lastSelectedBounds?.find( - (m) => m.screenId === target.id, - )?.bounds ?? CROP_ZERO - ); - return CROP_ZERO; + if (target.variant === "area" && target.screen === id) { + const { width, height } = target.bounds.size; + if (width > 1 && height > 1) { + return { + x: target.bounds.position.x, + y: target.bounds.position.y, + width, + height, + }; + } + } + + return ( + state.lastSelectedBounds?.find((m) => m.screenId === id) + ?.bounds ?? CROP_ZERO + ); }} onContextMenu={(e) => showCropOptionsMenu(e, true)} /> diff --git a/apps/desktop/src/routes/target-select-overlay.tsx b/apps/desktop/src/routes/target-select-overlay.tsx index eb64f497ead..81eade376e1 100644 --- a/apps/desktop/src/routes/target-select-overlay.tsx +++ b/apps/desktop/src/routes/target-select-overlay.tsx @@ -234,6 +234,27 @@ function Inner() { CropBounds | undefined >(undefined); + const effectiveInitialBounds = createMemo(() => { + const explicit = initialAreaBounds(); + if (explicit !== undefined) return explicit; + const target = options.captureTarget; + if ( + target.variant === "area" && + params.displayId && + target.screen === params.displayId + ) { + const { width, height } = target.bounds.size; + if (width <= 1 || height <= 1) return undefined; + return { + x: target.bounds.position.x, + y: target.bounds.position.y, + width, + height, + }; + } + return undefined; + }); + createEffect(() => { const target = options.captureTarget; if ( @@ -725,7 +746,7 @@ function Inner() { () => isInteracting() || isActiveDisplay(), ); const shouldShowSelectionHint = createMemo(() => { - if (initialAreaBounds() !== undefined) return false; + if (effectiveInitialBounds() !== undefined) return false; if (!isActiveDisplay()) return false; const bounds = crop(); return bounds.width <= 1 && bounds.height <= 1 && !isInteracting(); @@ -1146,7 +1167,7 @@ function Inner() { ref={cropperRef} onInteraction={setIsInteracting} onCropChange={setCrop} - initialCrop={() => initialAreaBounds() ?? CROP_ZERO} + initialCrop={() => effectiveInitialBounds() ?? CROP_ZERO} showBounds={isValid()} aspectRatio={aspect() ?? undefined} snapToRatioEnabled={snapToRatioEnabled()}