Remove hosted projects (#19754)

Mikayla Maki created

Release Notes:

- N/A

Change summary

crates/channel/src/channel_store.rs             | 76 ----------------
crates/collab/src/db.rs                         |  1 
crates/collab/src/db/queries.rs                 |  1 
crates/collab/src/db/queries/channels.rs        |  5 -
crates/collab/src/db/queries/hosted_projects.rs | 85 -------------------
crates/collab/src/db/queries/projects.rs        | 34 -------
crates/collab/src/db/tables.rs                  |  1 
crates/collab/src/db/tables/hosted_project.rs   | 27 ------
crates/collab/src/db/tables/project.rs          | 15 ---
crates/collab/src/rpc.rs                        | 30 ------
crates/collab_ui/src/collab_panel.rs            | 60 -------------
crates/project/src/project.rs                   | 53 -----------
crates/proto/proto/zed.proto                    | 23 ----
crates/proto/src/proto.rs                       |  2 
crates/workspace/src/workspace.rs               | 54 -----------
15 files changed, 8 insertions(+), 459 deletions(-)

Detailed changes

crates/channel/src/channel_store.rs 🔗

@@ -3,7 +3,7 @@ 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, Subscription, User, UserId, UserStore};
 use collections::{hash_map, HashMap, HashSet};
 use futures::{channel::mpsc, future::Shared, Future, FutureExt, StreamExt};
 use gpui::{
@@ -33,30 +33,11 @@ struct NotesVersion {
     version: clock::Global,
 }
 
-#[derive(Debug, Clone)]
-pub struct HostedProject {
-    project_id: ProjectId,
-    channel_id: ChannelId,
-    name: SharedString,
-    _visibility: proto::ChannelVisibility,
-}
-impl From<proto::HostedProject> for HostedProject {
-    fn from(project: proto::HostedProject) -> Self {
-        Self {
-            project_id: ProjectId(project.project_id),
-            channel_id: ChannelId(project.channel_id),
-            _visibility: project.visibility(),
-            name: project.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>,
-
     outgoing_invites: HashSet<(ChannelId, UserId)>,
     update_channels_tx: mpsc::UnboundedSender<proto::UpdateChannels>,
     opened_buffers: HashMap<ChannelId, OpenedModelHandle<ChannelBuffer>>,
@@ -85,7 +66,6 @@ pub struct ChannelState {
     observed_notes_version: NotesVersion,
     observed_chat_message: Option<u64>,
     role: Option<ChannelRole>,
-    projects: HashSet<ProjectId>,
 }
 
 impl Channel {
@@ -216,7 +196,6 @@ impl ChannelStore {
             channel_invitations: Vec::default(),
             channel_index: ChannelIndex::default(),
             channel_participants: Default::default(),
-            hosted_projects: Default::default(),
             outgoing_invites: Default::default(),
             opened_buffers: Default::default(),
             opened_chats: Default::default(),
@@ -316,19 +295,6 @@ impl ChannelStore {
         self.channel_index.by_id().get(&channel_id)
     }
 
-    pub fn projects_for_id(&self, channel_id: ChannelId) -> Vec<(SharedString, ProjectId)> {
-        let mut projects: Vec<(SharedString, ProjectId)> = self
-            .channel_states
-            .get(&channel_id)
-            .map(|state| state.projects.clone())
-            .unwrap_or_default()
-            .into_iter()
-            .flat_map(|id| Some((self.hosted_projects.get(&id)?.name.clone(), id)))
-            .collect();
-        projects.sort();
-        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 {
@@ -1102,9 +1068,7 @@ impl ChannelStore {
         let channels_changed = !payload.channels.is_empty()
             || !payload.delete_channels.is_empty()
             || !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.latest_channel_buffer_versions.is_empty();
 
         if channels_changed {
             if !payload.delete_channels.is_empty() {
@@ -1161,34 +1125,6 @@ impl ChannelStore {
                     .or_default()
                     .update_latest_message_id(latest_channel_message.message_id);
             }
-
-            for hosted_project in payload.hosted_projects {
-                let hosted_project: HostedProject = hosted_project.into();
-                if let Some(old_project) = self
-                    .hosted_projects
-                    .insert(hosted_project.project_id, hosted_project.clone())
-                {
-                    self.channel_states
-                        .entry(old_project.channel_id)
-                        .or_default()
-                        .remove_hosted_project(old_project.project_id);
-                }
-                self.channel_states
-                    .entry(hosted_project.channel_id)
-                    .or_default()
-                    .add_hosted_project(hosted_project.project_id);
-            }
-
-            for hosted_project_id in payload.deleted_hosted_projects {
-                let hosted_project_id = ProjectId(hosted_project_id);
-
-                if let Some(old_project) = self.hosted_projects.remove(&hosted_project_id) {
-                    self.channel_states
-                        .entry(old_project.channel_id)
-                        .or_default()
-                        .remove_hosted_project(old_project.project_id);
-                }
-            }
         }
 
         cx.notify();
@@ -1295,12 +1231,4 @@ impl ChannelState {
             };
         }
     }
-
-    fn add_hosted_project(&mut self, project_id: ProjectId) {
-        self.projects.insert(project_id);
-    }
-
-    fn remove_hosted_project(&mut self, project_id: ProjectId) {
-        self.projects.remove(&project_id);
-    }
 }

crates/collab/src/db.rs 🔗

@@ -617,7 +617,6 @@ pub struct ChannelsForUser {
     pub channels: Vec<Channel>,
     pub channel_memberships: Vec<channel_member::Model>,
     pub channel_participants: HashMap<ChannelId, Vec<UserId>>,
-    pub hosted_projects: Vec<proto::HostedProject>,
     pub invited_channels: Vec<Channel>,
 
     pub observed_buffer_versions: Vec<proto::ChannelBufferVersion>,

crates/collab/src/db/queries.rs 🔗

@@ -10,7 +10,6 @@ pub mod contacts;
 pub mod contributors;
 pub mod embeddings;
 pub mod extensions;
-pub mod hosted_projects;
 pub mod messages;
 pub mod notifications;
 pub mod processed_stripe_events;

crates/collab/src/db/queries/channels.rs 🔗

@@ -615,15 +615,10 @@ impl Database {
             .observed_channel_messages(&channel_ids, user_id, tx)
             .await?;
 
-        let hosted_projects = self
-            .get_hosted_projects(&channel_ids, &roles_by_channel_id, tx)
-            .await?;
-
         Ok(ChannelsForUser {
             channel_memberships,
             channels,
             invited_channels,
-            hosted_projects,
             channel_participants,
             latest_buffer_versions,
             latest_channel_messages,

crates/collab/src/db/queries/hosted_projects.rs 🔗

@@ -1,85 +0,0 @@
-use rpc::{proto, ErrorCode};
-
-use super::*;
-
-impl Database {
-    pub async fn get_hosted_projects(
-        &self,
-        channel_ids: &[ChannelId],
-        roles: &HashMap<ChannelId, ChannelRole>,
-        tx: &DatabaseTransaction,
-    ) -> Result<Vec<proto::HostedProject>> {
-        let projects = hosted_project::Entity::find()
-            .find_also_related(project::Entity)
-            .filter(hosted_project::Column::ChannelId.is_in(channel_ids.iter().map(|id| id.0)))
-            .all(tx)
-            .await?
-            .into_iter()
-            .flat_map(|(hosted_project, project)| {
-                if hosted_project.deleted_at.is_some() {
-                    return None;
-                }
-                match hosted_project.visibility {
-                    ChannelVisibility::Public => {}
-                    ChannelVisibility::Members => {
-                        let is_visible = roles
-                            .get(&hosted_project.channel_id)
-                            .map(|role| role.can_see_all_descendants())
-                            .unwrap_or(false);
-                        if !is_visible {
-                            return None;
-                        }
-                    }
-                };
-                Some(proto::HostedProject {
-                    project_id: project?.id.to_proto(),
-                    channel_id: hosted_project.channel_id.to_proto(),
-                    name: hosted_project.name.clone(),
-                    visibility: hosted_project.visibility.into(),
-                })
-            })
-            .collect();
-
-        Ok(projects)
-    }
-
-    pub async fn get_hosted_project(
-        &self,
-        hosted_project_id: HostedProjectId,
-        user_id: UserId,
-        tx: &DatabaseTransaction,
-    ) -> Result<(hosted_project::Model, ChannelRole)> {
-        let project = hosted_project::Entity::find_by_id(hosted_project_id)
-            .one(tx)
-            .await?
-            .ok_or_else(|| anyhow!(ErrorCode::NoSuchProject))?;
-        let channel = channel::Entity::find_by_id(project.channel_id)
-            .one(tx)
-            .await?
-            .ok_or_else(|| anyhow!(ErrorCode::NoSuchChannel))?;
-
-        let role = match project.visibility {
-            ChannelVisibility::Public => {
-                self.check_user_is_channel_participant(&channel, user_id, tx)
-                    .await?
-            }
-            ChannelVisibility::Members => {
-                self.check_user_is_channel_member(&channel, user_id, tx)
-                    .await?
-            }
-        };
-
-        Ok((project, role))
-    }
-
-    pub async fn is_hosted_project(&self, project_id: ProjectId) -> Result<bool> {
-        self.transaction(|tx| async move {
-            Ok(project::Entity::find_by_id(project_id)
-                .one(&*tx)
-                .await?
-                .map(|project| project.hosted_project_id.is_some())
-                .ok_or_else(|| anyhow!(ErrorCode::NoSuchProject))?)
-        })
-        .await
-    }
-}

crates/collab/src/db/queries/projects.rs 🔗

@@ -68,7 +68,6 @@ impl Database {
                     connection.owner_id as i32,
                 ))),
                 id: ActiveValue::NotSet,
-                hosted_project_id: ActiveValue::Set(None),
             }
             .insert(&*tx)
             .await?;
@@ -536,39 +535,6 @@ impl Database {
         .await
     }
 
-    /// Adds the given connection to the specified hosted project
-    pub async fn join_hosted_project(
-        &self,
-        id: ProjectId,
-        user_id: UserId,
-        connection: ConnectionId,
-    ) -> Result<(Project, ReplicaId)> {
-        self.transaction(|tx| async move {
-            let (project, hosted_project) = project::Entity::find_by_id(id)
-                .find_also_related(hosted_project::Entity)
-                .one(&*tx)
-                .await?
-                .ok_or_else(|| anyhow!("hosted project is no longer shared"))?;
-
-            let Some(hosted_project) = hosted_project else {
-                return Err(anyhow!("project is not hosted"))?;
-            };
-
-            let channel = channel::Entity::find_by_id(hosted_project.channel_id)
-                .one(&*tx)
-                .await?
-                .ok_or_else(|| anyhow!("no such channel"))?;
-
-            let role = self
-                .check_user_is_channel_participant(&channel, user_id, &tx)
-                .await?;
-
-            self.join_project_internal(project, user_id, connection, role, &tx)
-                .await
-        })
-        .await
-    }
-
     pub async fn get_project(&self, id: ProjectId) -> Result<project::Model> {
         self.transaction(|tx| async move {
             Ok(project::Entity::find_by_id(id)

crates/collab/src/db/tables.rs 🔗

@@ -18,7 +18,6 @@ pub mod extension;
 pub mod extension_version;
 pub mod feature_flag;
 pub mod follower;
-pub mod hosted_project;
 pub mod language_server;
 pub mod notification;
 pub mod notification_kind;

crates/collab/src/db/tables/hosted_project.rs 🔗

@@ -1,27 +0,0 @@
-use crate::db::{ChannelId, ChannelVisibility, HostedProjectId};
-use sea_orm::entity::prelude::*;
-
-#[derive(Clone, Debug, PartialEq, Eq, DeriveEntityModel)]
-#[sea_orm(table_name = "hosted_projects")]
-pub struct Model {
-    #[sea_orm(primary_key)]
-    pub id: HostedProjectId,
-    pub channel_id: ChannelId,
-    pub name: String,
-    pub visibility: ChannelVisibility,
-    pub deleted_at: Option<DateTime>,
-}
-
-impl ActiveModelBehavior for ActiveModel {}
-
-#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
-pub enum Relation {
-    #[sea_orm(has_one = "super::project::Entity")]
-    Project,
-}
-
-impl Related<super::project::Entity> for Entity {
-    fn to() -> RelationDef {
-        Relation::Project.def()
-    }
-}

crates/collab/src/db/tables/project.rs 🔗

@@ -1,4 +1,4 @@
-use crate::db::{HostedProjectId, ProjectId, Result, RoomId, ServerId, UserId};
+use crate::db::{ProjectId, Result, RoomId, ServerId, UserId};
 use anyhow::anyhow;
 use rpc::ConnectionId;
 use sea_orm::entity::prelude::*;
@@ -12,7 +12,6 @@ pub struct Model {
     pub host_user_id: Option<UserId>,
     pub host_connection_id: Option<i32>,
     pub host_connection_server_id: Option<ServerId>,
-    pub hosted_project_id: Option<HostedProjectId>,
 }
 
 impl Model {
@@ -50,12 +49,6 @@ pub enum Relation {
     Collaborators,
     #[sea_orm(has_many = "super::language_server::Entity")]
     LanguageServers,
-    #[sea_orm(
-        belongs_to = "super::hosted_project::Entity",
-        from = "Column::HostedProjectId",
-        to = "super::hosted_project::Column::Id"
-    )]
-    HostedProject,
 }
 
 impl Related<super::user::Entity> for Entity {
@@ -88,10 +81,4 @@ impl Related<super::language_server::Entity> for Entity {
     }
 }
 
-impl Related<super::hosted_project::Entity> for Entity {
-    fn to() -> RelationDef {
-        Relation::HostedProject.def()
-    }
-}
-
 impl ActiveModelBehavior for ActiveModel {}

crates/collab/src/rpc.rs 🔗

@@ -287,7 +287,6 @@ impl Server {
             .add_request_handler(share_project)
             .add_message_handler(unshare_project)
             .add_request_handler(join_project)
-            .add_request_handler(join_hosted_project)
             .add_message_handler(leave_project)
             .add_request_handler(update_project)
             .add_request_handler(update_worktree)
@@ -1795,11 +1794,6 @@ impl JoinProjectInternalResponse for Response<proto::JoinProject> {
         Response::<proto::JoinProject>::send(self, result)
     }
 }
-impl JoinProjectInternalResponse for Response<proto::JoinHostedProject> {
-    fn send(self, result: proto::JoinProjectResponse) -> Result<()> {
-        Response::<proto::JoinHostedProject>::send(self, result)
-    }
-}
 
 fn join_project_internal(
     response: impl JoinProjectInternalResponse,
@@ -1923,11 +1917,6 @@ async fn leave_project(request: proto::LeaveProject, session: Session) -> Result
     let sender_id = session.connection_id;
     let project_id = ProjectId::from_proto(request.project_id);
     let db = session.db().await;
-    if db.is_hosted_project(project_id).await? {
-        let project = db.leave_hosted_project(project_id, sender_id).await?;
-        project_left(&project, &session);
-        return Ok(());
-    }
 
     let (room, project) = &*db.leave_project(project_id, sender_id).await?;
     tracing::info!(
@@ -1943,24 +1932,6 @@ async fn leave_project(request: proto::LeaveProject, session: Session) -> Result
     Ok(())
 }
 
-async fn join_hosted_project(
-    request: proto::JoinHostedProject,
-    response: Response<proto::JoinHostedProject>,
-    session: Session,
-) -> Result<()> {
-    let (mut project, replica_id) = session
-        .db()
-        .await
-        .join_hosted_project(
-            ProjectId(request.project_id as i32),
-            session.user_id(),
-            session.connection_id,
-        )
-        .await?;
-
-    join_project_internal(response, session, &mut project, &replica_id)
-}
-
 /// Updates other participants with changes to the project
 async fn update_project(
     request: proto::UpdateProject,
@@ -4202,7 +4173,6 @@ fn build_channels_update(channels: ChannelsForUser) -> proto::UpdateChannels {
         update.channel_invitations.push(channel.to_proto());
     }
 
-    update.hosted_projects = channels.hosted_projects;
     update
 }
 

crates/collab_ui/src/collab_panel.rs 🔗

@@ -5,7 +5,7 @@ use self::channel_modal::ChannelModal;
 use crate::{channel_view::ChannelView, chat_panel::ChatPanel, CollaborationPanelSettings};
 use call::ActiveCall;
 use channel::{Channel, ChannelEvent, ChannelStore};
-use client::{ChannelId, Client, Contact, ProjectId, User, UserStore};
+use client::{ChannelId, Client, Contact, User, UserStore};
 use contact_finder::ContactFinder;
 use db::kvp::KEY_VALUE_STORE;
 use editor::{Editor, EditorElement, EditorStyle};
@@ -182,10 +182,6 @@ enum ListEntry {
     ChannelEditor {
         depth: usize,
     },
-    HostedProject {
-        id: ProjectId,
-        name: SharedString,
-    },
     Contact {
         contact: Arc<Contact>,
         calling: bool,
@@ -566,7 +562,6 @@ impl CollabPanel {
                     }
                 }
 
-                let hosted_projects = channel_store.projects_for_id(channel.id);
                 let has_children = channel_store
                     .channel_at_index(mat.candidate_id + 1)
                     .map_or(false, |next_channel| {
@@ -600,10 +595,6 @@ impl CollabPanel {
                         });
                     }
                 }
-
-                for (name, id) in hosted_projects {
-                    self.entries.push(ListEntry::HostedProject { id, name });
-                }
             }
         }
 
@@ -1029,40 +1020,6 @@ impl CollabPanel {
             .tooltip(move |cx| Tooltip::text("Open Chat", cx))
     }
 
-    fn render_channel_project(
-        &self,
-        id: ProjectId,
-        name: &SharedString,
-        is_selected: bool,
-        cx: &mut ViewContext<Self>,
-    ) -> impl IntoElement {
-        ListItem::new(ElementId::NamedInteger(
-            "channel-project".into(),
-            id.0 as usize,
-        ))
-        .indent_level(2)
-        .indent_step_size(px(20.))
-        .selected(is_selected)
-        .on_click(cx.listener(move |this, _, cx| {
-            if let Some(workspace) = this.workspace.upgrade() {
-                let app_state = workspace.read(cx).app_state().clone();
-                workspace::join_hosted_project(id, app_state, cx).detach_and_prompt_err(
-                    "Failed to open project",
-                    cx,
-                    |_, _| None,
-                )
-            }
-        }))
-        .start_slot(
-            h_flex()
-                .relative()
-                .gap_1()
-                .child(IconButton::new(0, IconName::FileTree)),
-        )
-        .child(Label::new(name.clone()))
-        .tooltip(move |cx| Tooltip::text("Open Project", cx))
-    }
-
     fn has_subchannels(&self, ix: usize) -> bool {
         self.entries.get(ix).map_or(false, |entry| {
             if let ListEntry::Channel { has_children, .. } = entry {
@@ -1538,12 +1495,6 @@ impl CollabPanel {
                     ListEntry::ChannelChat { channel_id } => {
                         self.join_channel_chat(*channel_id, cx)
                     }
-                    ListEntry::HostedProject {
-                        id: _id,
-                        name: _name,
-                    } => {
-                        // todo()
-                    }
                     ListEntry::OutgoingRequest(_) => {}
                     ListEntry::ChannelEditor { .. } => {}
                 }
@@ -2157,10 +2108,6 @@ impl CollabPanel {
             ListEntry::ChannelChat { channel_id } => self
                 .render_channel_chat(*channel_id, is_selected, cx)
                 .into_any_element(),
-
-            ListEntry::HostedProject { id, name } => self
-                .render_channel_project(*id, name, is_selected, cx)
-                .into_any_element(),
         }
     }
 
@@ -2898,11 +2845,6 @@ impl PartialEq for ListEntry {
                     return channel_1.id == channel_2.id;
                 }
             }
-            ListEntry::HostedProject { id, .. } => {
-                if let ListEntry::HostedProject { id: other_id, .. } = other {
-                    return id == other_id;
-                }
-            }
             ListEntry::ChannelNotes { channel_id } => {
                 if let ListEntry::ChannelNotes {
                     channel_id: other_id,

crates/project/src/project.rs 🔗

@@ -24,9 +24,7 @@ mod yarn;
 
 use anyhow::{anyhow, Context as _, Result};
 use buffer_store::{BufferStore, BufferStoreEvent};
-use client::{
-    proto, Client, Collaborator, PendingEntitySubscription, ProjectId, TypedEnvelope, UserStore,
-};
+use client::{proto, Client, Collaborator, PendingEntitySubscription, TypedEnvelope, UserStore};
 use clock::ReplicaId;
 use collections::{BTreeSet, HashMap, HashSet};
 use debounced_delay::DebouncedDelay;
@@ -154,7 +152,6 @@ pub struct Project {
     remotely_created_models: Arc<Mutex<RemotelyCreatedModels>>,
     terminals: Terminals,
     node: Option<NodeRuntime>,
-    hosted_project_id: Option<ProjectId>,
     search_history: SearchHistory,
     search_included_history: SearchHistory,
     search_excluded_history: SearchHistory,
@@ -678,7 +675,6 @@ impl Project {
                     local_handles: Vec::new(),
                 },
                 node: Some(node),
-                hosted_project_id: None,
                 search_history: Self::new_search_history(),
                 environment,
                 remotely_created_models: Default::default(),
@@ -796,7 +792,6 @@ impl Project {
                     local_handles: Vec::new(),
                 },
                 node: Some(node),
-                hosted_project_id: None,
                 search_history: Self::new_search_history(),
                 environment,
                 remotely_created_models: Default::default(),
@@ -993,7 +988,6 @@ impl Project {
                     local_handles: Vec::new(),
                 },
                 node: None,
-                hosted_project_id: None,
                 search_history: Self::new_search_history(),
                 search_included_history: Self::new_search_history(),
                 search_excluded_history: Self::new_search_history(),
@@ -1045,47 +1039,6 @@ impl Project {
         Ok(this)
     }
 
-    pub async fn hosted(
-        remote_id: ProjectId,
-        user_store: Model<UserStore>,
-        client: Arc<Client>,
-        languages: Arc<LanguageRegistry>,
-        fs: Arc<dyn Fs>,
-        cx: AsyncAppContext,
-    ) -> Result<Model<Self>> {
-        client.authenticate_and_connect(true, &cx).await?;
-
-        let subscriptions = [
-            EntitySubscription::Project(client.subscribe_to_entity::<Self>(remote_id.0)?),
-            EntitySubscription::BufferStore(
-                client.subscribe_to_entity::<BufferStore>(remote_id.0)?,
-            ),
-            EntitySubscription::WorktreeStore(
-                client.subscribe_to_entity::<WorktreeStore>(remote_id.0)?,
-            ),
-            EntitySubscription::LspStore(client.subscribe_to_entity::<LspStore>(remote_id.0)?),
-            EntitySubscription::SettingsObserver(
-                client.subscribe_to_entity::<SettingsObserver>(remote_id.0)?,
-            ),
-        ];
-        let response = client
-            .request_envelope(proto::JoinHostedProject {
-                project_id: remote_id.0,
-            })
-            .await?;
-        Self::from_join_project_response(
-            response,
-            subscriptions,
-            client,
-            true,
-            user_store,
-            languages,
-            fs,
-            cx,
-        )
-        .await
-    }
-
     fn new_search_history() -> SearchHistory {
         SearchHistory::new(
             Some(MAX_PROJECT_SEARCH_HISTORY_SIZE),
@@ -1290,10 +1243,6 @@ impl Project {
         }
     }
 
-    pub fn hosted_project_id(&self) -> Option<ProjectId> {
-        self.hosted_project_id
-    }
-
     pub fn supports_terminal(&self, _cx: &AppContext) -> bool {
         if self.is_local() {
             return true;

crates/proto/proto/zed.proto 🔗

@@ -196,8 +196,6 @@ message Envelope {
         GetImplementation get_implementation = 162;
         GetImplementationResponse get_implementation_response = 163;
 
-        JoinHostedProject join_hosted_project = 164;
-
         CountLanguageModelTokens count_language_model_tokens = 230;
         CountLanguageModelTokensResponse count_language_model_tokens_response = 231;
         GetCachedEmbeddings get_cached_embeddings = 189;
@@ -292,6 +290,7 @@ message Envelope {
 
     reserved 87 to 88;
     reserved 158 to 161;
+    reserved 164;
     reserved 166 to 169;
     reserved 177 to 185;
     reserved 188;
@@ -523,11 +522,6 @@ message JoinProject {
     uint64 project_id = 1;
 }
 
-message JoinHostedProject {
-    uint64 project_id = 1;
-}
-
-
 message ListRemoteDirectory {
     uint64 dev_server_id = 1;
     string path = 2;
@@ -1294,13 +1288,7 @@ message UpdateChannels {
     repeated ChannelMessageId latest_channel_message_ids = 8;
     repeated ChannelBufferVersion latest_channel_buffer_versions = 9;
 
-    repeated HostedProject hosted_projects = 10;
-    repeated uint64 deleted_hosted_projects = 11;
-
-    reserved 12;
-    reserved 13;
-    reserved 14;
-    reserved 15;
+    reserved 10 to 15;
 }
 
 message UpdateUserChannels {
@@ -1329,13 +1317,6 @@ message ChannelParticipants {
     repeated uint64 participant_user_ids = 2;
 }
 
-message HostedProject {
-    uint64 project_id = 1;
-    uint64 channel_id = 2;
-    string name = 3;
-    ChannelVisibility visibility = 4;
-}
-
 message JoinChannel {
     uint64 channel_id = 1;
 }

crates/proto/src/proto.rs 🔗

@@ -228,7 +228,6 @@ messages!(
     (JoinChannelChat, Foreground),
     (JoinChannelChatResponse, Foreground),
     (JoinProject, Foreground),
-    (JoinHostedProject, Foreground),
     (JoinProjectResponse, Foreground),
     (JoinRoom, Foreground),
     (JoinRoomResponse, Foreground),
@@ -411,7 +410,6 @@ request_messages!(
     (JoinChannel, JoinRoomResponse),
     (JoinChannelBuffer, JoinChannelBufferResponse),
     (JoinChannelChat, JoinChannelChatResponse),
-    (JoinHostedProject, JoinProjectResponse),
     (JoinProject, JoinProjectResponse),
     (JoinRoom, JoinRoomResponse),
     (LeaveChannelBuffer, Ack),

crates/workspace/src/workspace.rs 🔗

@@ -16,7 +16,7 @@ use anyhow::{anyhow, Context as _, Result};
 use call::{call_settings::CallSettings, ActiveCall};
 use client::{
     proto::{self, ErrorCode, PanelId, PeerId},
-    ChannelId, Client, ErrorExt, ProjectId, Status, TypedEnvelope, UserStore,
+    ChannelId, Client, ErrorExt, Status, TypedEnvelope, UserStore,
 };
 use collections::{hash_map, HashMap, HashSet};
 use derive_more::{Deref, DerefMut};
@@ -5469,58 +5469,6 @@ pub fn create_and_open_local_file(
     })
 }
 
-pub fn join_hosted_project(
-    hosted_project_id: ProjectId,
-    app_state: Arc<AppState>,
-    cx: &mut AppContext,
-) -> Task<Result<()>> {
-    cx.spawn(|mut cx| async move {
-        let existing_window = cx.update(|cx| {
-            cx.windows().into_iter().find_map(|window| {
-                let workspace = window.downcast::<Workspace>()?;
-                workspace
-                    .read(cx)
-                    .is_ok_and(|workspace| {
-                        workspace.project().read(cx).hosted_project_id() == Some(hosted_project_id)
-                    })
-                    .then_some(workspace)
-            })
-        })?;
-
-        let workspace = if let Some(existing_window) = existing_window {
-            existing_window
-        } else {
-            let project = Project::hosted(
-                hosted_project_id,
-                app_state.user_store.clone(),
-                app_state.client.clone(),
-                app_state.languages.clone(),
-                app_state.fs.clone(),
-                cx.clone(),
-            )
-            .await?;
-
-            let window_bounds_override = window_bounds_env_override();
-            cx.update(|cx| {
-                let mut options = (app_state.build_window_options)(None, cx);
-                options.window_bounds = window_bounds_override.map(WindowBounds::Windowed);
-                cx.open_window(options, |cx| {
-                    cx.new_view(|cx| {
-                        Workspace::new(Default::default(), project, app_state.clone(), cx)
-                    })
-                })
-            })??
-        };
-
-        workspace.update(&mut cx, |_, cx| {
-            cx.activate(true);
-            cx.activate_window();
-        })?;
-
-        Ok(())
-    })
-}
-
 pub fn open_ssh_project(
     window: WindowHandle<Workspace>,
     connection_options: SshConnectionOptions,