Detailed changes
@@ -1,6 +1,7 @@
#[cfg(any(test, feature = "test-support"))]
pub mod test;
+mod cloud;
mod proxy;
pub mod telemetry;
pub mod user;
@@ -52,6 +53,7 @@ use tokio::net::TcpStream;
use url::Url;
use util::{ConnectionResult, ResultExt};
+pub use cloud::*;
pub use rpc::*;
pub use telemetry_events::Event;
pub use user::*;
@@ -621,6 +623,10 @@ impl Client {
self.http.clone()
}
+ pub fn cloud_client(&self) -> Arc<CloudApiClient> {
+ self.cloud_client.clone()
+ }
+
pub fn set_id(&self, id: u64) -> &Self {
self.id.store(id, Ordering::SeqCst);
self
@@ -0,0 +1,3 @@
+mod user_store;
+
+pub use user_store::*;
@@ -0,0 +1,41 @@
+use std::sync::Arc;
+use std::time::Duration;
+
+use anyhow::Context as _;
+use cloud_api_client::{AuthenticatedUser, CloudApiClient};
+use gpui::{Context, Task};
+use util::{ResultExt as _, maybe};
+
+pub struct CloudUserStore {
+ authenticated_user: Option<AuthenticatedUser>,
+ _fetch_authenticated_user_task: Task<()>,
+}
+
+impl CloudUserStore {
+ pub fn new(cloud_client: Arc<CloudApiClient>, cx: &mut Context<Self>) -> Self {
+ Self {
+ authenticated_user: None,
+ _fetch_authenticated_user_task: cx.spawn(async move |this, cx| {
+ maybe!(async move {
+ loop {
+ if cloud_client.has_credentials() {
+ break;
+ }
+
+ cx.background_executor()
+ .timer(Duration::from_millis(100))
+ .await;
+ }
+
+ let response = cloud_client.get_authenticated_user().await?;
+ this.update(cx, |this, _cx| {
+ this.authenticated_user = Some(response.user);
+ })
+ })
+ .await
+ .context("failed to fetch authenticated user")
+ .log_err();
+ }),
+ }
+ }
+}
@@ -24,6 +24,10 @@ impl CloudApiClient {
}
}
+ pub fn has_credentials(&self) -> bool {
+ self.credentials.read().is_some()
+ }
+
pub fn set_credentials(&self, user_id: u32, access_token: String) {
*self.credentials.write() = Some(Credentials {
user_id,
@@ -43,7 +47,7 @@ impl CloudApiClient {
))
}
- pub async fn get_authenticated_user(&self) -> Result<AuthenticatedUser> {
+ pub async fn get_authenticated_user(&self) -> Result<GetAuthenticatedUserResponse> {
let request = Request::builder()
.method(Method::GET)
.uri(
@@ -69,8 +73,7 @@ impl CloudApiClient {
let mut body = String::new();
response.body_mut().read_to_string(&mut body).await?;
- let response: GetAuthenticatedUserResponse = serde_json::from_str(&body)?;
- Ok(response.user)
+ Ok(serde_json::from_str(&body)?)
}
}
@@ -8,6 +8,7 @@ use crate::{
use anyhow::anyhow;
use call::ActiveCall;
use channel::{ChannelBuffer, ChannelStore};
+use client::CloudUserStore;
use client::{
self, ChannelId, Client, Connection, Credentials, EstablishConnectionError, UserStore,
proto::PeerId,
@@ -281,12 +282,14 @@ impl TestServer {
.register_hosting_provider(Arc::new(git_hosting_providers::Github::public_instance()));
let user_store = cx.new(|cx| UserStore::new(client.clone(), cx));
+ let cloud_user_store = cx.new(|cx| CloudUserStore::new(client.cloud_client(), cx));
let workspace_store = cx.new(|cx| WorkspaceStore::new(client.clone(), cx));
let language_registry = Arc::new(LanguageRegistry::test(cx.executor()));
let session = cx.new(|cx| AppSession::new(Session::test(), cx));
let app_state = Arc::new(workspace::AppState {
client: client.clone(),
user_store: user_store.clone(),
+ cloud_user_store,
workspace_store,
languages: language_registry,
fs: fs.clone(),
@@ -15,6 +15,7 @@ mod toast_layer;
mod toolbar;
mod workspace_settings;
+use client::CloudUserStore;
pub use toast_layer::{ToastAction, ToastLayer, ToastView};
use anyhow::{Context as _, Result, anyhow};
@@ -839,6 +840,7 @@ pub struct AppState {
pub languages: Arc<LanguageRegistry>,
pub client: Arc<Client>,
pub user_store: Entity<UserStore>,
+ pub cloud_user_store: Entity<CloudUserStore>,
pub workspace_store: Entity<WorkspaceStore>,
pub fs: Arc<dyn fs::Fs>,
pub build_window_options: fn(Option<Uuid>, &mut App) -> WindowOptions,
@@ -911,6 +913,7 @@ impl AppState {
let client = Client::new(clock, http_client.clone(), cx);
let session = cx.new(|cx| AppSession::new(Session::test(), cx));
let user_store = cx.new(|cx| UserStore::new(client.clone(), cx));
+ let cloud_user_store = cx.new(|cx| CloudUserStore::new(client.cloud_client(), cx));
let workspace_store = cx.new(|cx| WorkspaceStore::new(client.clone(), cx));
theme::init(theme::LoadThemes::JustBase, cx);
@@ -922,6 +925,7 @@ impl AppState {
fs,
languages,
user_store,
+ cloud_user_store,
workspace_store,
node_runtime: NodeRuntime::unavailable(),
build_window_options: |_, _| Default::default(),
@@ -5689,6 +5693,7 @@ impl Workspace {
let client = project.read(cx).client();
let user_store = project.read(cx).user_store();
+ let cloud_user_store = cx.new(|cx| CloudUserStore::new(client.cloud_client(), cx));
let workspace_store = cx.new(|cx| WorkspaceStore::new(client.clone(), cx));
let session = cx.new(|cx| AppSession::new(Session::test(), cx));
@@ -5696,6 +5701,7 @@ impl Workspace {
let app_state = Arc::new(AppState {
languages: project.read(cx).languages().clone(),
workspace_store,
+ cloud_user_store,
client,
user_store,
fs: project.read(cx).fs().clone(),
@@ -5,7 +5,7 @@ use agent_ui::AgentPanel;
use anyhow::{Context as _, Result};
use clap::{Parser, command};
use cli::FORCE_CLI_MODE_ENV_VAR_NAME;
-use client::{Client, ProxySettings, UserStore, parse_zed_link};
+use client::{Client, CloudUserStore, ProxySettings, UserStore, parse_zed_link};
use collab_ui::channel_view::ChannelView;
use collections::HashMap;
use db::kvp::{GLOBAL_KEY_VALUE_STORE, KEY_VALUE_STORE};
@@ -457,6 +457,7 @@ pub fn main() {
language::init(cx);
languages::init(languages.clone(), node_runtime.clone(), cx);
let user_store = cx.new(|cx| UserStore::new(client.clone(), cx));
+ let cloud_user_store = cx.new(|cx| CloudUserStore::new(client.cloud_client(), cx));
let workspace_store = cx.new(|cx| WorkspaceStore::new(client.clone(), cx));
language_extension::init(
@@ -516,6 +517,7 @@ pub fn main() {
languages: languages.clone(),
client: client.clone(),
user_store: user_store.clone(),
+ cloud_user_store,
fs: fs.clone(),
build_window_options,
workspace_store,