Change channel join behavior

- Clicking on a channel name now joins the channel if you are not in it
- (or opens the notes if you are already there).
- When joining a channel, previously shared projects are opened
  automatically.
- If there are no previously shared projects, the notes are opened.
This commit is contained in:
Conrad Irwin 2023-10-02 23:20:06 -06:00
parent d9813a5bec
commit 18e7305b6d
3 changed files with 74 additions and 10 deletions

View File

@ -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)
})
}

View File

@ -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>,

View File

@ -8,7 +8,7 @@ use crate::{
panel_settings, CollaborationPanelSettings,
};
use anyhow::Result;
use call::ActiveCall;
use call::{participant, ActiveCall};
use channel::{Channel, ChannelData, ChannelEvent, ChannelId, ChannelPath, ChannelStore};
use channel_modal::ChannelModal;
use client::{proto::PeerId, Client, Contact, User, UserStore};
@ -1929,7 +1929,7 @@ impl CollabPanel {
}))
.into_any()
} else if row_hovered {
Svg::new("icons/speaker-loud.svg")
Svg::new("icons/file.svg")
.with_color(theme.channel_hash.color)
.constrained()
.with_width(theme.channel_hash.width)
@ -1939,7 +1939,11 @@ impl CollabPanel {
}
})
.on_click(MouseButton::Left, move |_, this, cx| {
if !is_active {
this.join_channel_call(channel_id, cx);
} else {
this.open_channel_notes(&OpenChannelNotes { channel_id }, cx)
}
}),
)
.align_children_center()
@ -1968,6 +1972,12 @@ impl CollabPanel {
})
.on_click(MouseButton::Left, move |_, this, cx| {
if this.drag_target_channel.take().is_none() {
if is_active {
this.open_channel_notes(&OpenChannelNotes { channel_id }, cx)
} else {
this.join_channel_call(channel_id, cx)
}
this.join_channel_chat(channel_id, cx);
}
})
@ -2991,9 +3001,36 @@ 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))
fn join_channel_call(&self, channel_id: u64, cx: &mut ViewContext<Self>) {
let join = ActiveCall::global(cx).update(cx, |call, cx| call.join_channel(channel_id, cx));
let workspace = self.workspace.clone();
cx.spawn(|_, mut cx| async move {
let room = join.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?;
}
Ok::<(), anyhow::Error>(())
})
.detach_and_log_err(cx);
}