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