@@ -59,6 +59,7 @@ async fn older_server_notice_falls_back_in_short_overview() {
5959 . collect :: < String > ( ) ;
6060 insta:: assert_snapshot!( header. trim_end( ) , @" Old srv" ) ;
6161}
62+ use crate :: app:: agents_overview_view:: AgentsOverviewFocus ;
6263use crate :: app:: test_support:: make_test_app;
6364use crate :: app_event:: AgentsOverviewThreadRefresh ;
6465use crate :: bottom_pane:: BottomPaneView ;
@@ -106,6 +107,66 @@ fn overview_draft(app: &App) -> (String, usize) {
106107 ( composer. current_text_with_pending ( ) , composer. cursor ( ) )
107108}
108109
110+ #[ tokio:: test]
111+ async fn overview_escape_returns_from_list_to_composer ( ) {
112+ for ( vim, offline) in [ ( false , false ) , ( true , false ) , ( false , true ) , ( true , true ) ] {
113+ let mut app = make_test_app ( ) . await ;
114+ app. config . disable_paste_burst = true ;
115+ if vim {
116+ app. chat_widget . toggle_vim_mode_and_notify ( ) ;
117+ }
118+ let ( tx, mut rx) = tokio:: sync:: mpsc:: unbounded_channel ( ) ;
119+ app. app_event_tx = AppEventSender :: new ( tx) ;
120+ let view = app. agents_overview_view (
121+ vec ! [ overview_thread(
122+ ThreadId :: new( ) ,
123+ /*parent_thread_id*/ None ,
124+ "Existing task" ,
125+ ThreadStatus :: Idle ,
126+ ) ] ,
127+ /*selected_thread_id*/ None ,
128+ ) ;
129+ app. chat_widget . show_bottom_pane_view ( Box :: new ( view) ) ;
130+ app. chat_widget . handle_paste ( "task draft" . into ( ) ) ;
131+ app. chat_widget . handle_key_event ( KeyCode :: Home . into ( ) ) ;
132+ let draft = overview_draft ( & app) ;
133+ if offline {
134+ app. agents_overview
135+ . view_state
136+ . lock ( )
137+ . unwrap ( )
138+ . connection_notice = Some ( "Reconnecting" ) ;
139+ }
140+ if vim {
141+ app. chat_widget . handle_key_event ( KeyCode :: Esc . into ( ) ) ;
142+ }
143+ app. chat_widget . handle_key_event ( KeyCode :: Esc . into ( ) ) ;
144+ assert ! ( matches!(
145+ app. agents_overview. view_state. lock( ) . unwrap( ) . focus,
146+ AgentsOverviewFocus :: List
147+ ) ) ;
148+ app. chat_widget . handle_key_event ( KeyCode :: Down . into ( ) ) ;
149+ app. chat_widget . handle_key_event ( KeyCode :: Esc . into ( ) ) ;
150+
151+ assert ! ( matches!(
152+ app. agents_overview. view_state. lock( ) . unwrap( ) . focus,
153+ AgentsOverviewFocus :: Composer
154+ ) ) ;
155+ assert_eq ! (
156+ app. chat_widget
157+ . selected_index_for_present_view( AGENTS_OVERVIEW_VIEW_ID ) ,
158+ Some ( 0 )
159+ ) ;
160+ assert_eq ! ( overview_draft( & app) , draft) ;
161+ assert ! ( rx. try_recv( ) . is_err( ) ) ;
162+ if !vim && !offline {
163+ insta:: assert_snapshot!( render_bottom_popup( & app. chat_widget, /*width*/ 80 ) . lines( ) . last( ) . unwrap( ) , @" enter create task ctrl+j newline esc tasks" ) ;
164+ }
165+ app. chat_widget . handle_key_event ( KeyCode :: Char ( '!' ) . into ( ) ) ;
166+ assert_eq ! ( overview_draft( & app) . 0 , "!task draft" ) ;
167+ }
168+ }
169+
109170#[ tokio:: test]
110171async fn overview_right_opens_current_or_highlighted_task ( ) {
111172 let mut app = make_test_app ( ) . await ;
@@ -658,7 +719,7 @@ async fn shared_overview_seeds_once_and_retains_locally_resumed_history() -> Res
658719 app. chat_widget
659720 . handle_key_event ( KeyEvent :: new ( KeyCode :: Esc , KeyModifiers :: NONE ) ) ;
660721 app. chat_widget
661- . handle_key_event ( KeyEvent :: new ( KeyCode :: Esc , KeyModifiers :: NONE ) ) ;
722+ . handle_key_event ( KeyEvent :: new ( KeyCode :: Enter , KeyModifiers :: NONE ) ) ;
662723 finish_overview_refresh ( & mut app, & app_server, & mut event_rx) . await ;
663724 let retained: HashSet < _ > = app. agents_overview . threads . keys ( ) . copied ( ) . collect ( ) ;
664725 assert_eq ! ( retained, expected) ;
@@ -1164,7 +1225,6 @@ async fn shared_overview_shows_only_root_sessions() {
11641225 let mut action_view = AgentsOverviewView :: new (
11651226 view. rows . clone ( ) ,
11661227 Some ( first_root) ,
1167- /*exit_on_cancel*/ false ,
11681228 /*worktrees_enabled*/ false ,
11691229 crate :: app_event_sender:: AppEventSender :: new ( event_tx) ,
11701230 app. keymap . clone ( ) ,
@@ -1282,7 +1342,7 @@ async fn shared_overview_shows_only_root_sessions() {
12821342 app. chat_widget
12831343 . handle_key_event ( KeyEvent :: new ( KeyCode :: Esc , KeyModifiers :: NONE ) ) ;
12841344 app. chat_widget
1285- . handle_key_event ( KeyEvent :: new ( KeyCode :: Esc , KeyModifiers :: NONE ) ) ;
1345+ . handle_key_event ( KeyEvent :: new ( KeyCode :: Enter , KeyModifiers :: NONE ) ) ;
12861346 let view = app. agents_overview_view ( threads, /*selected_thread_id*/ None ) ;
12871347 app. chat_widget . show_bottom_pane_view ( Box :: new ( view) ) ;
12881348 let rendered = render_bottom_popup ( & app. chat_widget , /*width*/ 96 ) ;
@@ -1304,7 +1364,7 @@ async fn shared_overview_shows_only_root_sessions() {
13041364 . expect ( "render full-screen dashboard" ) ;
13051365 assert_eq ! ( tui. terminal. viewport_area. height, screen_size. height) ;
13061366 app. chat_widget
1307- . handle_key_event ( KeyEvent :: new ( KeyCode :: Esc , KeyModifiers :: NONE ) ) ;
1367+ . handle_key_event ( KeyEvent :: new ( KeyCode :: Enter , KeyModifiers :: NONE ) ) ;
13081368 app. render_chat_widget_frame ( & mut tui, screen_size)
13091369 . expect ( "restore conversation after closing dashboard" ) ;
13101370 assert ! ( tui. terminal. viewport_area. height < screen_size. height) ;
@@ -1406,7 +1466,6 @@ async fn filtered_dashboard_actions_use_configured_shortcuts() {
14061466 )
14071467 . rows ,
14081468 Some ( first) ,
1409- /*exit_on_cancel*/ false ,
14101469 /*worktrees_enabled*/ false ,
14111470 crate :: app_event_sender:: AppEventSender :: new ( event_tx) ,
14121471 app. keymap . clone ( ) ,
0 commit comments