diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-04-09 21:57:28 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-04-09 21:59:18 +0300 |
| commit | c45a3b2dc1c2877dd6ee4ea9701d17ff656fc3ca (patch) | |
| tree | 11d614e2361aea23905a02416cdff3eaf08e8f60 /src | |
| parent | a6cbc9765116844744140fe89ef0633b480568cc (diff) | |
feat(api): return root panes from workspace and tab creation
Diffstat (limited to 'src')
| -rw-r--r-- | src/api/schema.rs | 43 | ||||
| -rw-r--r-- | src/app/mod.rs | 149 | ||||
| -rw-r--r-- | src/workspace.rs | 3 |
3 files changed, 153 insertions, 42 deletions
diff --git a/src/api/schema.rs b/src/api/schema.rs index 42a9c259..38393141 100644 --- a/src/api/schema.rs +++ b/src/api/schema.rs @@ -405,12 +405,21 @@ pub enum ResponseResult { WorkspaceInfo { workspace: WorkspaceInfo, }, + WorkspaceCreated { + workspace: WorkspaceInfo, + tab: TabInfo, + root_pane: PaneInfo, + }, WorkspaceList { workspaces: Vec<WorkspaceInfo>, }, TabInfo { tab: TabInfo, }, + TabCreated { + tab: TabInfo, + root_pane: PaneInfo, + }, TabList { tabs: Vec<TabInfo>, }, @@ -865,6 +874,40 @@ mod tests { } #[test] + fn create_response_round_trips_with_root_pane() { + let response = SuccessResponse { + id: "req_2".into(), + result: ResponseResult::TabCreated { + tab: TabInfo { + tab_id: "w_1:2".into(), + workspace_id: "w_1".into(), + number: 2, + label: "review".into(), + focused: false, + pane_count: 1, + agent_status: AgentStatus::Unknown, + }, + root_pane: PaneInfo { + pane_id: "w_1-3".into(), + workspace_id: "w_1".into(), + tab_id: "w_1:2".into(), + focused: false, + cwd: Some("/tmp/review".into()), + agent: None, + agent_status: AgentStatus::Unknown, + revision: 0, + }, + }, + }; + + let json = serde_json::to_string(&response).unwrap(); + assert!(json.contains("\"type\":\"tab_created\"")); + assert!(json.contains("\"root_pane\"")); + let restored: SuccessResponse = serde_json::from_str(&json).unwrap(); + assert_eq!(restored, response); + } + + #[test] fn error_response_round_trips() { let response = ErrorResponse { id: "req_1".into(), diff --git a/src/app/mod.rs b/src/app/mod.rs index 8d089a9d..9393521a 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -1075,34 +1075,33 @@ impl App { } } let workspace = self.workspace_info(index); + let tab = self + .tab_info(index, 0) + .expect("new workspace should have an initial tab"); + let root_pane = self + .root_pane_info(index, 0) + .expect("new workspace should have an initial root pane"); self.emit_event(crate::api::schema::EventEnvelope { event: crate::api::schema::EventKind::WorkspaceCreated, data: crate::api::schema::EventData::WorkspaceCreated { workspace: workspace.clone(), }, }); - if let Some(tab) = self.tab_info(index, 0) { - self.emit_event(crate::api::schema::EventEnvelope { - event: crate::api::schema::EventKind::TabCreated, - data: crate::api::schema::EventData::TabCreated { tab }, - }); - } - if let Some(pane_id) = self.state.workspaces[index] - .layout - .pane_ids() - .first() - .copied() - { - if let Some(pane) = self.pane_info(index, pane_id) { - self.emit_event(crate::api::schema::EventEnvelope { - event: crate::api::schema::EventKind::PaneCreated, - data: crate::api::schema::EventData::PaneCreated { pane }, - }); - } - } + self.emit_event(crate::api::schema::EventEnvelope { + event: crate::api::schema::EventKind::TabCreated, + data: crate::api::schema::EventData::TabCreated { tab: tab.clone() }, + }); + self.emit_event(crate::api::schema::EventEnvelope { + event: crate::api::schema::EventKind::PaneCreated, + data: crate::api::schema::EventData::PaneCreated { + pane: root_pane.clone(), + }, + }); SuccessResponse { id: request.id, - result: ResponseResult::WorkspaceInfo { workspace }, + result: self + .workspace_created_result(index) + .expect("new workspace should produce a complete create response"), } } Err(err) => { @@ -1360,28 +1359,24 @@ impl App { } self.schedule_session_save(); let tab = self.tab_info(ws_idx, tab_idx).unwrap(); - if let Some(pane_id) = self.state.workspaces[ws_idx].tabs[tab_idx] - .layout - .pane_ids() - .first() - .copied() - { - self.emit_event(crate::api::schema::EventEnvelope { - event: crate::api::schema::EventKind::TabCreated, - data: crate::api::schema::EventData::TabCreated { - tab: tab.clone(), - }, - }); - if let Some(pane) = self.pane_info(ws_idx, pane_id) { - self.emit_event(crate::api::schema::EventEnvelope { - event: crate::api::schema::EventKind::PaneCreated, - data: crate::api::schema::EventData::PaneCreated { pane }, - }); - } - } + let root_pane = self + .root_pane_info(ws_idx, tab_idx) + .expect("new tab should have a root pane"); + self.emit_event(crate::api::schema::EventEnvelope { + event: crate::api::schema::EventKind::TabCreated, + data: crate::api::schema::EventData::TabCreated { tab: tab.clone() }, + }); + self.emit_event(crate::api::schema::EventEnvelope { + event: crate::api::schema::EventKind::PaneCreated, + data: crate::api::schema::EventData::PaneCreated { + pane: root_pane.clone(), + }, + }); SuccessResponse { id: request.id, - result: ResponseResult::TabInfo { tab }, + result: self + .tab_created_result(ws_idx, tab_idx) + .expect("new tab should produce a complete create response"), } } Err(err) => { @@ -2279,6 +2274,38 @@ impl App { }) } + fn workspace_created_result( + &self, + ws_idx: usize, + ) -> Option<crate::api::schema::ResponseResult> { + Some(crate::api::schema::ResponseResult::WorkspaceCreated { + workspace: self.workspace_info(ws_idx), + tab: self.tab_info(ws_idx, 0)?, + root_pane: self.root_pane_info(ws_idx, 0)?, + }) + } + + fn tab_created_result( + &self, + ws_idx: usize, + tab_idx: usize, + ) -> Option<crate::api::schema::ResponseResult> { + Some(crate::api::schema::ResponseResult::TabCreated { + tab: self.tab_info(ws_idx, tab_idx)?, + root_pane: self.root_pane_info(ws_idx, tab_idx)?, + }) + } + + fn root_pane_info( + &self, + ws_idx: usize, + tab_idx: usize, + ) -> Option<crate::api::schema::PaneInfo> { + let ws = self.state.workspaces.get(ws_idx)?; + let tab = ws.tabs.get(tab_idx)?; + self.pane_info(ws_idx, tab.root_pane) + } + fn pane_info( &self, ws_idx: usize, @@ -2690,6 +2717,48 @@ mod tests { } #[test] + fn workspace_create_response_includes_initial_tab_and_root_pane() { + let mut app = test_app(); + app.state.workspaces = vec![Workspace::test_new("api-root-pane")]; + app.state.active = Some(0); + app.state.selected = 0; + + let crate::api::schema::ResponseResult::WorkspaceCreated { + workspace, + tab, + root_pane, + } = app.workspace_created_result(0).unwrap() + else { + panic!("expected workspace_created response"); + }; + + assert_eq!(workspace.label, "api-root-pane"); + assert_eq!(tab.workspace_id, workspace.workspace_id); + assert_eq!(root_pane.workspace_id, workspace.workspace_id); + assert_eq!(root_pane.tab_id, tab.tab_id); + } + + #[test] + fn tab_create_response_includes_root_pane() { + let mut app = test_app(); + let mut workspace = Workspace::test_new("api-tab-root-pane"); + workspace.test_add_tab(None); + app.state.workspaces = vec![workspace]; + app.state.active = Some(0); + app.state.selected = 0; + + let crate::api::schema::ResponseResult::TabCreated { tab, root_pane } = + app.tab_created_result(0, 1).unwrap() + else { + panic!("expected tab_created response"); + }; + + assert_eq!(tab.workspace_id, root_pane.workspace_id); + assert_eq!(root_pane.tab_id, tab.tab_id); + assert_eq!(tab.pane_count, 1); + } + + #[test] fn workspace_creation_in_navigate_mode_uses_selected_workspace_seed_cwd() { let mut app = test_app(); let mut first = Workspace::test_new("herdr"); diff --git a/src/workspace.rs b/src/workspace.rs index 447e6061..5fabe47f 100644 --- a/src/workspace.rs +++ b/src/workspace.rs @@ -379,8 +379,7 @@ impl Workspace { )?; self.register_new_pane(tab.root_pane); self.tabs.push(tab); - self.active_tab = self.tabs.len() - 1; - Ok(self.active_tab) + Ok(self.tabs.len() - 1) } pub fn close_tab(&mut self, idx: usize) -> bool { |
