feature(laser): implement telestrator pattern for laser pointer#7681
feature(laser): implement telestrator pattern for laser pointer#7681steveruizok merged 20 commits intomainfrom
Conversation
Add session management to ScribbleManager that keeps all laser strokes visible while actively drawing. Laser annotations now fade together when the user stops for 2 seconds (configurable via laserSessionTimeoutMs). Key changes: - Track laser scribbles in sessions that persist until idle timeout - Prevent point removal from laser scribbles during active session - All session scribbles fade together when session ends - Remove 5-scribble limit for laser strokes (but maintain for others) - Add laserSessionTimeoutMs and laserMaxSessionDurationMs options - End laser session when exiting the laser tool
|
The latest updates on your projects. Learn more about Vercel for GitHub.
4 Skipped Deployments
|
|
API Changes Check Passed Great! The PR description now includes the required "### API changes" section. This helps reviewers and SDK users understand the impact of your changes. |
When a user held the pointer down but stopped moving for 2+ seconds, the session timeout would fire and delete the scribble. If the user resumed moving while still holding the pointer, addPoint would throw an error because the scribble no longer existed. This fix keeps the laser session alive while the pointer is held by calling extendLaserSession() on every tick in the Lasering state. The timeout now only starts counting after the user lifts their pointer, which is the proper telestrator behavior. - Add extendLaserSession() public method to ScribbleManager - Add onTick() handler to Lasering state to extend session - Add tests for extendLaserSession()
|
excited about this one!
|
|
changed title from fix → feature |
Deploying with
|
| Status | Name | Latest Commit | Updated (UTC) |
|---|---|---|---|
| ❌ Deployment failed View logs |
multiplayer-template | 9148ff6 | Jan 26 2026, 06:43 PM |
|
had a jam session with @mimecuvalo
I've added these changes in the previous commit, I had added a configurable global timeout option (e.g since starting a laser session, all scribbles would disappear after 1m no matter what) but think this is not really needed. the thing that drives whether all the lasers stay is the idle timeout. |
packages/editor/src/lib/editor/managers/ScribbleManager/ScribbleManager.ts
Outdated
Show resolved
Hide resolved
Introduces TelestrationManager to manage telestration (laser pointer) sessions, enabling persistent and sequentially fading laser scribbles. Updates Editor to include telestration management, adds related options, and refactors ScribbleManager to delegate laser session logic. Includes comprehensive tests for TelestrationManager and updates ScribbleManager tests accordingly.
Introduces a fadeElapsed property to TelestrationSession to accurately track fade-out progress, and applies a quadratic ease-in curve for smoother point removal during fade-out. Updates tests to clarify front-to-back point removal behavior.
packages/editor/src/lib/editor/managers/TelestrationManager/TelestrationManager.ts
Outdated
Show resolved
Hide resolved
Replaces the TelestrationManager with a new ScribbleSession-based architecture for managing scribbles. The ScribbleManager now supports multiple sessions, improved session and scribble lifecycle handling, and more flexible fade/consumption behaviors. Updates all related tests and removes telestration-related code and exports.
packages/editor/src/lib/editor/managers/ScribbleManager/ScribbleSession.ts
Outdated
Show resolved
Hide resolved
Replaces telestration-related option names (telestrationFadeoutMs, telestrationIdleTimeoutMs) with laser-specific names (laserFadeoutMs, laserDelayMs) throughout the codebase. Updates related tests and removes deprecated laserSessionTimeoutMs. Ensures consistent naming and behavior for laser tool fade and delay settings.
Introduces a clear() method to ScribbleSession for immediate cleanup. Updates LaserTool and its child states to use this method, ensuring sessions are properly cleared and transitions are handled consistently when cancelling.
Introduces detailed tests for the LaserTool, covering state transitions, scribble creation, session management, cancel behavior, tool exit, and edge cases. Also removes the check in TldrawScribble that prevented rendering when a scribble in 'stopping' state had fewer than 2 points, ensuring scribbles are rendered as long as they have points.
| // Calculate points to remove | ||
| const targetRemoved = Math.floor(easedProgress * this.totalPointsAtFadeStart) | ||
| const actuallyRemoved = this.totalPointsAtFadeStart - remainingPoints | ||
| const pointsToRemove = Math.max(1, targetRemoved - actuallyRemoved) |
There was a problem hiding this comment.
Ease-in fade curve not followed due to forced minimum
Low Severity
The Math.max(1, targetRemoved - actuallyRemoved) in tickGroupedFade forces at least 1 point to be removed every tick, which defeats the 'ease-in' easing curve. With ease-in (progress²), early ticks should remove very few or zero points (slow start, then accelerate). Instead, short scribbles fade linearly at ~1 point per tick, completing much faster than fadeDurationMs. For example, a 10-point scribble with a 500ms ease-in fade would complete in ~160ms (10 ticks × 16ms).
Inlines the logic from ScribbleSession directly into ScribbleManager, removing the ScribbleSession class and its related types and tests. Updates all usages in the LaserTool and its child states to use the new session ID-based API. Removes now-obsolete tests for ScribbleManager and laser tool behavior.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.
packages/editor/src/lib/editor/managers/ScribbleManager/ScribbleManager.ts
Show resolved
Hide resolved
|
Ok, did a bunch of last-mile work on this one.
On the code:
|
In order to provide better stroke termination for the laser tool, this PR adds a 'complete' state to the scribble lifecycle. This state represents scribbles that are done being drawn but not yet fading, allowing taper effects to be applied when the user lifts the pointer. This builds on the telestrator pattern introduced in #7681. ### Change type - [x] `improvement` ### Test plan 1. Select the laser tool and draw a stroke on the canvas 2. Lift the pointer to complete the stroke 3. Observe the stroke has proper taper at the end point 4. Verify the stroke fades out normally after the idle timeout ### API changes - Added `complete` to `TL_SCRIBBLE_STATES` enum - Added `ScribbleManager.complete(id)` method to mark a scribble as complete ### Release notes - Laser pointer strokes now have smoother endings with proper taper when lifting the pointer
In order to make the laser pointer behave like a telestrator (where all annotations remain visible until the user stops drawing), this PR adds session management to the ScribbleManager. Closes #7579.
Previously, each laser stroke segment would fade independently after a delay, creating a "trailing" effect. Now, all laser strokes in a drawing session persist together and fade simultaneously when the user stops drawing.
Before
After
pr-7681-walkthrough.mp4
API changes
ScribbleManager.endLaserSession()method to manually end the active laser sessionScribbleManager.isScribbleInLaserSession(scribbleId)method to check if a scribble belongs to the active sessionTldrawOptions.laserSessionTimeoutMsoption (default: 2000ms) - duration of inactivity before laser session endsTldrawOptions.laserMaxSessionDurationMsoption (default: 60000ms) - maximum duration for a laser sessionLaserTool.onExit()lifecycle method (callsendLaserSession()when exiting the tool)Change type
improvementTest plan
Release notes
Note
Introduces session-based scribbles and updates the laser tool to keep all strokes visible during a session and fade them together afterward.
ScribbleManagersession API:startSession,addScribbleToSession,addPointToSession,extendSession,stopSession,clearSession,isSessionActive; updates simple APIs (addScribble,addPoint,stop,reset) to work with sessionsScribbleSessionOptionseditor.options.laserFadeoutMs(default 500) and useslaserDelayMsas session idle timeoutLaserToolto manage a shared session across strokes; handles cancel/exit and reuse/new session creationScribbleManagerandLaserToolWritten by Cursor Bugbot for commit b865104. This will update automatically on new commits. Configure here.