use fluidattacks_designs_domain::notification_sign::{
display_count, Variant, COUNT_HEIGHT, COUNT_LINE_HEIGHT, COUNT_MIN_WIDTH, COUNT_PADDING_X,
DOT_PADDING, TEXT,
};
use fluidattacks_designs_domain::typography::{TextSize, FONT_PRIMARY};
use gpui::prelude::FluentBuilder as _;
use gpui::{div, px, rgb, App, IntoElement, ParentElement as _, RenderOnce, Styled as _, Window};
use crate::theme::ActiveTheme as _;
#[derive(IntoElement)]
pub struct NotificationSign {
variant: Variant,
count: Option<u32>,
show: bool,
top: Option<f32>,
left: Option<f32>,
}
impl NotificationSign {
#[must_use]
pub const fn new() -> Self {
Self {
variant: Variant::Error,
count: None,
show: true,
top: None,
left: None,
}
}
#[must_use]
pub const fn variant(mut self, variant: Variant) -> Self {
self.variant = variant;
self
}
#[must_use]
pub const fn count(mut self, count: u32) -> Self {
self.count = Some(count);
self
}
#[must_use]
pub const fn show(mut self, show: bool) -> Self {
self.show = show;
self
}
#[must_use]
pub const fn top(mut self, top: f32) -> Self {
self.top = Some(top);
self
}
#[must_use]
pub const fn left(mut self, left: f32) -> Self {
self.left = Some(left);
self
}
}
impl Default for NotificationSign {
fn default() -> Self {
Self::new()
}
}
impl RenderOnce for NotificationSign {
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
if !self.show {
return div();
}
let theme = cx.theme();
let background = rgb(theme.shade(self.variant.background()));
let text = rgb(theme.shade(TEXT));
let (top, left) = (self.top, self.left);
self.count.filter(|&count| count > 0).map_or_else(
|| {
div()
.absolute()
.when_some(top, |el, top| el.top(px(top)))
.when_some(left, |el, left| el.left(px(left)))
.p(px(DOT_PADDING))
.rounded_full()
.bg(background)
},
|count| {
div()
.flex()
.items_center()
.justify_center()
.min_w(px(COUNT_MIN_WIDTH))
.h(px(COUNT_HEIGHT))
.px(px(COUNT_PADDING_X))
.rounded_full()
.bg(background)
.font_family(FONT_PRIMARY)
.text_size(px(TextSize::Sm.px()))
.line_height(px(COUNT_LINE_HEIGHT))
.text_color(text)
.child(display_count(count).to_string())
},
)
}
}