single click channel (#7596)
- Open channel notes and chat on channel click - WIP - Fix compile error - Don't join live kit until requested - Track in_call state separately from in_room Release Notes: - Improved channels: you can now be in a channel without joining the audio call automatically **or** - N/A --------- Co-authored-by: Nathan Sobo <nathan@zed.dev>
This commit is contained in:
parent
2b39a9512a
commit
efe23ebfcd
26 changed files with 659 additions and 489 deletions
|
@ -105,6 +105,7 @@ struct Session {
|
|||
zed_environment: Arc<str>,
|
||||
user_id: UserId,
|
||||
connection_id: ConnectionId,
|
||||
zed_version: SemanticVersion,
|
||||
db: Arc<tokio::sync::Mutex<DbHandle>>,
|
||||
peer: Arc<Peer>,
|
||||
connection_pool: Arc<parking_lot::Mutex<ConnectionPool>>,
|
||||
|
@ -131,6 +132,19 @@ impl Session {
|
|||
_not_send: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
fn endpoint_removed_in(&self, endpoint: &str, version: SemanticVersion) -> anyhow::Result<()> {
|
||||
if self.zed_version > version {
|
||||
Err(anyhow!(
|
||||
"{} was removed in {} (you're on {})",
|
||||
endpoint,
|
||||
version,
|
||||
self.zed_version
|
||||
))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Session {
|
||||
|
@ -274,8 +288,11 @@ impl Server {
|
|||
.add_request_handler(get_channel_members)
|
||||
.add_request_handler(respond_to_channel_invite)
|
||||
.add_request_handler(join_channel)
|
||||
.add_request_handler(join_channel2)
|
||||
.add_request_handler(join_channel_chat)
|
||||
.add_message_handler(leave_channel_chat)
|
||||
.add_request_handler(join_channel_call)
|
||||
.add_request_handler(leave_channel_call)
|
||||
.add_request_handler(send_channel_message)
|
||||
.add_request_handler(remove_channel_message)
|
||||
.add_request_handler(get_channel_messages)
|
||||
|
@ -559,6 +576,7 @@ impl Server {
|
|||
connection: Connection,
|
||||
address: String,
|
||||
user: User,
|
||||
zed_version: SemanticVersion,
|
||||
impersonator: Option<User>,
|
||||
mut send_connection_id: Option<oneshot::Sender<ConnectionId>>,
|
||||
executor: Executor,
|
||||
|
@ -616,6 +634,7 @@ impl Server {
|
|||
let session = Session {
|
||||
user_id,
|
||||
connection_id,
|
||||
zed_version,
|
||||
db: Arc::new(tokio::sync::Mutex::new(DbHandle(this.app_state.db.clone()))),
|
||||
zed_environment: this.app_state.config.zed_environment.clone(),
|
||||
peer: this.peer.clone(),
|
||||
|
@ -866,7 +885,7 @@ pub fn routes(server: Arc<Server>) -> Router<Body> {
|
|||
|
||||
pub async fn handle_websocket_request(
|
||||
TypedHeader(ProtocolVersion(protocol_version)): TypedHeader<ProtocolVersion>,
|
||||
_app_version_header: Option<TypedHeader<AppVersionHeader>>,
|
||||
app_version_header: Option<TypedHeader<AppVersionHeader>>,
|
||||
ConnectInfo(socket_address): ConnectInfo<SocketAddr>,
|
||||
Extension(server): Extension<Arc<Server>>,
|
||||
Extension(user): Extension<User>,
|
||||
|
@ -881,6 +900,12 @@ pub async fn handle_websocket_request(
|
|||
.into_response();
|
||||
}
|
||||
|
||||
// zed 0.122.x was the first version that sent an app header, so once that hits stable
|
||||
// we can return UPGRADE_REQUIRED instead of unwrap_or_default();
|
||||
let app_version = app_version_header
|
||||
.map(|header| header.0 .0)
|
||||
.unwrap_or_default();
|
||||
|
||||
let socket_address = socket_address.to_string();
|
||||
ws.on_upgrade(move |socket| {
|
||||
use util::ResultExt;
|
||||
|
@ -895,6 +920,7 @@ pub async fn handle_websocket_request(
|
|||
connection,
|
||||
socket_address,
|
||||
user,
|
||||
app_version,
|
||||
impersonator.0,
|
||||
None,
|
||||
Executor::Production,
|
||||
|
@ -1037,7 +1063,7 @@ async fn join_room(
|
|||
let channel_id = session.db().await.channel_id_for_room(room_id).await?;
|
||||
|
||||
if let Some(channel_id) = channel_id {
|
||||
return join_channel_internal(channel_id, Box::new(response), session).await;
|
||||
return join_channel_internal(channel_id, true, Box::new(response), session).await;
|
||||
}
|
||||
|
||||
let joined_room = {
|
||||
|
@ -2700,14 +2726,67 @@ async fn respond_to_channel_invite(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Join the channels' room
|
||||
/// Join the channels' call
|
||||
async fn join_channel(
|
||||
request: proto::JoinChannel,
|
||||
response: Response<proto::JoinChannel>,
|
||||
session: Session,
|
||||
) -> Result<()> {
|
||||
session.endpoint_removed_in("join_channel", "0.123.0".parse().unwrap())?;
|
||||
|
||||
let channel_id = ChannelId::from_proto(request.channel_id);
|
||||
join_channel_internal(channel_id, Box::new(response), session).await
|
||||
join_channel_internal(channel_id, true, Box::new(response), session).await
|
||||
}
|
||||
|
||||
async fn join_channel2(
|
||||
request: proto::JoinChannel2,
|
||||
response: Response<proto::JoinChannel2>,
|
||||
session: Session,
|
||||
) -> Result<()> {
|
||||
let channel_id = ChannelId::from_proto(request.channel_id);
|
||||
join_channel_internal(channel_id, false, Box::new(response), session).await
|
||||
}
|
||||
|
||||
async fn join_channel_call(
|
||||
request: proto::JoinChannelCall,
|
||||
response: Response<proto::JoinChannelCall>,
|
||||
session: Session,
|
||||
) -> Result<()> {
|
||||
let channel_id = ChannelId::from_proto(request.channel_id);
|
||||
let db = session.db().await;
|
||||
let (joined_room, role) = db
|
||||
.set_in_channel_call(channel_id, session.user_id, true)
|
||||
.await?;
|
||||
|
||||
let Some(connection_info) = session.live_kit_client.as_ref().and_then(|live_kit| {
|
||||
live_kit_info_for_user(live_kit, &session.user_id, role, &joined_room.live_kit_room)
|
||||
}) else {
|
||||
Err(anyhow!("no live kit token info"))?
|
||||
};
|
||||
|
||||
room_updated(&joined_room, &session.peer);
|
||||
response.send(proto::JoinChannelCallResponse {
|
||||
live_kit_connection_info: Some(connection_info),
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn leave_channel_call(
|
||||
request: proto::LeaveChannelCall,
|
||||
response: Response<proto::LeaveChannelCall>,
|
||||
session: Session,
|
||||
) -> Result<()> {
|
||||
let channel_id = ChannelId::from_proto(request.channel_id);
|
||||
let db = session.db().await;
|
||||
let (joined_room, _) = db
|
||||
.set_in_channel_call(channel_id, session.user_id, false)
|
||||
.await?;
|
||||
|
||||
room_updated(&joined_room, &session.peer);
|
||||
response.send(proto::Ack {})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
trait JoinChannelInternalResponse {
|
||||
|
@ -2723,9 +2802,15 @@ impl JoinChannelInternalResponse for Response<proto::JoinRoom> {
|
|||
Response::<proto::JoinRoom>::send(self, result)
|
||||
}
|
||||
}
|
||||
impl JoinChannelInternalResponse for Response<proto::JoinChannel2> {
|
||||
fn send(self, result: proto::JoinRoomResponse) -> Result<()> {
|
||||
Response::<proto::JoinChannel2>::send(self, result)
|
||||
}
|
||||
}
|
||||
|
||||
async fn join_channel_internal(
|
||||
channel_id: ChannelId,
|
||||
autojoin: bool,
|
||||
response: Box<impl JoinChannelInternalResponse>,
|
||||
session: Session,
|
||||
) -> Result<()> {
|
||||
|
@ -2737,39 +2822,22 @@ async fn join_channel_internal(
|
|||
.join_channel(
|
||||
channel_id,
|
||||
session.user_id,
|
||||
autojoin,
|
||||
session.connection_id,
|
||||
session.zed_environment.as_ref(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let live_kit_connection_info = session.live_kit_client.as_ref().and_then(|live_kit| {
|
||||
let (can_publish, token) = if role == ChannelRole::Guest {
|
||||
(
|
||||
false,
|
||||
live_kit
|
||||
.guest_token(
|
||||
&joined_room.room.live_kit_room,
|
||||
&session.user_id.to_string(),
|
||||
)
|
||||
.trace_err()?,
|
||||
)
|
||||
} else {
|
||||
(
|
||||
true,
|
||||
live_kit
|
||||
.room_token(
|
||||
&joined_room.room.live_kit_room,
|
||||
&session.user_id.to_string(),
|
||||
)
|
||||
.trace_err()?,
|
||||
)
|
||||
};
|
||||
|
||||
Some(LiveKitConnectionInfo {
|
||||
server_url: live_kit.url().into(),
|
||||
token,
|
||||
can_publish,
|
||||
})
|
||||
if !autojoin {
|
||||
return None;
|
||||
}
|
||||
live_kit_info_for_user(
|
||||
live_kit,
|
||||
&session.user_id,
|
||||
role,
|
||||
&joined_room.room.live_kit_room,
|
||||
)
|
||||
});
|
||||
|
||||
response.send(proto::JoinRoomResponse {
|
||||
|
@ -2805,6 +2873,35 @@ async fn join_channel_internal(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn live_kit_info_for_user(
|
||||
live_kit: &Arc<dyn live_kit_server::api::Client>,
|
||||
user_id: &UserId,
|
||||
role: ChannelRole,
|
||||
live_kit_room: &String,
|
||||
) -> Option<LiveKitConnectionInfo> {
|
||||
let (can_publish, token) = if role == ChannelRole::Guest {
|
||||
(
|
||||
false,
|
||||
live_kit
|
||||
.guest_token(live_kit_room, &user_id.to_string())
|
||||
.trace_err()?,
|
||||
)
|
||||
} else {
|
||||
(
|
||||
true,
|
||||
live_kit
|
||||
.room_token(live_kit_room, &user_id.to_string())
|
||||
.trace_err()?,
|
||||
)
|
||||
};
|
||||
|
||||
Some(LiveKitConnectionInfo {
|
||||
server_url: live_kit.url().into(),
|
||||
token,
|
||||
can_publish,
|
||||
})
|
||||
}
|
||||
|
||||
/// Start editing the channel notes
|
||||
async fn join_channel_buffer(
|
||||
request: proto::JoinChannelBuffer,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue