Fix focus handle leak (#26090)

This fixes a major performance issue in the current git beta.
This PR also removes the PopoverButton component, which was easy to
misuse.

Release Notes:

- Git Beta: Fix frame drops caused by opening the git panel

---------

Co-authored-by: Mikayla Maki <mikayla.c.maki@gmail.com>
This commit is contained in:
Conrad Irwin 2025-03-04 17:50:26 -07:00 committed by GitHub
parent fe18c73a07
commit 674fb7621f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 276 additions and 459 deletions

View file

@ -1,4 +1,4 @@
use std::sync::Arc;
use std::{rc::Rc, sync::Arc};
use feature_flags::ZedPro;
use gpui::{
@ -11,8 +11,8 @@ use language_model::{
use picker::{Picker, PickerDelegate};
use proto::Plan;
use ui::{
prelude::*, ButtonLike, IconButtonShape, ListItem, ListItemSpacing, PopoverButton,
PopoverMenuHandle, Tooltip, TriggerablePopover,
prelude::*, ButtonLike, IconButtonShape, ListItem, ListItemSpacing, PopoverMenu,
PopoverMenuHandle, Tooltip,
};
use workspace::ShowConfiguration;
@ -201,16 +201,6 @@ impl Render for LanguageModelSelector {
}
}
impl TriggerablePopover for LanguageModelSelector {
fn menu_handle(
&mut self,
_window: &mut Window,
_cx: &mut gpui::Context<Self>,
) -> PopoverMenuHandle<Self> {
self.popover_menu_handle.clone()
}
}
#[derive(Clone)]
struct ModelInfo {
model: Arc<dyn LanguageModel>,
@ -493,21 +483,26 @@ impl PickerDelegate for LanguageModelPickerDelegate {
}
}
pub struct InlineLanguageModelSelector {
selector: Entity<LanguageModelSelector>,
}
impl InlineLanguageModelSelector {
pub fn new(selector: Entity<LanguageModelSelector>) -> Self {
Self { selector }
}
}
impl RenderOnce for InlineLanguageModelSelector {
fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
PopoverButton::new(
self.selector,
gpui::Corner::TopRight,
pub fn inline_language_model_selector(
f: impl Fn(Arc<dyn LanguageModel>, &App) + 'static,
) -> AnyElement {
let f = Rc::new(f);
PopoverMenu::new("popover-button")
.menu(move |window, cx| {
Some(cx.new(|cx| {
LanguageModelSelector::new(
{
let f = f.clone();
move |model, cx| {
f(model, cx);
}
},
window,
cx,
)
}))
})
.trigger_with_tooltip(
IconButton::new("context", IconName::SettingsAlt)
.shape(IconButtonShape::Square)
.icon_size(IconSize::Small)
@ -528,36 +523,45 @@ impl RenderOnce for InlineLanguageModelSelector {
)
},
)
.render(window, cx)
}
.anchor(gpui::Corner::TopRight)
// .when_some(menu_handle, |el, handle| el.with_handle(handle))
.offset(gpui::Point {
x: px(0.0),
y: px(-2.0),
})
.into_any_element()
}
pub struct AssistantLanguageModelSelector {
focus_handle: FocusHandle,
selector: Entity<LanguageModelSelector>,
}
pub fn assistant_language_model_selector(
keybinding_target: FocusHandle,
menu_handle: Option<PopoverMenuHandle<LanguageModelSelector>>,
cx: &App,
f: impl Fn(Arc<dyn LanguageModel>, &App) + 'static,
) -> AnyElement {
let active_model = LanguageModelRegistry::read_global(cx).active_model();
let model_name = match active_model {
Some(model) => model.name().0,
_ => SharedString::from("No model selected"),
};
impl AssistantLanguageModelSelector {
pub fn new(focus_handle: FocusHandle, selector: Entity<LanguageModelSelector>) -> Self {
Self {
focus_handle,
selector,
}
}
}
let f = Rc::new(f);
impl RenderOnce for AssistantLanguageModelSelector {
fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
let active_model = LanguageModelRegistry::read_global(cx).active_model();
let focus_handle = self.focus_handle.clone();
let model_name = match active_model {
Some(model) => model.name().0,
_ => SharedString::from("No model selected"),
};
PopoverButton::new(
self.selector.clone(),
Corner::BottomRight,
PopoverMenu::new("popover-button")
.menu(move |window, cx| {
Some(cx.new(|cx| {
LanguageModelSelector::new(
{
let f = f.clone();
move |model, cx| {
f(model, cx);
}
},
window,
cx,
)
}))
})
.trigger_with_tooltip(
ButtonLike::new("active-model")
.style(ButtonStyle::Subtle)
.child(
@ -578,12 +582,17 @@ impl RenderOnce for AssistantLanguageModelSelector {
Tooltip::for_action_in(
"Change Model",
&ToggleModelSelector,
&focus_handle,
&keybinding_target,
window,
cx,
)
},
)
.render(window, cx)
}
.anchor(Corner::BottomRight)
.when_some(menu_handle, |el, handle| el.with_handle(handle))
.offset(gpui::Point {
x: px(0.0),
y: px(-2.0),
})
.into_any_element()
}