diff --git a/crates/call2/src/call2.rs b/crates/call2/src/call2.rs index 7885ef6e3f..3b821d4bec 100644 --- a/crates/call2/src/call2.rs +++ b/crates/call2/src/call2.rs @@ -14,8 +14,8 @@ use client::{ use collections::HashSet; use futures::{channel::oneshot, future::Shared, Future, FutureExt}; use gpui::{ - AppContext, AsyncAppContext, Context, EventEmitter, Model, ModelContext, Subscription, Task, - View, ViewContext, VisualContext, WeakModel, WeakView, + AppContext, AsyncAppContext, Context, EventEmitter, Model, ModelContext, PromptLevel, + Subscription, Task, View, ViewContext, VisualContext, WeakModel, WeakView, WindowHandle, }; pub use participant::ParticipantLocation; use postage::watch; @@ -334,12 +334,55 @@ impl ActiveCall { pub fn join_channel( &mut self, channel_id: u64, + requesting_window: WindowHandle, cx: &mut ModelContext, ) -> Task>>> { if let Some(room) = self.room().cloned() { if room.read(cx).channel_id() == Some(channel_id) { - return Task::ready(Ok(Some(room))); - } else { + return cx.spawn(|_, _| async move { + todo!(); + // let future = room.update(&mut cx, |room, cx| { + // room.most_active_project(cx).map(|(host, project)| { + // room.join_project(project, host, app_state.clone(), cx) + // }) + // }) + + // if let Some(future) = future { + // future.await?; + // } + + // Ok(Some(room)) + }); + } + + let should_prompt = room.update(cx, |room, _| { + room.channel_id().is_some() + && room.is_sharing_project() + && room.remote_participants().len() > 0 + }); + if should_prompt { + return cx.spawn(|this, mut cx| async move { + let answer = requesting_window.update(&mut cx, |_, cx| { + cx.prompt( + PromptLevel::Warning, + "Leaving this call will unshare your current project.\nDo you want to switch channels?", + &["Yes, Join Channel", "Cancel"], + ) + })?; + if answer.await? == 1 { + return Ok(None); + } + + room.update(&mut cx, |room, cx| room.clear_state(cx))?; + + this.update(&mut cx, |this, cx| { + this.join_channel(channel_id, requesting_window, cx) + })? + .await + }); + } + + if room.read(cx).channel_id().is_some() { room.update(cx, |room, cx| room.clear_state(cx)); } } diff --git a/crates/collab_ui2/src/collab_panel.rs b/crates/collab_ui2/src/collab_panel.rs index 3bbdfd5f92..3c2e78423a 100644 --- a/crates/collab_ui2/src/collab_panel.rs +++ b/crates/collab_ui2/src/collab_panel.rs @@ -90,10 +90,10 @@ use rpc::proto; // channel_id: ChannelId, // } -// #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -// pub struct OpenChannelNotes { -// pub channel_id: ChannelId, -// } +#[derive(Action, PartialEq, Debug, Clone, Serialize, Deserialize)] +pub struct OpenChannelNotes { + pub channel_id: ChannelId, +} // #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] // pub struct JoinChannelCall { @@ -167,10 +167,10 @@ use editor::Editor; use feature_flags::{ChannelsAlpha, FeatureFlagAppExt}; use fuzzy::{match_strings, StringMatchCandidate}; use gpui::{ - actions, div, img, prelude::*, serde_json, AppContext, AsyncWindowContext, Div, EventEmitter, - FocusHandle, Focusable, FocusableView, InteractiveElement, IntoElement, Model, ParentElement, - Render, RenderOnce, SharedString, Styled, Subscription, View, ViewContext, VisualContext, - WeakView, + actions, div, img, prelude::*, serde_json, Action, AppContext, AsyncWindowContext, Div, + EventEmitter, FocusHandle, Focusable, FocusableView, InteractiveElement, IntoElement, Model, + ParentElement, Render, RenderOnce, SharedString, Styled, Subscription, View, ViewContext, + VisualContext, WeakView, }; use project::Fs; use serde_derive::{Deserialize, Serialize}; @@ -322,17 +322,17 @@ pub struct CollabPanel { subscriptions: Vec, collapsed_sections: Vec
, collapsed_channels: Vec, - // drag_target_channel: ChannelDragTarget, + drag_target_channel: ChannelDragTarget, workspace: WeakView, // context_menu_on_selected: bool, } -// #[derive(PartialEq, Eq)] -// enum ChannelDragTarget { -// None, -// Root, -// Channel(ChannelId), -// } +#[derive(PartialEq, Eq)] +enum ChannelDragTarget { + None, + Root, + Channel(ChannelId), +} #[derive(Serialize, Deserialize)] struct SerializedCollabPanel { @@ -614,7 +614,7 @@ impl CollabPanel { workspace: workspace.weak_handle(), client: workspace.app_state().client.clone(), // context_menu_on_selected: true, - // drag_target_channel: ChannelDragTarget::None, + drag_target_channel: ChannelDragTarget::None, // list_state, }; @@ -2346,11 +2346,12 @@ impl CollabPanel { // } // } - // fn open_channel_notes(&mut self, action: &OpenChannelNotes, cx: &mut ViewContext) { - // if let Some(workspace) = self.workspace.upgrade(cx) { - // ChannelView::open(action.channel_id, workspace, cx).detach(); - // } - // } + fn open_channel_notes(&mut self, action: &OpenChannelNotes, cx: &mut ViewContext) { + if let Some(workspace) = self.workspace.upgrade() { + todo!(); + // ChannelView::open(action.channel_id, workspace, cx).detach(); + } + } // fn show_inline_context_menu(&mut self, _: &menu::ShowContextMenu, cx: &mut ViewContext) { // let Some(channel) = self.selected_channel() else { @@ -2504,21 +2505,17 @@ impl CollabPanel { // .detach_and_log_err(cx); // } - // fn join_channel(&self, channel_id: u64, cx: &mut ViewContext) { - // let Some(workspace) = self.workspace.upgrade(cx) else { - // return; - // }; - // let Some(handle) = cx.window().downcast::() else { - // return; - // }; - // workspace::join_channel( - // channel_id, - // workspace.read(cx).app_state().clone(), - // Some(handle), - // cx, - // ) - // .detach_and_log_err(cx) - // } + fn join_channel(&self, channel_id: u64, cx: &mut ViewContext) { + let Some(handle) = cx.window_handle().downcast::() else { + return; + }; + let active_call = ActiveCall::global(cx); + active_call + .update(cx, |active_call, cx| { + active_call.join_channel(channel_id, handle, cx) + }) + .detach_and_log_err(cx) + } // fn join_channel_chat(&mut self, action: &JoinChannelChat, cx: &mut ViewContext) { // let channel_id = action.channel_id; @@ -2982,9 +2979,7 @@ impl CollabPanel { is_selected: bool, cx: &mut ViewContext, ) -> impl IntoElement { - ListItem::new("contact-placeholder") - .child(Label::new("Add a Contact")) - .on_click(cx.listener(|this, _, cx| todo!())) + ListItem::new("contact-placeholder").child(Label::new("Add a Contact")) // enum AddContacts {} // MouseEventHandler::new::(0, cx, |state, _| { // let style = theme.list_empty_state.style_for(is_selected, state); @@ -3023,6 +3018,15 @@ impl CollabPanel { ) -> impl IntoElement { let channel_id = channel.id; + let is_active = maybe!({ + let call_channel = ActiveCall::global(cx) + .read(cx) + .room()? + .read(cx) + .channel_id()?; + Some(call_channel == channel_id) + }) + .unwrap_or(false); let is_public = self .channel_store .read(cx) @@ -3034,16 +3038,6 @@ impl CollabPanel { .then(|| !self.collapsed_channels.binary_search(&channel.id).is_ok()) .unwrap_or(false); - let is_active = maybe!({ - let call_channel = ActiveCall::global(cx) - .read(cx) - .room()? - .read(cx) - .channel_id()?; - Some(call_channel == channel_id) - }) - .unwrap_or(false); - let has_messages_notification = channel.unseen_message_id.is_some(); let has_notes_notification = channel.unseen_note_version.is_some(); @@ -3052,6 +3046,7 @@ impl CollabPanel { let face_pile = if !participants.is_empty() { let extra_count = participants.len().saturating_sub(FACEPILE_LIMIT); + let user = &participants[0]; let result = FacePile { faces: participants @@ -3059,6 +3054,7 @@ impl CollabPanel { .filter_map(|user| Some(Avatar::data(user.avatar.clone()?).into_any_element())) .take(FACEPILE_LIMIT) .chain(if extra_count > 0 { + // todo!() @nate - this label looks wrong. Some(Label::new(format!("+{}", extra_count)).into_any_element()) } else { None @@ -3081,7 +3077,7 @@ impl CollabPanel { .w_full() .justify_between() .child( - div() + h_stack() .id(channel_id as usize) .child(Label::new(channel.name.clone())) .children(face_pile.map(|face_pile| face_pile.render(cx))) @@ -3128,7 +3124,15 @@ impl CollabPanel { } else { Toggle::NotToggleable }) - .on_click(cx.listener(|this, _, cx| todo!())) + .on_click(cx.listener(move |this, _, cx| { + if this.drag_target_channel == ChannelDragTarget::None { + if is_active { + this.open_channel_notes(&OpenChannelNotes { channel_id }, cx) + } else { + this.join_channel(channel_id, cx) + } + } + })) .on_secondary_mouse_down(cx.listener(|this, _, cx| { todo!() // open context menu })),