1use std::marker::PhantomData;
2
3use gpui3::img;
4
5use crate::prelude::*;
6use crate::theme::theme;
7
8#[derive(Element, Clone)]
9pub struct Avatar<S: 'static + Send + Sync> {
10 state_type: PhantomData<S>,
11 src: SharedString,
12 shape: Shape,
13}
14
15impl<S: 'static + Send + Sync> Avatar<S> {
16 pub fn new(src: impl Into<SharedString>) -> Self {
17 Self {
18 state_type: PhantomData,
19 src: src.into(),
20 shape: Shape::Circle,
21 }
22 }
23
24 pub fn shape(mut self, shape: Shape) -> Self {
25 self.shape = shape;
26 self
27 }
28
29 fn render(&mut self, _view: &mut S, cx: &mut ViewContext<S>) -> impl Element<ViewState = S> {
30 let theme = theme(cx);
31
32 let mut img = img();
33
34 if self.shape == Shape::Circle {
35 img = img.rounded_full();
36 } else {
37 img = img.rounded_md();
38 }
39
40 img.uri(self.src.clone())
41 .size_4()
42 .bg(theme.middle.warning.default.foreground)
43 }
44}
45
46#[cfg(feature = "stories")]
47pub use stories::*;
48
49#[cfg(feature = "stories")]
50mod stories {
51 use crate::Story;
52
53 use super::*;
54
55 #[derive(Element)]
56 pub struct AvatarStory<S: 'static + Send + Sync> {
57 state_type: PhantomData<S>,
58 }
59
60 impl<S: 'static + Send + Sync> AvatarStory<S> {
61 pub fn new() -> Self {
62 Self {
63 state_type: PhantomData,
64 }
65 }
66
67 fn render(
68 &mut self,
69 _view: &mut S,
70 cx: &mut ViewContext<S>,
71 ) -> impl Element<ViewState = S> {
72 Story::container(cx)
73 .child(Story::title_for::<_, Avatar<S>>(cx))
74 .child(Story::label(cx, "Default"))
75 .child(Avatar::new(
76 "https://avatars.githubusercontent.com/u/1714999?v=4",
77 ))
78 .child(Story::label(cx, "Rounded rectangle"))
79 .child(
80 Avatar::new("https://avatars.githubusercontent.com/u/1714999?v=4")
81 .shape(Shape::RoundedRectangle),
82 )
83 }
84 }
85}