Show cursors for remote participants
This commit is contained in:
parent
26a3f68080
commit
0ca9f286c6
6 changed files with 122 additions and 4 deletions
|
@ -627,6 +627,7 @@ pub struct RemoteSelection {
|
|||
pub peer_id: PeerId,
|
||||
pub line_mode: bool,
|
||||
pub participant_index: Option<ParticipantIndex>,
|
||||
pub user_name: Option<SharedString>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -9246,6 +9247,7 @@ pub trait CollaborationHub {
|
|||
&self,
|
||||
cx: &'a AppContext,
|
||||
) -> &'a HashMap<u64, ParticipantIndex>;
|
||||
fn user_names(&self, cx: &AppContext) -> HashMap<u64, SharedString>;
|
||||
}
|
||||
|
||||
impl CollaborationHub for Model<Project> {
|
||||
|
@ -9259,6 +9261,14 @@ impl CollaborationHub for Model<Project> {
|
|||
) -> &'a HashMap<u64, ParticipantIndex> {
|
||||
self.read(cx).user_store().read(cx).participant_indices()
|
||||
}
|
||||
|
||||
fn user_names(&self, cx: &AppContext) -> HashMap<u64, SharedString> {
|
||||
let this = self.read(cx);
|
||||
let user_ids = this.collaborators().values().map(|c| c.user_id);
|
||||
this.user_store().read_with(cx, |user_store, cx| {
|
||||
user_store.participant_names(user_ids, cx)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn inlay_hint_settings(
|
||||
|
@ -9310,6 +9320,7 @@ impl EditorSnapshot {
|
|||
collaboration_hub: &dyn CollaborationHub,
|
||||
cx: &'a AppContext,
|
||||
) -> impl 'a + Iterator<Item = RemoteSelection> {
|
||||
let participant_names = collaboration_hub.user_names(cx);
|
||||
let participant_indices = collaboration_hub.user_participant_indices(cx);
|
||||
let collaborators_by_peer_id = collaboration_hub.collaborators(cx);
|
||||
let collaborators_by_replica_id = collaborators_by_peer_id
|
||||
|
@ -9321,6 +9332,7 @@ impl EditorSnapshot {
|
|||
.filter_map(move |(replica_id, line_mode, cursor_shape, selection)| {
|
||||
let collaborator = collaborators_by_replica_id.get(&replica_id)?;
|
||||
let participant_index = participant_indices.get(&collaborator.user_id).copied();
|
||||
let user_name = participant_names.get(&collaborator.user_id).cloned();
|
||||
Some(RemoteSelection {
|
||||
replica_id,
|
||||
selection,
|
||||
|
@ -9328,6 +9340,7 @@ impl EditorSnapshot {
|
|||
line_mode,
|
||||
participant_index,
|
||||
peer_id: collaborator.peer_id,
|
||||
user_name,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
@ -64,6 +64,7 @@ struct SelectionLayout {
|
|||
is_local: bool,
|
||||
range: Range<DisplayPoint>,
|
||||
active_rows: Range<u32>,
|
||||
user_name: Option<SharedString>,
|
||||
}
|
||||
|
||||
impl SelectionLayout {
|
||||
|
@ -74,6 +75,7 @@ impl SelectionLayout {
|
|||
map: &DisplaySnapshot,
|
||||
is_newest: bool,
|
||||
is_local: bool,
|
||||
user_name: Option<SharedString>,
|
||||
) -> Self {
|
||||
let point_selection = selection.map(|p| p.to_point(&map.buffer_snapshot));
|
||||
let display_selection = point_selection.map(|p| p.to_display_point(map));
|
||||
|
@ -113,6 +115,7 @@ impl SelectionLayout {
|
|||
is_local,
|
||||
range,
|
||||
active_rows,
|
||||
user_name,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -980,8 +983,10 @@ impl EditorElement {
|
|||
let corner_radius = 0.15 * layout.position_map.line_height;
|
||||
let mut invisible_display_ranges = SmallVec::<[Range<DisplayPoint>; 32]>::new();
|
||||
|
||||
for (selection_style, selections) in &layout.selections {
|
||||
for selection in selections {
|
||||
for (participant_ix, (selection_style, selections)) in
|
||||
layout.selections.iter().enumerate()
|
||||
{
|
||||
for selection in selections.into_iter() {
|
||||
self.paint_highlighted_range(
|
||||
selection.range.clone(),
|
||||
selection_style.selection,
|
||||
|
@ -1062,6 +1067,7 @@ impl EditorElement {
|
|||
))
|
||||
});
|
||||
}
|
||||
|
||||
cursors.push(Cursor {
|
||||
color: selection_style.cursor,
|
||||
block_width,
|
||||
|
@ -1069,6 +1075,14 @@ impl EditorElement {
|
|||
line_height: layout.position_map.line_height,
|
||||
shape: selection.cursor_shape,
|
||||
block_text,
|
||||
cursor_name: selection.user_name.clone().map(|name| {
|
||||
CursorName {
|
||||
string: name,
|
||||
color: self.style.background,
|
||||
is_top_row: cursor_position.row() == 0,
|
||||
z_index: (participant_ix % 256).try_into().unwrap(),
|
||||
}
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1887,6 +1901,7 @@ impl EditorElement {
|
|||
&snapshot.display_snapshot,
|
||||
is_newest,
|
||||
true,
|
||||
None,
|
||||
);
|
||||
if is_newest {
|
||||
newest_selection_head = Some(layout.head);
|
||||
|
@ -1959,6 +1974,7 @@ impl EditorElement {
|
|||
&snapshot.display_snapshot,
|
||||
false,
|
||||
false,
|
||||
selection.user_name,
|
||||
));
|
||||
}
|
||||
|
||||
|
@ -1990,6 +2006,7 @@ impl EditorElement {
|
|||
&snapshot.display_snapshot,
|
||||
true,
|
||||
true,
|
||||
None,
|
||||
)
|
||||
.head
|
||||
});
|
||||
|
@ -3096,6 +3113,15 @@ pub struct Cursor {
|
|||
color: Hsla,
|
||||
shape: CursorShape,
|
||||
block_text: Option<ShapedLine>,
|
||||
cursor_name: Option<CursorName>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CursorName {
|
||||
string: SharedString,
|
||||
color: Hsla,
|
||||
is_top_row: bool,
|
||||
z_index: u8,
|
||||
}
|
||||
|
||||
impl Cursor {
|
||||
|
@ -3106,6 +3132,7 @@ impl Cursor {
|
|||
color: Hsla,
|
||||
shape: CursorShape,
|
||||
block_text: Option<ShapedLine>,
|
||||
cursor_name: Option<CursorName>,
|
||||
) -> Cursor {
|
||||
Cursor {
|
||||
origin,
|
||||
|
@ -3114,6 +3141,7 @@ impl Cursor {
|
|||
color,
|
||||
shape,
|
||||
block_text,
|
||||
cursor_name,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3156,6 +3184,29 @@ impl Cursor {
|
|||
.paint(self.origin + origin, self.line_height, cx)
|
||||
.log_err();
|
||||
}
|
||||
|
||||
if let Some(name) = &self.cursor_name {
|
||||
let name_origin = if name.is_top_row {
|
||||
point(bounds.right() - px(1.), bounds.top())
|
||||
} else {
|
||||
point(bounds.left(), bounds.top() - self.line_height / 4. - px(1.))
|
||||
};
|
||||
cx.with_z_index(name.z_index, |cx| {
|
||||
div()
|
||||
.bg(self.color)
|
||||
.text_size(self.line_height / 2.)
|
||||
.px_0p5()
|
||||
.line_height(self.line_height / 2. + px(1.))
|
||||
.text_color(name.color)
|
||||
.child(name.string.clone())
|
||||
.into_any_element()
|
||||
.draw(
|
||||
name_origin,
|
||||
size(AvailableSpace::MinContent, AvailableSpace::MinContent),
|
||||
cx,
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn shape(&self) -> CursorShape {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue