use crate::{prelude::*, *};
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub enum AvatarStatus {
#[default]
None,
Online,
Busy,
Away,
}
#[derive(IntoElement)]
pub struct Avatar {
src: Option<ImageSource>,
fallback: SharedString,
size: Pixels,
status: AvatarStatus,
style: StyleRefinement,
}
impl Avatar {
pub fn new(fallback: impl Into<SharedString>) -> Self {
Self {
src: None,
fallback: fallback.into(),
size: px(32.0),
status: AvatarStatus::None,
style: StyleRefinement::default(),
}
}
pub fn src(mut self, src: impl Into<ImageSource>) -> Self {
self.src = Some(src.into());
self
}
pub fn size(mut self, size: impl Into<Pixels>) -> Self {
self.size = size.into();
self
}
pub fn status(mut self, status: AvatarStatus) -> Self {
self.status = status;
self
}
}
impl Styled for Avatar {
fn style(&mut self) -> &mut StyleRefinement {
&mut self.style
}
}
impl RenderOnce for Avatar {
fn render(self, _window: &mut Window, cx: &mut App) -> impl IntoElement {
let theme = cx.theme();
let muted_foreground = theme.tokens.muted_foreground.color;
let status_color = match self.status {
AvatarStatus::None => None,
AvatarStatus::Online => Some(rgb(0x22c55e)),
AvatarStatus::Busy => Some(rgb(0xef4444)),
AvatarStatus::Away => Some(rgb(0xeab308)),
};
let user_style = self.style;
div()
.relative()
.size(self.size)
.child(
div()
.size_full()
.rounded_full()
.overflow_hidden()
.bg(muted_foreground.opacity(0.2))
.flex()
.items_center()
.justify_center()
.text_color(muted_foreground)
.text_sm()
.child(match self.src {
Some(src) => img(src).size_full().into_any_element(),
None => div().child(self.fallback.clone()).into_any_element(),
}),
)
.when_some(status_color, |this, color| {
this.child(
div()
.absolute()
.right(px(0.0))
.bottom(px(0.0))
.size(px(10.0))
.rounded_full()
.bg(color)
.border_2()
.border_color(rgb(0xffffff)),
)
})
.map(|mut this| {
this.style().refine(&user_style);
this
})
}
}