Four user reports from the 0.6.0 rollout: - Text tool never committed. openTextInput placed the box correctly but a couple of Chromium quirks stopped a normal type-Enter cycle: focus() called synchronously right after appendChild lost the race in some builds, and the input's own mousedown / click was bubbling through to #base and re-firing openTextInput on every subsequent keystroke click-through, so what looked like "nothing happens" was actually "a new empty box spawned on top of the last one every time". Now: focus after requestAnimationFrame, contain pointerdown / mousedown / click inside the input so they don't bubble to the canvas, track the font size on the state so commit uses the same one openTextInput measured against, and preventDefault on the base pointerdown so Chromium doesn't reset focus back to <body>. - Toolbar wrapped one dot at a time when the sidebar was narrow (a lonely thin/medium/thick width would jump to a second row while the swatches stayed above it). Toolbar items are now wrapped in `<div class="tgroup">` per category — tools / swatches / widths / undo-redo — with `flex: 0 0 auto`, so a whole row wraps as a unit and lands cleanly under the previous one. `gap: 10px / row-gap: 6px` keeps the visual grouping obvious. - No way to close the sidebar without hunting for the dock icon. Added an X button in the top-right of both the sidebar panel and the editor toolbar. Both wire through a new `silentmode.sidebar.close()` preload method that calls the existing `sidebar-close` IPC. - Tightened the pointerdown text branch so preventDefault + explicit focus-after-frame make the click-through races impossible. Bundled but not shipped separately — parent session signs and pushes.
117 lines
6.4 KiB
HTML
117 lines
6.4 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<title>Screenshot editor</title>
|
|
<link rel="stylesheet" href="editor.css">
|
|
</head>
|
|
<body>
|
|
<div class="topbar">
|
|
<button class="btn" id="back" title="Back to sidebar panel">
|
|
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M13 8H3M6 5L3 8l3 3"/></svg>
|
|
</button>
|
|
<span class="name" id="name">screenshot</span>
|
|
|
|
<!-- Crop mode splits the topbar into a confirm/cancel prompt while the
|
|
user is dragging a crop rectangle. Everything else in the topbar
|
|
fades in and out around these two buttons. -->
|
|
<button class="btn wide" id="apply-crop" hidden title="Apply the crop (Enter)">
|
|
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M3 8l3 3 7-7"/></svg>
|
|
<span>Apply crop</span>
|
|
</button>
|
|
<button class="btn wide" id="cancel-crop" hidden title="Cancel crop (Esc)">
|
|
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><path d="M4 4l8 8M12 4l-8 8"/></svg>
|
|
<span>Cancel</span>
|
|
</button>
|
|
|
|
<span class="spacer"></span>
|
|
<button class="btn wide" id="copy" title="Copy PNG to clipboard (Ctrl+C)">
|
|
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="4" y="4" width="9" height="10"/><path d="M3 12V3h9"/></svg>
|
|
<span>Copy</span>
|
|
</button>
|
|
<button class="btn wide primary" id="save" title="Save PNG (Ctrl+S)">
|
|
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M8 2v9M4 7l4 4 4-4M2 14h12"/></svg>
|
|
<span>Save</span>
|
|
</button>
|
|
<button class="btn" id="toggle-sound" title="Toggle sound"></button>
|
|
<button class="btn" id="toggle-max" title="Expand the sidebar to full window / restore">
|
|
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M2 6V2h4M14 6V2h-4M2 10v4h4M14 10v4h-4"/></svg>
|
|
</button>
|
|
<button class="btn" id="close-sidebar" title="Close the sidebar">
|
|
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><path d="M4 4l8 8M12 4l-8 8"/></svg>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Toolbar rows are grouped so that when the sidebar is too narrow to
|
|
hold everything, whole categories wrap together (tools stay with
|
|
tools, swatches with swatches, widths with widths, history with
|
|
history) instead of one dot spilling to a lonely second row. -->
|
|
<div class="toolbar">
|
|
<div class="tgroup" role="group" aria-label="Tools">
|
|
<button class="tool active" data-tool="select" title="Select (no tool)">
|
|
<svg viewBox="0 0 16 16" fill="currentColor"><path d="M3 2l10 5-4 1-1 4z"/></svg>
|
|
</button>
|
|
<button class="tool" data-tool="crop" title="Crop (C)">
|
|
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><path d="M4 1v11h11M1 4h11v11"/></svg>
|
|
</button>
|
|
<button class="tool" data-tool="arrow" title="Arrow (A)">
|
|
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"><path d="M3 13L13 3M13 3H8M13 3v5"/></svg>
|
|
</button>
|
|
<button class="tool" data-tool="rect" title="Rectangle (R)">
|
|
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="2.5" y="3.5" width="11" height="9"/></svg>
|
|
</button>
|
|
<button class="tool" data-tool="ellipse" title="Ellipse (O)">
|
|
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><ellipse cx="8" cy="8" rx="5.5" ry="4"/></svg>
|
|
</button>
|
|
<button class="tool" data-tool="pen" title="Pen (P)">
|
|
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="M2 14c1-3 3-6 6-8s5-3 6-3l-3 4c-2 1-4 3-6 4s-2 2-3 3z"/></svg>
|
|
</button>
|
|
<button class="tool" data-tool="text" title="Text (T)">
|
|
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><path d="M3 3h10M8 3v10M6 13h4"/></svg>
|
|
</button>
|
|
<button class="tool" data-tool="blur" title="Blur / mosaic redaction (B)">
|
|
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="2.5" y="2.5" width="11" height="11"/><path d="M5 6h1M8 6h1M11 6h1M5 9h1M8 9h1M11 9h1M5 12h1M8 12h1M11 12h1"/></svg>
|
|
</button>
|
|
</div>
|
|
|
|
<div class="tgroup" role="group" aria-label="Colours">
|
|
<button class="swatch active" data-color="#ff3b30" style="background:#ff3b30" title="Red"></button>
|
|
<button class="swatch" data-color="#d6ff3d" style="background:#d6ff3d" title="Acid"></button>
|
|
<button class="swatch" data-color="#ffcc00" style="background:#ffcc00" title="Yellow"></button>
|
|
<button class="swatch" data-color="#0aa8ff" style="background:#0aa8ff" title="Blue"></button>
|
|
<button class="swatch" data-color="#ffffff" style="background:#ffffff" title="White"></button>
|
|
<button class="swatch" data-color="#000000" style="background:#000000" title="Black"></button>
|
|
</div>
|
|
|
|
<div class="tgroup" role="group" aria-label="Widths">
|
|
<button class="width" data-width="3" title="Thin"><span class="dot" style="width:4px;height:4px"></span></button>
|
|
<button class="width active" data-width="5" title="Medium"><span class="dot" style="width:7px;height:7px"></span></button>
|
|
<button class="width" data-width="9" title="Thick"><span class="dot" style="width:11px;height:11px"></span></button>
|
|
</div>
|
|
|
|
<div class="tgroup" role="group" aria-label="History">
|
|
<button class="btn" id="undo" title="Undo (Ctrl+Z)" disabled>
|
|
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><path d="M3 8c0-3 2-5 5-5s5 2 5 5-2 5-5 5"/><path d="M6 5L3 8l3 3"/></svg>
|
|
</button>
|
|
<button class="btn" id="redo" title="Redo (Ctrl+Shift+Z)" disabled>
|
|
<svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><path d="M13 8c0-3-2-5-5-5S3 5 3 8s2 5 5 5"/><path d="M10 5l3 3-3 3"/></svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="board" id="board">
|
|
<div class="empty" id="empty">
|
|
<div>Loading capture…</div>
|
|
</div>
|
|
<div class="stage" id="stage" hidden>
|
|
<canvas id="base"></canvas>
|
|
<canvas id="over"></canvas>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="toast" id="toast"></div>
|
|
<a id="download-link" style="display:none"></a>
|
|
|
|
<script src="editor.js"></script>
|
|
</body>
|
|
</html>
|