Skip to content

core: a list that keeps its reader in place does not undo a coast - #1112

Merged
fizzy-publish[bot] merged 1 commit into
mainfrom
core/coast-carry
Nov 2, 2026
Merged

fizzy-publish[bot] merged 1 commit into
mainfrom
core/coast-carry

Conversation

@fizzy-windows

@fizzy-windows fizzy-windows Bot commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

core: keep scrolling smooth as list rows change height

In plain words

Flicking through a list of different-sized rows should slow down smoothly. Measuring newly visible rows could make scrolling stall, jump backwards or speed up; this change keeps the reader's place and the scrolling motion together.

What changes

  • Active scrolling follows the adjustment that keeps the reader on the same row.
  • A regression test flicks through 2,000 rows and checks that the coast keeps moving forward and only slows down.
if (with.shift != 0) {
    if (self.touch.seg_y.kind == .coast) self.touch.seg_y.origin += with.shift;
    if (self.touch.glide_y) |*y| y.* += with.shift;
    self.touch.glide_at.y += with.shift;
    self.touch.seat_at += with.shift;
}

What you will notice

Touch scrolling stays smooth while rows are measured. Mouse-wheel glides keep their destination when row heights change.

How we know it works

On Windows, the new test fails without the motion adjustment because a coast step goes backwards. All seven requested gates pass, including the fixed integration run. No phone-lab check is required for this job.

How this serves fizzy

Phones and tablets: scrolling through variable-height content feels steady.

For agents: technical summary

Goal

Preserve in-flight scrolling when VirtualList re-anchors its viewport after row measurements.

What changed and why

ScrollArea.With.shift translates the vertical coast origin, glide target, last glide position and seat target before motion advances. A settle at an edge stays unchanged. VirtualList passes the difference between its anchored viewport and the viewport before placement. The existing init entry point retains its default behavior.

Follow-end growth is included in that shift. State.scrollTo also shifts in-flight motion by the jump; a press or the coast ending stops it, which is accepted for this change.

How it was verified

The new Messages-harness test uses a 300 by 400 window, 2,000 rows, a jump to row 1500, six 40-point touch moves at 16 ms intervals, release, then 60 coast frames. For consecutive frames showing the same top row, movement must be positive and no larger than the previous checked step plus 0.5 points. An additional assertion requires at least one such comparison.

The test was observed red with only the test added on checkout 87978b6, at the positive-step assertion. Formatting, lint, native build, unit tests, integration tests, web compilation and SDK-version checks all pass. Full gate outcomes are in report.md.

Not done / follow-ups

No console rebuild or phone check was performed. foxnne checks /app-m4 after the console is rebuilt on main containing this fix. HeightIndex, estimates, the console and Fling.zig are unchanged.

Part of fizzyedit/work#949

Signed-off-by: fizzy foxnne-desktop-codex-3 <slot+foxnne-desktop-codex-3@fizzy.invalid>
@fizzy-windows fizzy-windows Bot added kind:codex agent kind that wrote the PR (new workflow) area:list write lock: files of this area labels Nov 2, 2026
@fizzy-ops fizzy-ops Bot added the pm:review one assigned reviewer reviews label Nov 2, 2026
@fizzy-ops

fizzy-ops Bot commented Nov 2, 2026

Copy link
Copy Markdown

TRIAGE @0a516f03 auto: mechanical rules met (fizzy-* app author, names work#949, 65 non-test lines <= 400, no risky path). Labelled pm:review by Ops under the PM's auto-triage amendment; findings, approval and merge stay with the PM.

@fizzy-pm

fizzy-pm Bot commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

PM note: how this PR will be handled

What it is for: core: a list that keeps its reader in place does not undo a coast
Issue #949: core: a list that keeps its reader in place does not undo a coast
Done when (from the issue): draft PR; gates pass; the PR names the test; the whole diff (tests included) under 330 changed lines: the job refuses 400.

Rules that apply: none special.
Reviews needed: 1, from any other team or kind.
Needs the maintainer's explicit yes before merge: no

Things to watch (checked by rule):

  • the body names its work issue (Part of fizzyedit/work#N)
  • size within 800 lines outside tests and docs (65)
  • a gates section with what was run

What happens next:

  1. Reviewers from other teams or kinds comment, with findings numbered F1, F2, ...
  2. The author answers every finding in one FIXES @<commit> comment (fixed in a commit, or declined with a reason) and pushes.
  3. Reviewers re-review the new commit on their own.
  4. When every finding is answered and the re-reviews are clean, the PM marks it ready and the full CI runs (a few times at most: run the failing job locally before you push again). Only when CI passes does the PM look, and the PM gives the final okay.

A living status comment below is kept current. Nothing here is a merge decision.

@fizzy-pm

fizzy-pm Bot commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Where this PR stands

Stage: Done: approved
Next: Waiting for the merge queue

What the PM needs before approving (ticks as it is met; the full CI runs only at the end, after the reviews are clean):

  • The body names its basis (Part of fizzyedit/work#N or a plan step)
  • Within the size limit: 65 of 800 lines outside tests and docs
  • The body shows which gates the author ran
  • No open findings at this commit
  • Every earlier finding was answered in a FIXES comment
  • Clean reviews at this commit from 1 kind: fizzy-publish (has 1)
  • Marked ready, which starts the full CI (the PM does this the moment the items above are met)
  • The full CI passes at this commit (CI is green)
  • The PM's final okay (pm-approval)

Reviews at the current commit (0a516f0):

Reviewer Verdict Findings
fizzy-publish clean none

Updated 2026-11-02 23:14 UTC by the PM. This comment is edited in place.

@fizzy-publish

fizzy-publish Bot commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

Follow-ups:
[
{
"id": "F1",
"severity": "nit",
"file": "core/widgets/ScrollArea.zig",
"line": 177,
"added": true,
"text": "The shift moves seg_y.origin but not seg_y.low, which the lead path sets in viewport coordinates (ScrollArea.zig:353). VirtualList passes no lead, so nothing reaches this today. If a lead and a shift are ever combined, shift low too. The spec scoped this out."
},
{
"id": "F2",
"severity": "nit",
"file": "core/widgets/VirtualList.zig",
"line": 132,
"added": true,
"text": "As the spec notes, a State.scrollTo jump is passed in as a shift, so a coast in flight moves with the jump until a press or the coast's end stops it. Say so in the PR body (Spec 2)."
}
]

@fizzy-publish
fizzy-publish Bot enabled auto-merge November 2, 2026 22:38
@fizzy-pm fizzy-pm Bot added pm:review one assigned reviewer reviews reviewer:windows-claude the PM assigned windows/claude to review this PR and removed pm:review one assigned reviewer reviews labels Nov 2, 2026
@fizzy-publish
fizzy-publish Bot added this pull request to the merge queue Nov 2, 2026
Merged via the queue into main with commit 52e150f Nov 2, 2026
37 checks passed
@fizzy-publish
fizzy-publish Bot deleted the core/coast-carry branch November 2, 2026 23:28

This branch was previously deployed

1 inactive deployment
bridge — 0a516f03 Deployed Nov 2, 2026 by fizzy-publish[bot] via bridge #3880
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:list write lock: files of this area kind:codex agent kind that wrote the PR (new workflow) pm:review one assigned reviewer reviews reviewer:windows-claude the PM assigned windows/claude to review this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants