Skip to content

Show who else is editing a lineup group - #243

Merged
SunkenInTime merged 2 commits into
t3code/unify-cloud-mainfrom
lineup-editing-presence
Oct 3, 2026
Merged

SunkenInTime merged 2 commits into
t3code/unify-cloud-mainfrom
lineup-editing-presence

Conversation

@SunkenInTime

@SunkenInTime SunkenInTime commented Oct 3, 2026 •

Copy link
Copy Markdown
Owner

Stacked on #234. It needs #236's lineup group ids, so merge it into #234's branch, or after #234.

A lineup group (lineups that share a spot) is one cloud row, so two people changing it at the same time conflict. Rather than lock groups, presence now shows who is working on one. The lineup panel, the edit dialog and the media view say "Sam is editing these lineups right now.", with a dot in Sam's presence color. Two editors read "Sam and Alex are…"; three or more read "Sam and 2 others are…".

What counts as editing: the groups of the lineup spots you're dragging, the spot a new lineup is being placed from, and the lineups an open panel or edit dialog shows.

Room (presence/):

  • New message: {t: "editing", page, groups}.
  • Stored per peer, carried in welcome and join, broadcast only when it changes.
  • At most 8 group ids of up to 128 characters each, and at most one change per 100 ms. Anything else is ignored.
  • Old clients and an old room ignore it, so the Worker and the app can deploy in either order.

Client:

  • Sends the latest state no faster than every 150 ms, so nothing is lost to the room's limit.
  • Sends at most 8 groups, and sends them again after a rejoin.
  • The lineup group memory now says when it learns a group, so a group known only after a dialog opened is still picked up.

Verified:

  • presence/: npm run typecheck is clean; npm test passes 20 of 20, including 7 new tests.
  • flutter test: 1576 passed, 4 skipped. That includes tests for:
    • the room messages and the throttle;
    • a quick rejoin;
    • the editing provider, including a group learned while a dialog is open;
    • the panel notice.
  • Two bugs found by those tests are fixed here: a rejoin racing a throttled send, and the group memory being unobservable.

Not verified: a live run against the deployed Worker. The tests use fakes.

🤖 Generated with Claude Code

RetriggerConfidence Score: 4/5

Do not merge until renewal preserves editing changes made while pass verification is pending. The dialog attribution and eight-group limit issues are non-blocking.

Findings

  1. P1 Renewal restores stale editing ▶
  2. P2 Dialog follows wrong page ▶
  3. P2 Ninth group loses notice ▶

Summary

The PR adds lineup-group editing notices to the presence room and lineup views. A pass renewal can restore a cleared editing state, so newcomers see an incorrect notice; this must be fixed before merging. An edit dialog can also attribute an old-page draft to a group on a newly active page, and groups beyond the eight-group message limit lose their notices. Those two notice issues are non-blocking.

Reviews (1) · Last reviewed commit: "Never drop a cleared editing; fit the no..."

Presence now relays which lineup groups each person is editing, so a
teammate about to change the same lineups sees it first: "Sam is editing
these lineups right now." in the lineup panel and edit dialog, and over
the media view. A group is one cloud row, so edits to it at the same
time conflict; this is the soft hint we chose over an edit lock.

- Room: a new `editing` message ({page, groups}), kept per peer, carried
  in welcome and join, broadcast when it changes. Old clients and an old
  room ignore it, so either can deploy first.
- Client: what this user edits is the groups of the lineup spots held,
  the spot a placement is pinned to, and the lineups an open dialog
  shows. It goes out throttled (the room ignores faster sends), at most
  eight groups, and again after a rejoin. The lineup group memory now
  says when it learns a group, so both sides recompute.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: e00b4d8b-1ea6-4077-91a8-183a87aab425

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

From review:

- The room always relays a clear, however soon it follows a change: two
  messages the network delivered together could otherwise leave the
  notice on everyone's screen. A clear only broadcasts after an accepted
  change, so it cannot flood the room.
- Over the media view the notice shares one row with Delete, Edit and
  Close, so it gives way to them in a narrow window.
- The notice uses DESIGN.md's 8px step and the 12px/600 label role.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@SunkenInTime
SunkenInTime merged commit 16d3bac into t3code/unify-cloud-main Oct 3, 2026
14 checks passed
Comment thread presence/src/room.ts
) {
return;
}
ws.serializeAttachment({ ...self, editing, lastEditingAt: now });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Renewal restores stale editing

If a pass renewal is awaiting verification when an editor clears a lineup group, the clear reaches existing peers, but renewal restores the earlier socket attachment. Newcomers then receive the cleared group in their welcome message and see an incorrect editing notice. Preserve intervening editing changes when applying the renewed pass; this needs fixing before merging.

Artifacts

Executable room renewal and editing race test

  • The authored script executes both room source revisions with deferred pass verification and an interleaved editing clear, showing the exact tested sequence.

Parent room behavior before the change

  • Running the parent source shows the clear was throttled, so the existing group remained in the newcomer welcome.

Current room behavior after the change

  • Running the candidate shows the clear was broadcast but renewal restored the old group in the newcomer welcome, confirming the race.

View artifacts

T-Rex Ran code and verified through T-Rex

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in #244. After the pass check, the renewal re-reads the socket's attachment and renews that state. It returns without renewing if the socket closed while it waited.

Comment on lines +49 to +51
for (final ids in open.values) ...ids,
})
if (liveSync.lineupGroupOf(pageId, id) case final group?) group,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Dialog follows wrong page

An edit dialog can remain open after its page changes, but its registered lineup ID is looked up on the newly active page. If that page has a lineup with the same ID, collaborators see an editing notice for the new page’s group while the dialog still contains the old page’s draft. This misleading notice is a non-blocking concern; tie the registration to the page where the dialog opened.

Artifacts

Flutter test for the lineup edit dialog across a page switch

  • The authored test opens the edit dialog on p1, switches provider state and the lineup graph to p2, and checks registration, presence, draft fields, and saving, exercising the requested behavior.

Edit dialog state before switching pages

  • The focused widget command captured the open p1 dialog, its registered lineup ID, `{group-p1}` presence, and unsaved draft before the switch.

Edit dialog state after switching pages

  • The focused widget command captured the dialog remaining open in both p2 cases and, for a reused ID, `{group-p2}` presence and the p1 draft saved into p2’s lineup.

Edit dialog initialization and save paths

  • A captured source search located the one-time draft initialization, dialog registration, and save lookup, supporting the observed switch and save behavior.

View artifacts

T-Rex Ran code and verified through T-Rex

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in #244. Each open dialog records the page it opened on, and only dialogs from the page on screen count as editing.

'page': editing.pageId,
// The room refuses more than eight; in practice it is one or
// two.
'groups': ([...editing.groupIds]..sort()).take(8).toList(),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Ninth group loses notice

When open dialogs or held items cover more than eight distinct lineup groups, this truncation silently omits the remaining groups from presence. Collaborators receive no editing notice for an omitted group, making the notice incomplete in this non-blocking edge case.

Artifacts

Flutter test source for open-dialog group presence

  • The authored test creates distinct dialog groups, captures the real client outbound payload, and applies it to the remote presence reader.

Eight-group control test output

  • The Flutter test ran with eight open-dialog groups and captured all eight outbound and remotely visible, with none missing.

Nine-group test output

  • The Flutter test ran with nine open-dialog groups and captured an eight-group payload, missing `group-09` and leaving it without a remote editor.

View artifacts

T-Rex Ran code and verified through T-Rex

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intended. The room refuses more than 8 groups, so the client sends at most 8 rather than having the whole message dropped. In practice it's one or two: a held spot, a pinned placement, an open dialog. Editing nine lineup groups at once doesn't happen.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That’s fair. Since the room accepts at most eight groups, truncating the client payload to eight is the correct compatibility behavior, and the expected editing flows normally involve only one or two groups. I’m withdrawing this as a finding; no change is needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant