T22: Collaboration
- presence: avatars ringed in each peer's color with where they are, press to follow; a breathing live dot; follow mode frames the view and stops on Escape - remote cursors and selections painted over a field from its own layout - comment threads with replies, reactions and resolve; a marker that opens a thread in a bubble; a sidebar of open and resolved threads - annotations washed in their authors' colors, notes on hover - suggestion mode: edits become suggestions word by word; track changes shows them struck and underlined, to accept or reject - sharing: invite by email with checked chips, roles, the access list and who the link lets in, in one dialog - primitives::hold_focus gives a mode its own focus, shared with ZenMode - AvatarGroup's tuck and count shared; Avatar::ring_color; TagInput::check; TextInput::bounds_for_range; Popover::size - icons: smile-plus, user-plus, message-square-diff - gallery: the Collaboration page with scripted states
This commit is contained in:
34 files changed
+3297
-86
No files matched your search
@@ -358,7 +358,7 @@ fn keep_in_view(
|
||||
}
|
||||
|
||||
/// Boxes covering display offsets `start..end`, relative to the text origin.
|
||||
fn selection_rects(
|
||||
pub(super) fn selection_rects(
|
||||
lines: &[(usize, WrappedLine)],
|
||||
start: usize,
|
||||
end: usize,
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
use std::ops::Range;
|
||||
|
||||
use gpui::{Bounds, Pixels, Point};
|
||||
|
||||
use super::TextInput;
|
||||
use super::{TextInput, element::selection_rects};
|
||||
|
||||
impl TextInput {
|
||||
/// The caret's box in window coordinates, once laid out.
|
||||
@@ -22,6 +24,34 @@ impl TextInput {
|
||||
))
|
||||
}
|
||||
|
||||
/// A range's boxes in the window, a line each, from the last layout; later offsets clamp to its end.
|
||||
pub fn bounds_for_range(&self, range: Range<usize>) -> Vec<Bounds<Pixels>> {
|
||||
let Some(layout) = self.layout.as_ref() else {
|
||||
return Vec::new();
|
||||
};
|
||||
if layout.placeholder {
|
||||
return Vec::new();
|
||||
}
|
||||
let laid = layout
|
||||
.lines
|
||||
.last()
|
||||
.map_or(0, |(start, line)| start + line.len());
|
||||
let (start, end) = (
|
||||
self.display_offset(range.start).min(laid),
|
||||
self.display_offset(range.end).min(laid),
|
||||
);
|
||||
selection_rects(
|
||||
&layout.lines,
|
||||
start,
|
||||
end,
|
||||
layout.line_height,
|
||||
layout.bounds.size.width,
|
||||
)
|
||||
.into_iter()
|
||||
.map(|rect| Bounds::new(rect.origin + layout.bounds.origin - self.scroll, rect.size))
|
||||
.collect()
|
||||
}
|
||||
|
||||
/// Top-left of a display offset, relative to the text's origin.
|
||||
pub(crate) fn position_for(&self, display: usize) -> Option<Point<Pixels>> {
|
||||
let layout = self.layout.as_ref()?;
|
||||
|
||||
Reference in new issue
Block a user