debugger: Unify landing state for new session modal (#30046)

Closes #ISSUE

Release Notes:

- N/A
This commit is contained in:
Piotr Osiewicz 2025-05-07 00:27:50 +02:00 committed by GitHub
parent cec1d2584b
commit bbffe1ec2c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 58 additions and 101 deletions

View file

Before

Width:  |  Height:  |  Size: 474 B

After

Width:  |  Height:  |  Size: 474 B

Before After
Before After

View file

@ -1,11 +1,10 @@
use crate::persistence::DebuggerPaneItem;
use crate::session::DebugSession;
use crate::{
ClearAllBreakpoints, Continue, CreateDebuggingSession, Disconnect, FocusBreakpointList,
FocusConsole, FocusFrames, FocusLoadedSources, FocusModules, FocusTerminal, FocusVariables,
Pause, Restart, StepBack, StepInto, StepOut, StepOver, Stop, ToggleIgnoreBreakpoints,
persistence,
ClearAllBreakpoints, Continue, Detach, FocusBreakpointList, FocusConsole, FocusFrames,
FocusLoadedSources, FocusModules, FocusTerminal, FocusVariables, Pause, Restart, StepBack,
StepInto, StepOut, StepOver, Stop, ToggleIgnoreBreakpoints, persistence,
};
use crate::{new_session_modal::NewSessionModal, session::DebugSession};
use anyhow::Result;
use command_palette_hooks::CommandPaletteFilter;
use dap::adapters::DebugAdapterName;
@ -110,7 +109,7 @@ impl DebugPanel {
let filter = CommandPaletteFilter::global_mut(cx);
let debugger_action_types = [
TypeId::of::<Disconnect>(),
TypeId::of::<Detach>(),
TypeId::of::<Stop>(),
TypeId::of::<ToggleIgnoreBreakpoints>(),
];
@ -609,52 +608,19 @@ impl DebugPanel {
let focus_handle = self.focus_handle.clone();
let is_side = self.position(window, cx).axis() == gpui::Axis::Horizontal;
let div = if is_side { v_flex() } else { h_flex() };
let weak_panel = cx.weak_entity();
let new_session_button = || {
IconButton::new("debug-new-session", IconName::Plus)
.icon_size(IconSize::Small)
.on_click({
let workspace = self.workspace.clone();
let weak_panel = weak_panel.clone();
let past_debug_definition = self.past_debug_definition.clone();
move |_, window, cx| {
let weak_panel = weak_panel.clone();
let past_debug_definition = past_debug_definition.clone();
let workspace = workspace.clone();
window
.spawn(cx, async move |cx| {
let task_contexts = workspace
.update_in(cx, |workspace, window, cx| {
tasks_ui::task_contexts(workspace, window, cx)
})?
.await;
workspace.update_in(cx, |this, window, cx| {
this.toggle_modal(window, cx, |window, cx| {
NewSessionModal::new(
past_debug_definition,
weak_panel,
workspace.clone(),
None,
task_contexts,
window,
cx,
)
});
})?;
Result::<_, anyhow::Error>::Ok(())
})
.detach();
}
move |_, window, cx| window.dispatch_action(crate::Start.boxed_clone(), cx)
})
.tooltip({
let focus_handle = focus_handle.clone();
move |window, cx| {
Tooltip::for_action_in(
"New Debug Session",
&CreateDebuggingSession,
"Start Debug Session",
&crate::Start,
&focus_handle,
window,
cx,
@ -920,6 +886,28 @@ impl DebugPanel {
}
}),
)
.child(
IconButton::new("debug-disconnect", IconName::DebugDetach)
.icon_size(IconSize::XSmall)
.on_click(window.listener_for(
&running_session,
|this, _, _, cx| {
this.detach_client(cx);
},
))
.tooltip({
let focus_handle = focus_handle.clone();
move |window, cx| {
Tooltip::for_action_in(
"Detach",
&Detach,
&focus_handle,
window,
cx,
)
}
}),
)
},
),
)
@ -1270,10 +1258,7 @@ impl Render for DebugPanel {
Button::new("spawn-new-session-empty-state", "New Session")
.size(ButtonSize::Large)
.on_click(|_, window, cx| {
window.dispatch_action(
CreateDebuggingSession.boxed_clone(),
cx,
);
window.dispatch_action(crate::Start.boxed_clone(), cx);
}),
),
),

View file

@ -24,7 +24,7 @@ actions!(
[
Start,
Continue,
Disconnect,
Detach,
Pause,
Restart,
StepInto,
@ -34,7 +34,6 @@ actions!(
Stop,
ToggleIgnoreBreakpoints,
ClearAllBreakpoints,
CreateDebuggingSession,
FocusConsole,
FocusVariables,
FocusBreakpointList,
@ -147,38 +146,6 @@ pub fn init(cx: &mut App) {
})
},
)
.register_action(
|workspace: &mut Workspace, _: &CreateDebuggingSession, window, cx| {
if let Some(debug_panel) = workspace.panel::<DebugPanel>(cx) {
let weak_panel = debug_panel.downgrade();
let weak_workspace = cx.weak_entity();
cx.spawn_in(window, async move |this, cx| {
let task_contexts = this
.update_in(cx, |workspace, window, cx| {
tasks_ui::task_contexts(workspace, window, cx)
})?
.await;
this.update_in(cx, |workspace, window, cx| {
workspace.toggle_modal(window, cx, |window, cx| {
NewSessionModal::new(
debug_panel.read(cx).past_debug_definition.clone(),
weak_panel,
weak_workspace,
None,
task_contexts,
window,
cx,
)
});
})?;
Result::<_, anyhow::Error>::Ok(())
})
.detach();
}
},
)
.register_action(|workspace: &mut Workspace, _: &Start, window, cx| {
if let Some(debug_panel) = workspace.panel::<DebugPanel>(cx) {
let weak_panel = debug_panel.downgrade();

View file

@ -629,9 +629,7 @@ impl Render for NewSessionModal {
),
)
.justify_between()
.when(!matches!(self.mode, NewSessionMode::Scenario(_)), |this| {
this.children(self.adapter_drop_down_menu(window, cx))
})
.children(self.adapter_drop_down_menu(window, cx))
.border_color(cx.theme().colors().border_variant)
.border_b_1(),
)
@ -644,7 +642,15 @@ impl Render for NewSessionModal {
.border_color(cx.theme().colors().border_variant)
.border_t_1()
.w_full()
.child(self.debug_config_drop_down_menu(window, cx))
.child(
matches!(self.mode, NewSessionMode::Scenario(_))
.not()
.then(|| {
self.debug_config_drop_down_menu(window, cx)
.into_any_element()
})
.unwrap_or_else(|| v_flex().w_full().into_any_element()),
)
.child(
h_flex()
.justify_end()

View file

@ -103,14 +103,14 @@ impl DebugSession {
pub(crate) fn label_element(&self, cx: &App) -> AnyElement {
let label = self.label(cx);
let is_terminated = self
.running_state
.read(cx)
.session()
.read(cx)
.is_terminated();
let icon = {
if self
.running_state
.read(cx)
.session()
.read(cx)
.is_terminated()
{
if is_terminated {
Some(Indicator::dot().color(Color::Error))
} else {
match self
@ -131,7 +131,7 @@ impl DebugSession {
.gap_2()
.when_some(icon, |this, indicator| this.child(indicator))
.justify_between()
.child(Label::new(label))
.child(Label::new(label).when(is_terminated, |this| this.strikethrough()))
.into_any_element()
}
}

View file

@ -44,9 +44,10 @@ use task::{
use terminal_view::TerminalView;
use ui::{
ActiveTheme, AnyElement, App, ButtonCommon as _, Clickable as _, Context, ContextMenu,
DropdownMenu, FluentBuilder, IconButton, IconName, IconSize, InteractiveElement, IntoElement,
Label, LabelCommon as _, ParentElement, Render, SharedString, StatefulInteractiveElement,
Styled, Tab, Tooltip, VisibleOnHover, VisualContext, Window, div, h_flex, v_flex,
Disableable, DropdownMenu, FluentBuilder, IconButton, IconName, IconSize, InteractiveElement,
IntoElement, Label, LabelCommon as _, ParentElement, Render, SharedString,
StatefulInteractiveElement, Styled, Tab, Tooltip, VisibleOnHover, VisualContext, Window, div,
h_flex, v_flex,
};
use util::ResultExt;
use variable_list::VariableList;
@ -1420,11 +1421,7 @@ impl RunningState {
});
}
#[expect(
unused,
reason = "Support for disconnecting a client is not wired through yet"
)]
pub fn disconnect_client(&self, cx: &mut Context<Self>) {
pub fn detach_client(&self, cx: &mut Context<Self>) {
self.session().update(cx, |state, cx| {
state.disconnect_client(cx);
});
@ -1442,6 +1439,7 @@ impl RunningState {
cx: &mut Context<'_, RunningState>,
) -> DropdownMenu {
let state = cx.entity();
let session_terminated = self.session.read(cx).is_terminated();
let threads = self.session.update(cx, |this, cx| this.threads(cx));
let selected_thread_name = threads
.iter()
@ -1464,6 +1462,7 @@ impl RunningState {
this
}),
)
.disabled(session_terminated)
}
fn default_pane_layout(

View file

@ -81,7 +81,7 @@ pub enum IconName {
DebugContinue,
DebugDisabledBreakpoint,
DebugDisabledLogBreakpoint,
DebugDisconnect,
DebugDetach,
DebugIgnoreBreakpoints,
DebugLogBreakpoint,
DebugPause,