Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions extension/background/routes/dweb.js
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,22 @@ export const makeDwebRoutes = (deps) => {
await ensureOffscreen();
return browser.runtime.sendMessage({ type: 'dweb/base-host/start' });
},
// The master OFF — the user-facing kill switch, symmetric to start
// (docs/specs/FEATURE-FIRST-CLASS-MESSAGING.md §2). Persist the preference
// FIRST so it won't auto-restart on the next unlock (maybeStartBaseNetwork
// gates on dwebEnabled), then tear down a live host. NOT gated on dwebOn():
// we must be able to stop precisely as we flip the setting off. Gated only on
// DWEB_ENABLED — the store package prunes this module entirely.
'dweb/base/stop': async () => {
if (!DWEB_ENABLED) return { ok: false, error: 'dweb-disabled' };
await settingsStore.update({ dwebEnabled: false });
// Never SPAWN the offscreen just to stop it: if it isn't up, there is no
// live network to tear down. The offscreen stop handler closes every room,
// drops the mesh + lobby, and clears the re-sub timer (dweb-base.js).
const contexts = await browser.runtime.getContexts({ contextTypes: /** @type {any} */ (['OFFSCREEN_DOCUMENT']) });
if (contexts.length) await browser.runtime.sendMessage({ type: 'dweb/base-host/stop' });
return { ok: true, running: false };
},
'dweb/base/status': async () => {
if (!dwebOn()) return { ok: false, error: 'dweb-disabled' };
await ensureOffscreen();
Expand Down
20 changes: 20 additions & 0 deletions extension/home/network-section.js
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ export const NetworkSection = () => {
/** @type {string | null} */
let error = null;
let starting = false;
let stopping = false;
/** @type {ReturnType<typeof setInterval> | number} */
let timer = 0;
let dead = false; // set on unmount — an in-flight poll must not redraw
Expand All @@ -406,6 +407,17 @@ export const NetworkSection = () => {
await refresh(send);
};

/** The kill switch: shut down ALL dweb networking + persist it off. @param {Send} send */
const stop = async (send) => {
// Destructive — drops every live connection — so confirm before the kill.
if (typeof confirm === 'function'
&& !confirm('Shut down all peer-to-peer networking? This drops every live connection and keeps it off (it won’t come back on unlock) until you start it again.')) return;
stopping = true; if (!dead) m.redraw();
try { await send({ type: 'dweb/base/stop' }); } catch (e) { error = /** @type {{ message?: string }} */ (e)?.message || String(e); }
stopping = false;
await refresh(send);
};

return {
/** @param {{ attrs: { send: Send } }} vnode */
oninit(vnode) { refresh(vnode.attrs.send); },
Expand Down Expand Up @@ -460,6 +472,14 @@ export const NetworkSection = () => {
m('span.peerd-net-path', { class: `peerd-net-path--${pi.kind}` }, pi.label),
]);
})),
// Kill switch — symmetric to "Start the network" in the offline view.
// Drops every live connection and persists dweb off (won't auto-restart
// on unlock) — docs/specs/FEATURE-FIRST-CLASS-MESSAGING.md §2.
m('button.peerd-net-btn', {
disabled: stopping,
style: 'margin-top:10px; font-size:12px; opacity:.75;',
onclick: () => stop(send),
}, stopping ? 'Stopping…' : 'Stop the network'),
]);
},
};
Expand Down