fix(federation,cloud): dedup trusted nodes + chat contacts by onion; guard cloud my-folders (B1,B2,B4)
B1/B2: the same physical node can linger in the federation list under two dids (e.g. after a did/key change). An onion is a node's unique stable identity, so two entries with the same onion are one node. This showed the node twice in the trusted-node list (B1) and as two mesh chat contacts — one by name+logo, one by raw did (B2). - storage::load_nodes now collapses same-onion entries (keep first, merge fips_npub/name/last_state) so every consumer (list + chat seed + sync) sees one entry per node. - federation::sync merge_transitive_peers also matches by onion (not just did) so new transitive hints don't re-add a known node under a new did. - mesh::seed_federation_peers_into_mesh skips already-seeded onions (belt and suspenders). - Unit tests for dedup_nodes_by_onion (collapse + onion-suffix handling). B4: filebrowser-client.listDirectory only checked res.ok before res.json(), so when File Browser is absent (nginx serves the SPA index.html, 200) or down (502) the JSON parse threw the opaque "Unexpected token '<'". Now it checks the content-type and throws a friendly "File Browser is not available" the Cloud view already renders as an empty state. Verified: dedup unit tests 2/2; live .198 (15 entries→13 distinct onions) restarted healthy on new binary; B4 guard present in built bundle + deployed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
1db720af13
commit
ed4931064b
@@ -102,7 +102,15 @@ class FileBrowserClient {
|
||||
const res = await fetch(`${this.baseUrl}/api/resources${safePath}`, {
|
||||
headers: this.headers(),
|
||||
})
|
||||
if (!res.ok) throw new Error(`Failed to list directory: ${res.status}`)
|
||||
if (!res.ok) throw new Error(`File Browser is not available (HTTP ${res.status})`)
|
||||
// When File Browser isn't installed, nginx falls through to the SPA and
|
||||
// returns index.html (200, text/html); when it's down it returns 502.
|
||||
// Either way res.json() would throw the opaque "Unexpected token '<'"
|
||||
// error, so detect a non-JSON body and surface a friendly message instead.
|
||||
const contentType = res.headers.get('content-type') || ''
|
||||
if (!contentType.includes('application/json')) {
|
||||
throw new Error('File Browser is not available — install or start the File Browser app to use your folders')
|
||||
}
|
||||
const data: FileBrowserListResponse = await res.json()
|
||||
return (data.items || []).map((item) => ({
|
||||
...item,
|
||||
|
||||
Reference in New Issue
Block a user