Skip to content

feat(chart): pin the live edge - flick to leave, pull back on every step - #544

Merged
kirillDevPro merged 1 commit into
Moonbot-Tech:mainfrom
ThusMad:feat/chart-live-pin
Sep 13, 2026
Merged

feat(chart): pin the live edge - flick to leave, pull back on every step#544
kirillDevPro merged 1 commit into
Moonbot-Tech:mainfrom
ThusMad:feat/chart-live-pin

Conversation

@ThusMad

@ThusMad ThusMad commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

What & why

Navigating away from the live edge felt loose in three ways:

  • Live broke too easily. Any horizontal left drag past 20% of the plot width (ANCHOR_BREAK_PCT, floor 32 px) detached the chart, so a drag meant to move price often unhooked time as well.
  • The pull-back came late. Rejoining live was checked once, on mouse-up (snap_to_live_if_near in ChartInput::mouse_button), so the chart never caught while you were dragging back toward now.
  • A pan could walk into empty future, up to a whole window ahead of now.

The live edge now behaves like a pin:

  • Fast drag only. On a live view the left drag pans price, and time stays on the live edge until the drag flicks toward history: 1.9 logical px/ms over a 50 ms window (LiveHold in chartdx/input.rs). The drag then has to carry the chart past the rejoin radius plus 16 px before it lets go, and at that moment the chart jumps to where the pointer is.
  • Pull-back on every step. ChartView::pan_x_px rejoins live on any step that moves toward now and ends inside the radius — drags and Shift-wheel alike. Zoom keeps its own existing check. The mouse-up check is gone.
  • Radius stays a percentage, with a floor: max(5% of plot width, 40 px) (ChartView::live_rejoin_px), so a narrow stack pane still has a pull-back worth feeling.
  • No pan into the future. A pan stops at now. From history it lands on the live edge and rejoins; with the toolbar's Live off it stops exactly at now and stays manual.

Notable decisions

  • A step AWAY from now never rejoins, even inside the radius. That is the hysteresis that lets a drag leave the radius it starts in; without it the first pixel of a detach would snap straight back.
  • The flick is latched per hold. Once a flick is seen, the rest of the escape distance may be covered at any speed — the flick is the intent. Speed is measured over a window of at least 50 ms, so one coarse move event after a pause cannot read as a flick; a fast drag that is mostly vertical does not count either.
  • Speed is in logical pixels (scaled by ppp), the radius floor is in device pixels, matching the old ANCHOR_BREAK_MIN_PX convention in the same layer.
  • A view already off live pans at once. It used to need the same 20% of travel as a live view before X moved at all.
  • clamp_future_anchor stays, now only for a framed interval that ends near now (show_time_range can put the anchor slightly ahead). Such a view may pan back but a forward pan does not push it further. The is_ahead_of_now branch that suppressed the 3 s hold for views parked in the future is removed with the feature it served.
  • Unchanged: the 3-second auto-return after a pan (MANUAL_HOLD_MS), Shift-wheel pan leaving live without a flick, zoom behaviour, and the toolbar's persistent manual mode.
  • ChartInput::mouse_button keeps its signature and bool result so the four call sites stay as they are; no button transition changes a view now, and this is documented on the method.

Known limitations

  • Drawing ahead of the live edge is no longer reachable by panning. Figures already placed in the future stay where they are but cannot be scrolled to.
  • Not verified in a running build. The thresholds — 1.9 px/ms, 50 ms, 16 px, 40 px — are starting values, not tuned by hand against the real feel yet. They are named constants: LIVE_BREAK_SPEED, LIVE_BREAK_WINDOW_MS, LIVE_BREAK_HYSTERESIS_PX in chartdx/input.rs, LIVE_REJOIN_MIN_PX in view.rs.
  • Manual check: on a live chart drag slowly left/right — price moves, time stays live. Flick right — the chart detaches. Drag back toward now — it re-pins as it enters the radius, without releasing. Try to drag left past now — it stops.
  • FireTest not run.

Issues

None of the 17 open issues is touched by this change.

How to verify

cargo fmt --all -- --check
cargo clippy -p moon-chart -p moon-ui-gpui --all-targets
cargo test -p moon-chart
cargo test -p moon-ui-gpui

fmt --check exit 0 · clippy: no new findings — the ones reported inside the touched files (view.rs ensure_default_window / update_y, the pre-existing 8-argument wheel / mouse_button signatures, market.rs) are in code this PR does not change · tests: moon-chart 135 passed, moon-ui-gpui 1805 passed + theme_contract 331 passed, 0 failed.

New and reworked tests:

  • chartdx/input/tests.rs (new, 6): a slow drag never leaves live; a flick leaves once it clears the pull-back; one coarse event after a pause is not a flick; a fast vertical drag is not a flick; a flick toward the future does not break live; the break speed scales with the display.
  • view/tests.rs: a pan stops at the live edge (from live, from history, with Live off, and for a framed view ahead); a step toward now rejoins inside the radius; a step away never rejoins; the radius keeps its pixel floor on a narrow pane. The future-ceiling and zoom tests now start from a framed view parked ahead instead of a forward pan; the two tests that only covered the hold timer for views panned into the future are removed.

🤖 Generated with Claude Code

A live chart used to leave the live edge on any horizontal drag past 20% of
the plot width, rejoined only when the button came up within 5% of now, and
let a pan walk a whole window into empty future.

Leaving live now takes a flick toward history: 1.9 logical px/ms over a 50 ms
window, and the drag has to carry the chart past the rejoin radius plus 16 px
before it lets go, so the pull-back does not catch it on the next pixel. A
slower drag pans price only and time keeps following.

The pull-back runs inside ChartView::pan_x_px on every step that moves toward
now, for drags and Shift-wheel alike, instead of once on mouse-up; a step away
from now never rejoins. The radius is max(5% of the plot width, 40 px).

A pan stops at now. A framed interval already ahead may come back but not go
further, so clamp_future_anchor stays for that case only.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@kirillDevPro
kirillDevPro merged commit 6752525 into Moonbot-Tech:main Sep 13, 2026
6 checks passed
@ThusMad
ThusMad deleted the feat/chart-live-pin branch September 13, 2026 14:34
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.

2 participants