feat(sharing): manage public profiles and share links from the phone - #78
Merged
Merged
Conversation
The owner side of public profiles, ported from web. There is no native
viewer: a shared link already renders in any mobile browser, so the app
covers what the browser page cannot, which is managing what you share.
**Sharing screen** (Settings > Safety > Sharing). Share views, "who can see
what" from /sharing/audit, and a list of grants that are not serving right
now (pending, expired). The entry is shown whatever the instance switch says,
because an owner must always be able to reach revoke, including after an
operator turns publishing off. The audit keeps the curated member count and
the served one apart, and says when nothing is served at all and why.
Creating a link shows its token once, since nothing can read it back. Expiry
is picked at creation: presets or a date, meaning the end of that day on the
user's own calendar. The API has no way to move it later, and the dialog says
so. A date on or before the day a staged grant goes live is refused, because
that link would expire without ever having been readable.
**A view.** The six exposure flags show their staged twins, and member
permalinks sit outside the gate in both directions since they expose nobody
new. Members carry the server's own served/not-served reason rather than a
client guess. Fields and groups can be added and removed, and a group reports
who it left out and asks whether detaching it takes its members too. Preview
renders /share-views/{id}/preview, the same projection the public router
uses, so it cannot show a page that would not really be served.
**Step-up.** The client mirrors visibility_step_up_required to open the
credential sheet before the round trip, and a server bounce still wins and
reopens it. The error detail separates the cases that need different
answers: a missing credential (400), a wrong one, publishing switched off on
the instance, the missing 18+ declaration (all 403), and a pending account
deletion (409). Re-auth only clears one of them. The 18+ declaration is asked
for the first time someone publishes and then resumes what they were doing.
**Ceilings where the data is edited.** The same gate now runs in the member
editor (privacy, never shareable, keep fronting private), system privacy, the
per-edge relationship visibility (new PATCH endpoints; group edges are never
gated, matching the server), and custom field and group privacy. A raise the
grace window has staged is shown as staged instead of as done.
The member PATCH body serializes nulls and the server rejects an explicit
null on never_shareable and fronting_private, so both are always sent with
their real value. Error bodies are parsed with Moshi rather than org.json,
which is only a stub off-device and would leave the classifier untested.
Safety was a top-level category holding three rows: System Safety, Sharing and Revision retention. All three describe the system rather than the app or the account, so they now sit in System after tags, custom fields and archived members, and the separate category is gone. The System row's subtitle names safety and sharing so they can still be found from the top level. What the top level loses is the auth tier summary the Safety row used to show; it is still on the System Safety row inside. Nothing else routed to the Safety category. The Home banners for pending deletions and pending exposures link straight to System Safety and are unaffected.
feat(settings): fold the Safety category into System
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #77, which adds the
profile_visibilitycategory and the pending-exposure models this builds on. Merge that first; this PR's diff is against it.The owner side of public profiles, ported from web. There is no native viewer: a shared link already renders in any mobile browser, so the app covers what the browser page cannot, which is managing what you share.
The Sharing screen
Settings > Safety > Sharing (the follow-up PR moves it into System). It lists:
/sharing/audit: one row per live grant with its view, link or public profile, expiry and note, with Rotate link and Revoke behind a menu. The curated member count and the served one are kept apart ("3 of 5 members shown"), and a roster that is off reads as off rather than as zero.When nothing is served at all,
profile_suppressedsays why (system not public, publishing blocked, account state).The entry is shown whatever the instance switch says. An owner must always be able to reach revoke, including after an operator turns publishing off; the screen explains that nothing new can be published instead of hiding the list.
Creating a link shows its token once, since nothing can read it back. Expiry is chosen at creation, from presets or a date picker, and a date means the end of that day on the user's own calendar. The API cannot move an expiry later, and the dialog says so. A date on or before the day a staged grant goes live is refused: that link would expire without ever having been readable.
A single view
served/not_served_reason(never shareable, archived, queued for deletion, private) instead of a client-side guess./share-views/{id}/preview, the same projection the public router uses, so it cannot show a page that would not really be served. A section that is not published reads as not published, which is different from served and empty.Step-up and staging
The client mirrors
visibility_step_up_requiredso the credential sheet can open before the round trip, and a server bounce still wins and reopens it, since a mirror can drift. The error detail separates the cases that need different answers, because re-auth only clears one of them:Password required/TOTP code requiredCeilings, where the data is edited
The same gate now runs in the member editor (privacy, never shareable, keep fronting private), system privacy, per-edge relationship visibility (new
PATCHendpoints; group edges are never gated, matching the server), and custom field and group privacy. A raise the grace window staged is shown as staged rather than as done.Worth knowing
never_shareableandfronting_private, so both are always sent with their real value.org.json.org.jsonis a stub off-device, which would have left the error classifier untested.Checked
assembleOpenDebugon this branch alone.