Detailed changes
@@ -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);
- }
}
@@ -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>,
@@ -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;
@@ -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,
@@ -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
- }
-}
@@ -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)
@@ -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;
@@ -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()
- }
-}
@@ -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 {}
@@ -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
}
@@ -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,
@@ -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;
@@ -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;
}
@@ -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),
@@ -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,