edit wifi networks in webui (upstream #1743 by osteotek)

This commit is contained in:
jpirnay
2026-04-25 12:10:38 +02:00
parent 7f6cb65344
commit c1e51ac8a2
4 changed files with 281 additions and 4 deletions
+117 -2
View File
@@ -314,7 +314,8 @@
<div class="save-container" id="save-container" style="display:none;">
<button class="save-btn" id="saveBtn" onclick="saveSettings()">Save Settings</button>
</div>
<div id="wifi-container"></div>
<div id="opds-container"></div>
<div class="card">
@@ -504,6 +505,119 @@
loadSettings();
// --- Wi-Fi Network Management ---
// Renders an editable list of saved Wi-Fi networks using /api/wifi endpoints.
// Password fields are never pre-filled; when left blank during edit, existing
// passwords remain unchanged server-side.
let wifiNetworks = [];
function renderWifiNetwork(net, idx) {
const isNew = idx === -1;
const id = isNew ? 'new' : idx;
const lastConnected = net.isLastConnected
? '<div style="margin-top:8px;color:var(--label-color);font-size:0.9em;">Last connected network</div>'
: '';
return '<div class="opds-server" id="wifi-' + id + '">' +
'<div class="setting-row">' +
'<span class="setting-name">SSID</span>' +
'<span class="setting-control"><input type="text" id="wifi-ssid-' + id + '" value="' + escapeHtml(net.ssid || '') + '"></span>' +
'</div>' +
'<div class="setting-row">' +
'<span class="setting-name">Password</span>' +
'<span class="setting-control"><input type="password" id="wifi-pass-' + id + '" placeholder="' + (net.hasPassword ? '(unchanged)' : '') + '"></span>' +
'</div>' +
lastConnected +
'<div class="opds-actions">' +
'<button class="btn-small btn-save-server" onclick="saveWifiNetwork(' + idx + ')">Save</button>' +
(isNew ? '' : '<button class="btn-small btn-delete" onclick="deleteWifiNetwork(' + idx + ')">Delete</button>') +
'</div>' +
'</div>';
}
function renderWifiSection() {
const container = document.getElementById('wifi-container');
let html = '<div class="card"><h2>Wi-Fi Networks</h2>';
if (wifiNetworks.length === 0) {
html += '<p style="color:var(--label-color);text-align:center;">No Wi-Fi networks saved</p>';
} else {
wifiNetworks.forEach(function(net, idx) {
html += renderWifiNetwork(net, idx);
});
}
html += '<div style="margin-top:12px;text-align:center;">' +
'<button class="btn-small btn-add" onclick="addWifiNetwork()">+ Add Network</button>' +
'</div></div>';
container.innerHTML = html;
}
async function loadWifiNetworks() {
try {
const resp = await fetch('/api/wifi');
if (!resp.ok) throw new Error('Failed to load');
wifiNetworks = await resp.json();
renderWifiSection();
} catch (e) {
console.error('Wi-Fi load error:', e);
}
}
function addWifiNetwork() {
const container = document.getElementById('wifi-container');
const card = container.querySelector('.card');
const addBtn = card.querySelector('.btn-add').parentElement;
// Prevent multiple unsaved new-network forms at once (idx -1 -> id "new")
if (document.getElementById('wifi-new')) return;
addBtn.insertAdjacentHTML('beforebegin', renderWifiNetwork({ssid:'',hasPassword:false,isLastConnected:false}, -1));
}
async function saveWifiNetwork(idx) {
const id = idx === -1 ? 'new' : idx;
const ssid = document.getElementById('wifi-ssid-' + id).value.trim();
if (!ssid) {
showMessage('SSID is required.', true);
return;
}
const data = { ssid: ssid };
// Only include password when the user actually typed something; omitting it
// tells the server to preserve an existing password.
const pass = document.getElementById('wifi-pass-' + id).value;
if (pass) data.password = pass;
if (idx >= 0) data.index = idx;
try {
const resp = await fetch('/api/wifi', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(data)
});
if (!resp.ok) throw new Error(await resp.text());
showMessage('Wi-Fi network saved!', false);
await loadWifiNetworks();
} catch (e) {
showMessage('Error: ' + e.message, true);
}
}
async function deleteWifiNetwork(idx) {
if (!confirm('Delete this Wi-Fi network?')) return;
try {
const resp = await fetch('/api/wifi/delete', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({index: idx})
});
if (!resp.ok) throw new Error(await resp.text());
showMessage('Wi-Fi network deleted', false);
await loadWifiNetworks();
} catch (e) {
showMessage('Error: ' + e.message, true);
}
}
// --- OPDS Server Management ---
// Dynamically renders an editable list of OPDS servers, communicating with the
// /api/opds REST endpoints. Password fields are never pre-filled for security;
@@ -622,7 +736,8 @@
showMessage('Error: ' + e.message, true);
}
}
loadWifiNetworks();
loadOpdsServers();
</script>
</body>