()
| 1087 | } |
| 1088 | |
| 1089 | // Seed the local cache from the server config so a save on any device shows up |
| 1090 | // here. Accepts an already-fetched config to avoid an extra round-trip; fetches |
| 1091 | // one itself otherwise. Server wins when the key is present. |
| 1092 | async function syncRusenseTabFromServer(config) { |
| 1093 | try { |
| 1094 | const cfg = config || await fetchAPI('/api/config'); |
| 1095 | if (cfg && Object.prototype.hasOwnProperty.call(cfg, RUSENSE_TAB_KEY)) { |
| 1096 | localStorage.setItem(RUSENSE_TAB_KEY, cfg[RUSENSE_TAB_KEY] ? '1' : '0'); |
| 1097 | applyRusenseTabVisibility(); |
| 1098 | } |
| 1099 | } catch (e) { /* offline — keep the localStorage value */ } |
| 1100 | } |
| 1101 | |
| 1102 | function onRusenseTabToggled(cb) { |
| 1103 | localStorage.setItem(RUSENSE_TAB_KEY, cb.checked ? '1' : '0'); |
| 1104 | applyRusenseTabVisibility(); |
| 1105 | // Persist server-side so it's shared/persistent for everyone, not just here. |
| 1106 | postAPI('/api/config', { [RUSENSE_TAB_KEY]: cb.checked }) |
| 1107 | .catch(err => console.warn('Failed to persist RuSense tab visibility:', err)); |
| 1108 | if (cb.checked) showTab('rusense'); |
| 1109 | } |
| 1110 | |
| 1111 | // ── Ragnar Mesh tab visibility (toggle in Settings; ON by default) ────────── |
| 1112 | // Same server-backed + localStorage-cache pattern as the RuSense tab, but the |
| 1113 | // default is VISIBLE: absent the key the tab shows, and only an explicit '0' |
| 1114 | // hides it. Hiding is cosmetic — it never joins or leaves the mesh (that is |
| 1115 | // mesh_enabled); it only removes the nav entry. |
| 1116 | const MESH_TAB_KEY = 'mesh_tab_enabled'; |
| 1117 | |
| 1118 | function _meshTabVisible() { |
| 1119 | return localStorage.getItem(MESH_TAB_KEY) !== '0'; // default on |
| 1120 | } |
| 1121 | |
| 1122 | function syncMeshTabToggle() { |
| 1123 | const cb = document.getElementById('mesh-tab-enabled'); |
| 1124 | if (cb) cb.checked = _meshTabVisible(); |
| 1125 | } |
| 1126 | |
| 1127 | function applyMeshTabVisibility() { |
| 1128 | const visible = _meshTabVisible(); |
| 1129 | document.querySelectorAll('.mesh-nav').forEach(btn => btn.classList.toggle('hidden', !visible)); |
| 1130 | // If the tab is hidden while it's the active one, fall back to the dashboard. |
| 1131 | if (!visible && typeof currentTab !== 'undefined' && currentTab === 'mesh') showTab('dashboard'); |
| 1132 | syncMeshTabToggle(); |
| 1133 | } |
| 1134 | |
| 1135 | async function syncMeshTabFromServer(config) { |
| 1136 | try { |
no test coverage detected