Skip to content

Commit da6ee9e

Browse files
committed
docs: add documents of SyncPlugin
1 parent dcfe49e commit da6ee9e

1 file changed

Lines changed: 49 additions & 0 deletions

File tree

crates/core/src/plugin/sync.rs

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,69 @@
1+
//! Collaboration / replication hooks for the canvas graph.
2+
//!
3+
//! A [`SyncPlugin`] sits **beside** the local [`crate::Graph`]: the canvas still applies
4+
//! [`crate::GraphOp`] through commands and history, while the plugin mirrors those intents into a
5+
//! shared model (CRDT, document store, network sync, etc.) and pushes updates back through
6+
//! [`GraphChange`] so the UI stays consistent with peers and with undo/redo semantics.
7+
//!
8+
//! Implementations typically:
9+
//! - In [`SyncPlugin::setup`], subscribe to the shared model and forward diffs on
10+
//! [`UnboundedSender<GraphChange>`], setting [`crate::ChangeSource`] (`Local`, `Remote`, `Undo`,
11+
//! …) so the host can tell operator-driven edits from replay or remote merges.
12+
//! - In [`SyncPlugin::process_intent`], apply each [`GraphOp`] produced locally (after a command
13+
//! runs or history replays) into that model, using whatever metadata your stack needs to avoid
14+
//! mis-classifying those writes when your subscription fires again.
15+
//! - In [`SyncPlugin::undo`] / [`SyncPlugin::redo`], advance **your** backend undo manager if the
16+
//! sync layer owns a stack separate from the canvas history.
17+
//!
18+
//! The concrete backend (Yjs, operational transform, file append, etc.) is up to the plugin; this
19+
//! trait only defines the integration surface with the canvas.
20+
121
use futures::channel::mpsc::UnboundedSender;
222
use gpui::{AnyElement, Pixels, Point};
323

424
use crate::{FlowEvent, GraphChange, GraphOp, RenderContext, Viewport};
525

26+
/// Bridges local graph edits to a replicated or external graph model, and streams model changes
27+
/// back into the canvas.
28+
///
29+
/// **Data flow (intended pattern)**
30+
/// 1. User action → canvas runs a command → [`GraphOp`]s are applied to the local graph.
31+
/// 2. The host forwards those ops to [`SyncPlugin::process_intent`] so the plugin updates its
32+
/// shared state.
33+
/// 3. Shared state emits updates (local echo, remote peer, or undo replay) → plugin sends
34+
/// [`GraphChange`] on the channel passed to [`SyncPlugin::setup`].
35+
/// 4. Canvas applies those changes and refreshes; [`GraphChange::source`] distinguishes how each
36+
/// change should be treated (e.g. skip re-broadcasting remote edits).
37+
///
38+
/// Keep [`process_intent`](SyncPlugin::process_intent) idempotent with respect to your own
39+
/// observers where possible: the same logical op may be reflected back through your subscription;
40+
/// tagging “local intent” vs “remote” vs “undo” origins is the usual way to stay consistent.
641
pub trait SyncPlugin {
742
fn name(&self) -> &'static str;
843

44+
/// One-time wiring: subscribe to the shared model, retain subscriptions for the plugin
45+
/// lifetime, and send [`GraphChange`] values on `change_sender` whenever the model moves.
46+
///
47+
/// The host owns the receiver; do not block the UI thread on long-running I/O—spawn a task or
48+
/// use non-blocking channels as appropriate.
949
fn setup(&mut self, change_sender: UnboundedSender<GraphChange>);
1050

51+
/// Apply a single local [`GraphOp`] (or a batch already decomposed by the host) into your
52+
/// backend. This is invoked for operator-driven edits after they hit the local graph, not as
53+
/// a replacement for the canvas command pipeline.
1154
fn process_intent(&self, op: GraphOp);
1255

56+
/// Step the sync-layer undo stack backward, if your backend maintains one in addition to (or
57+
/// instead of) mirroring canvas history.
1358
fn undo(&mut self);
59+
/// Step the sync-layer undo stack forward.
1460
fn redo(&mut self);
1561

62+
/// Optional: handle canvas [`FlowEvent`]s for awareness, presence, or other non-[`GraphOp`]
63+
/// signals. Use [`SyncPluginContext`] for coordinate transforms when needed.
1664
fn on_event(&mut self, _event: &FlowEvent, _ctx: &mut SyncPluginContext);
1765

66+
/// Optional overlay (e.g. remote pointers) drawn with normal canvas [`RenderContext`].
1867
fn render(&mut self, _ctx: &mut RenderContext) -> Vec<AnyElement> {
1968
vec![]
2069
}

0 commit comments

Comments
 (0)