Show peer availability with stale markers and add Sharing settings
This commit is contained in:
55
frontend/p2p-core.js
Normal file
55
frontend/p2p-core.js
Normal file
@@ -0,0 +1,55 @@
|
||||
/* ============================================================================
|
||||
* p2p-core.js — pure helpers for peer-to-peer UI (window.P2PCore / node)
|
||||
*
|
||||
* formatAvailability(payload, now) turns GET /api/p2p/holders into the line
|
||||
* under the now-playing title, e.g.
|
||||
* "📡 On 3 devices · 1 online now · last checked 2d ago"
|
||||
* Holders are persistent (docs/p2p-architecture.md): they are never hidden
|
||||
* for age; when every holder is older than the server's staleDays the line
|
||||
* says so and is marked stale.
|
||||
* ========================================================================== */
|
||||
(function (root) {
|
||||
'use strict';
|
||||
|
||||
function ago(ms, now) {
|
||||
const s = Math.max(0, Math.round((now - ms) / 1000));
|
||||
if (s < 90) return 'just now';
|
||||
const m = Math.round(s / 60);
|
||||
if (m < 90) return m + 'm ago';
|
||||
const h = Math.round(m / 60);
|
||||
if (h < 48) return h + 'h ago';
|
||||
return Math.round(h / 24) + 'd ago';
|
||||
}
|
||||
|
||||
function formatAvailability(payload, now) {
|
||||
if (!payload || !payload.ok || !Array.isArray(payload.cids)) return null;
|
||||
const holders = [];
|
||||
for (const c of payload.cids) for (const h of c.holders || []) holders.push(h);
|
||||
if (!holders.length) return null;
|
||||
const online = holders.filter((h) => h.online).length;
|
||||
const fresh = holders.filter((h) => !h.stale).length;
|
||||
const newest = Math.max(...holders.map((h) => Number(h.lastVerifiedAt) || 0));
|
||||
const n = holders.length;
|
||||
const allStale = fresh === 0;
|
||||
const text = `📡 On ${n} device${n === 1 ? '' : 's'} · ${online ? online + ' online now' : 'none online'}`
|
||||
+ ` · last checked ${ago(newest, now)}` + (allStale ? ' (not checked recently)' : '');
|
||||
const title = holders.map((h) =>
|
||||
`${h.peer} · ${h.online ? 'online' : 'offline'} · checked ${ago(Number(h.lastVerifiedAt) || 0, now)}`
|
||||
+ `${h.stale ? ' (stale)' : ''}${h.trust === 'challenged' ? ' · spot-checked' : ''}`).join('\n');
|
||||
return { text, title, stale: allStale, online, holders: n };
|
||||
}
|
||||
|
||||
// Holders worth trying for a download: online first, then freshest check.
|
||||
function pickPeers(payload, cid) {
|
||||
if (!payload || !Array.isArray(payload.cids)) return [];
|
||||
const c = payload.cids.find((x) => x.cid === cid) || payload.cids[0];
|
||||
if (!c) return [];
|
||||
return (c.holders || []).filter((h) => h.online)
|
||||
.sort((a, b) => (b.trust === 'challenged') - (a.trust === 'challenged') || b.lastVerifiedAt - a.lastVerifiedAt)
|
||||
.map((h) => ({ peer: h.peer, cid: c.cid, size: c.size }));
|
||||
}
|
||||
|
||||
const P2PCore = { ago, formatAvailability, pickPeers };
|
||||
if (typeof module !== 'undefined' && module.exports) module.exports = P2PCore;
|
||||
else root.P2PCore = P2PCore;
|
||||
})(typeof globalThis !== 'undefined' ? globalThis : this);
|
||||
Reference in New Issue
Block a user