Positioning and logic fixes

This commit is contained in:
James Brunton 2025-09-19 15:44:41 +01:00
parent 5a24e00497
commit 03eda04aec
3 changed files with 17 additions and 67 deletions

View File

@ -43,7 +43,7 @@ const CropAreaSelector: React.FC<CropAreaSelectorProps> = ({
// Convert PDF crop area to DOM coordinates for display
const domRect = pdfToDOMCoordinates(cropArea, pdfBounds);
// Handle mouse down on overlay (start dragging)
// Handle mouse down on overlay (start dragging or resizing)
const handleOverlayMouseDown = useCallback((e: React.MouseEvent) => {
if (disabled || !containerRef.current) return;
@ -54,19 +54,19 @@ const CropAreaSelector: React.FC<CropAreaSelectorProps> = ({
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
// Check if we're clicking on a resize handle
// Check if we're clicking on a resize handle first (higher priority)
const handle = getResizeHandle(x, y, domRect);
if (handle) {
setIsResizing(handle);
setInitialCropArea(cropArea);
} else {
// Check if we're clicking within the crop area for dragging
if (isPointInCropArea(x, y, domRect)) {
setIsDragging(false); // Ensure we're not dragging when resizing
} else if (isPointInCropArea(x, y, domRect)) {
// Only allow dragging if we're not on a resize handle
setIsDragging(true);
setIsResizing(null); // Ensure we're not resizing when dragging
setDragStart({ x: x - domRect.x, y: y - domRect.y });
}
}
}, [disabled, cropArea, domRect]);
// Handle mouse down on container (start new selection)
@ -211,15 +211,15 @@ const CropAreaSelector: React.FC<CropAreaSelectorProps> = ({
function getResizeHandle(x: number, y: number, domRect: DOMRect): ResizeHandle {
const handleSize = 8;
const tolerance = 4;
const tolerance = handleSize;
// Corner handles
// Corner handles (check these first, they have priority)
if (isNear(x, domRect.x, tolerance) && isNear(y, domRect.y, tolerance)) return 'nw';
if (isNear(x, domRect.x + domRect.width, tolerance) && isNear(y, domRect.y, tolerance)) return 'ne';
if (isNear(x, domRect.x, tolerance) && isNear(y, domRect.y + domRect.height, tolerance)) return 'sw';
if (isNear(x, domRect.x + domRect.width, tolerance) && isNear(y, domRect.y + domRect.height, tolerance)) return 'se';
// Edge handles
// Edge handles (only if not in corner area)
if (isNear(x, domRect.x + domRect.width / 2, tolerance) && isNear(y, domRect.y, tolerance)) return 'n';
if (isNear(x, domRect.x + domRect.width, tolerance) && isNear(y, domRect.y + domRect.height / 2, tolerance)) return 'e';
if (isNear(x, domRect.x + domRect.width / 2, tolerance) && isNear(y, domRect.y + domRect.height, tolerance)) return 's';

View File

@ -1,28 +1,24 @@
import React, { useMemo, useState, useEffect } from "react";
import { useMemo, useState, useEffect } from "react";
import { Stack, Text, Box, Group, NumberInput, ActionIcon, Center, Alert } from "@mantine/core";
import { useTranslation } from "react-i18next";
import RestartAltIcon from "@mui/icons-material/RestartAlt";
import InfoIcon from "@mui/icons-material/Info";
import { CropParametersHook } from "../../../hooks/tools/crop/useCropParameters";
import { useSelectedFiles } from "../../../contexts/file/fileHooks";
import { useFileContext } from "../../../contexts/FileContext";
import DocumentThumbnail from "../../shared/filePreview/DocumentThumbnail";
import CropAreaSelector from "./CropAreaSelector";
import {
calculatePDFBounds,
PDFBounds,
CropArea,
getPDFAspectRatio,
createFullPDFCropArea
CropArea
} from "../../../utils/cropCoordinates";
import { pdfWorkerManager } from "../../../services/pdfWorkerManager";
import DocumentThumbnail from "../../shared/filePreview/DocumentThumbnail";
interface CropSettingsProps {
parameters: CropParametersHook;
disabled?: boolean;
}
const CONTAINER_SIZE = 400; // Larger container for better crop precision
const CONTAINER_SIZE = 250; // Fit within actual pane width
const CropSettings = ({ parameters, disabled = false }: CropSettingsProps) => {
const { t } = useTranslation();
@ -41,7 +37,6 @@ const CropSettings = ({ parameters, disabled = false }: CropSettingsProps) => {
// Get thumbnail for the selected file
const [thumbnail, setThumbnail] = useState<string | null>(null);
const [pdfBounds, setPdfBounds] = useState<PDFBounds | null>(null);
const [loading, setLoading] = useState(false);
useEffect(() => {
const loadPDFDimensions = async () => {
@ -52,7 +47,6 @@ const CropSettings = ({ parameters, disabled = false }: CropSettingsProps) => {
}
setThumbnail(selectedStub.thumbnailUrl || null);
setLoading(true);
try {
// Get PDF dimensions from the actual file
@ -95,8 +89,6 @@ const CropSettings = ({ parameters, disabled = false }: CropSettingsProps) => {
if (parameters.parameters.width === 595 && parameters.parameters.height === 842) {
parameters.resetToFullPDF(bounds);
}
} finally {
setLoading(false);
}
};
@ -106,6 +98,7 @@ const CropSettings = ({ parameters, disabled = false }: CropSettingsProps) => {
// Current crop area
const cropArea = parameters.getCropArea();
// Handle crop area changes from the selector
const handleCropAreaChange = (newCropArea: CropArea) => {
if (pdfBounds) {
@ -139,19 +132,6 @@ const CropSettings = ({ parameters, disabled = false }: CropSettingsProps) => {
return Math.round((cropAreaSize / totalArea) * 100);
}, [cropArea, pdfBounds]);
// Get aspect ratio information
const aspectRatioInfo = useMemo(() => {
if (!pdfBounds) return null;
const pdfRatio = getPDFAspectRatio(pdfBounds);
const cropRatio = cropArea.width / cropArea.height;
return {
pdf: pdfRatio.toFixed(2),
crop: cropRatio.toFixed(2),
orientation: pdfRatio > 1 ? 'Landscape' : 'Portrait'
};
}, [pdfBounds, cropArea]);
if (!selectedStub || !pdfBounds) {
return (
<Center style={{ height: '200px' }}>
@ -222,14 +202,6 @@ const CropSettings = ({ parameters, disabled = false }: CropSettingsProps) => {
<Text size="xs" color="dimmed">
{t("crop.info.percentage", "Area: {{percentage}}%", { percentage: cropPercentage })}
</Text>
{aspectRatioInfo && (
<Text size="xs" color="dimmed">
{t("crop.info.ratio", "Ratio: {{ratio}} ({{orientation}})", {
ratio: aspectRatioInfo.crop,
orientation: parseFloat(aspectRatioInfo.crop) > 1 ? 'Landscape' : 'Portrait'
})}
</Text>
)}
</Group>
</Stack>
@ -289,28 +261,6 @@ const CropSettings = ({ parameters, disabled = false }: CropSettingsProps) => {
/>
</Group>
{/* PDF Dimensions Info */}
<Alert
icon={<InfoIcon />}
color="blue"
variant="light"
style={{ fontSize: '0.75rem' }}
>
<Text size="xs">
{t("crop.info.pdfDimensions", "PDF Size: {{width}} × {{height}} points", {
width: Math.round(pdfBounds.actualWidth),
height: Math.round(pdfBounds.actualHeight)
})}
</Text>
{aspectRatioInfo && (
<Text size="xs">
{t("crop.info.aspectRatio", "Aspect Ratio: {{ratio}} ({{orientation}})", {
ratio: aspectRatioInfo.pdf,
orientation: aspectRatioInfo.orientation
})}
</Text>
)}
</Alert>
{/* Validation Alert */}
{!isCropValid && (

View File

@ -59,7 +59,7 @@ export const calculatePDFBounds = (
const thumbnailWidth = actualPDFWidth * scale;
const thumbnailHeight = actualPDFHeight * scale;
// Calculate centering offsets
// Calculate centering offsets - these represent where the thumbnail is positioned within the container
const offsetX = (containerWidth - thumbnailWidth) / 2;
const offsetY = (containerHeight - thumbnailHeight) / 2;