Skip to content

A local room's invite link has no Members-card row and no redemption dialog, and the preview card would be copied a second time #876

Closed

Description

@Birfy

The second half of #852, moved out of #864 on purpose. #864 delivers the wire (ask → invite → ask{accept} → join) and parseInviteLink; #852 stays open until this lands. Refs #852, follows #864.

What is missing

  1. The Members card has no "Invite by link" row. Today the only place that mints a link is the room's face overview panel — FaceInviteCard, plugins/social/client.js:971-1042, rendered at :2406. A person looking at the member list (the Members stack at :1683) has no row to mint, copy, count down, or withdraw the link for the room they are actually in.
  2. There is no redemption dialog. #864's offer reply is delivered to a seam with nothing behind it: core/src/host/room-membership.js:1282-1285 (if (data.op === 'invite') { … void rt.onLocalInviteOffer?.(…) }) — on the PR tip 0d1f5db8, answerLocalInvite at :1019. The paste field in FaceLinkDialog still only understands Bot Social tickets, so a well-formed local link handed to it lands on the generic "not an invite link" sentence instead of an offer card.
  3. The preview card would be written twice. The room preview (name, Lead:, n / 8 in the room, expiry) is built inline in plugins/social/client.js — faceInvitePreview at :919-930, drawn at :1531-1545. A member-invite flow needs the same card on the offer side, from the same fields the invite op already carries. Copying that markup is the bug this issue is meant to prevent.

What we ask

  • Members card: an Invite by link row with mint / copy / countdown / withdraw, for the room that card belongs to. One ticket per room — minting from the Members card and looking at the face overview must show the same link, not a second one.
  • Redemption: when a local link arrives (pasted, or from the offer seam), open a dialog that shows the preview from the invite reply and a Join that sends the accepting ask. Each refusal from #864 gets its own sentence: unknown, expired, consumed, no-sender, not-addable — the generic "not an invite link" is for a typo, not for a link the server answered.
  • The preview card becomes one shared core component, rendered by both the member-invite dialog and the existing paste flow. No second copy of the markup.

Scope

  • plugins/social/client.js (Members card row, dialog, wiring to the seam), the shared component's home under core/src/, docs/subsystems/social.md for the two shapes and the dialog, tests in plugins/social/test/, one changelog.d/ fragment.
  • No wire changes are expected. ask/invite and every refusal already exist in #864. If the UI needs a new field or op, stop and report instead of adding one here — that changes a contract another PR is being reviewed against.

Acceptance

  1. From the Members card: mint produces a link with copy and countdown; withdraw ends it; the same room's face overview shows that same link. A second mint replaces it (one live ticket per room), matching the contract #852 already fixed.
  2. Pasting a live local link opens the dialog with the offer's name, lead, member count and expiry; Join admits this home through the accepting ask and puts the person in that room.
  3. A dead link explains itself: an expired ticket says it expired, a ticket already accepted by another home says so, and neither says "not an invite link". One case per refusal.
  4. The preview markup exists once: a test renders both the member-invite dialog and the paste flow from the shared component, and a change to that component is visible in both (no copied markup left in client.js).
  5. #852 is closed by whoever merges the last linked piece, not by this issue alone — this one names the remaining gap, so it may close with a Refs #852 and leave that issue open until the Members card row is actually shipped.

Activity

  1. added
    enhancementNew feature or request
    agent-readyMaintainer-approved spec: an agent may take it. Only maintainers set this; never in a template
    area:socialFriends, invites, grants, Bot Social
    area:uiWeb/desktop UI and copy
    on Oct 23, 2026
  2. Birfy commented on Oct 23, 2026

    @Birfy
    CollaboratorAuthor

    Claiming this one. Branch: feat/876-local-room-invite-card.

    Order of work (the shared component comes first, because the issue names the second copy as the bug):

    1. The preview card moves to core/src/client/ as one component; the face-room paste flow and the member-invite dialog both render that component. Nothing in plugins/social/client.js keeps a second copy of the markup.
    2. Members card row: Invite by link with mint / copy / countdown / withdraw, reading the same one live ticket per room that the face overview shows.
    3. Redemption dialog behind the onLocalInviteOffer seam and behind a pasted local link, one sentence per refusal (unknown, expired, consumed, no-sender, not-addable).
    4. Tests, docs/subsystems/social.md, one changelog.d fragment.

    No wire changes: ask/invite and the five refusals are already in #864. If the UI turns out to need a new field or op, I stop and report here instead of adding one.

    #852 stays open; this closes with Refs #852.

  3. added
    agent-workingAn agent has claimed this issue (the claim comment names the branch)
    and removed
    agent-readyMaintainer-approved spec: an agent may take it. Only maintainers set this; never in a template
    on Oct 23, 2026
  4. self-assigned this
    on Oct 23, 2026
  5. Birfy commented on Oct 23, 2026

    @Birfy
    CollaboratorAuthor

    Split (2026-10-23): the green half is #885; the Members row and the redeem dialog stay here.

    The PR for the plumbing half reads Fixes #885 + Refs #876, so the guard gets a closable reference and this issue is not closed by a half. Reopening the scope here for clarity:

    • Left in #885: core RoomInvitePreview + invitePreviewOf on __flybot__, host room-invite / room-invite-mint / room-invite-revoke, tests, docs, changelog.
    • Left here: the Members card's Invite by link row (mint / copy / countdown / withdraw), the QR code, and the redeem dialog (onLocalInviteOffer, the preview card, Join).

    Still true for this issue: one ticket per room — the Members card and the face-room card read the same localInvite through the same three ops and neither mints a copy — and one preview component, not two.

  6. Birfy commented on Oct 23, 2026

    @Birfy
    CollaboratorAuthor

    Written-by: Dev

    Reopened: #887 (merged as d0cafd5) was linked as closing this issue, but it is the plumbing half (#885). The Members card's Invite by link row with the QR code and the redeem dialog are still to land here. Working on them now on feat/876-invite-row, on top of #889 (#884/#878) and the #883 plugin seam, so the row mints a Bot Social ticket that a stranger can redeem.

  7. reopened this on Oct 23, 2026
  8. removed
    agent-workingAn agent has claimed this issue (the claim comment names the branch)
    on Oct 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:socialFriends, invites, grants, Bot Socialarea:uiWeb/desktop UI and copyenhancementNew feature or request

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions