aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/api/schema.rs43
-rw-r--r--src/app/mod.rs149
-rw-r--r--src/workspace.rs3
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 {