1use gpui::{ModelHandle, ViewContext};
2use settings::{Settings, WorkingDirectory};
3use workspace::{programs::ProgramManager, Workspace};
4
5use crate::{
6 terminal_container_view::{
7 get_working_directory, DeployModal, TerminalContainer, TerminalContainerContent,
8 },
9 Event, Terminal,
10};
11
12pub fn deploy_modal(workspace: &mut Workspace, _: &DeployModal, cx: &mut ViewContext<Workspace>) {
13 let window = cx.window_id();
14
15 // Pull the terminal connection out of the global if it has been stored
16 let possible_terminal = ProgramManager::remove::<Terminal, _>(window, cx);
17
18 if let Some(terminal_handle) = possible_terminal {
19 workspace.toggle_modal(cx, |_, cx| {
20 // Create a view from the stored connection if the terminal modal is not already shown
21 cx.add_view(|cx| TerminalContainer::from_terminal(terminal_handle.clone(), true, cx))
22 });
23 // Toggle Modal will dismiss the terminal modal if it is currently shown, so we must
24 // store the terminal back in the global
25 ProgramManager::insert_or_replace::<Terminal, _>(window, terminal_handle, cx);
26 } else {
27 // No connection was stored, create a new terminal
28 if let Some(closed_terminal_handle) = workspace.toggle_modal(cx, |workspace, cx| {
29 // No terminal modal visible, construct a new one.
30 let wd_strategy = cx
31 .global::<Settings>()
32 .terminal_overrides
33 .working_directory
34 .clone()
35 .unwrap_or(WorkingDirectory::CurrentProjectDirectory);
36
37 let working_directory = get_working_directory(workspace, cx, wd_strategy);
38
39 let this = cx.add_view(|cx| TerminalContainer::new(working_directory, true, cx));
40
41 if let TerminalContainerContent::Connected(connected) = &this.read(cx).content {
42 let terminal_handle = connected.read(cx).handle();
43 cx.subscribe(&terminal_handle, on_event).detach();
44 // Set the global immediately if terminal construction was successful,
45 // in case the user opens the command palette
46 ProgramManager::insert_or_replace::<Terminal, _>(window, terminal_handle, cx);
47 }
48
49 this
50 }) {
51 // Terminal modal was dismissed and the terminal view is connected, store the terminal
52 if let TerminalContainerContent::Connected(connected) =
53 &closed_terminal_handle.read(cx).content
54 {
55 let terminal_handle = connected.read(cx).handle();
56 // Set the global immediately if terminal construction was successful,
57 // in case the user opens the command palette
58 ProgramManager::insert_or_replace::<Terminal, _>(window, terminal_handle, cx);
59 }
60 }
61 }
62}
63
64pub fn on_event(
65 workspace: &mut Workspace,
66 _: ModelHandle<Terminal>,
67 event: &Event,
68 cx: &mut ViewContext<Workspace>,
69) {
70 // Dismiss the modal if the terminal quit
71 if let Event::CloseTerminal = event {
72 ProgramManager::remove::<Terminal, _>(cx.window_id(), cx);
73
74 if workspace.modal::<TerminalContainer>().is_some() {
75 workspace.dismiss_modal(cx)
76 }
77 }
78}