Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/changes/unreleased/1628-task-room-keyboard.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
kind: fixed
title: Opening a task room gives its note box the keyboard
pr: 1628
surface: [chat, docs]
invalidates:
- "Opening a task with alt+t then Enter used to leave the roster holding the keyboard. A note appeared in the task's box but Enter reopened the row instead of sending it. Opening the room now releases roster focus, including the narrow overlay, so Enter sends the note to that task. Alt+t still returns to roster navigation."
---
4 changes: 4 additions & 0 deletions internal/manual/chat/keys.md
Original file line number Diff line number Diff line change
Expand Up @@ -2455,6 +2455,10 @@ ink once this conversation has spent four fifths of its own `per conversation` l

## Keys in the task roster and inside a room

Opening a task's room gives the keyboard to that room. For a task that accepts
notes, type one and press `enter` to send it; you do not need to press `alt+t` again first.
Use `alt+t` when you want to navigate the roster again.

**While the task roster holds the keyboard** (`alt+t`, `opt+t`): `esc` gives the keyboard
back · `up`/`down` move over the needs-you band, the group headings and the tasks ·
`enter` opens a task's room, opens or folds a group on its heading, and opens a band row's
Expand Down
11 changes: 10 additions & 1 deletion internal/tui3/room.go
Original file line number Diff line number Diff line change
Expand Up @@ -628,6 +628,9 @@ const roomTail = 120
// — and three copies of the same eight fields is three chances for the fourth
// one to be built wrong.
func (a *app) newRoom(id uint64, title string) *taskRoom {
// Opening a task hands its page the keyboard as well as the composer.
// Otherwise the roster keeps Enter while typed notes reach the room.
a.railTake(false)
// Replacing a view must release its subscription just as Escape does.
// Leaving the old lane open does not keep useful work running; it leaks a reader.
a.closeRoom()
Expand Down Expand Up @@ -1207,7 +1210,13 @@ func (a *app) openRoomFor(id uint64, title string) {
// pressed: the read may come back after the rail has been redrawn, and an
// absent page still opens exactly what this gesture chose.
func (a *app) openRailRoom(node *taskNode) tea.Cmd {
if node == nil || a.roomStandingOn(node) {
if node == nil {
return nil
}
if a.roomStandingOn(node) {
// Selecting the open room returns to its existing draft without
// replacing the page or its subscription.
a.railTake(false)
return nil
}
id, title, run, part := node.id, node.title, node.run, node.node
Expand Down
38 changes: 38 additions & 0 deletions internal/tui3/roomfocus_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package tui3

import (
"fmt"
"testing"
)

func TestOpeningTaskFromKeyboardRosterLetsEnterSendItsNote(t *testing.T) {
for _, width := range []int{80, 140} {
t.Run(fmt.Sprint(width), func(t *testing.T) {
a, fake, _ := roomApp(t)
a.width, a.height = width, 42
drive(t, a, altT())
drive(t, a, key("enter"))
if a.room == nil || a.room.id != 7 {
t.Fatal("keyboard roster did not open the selected task")
}
for _, r := range "Cover invalid units too" {
drive(t, a, key(string(r)))
}
drive(t, a, key("enter"))
if len(fake.steered) != 1 || fake.steered[0].text != "Cover invalid units too" {
t.Fatalf("Enter did not send the task note: %+v; draft %q", fake.steered, a.input.String())
}
opened := a.room
a.input.setText("Preserve this next note")
drive(t, a, altT())
drive(t, a, key("enter"))
if a.room != opened {
t.Fatal("selecting the open task replaced its room")
}
drive(t, a, key("enter"))
if len(fake.steered) != 2 || fake.steered[1].text != "Preserve this next note" {
t.Fatalf("reselecting the room lost or blocked its existing note: %+v", fake.steered)
}
})
}
}
Loading