mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-24 17:28:40 +00:00
join channels (#3082)
Release Notes: - Clicking on a channel in the sidebar will now join the channel and open the notes - If you join a channel that already shared projects, you will join the projects automatically and follow the host. - Clicking on the current channel in the sidebar will re-open the notes. - Chat can now be accessed from the right click menu of channels. - (probably not worth mentioning) Various improvements to hover states and tooltips in the collab ui; and if you click on a channel while in another call, confirm before switching.
This commit is contained in:
commit
55d2b9b3c9
3 changed files with 306 additions and 99 deletions
|
@ -291,10 +291,10 @@ impl ActiveCall {
|
|||
&mut self,
|
||||
channel_id: u64,
|
||||
cx: &mut ModelContext<Self>,
|
||||
) -> Task<Result<()>> {
|
||||
) -> Task<Result<ModelHandle<Room>>> {
|
||||
if let Some(room) = self.room().cloned() {
|
||||
if room.read(cx).channel_id() == Some(channel_id) {
|
||||
return Task::ready(Ok(()));
|
||||
return Task::ready(Ok(room));
|
||||
} else {
|
||||
room.update(cx, |room, cx| room.clear_state(cx));
|
||||
}
|
||||
|
@ -309,7 +309,7 @@ impl ActiveCall {
|
|||
this.update(&mut cx, |this, cx| {
|
||||
this.report_call_event("join channel", cx)
|
||||
});
|
||||
Ok(())
|
||||
Ok(room)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -594,6 +594,33 @@ impl Room {
|
|||
.map_or(&[], |v| v.as_slice())
|
||||
}
|
||||
|
||||
/// projects_to_join returns a list of shared projects sorted such
|
||||
/// that the most 'active' projects appear last.
|
||||
pub fn projects_to_join(&self) -> Vec<(u64, u64)> {
|
||||
let mut projects = HashMap::default();
|
||||
let mut hosts = HashMap::default();
|
||||
for participant in self.remote_participants.values() {
|
||||
match participant.location {
|
||||
ParticipantLocation::SharedProject { project_id } => {
|
||||
*projects.entry(project_id).or_insert(0) += 1;
|
||||
}
|
||||
ParticipantLocation::External | ParticipantLocation::UnsharedProject => {}
|
||||
}
|
||||
for project in &participant.projects {
|
||||
*projects.entry(project.id).or_insert(0) += 1;
|
||||
hosts.insert(project.id, participant.user.id);
|
||||
}
|
||||
}
|
||||
|
||||
let mut pairs: Vec<(u64, usize)> = projects.into_iter().collect();
|
||||
pairs.sort_by_key(|(_, count)| 0 - *count as i32);
|
||||
|
||||
pairs
|
||||
.into_iter()
|
||||
.map(|(project_id, _)| (project_id, hosts[&project_id]))
|
||||
.collect()
|
||||
}
|
||||
|
||||
async fn handle_room_updated(
|
||||
this: ModelHandle<Self>,
|
||||
envelope: TypedEnvelope<proto::RoomUpdated>,
|
||||
|
|
|
@ -95,6 +95,11 @@ pub struct JoinChannelCall {
|
|||
pub channel_id: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub struct JoinChannelChat {
|
||||
pub channel_id: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
struct StartMoveChannelFor {
|
||||
channel_id: ChannelId,
|
||||
|
@ -151,6 +156,7 @@ impl_actions!(
|
|||
ToggleCollapse,
|
||||
OpenChannelNotes,
|
||||
JoinChannelCall,
|
||||
JoinChannelChat,
|
||||
LinkChannel,
|
||||
StartMoveChannelFor,
|
||||
StartLinkChannelFor,
|
||||
|
@ -198,6 +204,7 @@ pub fn init(cx: &mut AppContext) {
|
|||
cx.add_action(CollabPanel::collapse_selected_channel);
|
||||
cx.add_action(CollabPanel::expand_selected_channel);
|
||||
cx.add_action(CollabPanel::open_channel_notes);
|
||||
cx.add_action(CollabPanel::join_channel_chat);
|
||||
|
||||
cx.add_action(
|
||||
|panel: &mut CollabPanel, action: &ToggleSelectedIx, cx: &mut ViewContext<CollabPanel>| {
|
||||
|
@ -471,6 +478,12 @@ impl CollabPanel {
|
|||
.iter()
|
||||
.position(|entry| !matches!(entry, ListEntry::Header(_)));
|
||||
}
|
||||
} else if let editor::Event::Blurred = event {
|
||||
let query = this.filter_editor.read(cx).text(cx);
|
||||
if query.is_empty() {
|
||||
this.selection.take();
|
||||
this.update_entries(true, cx);
|
||||
}
|
||||
}
|
||||
})
|
||||
.detach();
|
||||
|
@ -555,7 +568,7 @@ impl CollabPanel {
|
|||
&*channel,
|
||||
*depth,
|
||||
path.to_owned(),
|
||||
&theme.collab_panel,
|
||||
&theme,
|
||||
is_selected,
|
||||
ix,
|
||||
cx,
|
||||
|
@ -608,7 +621,7 @@ impl CollabPanel {
|
|||
contact,
|
||||
*calling,
|
||||
&this.project,
|
||||
&theme.collab_panel,
|
||||
&theme,
|
||||
is_selected,
|
||||
cx,
|
||||
),
|
||||
|
@ -768,9 +781,16 @@ impl CollabPanel {
|
|||
|
||||
let prev_selected_entry = self.selection.and_then(|ix| self.entries.get(ix).cloned());
|
||||
let old_entries = mem::take(&mut self.entries);
|
||||
let mut scroll_to_top = false;
|
||||
|
||||
if let Some(room) = ActiveCall::global(cx).read(cx).room() {
|
||||
self.entries.push(ListEntry::Header(Section::ActiveCall));
|
||||
if !old_entries
|
||||
.iter()
|
||||
.any(|entry| matches!(entry, ListEntry::Header(Section::ActiveCall)))
|
||||
{
|
||||
scroll_to_top = true;
|
||||
}
|
||||
|
||||
if !self.collapsed_sections.contains(&Section::ActiveCall) {
|
||||
let room = room.read(cx);
|
||||
|
@ -1138,44 +1158,49 @@ impl CollabPanel {
|
|||
}
|
||||
|
||||
let old_scroll_top = self.list_state.logical_scroll_top();
|
||||
|
||||
self.list_state.reset(self.entries.len());
|
||||
|
||||
// Attempt to maintain the same scroll position.
|
||||
if let Some(old_top_entry) = old_entries.get(old_scroll_top.item_ix) {
|
||||
let new_scroll_top = self
|
||||
.entries
|
||||
.iter()
|
||||
.position(|entry| entry == old_top_entry)
|
||||
.map(|item_ix| ListOffset {
|
||||
item_ix,
|
||||
offset_in_item: old_scroll_top.offset_in_item,
|
||||
})
|
||||
.or_else(|| {
|
||||
let entry_after_old_top = old_entries.get(old_scroll_top.item_ix + 1)?;
|
||||
let item_ix = self
|
||||
.entries
|
||||
.iter()
|
||||
.position(|entry| entry == entry_after_old_top)?;
|
||||
Some(ListOffset {
|
||||
if scroll_to_top {
|
||||
self.list_state.scroll_to(ListOffset::default());
|
||||
} else {
|
||||
// Attempt to maintain the same scroll position.
|
||||
if let Some(old_top_entry) = old_entries.get(old_scroll_top.item_ix) {
|
||||
let new_scroll_top = self
|
||||
.entries
|
||||
.iter()
|
||||
.position(|entry| entry == old_top_entry)
|
||||
.map(|item_ix| ListOffset {
|
||||
item_ix,
|
||||
offset_in_item: 0.,
|
||||
offset_in_item: old_scroll_top.offset_in_item,
|
||||
})
|
||||
})
|
||||
.or_else(|| {
|
||||
let entry_before_old_top =
|
||||
old_entries.get(old_scroll_top.item_ix.saturating_sub(1))?;
|
||||
let item_ix = self
|
||||
.entries
|
||||
.iter()
|
||||
.position(|entry| entry == entry_before_old_top)?;
|
||||
Some(ListOffset {
|
||||
item_ix,
|
||||
offset_in_item: 0.,
|
||||
.or_else(|| {
|
||||
let entry_after_old_top = old_entries.get(old_scroll_top.item_ix + 1)?;
|
||||
let item_ix = self
|
||||
.entries
|
||||
.iter()
|
||||
.position(|entry| entry == entry_after_old_top)?;
|
||||
Some(ListOffset {
|
||||
item_ix,
|
||||
offset_in_item: 0.,
|
||||
})
|
||||
})
|
||||
});
|
||||
.or_else(|| {
|
||||
let entry_before_old_top =
|
||||
old_entries.get(old_scroll_top.item_ix.saturating_sub(1))?;
|
||||
let item_ix = self
|
||||
.entries
|
||||
.iter()
|
||||
.position(|entry| entry == entry_before_old_top)?;
|
||||
Some(ListOffset {
|
||||
item_ix,
|
||||
offset_in_item: 0.,
|
||||
})
|
||||
});
|
||||
|
||||
self.list_state
|
||||
.scroll_to(new_scroll_top.unwrap_or(old_scroll_top));
|
||||
self.list_state
|
||||
.scroll_to(new_scroll_top.unwrap_or(old_scroll_top));
|
||||
}
|
||||
}
|
||||
|
||||
cx.notify();
|
||||
|
@ -1633,16 +1658,20 @@ impl CollabPanel {
|
|||
contact: &Contact,
|
||||
calling: bool,
|
||||
project: &ModelHandle<Project>,
|
||||
theme: &theme::CollabPanel,
|
||||
theme: &theme::Theme,
|
||||
is_selected: bool,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> AnyElement<Self> {
|
||||
enum ContactTooltip {}
|
||||
|
||||
let collab_theme = &theme.collab_panel;
|
||||
let online = contact.online;
|
||||
let busy = contact.busy || calling;
|
||||
let user_id = contact.user.id;
|
||||
let github_login = contact.user.github_login.clone();
|
||||
let initial_project = project.clone();
|
||||
let mut event_handler =
|
||||
|
||||
let event_handler =
|
||||
MouseEventHandler::new::<Contact, _>(contact.user.id as usize, cx, |state, cx| {
|
||||
Flex::row()
|
||||
.with_children(contact.user.avatar.clone().map(|avatar| {
|
||||
|
@ -1652,9 +1681,9 @@ impl CollabPanel {
|
|||
.collapsed()
|
||||
.contained()
|
||||
.with_style(if busy {
|
||||
theme.contact_status_busy
|
||||
collab_theme.contact_status_busy
|
||||
} else {
|
||||
theme.contact_status_free
|
||||
collab_theme.contact_status_free
|
||||
})
|
||||
.aligned(),
|
||||
)
|
||||
|
@ -1664,7 +1693,7 @@ impl CollabPanel {
|
|||
Stack::new()
|
||||
.with_child(
|
||||
Image::from_data(avatar)
|
||||
.with_style(theme.contact_avatar)
|
||||
.with_style(collab_theme.contact_avatar)
|
||||
.aligned()
|
||||
.left(),
|
||||
)
|
||||
|
@ -1673,58 +1702,94 @@ impl CollabPanel {
|
|||
.with_child(
|
||||
Label::new(
|
||||
contact.user.github_login.clone(),
|
||||
theme.contact_username.text.clone(),
|
||||
collab_theme.contact_username.text.clone(),
|
||||
)
|
||||
.contained()
|
||||
.with_style(theme.contact_username.container)
|
||||
.with_style(collab_theme.contact_username.container)
|
||||
.aligned()
|
||||
.left()
|
||||
.flex(1., true),
|
||||
)
|
||||
.with_child(
|
||||
MouseEventHandler::new::<Cancel, _>(
|
||||
contact.user.id as usize,
|
||||
cx,
|
||||
|mouse_state, _| {
|
||||
let button_style = theme.contact_button.style_for(mouse_state);
|
||||
render_icon_button(button_style, "icons/x.svg")
|
||||
.aligned()
|
||||
.flex_float()
|
||||
},
|
||||
.with_children(if state.hovered() {
|
||||
Some(
|
||||
MouseEventHandler::new::<Cancel, _>(
|
||||
contact.user.id as usize,
|
||||
cx,
|
||||
|mouse_state, _| {
|
||||
let button_style =
|
||||
collab_theme.contact_button.style_for(mouse_state);
|
||||
render_icon_button(button_style, "icons/x.svg")
|
||||
.aligned()
|
||||
.flex_float()
|
||||
},
|
||||
)
|
||||
.with_padding(Padding::uniform(2.))
|
||||
.with_cursor_style(CursorStyle::PointingHand)
|
||||
.on_click(MouseButton::Left, move |_, this, cx| {
|
||||
this.remove_contact(user_id, &github_login, cx);
|
||||
})
|
||||
.flex_float(),
|
||||
)
|
||||
.with_padding(Padding::uniform(2.))
|
||||
.with_cursor_style(CursorStyle::PointingHand)
|
||||
.on_click(MouseButton::Left, move |_, this, cx| {
|
||||
this.remove_contact(user_id, &github_login, cx);
|
||||
})
|
||||
.flex_float(),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
})
|
||||
.with_children(if calling {
|
||||
Some(
|
||||
Label::new("Calling", theme.calling_indicator.text.clone())
|
||||
Label::new("Calling", collab_theme.calling_indicator.text.clone())
|
||||
.contained()
|
||||
.with_style(theme.calling_indicator.container)
|
||||
.with_style(collab_theme.calling_indicator.container)
|
||||
.aligned(),
|
||||
)
|
||||
} else {
|
||||
None
|
||||
})
|
||||
.constrained()
|
||||
.with_height(theme.row_height)
|
||||
.with_height(collab_theme.row_height)
|
||||
.contained()
|
||||
.with_style(*theme.contact_row.in_state(is_selected).style_for(state))
|
||||
})
|
||||
.on_click(MouseButton::Left, move |_, this, cx| {
|
||||
if online && !busy {
|
||||
this.call(user_id, Some(initial_project.clone()), cx);
|
||||
}
|
||||
.with_style(
|
||||
*collab_theme
|
||||
.contact_row
|
||||
.in_state(is_selected)
|
||||
.style_for(state),
|
||||
)
|
||||
});
|
||||
|
||||
if online {
|
||||
event_handler = event_handler.with_cursor_style(CursorStyle::PointingHand);
|
||||
}
|
||||
if online && !busy {
|
||||
let room = ActiveCall::global(cx).read(cx).room();
|
||||
let label = if room.is_some() {
|
||||
format!("Invite {} to join call", contact.user.github_login)
|
||||
} else {
|
||||
format!("Call {}", contact.user.github_login)
|
||||
};
|
||||
|
||||
event_handler.into_any()
|
||||
event_handler
|
||||
.on_click(MouseButton::Left, move |_, this, cx| {
|
||||
this.call(user_id, Some(initial_project.clone()), cx);
|
||||
})
|
||||
.with_cursor_style(CursorStyle::PointingHand)
|
||||
.with_tooltip::<ContactTooltip>(
|
||||
contact.user.id as usize,
|
||||
label,
|
||||
None,
|
||||
theme.tooltip.clone(),
|
||||
cx,
|
||||
)
|
||||
.into_any()
|
||||
} else {
|
||||
event_handler
|
||||
.with_tooltip::<ContactTooltip>(
|
||||
contact.user.id as usize,
|
||||
format!(
|
||||
"{} is {}",
|
||||
contact.user.github_login,
|
||||
if busy { "on a call" } else { "offline" }
|
||||
),
|
||||
None,
|
||||
theme.tooltip.clone(),
|
||||
cx,
|
||||
)
|
||||
.into_any()
|
||||
}
|
||||
}
|
||||
|
||||
fn render_contact_placeholder(
|
||||
|
@ -1827,12 +1892,13 @@ impl CollabPanel {
|
|||
channel: &Channel,
|
||||
depth: usize,
|
||||
path: ChannelPath,
|
||||
theme: &theme::CollabPanel,
|
||||
theme: &theme::Theme,
|
||||
is_selected: bool,
|
||||
ix: usize,
|
||||
cx: &mut ViewContext<Self>,
|
||||
) -> AnyElement<Self> {
|
||||
let channel_id = channel.id;
|
||||
let collab_theme = &theme.collab_panel;
|
||||
let has_children = self.channel_store.read(cx).has_children(channel_id);
|
||||
let other_selected =
|
||||
self.selected_channel().map(|channel| channel.0.id) == Some(channel.id);
|
||||
|
@ -1851,6 +1917,8 @@ impl CollabPanel {
|
|||
const FACEPILE_LIMIT: usize = 3;
|
||||
|
||||
enum ChannelCall {}
|
||||
enum IconTooltip {}
|
||||
enum ChannelTooltip {}
|
||||
|
||||
let mut is_dragged_over = false;
|
||||
if cx
|
||||
|
@ -1886,18 +1954,29 @@ impl CollabPanel {
|
|||
Flex::<Self>::row()
|
||||
.with_child(
|
||||
Svg::new("icons/hash.svg")
|
||||
.with_color(theme.channel_hash.color)
|
||||
.with_color(collab_theme.channel_hash.color)
|
||||
.constrained()
|
||||
.with_width(theme.channel_hash.width)
|
||||
.with_width(collab_theme.channel_hash.width)
|
||||
.aligned()
|
||||
.left(),
|
||||
)
|
||||
.with_child(
|
||||
Label::new(channel.name.clone(), theme.channel_name.text.clone())
|
||||
Label::new(channel.name.clone(), collab_theme.channel_name.text.clone())
|
||||
.contained()
|
||||
.with_style(theme.channel_name.container)
|
||||
.with_style(collab_theme.channel_name.container)
|
||||
.aligned()
|
||||
.left()
|
||||
.with_tooltip::<ChannelTooltip>(
|
||||
channel_id as usize,
|
||||
if is_active {
|
||||
"Open channel notes"
|
||||
} else {
|
||||
"Join channel"
|
||||
},
|
||||
None,
|
||||
theme.tooltip.clone(),
|
||||
cx,
|
||||
)
|
||||
.flex(1., true),
|
||||
)
|
||||
.with_child(
|
||||
|
@ -1907,14 +1986,14 @@ impl CollabPanel {
|
|||
if !participants.is_empty() {
|
||||
let extra_count = participants.len().saturating_sub(FACEPILE_LIMIT);
|
||||
|
||||
FacePile::new(theme.face_overlap)
|
||||
FacePile::new(collab_theme.face_overlap)
|
||||
.with_children(
|
||||
participants
|
||||
.iter()
|
||||
.filter_map(|user| {
|
||||
Some(
|
||||
Image::from_data(user.avatar.clone()?)
|
||||
.with_style(theme.channel_avatar),
|
||||
.with_style(collab_theme.channel_avatar),
|
||||
)
|
||||
})
|
||||
.take(FACEPILE_LIMIT),
|
||||
|
@ -1922,24 +2001,48 @@ impl CollabPanel {
|
|||
.with_children((extra_count > 0).then(|| {
|
||||
Label::new(
|
||||
format!("+{}", extra_count),
|
||||
theme.extra_participant_label.text.clone(),
|
||||
collab_theme.extra_participant_label.text.clone(),
|
||||
)
|
||||
.contained()
|
||||
.with_style(theme.extra_participant_label.container)
|
||||
.with_style(collab_theme.extra_participant_label.container)
|
||||
}))
|
||||
.with_tooltip::<IconTooltip>(
|
||||
channel_id as usize,
|
||||
if is_active {
|
||||
"Open Channel Notes"
|
||||
} else {
|
||||
"Join channel"
|
||||
},
|
||||
None,
|
||||
theme.tooltip.clone(),
|
||||
cx,
|
||||
)
|
||||
.into_any()
|
||||
} else if row_hovered {
|
||||
Svg::new("icons/speaker-loud.svg")
|
||||
.with_color(theme.channel_hash.color)
|
||||
Svg::new("icons/file.svg")
|
||||
.with_color(collab_theme.channel_hash.color)
|
||||
.constrained()
|
||||
.with_width(theme.channel_hash.width)
|
||||
.with_width(collab_theme.channel_hash.width)
|
||||
.with_tooltip::<IconTooltip>(
|
||||
channel_id as usize,
|
||||
"Open channel notes",
|
||||
None,
|
||||
theme.tooltip.clone(),
|
||||
cx,
|
||||
)
|
||||
.into_any()
|
||||
} else {
|
||||
Empty::new().into_any()
|
||||
}
|
||||
})
|
||||
.on_click(MouseButton::Left, move |_, this, cx| {
|
||||
this.join_channel_call(channel_id, cx);
|
||||
let participants =
|
||||
this.channel_store.read(cx).channel_participants(channel_id);
|
||||
if is_active || participants.is_empty() {
|
||||
this.open_channel_notes(&OpenChannelNotes { channel_id }, cx);
|
||||
} else {
|
||||
this.join_channel(channel_id, cx);
|
||||
};
|
||||
}),
|
||||
)
|
||||
.align_children_center()
|
||||
|
@ -1951,24 +2054,28 @@ impl CollabPanel {
|
|||
}),
|
||||
)
|
||||
.with_id(ix)
|
||||
.with_style(theme.disclosure.clone())
|
||||
.with_style(collab_theme.disclosure.clone())
|
||||
.element()
|
||||
.constrained()
|
||||
.with_height(theme.row_height)
|
||||
.with_height(collab_theme.row_height)
|
||||
.contained()
|
||||
.with_style(select_state(
|
||||
theme
|
||||
collab_theme
|
||||
.channel_row
|
||||
.in_state(is_selected || is_active || is_dragged_over),
|
||||
))
|
||||
.with_padding_left(
|
||||
theme.channel_row.default_style().padding.left
|
||||
+ theme.channel_indent * depth as f32,
|
||||
collab_theme.channel_row.default_style().padding.left
|
||||
+ collab_theme.channel_indent * depth as f32,
|
||||
)
|
||||
})
|
||||
.on_click(MouseButton::Left, move |_, this, cx| {
|
||||
if this.drag_target_channel.take().is_none() {
|
||||
this.join_channel_chat(channel_id, cx);
|
||||
if is_active {
|
||||
this.open_channel_notes(&OpenChannelNotes { channel_id }, cx)
|
||||
} else {
|
||||
this.join_channel(channel_id, cx)
|
||||
}
|
||||
}
|
||||
})
|
||||
.on_click(MouseButton::Right, {
|
||||
|
@ -2392,6 +2499,13 @@ impl CollabPanel {
|
|||
},
|
||||
));
|
||||
|
||||
items.push(ContextMenuItem::action(
|
||||
"Open Chat",
|
||||
JoinChannelChat {
|
||||
channel_id: path.channel_id(),
|
||||
},
|
||||
));
|
||||
|
||||
if self.channel_store.read(cx).is_user_admin(path.channel_id()) {
|
||||
let parent_id = path.parent_id();
|
||||
|
||||
|
@ -2588,7 +2702,28 @@ impl CollabPanel {
|
|||
}
|
||||
}
|
||||
ListEntry::Channel { channel, .. } => {
|
||||
self.join_channel_chat(channel.id, cx);
|
||||
let is_active = iife!({
|
||||
let call_channel = ActiveCall::global(cx)
|
||||
.read(cx)
|
||||
.room()?
|
||||
.read(cx)
|
||||
.channel_id()?;
|
||||
|
||||
dbg!(call_channel, channel.id);
|
||||
Some(call_channel == channel.id)
|
||||
})
|
||||
.unwrap_or(false);
|
||||
dbg!(is_active);
|
||||
if is_active {
|
||||
self.open_channel_notes(
|
||||
&OpenChannelNotes {
|
||||
channel_id: channel.id,
|
||||
},
|
||||
cx,
|
||||
)
|
||||
} else {
|
||||
self.join_channel(channel.id, cx)
|
||||
}
|
||||
}
|
||||
ListEntry::ContactPlaceholder => self.toggle_contact_finder(cx),
|
||||
_ => {}
|
||||
|
@ -2991,13 +3126,58 @@ impl CollabPanel {
|
|||
.detach_and_log_err(cx);
|
||||
}
|
||||
|
||||
fn join_channel_call(&self, channel: u64, cx: &mut ViewContext<Self>) {
|
||||
ActiveCall::global(cx)
|
||||
.update(cx, |call, cx| call.join_channel(channel, cx))
|
||||
.detach_and_log_err(cx);
|
||||
fn join_channel(&self, channel_id: u64, cx: &mut ViewContext<Self>) {
|
||||
let workspace = self.workspace.clone();
|
||||
let window = cx.window();
|
||||
let active_call = ActiveCall::global(cx);
|
||||
cx.spawn(|_, mut cx| async move {
|
||||
if active_call.read_with(&mut cx, |active_call, _| active_call.room().is_some()) {
|
||||
let answer = window.prompt(
|
||||
PromptLevel::Warning,
|
||||
"Do you want to leave the current call?",
|
||||
&["Yes, Join Channel", "Cancel"],
|
||||
&mut cx,
|
||||
);
|
||||
|
||||
if let Some(mut answer) = answer {
|
||||
if answer.next().await == Some(1) {
|
||||
return anyhow::Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let room = active_call
|
||||
.update(&mut cx, |call, cx| call.join_channel(channel_id, cx))
|
||||
.await?;
|
||||
|
||||
let tasks = room.update(&mut cx, |room, cx| {
|
||||
let Some(workspace) = workspace.upgrade(cx) else {
|
||||
return vec![];
|
||||
};
|
||||
let projects = room.projects_to_join();
|
||||
|
||||
if projects.is_empty() {
|
||||
ChannelView::open(channel_id, workspace, cx).detach();
|
||||
return vec![];
|
||||
}
|
||||
room.projects_to_join()
|
||||
.into_iter()
|
||||
.map(|(project_id, user_id)| {
|
||||
let app_state = workspace.read(cx).app_state().clone();
|
||||
workspace::join_remote_project(project_id, user_id, app_state, cx)
|
||||
})
|
||||
.collect()
|
||||
});
|
||||
for task in tasks {
|
||||
task.await?;
|
||||
}
|
||||
anyhow::Ok(())
|
||||
})
|
||||
.detach_and_log_err(cx);
|
||||
}
|
||||
|
||||
fn join_channel_chat(&mut self, channel_id: u64, cx: &mut ViewContext<Self>) {
|
||||
fn join_channel_chat(&mut self, action: &JoinChannelChat, cx: &mut ViewContext<Self>) {
|
||||
let channel_id = action.channel_id;
|
||||
if let Some(workspace) = self.workspace.upgrade(cx) {
|
||||
cx.app_context().defer(move |cx| {
|
||||
workspace.update(cx, |workspace, cx| {
|
||||
|
|
Loading…
Reference in a new issue