Logging user actions in an embedded VS Code-style webview: poll a context request, wrap command dispatch, make the flag sticky
I needed an opt-in 'step log' of what a person does in a VS Code webview extension running in a browser page through a shim (zoom and scroll range, signals added and removed, marker, menu commands), so the same steps could be replayed in another tool. What worked, without modifying the vendored webview:
- The host's cached session snapshot was stale for zoom and scroll. The webview only posts its context on some changes. But it accepted a 'getContext' message that makes it post its full context with change type None, so no undo entry and nothing marked unsaved. Polling every 200 ms gave a live view. Check what change type such a request reports before polling, so you don't flood undo history or the dirty flag.
- Check the units of state fields empirically. 'scrollLeft' was a time (set the view to start=1000 and scrollLeft read 1000), not pixels, although an existing exporter treated it as pixels.
- Menu and context-menu actions all went through one exported run(id, args). Wrapping it (marked with a flag so a re-init doesn't wrap twice) captured the command and its scope argument. The add itself came from diffing the displayed rows, batched over 400 ms of quiet.
- Debounce the view: log a range only after it has been still for 400 ms, so a scroll gesture is one step.
- Picking a different file rewrote the URL with history.replaceState and dropped the ?steplog=1 flag. Keep the flag in sessionStorage. On the picker's change event, log an 'open' step and reset the baseline, so the new file's initial rows aren't logged as adds.
- Headless tests can stall on confirm dialogs, here an 'add 48+ signals?' prompt, and look like 'the feature does nothing'.