Skip to content

CPLAT-9497: preserve preview selection across detail modes#30

Merged
gavin-jeong merged 2 commits intomasterfrom
CPLAT-9497-preview-selection-and-artifact-grouping
Apr 21, 2026
Merged

CPLAT-9497: preserve preview selection across detail modes#30
gavin-jeong merged 2 commits intomasterfrom
CPLAT-9497-preview-selection-and-artifact-grouping

Conversation

@gavin-jeong
Copy link
Copy Markdown
Collaborator

@gavin-jeong gavin-jeong commented Apr 20, 2026

JIRA: https://sendbird.atlassian.net/browse/CPLAT-9497

Summary

Preview UX (original scope):

  • make compact preview selectable using the same fold-state model as the other preview modes
  • keep artifacts grouped near their related turns in standard preview instead of appending a detached artifact section
  • preserve the nearest logical block when switching compact, standard, and verbose preview modes

Kitty inline image rendering (added):

  • ccx images picker now renders the focused image inline (was text-only)
  • fix churning temp files on every render — decoded images are now persisted to ~/.claude/image-cache/<sessionID>/<pasteID>.png so Kitty sees a stable path
  • re-encode JPEG/GIF sources to PNG because Kitty f=100 is PNG-only
  • tmux window-switch handling: promote allow-passthrough to all so clear sequences can escape a hidden pane, and poll #{window_active} on a 250ms tick to detect window switches (tmux does not forward focus events for intra-session window changes)

Test plan

  • go test ./... (366 passing)
  • go test ./internal/tui -run 'TestCompactPreviewBuildsSelectableFoldState|TestCompactPreviewArrowKeysMoveBlockSelection|TestModeSwitchPreservesNearestSelection|TestBuildStandardEntryPlacesArtifactsNearRelatedText|TestRenderStandardPreviewShowsArtifactNearRelatedTurn'
  • go test ./internal/cli -run Kitty
  • go test ./internal/session -run ExtractImageToTempJPEG
  • manual: preview selection continuity across detail mode switches in the TUI
  • manual: ccx images renders inline image, survives pane resize, clears on tmux window switch
  • manual: conv view image-block selection renders via Kitty across multiple image entries

Make compact preview selectable, group standard preview artifacts near their related turns, and preserve the nearest logical block when switching compact, standard, and verbose detail modes.
The standalone `ccx images` picker had zero Kitty integration, so the
inline image never rendered outside the conversation split. In addition,
two bugs made Kitty rendering unreliable even where it did fire:

- Every render invoked ExtractImageToTemp, which wrote a fresh temp file
  per call. Hundreds of stale jpegs piled up and Kitty never got a
  stable file path to load. Fixed by persisting the decoded image into
  the shared ~/.claude/image-cache/<sessionID>/<pasteID>.png so the
  path is stable across renders, re-encoding non-PNG sources (JPEG/GIF)
  into PNG to match Kitty's f=100 protocol.

- tmux `allow-passthrough on` drops DCS passthrough from a hidden pane,
  so a clear sequence emitted after a window switch never reaches the
  terminal and the image lingers over the next window. Promote the
  option to `all` during kitty.Supported() so invisible-pane clears get
  through, then poll tmux #{window_active} on a 250ms tick (both in the
  main TUI and the standalone picker) to detect window switches — tmux
  does not forward focus events for intra-session window changes, so
  BlurMsg alone is not enough. The poll writes the clear sequence to
  os.Stdout the instant we transition to invisible.

Also: picker now handles tea.WindowSizeMsg with InvalidatePaneOffset(),
and the conv view kittyImageLayer path was simplified to share a single
kittyImagePath resolver that always goes through the persistent cache.

Tests added:
- internal/cli/picker_kitty_test.go: image-only kind, blur clear, happy
  draw, missing-file clear.
- internal/session/image_cache_test.go: JPEG source re-encodes as PNG
  and returns a stable cache path across calls.
Copy link
Copy Markdown

@jinsekim jinsekim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@gavin-jeong gavin-jeong merged commit 3879b70 into master Apr 21, 2026
3 checks passed
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.

3 participants