Skip to content

Real-time SSE sync: handle annotation.created & annotation.deleted (from upstream #116) #10

Description

@raimannma

Concept

The SSE listener currently only consumes annotation.updated. Expand it so multiple users viewing the same page see each other's changes live: handle annotation.created (add remote annotation with dedup against our own create), keep/extend annotation.updated (existing resolved/dismissed removal + merge field edits), and add annotation.deleted (remove with exit animation). Fire the existing onAnnotationAdd / onAnnotationUpdate / onAnnotationDelete callbacks for remote events. No new props, no new API, no new deps. From upstream benjitaylor#116 by the original author.

Value

Enables real-time multi-user annotation on shared pages (the author's use case: a shared git-diff viewer). Small, self-contained, high-leverage.

Why feasible to land soon

The actual SSE change is only ~50 lines. It is the cleanest part of the PR.

Blockers in the current PR (why not cherry-pick)

  • The PR's diff is ~1144 additions, of which the overwhelming majority is draw-mode code that is ALREADY MERGED on main (IconPencil, isDrawMode, drawStrokes, stroke gesture classification, marker-stagger timing tweaks). Cherry-picking re-introduces/duplicates merged code and conflicts heavily.
  • The PR was authored against an older SSE handler. Current main (package/src/components/page-toolbar-css/index.tsx, ~line 1010-1075) has since grown kind-aware logic for placement and rearrange annotations inside the annotation.updated handler. A naive cherry-pick would clobber that.

Recommended clean approach

Reimplement the ~50-line concept directly against the current handler:

  1. Add a handleCreated listener for annotation.created: dedup via an annotations ref AND inside the state setter (guard races), append, fire onAnnotationAdd.
  2. Add a handleDeleted listener for annotation.deleted: exit animation + removal, fire onAnnotationDelete only when found.
  3. Extend the existing annotation.updated handler to also merge non-removal field updates (comment edits, status transitions) while PRESERVING the current placement/rearrange kind-aware reverse-lookup logic.
  4. Register/cleanup all three listeners in the existing useEffect.
    Credit: reimplements the concept from feat: handle all SSE annotation events for real-time multi-user sync benjitaylor/agentation#116.

Acceptance

  • pnpm build succeeds; pnpm --filter agentation test passes (add a test that a created event with a new id appends once and a duplicate id is ignored).
  • Existing placement/rearrange removal behavior on annotation.updated is preserved.

Upstream PR: benjitaylor#116

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestupstream-trackedTracked from unmaintained upstream

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions