From 926ebce735afd01800a669a266b90fc98f673a6b Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Mon, 24 Aug 2026 23:35:09 +0200 Subject: fix(hub): make root-folder save success/failure actually visible Flagged directly: "Saving" ran for a few seconds then just stopped, with nothing telling the operator whether it had worked. Both outcomes used the same dim .settings-hint styling, so a real failure and a real success looked identical at a glance. Success and failure are now tracked separately (previously one plain string held either) and rendered with the same success-msg/error-msg styling already used elsewhere on this page, so which one happened is unambiguous. --- .../src/meshbay_hub/static/group-settings.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/packages/meshbay-hub/src/meshbay_hub/static/group-settings.js b/packages/meshbay-hub/src/meshbay_hub/static/group-settings.js index 858d672..34f94f9 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/group-settings.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/group-settings.js @@ -95,7 +95,8 @@ function RootFolderRow({ disabled=${busy || draft === (value || '')} onClick=${onSave}> ${busy ? t('settings_node.scan_saving') : t(saveKey)} - ${msg && html`

${msg}

`} + ${msg && html`

+ ${msg.text}

`} `; } @@ -534,7 +535,7 @@ function GroupSettingsPanel({ groupId, group, token, transportRef, gekRef, const [videoRootDraft, setVideoRootDraft] = useState(videoRoot || ''); useEffect(() => { setVideoRootDraft(videoRoot || ''); }, [videoRoot]); const [videoRootBusy, setVideoRootBusy] = useState(false); - const [videoRootMsg, setVideoRootMsg] = useState(''); + const [videoRootMsg, setVideoRootMsg] = useState(null); /** * Which folder is the Videos app's entry point for this group — same @@ -552,7 +553,7 @@ function GroupSettingsPanel({ groupId, group, token, transportRef, gekRef, if (next === current) return; if (current && !confirm(t('settings_node.video_root_change_confirm'))) return; const transport = transportRef && transportRef.current; - setVideoRootMsg(''); + setVideoRootMsg(null); setVideoRootBusy(true); try { if (!transport || !transport.connected) { @@ -564,9 +565,9 @@ function GroupSettingsPanel({ groupId, group, token, transportRef, gekRef, : null; await transport.setVideoRoot(next, signFn); if (onVideoRoot) onVideoRoot(next); - setVideoRootMsg(t('settings_node.scan_saved')); + setVideoRootMsg({ text: t('settings_node.scan_saved'), ok: true }); } catch (err) { - setVideoRootMsg(err.message); + setVideoRootMsg({ text: err.message, ok: false }); } finally { setVideoRootBusy(false); } @@ -577,7 +578,7 @@ function GroupSettingsPanel({ groupId, group, token, transportRef, gekRef, const [audioRootDraft, setAudioRootDraft] = useState(audioRoot || ''); useEffect(() => { setAudioRootDraft(audioRoot || ''); }, [audioRoot]); const [audioRootBusy, setAudioRootBusy] = useState(false); - const [audioRootMsg, setAudioRootMsg] = useState(''); + const [audioRootMsg, setAudioRootMsg] = useState(null); const saveAudioRoot = useCallback(async () => { const next = audioRootDraft; @@ -585,7 +586,7 @@ function GroupSettingsPanel({ groupId, group, token, transportRef, gekRef, if (next === current) return; if (current && !confirm(t('settings_node.audio_root_change_confirm'))) return; const transport = transportRef && transportRef.current; - setAudioRootMsg(''); + setAudioRootMsg(null); setAudioRootBusy(true); try { if (!transport || !transport.connected) { @@ -597,9 +598,9 @@ function GroupSettingsPanel({ groupId, group, token, transportRef, gekRef, : null; await transport.setAudioRoot(next, signFn); if (onAudioRoot) onAudioRoot(next); - setAudioRootMsg(t('settings_node.scan_saved')); + setAudioRootMsg({ text: t('settings_node.scan_saved'), ok: true }); } catch (err) { - setAudioRootMsg(err.message); + setAudioRootMsg({ text: err.message, ok: false }); } finally { setAudioRootBusy(false); } -- cgit v1.2.3