Skip to content

Commit

Permalink
Remote projects can be created and show up
Browse files Browse the repository at this point in the history
Co-Authored-By: Bennet <bennetbo@gmx.de>
  • Loading branch information
ConradIrwin and bennetbo committed Apr 2, 2024
1 parent ad03a7e commit 581bfa3
Show file tree
Hide file tree
Showing 20 changed files with 635 additions and 22 deletions.
2 changes: 1 addition & 1 deletion crates/channel/src/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub use channel_chat::{
mentions_to_proto, ChannelChat, ChannelChatEvent, ChannelMessage, ChannelMessageId,
MessageParams,
};
pub use channel_store::{Channel, ChannelEvent, ChannelMembership, ChannelStore};
pub use channel_store::{Channel, ChannelEvent, ChannelMembership, ChannelStore, RemoteProject};

#[cfg(test)]
mod channel_store_tests;
Expand Down
175 changes: 172 additions & 3 deletions crates/channel/src/channel_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ mod channel_index;
use crate::{channel_buffer::ChannelBuffer, channel_chat::ChannelChat, ChannelMessage};
use anyhow::{anyhow, Result};
use channel_index::ChannelIndex;
use client::{ChannelId, Client, ClientSettings, ProjectId, Subscription, User, UserId, UserStore};
use client::{
ChannelId, Client, ClientSettings, DevServerId, ProjectId, RemoteProjectId, Subscription, User,
UserId, UserStore,
};
use collections::{hash_map, HashMap, HashSet};
use futures::{channel::mpsc, future::Shared, Future, FutureExt, StreamExt};
use gpui::{
Expand Down Expand Up @@ -40,7 +43,6 @@ pub struct HostedProject {
name: SharedString,
_visibility: proto::ChannelVisibility,
}

impl From<proto::HostedProject> for HostedProject {
fn from(project: proto::HostedProject) -> Self {
Self {
Expand All @@ -52,12 +54,52 @@ impl From<proto::HostedProject> for HostedProject {
}
}

#[derive(Debug, Clone)]
pub struct RemoteProject {
pub id: RemoteProjectId,
pub project_id: Option<ProjectId>,
pub channel_id: ChannelId,
pub name: SharedString,
pub dev_server_id: DevServerId,
}

impl From<proto::RemoteProject> for RemoteProject {
fn from(project: proto::RemoteProject) -> Self {
Self {
id: RemoteProjectId(project.id),
project_id: project.project_id.map(|id| ProjectId(id)),
channel_id: ChannelId(project.channel_id),
name: project.name.into(),
dev_server_id: DevServerId(project.dev_server_id),
}
}
}

#[derive(Debug, Clone)]
pub struct DevServer {
pub id: DevServerId,
pub channel_id: ChannelId,
pub name: SharedString,
}

impl From<proto::DevServer> for DevServer {
fn from(dev_server: proto::DevServer) -> Self {
Self {
id: DevServerId(dev_server.dev_server_id),
channel_id: ChannelId(dev_server.channel_id),
name: dev_server.name.into(),
}
}
}

pub struct ChannelStore {
pub channel_index: ChannelIndex,
channel_invitations: Vec<Arc<Channel>>,
channel_participants: HashMap<ChannelId, Vec<Arc<User>>>,
channel_states: HashMap<ChannelId, ChannelState>,
hosted_projects: HashMap<ProjectId, HostedProject>,
remote_projects: HashMap<RemoteProjectId, RemoteProject>,
dev_servers: HashMap<DevServerId, DevServer>,

outgoing_invites: HashSet<(ChannelId, UserId)>,
update_channels_tx: mpsc::UnboundedSender<proto::UpdateChannels>,
Expand Down Expand Up @@ -87,6 +129,8 @@ pub struct ChannelState {
observed_chat_message: Option<u64>,
role: Option<ChannelRole>,
projects: HashSet<ProjectId>,
dev_servers: HashSet<DevServerId>,
remote_projects: HashSet<RemoteProjectId>,
}

impl Channel {
Expand Down Expand Up @@ -217,6 +261,8 @@ impl ChannelStore {
channel_index: ChannelIndex::default(),
channel_participants: Default::default(),
hosted_projects: Default::default(),
remote_projects: Default::default(),
dev_servers: Default::default(),
outgoing_invites: Default::default(),
opened_buffers: Default::default(),
opened_chats: Default::default(),
Expand Down Expand Up @@ -316,6 +362,32 @@ impl ChannelStore {
projects
}

pub fn dev_servers_for_id(&self, channel_id: ChannelId) -> Vec<DevServer> {
let mut dev_servers: Vec<DevServer> = self
.channel_states
.get(&channel_id)
.map(|state| state.dev_servers.clone())
.unwrap_or_default()
.into_iter()
.flat_map(|id| self.dev_servers.get(&id).cloned())
.collect();
dev_servers.sort_by_key(|s| (s.name.clone(), s.id));
dev_servers
}

pub fn remote_projects_for_id(&self, channel_id: ChannelId) -> Vec<RemoteProject> {
let mut remote_projects: Vec<RemoteProject> = self
.channel_states
.get(&channel_id)
.map(|state| state.remote_projects.clone())
.unwrap_or_default()
.into_iter()
.flat_map(|id| self.remote_projects.get(&id).cloned())
.collect();
remote_projects.sort_by_key(|p| (p.name.clone(), p.id));
remote_projects
}

pub fn has_open_channel_buffer(&self, channel_id: ChannelId, _cx: &AppContext) -> bool {
if let Some(buffer) = self.opened_buffers.get(&channel_id) {
if let OpenedModelHandle::Open(buffer) = buffer {
Expand Down Expand Up @@ -812,6 +884,28 @@ impl ChannelStore {
})
}

pub fn create_remote_project(
&mut self,
channel_id: ChannelId,
dev_server_id: DevServerId,
name: String,
path: String,
cx: &mut ModelContext<Self>,
) -> Task<Result<()>> {
let client = self.client.clone();
cx.background_executor().spawn(async move {
client
.request(proto::CreateRemoteProject {
channel_id: channel_id.0,
dev_server_id: dev_server_id.0,
name,
path,
})
.await?;
Ok(())
})
}

pub fn get_channel_member_details(
&self,
channel_id: ChannelId,
Expand Down Expand Up @@ -1059,6 +1153,7 @@ impl ChannelStore {
payload: proto::UpdateChannels,
cx: &mut ModelContext<ChannelStore>,
) -> Option<Task<Result<()>>> {
dbg!(&payload);
if !payload.remove_channel_invitations.is_empty() {
self.channel_invitations
.retain(|channel| !payload.remove_channel_invitations.contains(&channel.id.0));
Expand Down Expand Up @@ -1092,7 +1187,11 @@ impl ChannelStore {
|| !payload.latest_channel_message_ids.is_empty()
|| !payload.latest_channel_buffer_versions.is_empty()
|| !payload.hosted_projects.is_empty()
|| !payload.deleted_hosted_projects.is_empty();
|| !payload.deleted_hosted_projects.is_empty()
|| !payload.dev_servers.is_empty()
|| !payload.deleted_dev_servers.is_empty()
|| !payload.remote_projects.is_empty()
|| !payload.deleted_remote_projects.is_empty();

if channels_changed {
if !payload.delete_channels.is_empty() {
Expand Down Expand Up @@ -1180,6 +1279,60 @@ impl ChannelStore {
.remove_hosted_project(old_project.project_id);
}
}

for remote_project in payload.remote_projects {
let remote_project: RemoteProject = remote_project.into();
if let Some(old_remote_project) = self
.remote_projects
.insert(remote_project.id, remote_project.clone())
{
self.channel_states
.entry(old_remote_project.channel_id)
.or_default()
.remove_remote_project(old_remote_project.id);
}
self.channel_states
.entry(remote_project.channel_id)
.or_default()
.add_remote_project(remote_project.id);
}

for remote_project_id in payload.deleted_remote_projects {
let remote_project_id = RemoteProjectId(remote_project_id);

if let Some(old_project) = self.remote_projects.remove(&remote_project_id) {
self.channel_states
.entry(old_project.channel_id)
.or_default()
.remove_remote_project(old_project.id);
}
}

for dev_server in payload.dev_servers {
let dev_server: DevServer = dev_server.into();
if let Some(old_server) = self.dev_servers.insert(dev_server.id, dev_server.clone())
{
self.channel_states
.entry(old_server.channel_id)
.or_default()
.remove_dev_server(old_server.id);
}
self.channel_states
.entry(dev_server.channel_id)
.or_default()
.add_dev_server(dev_server.id);
}

for dev_server_id in payload.deleted_dev_servers {
let dev_server_id = DevServerId(dev_server_id);

if let Some(old_server) = self.dev_servers.remove(&dev_server_id) {
self.channel_states
.entry(old_server.channel_id)
.or_default()
.remove_dev_server(old_server.id);
}
}
}

cx.notify();
Expand Down Expand Up @@ -1294,4 +1447,20 @@ impl ChannelState {
fn remove_hosted_project(&mut self, project_id: ProjectId) {
self.projects.remove(&project_id);
}

fn add_remote_project(&mut self, remote_project_id: RemoteProjectId) {
self.remote_projects.insert(remote_project_id);
}

fn remove_remote_project(&mut self, remote_project_id: RemoteProjectId) {
self.remote_projects.remove(&remote_project_id);
}

fn add_dev_server(&mut self, dev_server_id: DevServerId) {
self.dev_servers.insert(dev_server_id);
}

fn remove_dev_server(&mut self, dev_server_id: DevServerId) {
self.dev_servers.remove(&dev_server_id);
}
}
6 changes: 6 additions & 0 deletions crates/client/src/user.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ impl std::fmt::Display for ChannelId {
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
pub struct ProjectId(pub u64);

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
pub struct DevServerId(pub u64);

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
pub struct RemoteProjectId(pub u64);

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ParticipantIndex(pub u32);

Expand Down
14 changes: 13 additions & 1 deletion crates/collab/migrations.sqlite/20221109000000_test_schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,9 @@ CREATE TABLE hosted_projects (
channel_id INTEGER NOT NULL REFERENCES channels(id),
name TEXT NOT NULL,
visibility TEXT NOT NULL,
deleted_at TIMESTAMP NULL
deleted_at TIMESTAMP NULL,
dev_server_id INTEGER REFERENCES dev_servers(id),
dev_server_path TEXT,
);
CREATE INDEX idx_hosted_projects_on_channel_id ON hosted_projects (channel_id);
CREATE UNIQUE INDEX uix_hosted_projects_on_channel_id_and_name ON hosted_projects (channel_id, name) WHERE (deleted_at IS NULL);
Expand All @@ -409,3 +411,13 @@ CREATE TABLE dev_servers (
hashed_token TEXT NOT NULL
);
CREATE INDEX idx_dev_servers_on_channel_id ON dev_servers (channel_id);

CREATE TABLE remote_projects (
id INTEGER PRIMARY KEY AUTOINCREMENT,
channel_id INTEGER NOT NULL REFERENCES channels(id),
dev_server_id INTEGER NOT NULL REFERENCES dev_servers(id),
name TEXT NOT NULL,
path TEXT NOT NULL
);

ALTER TABLE hosted_projects ADD COLUMN remote_project_id INTEGER REFERENCES remote_projects(id);
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
CREATE TABLE remote_projects (
id INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
channel_id INT NOT NULL REFERENCES channels(id),
dev_server_id INT NOT NULL REFERENCES dev_servers(id),
name TEXT NOT NULL,
path TEXT NOT NULL
);

ALTER TABLE projects ADD COLUMN remote_project_id INTEGER REFERENCES remote_projects(id);
2 changes: 2 additions & 0 deletions crates/collab/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,8 @@ pub struct ChannelsForUser {
pub channel_memberships: Vec<channel_member::Model>,
pub channel_participants: HashMap<ChannelId, Vec<UserId>>,
pub hosted_projects: Vec<proto::HostedProject>,
pub dev_servers: Vec<proto::DevServer>,
pub remote_projects: Vec<proto::RemoteProject>,

pub observed_buffer_versions: Vec<proto::ChannelBufferVersion>,
pub observed_channel_messages: Vec<proto::ChannelMessageId>,
Expand Down
1 change: 1 addition & 0 deletions crates/collab/src/db/ids.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ id_type!(NotificationId);
id_type!(NotificationKindId);
id_type!(ProjectCollaboratorId);
id_type!(ProjectId);
id_type!(RemoteProjectId);
id_type!(ReplicaId);
id_type!(RoomId);
id_type!(RoomParticipantId);
Expand Down
1 change: 1 addition & 0 deletions crates/collab/src/db/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub mod messages;
pub mod notifications;
pub mod projects;
pub mod rate_buckets;
pub mod remote_projects;
pub mod rooms;
pub mod servers;
pub mod users;
5 changes: 5 additions & 0 deletions crates/collab/src/db/queries/channels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -640,10 +640,15 @@ impl Database {
.get_hosted_projects(&channel_ids, &roles_by_channel_id, tx)
.await?;

let dev_servers = self.get_dev_servers(&channel_ids, tx).await?;
let remote_projects = self.get_remote_projects(&channel_ids, tx).await?;

Ok(ChannelsForUser {
channel_memberships,
channels,
hosted_projects,
dev_servers,
remote_projects,
channel_participants,
latest_buffer_versions,
latest_channel_messages,
Expand Down
25 changes: 23 additions & 2 deletions crates/collab/src/db/queries/dev_servers.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use sea_orm::EntityTrait;
use rpc::proto;
use sea_orm::{ColumnTrait, DatabaseTransaction, EntityTrait, QueryFilter};

use super::{dev_server, Database, DevServerId};
use super::{dev_server, ChannelId, Database, DevServerId};

impl Database {
pub async fn get_dev_server(
Expand All @@ -15,4 +16,24 @@ impl Database {
})
.await
}

pub async fn get_dev_servers(
&self,
channel_ids: &Vec<ChannelId>,
tx: &DatabaseTransaction,
) -> crate::Result<Vec<proto::DevServer>> {
let servers = dev_server::Entity::find()
.filter(dev_server::Column::ChannelId.is_in(channel_ids.iter().map(|id| id.0)))
.all(tx)
.await?;
Ok(servers
.into_iter()
.map(|s| proto::DevServer {
channel_id: s.channel_id.to_proto(),
name: s.name,
dev_server_id: s.id.to_proto(),
status: proto::DevServerStatus::Online.into(),
})
.collect())
}
}
1 change: 1 addition & 0 deletions crates/collab/src/db/queries/projects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ impl Database {
))),
id: ActiveValue::NotSet,
hosted_project_id: ActiveValue::Set(None),
remote_project_id: ActiveValue::Set(None),
}
.insert(&*tx)
.await?;
Expand Down
Loading

0 comments on commit 581bfa3

Please sign in to comment.