diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-06-14 02:43:45 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-06-14 03:47:07 +0300 |
| commit | fbd20ad6e488fb3b9efc1612fdffee6e672976c1 (patch) | |
| tree | d21daf93241786f8aa6fde23b41cdb9e15182b79 /src/app/api/workspaces.rs | |
| parent | d35c642ef36ee5ac2afe7c1b18ad5a717bc807d8 (diff) | |
feat: add plugin v1 system
Add manifest-driven plugin actions, event hooks, pane entrypoints, link handlers, and host APIs.
Support plugin link, GitHub install, build commands, installed plugin registry, pane movement, runtime context, and plugin docs.
Diffstat (limited to 'src/app/api/workspaces.rs')
| -rw-r--r-- | src/app/api/workspaces.rs | 59 |
1 files changed, 57 insertions, 2 deletions
diff --git a/src/app/api/workspaces.rs b/src/app/api/workspaces.rs index e1966adf..cdfd4ec5 100644 --- a/src/app/api/workspaces.rs +++ b/src/app/api/workspaces.rs @@ -51,7 +51,11 @@ impl App { .and_then(|ws_idx| self.seed_cwd_from_workspace(ws_idx)); self.resolve_new_terminal_cwd(follow_cwd) }); - match self.create_workspace_with_options(cwd, params.focus) { + let extra_env = match super::env::normalize_launch_env(params.env) { + Ok(env) => env, + Err((code, message)) => return encode_error(id, &code, message), + }; + match self.create_workspace_with_launch_env(cwd, params.focus, extra_env) { Ok(index) => { if let Some(label) = params.label { if let Some(workspace) = self.state.workspaces.get_mut(index) { @@ -147,12 +151,30 @@ impl App { return workspace_not_found(id, &target.workspace_id); } let workspace_id = self.public_workspace_id(index); + let workspace = self.workspace_info(index); + let pane_ids = self + .state + .workspaces + .get(index) + .map(|ws| { + ws.tabs + .iter() + .flat_map(|tab| tab.layout.pane_ids()) + .collect::<Vec<_>>() + }) + .unwrap_or_default(); self.state.selected = index; self.state.close_selected_workspace(); + for pane_id in pane_ids { + self.state.plugin_panes.remove(&pane_id); + } self.shutdown_detached_terminal_runtimes(); self.emit_event(EventEnvelope { event: EventKind::WorkspaceClosed, - data: EventData::WorkspaceClosed { workspace_id }, + data: EventData::WorkspaceClosed { + workspace_id, + workspace: Some(workspace), + }, }); encode_success(id, ResponseResult::Ok {}) @@ -208,4 +230,37 @@ mod tests { assert_eq!(app.state.request_remove_linked_worktree, None); assert!(app.state.workspaces.is_empty()); } + + #[test] + fn api_workspace_close_event_includes_final_worktree_snapshot() { + let event_hub = crate::api::EventHub::default(); + let (_api_tx, api_rx) = tokio::sync::mpsc::unbounded_channel(); + let mut app = App::new(&Config::default(), true, None, api_rx, event_hub.clone()); + app.state.workspaces = app_with_linked_worktree().state.workspaces; + let workspace_id = app.state.workspaces[0].id.clone(); + + let response = app.handle_workspace_close( + "req".into(), + WorkspaceTarget { + workspace_id: workspace_id.clone(), + }, + ); + + let success: SuccessResponse = serde_json::from_str(&response).unwrap(); + assert_eq!(success.id, "req"); + let events = event_hub.events_after(0); + assert!(events.iter().any(|(_, event)| { + matches!( + &event.data, + EventData::WorkspaceClosed { + workspace_id: closed_id, + workspace: Some(workspace), + } if closed_id == &workspace_id + && workspace + .worktree + .as_ref() + .is_some_and(|worktree| worktree.is_linked_worktree) + ) + })); + } } |
