call.rs

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