Detailed changes
@@ -55,7 +55,7 @@ use language_model::{
LanguageModelProvider, LanguageModelProviderId, LanguageModelRegistry, Role,
ZED_CLOUD_PROVIDER_ID,
};
-use language_model_selector::{LanguageModelPickerDelegate, LanguageModelSelector};
+use language_model_selector::{LanguageModelSelector, LanguageModelSelectorPopoverMenu};
use multi_buffer::MultiBufferRow;
use picker::{Picker, PickerDelegate};
use project::lsp_store::LocalLspAdapterDelegate;
@@ -143,7 +143,7 @@ pub struct AssistantPanel {
languages: Arc<LanguageRegistry>,
fs: Arc<dyn Fs>,
subscriptions: Vec<Subscription>,
- model_selector_menu_handle: PopoverMenuHandle<Picker<LanguageModelPickerDelegate>>,
+ model_selector_menu_handle: PopoverMenuHandle<LanguageModelSelector>,
model_summary_editor: View<Editor>,
authenticate_provider_task: Option<(LanguageModelProviderId, Task<()>)>,
configuration_subscription: Option<Subscription>,
@@ -341,11 +341,12 @@ impl AssistantPanel {
) -> Self {
let model_selector_menu_handle = PopoverMenuHandle::default();
let model_summary_editor = cx.new_view(Editor::single_line);
- let context_editor_toolbar = cx.new_view(|_| {
+ let context_editor_toolbar = cx.new_view(|cx| {
ContextEditorToolbarItem::new(
workspace,
model_selector_menu_handle.clone(),
model_summary_editor.clone(),
+ cx,
)
});
@@ -4455,23 +4456,36 @@ impl FollowableItem for ContextEditor {
}
pub struct ContextEditorToolbarItem {
- fs: Arc<dyn Fs>,
active_context_editor: Option<WeakView<ContextEditor>>,
model_summary_editor: View<Editor>,
- model_selector_menu_handle: PopoverMenuHandle<Picker<LanguageModelPickerDelegate>>,
+ language_model_selector: View<LanguageModelSelector>,
+ language_model_selector_menu_handle: PopoverMenuHandle<LanguageModelSelector>,
}
impl ContextEditorToolbarItem {
pub fn new(
workspace: &Workspace,
- model_selector_menu_handle: PopoverMenuHandle<Picker<LanguageModelPickerDelegate>>,
+ model_selector_menu_handle: PopoverMenuHandle<LanguageModelSelector>,
model_summary_editor: View<Editor>,
+ cx: &mut ViewContext<Self>,
) -> Self {
Self {
- fs: workspace.app_state().fs.clone(),
active_context_editor: None,
model_summary_editor,
- model_selector_menu_handle,
+ language_model_selector: cx.new_view(|cx| {
+ let fs = workspace.app_state().fs.clone();
+ LanguageModelSelector::new(
+ move |model, cx| {
+ update_settings_file::<AssistantSettings>(
+ fs.clone(),
+ cx,
+ move |settings, _| settings.set_model(model.clone()),
+ );
+ },
+ cx,
+ )
+ }),
+ language_model_selector_menu_handle: model_selector_menu_handle,
}
}
@@ -4560,17 +4574,8 @@ impl Render for ContextEditorToolbarItem {
// .map(|remaining_items| format!("Files to scan: {}", remaining_items))
// })
.child(
- LanguageModelSelector::new(
- {
- let fs = self.fs.clone();
- move |model, cx| {
- update_settings_file::<AssistantSettings>(
- fs.clone(),
- cx,
- move |settings, _| settings.set_model(model.clone()),
- );
- }
- },
+ LanguageModelSelectorPopoverMenu::new(
+ self.language_model_selector.clone(),
ButtonLike::new("active-model")
.style(ButtonStyle::Subtle)
.child(
@@ -4616,7 +4621,7 @@ impl Render for ContextEditorToolbarItem {
Tooltip::for_action("Change Model", &ToggleModelSelector, cx)
}),
)
- .with_handle(self.model_selector_menu_handle.clone()),
+ .with_handle(self.language_model_selector_menu_handle.clone()),
)
.children(self.render_remaining_tokens(cx));
@@ -33,7 +33,7 @@ use language_model::{
LanguageModel, LanguageModelRegistry, LanguageModelRequest, LanguageModelRequestMessage,
LanguageModelTextStream, Role,
};
-use language_model_selector::LanguageModelSelector;
+use language_model_selector::{LanguageModelSelector, LanguageModelSelectorPopoverMenu};
use language_models::report_assistant_event;
use multi_buffer::MultiBufferRow;
use parking_lot::Mutex;
@@ -1358,8 +1358,8 @@ enum PromptEditorEvent {
struct PromptEditor {
id: InlineAssistId,
- fs: Arc<dyn Fs>,
editor: View<Editor>,
+ language_model_selector: View<LanguageModelSelector>,
edited_since_done: bool,
gutter_dimensions: Arc<Mutex<GutterDimensions>>,
prompt_history: VecDeque<String>,
@@ -1500,43 +1500,27 @@ impl Render for PromptEditor {
.w(gutter_dimensions.full_width() + (gutter_dimensions.margin / 2.0))
.justify_center()
.gap_2()
- .child(
- LanguageModelSelector::new(
- {
- let fs = self.fs.clone();
- move |model, cx| {
- update_settings_file::<AssistantSettings>(
- fs.clone(),
- cx,
- move |settings, _| settings.set_model(model.clone()),
- );
- }
- },
- IconButton::new("context", IconName::SettingsAlt)
- .shape(IconButtonShape::Square)
- .icon_size(IconSize::Small)
- .icon_color(Color::Muted)
- .tooltip(move |cx| {
- Tooltip::with_meta(
- format!(
- "Using {}",
- LanguageModelRegistry::read_global(cx)
- .active_model()
- .map(|model| model.name().0)
- .unwrap_or_else(|| "No model selected".into()),
- ),
- None,
- "Change Model",
- cx,
- )
- }),
- )
- .info_text(
- "Inline edits use context\n\
- from the currently selected\n\
- assistant panel tab.",
- ),
- )
+ .child(LanguageModelSelectorPopoverMenu::new(
+ self.language_model_selector.clone(),
+ IconButton::new("context", IconName::SettingsAlt)
+ .shape(IconButtonShape::Square)
+ .icon_size(IconSize::Small)
+ .icon_color(Color::Muted)
+ .tooltip(move |cx| {
+ Tooltip::with_meta(
+ format!(
+ "Using {}",
+ LanguageModelRegistry::read_global(cx)
+ .active_model()
+ .map(|model| model.name().0)
+ .unwrap_or_else(|| "No model selected".into()),
+ ),
+ None,
+ "Change Model",
+ cx,
+ )
+ }),
+ ))
.map(|el| {
let CodegenStatus::Error(error) = self.codegen.read(cx).status(cx) else {
return el;
@@ -1642,6 +1626,19 @@ impl PromptEditor {
let mut this = Self {
id,
editor: prompt_editor,
+ language_model_selector: cx.new_view(|cx| {
+ let fs = fs.clone();
+ LanguageModelSelector::new(
+ move |model, cx| {
+ update_settings_file::<AssistantSettings>(
+ fs.clone(),
+ cx,
+ move |settings, _| settings.set_model(model.clone()),
+ );
+ },
+ cx,
+ )
+ }),
edited_since_done: false,
gutter_dimensions,
prompt_history,
@@ -1650,7 +1647,6 @@ impl PromptEditor {
_codegen_subscription: cx.observe(&codegen, Self::handle_codegen_changed),
editor_subscriptions: Vec::new(),
codegen,
- fs,
pending_token_count: Task::ready(Ok(())),
token_counts: None,
_token_count_subscriptions: token_count_subscriptions,
@@ -20,7 +20,7 @@ use language::Buffer;
use language_model::{
LanguageModelRegistry, LanguageModelRequest, LanguageModelRequestMessage, Role,
};
-use language_model_selector::LanguageModelSelector;
+use language_model_selector::{LanguageModelSelector, LanguageModelSelectorPopoverMenu};
use language_models::report_assistant_event;
use settings::{update_settings_file, Settings};
use std::{
@@ -476,9 +476,9 @@ enum PromptEditorEvent {
struct PromptEditor {
id: TerminalInlineAssistId,
- fs: Arc<dyn Fs>,
height_in_lines: u8,
editor: View<Editor>,
+ language_model_selector: View<LanguageModelSelector>,
edited_since_done: bool,
prompt_history: VecDeque<String>,
prompt_history_ix: Option<usize>,
@@ -614,17 +614,8 @@ impl Render for PromptEditor {
.w_12()
.justify_center()
.gap_2()
- .child(LanguageModelSelector::new(
- {
- let fs = self.fs.clone();
- move |model, cx| {
- update_settings_file::<AssistantSettings>(
- fs.clone(),
- cx,
- move |settings, _| settings.set_model(model.clone()),
- );
- }
- },
+ .child(LanguageModelSelectorPopoverMenu::new(
+ self.language_model_selector.clone(),
IconButton::new("context", IconName::SettingsAlt)
.shape(IconButtonShape::Square)
.icon_size(IconSize::Small)
@@ -718,6 +709,19 @@ impl PromptEditor {
id,
height_in_lines: 1,
editor: prompt_editor,
+ language_model_selector: cx.new_view(|cx| {
+ let fs = fs.clone();
+ LanguageModelSelector::new(
+ move |model, cx| {
+ update_settings_file::<AssistantSettings>(
+ fs.clone(),
+ cx,
+ move |settings, _| settings.set_model(model.clone()),
+ );
+ },
+ cx,
+ )
+ }),
edited_since_done: false,
prompt_history,
prompt_history_ix: None,
@@ -725,7 +729,6 @@ impl PromptEditor {
_codegen_subscription: cx.observe(&codegen, Self::handle_codegen_changed),
editor_subscriptions: Vec::new(),
codegen,
- fs,
pending_token_count: Task::ready(Ok(())),
token_count: None,
_token_count_subscriptions: token_count_subscriptions,
@@ -31,7 +31,7 @@ use language_model::{
LanguageModel, LanguageModelRegistry, LanguageModelRequest, LanguageModelRequestMessage,
LanguageModelTextStream, Role,
};
-use language_model_selector::LanguageModelSelector;
+use language_model_selector::{LanguageModelSelector, LanguageModelSelectorPopoverMenu};
use language_models::report_assistant_event;
use multi_buffer::MultiBufferRow;
use parking_lot::Mutex;
@@ -1454,8 +1454,8 @@ enum PromptEditorEvent {
struct PromptEditor {
id: InlineAssistId,
- fs: Arc<dyn Fs>,
editor: View<Editor>,
+ language_model_selector: View<LanguageModelSelector>,
edited_since_done: bool,
gutter_dimensions: Arc<Mutex<GutterDimensions>>,
prompt_history: VecDeque<String>,
@@ -1589,43 +1589,27 @@ impl Render for PromptEditor {
.w(gutter_dimensions.full_width() + (gutter_dimensions.margin / 2.0))
.justify_center()
.gap_2()
- .child(
- LanguageModelSelector::new(
- {
- let fs = self.fs.clone();
- move |model, cx| {
- update_settings_file::<AssistantSettings>(
- fs.clone(),
- cx,
- move |settings, _| settings.set_model(model.clone()),
- );
- }
- },
- IconButton::new("context", IconName::SettingsAlt)
- .shape(IconButtonShape::Square)
- .icon_size(IconSize::Small)
- .icon_color(Color::Muted)
- .tooltip(move |cx| {
- Tooltip::with_meta(
- format!(
- "Using {}",
- LanguageModelRegistry::read_global(cx)
- .active_model()
- .map(|model| model.name().0)
- .unwrap_or_else(|| "No model selected".into()),
- ),
- None,
- "Change Model",
- cx,
- )
- }),
- )
- .info_text(
- "Inline edits use context\n\
- from the currently selected\n\
- assistant panel tab.",
- ),
- )
+ .child(LanguageModelSelectorPopoverMenu::new(
+ self.language_model_selector.clone(),
+ IconButton::new("context", IconName::SettingsAlt)
+ .shape(IconButtonShape::Square)
+ .icon_size(IconSize::Small)
+ .icon_color(Color::Muted)
+ .tooltip(move |cx| {
+ Tooltip::with_meta(
+ format!(
+ "Using {}",
+ LanguageModelRegistry::read_global(cx)
+ .active_model()
+ .map(|model| model.name().0)
+ .unwrap_or_else(|| "No model selected".into()),
+ ),
+ None,
+ "Change Model",
+ cx,
+ )
+ }),
+ ))
.map(|el| {
let CodegenStatus::Error(error) = self.codegen.read(cx).status(cx) else {
return el;
@@ -1714,6 +1698,19 @@ impl PromptEditor {
let mut this = Self {
id,
editor: prompt_editor,
+ language_model_selector: cx.new_view(|cx| {
+ let fs = fs.clone();
+ LanguageModelSelector::new(
+ move |model, cx| {
+ update_settings_file::<AssistantSettings>(
+ fs.clone(),
+ cx,
+ move |settings, _| settings.set_model(model.clone()),
+ );
+ },
+ cx,
+ )
+ }),
edited_since_done: false,
gutter_dimensions,
prompt_history,
@@ -1722,7 +1719,6 @@ impl PromptEditor {
_codegen_subscription: cx.observe(&codegen, Self::handle_codegen_changed),
editor_subscriptions: Vec::new(),
codegen,
- fs,
show_rate_limit_notice: false,
};
this.subscribe_to_editor(cx);
@@ -3,7 +3,7 @@ use std::rc::Rc;
use editor::{Editor, EditorElement, EditorStyle};
use gpui::{AppContext, FocusableView, Model, TextStyle, View, WeakView};
use language_model::{LanguageModelRegistry, LanguageModelRequestTool};
-use language_model_selector::LanguageModelSelector;
+use language_model_selector::{LanguageModelSelector, LanguageModelSelectorPopoverMenu};
use settings::Settings;
use theme::ThemeSettings;
use ui::{
@@ -25,6 +25,7 @@ pub struct MessageEditor {
next_context_id: ContextId,
context_picker: View<ContextPicker>,
pub(crate) context_picker_handle: PopoverMenuHandle<ContextPicker>,
+ language_model_selector: View<LanguageModelSelector>,
use_tools: bool,
}
@@ -47,6 +48,14 @@ impl MessageEditor {
next_context_id: ContextId(0),
context_picker: cx.new_view(|cx| ContextPicker::new(workspace.clone(), weak_self, cx)),
context_picker_handle: PopoverMenuHandle::default(),
+ language_model_selector: cx.new_view(|cx| {
+ LanguageModelSelector::new(
+ |model, _cx| {
+ println!("Selected {:?}", model.name());
+ },
+ cx,
+ )
+ }),
use_tools: false,
}
}
@@ -120,10 +129,8 @@ impl MessageEditor {
let active_provider = LanguageModelRegistry::read_global(cx).active_provider();
let active_model = LanguageModelRegistry::read_global(cx).active_model();
- LanguageModelSelector::new(
- |model, _cx| {
- println!("Selected {:?}", model.name());
- },
+ LanguageModelSelectorPopoverMenu::new(
+ self.language_model_selector.clone(),
ButtonLike::new("active-model")
.style(ButtonStyle::Subtle)
.child(
@@ -17,7 +17,7 @@ use language::Buffer;
use language_model::{
LanguageModelRegistry, LanguageModelRequest, LanguageModelRequestMessage, Role,
};
-use language_model_selector::LanguageModelSelector;
+use language_model_selector::{LanguageModelSelector, LanguageModelSelectorPopoverMenu};
use language_models::report_assistant_event;
use settings::{update_settings_file, Settings};
use std::{cmp, sync::Arc, time::Instant};
@@ -439,9 +439,9 @@ enum PromptEditorEvent {
struct PromptEditor {
id: TerminalInlineAssistId,
- fs: Arc<dyn Fs>,
height_in_lines: u8,
editor: View<Editor>,
+ language_model_selector: View<LanguageModelSelector>,
edited_since_done: bool,
prompt_history: VecDeque<String>,
prompt_history_ix: Option<usize>,
@@ -575,17 +575,8 @@ impl Render for PromptEditor {
.w_12()
.justify_center()
.gap_2()
- .child(LanguageModelSelector::new(
- {
- let fs = self.fs.clone();
- move |model, cx| {
- update_settings_file::<AssistantSettings>(
- fs.clone(),
- cx,
- move |settings, _| settings.set_model(model.clone()),
- );
- }
- },
+ .child(LanguageModelSelectorPopoverMenu::new(
+ self.language_model_selector.clone(),
IconButton::new("context", IconName::SettingsAlt)
.shape(IconButtonShape::Square)
.icon_size(IconSize::Small)
@@ -665,6 +656,19 @@ impl PromptEditor {
id,
height_in_lines: 1,
editor: prompt_editor,
+ language_model_selector: cx.new_view(|cx| {
+ let fs = fs.clone();
+ LanguageModelSelector::new(
+ move |model, cx| {
+ update_settings_file::<AssistantSettings>(
+ fs.clone(),
+ cx,
+ move |settings, _| settings.set_model(model.clone()),
+ );
+ },
+ cx,
+ )
+ }),
edited_since_done: false,
prompt_history,
prompt_history_ix: None,
@@ -672,7 +676,6 @@ impl PromptEditor {
_codegen_subscription: cx.observe(&codegen, Self::handle_codegen_changed),
editor_subscriptions: Vec::new(),
codegen,
- fs,
};
this.count_lines(cx);
this.subscribe_to_editor(cx);
@@ -1,7 +1,10 @@
use std::sync::Arc;
use feature_flags::ZedPro;
-use gpui::{Action, AnyElement, AppContext, DismissEvent, SharedString, Task};
+use gpui::{
+ Action, AnyElement, AppContext, DismissEvent, EventEmitter, FocusHandle, FocusableView, Task,
+ View, WeakView,
+};
use language_model::{LanguageModel, LanguageModelAvailability, LanguageModelRegistry};
use picker::{Picker, PickerDelegate};
use proto::Plan;
@@ -12,56 +15,118 @@ const TRY_ZED_PRO_URL: &str = "https://zed.dev/pro";
type OnModelChanged = Arc<dyn Fn(Arc<dyn LanguageModel>, &AppContext) + 'static>;
-#[derive(IntoElement)]
-pub struct LanguageModelSelector<T: PopoverTrigger> {
- handle: Option<PopoverMenuHandle<Picker<LanguageModelPickerDelegate>>>,
- on_model_changed: OnModelChanged,
- trigger: T,
- info_text: Option<SharedString>,
+pub struct LanguageModelSelector {
+ picker: View<Picker<LanguageModelPickerDelegate>>,
}
-pub struct LanguageModelPickerDelegate {
- on_model_changed: OnModelChanged,
- all_models: Vec<ModelInfo>,
- filtered_models: Vec<ModelInfo>,
- selected_index: usize,
+impl LanguageModelSelector {
+ pub fn new(
+ on_model_changed: impl Fn(Arc<dyn LanguageModel>, &AppContext) + 'static,
+ cx: &mut ViewContext<Self>,
+ ) -> Self {
+ let on_model_changed = Arc::new(on_model_changed);
+
+ let all_models = LanguageModelRegistry::global(cx)
+ .read(cx)
+ .providers()
+ .iter()
+ .flat_map(|provider| {
+ let icon = provider.icon();
+
+ provider.provided_models(cx).into_iter().map(move |model| {
+ let model = model.clone();
+ let icon = model.icon().unwrap_or(icon);
+
+ ModelInfo {
+ model: model.clone(),
+ icon,
+ availability: model.availability(),
+ }
+ })
+ })
+ .collect::<Vec<_>>();
+
+ let delegate = LanguageModelPickerDelegate {
+ language_model_selector: cx.view().downgrade(),
+ on_model_changed: on_model_changed.clone(),
+ all_models: all_models.clone(),
+ filtered_models: all_models,
+ selected_index: 0,
+ };
+
+ let picker =
+ cx.new_view(|cx| Picker::uniform_list(delegate, cx).max_height(Some(rems(20.).into())));
+
+ LanguageModelSelector { picker }
+ }
}
-#[derive(Clone)]
-struct ModelInfo {
- model: Arc<dyn LanguageModel>,
- icon: IconName,
- availability: LanguageModelAvailability,
- is_selected: bool,
+impl EventEmitter<DismissEvent> for LanguageModelSelector {}
+
+impl FocusableView for LanguageModelSelector {
+ fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
+ self.picker.focus_handle(cx)
+ }
}
-impl<T: PopoverTrigger> LanguageModelSelector<T> {
- pub fn new(
- on_model_changed: impl Fn(Arc<dyn LanguageModel>, &AppContext) + 'static,
- trigger: T,
- ) -> Self {
- LanguageModelSelector {
- handle: None,
- on_model_changed: Arc::new(on_model_changed),
+impl Render for LanguageModelSelector {
+ fn render(&mut self, _cx: &mut ViewContext<Self>) -> impl IntoElement {
+ self.picker.clone()
+ }
+}
+
+#[derive(IntoElement)]
+pub struct LanguageModelSelectorPopoverMenu<T>
+where
+ T: PopoverTrigger,
+{
+ language_model_selector: View<LanguageModelSelector>,
+ trigger: T,
+ handle: Option<PopoverMenuHandle<LanguageModelSelector>>,
+}
+
+impl<T: PopoverTrigger> LanguageModelSelectorPopoverMenu<T> {
+ pub fn new(language_model_selector: View<LanguageModelSelector>, trigger: T) -> Self {
+ Self {
+ language_model_selector,
trigger,
- info_text: None,
+ handle: None,
}
}
- pub fn with_handle(
- mut self,
- handle: PopoverMenuHandle<Picker<LanguageModelPickerDelegate>>,
- ) -> Self {
+ pub fn with_handle(mut self, handle: PopoverMenuHandle<LanguageModelSelector>) -> Self {
self.handle = Some(handle);
self
}
+}
- pub fn info_text(mut self, text: impl Into<SharedString>) -> Self {
- self.info_text = Some(text.into());
- self
+impl<T: PopoverTrigger> RenderOnce for LanguageModelSelectorPopoverMenu<T> {
+ fn render(self, _cx: &mut WindowContext) -> impl IntoElement {
+ let language_model_selector = self.language_model_selector.clone();
+
+ PopoverMenu::new("model-switcher")
+ .menu(move |_cx| Some(language_model_selector.clone()))
+ .trigger(self.trigger)
+ .attach(gpui::AnchorCorner::BottomLeft)
+ .when_some(self.handle.clone(), |menu, handle| menu.with_handle(handle))
}
}
+#[derive(Clone)]
+struct ModelInfo {
+ model: Arc<dyn LanguageModel>,
+ icon: IconName,
+ availability: LanguageModelAvailability,
+}
+
+pub struct LanguageModelPickerDelegate {
+ language_model_selector: WeakView<LanguageModelSelector>,
+ on_model_changed: OnModelChanged,
+ all_models: Vec<ModelInfo>,
+ filtered_models: Vec<ModelInfo>,
+ selected_index: usize,
+}
+
impl PickerDelegate for LanguageModelPickerDelegate {
type ListItem = ListItem;
@@ -142,23 +207,15 @@ impl PickerDelegate for LanguageModelPickerDelegate {
let model = model_info.model.clone();
(self.on_model_changed)(model.clone(), cx);
- // Update the selection status
- let selected_model_id = model_info.model.id();
- let selected_provider_id = model_info.model.provider_id();
- for model in &mut self.all_models {
- model.is_selected = model.model.id() == selected_model_id
- && model.model.provider_id() == selected_provider_id;
- }
- for model in &mut self.filtered_models {
- model.is_selected = model.model.id() == selected_model_id
- && model.model.provider_id() == selected_provider_id;
- }
-
cx.emit(DismissEvent);
}
}
- fn dismissed(&mut self, _cx: &mut ViewContext<Picker<Self>>) {}
+ fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {
+ self.language_model_selector
+ .update(cx, |_this, cx| cx.emit(DismissEvent))
+ .ok();
+ }
fn render_header(&self, cx: &mut ViewContext<Picker<Self>>) -> Option<AnyElement> {
let configured_models_count = LanguageModelRegistry::global(cx)
@@ -195,6 +252,17 @@ impl PickerDelegate for LanguageModelPickerDelegate {
let model_info = self.filtered_models.get(ix)?;
let provider_name: String = model_info.model.provider_name().0.clone().into();
+ let active_provider_id = LanguageModelRegistry::read_global(cx)
+ .active_provider()
+ .map(|m| m.id());
+
+ let active_model_id = LanguageModelRegistry::read_global(cx)
+ .active_model()
+ .map(|m| m.id());
+
+ let is_selected = Some(model_info.model.provider_id()) == active_provider_id
+ && Some(model_info.model.id()) == active_model_id;
+
Some(
ListItem::new(ix)
.inset(true)
@@ -235,7 +303,7 @@ impl PickerDelegate for LanguageModelPickerDelegate {
}),
),
)
- .end_slot(div().when(model_info.is_selected, |this| {
+ .end_slot(div().when(is_selected, |this| {
this.child(
Icon::new(IconName::Check)
.color(Color::Accent)
@@ -296,58 +364,3 @@ impl PickerDelegate for LanguageModelPickerDelegate {
)
}
}
-
-impl<T: PopoverTrigger> RenderOnce for LanguageModelSelector<T> {
- fn render(self, cx: &mut WindowContext) -> impl IntoElement {
- let selected_provider = LanguageModelRegistry::read_global(cx)
- .active_provider()
- .map(|m| m.id());
-
- let selected_model = LanguageModelRegistry::read_global(cx)
- .active_model()
- .map(|m| m.id());
-
- let all_models = LanguageModelRegistry::global(cx)
- .read(cx)
- .providers()
- .iter()
- .flat_map(|provider| {
- let provider_id = provider.id();
- let icon = provider.icon();
- let selected_model = selected_model.clone();
- let selected_provider = selected_provider.clone();
-
- provider.provided_models(cx).into_iter().map(move |model| {
- let model = model.clone();
- let icon = model.icon().unwrap_or(icon);
-
- ModelInfo {
- model: model.clone(),
- icon,
- availability: model.availability(),
- is_selected: selected_model.as_ref() == Some(&model.id())
- && selected_provider.as_ref() == Some(&provider_id),
- }
- })
- })
- .collect::<Vec<_>>();
-
- let delegate = LanguageModelPickerDelegate {
- on_model_changed: self.on_model_changed.clone(),
- all_models: all_models.clone(),
- filtered_models: all_models,
- selected_index: 0,
- };
-
- let picker_view = cx.new_view(|cx| {
- let picker = Picker::uniform_list(delegate, cx).max_height(Some(rems(20.).into()));
- picker
- });
-
- PopoverMenu::new("model-switcher")
- .menu(move |_cx| Some(picker_view.clone()))
- .trigger(self.trigger)
- .attach(gpui::AnchorCorner::BottomLeft)
- .when_some(self.handle, |menu, handle| menu.with_handle(handle))
- }
-}