use std::rc::Rc;
use gpui::prelude::*;
use gpui::{div, px, App, IntoElement, SharedString, Window};
use super::AISource;
use crate::devtools::Probed;
use crate::icon::{Icon, IconName};
use crate::theme::{theme, ColorName, Size};
type SourceHandler = Rc<dyn Fn(usize, &mut Window, &mut App) + 'static>;
#[derive(IntoElement)]
pub struct AISources {
sources: Vec<AISource>,
title: Option<SharedString>,
size: Size,
excerpts: bool,
on_open: Option<SourceHandler>,
}
impl AISources {
pub fn new(sources: impl IntoIterator<Item = AISource>) -> Self {
AISources {
sources: sources.into_iter().collect(),
title: None,
size: Size::Xs,
excerpts: false,
on_open: None,
}
}
pub fn title(mut self, title: impl Into<SharedString>) -> Self {
self.title = Some(title.into());
self
}
pub fn size(mut self, size: Size) -> Self {
self.size = size;
self
}
pub fn excerpts(mut self, excerpts: bool) -> Self {
self.excerpts = excerpts;
self
}
pub fn on_open(mut self, handler: impl Fn(usize, &mut Window, &mut App) + 'static) -> Self {
self.on_open = Some(Rc::new(handler));
self
}
}
impl RenderOnce for AISources {
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let t = theme(cx);
let font = t.font_size(self.size);
let dimmed = t.dimmed().hsla();
let text_color = t.text().hsla();
let border = t.border().hsla();
let surface = t.surface_hover().alpha(0.5);
let radius = t.radius(Size::Sm);
let mut list = div().flex().flex_col().gap(px(4.0)).w_full();
if let Some(title) = self.title {
list = list.child(
div()
.flex()
.items_center()
.gap(px(6.0))
.text_size(px(font))
.text_color(dimmed)
.child(
Icon::new(IconName::BookOpen)
.size(Size::Xs)
.color(ColorName::Gray),
)
.child(title),
);
}
for (index, source) in self.sources.into_iter().enumerate() {
let handler = self.on_open.clone();
list = list.child(
div()
.id(("guise-ai-source", index))
.flex()
.flex_row()
.items_start()
.gap(px(8.0))
.w_full()
.px(px(8.0))
.py(px(6.0))
.rounded(px(radius))
.border_1()
.border_color(border)
.text_size(px(font))
.when(handler.is_some(), |row| {
row.cursor_pointer().hover(move |row| row.bg(surface))
})
.child(
div()
.flex_none()
.min_w(px(font * 1.4))
.text_color(dimmed)
.child(SharedString::from((index + 1).to_string())),
)
.child(
div()
.flex()
.flex_col()
.gap(px(1.0))
.flex_1()
.min_w(px(0.0))
.child(
div()
.text_color(text_color)
.child(SharedString::from(source.title)),
)
.child(
div()
.text_color(dimmed)
.child(SharedString::from(source.location)),
)
.when_some(
source.excerpt.filter(|_| self.excerpts),
|column, excerpt| {
column.child(
div()
.mt(px(4.0))
.pl(px(8.0))
.border_l_2()
.border_color(border)
.text_color(dimmed)
.child(SharedString::from(excerpt)),
)
},
),
)
.when_some(handler, |row, handler| {
row.on_click(move |_event, window, cx| handler(index, window, cx))
}),
);
}
list.probe("AISources")
}
}