feat(#571): share dialog — people and groups, internal link, public link #581

Merged
Cordy merged 6 commits from fix-571dlg into main 2026-09-17 20:50:21 +00:00
Owner

The dialog from the approved mockup. Three sections in the agreed order, backed entirely by what #573–#576 already shipped.

The policy rule is the tested part. pure:share-sections encodes what we settled in rev 2:

  • one switch off → the refusal stays in the section it belongs to, because the surrounding sections are live and the heading is useful context for it;
  • both off → one notice at the top naming both, and the sections with nothing to offer are not rendered at all.

share-sections.test.js also pins the claim most likely to be "tidied" away by someone wiring all three sections to one flag: the internal link survives every combination, because it grants nothing on its own.

The internal link is not a new invention. Line 6639 already builds one for the copy-location feature:

location.origin + location.pathname + "#loc:" + encodeURIComponent(loc)

and the loc: hash handler probes access and says locNoAccess when the viewer has none. That is precisely "grants nothing, resolves only for people who already have access" — so the section reuses the proven format rather than a guess.

Two things the implementation decides, both deliberate:

  • Add stays disabled until a candidate is picked from the search results. Typing a group name by hand would otherwise create a user grant with that name — which entitles nobody and looks like it worked. The picker returns the kind; nothing else should guess it.
  • A role change is a revoke followed by a fresh grant, because there is no PATCH for a grant. Only the owner can reach the control and the list reloads either way, so a failure cannot leave a stale row. A PATCH endpoint would be the tidier follow-up.

Surgical notes. The existing markup was moved, not rewritten: the protection, expiry, password, upload and result blocks are captured verbatim by id and re-parented into the new Public link section, because those lines carry shipped i18n copy and em-dashes that retyping would silently alter. Every id the current submit handler depends on is unchanged, so link creation is untouched. The #sharedlg.shareoff CSS is removed — nothing applies that class any more, the sections carry their own state.

Federated send needed no work: line 872 already carries #sharedlg-fed{display:none !important}, so the surface #572 exists to relocate is already dark.

17 new i18n keys ×4.

What I have not verified, and cannot. These tests cover the policy rule, JS syntax and the #389 desktop-invariant fence — not appearance, and not a live round-trip against the grant API. The dialog is substantially restructured and I have not seen it render. It wants a look on the dogfood before it is trusted.

Verified: share-sections.test.js green (red witnessed first — the block did not exist), all ten web tests green, extract.js + node --check green, \\u escape guard green, full Go suite green.

The dialog from the approved mockup. Three sections in the agreed order, backed entirely by what #573–#576 already shipped. **The policy rule is the tested part.** `pure:share-sections` encodes what we settled in rev 2: - **one switch off** → the refusal stays in the section it belongs to, because the surrounding sections are live and the heading is useful context for it; - **both off** → one notice at the top naming both, and the sections with nothing to offer are not rendered at all. `share-sections.test.js` also pins the claim most likely to be "tidied" away by someone wiring all three sections to one flag: **the internal link survives every combination**, because it grants nothing on its own. **The internal link is not a new invention.** Line 6639 already builds one for the copy-location feature: ```js location.origin + location.pathname + "#loc:" + encodeURIComponent(loc) ``` and the `loc:` hash handler probes access and says `locNoAccess` when the viewer has none. That is precisely "grants nothing, resolves only for people who already have access" — so the section reuses the proven format rather than a guess. **Two things the implementation decides, both deliberate:** - **Add stays disabled until a candidate is picked** from the search results. Typing a group name by hand would otherwise create a *user* grant with that name — which entitles nobody and looks like it worked. The picker returns the kind; nothing else should guess it. - **A role change is a revoke followed by a fresh grant**, because there is no PATCH for a grant. Only the owner can reach the control and the list reloads either way, so a failure cannot leave a stale row. A PATCH endpoint would be the tidier follow-up. **Surgical notes.** The existing markup was *moved*, not rewritten: the protection, expiry, password, upload and result blocks are captured verbatim by id and re-parented into the new Public link section, because those lines carry shipped i18n copy and em-dashes that retyping would silently alter. Every id the current submit handler depends on is unchanged, so link creation is untouched. The `#sharedlg.shareoff` CSS is removed — nothing applies that class any more, the sections carry their own state. Federated send needed no work: line 872 already carries `#sharedlg-fed{display:none !important}`, so the surface #572 exists to relocate is already dark. 17 new i18n keys ×4. **What I have not verified, and cannot.** These tests cover the policy rule, JS syntax and the #389 desktop-invariant fence — not appearance, and not a live round-trip against the grant API. The dialog is substantially restructured and I have not seen it render. It wants a look on the dogfood before it is trusted. Verified: `share-sections.test.js` green (red witnessed first — the block did not exist), all ten web tests green, `extract.js` + `node --check` green, `\\u` escape guard green, full Go suite green.
Cordy merged commit 67b1c11eb6 into main 2026-09-17 20:50:21 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: Cordy/Cairn#581
No description provided.