detached 488efa2

fix(session): repaint switched session after CNS

commit
488efa266beebd093bdde9b797019d3300130bd1
author
brice · · 2026-07-03 16:23 UTC
parent
b60ef98
signature
GPG VerifiedCD88F9E564E0102646FB6077A1A07C7C7C3E349D · arch-gpg Verified for the committer email
2 files · +11 -4
M internal/usecase/daemon/palette_test.go +8 -3
@@ -61,8 +61,12 @@ func TestPaletteCNSPromptsForSessionNameThenCreatesAndSwitches(t *testing.T) {
6161 require.Contains(t, string(promptOutput.Data), "Create session")
6262
6363 d.handleInput(sess, ac, []byte("scratch\r"))
64- repaint := awaitFrame(t, sends, ports.MsgOutput)
65- repaintOutput, err := ports.UnmarshalOutput(repaint.Payload)
64+ // The submit first paints the newly attached session while the prompt is
65+ // still open, then handlePromptInput closes the prompt and repaints the
66+ // client's current session. The final frame must be for the new session.
67+ awaitFrame(t, sends, ports.MsgOutput)
68+ finalRepaint := awaitFrame(t, sends, ports.MsgOutput)
69+ finalOutput, err := ports.UnmarshalOutput(finalRepaint.Payload)
6670 require.NoError(t, err)
6771 require.False(t, ac.promptActive())
6872 require.Equal(t, 2, sessionCount(d))
@@ -73,7 +77,8 @@ func TestPaletteCNSPromptsForSessionNameThenCreatesAndSwitches(t *testing.T) {
7377 require.Equal(t, "scratch", newSess.name)
7478 require.False(t, newSess.ephemeral)
7579 require.Same(t, ac, newSess.client)
76- require.Contains(t, string(repaintOutput.Data), "scratch")
80+ require.Contains(t, string(finalOutput.Data), "scratch")
81+ require.NotContains(t, string(finalOutput.Data), "Create session")
7782 }
7883
7984 func TestPaletteCommandNoopRepaintsAfterClose(t *testing.T) {
@@ -61,8 +61,12 @@ func TestPaletteCNSPromptsForSessionNameThenCreatesAndSwitches(t *testing.T) {
61 require.Contains(t, string(promptOutput.Data), "Create session")61 require.Contains(t, string(promptOutput.Data), "Create session")
62 62
63 d.handleInput(sess, ac, []byte("scratch\r"))63 d.handleInput(sess, ac, []byte("scratch\r"))
64- repaint := awaitFrame(t, sends, ports.MsgOutput)64+ // The submit first paints the newly attached session while the prompt is
65- repaintOutput, err := ports.UnmarshalOutput(repaint.Payload)65+ // still open, then handlePromptInput closes the prompt and repaints the
66+ // client's current session. The final frame must be for the new session.
67+ awaitFrame(t, sends, ports.MsgOutput)
68+ finalRepaint := awaitFrame(t, sends, ports.MsgOutput)
69+ finalOutput, err := ports.UnmarshalOutput(finalRepaint.Payload)
66 require.NoError(t, err)70 require.NoError(t, err)
67 require.False(t, ac.promptActive())71 require.False(t, ac.promptActive())
68 require.Equal(t, 2, sessionCount(d))72 require.Equal(t, 2, sessionCount(d))
@@ -73,7 +77,8 @@ func TestPaletteCNSPromptsForSessionNameThenCreatesAndSwitches(t *testing.T) {
73 require.Equal(t, "scratch", newSess.name)77 require.Equal(t, "scratch", newSess.name)
74 require.False(t, newSess.ephemeral)78 require.False(t, newSess.ephemeral)
75 require.Same(t, ac, newSess.client)79 require.Same(t, ac, newSess.client)
76- require.Contains(t, string(repaintOutput.Data), "scratch")80+ require.Contains(t, string(finalOutput.Data), "scratch")
81+ require.NotContains(t, string(finalOutput.Data), "Create session")
77 }82 }
78 83
79 func TestPaletteCommandNoopRepaintsAfterClose(t *testing.T) {84 func TestPaletteCommandNoopRepaintsAfterClose(t *testing.T) {
M internal/usecase/daemon/prompt.go +3 -1
@@ -79,7 +79,9 @@ func (d *Daemon) handlePromptInput(ac *attachedClient, data []byte) {
7979 return
8080 }
8181 d.closePrompt(ac)
82- d.paint(sess, ac, true)
82+ if current := ac.currentSession(); current != nil {
83+ d.paint(current, ac, true)
84+ }
8385 return
8486 }
8587 if exit {
@@ -79,7 +79,9 @@ func (d *Daemon) handlePromptInput(ac *attachedClient, data []byte) {
79 return79 return
80 }80 }
81 d.closePrompt(ac)81 d.closePrompt(ac)
82- d.paint(sess, ac, true)82+ if current := ac.currentSession(); current != nil {
83+ d.paint(current, ac, true)
84+ }
83 return85 return
84 }86 }
85 if exit {87 if exit {

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 12

Tags 11

↑↓ moveenter openesc close