1
0
mirror of https://github.com/KubaPro010/fm-dx-webserver.git synced 2026-02-26 22:13:53 +01:00

bugfixes, accessibility settings

This commit is contained in:
NoobishSVK
2024-05-20 21:43:56 +02:00
parent 42c528a480
commit 2314ba5d2a
14 changed files with 110 additions and 87 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "fm-dx-webserver", "name": "fm-dx-webserver",
"version": "1.2.1", "version": "1.2.2",
"description": "FM DX Webserver", "description": "FM DX Webserver",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {

View File

@@ -160,6 +160,7 @@ router.get('/logout', (req, res) => {
router.get('/kick', (req, res) => { router.get('/kick', (req, res) => {
const ipAddress = req.query.ip; // Extract the IP address parameter from the query string const ipAddress = req.query.ip; // Extract the IP address parameter from the query string
// Terminate the WebSocket connection for the specified IP address // Terminate the WebSocket connection for the specified IP address
console.log(ipAddress);
if(req.session.isAdminAuthenticated) { if(req.session.isAdminAuthenticated) {
helpers.kickClient(ipAddress); helpers.kickClient(ipAddress);
} }

View File

@@ -84,6 +84,7 @@ function resolveDataBuffer(data, wss) {
function kickClient(ipAddress) { function kickClient(ipAddress) {
// Find the entry in connectedClients associated with the provided IP address // Find the entry in connectedClients associated with the provided IP address
const targetClient = storage.connectedUsers.find(client => client.ip === ipAddress); const targetClient = storage.connectedUsers.find(client => client.ip === ipAddress);
console.log(storage.connectedUsers);
if (targetClient && targetClient.instance) { if (targetClient && targetClient.instance) {
// Send a termination message to the client // Send a termination message to the client
targetClient.instance.send('KICK'); targetClient.instance.send('KICK');

View File

@@ -259,7 +259,7 @@ wss.on('connection', (ws, request) => {
logInfo(`Web client \x1b[32mconnected\x1b[0m (${clientIp}) \x1b[90m[${currentUsers}]\x1b[0m`); logInfo(`Web client \x1b[32mconnected\x1b[0m (${clientIp}) \x1b[90m[${currentUsers}]\x1b[0m`);
} else { } else {
const userLocation = `${locationInfo.city}, ${locationInfo.region}, ${locationInfo.country}`; const userLocation = `${locationInfo.city}, ${locationInfo.region}, ${locationInfo.country}`;
const userData = { ip: clientIp, location: userLocation, time: connectionTime }; const userData = { ip: clientIp, location: userLocation, time: connectionTime, instance: ws };
storage.connectedUsers.push(userData); storage.connectedUsers.push(userData);
logInfo(`Web client \x1b[32mconnected\x1b[0m (${clientIp}) \x1b[90m[${currentUsers}]\x1b[0m Location: ${locationInfo.city}, ${locationInfo.region}, ${locationInfo.country}`); logInfo(`Web client \x1b[32mconnected\x1b[0m (${clientIp}) \x1b[90m[${currentUsers}]\x1b[0m Location: ${locationInfo.city}, ${locationInfo.region}, ${locationInfo.country}`);
} }
@@ -338,6 +338,10 @@ wss.on('connection', (ws, request) => {
storage.connectedUsers.splice(index, 1); // Remove the user's data from storage.connectedUsers array storage.connectedUsers.splice(index, 1); // Remove the user's data from storage.connectedUsers array
} }
if(currentUsers === 0) {
storage.connectedUsers = [];
}
if (currentUsers === 0 && serverConfig.enableDefaultFreq === true && serverConfig.autoShutdown !== true && serverConfig.xdrd.wirelessConnection === true) { if (currentUsers === 0 && serverConfig.enableDefaultFreq === true && serverConfig.autoShutdown !== true && serverConfig.xdrd.wirelessConnection === true) {
setTimeout(function() { setTimeout(function() {
if(currentUsers === 0) { if(currentUsers === 0) {

View File

@@ -29,13 +29,10 @@
width: 88%; width: 88%;
} }
.panel-100 { .panel-100 {
width: 98%; width: 98%;
} }
@media only screen and (max-width: 768px) { @media only screen and (max-width: 768px) {
.panel-75 { .panel-75 {
width: 90%; width: 90%;

View File

@@ -39,8 +39,8 @@
<div id="wrapper"> <div id="wrapper">
<div class="panel-100 no-bg tuner-info"> <div class="panel-100 no-bg tuner-info">
<h1 id="tuner-name"><%= tunerName %> <h1 id="tuner-name"><%= tunerName %>
<% if (!publicTuner) { %><i class="fa-solid fa-key pointer tooltip" data-tooltip="Only people with tune password can tune."></i> <% if (!publicTuner) { %><i class="fa-solid fa-key pointer tooltip" aria-label="Only people with tune password can tune." data-tooltip="Only people with tune password can tune."></i>
<% } if (tunerLock) { %><i class="fa-solid fa-lock pointer tooltip" data-tooltip="Tuner is currently locked to admin."></i> <% } if (tunerLock) { %><i class="fa-solid fa-lock pointer tooltip" aria-label="Tuner is currently locked to admin." data-tooltip="Tuner is currently locked to admin."></i>
<% } %> <% } %>
</h1> </h1>
<p id="tuner-desc"> <p id="tuner-desc">
@@ -60,7 +60,7 @@
<div class="flex-container"> <div class="flex-container">
<div class="panel-75 flex-container no-bg"> <div class="panel-75 flex-container no-bg">
<div class="panel-10 no-bg h-100 m-0 m-right-20 hide-phone" style="width: 100px;margin-right: 20px !important;"> <div class="panel-10 no-bg h-100 m-0 m-right-20 hide-phone" style="width: 100px;margin-right: 20px !important;">
<button class="playbutton" aria-label="Play / Stop Button"><i class="fa-solid fa-play fa-lg"></i></button> <button class="playbutton" aria-label="Play / Stop"><i class="fa-solid fa-play fa-lg"></i></button>
</div> </div>
<div class="panel-100 m-0 hover-brighten flex-center tooltip" id="ps-container" style="height: 90px;" data-tooltip="Clicking on the RDS PS will copy the RDS info into the clipboard."> <div class="panel-100 m-0 hover-brighten flex-center tooltip" id="ps-container" style="height: 90px;" data-tooltip="Clicking on the RDS PS will copy the RDS info into the clipboard.">
<span class="text-big" id="data-ps"></span> <span class="text-big" id="data-ps"></span>
@@ -143,9 +143,9 @@
</div> </div>
<div class="panel-33 flex-container flex-phone" id="tune-buttons"> <div class="panel-33 flex-container flex-phone" id="tune-buttons">
<button id="freq-down" aria-label="Tune down by 100 KHz"><i class="fa-solid fa-chevron-left"></i></button> <button id="freq-down" aria-label="Tune down"><i class="fa-solid fa-chevron-left"></i></button>
<input type="text" id="commandinput" inputmode="numeric" placeholder="Frequency" autocomplete="off" aria-label="Current frequency: "> <input type="text" id="commandinput" inputmode="numeric" placeholder="Frequency" autocomplete="off" aria-label="Current frequency: ">
<button id="freq-up" aria-label="Tune up by 100 KHz"><i class="fa-solid fa-chevron-right"></i></button> <button id="freq-up" aria-label="Tune up"><i class="fa-solid fa-chevron-right"></i></button>
</div> </div>
<div class="panel-33 hide-phone no-bg"> <div class="panel-33 hide-phone no-bg">
@@ -163,7 +163,7 @@
<div class="panel-50 w-150 no-bg h-100 m-0 dropdown" id="data-bw" style="margin-left: 25px;"> <div class="panel-50 w-150 no-bg h-100 m-0 dropdown" id="data-bw" style="margin-left: 25px;">
<input type="text" placeholder="Auto BW" readonly> <input type="text" placeholder="Auto BW" readonly>
<ul class="options open-top"> <ul class="options open-top">
<li data-vlaue="0" class="option">Auto</li> <li data-value="0" class="option">Auto</li>
<li data-value="56000" class="option">56 KHz</li> <li data-value="56000" class="option">56 KHz</li>
<li data-value="64000" class="option">64 KHz</li> <li data-value="64000" class="option">64 KHz</li>
<li data-value="72000" class="option">72 KHz</li> <li data-value="72000" class="option">72 KHz</li>
@@ -187,36 +187,36 @@
<div class="panel-50 w-150 no-bg h-100 m-0 dropdown" id="data-bw" style="margin-left: 25px;"> <div class="panel-50 w-150 no-bg h-100 m-0 dropdown" id="data-bw" style="margin-left: 25px;">
<input type="text" placeholder="Auto BW" readonly> <input type="text" placeholder="Auto BW" readonly>
<ul class="options open-top"> <ul class="options open-top">
<li data-vlaue="0" class="option">Auto</li> <li data-value="0" data-value2="0" class="option">Auto</li>
<li data-value="1" class="option">9 KHz</li> <li data-value="9000" data-value2="1" class="option">9 KHz</li>
<li data-value="2" class="option">15 KHz</li> <li data-value="15000" data-value2="2" class="option">15 KHz</li>
<li data-value="3" class="option">17 KHz</li> <li data-value="17000" data-value2="3" class="option">17 KHz</li>
<li data-value="4" class="option">20 KHz</li> <li data-value="20000" data-value2="4" class="option">20 KHz</li>
<li data-value="5" class="option">24 KHz</li> <li data-value="24000" data-value2="5" class="option">24 KHz</li>
<li data-value="6" class="option">27 KHz</li> <li data-value="27000" data-value2="6" class="option">27 KHz</li>
<li data-value="7" class="option">32 KHz</li> <li data-value="32000" data-value2="7" class="option">32 KHz</li>
<li data-value="8" class="option">36 KHz</li> <li data-value="36000" data-value2="8" class="option">36 KHz</li>
<li data-value="9" class="option">42 KHz</li> <li data-value="42000" data-value2="9" class="option">42 KHz</li>
<li data-value="10" class="option">48 KHz</li> <li data-value="48000" data-value2="10" class="option">48 KHz</li>
<li data-value="11" class="option">55 KHz</li> <li data-value="55000" data-value2="11" class="option">55 KHz</li>
<li data-value="12" class="option">63 KHz</li> <li data-value="63000" data-value2="12" class="option">63 KHz</li>
<li data-value="13" class="option">73 KHz</li> <li data-value="73000" data-value2="13" class="option">73 KHz</li>
<li data-value="14" class="option">83 KHz</li> <li data-value="83000" data-value2="14" class="option">83 KHz</li>
<li data-value="15" class="option">90 KHz</li> <li data-value="90000" data-value2="15" class="option">90 KHz</li>
<li data-value="16" class="option">95 KHz</li> <li data-value="95000" data-value2="16" class="option">95 KHz</li>
<li data-value="17" class="option">108 KHz</li> <li data-value="108000" data-value2="17" class="option">108 KHz</li>
<li data-value="18" class="option">125 KHz</li> <li data-value="125000" data-value2="18" class="option">125 KHz</li>
<li data-value="19" class="option">142 KHz</li> <li data-value="142000" data-value2="19" class="option">142 KHz</li>
<li data-value="20" class="option">159 KHz</li> <li data-value="155000" data-value2="20" class="option">159 KHz</li>
<li data-value="21" class="option">177 KHz</li> <li data-value="177000" data-value2="21" class="option">177 KHz</li>
<li data-value="22" class="option">194 KHz</li> <li data-value="194000" data-value2="22" class="option">194 KHz</li>
<li data-value="23" class="option">211 KHz</li> <li data-value="211000" data-value2="23" class="option">211 KHz</li>
<li data-value="24" class="option">229 KHz</li> <li data-value="229000" data-value2="24" class="option">229 KHz</li>
<li data-value="25" class="option">246 KHz</li> <li data-value="246000" data-value2="25" class="option">246 KHz</li>
<li data-value="26" class="option">263 KHz</li> <li data-value="263000" data-value2="26" class="option">263 KHz</li>
<li data-value="27" class="option">281 KHz</li> <li data-value="281000" data-value2="27" class="option">281 KHz</li>
<li data-value="28" class="option">298 KHz</li> <li data-value="298000" data-value2="28" class="option">298 KHz</li>
<li data-value="29" class="option">309 KHz</li> <li data-value="309000" data-value2="29" class="option">309 KHz</li>
</ul> </ul>
</div> </div>
<% } %> <% } %>
@@ -225,7 +225,7 @@
<div class="panel-50 w-150 no-bg h-100 m-0 dropdown" id="data-bw" style="margin-left: 25px;"> <div class="panel-50 w-150 no-bg h-100 m-0 dropdown" id="data-bw" style="margin-left: 25px;">
<input type="text" placeholder="Auto BW" readonly> <input type="text" placeholder="Auto BW" readonly>
<ul class="options open-top"> <ul class="options open-top">
<li data-vlaue="0" class="option">Auto</li> <li data-value="0" class="option">Auto</li>
<li data-value="4000" class="option">4 KHz</li> <li data-value="4000" class="option">4 KHz</li>
<li data-value="8000" class="option">8 KHz</li> <li data-value="8000" class="option">8 KHz</li>
<li data-value="10000" class="option">10 KHz</li> <li data-value="10000" class="option">10 KHz</li>
@@ -286,7 +286,7 @@
</div> </div>
<% if (chatEnabled) { %> <% if (chatEnabled) { %>
<div class="panel-10 no-bg h-100 hide-phone" style="width: 100px; height: 100px;"> <div class="panel-10 no-bg h-100 hide-phone" style="width: 100px; height: 100px;">
<button class="chatbutton bg-color-2"><i class="fa-solid fa-comments fa-lg"></i> (<span class="chat-messages-count">0</span>)</button> <button class="chatbutton bg-color-2" aria-label="Chatbox"><i class="fa-solid fa-comments fa-lg"></i> (<span class="chat-messages-count">0</span>)</button>
</div> </div>
<% } %> <% } %>
</div> </div>
@@ -469,7 +469,7 @@
</div> </div>
<div class="modal-panel-chat"> <div class="modal-panel-chat">
<div class="modal-panel-sidebar hover-brighten flex-center text-medium-big closeModal"><i class="fa-solid fa-chevron-down"></i></div> <div class="modal-panel-sidebar hover-brighten flex-center text-medium-big closeModal" role="button"><i class="fa-solid fa-chevron-down"></i></div>
<div class="modal-panel-content text-left"> <div class="modal-panel-content text-left">
<div style="text-align: center;"> <div style="text-align: center;">
<input type="text" id="chat-nickname" name="chat-nickname" placeholder="Nickname"> <input type="text" id="chat-nickname" name="chat-nickname" placeholder="Nickname">
@@ -484,7 +484,7 @@
<div class="flex-container flex-phone" style="align-content: stretch;"> <div class="flex-container flex-phone" style="align-content: stretch;">
<input class="bg-color-2" type="text" id="chat-send-message" name="chat-send-message" placeholder="Send message..." style="background-color: var(--color-2);width: 100%;"> <input class="bg-color-2" type="text" id="chat-send-message" name="chat-send-message" placeholder="Send message..." style="background-color: var(--color-2);width: 100%;">
<button class="chat-send-message-btn br-0" style="width: 80px; height: 45px;"><i class="fa-solid fa-paper-plane"></i></button> <button aria-label="Send message" class="chat-send-message-btn br-0" style="width: 80px; height: 45px;"><i class="fa-solid fa-paper-plane"></i></button>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -72,7 +72,7 @@ var Fallback = /** @class */ (function () {
Fallback.prototype.Init = function (webSocket) { Fallback.prototype.Init = function (webSocket) {
this.MobileUnmute(); this.MobileUnmute();
this.WebSocket = webSocket; this.WebSocket = webSocket;
this.WebSocket.Send(JSON.stringify({ this.WebSocket?.Send(JSON.stringify({
"type": "fallback", "type": "fallback",
"data": this.SelectedFormatName "data": this.SelectedFormatName
})); }));

View File

@@ -4,15 +4,17 @@ let Stream;
function Init(_ev) { function Init(_ev) {
try { try {
const settings = new _3LAS_Settings(); const settings = new _3LAS_Settings();
if (!Stream) { // Ensure Stream is not re-initialized
Stream = new _3LAS(null, settings); Stream = new _3LAS(null, settings);
}
} catch (error) { } catch (error) {
console.log(error); console.log(error);
return; return;
} }
Stream.ConnectivityCallback = OnConnectivityCallback; Stream.ConnectivityCallback = OnConnectivityCallback;
$(".playbutton").on('click', OnPlayButtonClick); $(".playbutton").off('click').on('click', OnPlayButtonClick); // Ensure only one event handler is attached
$("#volumeSlider").on("input", updateVolume); $("#volumeSlider").off("input").on("input", updateVolume); // Ensure only one event handler is attached
} }
function OnConnectivityCallback(isConnected) { function OnConnectivityCallback(isConnected) {
@@ -22,7 +24,7 @@ function OnConnectivityCallback(isConnected) {
function OnPlayButtonClick(_ev) { function OnPlayButtonClick(_ev) {
const $playbutton = $('.playbutton'); const $playbutton = $('.playbutton');
$playbutton.find('.fa-solid').toggleClass('fa-play fa-stop'); $playbutton.find('.fa-solid').toggleClass('fa-play fa-stop');
try {
if (Stream.ConnectivityFlag) { if (Stream.ConnectivityFlag) {
Stream.Stop(); Stream.Stop();
} else { } else {
@@ -32,11 +34,10 @@ function OnPlayButtonClick(_ev) {
$playbutton.removeClass('bg-gray').prop('disabled', false); $playbutton.removeClass('bg-gray').prop('disabled', false);
}, 3000); }, 3000);
} }
} catch (error) {
console.error(error);
}
} }
function updateVolume() { function updateVolume() {
Stream.Volume = $(this).val(); Stream.Volume = $(this).val();
} }
$(document).ready(Init);

View File

@@ -33,6 +33,7 @@ $(document).ready(function() {
if (!messageData.history) { if (!messageData.history) {
chatMessageCount++; chatMessageCount++;
chatMessagesCount.text(chatMessageCount); chatMessagesCount.text(chatMessageCount);
chatMessagesCount.attr("aria-label", "Chat (" + chatMessageCount + " unread)");
chatButton.removeClass('bg-color-2').addClass('bg-color-4'); chatButton.removeClass('bg-color-2').addClass('bg-color-4');
} }
} }

View File

@@ -59,7 +59,7 @@ function submitData() {
}).data('value') || "tef"); }).data('value') || "tef");
const softwareMode = $('#audio-software-mode').is(":checked") || false; const softwareMode = $('#audio-software-mode').is(":checked") || false;
const startupVolume = $('#startup-volume').val() || '100'; const startupVolume = $('#startup-volume').val() || '1';
const tunerName = $('#webserver-name').val() || 'FM Tuner'; const tunerName = $('#webserver-name').val() || 'FM Tuner';
const tunerDesc = $('#webserver-desc').val() || 'Default FM tuner description'; const tunerDesc = $('#webserver-desc').val() || 'Default FM tuner description';

View File

@@ -25,12 +25,9 @@ const selectOption = (event) => {
tuneTo(getCurrentFreq()); //Reset RDS when change antenna input tuneTo(getCurrentFreq()); //Reset RDS when change antenna input
break; break;
case 'data-bw': case 'data-bw':
if($(event.currentTarget).attr('data-value') > 500) { legacyBwValue = $(event.currentTarget).attr('data-value2') || "";
socket.send("F" + $(event.currentTarget).attr('data-value')); socket.send("F" + legacyBwValue);
} else {
socket.send("W" + $(event.currentTarget).attr('data-value')); socket.send("W" + $(event.currentTarget).attr('data-value'));
}
$currentDropdown.find('input').val($(event.currentTarget).text()); $currentDropdown.find('input').val($(event.currentTarget).text());
break; break;
default: default:

View File

@@ -1,9 +1,9 @@
var currentDate = new Date('May 4, 2024 01:00:00'); var currentDate = new Date('May 20, 2024 22:00:00');
var day = currentDate.getDate(); var day = currentDate.getDate();
var month = currentDate.getMonth() + 1; // Months are zero-indexed, so add 1 var month = currentDate.getMonth() + 1; // Months are zero-indexed, so add 1
var year = currentDate.getFullYear(); var year = currentDate.getFullYear();
var formattedDate = day + '/' + month + '/' + year; var formattedDate = day + '/' + month + '/' + year;
var currentVersion = 'v1.2.1 [' + formattedDate + ']'; var currentVersion = 'v1.2.2 [' + formattedDate + ']';
getInitialSettings(); getInitialSettings();

View File

@@ -370,7 +370,7 @@ socket.onmessage = (event) => {
console.log('Kick iniitiated.') console.log('Kick iniitiated.')
setTimeout(() => { setTimeout(() => {
window.location.href = '/403'; window.location.href = '/403';
}, 500); // Adjust the delay as needed }, 500);
return; return;
} }
@@ -763,6 +763,7 @@ const updateDataElements = throttle(function(parsedData) {
$dataPs.attr('aria-label', parsedData.ps); $dataPs.attr('aria-label', parsedData.ps);
$dataRt0.attr('aria-label', parsedData.rt0); $dataRt0.attr('aria-label', parsedData.rt0);
$dataRt1.attr('aria-label', parsedData.rt1); $dataRt1.attr('aria-label', parsedData.rt1);
$('#users-online-container').attr("aria-label", "Online users: " + parsedData.users);
} }
}, 100); // Update at most once every 100 milliseconds }, 100); // Update at most once every 100 milliseconds
@@ -850,9 +851,11 @@ function toggleAdminLock() {
if($adminLockButton.hasClass('active')) { if($adminLockButton.hasClass('active')) {
socket.send('wL0'); socket.send('wL0');
$adminLockButton.attr('aria-label', '"ock Tuner (Admin)')
$adminLockButton.removeClass('active'); $adminLockButton.removeClass('active');
} else { } else {
socket.send('wL1'); socket.send('wL1');
$adminLockButton.attr('aria-label', 'Unlock Tuner (Admin)')
$adminLockButton.addClass('active'); $adminLockButton.addClass('active');
} }
} }
@@ -863,9 +866,11 @@ function togglePasswordLock() {
if($passwordLockButton.hasClass('active')) { if($passwordLockButton.hasClass('active')) {
socket.send('wT0'); socket.send('wT0');
$passwordLockButton.removeClass('active'); $passwordLockButton.removeClass('active');
$passwordLockButton.attr('aria-label', 'Lock Tuner (Password tune)')
} else { } else {
socket.send('wT1'); socket.send('wT1');
$passwordLockButton.addClass('active'); $passwordLockButton.addClass('active');
$passwordLockButton.attr('aria-label', 'Unlock Tuner (Password tune)')
} }
} }

View File

@@ -19,21 +19,37 @@
<h2 class="text-monospace text-light">[ADMIN PANEL]</h2> <h2 class="text-monospace text-light">[ADMIN PANEL]</h2>
</div> </div>
<div class="panel-100"> <div class="panel-100">
<ul class="nav"> <ul class="nav" role="tablist">
<li data-panel="dashboard" class="active">Dashboard</li> <li role="presentation" data-panel="dashboard">
<li data-panel="tuner">Tuner</li> <a href="#" role="tab" aria-controls="dashboard" aria-selected="true">Dashboard</a>
<li data-panel="connection">Connection</li> </li>
<li data-panel="audio">Audio</li> <li role="presentation" data-panel="tuner">
<li data-panel="webserver">Webserver</li> <a href="#" role="tab" aria-controls="tuner">Tuner</a>
<li data-panel="plugins">Plugins</li> </li>
<li data-panel="identification">Info & Map</li> <li role="presentation" data-panel="connection">
<li class="logout-link text-gray"><i class="fas fa-sign-out"></i></li> <a href="#" role="tab" aria-controls="connection">Connection</a>
</li>
<li role="presentation" data-panel="audio">
<a href="#" role="tab" aria-controls="audio">Audio</a>
</li>
<li role="presentation" data-panel="webserver">
<a href="#" role="tab" aria-controls="webserver">Webserver</a>
</li>
<li role="presentation" data-panel="plugins">
<a href="#" role="tab" aria-controls="plugins">Plugins</a>
</li>
<li role="presentation" data-panel="identification">
<a href="#" role="tab" aria-controls="identification">Info & Map</a>
</li>
<li role="presentation" class="logout-link text-gray">
<a href="./logout"><i class="fas fa-sign-out"></i></a>
</li>
</ul> </ul>
</div> </div>
<div id="login-message"></div> <div id="login-message"></div>
<div class="panel-100"> <div class="panel-100">
<div class="panel-100 tab-content" id="dashboard"> <div class="panel-100 tab-content" id="dashboard" role="tabpanel">
<h2>Dashboard</h2> <h2>Dashboard</h2>
<div class="panel-100 flex-container auto"> <div class="panel-100 flex-container auto">
@@ -121,7 +137,7 @@
<p><a href="https://github.com/noobishsvk/fm-dx-webserver" target="_blank">Check for the latest source code</a> • <a href="https://buymeacoffee.com/noobish" target="_blank">Support the developer</a></p> <p><a href="https://github.com/noobishsvk/fm-dx-webserver" target="_blank">Check for the latest source code</a> • <a href="https://buymeacoffee.com/noobish" target="_blank">Support the developer</a></p>
</div> </div>
<div class="panel-100 tab-content" id="connection"> <div class="panel-100 tab-content" id="connection" role="tabpanel">
<h2>Connection settings</h2> <h2>Connection settings</h2>
<p>You can set up your connection settings here. Changing these settings requires a server restart.</p> <p>You can set up your connection settings here. Changing these settings requires a server restart.</p>
<h3>Tuner connection:</h3> <h3>Tuner connection:</h3>
@@ -182,7 +198,7 @@
<br> <br>
</div> </div>
<div class="panel-100 tab-content" id="audio"> <div class="panel-100 tab-content" id="audio" role="tabpanel">
<h2>Audio settings</h2> <h2>Audio settings</h2>
<p>You can set up your audio settings here. Changing these settings requires a server restart.</p> <p>You can set up your audio settings here. Changing these settings requires a server restart.</p>
@@ -244,7 +260,7 @@
</div> </div>
</div> </div>
<div class="panel-100 tab-content" id="webserver"> <div class="panel-100 tab-content" id="webserver" role="tabpanel">
<h2>Webserver settings</h2> <h2>Webserver settings</h2>
<div class="flex-container"> <div class="flex-container">
<div class="panel-50 no-bg"> <div class="panel-50 no-bg">
@@ -403,7 +419,7 @@
</div> </div>
<div class="panel-100 tab-content" id="plugins"> <div class="panel-100 tab-content" id="plugins" role="tabpanel">
<h2>Plugins</h2> <h2>Plugins</h2>
<p>Any compatible <strong>.js</strong> plugin, which is in the "plugins" folder, will be listed here.<br> <p>Any compatible <strong>.js</strong> plugin, which is in the "plugins" folder, will be listed here.<br>
Click on the individual plugins to enable/disable them.</p> Click on the individual plugins to enable/disable them.</p>
@@ -418,7 +434,7 @@
</div> </div>
<div class="panel-100 tab-content" id="tuner"> <div class="panel-100 tab-content" id="tuner" role="tabpanel">
<h2>Tuner Specific Settings</h2> <h2>Tuner Specific Settings</h2>
<div class="form-group"> <div class="form-group">
<label for="themes"><i class="fa-solid fa-radio"></i> Device:</label> <label for="themes"><i class="fa-solid fa-radio"></i> Device:</label>
@@ -449,7 +465,7 @@
</div> </div>
<div class="panel-100 tab-content" id="identification"> <div class="panel-100 tab-content" id="identification" role="tabpanel">
<h2>Identification & Map</h2> <h2>Identification & Map</h2>
<div class="flex-container"> <div class="flex-container">