use gpui::{ModelHandle, ViewContext}; use settings::{Settings, WorkingDirectory}; use workspace::Workspace; use crate::{ terminal_container_view::{ get_working_directory, DeployModal, TerminalContainer, TerminalContainerContent, }, Event, Terminal, }; #[derive(Debug)] struct StoredTerminal(ModelHandle); pub fn deploy_modal(workspace: &mut Workspace, _: &DeployModal, cx: &mut ViewContext) { // Pull the terminal connection out of the global if it has been stored let possible_terminal = cx.update_default_global::, _, _>(|possible_connection, _| { possible_connection.take() }); if let Some(StoredTerminal(stored_terminal)) = possible_terminal { workspace.toggle_modal(cx, |_, cx| { // Create a view from the stored connection if the terminal modal is not already shown cx.add_view(|cx| TerminalContainer::from_terminal(stored_terminal.clone(), true, cx)) }); // Toggle Modal will dismiss the terminal modal if it is currently shown, so we must // store the terminal back in the global cx.set_global::>(Some(StoredTerminal(stored_terminal.clone()))); } else { // No connection was stored, create a new terminal if let Some(closed_terminal_handle) = workspace.toggle_modal(cx, |workspace, cx| { // No terminal modal visible, construct a new one. let wd_strategy = cx .global::() .terminal_overrides .working_directory .clone() .unwrap_or(WorkingDirectory::CurrentProjectDirectory); let working_directory = get_working_directory(workspace, cx, wd_strategy); let this = cx.add_view(|cx| TerminalContainer::new(working_directory, true, cx)); if let TerminalContainerContent::Connected(connected) = &this.read(cx).content { let terminal_handle = connected.read(cx).handle(); cx.subscribe(&terminal_handle, on_event).detach(); // Set the global immediately if terminal construction was successful, // in case the user opens the command palette cx.set_global::>(Some(StoredTerminal( terminal_handle.clone(), ))); } this }) { // Terminal modal was dismissed. Store terminal if the terminal view is connected if let TerminalContainerContent::Connected(connected) = &closed_terminal_handle.read(cx).content { let terminal_handle = connected.read(cx).handle(); // Set the global immediately if terminal construction was successful, // in case the user opens the command palette cx.set_global::>(Some(StoredTerminal(terminal_handle))); } } } } pub fn on_event( workspace: &mut Workspace, _: ModelHandle, event: &Event, cx: &mut ViewContext, ) { // Dismiss the modal if the terminal quit if let Event::CloseTerminal = event { cx.set_global::>(None); if workspace.modal::().is_some() { workspace.dismiss_modal(cx) } } }