1use gpui::AnyView;
2
3use crate::prelude::*;
4
5/// The audio status of an player, for use in representing
6/// their status visually on their avatar.
7#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
8pub enum AudioStatus {
9 /// The player's microphone is muted.
10 Muted,
11 /// The player's microphone is muted, and collaboration audio is disabled.
12 Deafened,
13}
14
15/// An indicator that shows the audio status of a player.
16#[derive(IntoElement)]
17pub struct AvatarAudioStatusIndicator {
18 audio_status: AudioStatus,
19 tooltip: Option<Box<dyn Fn(&mut WindowContext) -> AnyView>>,
20}
21
22impl AvatarAudioStatusIndicator {
23 /// Creates a new `AvatarAudioStatusIndicator`
24 pub fn new(audio_status: AudioStatus) -> Self {
25 Self {
26 audio_status,
27 tooltip: None,
28 }
29 }
30
31 /// Sets the tooltip for the indicator.
32 pub fn tooltip(mut self, tooltip: impl Fn(&mut WindowContext) -> AnyView + 'static) -> Self {
33 self.tooltip = Some(Box::new(tooltip));
34 self
35 }
36}
37
38impl RenderOnce for AvatarAudioStatusIndicator {
39 fn render(self, cx: &mut WindowContext) -> impl IntoElement {
40 let icon_size = IconSize::Indicator;
41
42 let width_in_px = icon_size.rems() * cx.rem_size();
43 let padding_x = px(4.);
44
45 div()
46 .absolute()
47 .bottom(rems_from_px(-3.))
48 .right(rems_from_px(-6.))
49 .w(width_in_px + padding_x)
50 .h(icon_size.rems())
51 .child(
52 h_flex()
53 .id("muted-indicator")
54 .justify_center()
55 .px(padding_x)
56 .py(px(2.))
57 .bg(cx.theme().status().error_background)
58 .rounded_md()
59 .child(
60 Icon::new(match self.audio_status {
61 AudioStatus::Muted => IconName::MicMute,
62 AudioStatus::Deafened => IconName::AudioOff,
63 })
64 .size(icon_size)
65 .color(Color::Error),
66 )
67 .when_some(self.tooltip, |this, tooltip| {
68 this.tooltip(move |cx| tooltip(cx))
69 }),
70 )
71 }
72}