
This PR allows configuring existing dev server, right now you can: - Change the dev servers name - Generate a new token (and invalidate the old one) <img width="563" alt="image" src="https://github.com/zed-industries/zed/assets/53836821/9bc95042-c969-4293-90fd-0848d021b664"> Release Notes: - N/A
240 lines
7.2 KiB
Rust
240 lines
7.2 KiB
Rust
use anyhow::Result;
|
|
use gpui::{AppContext, AsyncAppContext, Context, Global, Model, ModelContext, SharedString, Task};
|
|
use rpc::{
|
|
proto::{self, DevServerStatus},
|
|
TypedEnvelope,
|
|
};
|
|
use std::{collections::HashMap, sync::Arc};
|
|
|
|
use client::{Client, ProjectId};
|
|
pub use client::{DevServerId, DevServerProjectId};
|
|
|
|
pub struct Store {
|
|
dev_server_projects: HashMap<DevServerProjectId, DevServerProject>,
|
|
dev_servers: HashMap<DevServerId, DevServer>,
|
|
_subscriptions: Vec<client::Subscription>,
|
|
client: Arc<Client>,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct DevServerProject {
|
|
pub id: DevServerProjectId,
|
|
pub project_id: Option<ProjectId>,
|
|
pub path: SharedString,
|
|
pub dev_server_id: DevServerId,
|
|
}
|
|
|
|
impl From<proto::DevServerProject> for DevServerProject {
|
|
fn from(project: proto::DevServerProject) -> Self {
|
|
Self {
|
|
id: DevServerProjectId(project.id),
|
|
project_id: project.project_id.map(|id| ProjectId(id)),
|
|
path: project.path.into(),
|
|
dev_server_id: DevServerId(project.dev_server_id),
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct DevServer {
|
|
pub id: DevServerId,
|
|
pub name: SharedString,
|
|
pub status: DevServerStatus,
|
|
}
|
|
|
|
impl From<proto::DevServer> for DevServer {
|
|
fn from(dev_server: proto::DevServer) -> Self {
|
|
Self {
|
|
id: DevServerId(dev_server.dev_server_id),
|
|
status: dev_server.status(),
|
|
name: dev_server.name.into(),
|
|
}
|
|
}
|
|
}
|
|
|
|
struct GlobalStore(Model<Store>);
|
|
|
|
impl Global for GlobalStore {}
|
|
|
|
pub fn init(client: Arc<Client>, cx: &mut AppContext) {
|
|
let store = cx.new_model(|cx| Store::new(client, cx));
|
|
cx.set_global(GlobalStore(store));
|
|
}
|
|
|
|
impl Store {
|
|
pub fn global(cx: &AppContext) -> Model<Store> {
|
|
cx.global::<GlobalStore>().0.clone()
|
|
}
|
|
|
|
pub fn new(client: Arc<Client>, cx: &ModelContext<Self>) -> Self {
|
|
Self {
|
|
dev_server_projects: Default::default(),
|
|
dev_servers: Default::default(),
|
|
_subscriptions: vec![client
|
|
.add_message_handler(cx.weak_model(), Self::handle_dev_server_projects_update)],
|
|
client,
|
|
}
|
|
}
|
|
|
|
pub fn projects_for_server(&self, id: DevServerId) -> Vec<DevServerProject> {
|
|
let mut projects: Vec<DevServerProject> = self
|
|
.dev_server_projects
|
|
.values()
|
|
.filter(|project| project.dev_server_id == id)
|
|
.cloned()
|
|
.collect();
|
|
projects.sort_by_key(|p| (p.path.clone(), p.id));
|
|
projects
|
|
}
|
|
|
|
pub fn dev_servers(&self) -> Vec<DevServer> {
|
|
let mut dev_servers: Vec<DevServer> = self.dev_servers.values().cloned().collect();
|
|
dev_servers.sort_by_key(|d| (d.status == DevServerStatus::Offline, d.name.clone(), d.id));
|
|
dev_servers
|
|
}
|
|
|
|
pub fn dev_server(&self, id: DevServerId) -> Option<&DevServer> {
|
|
self.dev_servers.get(&id)
|
|
}
|
|
|
|
pub fn dev_server_status(&self, id: DevServerId) -> DevServerStatus {
|
|
self.dev_server(id)
|
|
.map(|server| server.status)
|
|
.unwrap_or(DevServerStatus::Offline)
|
|
}
|
|
|
|
pub fn dev_server_projects(&self) -> Vec<DevServerProject> {
|
|
let mut projects: Vec<DevServerProject> =
|
|
self.dev_server_projects.values().cloned().collect();
|
|
projects.sort_by_key(|p| (p.path.clone(), p.id));
|
|
projects
|
|
}
|
|
|
|
pub fn dev_server_project(&self, id: DevServerProjectId) -> Option<&DevServerProject> {
|
|
self.dev_server_projects.get(&id)
|
|
}
|
|
|
|
pub fn dev_server_for_project(&self, id: DevServerProjectId) -> Option<&DevServer> {
|
|
self.dev_server_project(id)
|
|
.and_then(|project| self.dev_server(project.dev_server_id))
|
|
}
|
|
|
|
async fn handle_dev_server_projects_update(
|
|
this: Model<Self>,
|
|
envelope: TypedEnvelope<proto::DevServerProjectsUpdate>,
|
|
_: Arc<Client>,
|
|
mut cx: AsyncAppContext,
|
|
) -> Result<()> {
|
|
this.update(&mut cx, |this, cx| {
|
|
this.dev_servers = envelope
|
|
.payload
|
|
.dev_servers
|
|
.into_iter()
|
|
.map(|dev_server| (DevServerId(dev_server.dev_server_id), dev_server.into()))
|
|
.collect();
|
|
this.dev_server_projects = envelope
|
|
.payload
|
|
.dev_server_projects
|
|
.into_iter()
|
|
.map(|project| (DevServerProjectId(project.id), project.into()))
|
|
.collect();
|
|
|
|
cx.notify();
|
|
})?;
|
|
Ok(())
|
|
}
|
|
|
|
pub fn create_dev_server_project(
|
|
&mut self,
|
|
dev_server_id: DevServerId,
|
|
path: String,
|
|
cx: &mut ModelContext<Self>,
|
|
) -> Task<Result<proto::CreateDevServerProjectResponse>> {
|
|
let client = self.client.clone();
|
|
cx.background_executor().spawn(async move {
|
|
client
|
|
.request(proto::CreateDevServerProject {
|
|
dev_server_id: dev_server_id.0,
|
|
path,
|
|
})
|
|
.await
|
|
})
|
|
}
|
|
|
|
pub fn create_dev_server(
|
|
&mut self,
|
|
name: String,
|
|
cx: &mut ModelContext<Self>,
|
|
) -> Task<Result<proto::CreateDevServerResponse>> {
|
|
let client = self.client.clone();
|
|
cx.background_executor().spawn(async move {
|
|
let result = client.request(proto::CreateDevServer { name }).await?;
|
|
Ok(result)
|
|
})
|
|
}
|
|
|
|
pub fn rename_dev_server(
|
|
&mut self,
|
|
dev_server_id: DevServerId,
|
|
name: String,
|
|
cx: &mut ModelContext<Self>,
|
|
) -> Task<Result<()>> {
|
|
let client = self.client.clone();
|
|
cx.background_executor().spawn(async move {
|
|
client
|
|
.request(proto::RenameDevServer {
|
|
dev_server_id: dev_server_id.0,
|
|
name,
|
|
})
|
|
.await?;
|
|
Ok(())
|
|
})
|
|
}
|
|
|
|
pub fn regenerate_dev_server_token(
|
|
&mut self,
|
|
dev_server_id: DevServerId,
|
|
cx: &mut ModelContext<Self>,
|
|
) -> Task<Result<proto::RegenerateDevServerTokenResponse>> {
|
|
let client = self.client.clone();
|
|
cx.background_executor().spawn(async move {
|
|
client
|
|
.request(proto::RegenerateDevServerToken {
|
|
dev_server_id: dev_server_id.0,
|
|
})
|
|
.await
|
|
})
|
|
}
|
|
|
|
pub fn delete_dev_server(
|
|
&mut self,
|
|
id: DevServerId,
|
|
cx: &mut ModelContext<Self>,
|
|
) -> Task<Result<()>> {
|
|
let client = self.client.clone();
|
|
cx.background_executor().spawn(async move {
|
|
client
|
|
.request(proto::DeleteDevServer {
|
|
dev_server_id: id.0,
|
|
})
|
|
.await?;
|
|
Ok(())
|
|
})
|
|
}
|
|
|
|
pub fn delete_dev_server_project(
|
|
&mut self,
|
|
id: DevServerProjectId,
|
|
cx: &mut ModelContext<Self>,
|
|
) -> Task<Result<()>> {
|
|
let client = self.client.clone();
|
|
cx.background_executor().spawn(async move {
|
|
client
|
|
.request(proto::DeleteDevServerProject {
|
|
dev_server_project_id: id.0,
|
|
})
|
|
.await?;
|
|
Ok(())
|
|
})
|
|
}
|
|
}
|