(tabName)
| 1133 | } |
| 1134 | |
| 1135 | async function syncMeshTabFromServer(config) { |
| 1136 | try { |
| 1137 | const cfg = config || await fetchAPI('/api/config'); |
| 1138 | if (cfg && Object.prototype.hasOwnProperty.call(cfg, MESH_TAB_KEY)) { |
| 1139 | localStorage.setItem(MESH_TAB_KEY, cfg[MESH_TAB_KEY] ? '1' : '0'); |
| 1140 | applyMeshTabVisibility(); |
| 1141 | } |
| 1142 | } catch (e) { /* offline — keep the localStorage value */ } |
| 1143 | } |
| 1144 | |
| 1145 | function onMeshTabToggled(cb) { |
| 1146 | localStorage.setItem(MESH_TAB_KEY, cb.checked ? '1' : '0'); |
| 1147 | applyMeshTabVisibility(); |
| 1148 | postAPI('/api/config', { [MESH_TAB_KEY]: cb.checked }) |
| 1149 | .catch(err => console.warn('Failed to persist Mesh tab visibility:', err)); |
| 1150 | if (cb.checked) showTab('mesh'); |
| 1151 | } |
| 1152 | window.onMeshTabToggled = onMeshTabToggled; |
| 1153 | |
| 1154 | // ==================== Web Terminal (xterm.js over Socket.IO) ==================== |
| 1155 | const TERMINAL_KEY = 'terminal_enabled'; |
| 1156 | let _term = null, _termFit = null, _termSocket = null, _termResizeHooked = false; |
| 1157 | |
| 1158 | function _terminalEnabled() { return localStorage.getItem(TERMINAL_KEY) === '1'; } |
| 1159 | |
| 1160 | function syncTerminalToggle() { |
| 1161 | const cb = document.getElementById('terminal-enabled'); |
| 1162 | if (cb) cb.checked = _terminalEnabled(); |
| 1163 | } |
| 1164 | |
| 1165 | function applyTerminalVisibility() { |
| 1166 | const enabled = _terminalEnabled(); |
| 1167 | document.querySelectorAll('.terminal-nav').forEach(btn => btn.classList.toggle('hidden', !enabled)); |
| 1168 | if (!enabled && typeof currentTab !== 'undefined' && currentTab === 'terminal') showTab('dashboard'); |
| 1169 | syncTerminalToggle(); |
| 1170 | } |
| 1171 | |
| 1172 | async function syncTerminalFromServer(config) { |
| 1173 | try { |
| 1174 | const cfg = config || await fetchAPI('/api/config'); |
| 1175 | if (cfg && Object.prototype.hasOwnProperty.call(cfg, TERMINAL_KEY)) { |
| 1176 | localStorage.setItem(TERMINAL_KEY, cfg[TERMINAL_KEY] ? '1' : '0'); |
| 1177 | applyTerminalVisibility(); |
| 1178 | } |
| 1179 | } catch (e) { /* offline — keep the localStorage value */ } |
| 1180 | } |
| 1181 | |
| 1182 | function onTerminalToggled(cb) { |
| 1183 | localStorage.setItem(TERMINAL_KEY, cb.checked ? '1' : '0'); |
| 1184 | applyTerminalVisibility(); |
| 1185 | postAPI('/api/config', { [TERMINAL_KEY]: cb.checked }) |
| 1186 | .then(() => addConsoleMessage(cb.checked ? 'Web terminal enabled' : 'Web terminal disabled', 'info')) |
| 1187 | .catch(err => { |
| 1188 | addConsoleMessage('Failed to toggle terminal: ' + err.message, 'error'); |
| 1189 | cb.checked = !cb.checked; |
| 1190 | localStorage.setItem(TERMINAL_KEY, cb.checked ? '1' : '0'); |
| 1191 | applyTerminalVisibility(); |
no test coverage detected