fix(desktop): identify a community's relay the way its storage does - #6068
fix(desktop): identify a community's relay the way its storage does#6068Chessing234 wants to merge 3 commits into
Conversation
Adding or editing a community compared relay URLs with ===, while every per-relay storage slot is keyed through normalizeRelayUrl (trim, strip trailing slashes, lowercase). So wss://relay.example and wss://relay.example/ were two communities that shared one set of keys: self profile, read state, channel sections, sort preference, sidebar watermark, thread activity, observed unread — all of it. The second community therefore never got its own data. Admitting it did not separate the two; it hid that they were one. Both seams now go through isSameRelay, which is normalizeRelayUrl on both sides — the same function the keys use, rather than a second notion of sameness invented next to it. addCommunity folds an equivalent spelling into the existing community as it already did for an exact match, and an edit onto another community's relay is rejected as the duplicate it is. Re-spelling your *own* relay stays an ordinary update, reinit included: the connection URL really did change. Signed-off-by: Taksh <takshkothari09@gmail.com>
Five cases. The identity tests assert the collision they rest on rather than assuming it — each spelling is checked through selfProfileStorage.storageKey as well as isSameRelay, so the premise cannot rot silently. Also covers the two directions that must not change: ws:// vs wss:// stay different relays, and re-spelling your own relay is still an update with reinit, not a duplicate of yourself. Reverting the comparison turns the two duplicate cases red. Signed-off-by: Taksh <takshkothari09@gmail.com>
themiguelamador
left a comment
There was a problem hiding this comment.
I found one P1 rollback bug in the new relay-identity behavior.
addCommunity now folds a storage-equivalent URL spelling into the existing community, but handleCommunityOnboardingConnect still computed relayAlreadyExists with raw string equality. For an existing wss://relay.example community and a transaction using WSS://Relay.Example/, the add returns the existing ID while the transaction records addedCommunity: true. If the user cancels, onboarding then treats that pre-existing community as temporary: it can remove it, or call clearCommunities() when it is the only community.
I fixed this on Complear/buzz branch review/pr-6068-fix (commit 667ed970d) by centralizing the community-list identity check in hasCommunityForRelay, using it for the cancellation bookkeeping, documenting why the rollback flag must match addCommunity, and adding focused equivalent/different-relay coverage.
Validation:
- Focused relay-identity tests: 15 passed
- Full Desktop suite: 4,960 passed
pnpm typecheck: passedpnpm check: passed with the same 2 warnings and 2 infos already present on the PR- Formatting and
git diff --check: passed
Review finding (P1, themiguelamador on block#6068): `addCommunity` now folds a storage-equivalent relay spelling into the existing community, but `handleCommunityOnboardingConnect` still computed `relayAlreadyExists` with raw string equality. Connecting `WSS://Relay.Example/` while `wss://relay.example` already exists therefore returned the existing id and still recorded `addedCommunity: true`; cancelling then treated a pre-existing community as temporary and removed it, or called `clearCommunities()` when it was the only one. Centralize the list-level check in `hasCommunityForRelay`, next to the `isSameRelay` predicate `addCommunity` matches on, and read the rollback flag from it. The doc comment records why the two must stay in lockstep. Added coverage for equivalent spellings, genuinely different relays, and agreement with `addCommunity`'s own match. Signed-off-by: Taksh <takshkothari09@gmail.com>
|
Confirmed and fixed in You're right on both the defect and the consequence. The list-level check is now Verification: desktop typecheck, biome on the touched files, and the full desktop suite (4,962 passed). |
Adding or editing a community compares relay URLs with
===, while every per-relay storage slot is keyed throughnormalizeRelayUrl(trim, strip trailing slashes, lowercase). The two notions of "same relay" disagree, and the storage one wins.Probed against the real helper:
So
wss://relay.exampleandwss://relay.example/are two communities in the sidebar sharing one set of keys: self profile, read state, channel sections, sort preference, sidebar watermark, thread activity, observed unread. The second community never gets its own data — admitting it does not separate the two, it hides that they are one. Add-by-invite, add-by-paste and the edit form can all produce the second spelling, andcommunityStorage.normalizeRelayUrl(a different function with the same name) prefixeswss://without trimming or stripping, so it is reachable without the user doing anything odd.The fix is to reuse the storage function, not to invent a third notion of sameness.
isSameRelayisnormalizeRelayUrlon both sides, and both seams go through it:addCommunityfolds an equivalent spelling into the existing community, exactly as it already did for an exact match;resolveCommunityUpdateResultreturnsduplicate-relayfor an edit onto another community's relay in any equivalent spelling.Re-spelling your own relay stays an ordinary update, reinit included — the connection URL really did change, and it is not a duplicate of itself. There is a test for that, because it is the case a careless fix breaks.
Tests — 5 new. The identity cases assert the collision they rest on rather than assuming it: each spelling is checked through
selfProfileStorage.storageKeyas well asisSameRelay, so if the key function ever stops colliding, the test says so instead of quietly passing. Also covered:ws://vswss://stay different relays. Reverting the comparison turns the two duplicate cases red.Not changed, deliberately. The stored
relayUrlkeeps whatever spelling the user typed — this is about identity, not canonicalising what is displayed and connected to. AndnormalizeRelayUrllowercases the whole URL including the path, so two relays differing only by path case would be folded together; that is pre-existing and already true of the storage keys, so it is not something this change introduces or should fix on its own.Verified locally in
desktop/:pnpm typecheck,pnpm check(2 warnings + 2 infos, all pre-existing on main),pnpm test4959 passed,git diff --check.