title_bar.rs

  1use std::marker::PhantomData;
  2use std::sync::atomic::AtomicBool;
  3use std::sync::Arc;
  4
  5use crate::{prelude::*, PlayerWithCallStatus};
  6use crate::{
  7    theme, Avatar, Button, Icon, IconButton, IconColor, PlayerStack, ToolDivider, TrafficLights,
  8};
  9
 10#[derive(Clone)]
 11pub struct Livestream {
 12    pub players: Vec<PlayerWithCallStatus>,
 13    pub channel: Option<String>, // projects
 14                                 // windows
 15}
 16
 17#[derive(Element)]
 18pub struct TitleBar<V: 'static> {
 19    view_type: PhantomData<V>,
 20    /// If the window is active from the OS's perspective.
 21    is_active: Arc<AtomicBool>,
 22    livestream: Option<Livestream>,
 23}
 24
 25impl<V: 'static> TitleBar<V> {
 26    pub fn new(cx: &mut ViewContext<V>) -> Self {
 27        let is_active = Arc::new(AtomicBool::new(true));
 28        let active = is_active.clone();
 29
 30        cx.observe_window_activation(move |_, is_active, cx| {
 31            active.store(is_active, std::sync::atomic::Ordering::SeqCst);
 32            cx.notify();
 33        })
 34        .detach();
 35
 36        Self {
 37            view_type: PhantomData,
 38            is_active,
 39            livestream: None,
 40        }
 41    }
 42
 43    pub fn set_livestream(mut self, livestream: Option<Livestream>) -> Self {
 44        self.livestream = livestream;
 45        self
 46    }
 47
 48    fn render(&mut self, _: &mut V, cx: &mut ViewContext<V>) -> impl IntoElement<V> {
 49        let theme = theme(cx);
 50        let has_focus = cx.window_is_active();
 51
 52        let player_list = if let Some(livestream) = &self.livestream {
 53            livestream.players.clone().into_iter()
 54        } else {
 55            vec![].into_iter()
 56        };
 57
 58        div()
 59            .flex()
 60            .items_center()
 61            .justify_between()
 62            .w_full()
 63            .h_8()
 64            .fill(theme.lowest.base.default.background)
 65            .child(
 66                div()
 67                    .flex()
 68                    .items_center()
 69                    .h_full()
 70                    .gap_4()
 71                    .px_2()
 72                    .child(TrafficLights::new().window_has_focus(has_focus))
 73                    // === Project Info === //
 74                    .child(
 75                        div()
 76                            .flex()
 77                            .items_center()
 78                            .gap_1()
 79                            .child(Button::new("zed"))
 80                            .child(Button::new("nate/gpui2-ui-components")),
 81                    )
 82                    .children(player_list.map(|p| PlayerStack::new(p)))
 83                    .child(IconButton::new(Icon::Plus)),
 84            )
 85            .child(
 86                div()
 87                    .flex()
 88                    .items_center()
 89                    .child(
 90                        div()
 91                            .px_2()
 92                            .flex()
 93                            .items_center()
 94                            .gap_1()
 95                            .child(IconButton::new(Icon::FolderX))
 96                            .child(IconButton::new(Icon::Close)),
 97                    )
 98                    .child(ToolDivider::new())
 99                    .child(
100                        div()
101                            .px_2()
102                            .flex()
103                            .items_center()
104                            .gap_1()
105                            .child(IconButton::new(Icon::Mic))
106                            .child(IconButton::new(Icon::AudioOn))
107                            .child(IconButton::new(Icon::Screen).color(IconColor::Accent)),
108                    )
109                    .child(
110                        div().px_2().flex().items_center().child(
111                            Avatar::new("https://avatars.githubusercontent.com/u/1714999?v=4")
112                                .shape(Shape::RoundedRectangle),
113                        ),
114                    ),
115            )
116    }
117}