1use gpui::{Hsla, ViewContext};
2
3use crate::prelude::*;
4
5/// Represents a person with a Zed account's public profile.
6/// All data in this struct should be considered public.
7pub struct PublicPlayer {
8 pub username: SharedString,
9 pub avatar: SharedString,
10 pub is_contact: bool,
11}
12
13impl PublicPlayer {
14 pub fn new(username: impl Into<SharedString>, avatar: impl Into<SharedString>) -> Self {
15 Self {
16 username: username.into(),
17 avatar: avatar.into(),
18 is_contact: false,
19 }
20 }
21}
22
23#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
24pub enum PlayerStatus {
25 #[default]
26 Offline,
27 Online,
28 InCall,
29 Away,
30 DoNotDisturb,
31 Invisible,
32}
33
34#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
35pub enum MicStatus {
36 Muted,
37 #[default]
38 Unmuted,
39}
40
41impl MicStatus {
42 pub fn inverse(&self) -> Self {
43 match self {
44 Self::Muted => Self::Unmuted,
45 Self::Unmuted => Self::Muted,
46 }
47 }
48}
49
50#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
51pub enum VideoStatus {
52 On,
53 #[default]
54 Off,
55}
56
57impl VideoStatus {
58 pub fn inverse(&self) -> Self {
59 match self {
60 Self::On => Self::Off,
61 Self::Off => Self::On,
62 }
63 }
64}
65
66#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
67pub enum ScreenShareStatus {
68 Shared,
69 #[default]
70 NotShared,
71}
72
73impl ScreenShareStatus {
74 pub fn inverse(&self) -> Self {
75 match self {
76 Self::Shared => Self::NotShared,
77 Self::NotShared => Self::Shared,
78 }
79 }
80}
81
82#[derive(Clone)]
83pub struct PlayerCallStatus {
84 pub mic_status: MicStatus,
85 /// Indicates if the player is currently speaking
86 /// And the intensity of the volume coming through
87 ///
88 /// 0.0 - 1.0
89 pub voice_activity: f32,
90 pub video_status: VideoStatus,
91 pub screen_share_status: ScreenShareStatus,
92 pub in_current_project: bool,
93 pub disconnected: bool,
94 pub following: Option<Vec<Player>>,
95 pub followers: Option<Vec<Player>>,
96}
97
98impl PlayerCallStatus {
99 pub fn new() -> Self {
100 Self {
101 mic_status: MicStatus::default(),
102 voice_activity: 0.,
103 video_status: VideoStatus::default(),
104 screen_share_status: ScreenShareStatus::default(),
105 in_current_project: true,
106 disconnected: false,
107 following: None,
108 followers: None,
109 }
110 }
111}
112
113#[derive(PartialEq, Clone)]
114pub struct Player {
115 index: usize,
116 avatar_src: String,
117 username: String,
118 status: PlayerStatus,
119}
120
121#[derive(Clone)]
122pub struct PlayerWithCallStatus {
123 player: Player,
124 call_status: PlayerCallStatus,
125}
126
127impl PlayerWithCallStatus {
128 pub fn new(player: Player, call_status: PlayerCallStatus) -> Self {
129 Self {
130 player,
131 call_status,
132 }
133 }
134
135 pub fn get_player(&self) -> &Player {
136 &self.player
137 }
138
139 pub fn get_call_status(&self) -> &PlayerCallStatus {
140 &self.call_status
141 }
142}
143
144impl Player {
145 pub fn new(index: usize, avatar_src: String, username: String) -> Self {
146 Self {
147 index,
148 avatar_src,
149 username,
150 status: Default::default(),
151 }
152 }
153
154 pub fn set_status(mut self, status: PlayerStatus) -> Self {
155 self.status = status;
156 self
157 }
158
159 pub fn cursor_color<V: 'static>(&self, cx: &mut ViewContext<V>) -> Hsla {
160 cx.theme().styles.player.0[self.index % cx.theme().styles.player.0.len()].cursor
161 }
162
163 pub fn selection_color<V: 'static>(&self, cx: &mut ViewContext<V>) -> Hsla {
164 cx.theme().styles.player.0[self.index % cx.theme().styles.player.0.len()].selection
165 }
166
167 pub fn avatar_src(&self) -> &str {
168 &self.avatar_src
169 }
170
171 pub fn index(&self) -> usize {
172 self.index
173 }
174}