- 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
117 lines
4.2 KiB
Rust
117 lines
4.2 KiB
Rust
use ely_gpui_component::{
|
|
collab::{FollowMode, LiveIndicator, Peer, PresenceAvatars, RemoteCursor, RemoteSelection},
|
|
forms::{Input, TextInput},
|
|
theme::{ActiveTheme, TextSize},
|
|
};
|
|
use gpui::{
|
|
App, Entity, FontWeight, IntoElement, ParentElement, SharedString, Styled, Window, div, px,
|
|
};
|
|
|
|
use crate::{
|
|
probe::probe,
|
|
ui::{keep, section, set},
|
|
};
|
|
|
|
/// The people in the demo document, each somewhere in it.
|
|
pub fn peers() -> Vec<Peer> {
|
|
[
|
|
("ada", "Ada Park", "Reading “In dark”"),
|
|
("grace", "Grace Lin", "Writing the opening"),
|
|
("alan", "Alan Reyes", "In the comments"),
|
|
("mae", "Mae Okafor", "Viewing"),
|
|
("tim", "Tim Novak", "Viewing"),
|
|
("joan", "Joan Ito", "Viewing"),
|
|
]
|
|
.into_iter()
|
|
.enumerate()
|
|
.map(|(hue, (key, name, place))| Peer {
|
|
place: Some(place.into()),
|
|
..Peer::new(key, name, hue)
|
|
})
|
|
.collect()
|
|
}
|
|
|
|
/// The one reading the demo.
|
|
pub fn you() -> Peer {
|
|
Peer::new("you", "You", 6)
|
|
}
|
|
|
|
const DRAFT: &str = "A lift blends a color toward white.\nHalf a lift sits midway; a full lift is white itself.\nIn dark, accents lift further so they read with the same weight.";
|
|
|
|
fn draft(window: &mut Window, cx: &mut App) -> Entity<TextInput> {
|
|
window.use_keyed_state("collab-draft", cx, |window, cx| {
|
|
let mut input = TextInput::new(window, cx).multi_line(3, 6);
|
|
input.set_text(DRAFT, cx);
|
|
input
|
|
})
|
|
}
|
|
|
|
pub fn presence(window: &mut Window, cx: &mut App) -> impl IntoElement + use<> {
|
|
let following = keep("collab-following", || None::<SharedString>, window, cx);
|
|
let now = following.read(cx).clone();
|
|
let people = peers();
|
|
let followed = now
|
|
.as_ref()
|
|
.and_then(|key| people.iter().find(|peer| &peer.key == key).cloned());
|
|
let draft = draft(window, cx);
|
|
let selected = DRAFT
|
|
.find("a full lift")
|
|
.expect("the draft names a full lift");
|
|
let caret = DRAFT.find("accents").expect("the draft names accents");
|
|
let theme = cx.theme();
|
|
let (toggle, stop) = (following.clone(), following);
|
|
section(
|
|
"PresenceAvatars / LiveIndicator / FollowMode / RemoteCursor / RemoteSelection",
|
|
"Who else is here, ringed in their colors, their carets and selections live in the text. Rest on someone to see where they are; press to follow their view, and Escape to stop.",
|
|
cx,
|
|
)
|
|
.child(
|
|
div()
|
|
.w(px(760.))
|
|
.flex()
|
|
.flex_col()
|
|
.gap_3()
|
|
.child(
|
|
div()
|
|
.flex()
|
|
.items_center()
|
|
.gap_3()
|
|
.child(
|
|
div()
|
|
.flex_1()
|
|
.text_size(theme.text_size(TextSize::Sm))
|
|
.font_weight(FontWeight::MEDIUM)
|
|
.child("Handbook / Color / Lift"),
|
|
)
|
|
.child(LiveIndicator::new("collab-live", people.len()))
|
|
.child(probe(
|
|
"collab-peers",
|
|
PresenceAvatars::new("collab-peers", people.clone()).follow(
|
|
now,
|
|
move |key, _, cx| {
|
|
let next =
|
|
(toggle.read(cx).as_ref() != Some(key)).then(|| key.clone());
|
|
set(&toggle, next, cx)
|
|
},
|
|
),
|
|
)),
|
|
)
|
|
.child(
|
|
FollowMode::new("collab-follow", followed, move |_, cx| set(&stop, None, cx))
|
|
.child(
|
|
div().p_2().child(
|
|
div()
|
|
.relative()
|
|
.child(Input::new(&draft))
|
|
.child(RemoteSelection::new(
|
|
&people[2],
|
|
&draft,
|
|
selected..selected + "a full lift".len(),
|
|
))
|
|
.child(RemoteCursor::new(&people[1], &draft, caret)),
|
|
),
|
|
),
|
|
),
|
|
)
|
|
}
|