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}