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, 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}