1use std::sync::Arc;
2use std::time::Duration;
3
4use anyhow::Context as _;
5use cloud_api_client::{AuthenticatedUser, CloudApiClient};
6use gpui::{Context, Task};
7use util::{ResultExt as _, maybe};
8
9pub struct CloudUserStore {
10 authenticated_user: Option<Arc<AuthenticatedUser>>,
11 _maintain_authenticated_user_task: Task<()>,
12}
13
14impl CloudUserStore {
15 pub fn new(cloud_client: Arc<CloudApiClient>, cx: &mut Context<Self>) -> Self {
16 Self {
17 authenticated_user: None,
18 _maintain_authenticated_user_task: cx.spawn(async move |this, cx| {
19 maybe!(async move {
20 loop {
21 let Some(this) = this.upgrade() else {
22 return anyhow::Ok(());
23 };
24
25 if cloud_client.has_credentials() {
26 let already_fetched_authenticated_user = this
27 .read_with(cx, |this, _cx| this.authenticated_user().is_some())
28 .unwrap_or(false);
29
30 if already_fetched_authenticated_user {
31 // We already fetched the authenticated user; nothing to do.
32 } else {
33 let authenticated_user_result = cloud_client
34 .get_authenticated_user()
35 .await
36 .context("failed to fetch authenticated user");
37 if let Some(response) = authenticated_user_result.log_err() {
38 this.update(cx, |this, _cx| {
39 this.authenticated_user = Some(Arc::new(response.user));
40 })
41 .ok();
42 }
43 }
44 } else {
45 this.update(cx, |this, _cx| {
46 this.authenticated_user = None;
47 })
48 .ok();
49 }
50
51 cx.background_executor()
52 .timer(Duration::from_millis(100))
53 .await;
54 }
55 })
56 .await
57 .log_err();
58 }),
59 }
60 }
61
62 pub fn is_authenticated(&self) -> bool {
63 self.authenticated_user.is_some()
64 }
65
66 pub fn authenticated_user(&self) -> Option<Arc<AuthenticatedUser>> {
67 self.authenticated_user.clone()
68 }
69}