Skip to content

Draw on the paused replay - #311

Merged
SunkenInTime merged 4 commits into
mainfrom
t3/replay-draw-on-watch
Oct 15, 2026
Merged

SunkenInTime merged 4 commits into
mainfrom
t3/replay-draw-on-watch

Conversation

@SunkenInTime

Copy link
Copy Markdown
Owner

Coaches review matches with their team over a screen share: they pause on a moment and want to circle a player or show where someone should have gone, right on the replay. Until now the only way to draw was to Capture the moment and open it in the editor, which is too heavy in the middle of a review. ValoPlant lets you draw over its replay; this does the same in Icarus.

What changed

  • A pen button next to Capture, also taken out with the editor's Draw key (Q unless the user rebound it; D is Next page in the editor, so it isn't used here). Taking the pen out pauses playback and shows two tools, freehand and arrow, plus Clear once something is drawn. Q, Esc or the pen button put it away.
  • Strokes are the editor's own drawings (FreeDrawing, Line with an arrowhead), drawn by the editor's DrawingPainter in the user's last pen colour and thickness. They live in the canvas's world, so they zoom and pan with the map, and are flipped on defense the way the editor flips a page.
  • Strokes describe a frozen moment. Playing clears them and puts the pen away. Seeking or changing round while paused clears them and keeps the pen out.
  • While the pen is out, a drag draws instead of panning, the wheel still zooms, and clicking an agent doesn't start watching them (from Watch one player in the replay viewer #309, which this sits on).
  • Capture keeps the strokes. The captured page gets them as its ordinary drawings: drawingData locally, and normal drawing elements through the existing page ops in the cloud. No Hive model, .ica export, server or sync change.
  • DrawingPainter loses a provider parameter it never read, so the replay can paint without the editor's state.

How it was checked

  • test/replay_drawing_test.dart covers:
    • drawing pausing playback;
    • a drag drawing without panning, while the same drag with the pen away pans;
    • the wheel zooming;
    • strokes clearing on play and on seek;
    • the Draw key, Esc and the button;
    • a capture whose page puts the strokes at the same world points, locally and in the cloud payload;
    • the editor's own drawing widget rendering that page at another size with the stroke at the same fraction of the map.
  • In a release build on a 13.08 Abyss replay, driven by an input driver that injects pointer and key events into the app:
    • Q took the pen out. A circle and an arrow drew, and stayed on the same map spots when zoomed in.
    • Esc put the pen away and kept the strokes.
    • Capture → Open showed both strokes on the page in the same places relative to the map and players.
    • With the pen out, clicking an agent did not start watching. Seeking cleared the strokes, and Space cleared them and put the pen away.
  • Astra's computer-use tool couldn't draw here or in the editor's own pen. Its drags move without deltas, which never start a drag in Flutter, so I ran the drawing checks through the driver instead.

ci: analyze test

🤖 Generated with Claude Code

SunkenInTime and others added 3 commits October 15, 2026 18:19
Coaches reviewing a match over a screen share pause on a moment and want to
circle a player or show where someone should have gone. Until now the only
way to draw was to capture the moment and open it in the editor.

The match card gets a pen next to Capture (and the D key). Taking it out
pauses playback and shows two tools, freehand and a straight arrow, plus
Clear once something is drawn. Esc, D or the pen again put it away; the
strokes stay until cleared or until the moment changes: playing clears them
and puts the pen away, seeking or changing round clears them.

Strokes are the editor's own drawing elements (FreeDrawing, Line with an
arrowhead) in the attack-side world, drawn by the editor's DrawingPainter in
the user's last editor pen colour and thickness, in a layer of its own above
everything on the map. The layer is flipped on defense as the editor flips a
page's drawings, zooms and pans with the map, and repaints only when the
strokes change. While the pen is out a drag draws instead of panning; the
wheel still zooms. The strokes live in the replay screen's own state, never
in the editor's drawing providers.

Capture saves them as the page's drawings, on both paths: locally as
StrategyPage.drawingData, in the cloud as ordinary drawing elements through
the existing page ops. No saved format, Hive model, export or server change.

DrawingPainter loses a provider parameter it never read, so the replay can
paint with it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
D is the editor's Next page; Draw is Q unless the user rebound it. The
replay's pen now answers to that same binding, and its tooltip names it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Esc puts the pen away before it stops watching, and a click with the pen
out starts a stroke rather than watching the agent under it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 51 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 69e91f31-021a-43c9-9745-324f52f77ad4
📥 Commits

Reviewing files that changed from the base of the PR and between a70ae2b and d22fa39.

📒 Files selected for processing: 11
  • lib/replay/replay_capture.dart
  • lib/replay/replay_drawing.dart
  • lib/replay_view.dart
  • lib/widgets/drawing_painter.dart
  • lib/widgets/replay/replay_canvas.dart
  • lib/widgets/replay/replay_drawing_layer.dart
  • lib/widgets/replay/replay_match_card.dart
  • test/replay_capture_test.dart
  • test/replay_drawing_test.dart
  • test/replay_test_support.dart
  • test/replay_watch_test.dart
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Through the map's centre a stroke looks the same flipped or not, so the
test could not tell a missing defense flip. Off-centre, and with the
mirrored point checked empty in the editor, it fails without the flip.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@SunkenInTime
SunkenInTime changed the base branch from t3/replay-watch-player to main October 15, 2026 23:34
@SunkenInTime
SunkenInTime merged commit 765054e into main Oct 15, 2026
14 checks passed
@SunkenInTime
SunkenInTime deleted the t3/replay-draw-on-watch branch October 15, 2026 23:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant