Detailed changes
@@ -1,6 +1,6 @@
use crate::{Channel, ChannelId, ChannelStore};
use anyhow::Result;
-use client::{Client, Collaborator, UserStore};
+use client::{Client, Collaborator, UserStore, ZED_ALWAYS_ACTIVE};
use collections::HashMap;
use gpui::{AppContext, AsyncAppContext, Context, EventEmitter, Model, ModelContext, Task};
use language::proto::serialize_version;
@@ -181,6 +181,16 @@ impl ChannelBuffer {
) {
match event {
language::Event::Operation(operation) => {
+ if *ZED_ALWAYS_ACTIVE {
+ match operation {
+ language::Operation::UpdateSelections { selections, .. } => {
+ if selections.is_empty() {
+ return;
+ }
+ }
+ _ => {}
+ }
+ }
let operation = language::proto::serialize_operation(operation);
self.client
.send(proto::UpdateChannelBuffer {
@@ -635,7 +635,6 @@ impl UserStore {
cx.spawn(|this, mut cx| async move {
if let Some(rpc) = client.upgrade() {
let response = rpc.request(request).await.context("error loading users")?;
- dbg!(&response.users);
let users = response
.users
.into_iter()
@@ -450,8 +450,21 @@ impl Database {
)> {
self.transaction(move |tx| async move {
let channel = self.get_channel_internal(channel_id, &*tx).await?;
- self.check_user_is_channel_member(&channel, user, &*tx)
- .await?;
+
+ let mut requires_write_permission = false;
+ for op in operations.iter() {
+ match op.variant {
+ None | Some(proto::operation::Variant::UpdateSelections(_)) => {}
+ Some(_) => requires_write_permission = true,
+ }
+ }
+ if requires_write_permission {
+ self.check_user_is_channel_member(&channel, user, &*tx)
+ .await?;
+ } else {
+ self.check_user_is_channel_participant(&channel, user, &*tx)
+ .await?;
+ }
let buffer = buffer::Entity::find()
.filter(buffer::Column::ChannelId.eq(channel_id))
@@ -368,7 +368,7 @@ pub struct Editor {
collaboration_hub: Option<Box<dyn CollaborationHub>>,
blink_manager: Model<BlinkManager>,
recently_focused: bool,
- hovered_selections: HashSet<(ReplicaId, usize)>,
+ hovered_cursor: Option<HoveredCursor>,
pub show_local_selections: bool,
mode: EditorMode,
show_gutter: bool,
@@ -420,6 +420,7 @@ pub struct EditorSnapshot {
ongoing_scroll: OngoingScroll,
}
+#[derive(Debug)]
pub struct RemoteSelection {
pub replica_id: ReplicaId,
pub selection: Selection<Anchor>,
@@ -444,6 +445,11 @@ enum SelectionHistoryMode {
Redoing,
}
+struct HoveredCursor {
+ replica_id: u16,
+ selection_id: usize,
+}
+
impl Default for SelectionHistoryMode {
fn default() -> Self {
Self::Normal
@@ -1608,7 +1614,7 @@ impl Editor {
gutter_width: Default::default(),
style: None,
recently_focused: false,
- hovered_selections: Default::default(),
+ hovered_cursor: Default::default(),
editor_actions: Default::default(),
show_copilot_suggestions: mode == EditorMode::Full,
_subscriptions: vec![
@@ -8998,8 +9004,9 @@ impl Editor {
} else {
self.blink_manager.update(cx, BlinkManager::enable);
self.recently_focused = true;
+ cx.notify();
cx.spawn(|this, mut cx| async move {
- cx.background_executor().timer(Duration::from_secs(5)).await;
+ cx.background_executor().timer(Duration::from_secs(2)).await;
this.update(&mut cx, |this, cx| {
this.recently_focused = false;
cx.notify()
@@ -567,6 +567,7 @@ impl EditorElement {
cx,
);
hover_at(editor, Some(point), cx);
+ Self::update_visible_cursor(editor, point, cx);
}
None => {
update_inlay_link_and_hover_points(
@@ -594,24 +595,28 @@ impl EditorElement {
cx: &mut ViewContext<Editor>,
) {
let snapshot = editor.snapshot(cx);
- if let Some(hub) = editor.collaboration_hub() {
- let range = if point.column() > 0 {
- DisplayPoint::new(point.row(), point.column() - 1)..point
- } else {
- point..DisplayPoint::new(point.row(), point.column() + 1)
- };
- let range = snapshot
+ let Some(hub) = editor.collaboration_hub() else {
+ return;
+ };
+ let range = DisplayPoint::new(point.row(), point.column().saturating_sub(1))
+ ..DisplayPoint::new(point.row(), point.column() + 1);
+
+ let range = snapshot
+ .buffer_snapshot
+ .anchor_at(range.start.to_point(&snapshot.display_snapshot), Bias::Left)
+ ..snapshot
.buffer_snapshot
- .anchor_at(range.start.to_point(&snapshot.display_snapshot), Bias::Left)
- ..snapshot
- .buffer_snapshot
- .anchor_at(range.end.to_point(&snapshot.display_snapshot), Bias::Right);
- for selection in snapshot.remote_selections_in_range(&range, hub, cx) {
- let key = (selection.replica_id, selection.selection.id);
- editor.hovered_selections.insert(key);
- }
- }
- editor.hovered_selections.clear();
+ .anchor_at(range.end.to_point(&snapshot.display_snapshot), Bias::Right);
+
+ let Some(selection) = snapshot.remote_selections_in_range(&range, hub, cx).next() else {
+ editor.hovered_cursor.take();
+ return;
+ };
+ editor.hovered_cursor.replace(crate::HoveredCursor {
+ replica_id: selection.replica_id,
+ selection_id: selection.selection.id,
+ });
+ cx.notify()
}
fn paint_background(
@@ -1990,7 +1995,7 @@ impl EditorElement {
if Some(selection.peer_id) == editor.leader_peer_id {
continue;
}
- let id = (selection.replica_id, selection.selection.id);
+ let is_shown = editor.recently_focused || editor.hovered_cursor.as_ref().is_some_and(|c| c.replica_id == selection.replica_id && c.selection_id == selection.selection.id);
remote_selections
.entry(selection.replica_id)
@@ -2003,7 +2008,7 @@ impl EditorElement {
&snapshot.display_snapshot,
false,
false,
- if editor.recently_focused || editor.hovered_selections.contains(&id) {
+ if is_shown {
selection.user_name
} else {
None
@@ -3209,26 +3214,20 @@ impl Cursor {
fill(bounds, self.color)
};
- cx.paint_quad(cursor);
-
- if let Some(block_text) = &self.block_text {
- block_text
- .paint(self.origin + origin, self.line_height, cx)
- .log_err();
- }
-
if let Some(name) = &self.cursor_name {
+ let text_size = self.line_height / 1.5;
+
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.))
+ point(bounds.left(), bounds.top() - text_size / 2. - px(1.))
};
cx.with_z_index(name.z_index, |cx| {
div()
.bg(self.color)
- .text_size(self.line_height / 2.)
+ .text_size(text_size)
.px_0p5()
- .line_height(self.line_height / 2. + px(1.))
+ .line_height(text_size + px(2.))
.text_color(name.color)
.child(name.string.clone())
.into_any_element()
@@ -3239,6 +3238,14 @@ impl Cursor {
)
})
}
+
+ cx.paint_quad(cursor);
+
+ if let Some(block_text) = &self.block_text {
+ block_text
+ .paint(self.origin + origin, self.line_height, cx)
+ .log_err();
+ }
}
pub fn shape(&self) -> CursorShape {