use crate::{prelude::*, *};
use std::sync::Arc;
#[derive(Clone)]
pub struct AttachmentItem {
pub name: SharedString,
pub size: Option<SharedString>,
}
impl AttachmentItem {
pub fn new(name: impl Into<SharedString>) -> Self {
Self {
name: name.into(),
size: None,
}
}
pub fn size(mut self, size: impl Into<SharedString>) -> Self {
self.size = Some(size.into());
self
}
}
#[derive(IntoElement)]
pub struct FileCard {
item: AttachmentItem,
on_remove: Option<Arc<dyn Fn(&mut Window, &mut App) + Send + Sync + 'static>>,
style: StyleRefinement,
}
impl FileCard {
pub fn new(item: AttachmentItem) -> Self {
Self {
item,
on_remove: None,
style: StyleRefinement::default(),
}
}
pub fn on_remove<F>(mut self, f: F) -> Self
where
F: Fn(&mut Window, &mut App) + Send + Sync + 'static,
{
self.on_remove = Some(Arc::new(f));
self
}
}
impl Styled for FileCard {
fn style(&mut self) -> &mut StyleRefinement {
&mut self.style
}
}
impl RenderOnce for FileCard {
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let theme = cx.theme();
let border = theme.tokens.border.color;
let popover = theme.tokens.popover;
let muted_foreground = theme.tokens.muted_foreground.color;
let user_style = self.style;
div()
.flex()
.flex_row()
.items_center()
.gap(px(8.0))
.px(px(10.0))
.py(px(8.0))
.rounded_md()
.border_1()
.border_color(border)
.bg(popover)
.child(div().text_color(muted_foreground).child(IconName::File))
.child(
div()
.flex()
.flex_col()
.flex_1()
.gap(px(2.0))
.child(div().text_sm().child(self.item.name))
.when_some(self.item.size, |this, size| {
this.child(div().text_xs().text_color(muted_foreground).child(size))
}),
)
.when_some(self.on_remove, |this, cb| {
this.child(
Button::new("file-card-remove")
.ghost()
.small()
.icon(IconName::Close)
.on_click(move |_, window, cx| cb(window, cx)),
)
})
.map(|mut this| {
this.style().refine(&user_style);
this
})
}
}
#[derive(IntoElement)]
pub struct Attachments {
items: Vec<AttachmentItem>,
on_remove: Option<Arc<dyn Fn(usize, &mut Window, &mut App) + Send + Sync + 'static>>,
}
impl Attachments {
pub fn new(items: Vec<AttachmentItem>) -> Self {
Self {
items,
on_remove: None,
}
}
pub fn on_remove<F>(mut self, f: F) -> Self
where
F: Fn(usize, &mut Window, &mut App) + Send + Sync + 'static,
{
self.on_remove = Some(Arc::new(f));
self
}
}
impl RenderOnce for Attachments {
fn render(self, _window: &mut Window, _cx: &mut App) -> impl IntoElement {
let on_remove = self.on_remove;
div().flex().flex_row().flex_wrap().gap(px(6.0)).children(
self.items.into_iter().enumerate().map(|(ix, item)| {
let mut card = FileCard::new(item);
if let Some(ref cb) = on_remove {
let cb = cb.clone();
card = card.on_remove(move |window, cx| cb(ix, window, cx));
}
card.into_any_element()
}),
)
}
}