diff --git a/unredact/static/app.js b/unredact/static/app.js index a563a55..e0e6217 100644 --- a/unredact/static/app.js +++ b/unredact/static/app.js @@ -19,8 +19,6 @@ const rightPanel = document.getElementById("right-panel"); const docContainer = document.getElementById("doc-container"); const popover = document.getElementById("popover"); const popoverClose = document.getElementById("popover-close"); -const popoverContext = document.getElementById("popover-context"); -const popoverFontInfo = document.getElementById("popover-font-info"); const solveCharset = document.getElementById("solve-charset"); const solveTolerance = document.getElementById("solve-tolerance"); const solveTolValue = document.getElementById("solve-tol-value"); @@ -53,6 +51,15 @@ const leftTextInput = document.getElementById("left-text-input"); const rightTextInput = document.getElementById("right-text-input"); const redactionMarker = document.getElementById("redaction-marker"); const textReset = document.getElementById("text-reset"); +const toastContainer = document.getElementById("toast-container"); + +function showToast(message, type = "info") { + const el = document.createElement("div"); + el.className = `toast ${type}`; + el.textContent = message; + toastContainer.appendChild(el); + setTimeout(() => el.remove(), 3000); +} // ── State ── @@ -369,22 +376,6 @@ function openPopover(id) { const r = state.redactions[id]; if (!r || !r.analysis) return; - const a = r.analysis; - - // Context line - const segs = a.segments; - const leftText = segs.length > 0 ? segs[0].text : ""; - const rightText = segs.length > 1 ? segs[1].text : ""; - popoverContext.innerHTML = `${escapeHtml(leftText)}\u2588\u2588\u2588${escapeHtml(rightText)}`; - - // Font info - const font = a.font; - popoverFontInfo.innerHTML = ` - ${escapeHtml(font.name)} ${font.size}px - score: ${font.score.toFixed(1)} - gap: ${Math.round(a.gap.w)}px - `; - // Pre-fill prefix/suffix from context solveFilterPrefix.value = ""; solveFilterSuffix.value = ""; @@ -1319,7 +1310,7 @@ function showAssocDetail(assocMatches, anchorEl) { let drawDrag = null; canvas.addEventListener("mousedown", (e) => { - if (!e.shiftKey || e.button !== 0) return; + if (!e.shiftKey || e.ctrlKey || e.button !== 0) return; const rect = rightPanel.getBoundingClientRect(); const sx = e.clientX - rect.left; @@ -1389,6 +1380,50 @@ window.addEventListener("mouseup", (e) => { activateRedaction(id); }); +// ── Ctrl+drag offset / Ctrl+Shift+drag gap width ── + +let ctrlDrag = null; + +canvas.addEventListener("mousedown", (e) => { + if (!e.ctrlKey || e.button !== 0) return; + const r = state.redactions[state.activeRedaction]; + if (!r?.overrides) return; + + ctrlDrag = { + startX: e.clientX, + startY: e.clientY, + startOffsetX: r.overrides.offsetX, + startOffsetY: r.overrides.offsetY, + startGapWidth: r.overrides.gapWidth, + widthMode: e.shiftKey, + }; + e.stopPropagation(); + e.preventDefault(); +}, { capture: true }); + +window.addEventListener("mousemove", (e) => { + if (!ctrlDrag) return; + const r = state.redactions[state.activeRedaction]; + if (!r?.overrides) return; + + const dx = (e.clientX - ctrlDrag.startX) / state.zoom; + const dy = (e.clientY - ctrlDrag.startY) / state.zoom; + + if (ctrlDrag.widthMode) { + r.overrides.gapWidth = Math.max(1, ctrlDrag.startGapWidth + dx); + gapValue.textContent = Math.round(r.overrides.gapWidth); + } else { + r.overrides.offsetX = ctrlDrag.startOffsetX + dx; + r.overrides.offsetY = ctrlDrag.startOffsetY + dy; + updatePosDisplay(); + } + renderCanvas(); +}); + +window.addEventListener("mouseup", () => { + if (ctrlDrag) ctrlDrag = null; +}); + // ── Utility ── function escapeHtml(text) { diff --git a/unredact/static/index.html b/unredact/static/index.html index b515de5..b8a3e41 100644 --- a/unredact/static/index.html +++ b/unredact/static/index.html @@ -78,8 +78,6 @@ Analyze Redaction -
-