diff --git a/resources/js/Components/DocumentsTable/DocumentViewerDialog.vue b/resources/js/Components/DocumentsTable/DocumentViewerDialog.vue index 1988afb..288e2c9 100644 --- a/resources/js/Components/DocumentsTable/DocumentViewerDialog.vue +++ b/resources/js/Components/DocumentsTable/DocumentViewerDialog.vue @@ -42,6 +42,9 @@ const dragStartTY = ref(0); const MAX_SCALE = 8; +// Image context menu state +const contextMenu = ref({ visible: false, x: 0, y: 0 }); + const imageCursorClass = computed(() => { if (isDragging.value && hasMoved.value) return "cursor-grabbing"; if (imageScale.value > fitScale.value + 0.01) return "cursor-grab"; @@ -56,7 +59,7 @@ const initImageView = () => { const cH = container.clientHeight; const iW = img.naturalWidth || cW; const iH = img.naturalHeight || cH; - const fs = Math.min(cW / iW, cH / iH); + const fs = Math.min(1, cW / iW, cH / iH); fitScale.value = fs; imageScale.value = fs; translateX.value = (cW - iW * fs) / 2; @@ -156,9 +159,42 @@ const handleMouseDown = (e) => { window.addEventListener("mouseup", onMouseUp); }; +const closeContextMenu = () => { + contextMenu.value.visible = false; + window.removeEventListener("click", closeContextMenu); +}; + +const handleContextMenu = (e) => { + e.preventDefault(); + contextMenu.value = { visible: true, x: e.clientX, y: e.clientY }; + setTimeout(() => window.addEventListener("click", closeContextMenu), 0); +}; + +const copyImageToClipboard = async () => { + closeContextMenu(); + const img = imageRef.value; + if (!img) return; + const displayW = Math.round(img.naturalWidth * fitScale.value); + const displayH = Math.round(img.naturalHeight * fitScale.value); + const canvas = document.createElement("canvas"); + canvas.width = displayW; + canvas.height = displayH; + const ctx = canvas.getContext("2d"); + ctx.drawImage(img, 0, 0, displayW, displayH); + canvas.toBlob(async (blob) => { + if (!blob) return; + try { + await navigator.clipboard.write([new ClipboardItem({ "image/png": blob })]); + } catch (err) { + console.error("Copy failed", err); + } + }, "image/png"); +}; + onUnmounted(() => { window.removeEventListener("mousemove", onMouseMove); window.removeEventListener("mouseup", onMouseUp); + window.removeEventListener("click", closeContextMenu); }); const fileExtension = computed(() => { @@ -337,6 +373,7 @@ watch( transition: isDragging ? 'none' : 'transform 0.12s ease', }" @load="handleImageLoad" + @contextmenu.prevent="handleContextMenu" />