Skip to content

Fill Settings rows at once and repaint frames a batch update held back - #222

Merged
ben-dev-au merged 1 commit into
mainfrom
fix/blank-settings-screen
Oct 21, 2026
Merged

ben-dev-au merged 1 commit into
mainfrom
fix/blank-settings-screen

Conversation

@ben-dev-au

Copy link
Copy Markdown
Owner

Two Textual 8.2.8 behaviours left the screen out of date, without raising an error.

Blank Settings screen ("box, no rows")

  • SettingsList.set_items mounted empty rows and filled them in a call_after_refresh.
  • Textual queues that callback on the top screen and discards the queue when that screen closes.
  • After a reindex, _refresh_open_settings rebuilds the Settings screens under the indexer modal, so closing the modal could drop every fill.
  • Rows are now filled in the call. A width not yet laid out is corrected by on_resize.

Selection one step behind until the next arrow key

  • While a batch update is open, a visible screen's paint tick skips its frame. When the batch closes, Textual re-arms only the App, so the frame waits for the next message to that screen, usually the next keypress.
  • Markdown opens a batch on every preview build, including background warming, so both the results pane and Settings were affected.
  • FNDApp._end_batch now prompts every visible screen to paint what it is holding, including a screen behind a see-through modal.
  • check_idle rather than delay_update's screen.refresh(): it paints only what is already dirty, with no full redraw each time Markdown closes a batch.

Evidence

  • Live tmux probe. Flags a screen with a pending paint, a paused timer and no open batch. With keys 0.3 to 2.5s apart, unfixed runs showed 3 to 7 stale frames each and fixed runs showed 0. Fast key pacing hides the bug, because each key re-arms the screen.
  • Negative controls. Each new test fails with its fix removed:
    • Rows blank with call_after_refresh restored.
    • Frame held with no override.
    • Frame behind a see-through modal held when only the top screen is prompted.
  • make batch-close:
    • ruff, pyright and the suite: 6364 passed, 5 skipped.
    • The tmux harness: 12 scenarios passed, 1 skipped (it needs the real corpus).

Not in this PR

The same call_after_refresh loss can drop two main-screen callbacks when the indexer modal closes: _do_reflow_sidebar and the filters-panel scroll_to_line. Fixing that needs an app-level change, to be proposed separately.

Two Textual 8.2.8 behaviours left the screen out of date with no error.

Blank Settings screen ("box, no rows"):
- `SettingsList.set_items` mounted empty rows and filled them in a
  `call_after_refresh`. Textual queues that callback on the TOP screen
  and discards the queue when that screen closes. After a reindex,
  `_refresh_open_settings` rebuilds the Settings screens under the
  indexer modal, so closing the modal could drop every fill.
- Rows are now filled in the call. A width not yet laid out is corrected
  by `on_resize`.

Selection one step behind until the next arrow key:
- While a batch update is open, a visible screen's paint tick skips its
  frame, and Textual re-arms only the App when the batch closes. The
  frame then waits for the next message to that screen, usually the next
  keypress. Markdown opens a batch on every preview build, including
  background warming, so both the results pane and Settings were hit.
- `FNDApp._end_batch` now prompts every visible screen, including one
  behind a see-through modal, to paint what it is holding.
- Measured in a real terminal with keys 0.3 to 2.5s apart: 3 to 7 stale
  frames per run without the fix, none with it.
@coderabbitai

coderabbitai Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: b4f2d423-7bee-441e-a026-8eec84588922
📥 Commits

Reviewing files that changed from the base of the PR and between 583406b and b8ef8b4.

📒 Files selected for processing: 4
  • fnd/tui/app.py
  • fnd/tui/settings_screen.py
  • tests/test_a_covered_settings_list_labels_every_row.py
  • tests/test_a_repaint_held_by_a_batch_lands_when_it_ends.py

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

📝 Walkthrough

Settings rows now initialise synchronously. When a batch update ends, the app checks idle state for background and active screens. Regression tests cover rendered row labels and repaint completion.

Changes: Settings screen refresh

Layer / File(s) Summary
Synchronise settings row initialisation
fnd/tui/settings_screen.py, tests/test_a_covered_settings_list_labels_every_row.py
SettingsList.set_items now calls _init_cursor directly after mounting rows. The test checks that every retained item has a rendered row with its label.
Resume repaint checks after batch updates
fnd/tui/app.py, tests/test_a_repaint_held_by_a_batch_lands_when_it_ends.py
FNDApp._end_batch checks idle state for background and active screens when the batch counter reaches zero. Tests check repaint completion on the active screen and behind a translucent modal.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~15 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to b8ef8

The settings rows and batched repaints appear ready to merge after normal checks.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 54.55% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 11 functions across 4 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title identifies both main changes: synchronous Settings row filling and repainting frames held by a batch update. It is specific and related to the changeset, although the wording is slightly awk…
Description check Passed The description directly explains the two Textual behaviours addressed, the implemented fixes, validation results, and the scope excluded from this pull request.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Title check

Explanation

The title identifies both main changes: synchronous Settings row filling and repainting frames held by a batch update. It is specific and related to the changeset, although the wording is slightly awkward.

✨ Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

A rabbit watched the settings rows appear,
Each label settled, crisp and clear.
The batch let go; the screens could paint,
No waiting mouse, no needed saint.
I hop through rows and nibble greens.

Comment @coderabbitai help to get the list of available commands.

@ben-dev-au
ben-dev-au merged commit 095cdb8 into main Oct 21, 2026
22 checks passed
@ben-dev-au
ben-dev-au deleted the fix/blank-settings-screen branch October 21, 2026 13:29
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