try to fix mobile crop
All checks were successful
Build Images and Deploy / Update-PROD-Stack (push) Successful in 2m40s

This commit is contained in:
2026-02-10 21:51:00 -05:00
parent c10c9d819c
commit 229f7c4b16

View File

@@ -748,7 +748,7 @@
<p><strong>Codec:</strong> ${videoInfo.codec}</p> <p><strong>Codec:</strong> ${videoInfo.codec}</p>
<div style="margin-top: 15px; text-align: center;"> <div style="margin-top: 15px; text-align: center;">
<button class="crop-mode-btn" id="crop-mode-btn">🎯 Click to Draw Crop Area</button> <button class="crop-mode-btn" id="crop-mode-btn">🎯 Click to Draw Crop Area</button>
<p class="crop-hint" id="crop-hint" style="display: none;">Click and drag to select • Drag corners to resize • Drag center to move</p> <p class="crop-hint" id="crop-hint" style="display: none;">Click and drag to select • Drag corners and edges to resize or double click them to max • Drag center to move</p>
</div> </div>
`; `;
@@ -830,10 +830,26 @@
cropCanvas.addEventListener('mousedown', (e) => { cropCanvas.addEventListener('mousedown', (e) => {
if (!cropMode) return; if (!cropMode) return;
e.preventDefault();
const rect = cropCanvas.getBoundingClientRect(); const rect = cropCanvas.getBoundingClientRect();
const mouseX = e.clientX - rect.left; const mouseX = e.clientX - rect.left;
const mouseY = e.clientY - rect.top; const mouseY = e.clientY - rect.top;
handlePointerDown(mouseX, mouseY);
});
cropCanvas.addEventListener('touchstart', (e) => {
if (!cropMode) return;
e.preventDefault();
const rect = cropCanvas.getBoundingClientRect();
const touch = e.touches[0];
const mouseX = touch.clientX - rect.left;
const mouseY = touch.clientY - rect.top;
handlePointerDown(mouseX, mouseY);
});
function handlePointerDown(mouseX, mouseY) {
// Check if clicking on a handle // Check if clicking on a handle
if (cropRect) { if (cropRect) {
const handle = getHandleAtPosition(mouseX, mouseY); const handle = getHandleAtPosition(mouseX, mouseY);
@@ -866,7 +882,7 @@
cropRect = null; cropRect = null;
startX = mouseX; startX = mouseX;
startY = mouseY; startY = mouseY;
}); }
cropCanvas.addEventListener('mousemove', (e) => { cropCanvas.addEventListener('mousemove', (e) => {
if (!cropMode) return; if (!cropMode) return;
@@ -874,6 +890,21 @@
const mouseX = e.clientX - rect.left; const mouseX = e.clientX - rect.left;
const mouseY = e.clientY - rect.top; const mouseY = e.clientY - rect.top;
handlePointerMove(mouseX, mouseY);
});
cropCanvas.addEventListener('touchmove', (e) => {
if (!cropMode) return;
e.preventDefault();
const rect = cropCanvas.getBoundingClientRect();
const touch = e.touches[0];
const mouseX = touch.clientX - rect.left;
const mouseY = touch.clientY - rect.top;
handlePointerMove(mouseX, mouseY);
});
function handlePointerMove(mouseX, mouseY) {
// Update cursor based on position // Update cursor based on position
if (!isDrawing && !isDraggingHandle && !isDraggingEdge && !isDraggingBox && cropRect) { if (!isDrawing && !isDraggingHandle && !isDraggingEdge && !isDraggingBox && cropRect) {
const handle = getHandleAtPosition(mouseX, mouseY); const handle = getHandleAtPosition(mouseX, mouseY);
@@ -924,11 +955,20 @@
}; };
drawCropRect(); drawCropRect();
} }
}); }
cropCanvas.addEventListener('mouseup', (e) => { cropCanvas.addEventListener('mouseup', (e) => {
if (!cropMode) return; if (!cropMode) return;
handlePointerUp();
});
cropCanvas.addEventListener('touchend', (e) => {
if (!cropMode) return;
e.preventDefault();
handlePointerUp();
});
function handlePointerUp() {
if (isDrawing || isDraggingHandle || isDraggingEdge || isDraggingBox) { if (isDrawing || isDraggingHandle || isDraggingEdge || isDraggingBox) {
updateFormFields(); updateFormFields();
} }
@@ -943,20 +983,18 @@
// Keep crop mode active and canvas visible // Keep crop mode active and canvas visible
drawCropRect(); drawCropRect();
}); }
// Handle mouse leaving canvas while dragging // Handle mouse leaving canvas while dragging
cropCanvas.addEventListener('mouseleave', (e) => { cropCanvas.addEventListener('mouseleave', (e) => {
if (isDrawing || isDraggingHandle || isDraggingEdge || isDraggingBox) { if (isDrawing || isDraggingHandle || isDraggingEdge || isDraggingBox) {
// Finish the drag operation handlePointerUp();
updateFormFields(); }
isDrawing = false; });
isDraggingHandle = false;
isDraggingEdge = false; cropCanvas.addEventListener('touchcancel', (e) => {
isDraggingBox = false; if (cropMode) {
activeHandle = null; handlePointerUp();
activeEdge = null;
drawCropRect();
} }
}); });
@@ -1038,6 +1076,9 @@
function getHandleAtPosition(x, y) { function getHandleAtPosition(x, y) {
if (!cropRect) return null; if (!cropRect) return null;
// Larger hit area on mobile (touch targets should be at least 44x44px)
const hitSize = 'ontouchstart' in window ? 22 : handleSize;
const handles = [ const handles = [
{ name: 'tl', x: cropRect.x, y: cropRect.y }, { name: 'tl', x: cropRect.x, y: cropRect.y },
{ name: 'tr', x: cropRect.x + cropRect.width, y: cropRect.y }, { name: 'tr', x: cropRect.x + cropRect.width, y: cropRect.y },
@@ -1046,7 +1087,7 @@
]; ];
for (const handle of handles) { for (const handle of handles) {
if (Math.abs(x - handle.x) <= handleSize && Math.abs(y - handle.y) <= handleSize) { if (Math.abs(x - handle.x) <= hitSize && Math.abs(y - handle.y) <= hitSize) {
return handle.name; return handle.name;
} }
} }
@@ -1056,30 +1097,32 @@
function getEdgeAtPosition(x, y) { function getEdgeAtPosition(x, y) {
if (!cropRect) return null; if (!cropRect) return null;
const tolerance = 15; // Click detection tolerance in pixels // Larger tolerance on mobile for easier touch interaction
const tolerance = 'ontouchstart' in window ? 25 : 15;
const { x: rx, y: ry, width: rw, height: rh } = cropRect; const { x: rx, y: ry, width: rw, height: rh } = cropRect;
const hitSize = 'ontouchstart' in window ? 22 : handleSize;
// Check if within the rectangle bounds (with tolerance) // Check if within the rectangle bounds (with tolerance)
const inHorizontalRange = x >= rx - tolerance && x <= rx + rw + tolerance; const inHorizontalRange = x >= rx - tolerance && x <= rx + rw + tolerance;
const inVerticalRange = y >= ry - tolerance && y <= ry + rh + tolerance; const inVerticalRange = y >= ry - tolerance && y <= ry + rh + tolerance;
// Top edge (exclude corners) // Top edge (exclude corners)
if (Math.abs(y - ry) <= tolerance && x > rx + handleSize && x < rx + rw - handleSize) { if (Math.abs(y - ry) <= tolerance && x > rx + hitSize && x < rx + rw - hitSize) {
return 'top'; return 'top';
} }
// Bottom edge (exclude corners) // Bottom edge (exclude corners)
if (Math.abs(y - (ry + rh)) <= tolerance && x > rx + handleSize && x < rx + rw - handleSize) { if (Math.abs(y - (ry + rh)) <= tolerance && x > rx + hitSize && x < rx + rw - hitSize) {
return 'bottom'; return 'bottom';
} }
// Left edge (exclude corners) // Left edge (exclude corners)
if (Math.abs(x - rx) <= tolerance && y > ry + handleSize && y < ry + rh - handleSize) { if (Math.abs(x - rx) <= tolerance && y > ry + hitSize && y < ry + rh - hitSize) {
return 'left'; return 'left';
} }
// Right edge (exclude corners) // Right edge (exclude corners)
if (Math.abs(x - (rx + rw)) <= tolerance && y > ry + handleSize && y < ry + rh - handleSize) { if (Math.abs(x - (rx + rw)) <= tolerance && y > ry + hitSize && y < ry + rh - hitSize) {
return 'right'; return 'right';
} }