call.rs

 1mod participant;
 2pub mod room;
 3
 4use anyhow::{anyhow, Result};
 5use client::{incoming_call::IncomingCall, Client, UserStore};
 6use gpui::{Entity, ModelContext, ModelHandle, MutableAppContext, 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>>,
18    client: Arc<Client>,
19    user_store: ModelHandle<UserStore>,
20}
21
22impl Entity for ActiveCall {
23    type 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.clone();
45
46        let client = self.client.clone();
47        let user_store = self.user_store.clone();
48        cx.spawn(|this, mut cx| async move {
49            let room = if let Some(room) = room {
50                room
51            } else {
52                let room = cx.update(|cx| Room::create(client, user_store, cx)).await?;
53                this.update(&mut cx, |this, cx| {
54                    this.room = Some(room.clone());
55                    cx.notify();
56                });
57                room
58            };
59            room.update(&mut cx, |room, cx| room.call(recipient_user_id, cx))
60                .await?;
61
62            Ok(())
63        })
64    }
65
66    pub fn join(&mut self, call: &IncomingCall, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
67        if self.room.is_some() {
68            return Task::ready(Err(anyhow!("cannot join while on another call")));
69        }
70
71        let join = Room::join(call, self.client.clone(), self.user_store.clone(), cx);
72        cx.spawn(|this, mut cx| async move {
73            let room = join.await?;
74            this.update(&mut cx, |this, cx| {
75                this.room = Some(room);
76                cx.notify();
77            });
78            Ok(())
79        })
80    }
81
82    pub fn room(&self) -> Option<&ModelHandle<Room>> {
83        self.room.as_ref()
84    }
85}