Add Code Actions to the Toolbar (#31236)
Closes issue #31120. https://github.com/user-attachments/assets/a4b3c86d-7358-49ac-b8d9-e9af50daf671 Release Notes: - Added a code actions icon to the toolbar. This icon can be disabled by setting `toolbar.code_actions` to `false`.
This commit is contained in:
parent
fbc922ad46
commit
1cad1cbbfc
17 changed files with 167 additions and 50 deletions
|
@ -1,3 +1,3 @@
|
|||
<svg width="8" height="8" viewBox="0 0 8 8" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4.76019 3.50003H6.50231C6.71012 3.50003 6.89761 3.62971 6.95698 3.82346C7.04292 4.01876 6.98823 4.23906 6.83199 4.37656L2.83214 7.87643C2.65558 8.02954 2.39731 8.04204 2.20857 7.90455C2.01967 7.76705 1.95092 7.51706 2.04295 7.30301L3.24462 4.49999H1.48844C1.29423 4.49999 1.10767 4.37031 1.0344 4.17657C0.961132 3.98126 1.01643 3.76096 1.17323 3.62346L5.17261 0.123753C5.34917 -0.0299914 5.60697 -0.0417097 5.79603 0.0954726C5.98508 0.232749 6.05383 0.482177 5.96165 0.69695L4.76013 3.49981L4.76019 3.50003Z" fill="white"/>
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M9.3 1.75L3 7.35H5.8L4.7 12.25L11 6.65H8.2L9.3 1.75Z" stroke="black" stroke-width="1.25" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 633 B After Width: | Height: | Size: 227 B |
3
assets/icons/bolt_filled.svg
Normal file
3
assets/icons/bolt_filled.svg
Normal file
|
@ -0,0 +1,3 @@
|
|||
<svg width="8" height="8" viewBox="0 0 8 8" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M4.76019 3.50003H6.50231C6.71012 3.50003 6.89761 3.62971 6.95698 3.82346C7.04292 4.01876 6.98823 4.23906 6.83199 4.37656L2.83214 7.87643C2.65558 8.02954 2.39731 8.04204 2.20857 7.90455C2.01967 7.76705 1.95092 7.51706 2.04295 7.30301L3.24462 4.49999H1.48844C1.29423 4.49999 1.10767 4.37031 1.0344 4.17657C0.961132 3.98126 1.01643 3.76096 1.17323 3.62346L5.17261 0.123753C5.34917 -0.0299914 5.60697 -0.0417097 5.79603 0.0954726C5.98508 0.232749 6.05383 0.482177 5.96165 0.69695L4.76013 3.49981L4.76019 3.50003Z" fill="white"/>
|
||||
</svg>
|
After Width: | Height: | Size: 633 B |
|
@ -322,7 +322,9 @@
|
|||
// Whether to show the Selections menu in the editor toolbar.
|
||||
"selections_menu": true,
|
||||
// Whether to show agent review buttons in the editor toolbar.
|
||||
"agent_review": true
|
||||
"agent_review": true,
|
||||
// Whether to show code action buttons in the editor toolbar.
|
||||
"code_actions": true
|
||||
},
|
||||
// Titlebar related settings
|
||||
"title_bar": {
|
||||
|
|
|
@ -679,7 +679,7 @@ async fn test_collaborating_with_code_actions(
|
|||
editor_b.update_in(cx_b, |editor, window, cx| {
|
||||
editor.toggle_code_actions(
|
||||
&ToggleCodeActions {
|
||||
deployed_from_indicator: None,
|
||||
deployed_from: None,
|
||||
quick_launch: false,
|
||||
},
|
||||
window,
|
||||
|
|
|
@ -1123,7 +1123,7 @@ impl PickerDelegate for DebugScenarioDelegate {
|
|||
let task_kind = &self.candidates[hit.candidate_id].0;
|
||||
|
||||
let icon = match task_kind {
|
||||
Some(TaskSourceKind::Lsp(..)) => Some(Icon::new(IconName::Bolt)),
|
||||
Some(TaskSourceKind::Lsp(..)) => Some(Icon::new(IconName::BoltFilled)),
|
||||
Some(TaskSourceKind::UserInput) => Some(Icon::new(IconName::Terminal)),
|
||||
Some(TaskSourceKind::AbsPath { .. }) => Some(Icon::new(IconName::Settings)),
|
||||
Some(TaskSourceKind::Worktree { .. }) => Some(Icon::new(IconName::FileTree)),
|
||||
|
|
|
@ -74,16 +74,22 @@ pub struct SelectToEndOfLine {
|
|||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct ToggleCodeActions {
|
||||
// Display row from which the action was deployed.
|
||||
// Source from which the action was deployed.
|
||||
#[serde(default)]
|
||||
#[serde(skip)]
|
||||
pub deployed_from_indicator: Option<DisplayRow>,
|
||||
pub deployed_from: Option<CodeActionSource>,
|
||||
// Run first available task if there is only one.
|
||||
#[serde(default)]
|
||||
#[serde(skip)]
|
||||
pub quick_launch: bool,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Clone, Debug)]
|
||||
pub enum CodeActionSource {
|
||||
Indicator(DisplayRow),
|
||||
QuickActionBar,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Clone, Deserialize, Default, JsonSchema)]
|
||||
#[serde(deny_unknown_fields)]
|
||||
pub struct ConfirmCompletion {
|
||||
|
|
|
@ -26,6 +26,7 @@ use task::ResolvedTask;
|
|||
use ui::{Color, IntoElement, ListItem, Pixels, Popover, Styled, prelude::*};
|
||||
use util::ResultExt;
|
||||
|
||||
use crate::CodeActionSource;
|
||||
use crate::editor_settings::SnippetSortOrder;
|
||||
use crate::hover_popover::{hover_markdown_style, open_markdown_url};
|
||||
use crate::{
|
||||
|
@ -168,6 +169,7 @@ impl CodeContextMenu {
|
|||
pub enum ContextMenuOrigin {
|
||||
Cursor,
|
||||
GutterIndicator(DisplayRow),
|
||||
QuickActionBar,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -840,7 +842,7 @@ pub struct AvailableCodeAction {
|
|||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct CodeActionContents {
|
||||
pub struct CodeActionContents {
|
||||
tasks: Option<Rc<ResolvedTasks>>,
|
||||
actions: Option<Rc<[AvailableCodeAction]>>,
|
||||
debug_scenarios: Vec<DebugScenario>,
|
||||
|
@ -968,12 +970,12 @@ impl CodeActionsItem {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) struct CodeActionsMenu {
|
||||
pub struct CodeActionsMenu {
|
||||
pub actions: CodeActionContents,
|
||||
pub buffer: Entity<Buffer>,
|
||||
pub selected_item: usize,
|
||||
pub scroll_handle: UniformListScrollHandle,
|
||||
pub deployed_from_indicator: Option<DisplayRow>,
|
||||
pub deployed_from: Option<CodeActionSource>,
|
||||
}
|
||||
|
||||
impl CodeActionsMenu {
|
||||
|
@ -1042,10 +1044,10 @@ impl CodeActionsMenu {
|
|||
}
|
||||
|
||||
fn origin(&self) -> ContextMenuOrigin {
|
||||
if let Some(row) = self.deployed_from_indicator {
|
||||
ContextMenuOrigin::GutterIndicator(row)
|
||||
} else {
|
||||
ContextMenuOrigin::Cursor
|
||||
match &self.deployed_from {
|
||||
Some(CodeActionSource::Indicator(row)) => ContextMenuOrigin::GutterIndicator(*row),
|
||||
Some(CodeActionSource::QuickActionBar) => ContextMenuOrigin::QuickActionBar,
|
||||
None => ContextMenuOrigin::Cursor,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
pub mod actions;
|
||||
mod blink_manager;
|
||||
mod clangd_ext;
|
||||
mod code_context_menus;
|
||||
pub mod code_context_menus;
|
||||
pub mod display_map;
|
||||
mod editor_settings;
|
||||
mod editor_settings_controls;
|
||||
|
@ -777,7 +777,7 @@ impl RunnableTasks {
|
|||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct ResolvedTasks {
|
||||
pub struct ResolvedTasks {
|
||||
templates: SmallVec<[(TaskSourceKind, ResolvedTask); 1]>,
|
||||
position: Anchor,
|
||||
}
|
||||
|
@ -5375,7 +5375,7 @@ impl Editor {
|
|||
let quick_launch = action.quick_launch;
|
||||
let mut context_menu = self.context_menu.borrow_mut();
|
||||
if let Some(CodeContextMenu::CodeActions(code_actions)) = context_menu.as_ref() {
|
||||
if code_actions.deployed_from_indicator == action.deployed_from_indicator {
|
||||
if code_actions.deployed_from == action.deployed_from {
|
||||
// Toggle if we're selecting the same one
|
||||
*context_menu = None;
|
||||
cx.notify();
|
||||
|
@ -5388,7 +5388,7 @@ impl Editor {
|
|||
}
|
||||
drop(context_menu);
|
||||
let snapshot = self.snapshot(window, cx);
|
||||
let deployed_from_indicator = action.deployed_from_indicator;
|
||||
let deployed_from = action.deployed_from.clone();
|
||||
let mut task = self.code_actions_task.take();
|
||||
let action = action.clone();
|
||||
cx.spawn_in(window, async move |editor, cx| {
|
||||
|
@ -5399,10 +5399,12 @@ impl Editor {
|
|||
|
||||
let spawned_test_task = editor.update_in(cx, |editor, window, cx| {
|
||||
if editor.focus_handle.is_focused(window) {
|
||||
let multibuffer_point = action
|
||||
.deployed_from_indicator
|
||||
.map(|row| DisplayPoint::new(row, 0).to_point(&snapshot))
|
||||
.unwrap_or_else(|| editor.selections.newest::<Point>(cx).head());
|
||||
let multibuffer_point = match &action.deployed_from {
|
||||
Some(CodeActionSource::Indicator(row)) => {
|
||||
DisplayPoint::new(*row, 0).to_point(&snapshot)
|
||||
}
|
||||
_ => editor.selections.newest::<Point>(cx).head(),
|
||||
};
|
||||
let (buffer, buffer_row) = snapshot
|
||||
.buffer_snapshot
|
||||
.buffer_line_for_row(MultiBufferRow(multibuffer_point.row))
|
||||
|
@ -5526,7 +5528,7 @@ impl Editor {
|
|||
),
|
||||
selected_item: Default::default(),
|
||||
scroll_handle: UniformListScrollHandle::default(),
|
||||
deployed_from_indicator,
|
||||
deployed_from,
|
||||
}));
|
||||
if spawn_straight_away {
|
||||
if let Some(task) = editor.confirm_code_action(
|
||||
|
@ -5746,6 +5748,21 @@ impl Editor {
|
|||
self.refresh_code_actions(window, cx);
|
||||
}
|
||||
|
||||
pub fn code_actions_enabled(&self, cx: &App) -> bool {
|
||||
!self.code_action_providers.is_empty()
|
||||
&& EditorSettings::get_global(cx).toolbar.code_actions
|
||||
}
|
||||
|
||||
pub fn has_available_code_actions(&self) -> bool {
|
||||
self.available_code_actions
|
||||
.as_ref()
|
||||
.is_some_and(|(_, actions)| !actions.is_empty())
|
||||
}
|
||||
|
||||
pub fn context_menu(&self) -> &RefCell<Option<CodeContextMenu>> {
|
||||
&self.context_menu
|
||||
}
|
||||
|
||||
fn refresh_code_actions(&mut self, window: &mut Window, cx: &mut Context<Self>) -> Option<()> {
|
||||
let newest_selection = self.selections.newest_anchor().clone();
|
||||
let newest_selection_adjusted = self.selections.newest_adjusted(cx).clone();
|
||||
|
@ -7498,7 +7515,7 @@ impl Editor {
|
|||
window.focus(&editor.focus_handle(cx));
|
||||
editor.toggle_code_actions(
|
||||
&ToggleCodeActions {
|
||||
deployed_from_indicator: Some(row),
|
||||
deployed_from: Some(CodeActionSource::Indicator(row)),
|
||||
quick_launch,
|
||||
},
|
||||
window,
|
||||
|
@ -7519,7 +7536,7 @@ impl Editor {
|
|||
.map_or(false, |menu| menu.visible())
|
||||
}
|
||||
|
||||
fn context_menu_origin(&self) -> Option<ContextMenuOrigin> {
|
||||
pub fn context_menu_origin(&self) -> Option<ContextMenuOrigin> {
|
||||
self.context_menu
|
||||
.borrow()
|
||||
.as_ref()
|
||||
|
@ -8538,7 +8555,7 @@ impl Editor {
|
|||
}
|
||||
}
|
||||
|
||||
fn render_context_menu(
|
||||
pub fn render_context_menu(
|
||||
&self,
|
||||
style: &EditorStyle,
|
||||
max_height_in_lines: u32,
|
||||
|
|
|
@ -109,6 +109,7 @@ pub struct Toolbar {
|
|||
pub quick_actions: bool,
|
||||
pub selections_menu: bool,
|
||||
pub agent_review: bool,
|
||||
pub code_actions: bool,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize, JsonSchema, PartialEq, Eq)]
|
||||
|
@ -503,6 +504,10 @@ pub struct ToolbarContent {
|
|||
///
|
||||
/// Default: true
|
||||
pub agent_review: Option<bool>,
|
||||
/// Whether to display code action buttons in the editor toolbar.
|
||||
///
|
||||
/// Default: true
|
||||
pub code_actions: Option<bool>,
|
||||
}
|
||||
|
||||
/// Scrollbar related settings
|
||||
|
|
|
@ -14243,7 +14243,7 @@ async fn test_context_menus_hide_hover_popover(cx: &mut gpui::TestAppContext) {
|
|||
cx.update_editor(|editor, window, cx| {
|
||||
editor.toggle_code_actions(
|
||||
&ToggleCodeActions {
|
||||
deployed_from_indicator: None,
|
||||
deployed_from: None,
|
||||
quick_launch: false,
|
||||
},
|
||||
window,
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use crate::{
|
||||
ActiveDiagnostic, BlockId, COLUMNAR_SELECTION_MODIFIERS, CURSORS_VISIBLE_FOR,
|
||||
ChunkRendererContext, ChunkReplacement, ConflictsOurs, ConflictsOursMarker, ConflictsOuter,
|
||||
ConflictsTheirs, ConflictsTheirsMarker, ContextMenuPlacement, CursorShape, CustomBlockId,
|
||||
DisplayDiffHunk, DisplayPoint, DisplayRow, DocumentHighlightRead, DocumentHighlightWrite,
|
||||
EditDisplayMode, Editor, EditorMode, EditorSettings, EditorSnapshot, EditorStyle,
|
||||
FILE_HEADER_HEIGHT, FocusedBlock, GutterDimensions, HalfPageDown, HalfPageUp, HandleInput,
|
||||
HoveredCursor, InlayHintRefreshReason, InlineCompletion, JumpData, LineDown, LineHighlight,
|
||||
LineUp, MAX_LINE_LEN, MIN_LINE_NUMBER_DIGITS, MINIMAP_FONT_SIZE,
|
||||
ChunkRendererContext, ChunkReplacement, CodeActionSource, ConflictsOurs, ConflictsOursMarker,
|
||||
ConflictsOuter, ConflictsTheirs, ConflictsTheirsMarker, ContextMenuPlacement, CursorShape,
|
||||
CustomBlockId, DisplayDiffHunk, DisplayPoint, DisplayRow, DocumentHighlightRead,
|
||||
DocumentHighlightWrite, EditDisplayMode, Editor, EditorMode, EditorSettings, EditorSnapshot,
|
||||
EditorStyle, FILE_HEADER_HEIGHT, FocusedBlock, GutterDimensions, HalfPageDown, HalfPageUp,
|
||||
HandleInput, HoveredCursor, InlayHintRefreshReason, InlineCompletion, JumpData, LineDown,
|
||||
LineHighlight, LineUp, MAX_LINE_LEN, MIN_LINE_NUMBER_DIGITS, MINIMAP_FONT_SIZE,
|
||||
MULTI_BUFFER_EXCERPT_HEADER_HEIGHT, OpenExcerpts, PageDown, PageUp, PhantomBreakpointIndicator,
|
||||
Point, RowExt, RowRangeExt, SelectPhase, SelectedTextHighlight, Selection, SoftWrap,
|
||||
StickyHeaderExcerpt, ToPoint, ToggleFold,
|
||||
|
@ -2385,7 +2385,7 @@ impl EditorElement {
|
|||
self.editor.update(cx, |editor, cx| {
|
||||
let active_task_indicator_row =
|
||||
if let Some(crate::CodeContextMenu::CodeActions(CodeActionsMenu {
|
||||
deployed_from_indicator,
|
||||
deployed_from,
|
||||
actions,
|
||||
..
|
||||
})) = editor.context_menu.borrow().as_ref()
|
||||
|
@ -2393,7 +2393,10 @@ impl EditorElement {
|
|||
actions
|
||||
.tasks()
|
||||
.map(|tasks| tasks.position.to_display_point(snapshot).row())
|
||||
.or(*deployed_from_indicator)
|
||||
.or_else(|| match deployed_from {
|
||||
Some(CodeActionSource::Indicator(row)) => Some(*row),
|
||||
_ => None,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
|
|
@ -226,7 +226,7 @@ pub fn deploy_context_menu(
|
|||
.action(
|
||||
"Show Code Actions",
|
||||
Box::new(ToggleCodeActions {
|
||||
deployed_from_indicator: None,
|
||||
deployed_from: None,
|
||||
quick_launch: false,
|
||||
}),
|
||||
)
|
||||
|
|
|
@ -41,6 +41,7 @@ pub enum IconName {
|
|||
Binary,
|
||||
Blocks,
|
||||
Bolt,
|
||||
BoltFilled,
|
||||
Book,
|
||||
BookCopy,
|
||||
BookPlus,
|
||||
|
|
|
@ -411,7 +411,7 @@ impl PickerDelegate for TasksModalDelegate {
|
|||
color: Color::Default,
|
||||
};
|
||||
let icon = match source_kind {
|
||||
TaskSourceKind::Lsp(..) => Some(Icon::new(IconName::Bolt)),
|
||||
TaskSourceKind::Lsp(..) => Some(Icon::new(IconName::BoltFilled)),
|
||||
TaskSourceKind::UserInput => Some(Icon::new(IconName::Terminal)),
|
||||
TaskSourceKind::AbsPath { .. } => Some(Icon::new(IconName::Settings)),
|
||||
TaskSourceKind::Worktree { .. } => Some(Icon::new(IconName::FileTree)),
|
||||
|
|
|
@ -18,12 +18,12 @@ impl Render for ListHeaderStory {
|
|||
.child(
|
||||
ListHeader::new("Section 3")
|
||||
.start_slot(Icon::new(IconName::BellOff))
|
||||
.end_slot(IconButton::new("action_1", IconName::Bolt)),
|
||||
.end_slot(IconButton::new("action_1", IconName::BoltFilled)),
|
||||
)
|
||||
.child(Story::label("With multiple meta", cx))
|
||||
.child(
|
||||
ListHeader::new("Section 4")
|
||||
.end_slot(IconButton::new("action_1", IconName::Bolt))
|
||||
.end_slot(IconButton::new("action_1", IconName::BoltFilled))
|
||||
.end_slot(IconButton::new("action_2", IconName::Warning))
|
||||
.end_slot(IconButton::new("action_3", IconName::Plus)),
|
||||
)
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
mod markdown_preview;
|
||||
mod repl_menu;
|
||||
|
||||
use assistant_settings::AssistantSettings;
|
||||
use editor::actions::{
|
||||
AddSelectionAbove, AddSelectionBelow, DuplicateLineDown, GoToDiagnostic, GoToHunk,
|
||||
GoToPreviousDiagnostic, GoToPreviousHunk, MoveLineDown, MoveLineUp, SelectAll,
|
||||
SelectLargerSyntaxNode, SelectNext, SelectSmallerSyntaxNode, ToggleDiagnostics, ToggleGoToLine,
|
||||
ToggleInlineDiagnostics,
|
||||
AddSelectionAbove, AddSelectionBelow, CodeActionSource, DuplicateLineDown, GoToDiagnostic,
|
||||
GoToHunk, GoToPreviousDiagnostic, GoToPreviousHunk, MoveLineDown, MoveLineUp, SelectAll,
|
||||
SelectLargerSyntaxNode, SelectNext, SelectSmallerSyntaxNode, ToggleCodeActions,
|
||||
ToggleDiagnostics, ToggleGoToLine, ToggleInlineDiagnostics,
|
||||
};
|
||||
use editor::code_context_menus::{CodeContextMenu, ContextMenuOrigin};
|
||||
use editor::{Editor, EditorSettings};
|
||||
use gpui::{
|
||||
Action, ClickEvent, Context, Corner, ElementId, Entity, EventEmitter, FocusHandle, Focusable,
|
||||
InteractiveElement, ParentElement, Render, Styled, Subscription, WeakEntity, Window,
|
||||
Action, AnchoredPositionMode, ClickEvent, Context, Corner, ElementId, Entity, EventEmitter,
|
||||
FocusHandle, Focusable, InteractiveElement, ParentElement, Render, Styled, Subscription,
|
||||
WeakEntity, Window, anchored, deferred, point,
|
||||
};
|
||||
use project::project_settings::DiagnosticSeverity;
|
||||
use search::{BufferSearchBar, buffer_search};
|
||||
|
@ -26,6 +27,8 @@ use workspace::{
|
|||
};
|
||||
use zed_actions::{assistant::InlineAssist, outline::ToggleOutline};
|
||||
|
||||
const MAX_CODE_ACTION_MENU_LINES: u32 = 16;
|
||||
|
||||
pub struct QuickActionBar {
|
||||
_inlay_hints_enabled_subscription: Option<Subscription>,
|
||||
active_item: Option<Box<dyn ItemHandle>>,
|
||||
|
@ -83,7 +86,7 @@ impl QuickActionBar {
|
|||
}
|
||||
|
||||
impl Render for QuickActionBar {
|
||||
fn render(&mut self, _: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
|
||||
let Some(editor) = self.active_editor() else {
|
||||
return div().id("empty quick action bar");
|
||||
};
|
||||
|
@ -107,7 +110,8 @@ impl Render for QuickActionBar {
|
|||
editor_value.edit_predictions_enabled_at_cursor(cx);
|
||||
let supports_minimap = editor_value.supports_minimap(cx);
|
||||
let minimap_enabled = supports_minimap && editor_value.minimap().is_some();
|
||||
|
||||
let has_available_code_actions = editor_value.has_available_code_actions();
|
||||
let code_action_enabled = editor_value.code_actions_enabled(cx);
|
||||
let focus_handle = editor_value.focus_handle(cx);
|
||||
|
||||
let search_button = editor.is_singleton(cx).then(|| {
|
||||
|
@ -141,6 +145,78 @@ impl Render for QuickActionBar {
|
|||
},
|
||||
);
|
||||
|
||||
let code_actions_dropdown = code_action_enabled.then(|| {
|
||||
let focus = editor.focus_handle(cx);
|
||||
let (code_action_menu_active, is_deployed_from_quick_action) = {
|
||||
let menu_ref = editor.read(cx).context_menu().borrow();
|
||||
let code_action_menu = menu_ref
|
||||
.as_ref()
|
||||
.filter(|menu| matches!(menu, CodeContextMenu::CodeActions(..)));
|
||||
let is_deployed = code_action_menu.as_ref().map_or(false, |menu| {
|
||||
matches!(menu.origin(), ContextMenuOrigin::QuickActionBar)
|
||||
});
|
||||
(code_action_menu.is_some(), is_deployed)
|
||||
};
|
||||
let code_action_element = if is_deployed_from_quick_action {
|
||||
editor.update(cx, |editor, cx| {
|
||||
if let Some(style) = editor.style() {
|
||||
editor.render_context_menu(&style, MAX_CODE_ACTION_MENU_LINES, window, cx)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
v_flex()
|
||||
.child(
|
||||
IconButton::new("toggle_code_actions_icon", IconName::Bolt)
|
||||
.icon_size(IconSize::Small)
|
||||
.style(ButtonStyle::Subtle)
|
||||
.disabled(!has_available_code_actions)
|
||||
.toggle_state(code_action_menu_active)
|
||||
.when(!code_action_menu_active, |this| {
|
||||
this.when(has_available_code_actions, |this| {
|
||||
this.tooltip(Tooltip::for_action_title(
|
||||
"Code Actions",
|
||||
&ToggleCodeActions::default(),
|
||||
))
|
||||
})
|
||||
.when(
|
||||
!has_available_code_actions,
|
||||
|this| {
|
||||
this.tooltip(Tooltip::for_action_title(
|
||||
"No Code Actions Available",
|
||||
&ToggleCodeActions::default(),
|
||||
))
|
||||
},
|
||||
)
|
||||
})
|
||||
.on_click({
|
||||
let focus = focus.clone();
|
||||
move |_, window, cx| {
|
||||
focus.dispatch_action(
|
||||
&ToggleCodeActions {
|
||||
deployed_from: Some(CodeActionSource::QuickActionBar),
|
||||
quick_launch: false,
|
||||
},
|
||||
window,
|
||||
cx,
|
||||
);
|
||||
}
|
||||
}),
|
||||
)
|
||||
.children(code_action_element.map(|menu| {
|
||||
deferred(
|
||||
anchored()
|
||||
.position_mode(AnchoredPositionMode::Local)
|
||||
.position(point(px(20.), px(20.)))
|
||||
.anchor(Corner::TopRight)
|
||||
.child(menu),
|
||||
)
|
||||
}))
|
||||
});
|
||||
|
||||
let editor_selections_dropdown = selection_menu_enabled.then(|| {
|
||||
let focus = editor.focus_handle(cx);
|
||||
|
||||
|
@ -487,6 +563,7 @@ impl Render for QuickActionBar {
|
|||
&& AssistantSettings::get_global(cx).button,
|
||||
|bar| bar.child(assistant_button),
|
||||
)
|
||||
.children(code_actions_dropdown)
|
||||
.children(editor_selections_dropdown)
|
||||
.child(editor_settings_dropdown)
|
||||
}
|
||||
|
|
|
@ -1214,7 +1214,8 @@ or
|
|||
"breadcrumbs": true,
|
||||
"quick_actions": true,
|
||||
"selections_menu": true,
|
||||
"agent_review": true
|
||||
"agent_review": true,
|
||||
"code_actions": true
|
||||
},
|
||||
```
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue