mirror of
https://github.com/stablyai/orca.git
synced 2026-10-07 08:02:21 +00:00
* feat(browser): add an eraser to screenshot markup Click or drag across marks to remove them whole, one undo step per drag. Fixes #23258 * fix(browser): drop the in-flight markup gesture on undo and redo Undo mid-erase left marks hidden against the restored drawing, so release removed them and cleared redo. * fix(browser): settle a markup gesture whose release was lost A gesture now blocks any new press so a second finger cannot steer it. If its own release never arrived, that block also swallowed the next press from the same pointer, so the next drag continued the stale gesture: a stroke jumped from its old end, and an erase swept from the old point, removing marks along a line the user never touched. A pointer cannot press twice without releasing, so a press from the gesture's own pointer now settles the old gesture as its release would have, then starts the new one. * fix(browser): an eraser click takes only the top mark, a drag takes all A click on overlapping marks now erases only the one drawn last, matching what a user expects from pointing at a mark. Once the pointer really moves the press becomes a drag, whose first sweep starts at the press point, so every mark under it and along the path is erased. A move that reports the press point again does not turn a click into a drag. * fix(browser): undo mid-gesture takes back only the gesture Undo pressed while a stroke or an erase is still held now drops just that gesture, as the newest step; the committed marks are untouched, so the next Undo takes back the last of them. Redo and Clear drop the gesture, then apply as before. With the gesture gone, the rest of that drag neither draws nor erases until the next press. Undo is enabled while a gesture is in flight, since it now has something to take back. * fix(browser): keep an eraser tap a click within a 4px slop A touch or pen tap often reports a move a fraction of a pixel from the press point. The eraser treated any move to a different point as a drag, so such a tap erased every mark under the finger instead of only the top one. The erase gesture now records its press point and a pressed/dragging phase: it stays a click until the pointer travels 4 CSS px, then sweeps from the press point as a drag. * fix(browser): undo over an empty erase undoes the last mark Pressing Undo while an eraser was held over empty space only dropped the erase, which had hidden nothing, so Undo looked dead and the Undo button was enabled for a step with no visible effect. Undo now treats a held gesture as a step only when releasing it would change the markup (a stroke being drawn, or an erase that hides at least one mark). Otherwise Undo takes back the last committed mark and ends the erase; with nothing to undo it leaves the erase alone. The Undo button is enabled exactly when pressing it would change something. * fix(browser): redo with nothing to redo keeps a held markup gesture The Redo button is disabled when there is nothing to redo, but the Cmd/Ctrl+Shift+Z shortcut is not. Pressed while a stroke or erase was held down, it replaced the document with itself and dropped the gesture, so the stroke or erase silently stopped. Redo now leaves the state untouched when there is nothing to redo. Clear still always drops the gesture. * fix(browser): discard a markup gesture whose pointer was cancelled pointercancel was wired to the release handler, so when the system took a touch or pen pointer away mid-gesture (an OS gesture or palm rejection), the stroke was saved and an erase was applied as if the user had lifted deliberately. pointercancel now discards the in-flight gesture owned by that pointer: the stroke is not saved and the marks an erase was hiding come back, with no undo step. Lost pointer capture and a press that reveals a missed release still commit, since both stand in for a release that did happen. * test(browser): pin that losing the pointer commits a markup gesture The canvas commits a stroke or erase when it loses pointer capture without a release, so a gesture can never be left open. No test covered that wiring: removing it, or routing it to the cancel handler, left every test green. The new test ends a stroke with only the lost capture and checks that Undo then leaves it to redo, which only a committed stroke does. * fix(browser): do not save a markup shape pressed without dragging A Rectangle, Ellipse or Arrow press released without dragging paints nothing, but it was saved as a zero-size mark. With the eraser, a click takes only the topmost mark, so that invisible mark made the next eraser click on a visible mark at the same spot appear to do nothing. It also added an undo step with no visible effect, and while such a press was held Undo was enabled but only dropped the invisible shape. A shape with no size is now not saved, and a held unmoved shape press is not something Undo takes back. Pen and Highlighter taps still save the dot they draw; text is unchanged. * test(browser): drop a cancelled-stroke test the overlay test already covers MarkupOverlay.test.tsx drives the same press, move, pointercancel and following lost capture through the real canvas wiring and asserts Undo stays disabled, which already proves nothing was committed or held. * docs(browser): note the erase drag re-rasterizes the markup layer The committed layer now renders the visible marks, so an erase drag re-rasterizes it once per newly hit mark; the comment said never. --------- Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com>