// content.js — Injected into every page // Manages the screen selection overlay and sidebar panel let overlayActive = false; let sidebarFrame = null; // ── Listen for messages from background / popup ─────────────────────────────── chrome.runtime.onMessage.addListener((msg, _sender, sendResponse) => { if (msg.type === "START_SELECTION") { if (!overlayActive) startSelection(); sendResponse({ ok: true }); return false; } if (msg.type === "SHOW_SIDEBAR") { showSidebar({}); return false; } if (msg.type === "SHOW_RESULT") { showSidebar(msg.data); return false; } }); // ── Selection overlay ───────────────────────────────────────────────────────── function startSelection() { overlayActive = true; // Dim the page const overlay = document.createElement("div"); overlay.id = "glmocr-overlay"; // Crosshair hint const hint = document.createElement("div"); hint.id = "glmocr-hint"; hint.textContent = "Drag to select text region — Press Esc to cancel"; overlay.appendChild(hint); // Selection box const selBox = document.createElement("div"); selBox.id = "glmocr-selbox"; overlay.appendChild(selBox); document.body.appendChild(overlay); let startX = 0, startY = 0, isDragging = false; function onMouseDown(e) { if (e.button !== 0) return; isDragging = true; startX = e.clientX; startY = e.clientY; selBox.style.cssText = `left:${startX}px; top:${startY}px; width:0; height:0; display:block`; hint.style.opacity = "0"; e.preventDefault(); } function onMouseMove(e) { if (!isDragging) return; const x = Math.min(e.clientX, startX); const y = Math.min(e.clientY, startY); const w = Math.abs(e.clientX - startX); const h = Math.abs(e.clientY - startY); selBox.style.cssText = `left:${x}px; top:${y}px; width:${w}px; height:${h}px; display:block`; } function onMouseUp(e) { if (!isDragging) return; isDragging = false; const x = Math.min(e.clientX, startX); const y = Math.min(e.clientY, startY); const w = Math.abs(e.clientX - startX); const h = Math.abs(e.clientY - startY); cleanup(); if (w < 10 || h < 10) { showToast("Selection too small — try again."); return; } const dpr = window.devicePixelRatio || 1; const rect = { x: x + window.scrollX, y: y + window.scrollY, width: w, height: h, dpr, }; runOcr(rect); } function onKeyDown(e) { if (e.key === "Escape") { cleanup(); showToast("Cancelled."); } } function cleanup() { overlayActive = false; overlay.removeEventListener("mousedown", onMouseDown); overlay.removeEventListener("mousemove", onMouseMove); overlay.removeEventListener("mouseup", onMouseUp); document.removeEventListener("keydown", onKeyDown); overlay.remove(); } overlay.addEventListener("mousedown", onMouseDown); overlay.addEventListener("mousemove", onMouseMove); overlay.addEventListener("mouseup", onMouseUp); document.addEventListener("keydown", onKeyDown); } // ── Send region to background for capture + OCR ─────────────────────────────── function runOcr(rect) { // Show a loading sidebar immediately showSidebar({ loading: true }); chrome.runtime.sendMessage({ type: "CAPTURE_REGION", rect }, (response) => { if (chrome.runtime.lastError) { showSidebar({ error: chrome.runtime.lastError.message }); return; } if (response.success) { showSidebar(response); } else { showSidebar({ error: response.error }); } }); } // ── Sidebar panel ───────────────────────────────────────────────────────────── function showSidebar(data) { // Remove existing sidebar if any if (sidebarFrame) sidebarFrame.remove(); const frame = document.createElement("iframe"); frame.id = "glmocr-sidebar"; frame.src = chrome.runtime.getURL("sidebar.html"); document.body.appendChild(frame); sidebarFrame = frame; // Wait for iframe to load, then send data frame.onload = () => { frame.contentWindow.postMessage({ type: "SIDEBAR_DATA", data }, "*"); }; // Close button via message from sidebar window.addEventListener("message", (e) => { if (e.data?.type === "CLOSE_SIDEBAR") { frame.remove(); sidebarFrame = null; } if (e.data?.type === "START_NEW_SELECTION") { frame.remove(); sidebarFrame = null; startSelection(); } }); } // ── Toast notification ──────────────────────────────────────────────────────── function showToast(msg) { const existing = document.getElementById("glmocr-toast"); if (existing) existing.remove(); const toast = document.createElement("div"); toast.id = "glmocr-toast"; toast.textContent = msg; document.body.appendChild(toast); setTimeout(() => toast?.remove(), 3000); }