1mod participant;
2pub mod room;
3
4use anyhow::{anyhow, Result};
5use client::{incoming_call::IncomingCall, Client, UserStore};
6use gpui::{Entity, ModelContext, ModelHandle, MutableAppContext, Subscription, Task};
7pub use participant::ParticipantLocation;
8pub use room::Room;
9use std::sync::Arc;
10
11pub fn init(client: Arc<Client>, user_store: ModelHandle<UserStore>, cx: &mut MutableAppContext) {
12 let active_call = cx.add_model(|_| ActiveCall::new(client, user_store));
13 cx.set_global(active_call);
14}
15
16pub struct ActiveCall {
17 room: Option<(ModelHandle<Room>, Vec<Subscription>)>,
18 client: Arc<Client>,
19 user_store: ModelHandle<UserStore>,
20}
21
22impl Entity for ActiveCall {
23 type Event = room::Event;
24}
25
26impl ActiveCall {
27 fn new(client: Arc<Client>, user_store: ModelHandle<UserStore>) -> Self {
28 Self {
29 room: None,
30 client,
31 user_store,
32 }
33 }
34
35 pub fn global(cx: &mut MutableAppContext) -> ModelHandle<Self> {
36 cx.global::<ModelHandle<Self>>().clone()
37 }
38
39 pub fn invite(
40 &mut self,
41 recipient_user_id: u64,
42 cx: &mut ModelContext<Self>,
43 ) -> Task<Result<()>> {
44 let room = self.room.as_ref().map(|(room, _)| room.clone());
45 let client = self.client.clone();
46 let user_store = self.user_store.clone();
47 cx.spawn(|this, mut cx| async move {
48 let room = if let Some(room) = room {
49 room
50 } else {
51 let room = cx.update(|cx| Room::create(client, user_store, cx)).await?;
52 this.update(&mut cx, |this, cx| this.set_room(Some(room.clone()), cx));
53 room
54 };
55 room.update(&mut cx, |room, cx| room.call(recipient_user_id, cx))
56 .await?;
57
58 Ok(())
59 })
60 }
61
62 pub fn join(&mut self, call: &IncomingCall, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
63 if self.room.is_some() {
64 return Task::ready(Err(anyhow!("cannot join while on another call")));
65 }
66
67 let join = Room::join(call, self.client.clone(), self.user_store.clone(), cx);
68 cx.spawn(|this, mut cx| async move {
69 let room = join.await?;
70 this.update(&mut cx, |this, cx| this.set_room(Some(room.clone()), cx));
71 Ok(())
72 })
73 }
74
75 fn set_room(&mut self, room: Option<ModelHandle<Room>>, cx: &mut ModelContext<Self>) {
76 if let Some(room) = room {
77 let subscriptions = vec![
78 cx.observe(&room, |_, _, cx| cx.notify()),
79 cx.subscribe(&room, |_, _, event, cx| cx.emit(event.clone())),
80 ];
81 self.room = Some((room, subscriptions));
82 } else {
83 self.room = None;
84 }
85 cx.notify();
86 }
87
88 pub fn room(&self) -> Option<&ModelHandle<Room>> {
89 self.room.as_ref().map(|(room, _)| room)
90 }
91}