Add option to change app-specific profile #160
Labels
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Grandiras/Ponente#160
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Right now, a profile change on Ponente also affects other apps like Bluesky. Add the possibility to only change the profile on Ponente.
🤖 On it — follow along in the action run; the reply will link the full session transcript.
📜 Live transcript — updating every ~5 minutes while the task runs.
Pushed
claude/issue-160. Unit suite green (395/395), and the profile e2e spec passes against a live app.What changed
/profilenow asks where a change applies before it applies it — per save, with the Atmosphere profile still the default:Picking Ponente only writes Ponente's own
Membersrow and stops there: no token, no scope, noapp.bsky.actor.profilerecord, nothing sent to the member's account. Two consequences worth knowing:AtProto:ProfileScope=none, and for a member who signed in before this app started asking. That is why "sign in once more" now sits under a disabled option instead of replacing the whole form; a name for Ponente alone was never gated on a grant it does not use.Member.UsesLocalProfilemarks whose answer the name and picture are, andMemberService.RefreshProfileAsync, the startup backfill and/dev/login/{did}all check it before overwriting. Without that guard the first profile lookup after the save would quietly put the network's name back.It reuses the same two columns rather than adding a second pair, so every screen that draws a face (card tile, comment, assignee picker, nav header, admin list) keeps reading what it always read — the change is confined to the writers, which is the short list above.
The picture is the part that needed new storage: a network avatar is a blob in a repository that already exists, this one has nowhere to live. New
MemberAvatartable — encrypted through abyte[]converter (the first caller ofIDataEncryptor.EncryptBytes), deliberately with no navigation property, so a megabyte of image can never ride along on a member read via anInclude— served byGET /avatar/{did}behind the allowlist, at a URL carrying a random version that changes with the picture.The way back is the button that used to say "refresh from the network": for a member holding a local profile it reads "Use my Atmosphere profile", because for them fetching what the account says and adopting it are the same act. Saving to the network is the other way back, and both delete the stored picture.
Also generalised the board-access option cards (
.access-choice/.access-option) into.choice-list/.choice-option— the profile page is the second thing that needs that shape, and duplicating 30 lines of CSS was the alternative.Verified
dotnet build/dotnet test Ponente.sln— 395 passed.profile.spec.js4/4, plusboard.spec.js,i18n.spec.js,prefs.spec.js,changelog.spec.js(32/32) andaccess.spec.jsfor the class rename — its two failures there are the PDS-signup tests, and no container runtime exists in this job to run the PDS.profile.spec.jsnow reaches a save end to end, which it never could before: it sets a Ponente-only name and picture, asserts the preview points at/avatar/{did}?v=…, fetches that URL back (200,image/png), and checks both survive the next sign-in. That also pins the route literal inProgram.csagainstAvatarStore.Route.NotifyProfileChangedfires on this path too.Changelog entry added in both locales;
docs/auth.md(new "the profile that stays here" section),docs/data.mdanddocs/orientation.mdupdated in the same commit. Writing the network profile still needs a real OAuth grant and remains a manual check, as it was before.⏱ 20m 44s · 135 turns · tokens: 199.3k in / 74.6k out (+18703.2k cache-read)
📜 Full session transcript
→ Opened PR: #161