use std::sync::Arc;
use gpui::SharedString;
use crate::prelude::*;
use crate::{ContextMenu, DropdownMenu, DropdownStyle};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SessionModeChoice {
Persistent,
Oneshot,
}
impl SessionModeChoice {
const ALL: [SessionModeChoice; 2] = [SessionModeChoice::Persistent, SessionModeChoice::Oneshot];
fn label(self) -> &'static str {
match self {
SessionModeChoice::Persistent => "Persistent",
SessionModeChoice::Oneshot => "One-shot",
}
}
}
#[derive(IntoElement, RegisterComponent)]
pub struct ModeSelector {
id: ElementId,
current: Option<SessionModeChoice>,
on_select: Option<Arc<dyn Fn(SessionModeChoice, &mut Window, &mut App) + 'static>>,
}
impl ModeSelector {
pub fn new(id: impl Into<ElementId>, current: Option<SessionModeChoice>) -> Self {
Self {
id: id.into(),
current,
on_select: None,
}
}
pub fn on_select(
mut self,
handler: impl Fn(SessionModeChoice, &mut Window, &mut App) + 'static,
) -> Self {
self.on_select = Some(Arc::new(handler));
self
}
}
impl RenderOnce for ModeSelector {
fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
let label: SharedString = self
.current
.map(SessionModeChoice::label)
.unwrap_or("Select mode")
.into();
let current = self.current;
let on_select = self.on_select.clone();
let menu = ContextMenu::build(window, cx, move |mut menu, _window, _cx| {
for mode in SessionModeChoice::ALL {
let is_current = current == Some(mode);
let on_select = on_select.clone();
menu = menu.toggleable_entry(
mode.label(),
is_current,
IconPosition::End,
None,
move |window, cx| {
if let Some(on_select) = &on_select {
on_select(mode, window, cx);
}
},
);
}
menu
});
DropdownMenu::new(self.id, label, menu).style(DropdownStyle::Subtle)
}
}
impl Component for ModeSelector {
fn scope() -> ComponentScope {
ComponentScope::Agent
}
fn name() -> &'static str {
"ModeSelector"
}
fn description() -> Option<&'static str> {
Some(
"A dropdown for picking whether an agent thread's session \
persists across requests or runs as a single one-shot exchange.",
)
}
fn preview(_window: &mut Window, _cx: &mut App) -> Option<AnyElement> {
Some(
v_flex()
.gap_4()
.child(single_example(
"Persistent selected",
ModeSelector::new("mode-selector-1", Some(SessionModeChoice::Persistent))
.into_any_element(),
))
.child(single_example(
"One-shot selected",
ModeSelector::new("mode-selector-2", Some(SessionModeChoice::Oneshot))
.into_any_element(),
))
.child(single_example(
"No selection",
ModeSelector::new("mode-selector-3", None).into_any_element(),
))
.into_any_element(),
)
}
}