From 1f8a52484412b48205e5ff6aac506428e2fb77ed Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Sat, 29 Aug 2026 18:42:43 +0200 Subject: feat(node): editable node settings in the Node page (D5) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Expose invite_ttl_hours, pair_ttl_hours, device_request_ttl_minutes, max_concurrent_streams and transcode_incompatible_video in the Node management panel. Changes are applied immediately via roster.db and written back to node.toml so they survive a DB wipe. On startup, roster overrides take precedence over node.toml defaults. Draft v6 ยง2.11 documents the design; MNP gains node_settings_set / node_settings_set_ack for the browser path. Co-Authored-By: Claude Opus 4.6 --- packages/meshbay-hub/src/meshbay_hub/static/app.js | 77 ++++++++++++++++++++++ 1 file changed, 77 insertions(+) (limited to 'packages/meshbay-hub/src/meshbay_hub/static/app.js') diff --git a/packages/meshbay-hub/src/meshbay_hub/static/app.js b/packages/meshbay-hub/src/meshbay_hub/static/app.js index 4aab150..c31653a 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/app.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/app.js @@ -2373,6 +2373,9 @@ function NodePage({ token, username, userId, groups }) { const [rosterGroup, setRosterGroup] = useState(''); const [denylist, setDenylist] = useState(null); const [showDenylist, setShowDenylist] = useState(false); + const [nodeSettings, setNodeSettings] = useState(null); + const [editSettings, setEditSettings] = useState(null); + const [savingSettings, setSavingSettings] = useState(false); const [attachGroup_, setAttachGroup_] = useState(''); const [attachDir, setAttachDir] = useState(''); const [attachUpload, setAttachUpload] = useState(''); @@ -2434,6 +2437,7 @@ function NodePage({ token, username, userId, groups }) { transportRef.current = transport; setNodeGroups(result.groups || []); setOperatorPaired(!!result.operator_paired); + setNodeSettings(result.settings || null); setStatus('connected'); return; } catch (err) { @@ -2460,6 +2464,10 @@ function NodePage({ token, username, userId, groups }) { }; }, [connectAndFetch]); + useEffect(() => { + if (nodeSettings && !editSettings) setEditSettings({ ...nodeSettings }); + }, [nodeSettings]); + const refresh = useCallback(async () => { const transport = transportRef.current; if (!transport || !transport.connected) return; @@ -2467,6 +2475,7 @@ function NodePage({ token, username, userId, groups }) { const result = await transport.fetchNodeStatus(); setNodeGroups(result.groups || []); setOperatorPaired(!!result.operator_paired); + setNodeSettings(result.settings || null); } catch {} }, []); @@ -2673,6 +2682,22 @@ function NodePage({ token, username, userId, groups }) { } }, [refresh]); + const saveSettings = useCallback(async () => { + const transport = transportRef.current; + if (!transport || !transport.connected || !editSettings) return; + setSavingSettings(true); + setActionMsg(''); + try { + await transport.updateNodeSettings(editSettings); + setNodeSettings({ ...editSettings }); + setActionMsg(t('node.settings_saved')); + } catch (err) { + setActionMsg(err.message); + } finally { + setSavingSettings(false); + } + }, [editSettings]); + if (status === 'idle' || status === 'connecting') { return html`

${t('node.title')}

@@ -2888,6 +2913,58 @@ function NodePage({ token, username, userId, groups }) { `}
+ ${editSettings && html` +
+ ${t('node.settings')} +

${t('node.settings_edit_hint')}

+
+ + + + + +
+
+ +
+
+ `} + ${/* In Electron, the Create Group wizard handles attaching. Keep for browser users who manage nodes via MNP. */ !platform.node.available && (() => { -- cgit v1.2.3