Files
2026-06-30 13:10:35 +07:00

179 lines
4.7 KiB
JavaScript

/**
* Single BackOne core network for all addons (same as backone-cli listnetworks/join).
*/
window.BackOneNetworkSession = (function () {
const NETWORK_KEY = 'backone.lastNetworkId';
const PEER_KEY = 'backone.lastPeerId';
let activeNetwork = null;
let selectedPeer = null;
let coreStatus = { online: false, address: '', networkCount: 0, leafPeerCount: 0, authenticated: false };
const listeners = new Set();
function emit() {
const snap = {
network: activeNetwork,
networkId: getNetworkId(),
peer: selectedPeer,
core: { ...coreStatus }
};
listeners.forEach(fn => {
try { fn(snap); } catch (_) { /* ignore */ }
});
}
function getNetworkId() {
return (localStorage.getItem(NETWORK_KEY) || '').toLowerCase();
}
function setNetworkId(id) {
const nwid = BackOnePeerDirectory.normalizeNetworkId(id);
if (nwid) {
localStorage.setItem(NETWORK_KEY, nwid);
} else {
localStorage.removeItem(NETWORK_KEY);
}
BackOnePeerDirectory.setLastNetworkId(nwid);
return nwid;
}
function getSelectedPeerId() {
return (localStorage.getItem(PEER_KEY) || '').toLowerCase();
}
function setSelectedPeer(peer) {
selectedPeer = peer || null;
if (peer && peer.peerId) {
localStorage.setItem(PEER_KEY, peer.peerId);
} else {
localStorage.removeItem(PEER_KEY);
}
emit();
}
function pickDefaultNetworkId(networks) {
if (!networks.length) return '';
const stored = getNetworkId();
if (stored && networks.some(n => (n.id || '').toLowerCase() === stored)) {
return stored;
}
const preferred = networks.find(n => n.status === 'OK')
|| networks.find(n => n.status === 'REQUESTING_CONFIGURATION')
|| networks[0];
return preferred ? (preferred.id || '').toLowerCase() : '';
}
/**
* On app start: read BackOne core state (same as backone-cli info / listnetworks / peers).
*/
async function syncFromCore() {
const token = await BackOneAuth.getToken();
const [status, networks, cliPeers] = await Promise.all([
BackOnePeerDirectory.loadCoreStatus(),
BackOnePeerDirectory.loadNetworks(),
BackOnePeerDirectory.loadCliPeers()
]);
coreStatus = {
online: !!(status && status.online),
address: (status && status.address) || '',
version: (status && status.version) || '',
networkCount: networks.length,
leafPeerCount: BackOnePeerDirectory.countLeafPeers(cliPeers),
authenticated: !!token
};
const pick = pickDefaultNetworkId(networks);
if (pick) {
setNetworkId(pick);
activeNetwork = networks.find(n => (n.id || '').toLowerCase() === pick)
|| await BackOnePeerDirectory.loadNetwork(pick);
} else {
setNetworkId('');
activeNetwork = null;
}
emit();
return { coreStatus, activeNetwork, networks };
}
async function refresh() {
const id = getNetworkId();
if (!id) {
activeNetwork = null;
emit();
return null;
}
activeNetwork = await BackOnePeerDirectory.loadNetwork(id);
if (!activeNetwork) {
activeNetwork = { id, name: id, status: 'UNKNOWN' };
}
emit();
return activeNetwork;
}
async function loadNetworks() {
return BackOnePeerDirectory.loadNetworks();
}
async function selectNetwork(nwid) {
const id = setNetworkId(nwid);
if (!id) {
await refresh();
return null;
}
return refresh();
}
async function joinNetwork(nwid) {
const id = BackOnePeerDirectory.normalizeNetworkId(nwid);
if (!id) throw new Error('Network ID must be 16 hexadecimal characters');
await BackOnePeerDirectory.joinNetwork(id);
return syncFromCore();
}
async function leaveNetwork(nwid) {
const id = BackOnePeerDirectory.normalizeNetworkId(nwid || getNetworkId());
if (!id) throw new Error('No network selected');
await BackOnePeerDirectory.leaveNetwork(id);
if (getNetworkId() === id) {
setNetworkId('');
selectedPeer = null;
localStorage.removeItem(PEER_KEY);
}
return syncFromCore();
}
function subscribe(fn) {
listeners.add(fn);
return () => listeners.delete(fn);
}
function requireNetworkId() {
const id = getNetworkId();
if (!id) throw new Error('Join a BackOne network first (same as backone-cli join)');
return id;
}
function getCoreStatus() {
return { ...coreStatus };
}
return {
getNetworkId,
getActiveNetwork: () => activeNetwork,
getCoreStatus,
getSelectedPeer: () => selectedPeer,
getSelectedPeerId,
setSelectedPeer,
selectNetwork,
joinNetwork,
leaveNetwork,
loadNetworks,
syncFromCore,
refresh,
subscribe,
requireNetworkId
};
})();