feat(tui): generate screen rewrite + cross-screen nav polish #129

Merged
charles merged 9 commits from tui/generate-rewrite-and-nav into main 2026-04-14 19:21:14 +00:00
Collaborator

Summary

Major TUI improvements across the gallery, model browser, entities, and (especially) the generate screen. Bumps to ratatui 0.30 to unlock the rat-widget ecosystem for proper textareas and pickers.

What's in this PR

  • Masonry grid layout with column-balanced cell heights computed from real image aspect ratios
  • Scroll virtualization — only visible cells render and load images
  • Image protocols evicted off-screen to bound memory
  • Resolution label replaces prompt text in cells
  • Layout + image cache invalidate on resize

Model browser

  • Per-result thumbnails (downloaded async to ~/.cache/loom/thumbs/)
  • 6-row card layout with name + kind + downloads
  • Fix install subdir: backend expects Lora, Stable-diffusion, ControlNet, adetailer (no models/ prefix)

Entities

  • Reference image displayed in detail panel (capped 40% height)
  • Two scrollable, focusable prompt boxes (prompt + negative)
  • Three-column focus navigation (kind ↔ list ↔ detail)
  • Cyan border highlights focused column / active prompt field

Generate (the big one)

  • rat-widget TextArea for prompts — real cursor, arrow keys, selection, clipboard, word wrap
  • Picker overlays for model + sampler (fuzzy search, ✓ marker for current)
  • Three-column params panel instead of cramped one-line bar
  • Mode tabs are focusable — Left/Right switches mode
  • Layout uses percentage heights so prompts grow with the viewport

Navigation model (app-wide)

  • Startup focus on the sidebar
  • Arrows navigate within the current container only (don't escape)
  • Tab / Shift-Tab switch between sidebar and content
  • Enter activates / drills in
  • Esc goes back
  • Sidebar-focused: keys no longer leak into content textareas
  • Generate fields: Up/Down navigate, Left/Right adjust numeric values (Ctrl ±10)

Misc

  • Removed stderr fmt tracing layer that bled through the alternate screen
  • Bumped ratatui 0.29 → 0.30 and ratatui-image 3 → 10

Test plan

  • Sidebar focused at startup; arrows stay in sidebar
  • Tab from sidebar enters content; Tab from content returns to sidebar
  • Generate: typing in prompt has cursor + arrow movement
  • Generate: Enter on Model opens picker, fuzzy search works, selection updates value
  • Generate: Left/Right on Steps changes value ±1, Ctrl ±10
  • Generate: Mode tabs focusable, Left/Right switches T2i ↔ I2i ↔ etc.
  • Gallery: masonry shows variable-height cells, scrolls smoothly with 100+ images
  • Gallery: terminal resize reflows the masonry
  • Model browser: thumbnails appear next to results
  • Model browser: install completes (no "Invalid subdir" error)
  • Entities: reference image renders, prompt boxes scroll independently

🤖 Generated with Claude Code

## Summary Major TUI improvements across the gallery, model browser, entities, and (especially) the generate screen. Bumps to ratatui 0.30 to unlock the rat-widget ecosystem for proper textareas and pickers. ## What's in this PR ### Gallery - Masonry grid layout with column-balanced cell heights computed from real image aspect ratios - Scroll virtualization — only visible cells render and load images - Image protocols evicted off-screen to bound memory - Resolution label replaces prompt text in cells - Layout + image cache invalidate on resize ### Model browser - Per-result thumbnails (downloaded async to `~/.cache/loom/thumbs/`) - 6-row card layout with name + kind + downloads - Fix install subdir: backend expects `Lora`, `Stable-diffusion`, `ControlNet`, `adetailer` (no `models/` prefix) ### Entities - Reference image displayed in detail panel (capped 40% height) - Two scrollable, focusable prompt boxes (prompt + negative) - Three-column focus navigation (kind ↔ list ↔ detail) - Cyan border highlights focused column / active prompt field ### Generate (the big one) - **rat-widget TextArea** for prompts — real cursor, arrow keys, selection, clipboard, word wrap - **Picker overlays** for model + sampler (fuzzy search, ✓ marker for current) - **Three-column params panel** instead of cramped one-line bar - **Mode tabs are focusable** — Left/Right switches mode - Layout uses percentage heights so prompts grow with the viewport ### Navigation model (app-wide) - Startup focus on the sidebar - **Arrows** navigate within the current container only (don't escape) - **Tab / Shift-Tab** switch between sidebar and content - **Enter** activates / drills in - **Esc** goes back - Sidebar-focused: keys no longer leak into content textareas - Generate fields: Up/Down navigate, Left/Right adjust numeric values (Ctrl ±10) ### Misc - Removed stderr fmt tracing layer that bled through the alternate screen - Bumped ratatui 0.29 → 0.30 and ratatui-image 3 → 10 ## Test plan - [ ] Sidebar focused at startup; arrows stay in sidebar - [ ] Tab from sidebar enters content; Tab from content returns to sidebar - [ ] Generate: typing in prompt has cursor + arrow movement - [ ] Generate: Enter on Model opens picker, fuzzy search works, selection updates value - [ ] Generate: Left/Right on Steps changes value ±1, Ctrl ±10 - [ ] Generate: Mode tabs focusable, Left/Right switches T2i ↔ I2i ↔ etc. - [ ] Gallery: masonry shows variable-height cells, scrolls smoothly with 100+ images - [ ] Gallery: terminal resize reflows the masonry - [ ] Model browser: thumbnails appear next to results - [ ] Model browser: install completes (no "Invalid subdir" error) - [ ] Entities: reference image renders, prompt boxes scroll independently 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(tui): gallery grid thumbnail images via ratatui-image
All checks were successful
qa / qa (pull_request) Successful in 5m0s
6d89718c27
Render image thumbnails in gallery grid cells using ratatui-image
StatefulProtocol. Each visible cell gets a lazily-loaded image from the
thumbnail path (falling back to full image). Grid cells are now 10 rows
tall (border + 7 image rows + 1 label + border) to accommodate the
thumbnail preview.

Per-cell image state is cached in HashMap<usize, StatefulProtocol> and
cleared when items reload from storage.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the uniform grid with a masonry (Pinterest-style) layout where
cell heights are computed from actual image aspect ratios using terminal
font metrics from ratatui-image's Picker. Images are pre-resized to
exact cell pixel dimensions for zero-padding fill.

- Shortest-column assignment algorithm distributes items evenly
- Scroll virtualization: only render/load images in the viewport
- Off-screen image protocols evicted to bound memory
- Navigation reworked for variable-height cells (nearest-by-midpoint)
- Layout + image cache invalidated on terminal resize
- Resolution label replaces prompt text in grid cells

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add preview_url to ResultCard, download thumbnails async to cache dir
- Render results as cards with thumbnail + name/kind/downloads
- Fix subdir_for_type: use bare names (Lora, Stable-diffusion) matching
  the Forge extension's ALLOWED_SUBDIRS, not models/-prefixed paths

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Show reference_image in detail panel (capped at 40% height)
- Two word-wrapped, scrollable prompt boxes (prompt + negative)
- Three-column focus navigation: kind ↔ list ↔ detail via arrows
- Cyan border highlights focused column and active prompt field
- j/k scrolls focused prompt, Tab switches between them

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- App: Left arrow (unconsumed) returns to sidebar like Esc
- Generate: Up arrow in prompt fields navigates to previous field
- Generate: Up/Down in numeric fields adjusts values (±1 or ±0.5)
- Remove stderr fmt tracing layer that bled into alternate screen

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pull in the split-crate architecture from ratatui 0.30 (ratatui-core,
ratatui-widgets, ratatui-crossterm) to unlock the rat-widget ecosystem.

API changes absorbed:
- StatefulImage::new() takes no args (was new(None))
- StatefulImage state borrow no longer needs &mut
- Screen trait drops Send bound (rat-widget state uses Rc internally)
- loom-cli adds B::Error: Send + Sync bound for terminal.draw()?

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replaces the cramped single-line param bar and push/pop string
prompt fields with proper widgets.

Prompt + negative:
- rat-widget TextArea state per field with full cursor + selection
- Word-wrapped, scrolls within its rect
- Up/Down only escape to next/prev field at top/bottom line

Model + sampler:
- Enter on the field opens a fuzzy-search overlay
- Lists pulled async from PluginBridge::list_models / list_samplers
- Reusable StringPickerState in components/string_picker.rs
- Wired through new OverlayKind::ModelPicker / SamplerPicker and
  AppAction::SetModel / SetSampler

Layout:
- Mode tabs become focusable (Up/Down navigate to them, Left/Right
  switch mode)
- Three-column params panel (model+sampler · sampling · seed+batch)
- Prompts use percentage heights so they grow with the viewport

Navigation:
- Up/Down navigate between fields
- Left/Right adjust numeric values (Ctrl ±10)
- Tab/Shift-Tab reserved for global container switching
- Enter activates pickers; Esc returns to sidebar

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
test(tui): adapt integration tests to new focus model
Some checks failed
qa / qa (pull_request) Has been cancelled
f6048575c4
Startup focus is now the sidebar; tests that drive the content area
must call `app.focus_main()` first. The arrow-key test also moves to
KeyCode::Down since Tab is now reserved for container switching.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
chore: merge main
All checks were successful
qa / qa (pull_request) Successful in 21m25s
890dfac1f0
Resolved conflict in crates/loom-tui/src/screens/gallery.rs — our
masonry rewrite supersedes the thumbnail-image changes from #121,
and all thumbnail rendering remains intact within the masonry cells.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
charles deleted branch tui/generate-rewrite-and-nav 2026-04-14 19:21:15 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/loom!129
No description provided.