Show remote collaborators' active selections

This commit is contained in:
Antonio Scandurra 2021-12-13 11:38:38 +01:00
parent 2adf11e204
commit c984b39aaa
8 changed files with 117 additions and 45 deletions

View file

@ -1991,8 +1991,8 @@ impl Editor {
pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) { pub fn undo(&mut self, _: &Undo, cx: &mut ViewContext<Self>) {
if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) { if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.undo(cx)) {
if let Some((selections, _)) = self.selection_history.get(&tx_id) { if let Some((selections, _)) = self.selection_history.get(&tx_id).cloned() {
self.selections = selections.clone(); self.set_selections(selections, cx);
} }
self.request_autoscroll(Autoscroll::Fit, cx); self.request_autoscroll(Autoscroll::Fit, cx);
} }
@ -2000,8 +2000,8 @@ impl Editor {
pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) { pub fn redo(&mut self, _: &Redo, cx: &mut ViewContext<Self>) {
if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) { if let Some(tx_id) = self.buffer.update(cx, |buffer, cx| buffer.redo(cx)) {
if let Some((_, Some(selections))) = self.selection_history.get(&tx_id) { if let Some((_, Some(selections))) = self.selection_history.get(&tx_id).cloned() {
self.selections = selections.clone(); self.set_selections(selections, cx);
} }
self.request_autoscroll(Autoscroll::Fit, cx); self.request_autoscroll(Autoscroll::Fit, cx);
} }
@ -3256,13 +3256,23 @@ impl Editor {
} }
self.pause_cursor_blinking(cx); self.pause_cursor_blinking(cx);
self.selections = Arc::from_iter(selections.into_iter().map(|selection| Selection { self.set_selections(
id: selection.id, Arc::from_iter(selections.into_iter().map(|selection| Selection {
start: buffer.anchor_before(selection.start), id: selection.id,
end: buffer.anchor_before(selection.end), start: buffer.anchor_before(selection.start),
reversed: selection.reversed, end: buffer.anchor_before(selection.end),
goal: selection.goal, reversed: selection.reversed,
})); goal: selection.goal,
})),
cx,
);
}
fn set_selections(&mut self, selections: Arc<[Selection<Anchor>]>, cx: &mut ViewContext<Self>) {
self.selections = selections;
self.buffer.update(cx, |buffer, cx| {
buffer.set_active_selections(&self.selections, cx)
});
} }
fn request_autoscroll(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) { fn request_autoscroll(&mut self, autoscroll: Autoscroll, cx: &mut ViewContext<Self>) {
@ -3651,11 +3661,16 @@ impl View for Editor {
fn on_focus(&mut self, cx: &mut ViewContext<Self>) { fn on_focus(&mut self, cx: &mut ViewContext<Self>) {
self.focused = true; self.focused = true;
self.blink_cursors(self.blink_epoch, cx); self.blink_cursors(self.blink_epoch, cx);
self.buffer.update(cx, |buffer, cx| {
buffer.set_active_selections(&self.selections, cx)
});
} }
fn on_blur(&mut self, cx: &mut ViewContext<Self>) { fn on_blur(&mut self, cx: &mut ViewContext<Self>) {
self.focused = false; self.focused = false;
self.show_local_cursors = false; self.show_local_cursors = false;
self.buffer
.update(cx, |buffer, cx| buffer.remove_active_selections(cx));
cx.emit(Event::Blurred); cx.emit(Event::Blurred);
cx.notify(); cx.notify();
} }

View file

@ -12,7 +12,7 @@ use language::{
use std::{ use std::{
cell::{Ref, RefCell}, cell::{Ref, RefCell},
cmp, io, cmp, io,
iter::Peekable, iter::{FromIterator, Peekable},
ops::{Range, Sub}, ops::{Range, Sub},
sync::Arc, sync::Arc,
time::{Duration, Instant, SystemTime}, time::{Duration, Instant, SystemTime},
@ -242,6 +242,34 @@ impl MultiBuffer {
.update(cx, |buffer, cx| buffer.end_transaction_at(now, cx)) .update(cx, |buffer, cx| buffer.end_transaction_at(now, cx))
} }
pub fn set_active_selections(
&mut self,
selections: &[Selection<Anchor>],
cx: &mut ModelContext<Self>,
) {
// TODO
let this = self.read(cx);
self.as_singleton().unwrap().update(cx, |buffer, cx| {
let buffer_snapshot = buffer.snapshot();
let selections = selections.iter().map(|selection| Selection {
id: selection.id,
start: buffer_snapshot.anchor_before(selection.start.to_offset(&this)),
end: buffer_snapshot.anchor_before(selection.end.to_offset(&this)),
reversed: selection.reversed,
goal: selection.goal,
});
buffer.set_active_selections(Arc::from_iter(selections), cx);
});
}
pub fn remove_active_selections(&mut self, cx: &mut ModelContext<Self>) {
for buffer in self.buffers.values() {
buffer
.buffer
.update(cx, |buffer, cx| buffer.remove_active_selections(cx));
}
}
pub fn undo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> { pub fn undo(&mut self, cx: &mut ModelContext<Self>) -> Option<TransactionId> {
// TODO // TODO
self.as_singleton() self.as_singleton()

View file

@ -289,6 +289,12 @@ impl Buffer {
.map(|op| text::Operation::Edit(proto::deserialize_edit_operation(op))); .map(|op| text::Operation::Edit(proto::deserialize_edit_operation(op)));
buffer.apply_ops(ops)?; buffer.apply_ops(ops)?;
let mut this = Self::build(buffer, file); let mut this = Self::build(buffer, file);
for selection_set in message.selections {
this.remote_selections.insert(
selection_set.replica_id as ReplicaId,
proto::deserialize_selections(selection_set.selections),
);
}
this.apply_diagnostic_update( this.apply_diagnostic_update(
Arc::from(proto::deserialize_diagnostics(message.diagnostics)), Arc::from(proto::deserialize_diagnostics(message.diagnostics)),
cx, cx,
@ -306,7 +312,14 @@ impl Buffer {
.history() .history()
.map(proto::serialize_edit_operation) .map(proto::serialize_edit_operation)
.collect(), .collect(),
selections: Vec::new(), selections: self
.remote_selections
.iter()
.map(|(replica_id, selections)| proto::SelectionSet {
replica_id: *replica_id as u32,
selections: proto::serialize_selections(selections),
})
.collect(),
diagnostics: proto::serialize_diagnostics(self.diagnostics.iter()), diagnostics: proto::serialize_diagnostics(self.diagnostics.iter()),
} }
} }
@ -835,7 +848,7 @@ impl Buffer {
cx.emit(Event::DiagnosticsUpdated); cx.emit(Event::DiagnosticsUpdated);
Ok(Operation::UpdateDiagnostics { Ok(Operation::UpdateDiagnostics {
diagnostics: Arc::from(self.diagnostics.iter().cloned().collect::<Vec<_>>()), diagnostics: Arc::from(self.diagnostics.iter().cloned().collect::<Vec<_>>()),
lamport_timestamp: self.lamport_timestamp(), lamport_timestamp: self.text.lamport_clock.tick(),
}) })
} }
@ -1084,6 +1097,35 @@ impl Buffer {
} }
} }
pub fn set_active_selections(
&mut self,
selections: Arc<[Selection<Anchor>]>,
cx: &mut ModelContext<Self>,
) {
let lamport_timestamp = self.text.lamport_clock.tick();
self.remote_selections
.insert(self.text.replica_id(), selections.clone());
self.send_operation(
Operation::UpdateSelections {
replica_id: self.text.replica_id(),
selections,
lamport_timestamp,
},
cx,
);
}
pub fn remove_active_selections(&mut self, cx: &mut ModelContext<Self>) {
let lamport_timestamp = self.text.lamport_clock.tick();
self.send_operation(
Operation::RemoveSelections {
replica_id: self.text.replica_id(),
lamport_timestamp,
},
cx,
);
}
fn update_language_server(&mut self) { fn update_language_server(&mut self) {
let language_server = if let Some(language_server) = self.language_server.as_mut() { let language_server = if let Some(language_server) = self.language_server.as_mut() {
language_server language_server
@ -1321,14 +1363,14 @@ impl Buffer {
lamport_timestamp, lamport_timestamp,
} => { } => {
self.remote_selections.insert(replica_id, selections); self.remote_selections.insert(replica_id, selections);
self.text.observe_lamport_timestamp(lamport_timestamp); self.text.lamport_clock.observe(lamport_timestamp);
} }
Operation::RemoveSelections { Operation::RemoveSelections {
replica_id: set_id, replica_id,
lamport_timestamp, lamport_timestamp,
} => { } => {
self.remote_selections.remove(&set_id); self.remote_selections.remove(&replica_id);
self.text.observe_lamport_timestamp(lamport_timestamp); self.text.lamport_clock.observe(lamport_timestamp);
} }
} }
} }
@ -1655,6 +1697,7 @@ impl BufferSnapshot {
{ {
self.remote_selections self.remote_selections
.iter() .iter()
.filter(|(replica_id, _)| **replica_id != self.text.replica_id())
.map(move |(replica_id, selections)| { .map(move |(replica_id, selections)| {
let start_ix = match selections let start_ix = match selections
.binary_search_by(|probe| probe.end.cmp(&range.start, self).unwrap()) .binary_search_by(|probe| probe.end.cmp(&range.start, self).unwrap())

View file

@ -1,13 +1,12 @@
use std::sync::Arc;
use crate::{diagnostic_set::DiagnosticEntry, Diagnostic, Operation}; use crate::{diagnostic_set::DiagnosticEntry, Diagnostic, Operation};
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use clock::ReplicaId; use clock::ReplicaId;
use lsp::DiagnosticSeverity; use lsp::DiagnosticSeverity;
use rpc::proto; use rpc::proto;
use std::sync::Arc;
use text::*; use text::*;
pub use proto::Buffer; pub use proto::{Buffer, SelectionSet};
pub fn serialize_operation(operation: &Operation) -> proto::Operation { pub fn serialize_operation(operation: &Operation) -> proto::Operation {
proto::Operation { proto::Operation {
@ -48,15 +47,7 @@ pub fn serialize_operation(operation: &Operation) -> proto::Operation {
} => proto::operation::Variant::UpdateSelections(proto::operation::UpdateSelections { } => proto::operation::Variant::UpdateSelections(proto::operation::UpdateSelections {
replica_id: *replica_id as u32, replica_id: *replica_id as u32,
lamport_timestamp: lamport_timestamp.value, lamport_timestamp: lamport_timestamp.value,
selections: selections selections: serialize_selections(selections),
.iter()
.map(|selection| proto::Selection {
id: selection.id as u64,
start: Some(serialize_anchor(&selection.start)),
end: Some(serialize_anchor(&selection.end)),
reversed: selection.reversed,
})
.collect(),
}), }),
Operation::RemoveSelections { Operation::RemoveSelections {
replica_id, replica_id,

View file

@ -234,9 +234,7 @@ message Buffer {
message SelectionSet { message SelectionSet {
uint32 replica_id = 1; uint32 replica_id = 1;
uint32 lamport_timestamp = 2; repeated Selection selections = 2;
bool is_active = 3;
repeated Selection selections = 4;
} }
message Selection { message Selection {

View file

@ -5,4 +5,4 @@ pub mod proto;
pub use conn::Connection; pub use conn::Connection;
pub use peer::*; pub use peer::*;
pub const PROTOCOL_VERSION: u32 = 3; pub const PROTOCOL_VERSION: u32 = 4;

View file

@ -49,12 +49,13 @@ pub struct Buffer {
replica_id: ReplicaId, replica_id: ReplicaId,
remote_id: u64, remote_id: u64,
local_clock: clock::Local, local_clock: clock::Local,
lamport_clock: clock::Lamport, pub lamport_clock: clock::Lamport,
subscriptions: Topic, subscriptions: Topic,
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct BufferSnapshot { pub struct BufferSnapshot {
replica_id: ReplicaId,
visible_text: Rope, visible_text: Rope,
deleted_text: Rope, deleted_text: Rope,
undo_map: UndoMap, undo_map: UndoMap,
@ -464,6 +465,7 @@ impl Buffer {
Buffer { Buffer {
snapshot: BufferSnapshot { snapshot: BufferSnapshot {
replica_id,
visible_text, visible_text,
deleted_text: Rope::new(), deleted_text: Rope::new(),
fragments, fragments,
@ -495,14 +497,6 @@ impl Buffer {
self.local_clock.replica_id self.local_clock.replica_id
} }
pub fn lamport_timestamp(&self) -> clock::Lamport {
self.lamport_clock
}
pub fn observe_lamport_timestamp(&mut self, timestamp: clock::Lamport) {
self.lamport_clock.observe(timestamp);
}
pub fn remote_id(&self) -> u64 { pub fn remote_id(&self) -> u64 {
self.remote_id self.remote_id
} }
@ -1219,6 +1213,10 @@ impl BufferSnapshot {
&self.visible_text &self.visible_text
} }
pub fn replica_id(&self) -> ReplicaId {
self.replica_id
}
pub fn row_count(&self) -> u32 { pub fn row_count(&self) -> u32 {
self.max_point().row + 1 self.max_point().row + 1
} }

View file

@ -1,5 +1,4 @@
#!/bin/bash #!/bin/bash
set -e set -e
cd server cargo run --package=zed-server --features seed-support --bin seed
cargo run --features seed-support --bin seed