client: Add CloudUserStore
(#35370)
This PR adds a new `CloudUserStore` for storing information about the user retrieved from Cloud instead of Collab. Release Notes: - N/A
This commit is contained in:
parent
289f420504
commit
bb1a7ccbba
7 changed files with 68 additions and 4 deletions
|
@ -1,6 +1,7 @@
|
||||||
#[cfg(any(test, feature = "test-support"))]
|
#[cfg(any(test, feature = "test-support"))]
|
||||||
pub mod test;
|
pub mod test;
|
||||||
|
|
||||||
|
mod cloud;
|
||||||
mod proxy;
|
mod proxy;
|
||||||
pub mod telemetry;
|
pub mod telemetry;
|
||||||
pub mod user;
|
pub mod user;
|
||||||
|
@ -52,6 +53,7 @@ use tokio::net::TcpStream;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use util::{ConnectionResult, ResultExt};
|
use util::{ConnectionResult, ResultExt};
|
||||||
|
|
||||||
|
pub use cloud::*;
|
||||||
pub use rpc::*;
|
pub use rpc::*;
|
||||||
pub use telemetry_events::Event;
|
pub use telemetry_events::Event;
|
||||||
pub use user::*;
|
pub use user::*;
|
||||||
|
@ -621,6 +623,10 @@ impl Client {
|
||||||
self.http.clone()
|
self.http.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn cloud_client(&self) -> Arc<CloudApiClient> {
|
||||||
|
self.cloud_client.clone()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_id(&self, id: u64) -> &Self {
|
pub fn set_id(&self, id: u64) -> &Self {
|
||||||
self.id.store(id, Ordering::SeqCst);
|
self.id.store(id, Ordering::SeqCst);
|
||||||
self
|
self
|
||||||
|
|
3
crates/client/src/cloud.rs
Normal file
3
crates/client/src/cloud.rs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
mod user_store;
|
||||||
|
|
||||||
|
pub use user_store::*;
|
41
crates/client/src/cloud/user_store.rs
Normal file
41
crates/client/src/cloud/user_store.rs
Normal file
|
@ -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) {
|
pub fn set_credentials(&self, user_id: u32, access_token: String) {
|
||||||
*self.credentials.write() = Some(Credentials {
|
*self.credentials.write() = Some(Credentials {
|
||||||
user_id,
|
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()
|
let request = Request::builder()
|
||||||
.method(Method::GET)
|
.method(Method::GET)
|
||||||
.uri(
|
.uri(
|
||||||
|
@ -69,8 +73,7 @@ impl CloudApiClient {
|
||||||
|
|
||||||
let mut body = String::new();
|
let mut body = String::new();
|
||||||
response.body_mut().read_to_string(&mut body).await?;
|
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 anyhow::anyhow;
|
||||||
use call::ActiveCall;
|
use call::ActiveCall;
|
||||||
use channel::{ChannelBuffer, ChannelStore};
|
use channel::{ChannelBuffer, ChannelStore};
|
||||||
|
use client::CloudUserStore;
|
||||||
use client::{
|
use client::{
|
||||||
self, ChannelId, Client, Connection, Credentials, EstablishConnectionError, UserStore,
|
self, ChannelId, Client, Connection, Credentials, EstablishConnectionError, UserStore,
|
||||||
proto::PeerId,
|
proto::PeerId,
|
||||||
|
@ -281,12 +282,14 @@ impl TestServer {
|
||||||
.register_hosting_provider(Arc::new(git_hosting_providers::Github::public_instance()));
|
.register_hosting_provider(Arc::new(git_hosting_providers::Github::public_instance()));
|
||||||
|
|
||||||
let user_store = cx.new(|cx| UserStore::new(client.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));
|
let workspace_store = cx.new(|cx| WorkspaceStore::new(client.clone(), cx));
|
||||||
let language_registry = Arc::new(LanguageRegistry::test(cx.executor()));
|
let language_registry = Arc::new(LanguageRegistry::test(cx.executor()));
|
||||||
let session = cx.new(|cx| AppSession::new(Session::test(), cx));
|
let session = cx.new(|cx| AppSession::new(Session::test(), cx));
|
||||||
let app_state = Arc::new(workspace::AppState {
|
let app_state = Arc::new(workspace::AppState {
|
||||||
client: client.clone(),
|
client: client.clone(),
|
||||||
user_store: user_store.clone(),
|
user_store: user_store.clone(),
|
||||||
|
cloud_user_store,
|
||||||
workspace_store,
|
workspace_store,
|
||||||
languages: language_registry,
|
languages: language_registry,
|
||||||
fs: fs.clone(),
|
fs: fs.clone(),
|
||||||
|
|
|
@ -15,6 +15,7 @@ mod toast_layer;
|
||||||
mod toolbar;
|
mod toolbar;
|
||||||
mod workspace_settings;
|
mod workspace_settings;
|
||||||
|
|
||||||
|
use client::CloudUserStore;
|
||||||
pub use toast_layer::{ToastAction, ToastLayer, ToastView};
|
pub use toast_layer::{ToastAction, ToastLayer, ToastView};
|
||||||
|
|
||||||
use anyhow::{Context as _, Result, anyhow};
|
use anyhow::{Context as _, Result, anyhow};
|
||||||
|
@ -839,6 +840,7 @@ pub struct AppState {
|
||||||
pub languages: Arc<LanguageRegistry>,
|
pub languages: Arc<LanguageRegistry>,
|
||||||
pub client: Arc<Client>,
|
pub client: Arc<Client>,
|
||||||
pub user_store: Entity<UserStore>,
|
pub user_store: Entity<UserStore>,
|
||||||
|
pub cloud_user_store: Entity<CloudUserStore>,
|
||||||
pub workspace_store: Entity<WorkspaceStore>,
|
pub workspace_store: Entity<WorkspaceStore>,
|
||||||
pub fs: Arc<dyn fs::Fs>,
|
pub fs: Arc<dyn fs::Fs>,
|
||||||
pub build_window_options: fn(Option<Uuid>, &mut App) -> WindowOptions,
|
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 client = Client::new(clock, http_client.clone(), cx);
|
||||||
let session = cx.new(|cx| AppSession::new(Session::test(), cx));
|
let session = cx.new(|cx| AppSession::new(Session::test(), cx));
|
||||||
let user_store = cx.new(|cx| UserStore::new(client.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));
|
let workspace_store = cx.new(|cx| WorkspaceStore::new(client.clone(), cx));
|
||||||
|
|
||||||
theme::init(theme::LoadThemes::JustBase, cx);
|
theme::init(theme::LoadThemes::JustBase, cx);
|
||||||
|
@ -922,6 +925,7 @@ impl AppState {
|
||||||
fs,
|
fs,
|
||||||
languages,
|
languages,
|
||||||
user_store,
|
user_store,
|
||||||
|
cloud_user_store,
|
||||||
workspace_store,
|
workspace_store,
|
||||||
node_runtime: NodeRuntime::unavailable(),
|
node_runtime: NodeRuntime::unavailable(),
|
||||||
build_window_options: |_, _| Default::default(),
|
build_window_options: |_, _| Default::default(),
|
||||||
|
@ -5689,6 +5693,7 @@ impl Workspace {
|
||||||
|
|
||||||
let client = project.read(cx).client();
|
let client = project.read(cx).client();
|
||||||
let user_store = project.read(cx).user_store();
|
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 workspace_store = cx.new(|cx| WorkspaceStore::new(client.clone(), cx));
|
||||||
let session = cx.new(|cx| AppSession::new(Session::test(), cx));
|
let session = cx.new(|cx| AppSession::new(Session::test(), cx));
|
||||||
|
@ -5696,6 +5701,7 @@ impl Workspace {
|
||||||
let app_state = Arc::new(AppState {
|
let app_state = Arc::new(AppState {
|
||||||
languages: project.read(cx).languages().clone(),
|
languages: project.read(cx).languages().clone(),
|
||||||
workspace_store,
|
workspace_store,
|
||||||
|
cloud_user_store,
|
||||||
client,
|
client,
|
||||||
user_store,
|
user_store,
|
||||||
fs: project.read(cx).fs().clone(),
|
fs: project.read(cx).fs().clone(),
|
||||||
|
|
|
@ -5,7 +5,7 @@ use agent_ui::AgentPanel;
|
||||||
use anyhow::{Context as _, Result};
|
use anyhow::{Context as _, Result};
|
||||||
use clap::{Parser, command};
|
use clap::{Parser, command};
|
||||||
use cli::FORCE_CLI_MODE_ENV_VAR_NAME;
|
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 collab_ui::channel_view::ChannelView;
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
use db::kvp::{GLOBAL_KEY_VALUE_STORE, KEY_VALUE_STORE};
|
use db::kvp::{GLOBAL_KEY_VALUE_STORE, KEY_VALUE_STORE};
|
||||||
|
@ -457,6 +457,7 @@ pub fn main() {
|
||||||
language::init(cx);
|
language::init(cx);
|
||||||
languages::init(languages.clone(), node_runtime.clone(), cx);
|
languages::init(languages.clone(), node_runtime.clone(), cx);
|
||||||
let user_store = cx.new(|cx| UserStore::new(client.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));
|
let workspace_store = cx.new(|cx| WorkspaceStore::new(client.clone(), cx));
|
||||||
|
|
||||||
language_extension::init(
|
language_extension::init(
|
||||||
|
@ -516,6 +517,7 @@ pub fn main() {
|
||||||
languages: languages.clone(),
|
languages: languages.clone(),
|
||||||
client: client.clone(),
|
client: client.clone(),
|
||||||
user_store: user_store.clone(),
|
user_store: user_store.clone(),
|
||||||
|
cloud_user_store,
|
||||||
fs: fs.clone(),
|
fs: fs.clone(),
|
||||||
build_window_options,
|
build_window_options,
|
||||||
workspace_store,
|
workspace_store,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue