1use fs::Fs;
2use gpui::{FocusHandle, View};
3use language_model::LanguageModelRegistry;
4use language_model_selector::{LanguageModelSelector, LanguageModelSelectorPopoverMenu};
5use settings::update_settings_file;
6use std::sync::Arc;
7use ui::{prelude::*, ButtonLike, PopoverMenuHandle, Tooltip};
8
9use crate::{assistant_settings::AssistantSettings, ToggleModelSelector};
10
11pub struct AssistantModelSelector {
12 selector: View<LanguageModelSelector>,
13 menu_handle: PopoverMenuHandle<LanguageModelSelector>,
14 focus_handle: FocusHandle,
15}
16
17impl AssistantModelSelector {
18 pub(crate) fn new(
19 fs: Arc<dyn Fs>,
20 menu_handle: PopoverMenuHandle<LanguageModelSelector>,
21 focus_handle: FocusHandle,
22 cx: &mut WindowContext,
23 ) -> Self {
24 Self {
25 selector: cx.new_view(|cx| {
26 let fs = fs.clone();
27 LanguageModelSelector::new(
28 move |model, cx| {
29 update_settings_file::<AssistantSettings>(
30 fs.clone(),
31 cx,
32 move |settings, _cx| settings.set_model(model.clone()),
33 );
34 },
35 cx,
36 )
37 }),
38 menu_handle,
39 focus_handle,
40 }
41 }
42}
43
44impl Render for AssistantModelSelector {
45 fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
46 let active_model = LanguageModelRegistry::read_global(cx).active_model();
47 let focus_handle = self.focus_handle.clone();
48
49 LanguageModelSelectorPopoverMenu::new(
50 self.selector.clone(),
51 ButtonLike::new("active-model")
52 .style(ButtonStyle::Subtle)
53 .child(
54 h_flex()
55 .gap_0p5()
56 .child(
57 div()
58 .overflow_x_hidden()
59 .flex_grow()
60 .whitespace_nowrap()
61 .child(match active_model {
62 Some(model) => h_flex()
63 .child(
64 Label::new(model.name().0)
65 .size(LabelSize::Small)
66 .color(Color::Muted),
67 )
68 .into_any_element(),
69 _ => Label::new("No model selected")
70 .size(LabelSize::Small)
71 .color(Color::Muted)
72 .into_any_element(),
73 }),
74 )
75 .child(
76 Icon::new(IconName::ChevronDown)
77 .color(Color::Muted)
78 .size(IconSize::XSmall),
79 ),
80 )
81 .tooltip(move |cx| {
82 Tooltip::for_action_in("Change Model", &ToggleModelSelector, &focus_handle, cx)
83 }),
84 )
85 .with_handle(self.menu_handle.clone())
86 }
87}