Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 54 additions & 22 deletions apps/desktop/src/routes/capture-area.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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 },
]);
}

Expand All @@ -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 },
Expand Down Expand Up @@ -145,14 +159,20 @@ export default function CaptureArea() {
const [aspect, setAspect] = createSignal<Ratio | null>(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) {
Expand Down Expand Up @@ -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)}
/>
Expand Down
25 changes: 23 additions & 2 deletions apps/desktop/src/routes/target-select-overlay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,27 @@ function Inner() {
CropBounds | undefined
>(undefined);

const effectiveInitialBounds = createMemo<CropBounds | undefined>(() => {
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 (
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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()}
Expand Down
Loading