use gpui::{AnyElement, App, IntoElement, RenderOnce, SharedString, Window, div, prelude::*, px};
use liora_core::Config;
use liora_icons::Icon;
use liora_icons_lucide::IconName;
pub struct Empty {
image: Option<AnyElement>,
description: SharedString,
extra: Option<Box<dyn Fn(&mut Window, &mut App) -> AnyElement + 'static>>,
}
impl Empty {
pub fn new() -> Self {
Self {
image: None,
description: "暂无数据".into(),
extra: None,
}
}
pub fn image(mut self, image: impl IntoElement) -> Self {
self.image = Some(image.into_any_element());
self
}
pub fn description(mut self, d: impl Into<SharedString>) -> Self {
self.description = d.into();
self
}
pub fn extra<F>(mut self, f: F) -> Self
where
F: Fn(&mut Window, &mut App) -> AnyElement + 'static,
{
self.extra = Some(Box::new(f));
self
}
}
impl RenderOnce for Empty {
fn render(self, window: &mut Window, cx: &mut App) -> impl IntoElement {
let theme = cx.global::<Config>().theme.clone();
div()
.flex()
.flex_col()
.items_center()
.justify_center()
.w_full()
.p_10()
.gap_4()
.child(
div()
.flex()
.items_center()
.justify_center()
.w(px(160.0))
.h(px(160.0))
.child(match self.image {
Some(img) => img,
None => Icon::new(IconName::PackageOpen)
.size(px(100.0))
.color(theme.neutral.text_3)
.into_any_element(),
}),
)
.child(
div()
.text_sm()
.text_color(theme.neutral.text_3)
.child(self.description),
)
.when_some(self.extra, |s, extra| {
s.child(div().mt_2().child((extra)(window, cx)))
})
}
}
impl IntoElement for Empty {
type Element = gpui::Component<Self>;
fn into_element(self) -> Self::Element {
gpui::Component::new(self)
}
}