Skip to content

island: ease the OSC 9;4 progress bar in and out - #1868

Open
aymanbagabas wants to merge 1 commit into
raphamorim:mainfrom
aymanbagabas:progress-bar-smooth-transitions
Open

island: ease the OSC 9;4 progress bar in and out#1868
aymanbagabas wants to merge 1 commit into
raphamorim:mainfrom
aymanbagabas:progress-bar-smooth-transitions

Conversation

@aymanbagabas

Copy link
Copy Markdown
Contributor

The progress bar from OSC 9;4 (printf '\x1b]9;4;3\x07') transitions like a switch rather than an animation. Three separate discontinuities:

The indeterminate block appears at its full 20% length. Nothing grows in, it is simply there on the first frame after the report arrives.

It then slides between 0 and width - bar_width, so it decelerates into nothing at the right edge and teleports back to the left on the next cycle. Every 2 seconds the bar jumps the full width of the window.

Dismissal (OSC 9;4;0, or the 15 second stale-bar timeout) cleared the state outright, so the bar vanished mid-stride on whatever frame the report landed.

The block is now a head and a tail sweeping at the same speed with the tail lagging by a fixed edge time (400ms, the time to cover its own length). That single relationship produces the grow-in for free: while the head has travelled less than the edge time the tail is still pinned at the left edge, so the block emerges from zero and reaches its designated length before it translates. The right-edge clamp is gone, draw_progress_segment wraps the span with rem_euclid and splits it into two rects when it straddles the edge, so exactly as much bar as leaves on the right is entering on the left. The bar never jumps.

Dismissal arms progress_exit_at instead of clearing the fields. The head freezes where it was and the tail runs into it over the same 400ms, so the block shrinks away in place; the fields are released once the shrink completes. A report arriving mid-exit cancels the shrink and grows the bar back in. Determinate states (Set, Error, Pause) get the same treatment against their left edge, growing out of it on arrival and retracting into it on dismissal.

needs_redraw now covers the grow-in and the shrink-out, not just the indeterminate travel, so those frames actually tick. The existing heartbeat handling from #1509 is untouched: progress_started_at still moves only on a real state transition, so a TUI reporting OSC 9;4;3 every 100ms does not restart the phase.

The animation is linear, no easing curves, and the geometry is a pure function so it is covered by a unit test rather than by eye: grow, travel, wrap and shrink are each asserted at known timestamps. progress_remove_clears_all_progress_state became progress_remove_shrinks_out_then_clears_all_progress_state, since immediate clearing is exactly the behaviour being replaced.

Release Notes:

  • Improved the OSC 9;4 progress bar animation: the indeterminate bar now grows in from the edge, wraps around instead of jumping back, and shrinks away when dismissed.

The indeterminate bar appeared at its full length, slid to the right edge
and snapped back, and vanished the instant the report was removed. Every
transition was on/off.

Model the block as a head and a tail sweeping at the same speed, the tail
lagging by a fixed edge time: it grows out of nothing at the left edge,
reaches its designated length, then travels. Drop the right-edge clamp so
whatever slides past the right edge is drawn re-entering on the left.

Dismissal (OSC 9;4;0 or the stale-bar timeout) now arms an exit instead of
clearing state: the head freezes, the tail runs into it, and the fields are
released once the shrink finishes. Determinate bars grow out of and retract
into the left edge over the same duration.

Signed-off-by: Ayman Bagabas <ayman.bagabas@gmail.com>
@aymanbagabas
aymanbagabas force-pushed the progress-bar-smooth-transitions branch from 6c43d0e to 320b996 Compare August 12, 2026 21:28
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