From e9d389fef0c1efebb0edda33b16535a2e7ae4459 Mon Sep 17 00:00:00 2001 From: NoobishSVK Date: Wed, 31 Jul 2024 16:29:16 +0200 Subject: [PATCH] bugfixes, global url params, rds endpoint --- .gitignore | 6 +- index.js | 1 + package.json | 2 +- server/datahandler.js | 43 ++++++----- server/endpoints.js | 3 + server/helpers.js | 5 +- server/index.js | 20 +++++- server/tx_search.js | 1 + web/css/buttons.css | 14 ++-- web/css/dropdown.css | 5 ++ web/css/helpers.css | 2 +- web/css/main.css | 4 +- web/css/panels.css | 24 ++++++- web/index.ejs | 160 +++++++++++++++++++++-------------------- web/js/3las/main.js | 3 +- web/js/dropdown.js | 163 +++++++++++++++++++++++++----------------- web/js/init.js | 4 +- web/js/main.js | 23 +++--- web/js/settings.js | 32 +++++++-- web/setup.ejs | 106 +++++++++++++-------------- web/wizard.ejs | 6 +- 21 files changed, 376 insertions(+), 251 deletions(-) diff --git a/.gitignore b/.gitignore index 03f42a7..aa29cb0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ node_modules/ /*.json -/ffmpeg.exe /serverlog.txt -/web/js/plugins/ \ No newline at end of file +/web/js/plugins/ +/plugins/* +!/plugins/example/frontend.js +!/plugins/example.js \ No newline at end of file diff --git a/index.js b/index.js index adba7f8..d0ed3bb 100644 --- a/index.js +++ b/index.js @@ -6,4 +6,5 @@ require('./server/index.js'); * Github repo: https://github.com/NoobishSVK/fm-dx-webserver * Server files: /server * Client files (web): /web + * Plugin files: /plugins */ \ No newline at end of file diff --git a/package.json b/package.json index 69b381b..03732ae 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fm-dx-webserver", - "version": "1.2.5", + "version": "1.2.6", "description": "FM DX Webserver", "main": "index.js", "scripts": { diff --git a/server/datahandler.js b/server/datahandler.js index 60bce67..337bc9f 100644 --- a/server/datahandler.js +++ b/server/datahandler.js @@ -205,12 +205,13 @@ const updateInterval = 75; var dataToSend = { pi: '?', freq: 87.500.toFixed(3), - previousFreq: 87.500.toFixed(3), - signal: 0, - highestSignal: -Infinity, + prevFreq: 87.500.toFixed(3), + sig: 0, + sigRaw: '', + sigTop: -Infinity, bw: 0, st: false, - st_forced: false, + stForced: false, rds: false, ps: '', tp: 0, @@ -224,13 +225,14 @@ var dataToSend = { eq: 0, ant: 0, txInfo: { - station: '', + tx: '', pol: '', erp: '', city: '', itu: '', - distance: '', - azimuth: '' + dist: '', + azi: '', + id: '' }, country_name: '', country_iso: 'UN', @@ -251,7 +253,7 @@ const initialData = { ...dataToSend }; const resetToDefault = dataToSend => Object.assign(dataToSend, initialData); -function handleData(wss, receivedData) { +function handleData(wss, receivedData, rdsWss) { // Retrieve the last update time for this client const currentTime = Date.now(); @@ -350,6 +352,10 @@ function handleData(wss, receivedData) { modifiedData += errorsNew.toString(16).padStart(2, '0'); } + rdsWss.clients.forEach((client) => { // Send to /rds endpoint via WebSocket + client.send(modifiedData); + }); + rdsparser.parse_string(rds, modifiedData); legacyRdsPiBuffer = null; break; @@ -360,13 +366,14 @@ function handleData(wss, receivedData) { const currentTx = fetchTx(parseFloat(dataToSend.freq).toFixed(1), dataToSend.pi, dataToSend.ps); if(currentTx && currentTx.station !== undefined) { dataToSend.txInfo = { - station: currentTx.station, + tx: currentTx.station, pol: currentTx.pol, erp: currentTx.erp, city: currentTx.city, itu: currentTx.itu, - distance: currentTx.distance, - azimuth: currentTx.azimuth + dist: currentTx.distance, + azi: currentTx.azimuth, + id: currentTx.id } } @@ -389,20 +396,22 @@ function processSignal(receivedData, st, stForced) { const modifiedData = receivedData.substring(2); const parsedValue = parseFloat(modifiedData); dataToSend.st = st; - dataToSend.st_forced = stForced; + dataToSend.stForced = stForced; initialData.st = st; - initialData.st_forced = stForced; + initialData.stForced = stForced; if (!isNaN(parsedValue)) { // Convert parsedValue to a number var signal = parseFloat(parsedValue.toFixed(2)); - dataToSend.signal = signal; - initialData.signal = signal; + dataToSend.sig = signal; + initialData.sig = signal; + dataToSend.sigRaw = receivedData; + initialData.sigRaw = receivedData; // Convert highestSignal to a number for comparison - var highestSignal = parseFloat(dataToSend.highestSignal); + var highestSignal = parseFloat(dataToSend.sigTop); if (signal > highestSignal) { - dataToSend.highestSignal = signal.toString(); // Convert back to string for consistency + dataToSend.sigTop = signal.toString(); // Convert back to string for consistency } } diff --git a/server/endpoints.js b/server/endpoints.js index 225c005..3d54050 100644 --- a/server/endpoints.js +++ b/server/endpoints.js @@ -22,6 +22,8 @@ router.get('/', (req, res) => { return; } + const noPlugins = req.query.noPlugins === 'true'; + if (configExists() === false) { let serialPorts; @@ -57,6 +59,7 @@ router.get('/', (req, res) => { tuningUpperLimit: serverConfig.webserver.tuningUpperLimit, chatEnabled: serverConfig.webserver.chatEnabled, device: serverConfig.device, + noPlugins, plugins: serverConfig.plugins, bwSwitch: serverConfig.bwSwitch ? serverConfig.bwSwitch : false }); diff --git a/server/helpers.js b/server/helpers.js index e31b5fc..3e2ec48 100644 --- a/server/helpers.js +++ b/server/helpers.js @@ -1,4 +1,3 @@ -const WebSocket = require('ws'); const dataHandler = require('./datahandler'); const storage = require('./storage'); const consoleCmd = require('./console'); @@ -55,7 +54,7 @@ function formatUptime(uptimeInSeconds) { let incompleteDataBuffer = ''; -function resolveDataBuffer(data, wss) { +function resolveDataBuffer(data, wss, rdsWss) { var receivedData = incompleteDataBuffer + data.toString(); const isIncomplete = (receivedData.slice(-1) != '\n'); @@ -73,7 +72,7 @@ function resolveDataBuffer(data, wss) { } if (receivedData.length) { - dataHandler.handleData(wss, receivedData); + dataHandler.handleData(wss, receivedData, rdsWss); }; } diff --git a/server/index.js b/server/index.js index 739b6be..023ac9a 100644 --- a/server/index.js +++ b/server/index.js @@ -11,6 +11,7 @@ const httpServer = http.createServer(app); const WebSocket = require('ws'); const wss = new WebSocket.Server({ noServer: true }); const chatWss = new WebSocket.Server({ noServer: true }); +const rdsWss = new WebSocket.Server({ noServer: true }); const path = require('path'); const net = require('net'); const client = new net.Socket(); @@ -109,7 +110,7 @@ if (serverConfig.xdrd.wirelessConnection === false) { }, 3000); serialport.on('data', (data) => { - helpers.resolveDataBuffer(data, wss); + helpers.resolveDataBuffer(data, wss, rdsWss); }); serialport.on('error', (error) => { @@ -185,7 +186,7 @@ function connectToXdrd() { }; client.on('data', (data) => { - helpers.resolveDataBuffer(data, wss); + helpers.resolveDataBuffer(data, wss, rdsWss); if (authFlags.authMsg == true && authFlags.messageCount > 1) { // If the limit is reached, remove the 'data' event listener client.off('data', authDataHandler); @@ -437,6 +438,15 @@ chatWss.on('connection', (ws, request) => { }); }); +rdsWss.on('connection', (ws, request) => { + ws.on('message', function incoming(message) { + + }); + + ws.on('close', function close() { + }); +}); + // Websocket register for /text, /audio and /chat paths httpServer.on('upgrade', (request, socket, head) => { if (request.url === '/text') { @@ -453,6 +463,12 @@ httpServer.on('upgrade', (request, socket, head) => { chatWss.emit('connection', ws, request); }); }); + } else if (request.url === '/rds') { + sessionMiddleware(request, {}, () => { + rdsWss.handleUpgrade(request, socket, head, (ws) => { + rdsWss.emit('connection', ws, request); + }); + }); } else { socket.destroy(); } diff --git a/server/tx_search.js b/server/tx_search.js index 998db7d..c2acdc9 100644 --- a/server/tx_search.js +++ b/server/tx_search.js @@ -83,6 +83,7 @@ function processData(data, piCode, rdsPs) { itu: matchingCity.itu, distance: maxDistance.toFixed(0), azimuth: txAzimuth.toFixed(0), + id: matchingStation.id, foundStation: true }; } else { diff --git a/web/css/buttons.css b/web/css/buttons.css index 61e0a5d..f471812 100644 --- a/web/css/buttons.css +++ b/web/css/buttons.css @@ -83,14 +83,14 @@ input[type="text"], textarea, input[type="password"] { #tune-buttons input[type="text"] { width: 50%; - height: 100%; + height: 48px; min-height: 46px; padding-left: 20px; box-sizing: border-box; border: 2px solid transparent; outline: 0; color: var(--color-text); - background-color: var(--color-1-transparent); + background-color: transparent; font-family: 'Titillium Web', sans-serif; } @@ -120,7 +120,7 @@ input[type="text"], textarea, input[type="password"] { border: 0; color: var(--color-1); width: 25%; - height: 100%; + height: 48px; display: block; padding: 14px; cursor: pointer; @@ -158,7 +158,7 @@ input[type="range"] { /* Track: Mozilla Firefox */ input[type="range"]::-moz-range-track { height: 48px; - background: var(--color-1-transparent); + background-color: transpraent; border-radius: 15px; border: 0; } @@ -340,4 +340,10 @@ select option { select:hover { background: var(--color-5); +} + +@media only screen and (max-width: 768px) { + #tune-buttons input[type="text"] { + background-color: var(--color-1-transparent); + } } \ No newline at end of file diff --git a/web/css/dropdown.css b/web/css/dropdown.css index 287b7a8..6c2f89a 100644 --- a/web/css/dropdown.css +++ b/web/css/dropdown.css @@ -40,6 +40,11 @@ background-color: var(--color-4); color: var(--color-main); border-radius: 15px; + transition: 0.35s ease-in-out background-color; + } + + .dropdown input:hover { + background-color: var(--color-main-bright); } .dropdown.opened > input { diff --git a/web/css/helpers.css b/web/css/helpers.css index 3215c7e..8be4055 100644 --- a/web/css/helpers.css +++ b/web/css/helpers.css @@ -112,7 +112,7 @@ .hover-brighten:hover { cursor: pointer; - background-color: var(--color-2); + background-color: var(--color-2-transparent); } .text-left { diff --git a/web/css/main.css b/web/css/main.css index f514e33..4ecc064 100644 --- a/web/css/main.css +++ b/web/css/main.css @@ -77,8 +77,8 @@ body { } #wrapper { - width: 1180px; - max-width: 1180px; + width: 100%; + max-width: calc(0% + 1180px); } #wrapper.setup-wrapper { margin: auto; diff --git a/web/css/panels.css b/web/css/panels.css index 78eb4c7..8fea02b 100644 --- a/web/css/panels.css +++ b/web/css/panels.css @@ -8,8 +8,25 @@ transition: 0.3s ease-in-out background-color; } -*[class^="panel-"]:not(.no-bg):not(.no-filter) { - backdrop-filter:blur(5px); +*[class^="panel-"]:not(.no-bg):not(.no-filter):not(.w-100) { + -webkit-backdrop-filter: blur(5px); + backdrop-filter: blur(5px); +} + +.panel-100.w-100 { + position: relative; +} + +.panel-100.w-100::before { + content: ''; + backdrop-filter: blur(10px); + width: 100%; + height: 100%; + position: absolute; + top: 0; + left: 0; + z-index: -1; + border-radius: 15px; } .panel-10 { @@ -54,6 +71,9 @@ margin-bottom: 20px; background-color: transparent; } + *[class^="panel-"]:not(.no-bg):not(.no-filter) { + backdrop-filter:blur(0px); + } .flex-phone { display: flex; } diff --git a/web/index.ejs b/web/index.ejs index dfcd505..e4faff7 100644 --- a/web/index.ejs +++ b/web/index.ejs @@ -125,12 +125,12 @@ <% if (antennas.enabled == true) { %> <% } %> @@ -165,71 +165,71 @@ <% } %> <% if (device == 'tef' && bwSwitch == true) { %> <% } %> <% if (device == 'xdr' && bwSwitch == true) { %> <% } %> <% if (device == 'sdr' && bwSwitch == true) { %> <% } %> @@ -323,17 +323,17 @@
@@ -342,22 +342,22 @@

<% } %>
- +
- +
@@ -491,8 +491,10 @@ -<% plugins?.forEach(function(plugin) { %> +<% if (!noPlugins) { %> + <% plugins?.forEach(function(plugin) { %> -<% }); %> + <% }); %> +<% } %> diff --git a/web/js/3las/main.js b/web/js/3las/main.js index 9e716cb..7784272 100644 --- a/web/js/3las/main.js +++ b/web/js/3las/main.js @@ -1,4 +1,3 @@ -const DefaultVolume = 0.5; let Stream; let shouldReconnect = true; let newVolumeGlobal = 1; @@ -28,7 +27,7 @@ function destroyStream() { function OnConnectivityCallback(isConnected) { console.log("Connectivity changed:", isConnected); if (Stream) { - Stream.Volume = isConnected ? 1.0 : DefaultVolume; + Stream.Volume = $('#volumeSlider').val(); } else { console.warn("Stream is not initialized."); } diff --git a/web/js/dropdown.js b/web/js/dropdown.js index a2598d9..767f195 100644 --- a/web/js/dropdown.js +++ b/web/js/dropdown.js @@ -1,73 +1,108 @@ -// Variables -const $dropdowns = $('.dropdown'); -const $input = $('input'); -const $listOfOptions = $('.option'); -let currentDropdown = null; // Track the currently clicked dropdown +$(document).ready(function() { + // Variables + const $dropdowns = $('.dropdown'); + const $listOfOptions = $('.option'); + let currentDropdown = null; // Track the currently clicked dropdown + let currentIndex = -1; // Track the currently focused option -// Functions -const toggleDropdown = (event) => { - event.stopPropagation(); - const $currentDropdown = $(event.currentTarget); - - // Close the previously opened dropdown if any - $dropdowns.not($currentDropdown).removeClass('opened'); - - $currentDropdown.toggleClass('opened'); - currentDropdown = $currentDropdown.hasClass('opened') ? $currentDropdown : null; + // Functions + const toggleDropdown = (event) => { + event.stopPropagation(); + const $currentDropdown = $(event.currentTarget).closest('.dropdown'); + + // Close the previously opened dropdown if any + $dropdowns.not($currentDropdown).removeClass('opened'); + + $currentDropdown.toggleClass('opened'); + currentDropdown = $currentDropdown.hasClass('opened') ? $currentDropdown : null; + currentIndex = -1; // Reset the current index when toggling the dropdown }; -const selectOption = (event) => { - const $currentDropdown = currentDropdown; + const selectOption = (event) => { + const $currentDropdown = currentDropdown; - switch($currentDropdown.attr('id')) { - case 'data-ant': - socket.send("Z" + $(event.currentTarget).attr('data-value')); - tuneTo(getCurrentFreq()); //Reset RDS when change antenna input - break; - case 'data-bw': - legacyBwValue = $(event.currentTarget).attr('data-value2') || ""; - socket.send("F" + legacyBwValue); - socket.send("W" + $(event.currentTarget).attr('data-value')); - $currentDropdown.find('input').val($(event.currentTarget).text()); - break; - default: - $currentDropdown.find('input').val($(event.currentTarget).text()); - break; - } + switch($currentDropdown.attr('id')) { + case 'data-ant': + socket.send("Z" + $(event.currentTarget).attr('data-value')); + tuneTo(getCurrentFreq()); // Reset RDS when change antenna input + break; + case 'data-bw': + legacyBwValue = $(event.currentTarget).attr('data-value2') || ""; + socket.send("F" + legacyBwValue); + socket.send("W" + $(event.currentTarget).attr('data-value')); + $currentDropdown.find('input').val($(event.currentTarget).text()); + break; + default: + $currentDropdown.find('input').val($(event.currentTarget).text()); + break; + } - // Use setTimeout to delay class removal - setTimeout(() => { - $currentDropdown.removeClass('opened'); - currentDropdown = null; - }, 10); // Adjust the delay as needed -}; + // Use setTimeout to delay class removal + setTimeout(() => { + $currentDropdown.removeClass('opened'); + currentDropdown = null; + }, 10); // Adjust the delay as needed + }; -const closeDropdownFromOutside = (event) => { - const $currentDropdown = currentDropdown && $(currentDropdown); - const isClickedInsideDropdown = $currentDropdown && $currentDropdown.has(event.target).length > 0; + const closeDropdownFromOutside = (event) => { + const $currentDropdown = currentDropdown && $(currentDropdown); + const isClickedInsideDropdown = $currentDropdown && $currentDropdown.has(event.target).length > 0; - if (!isClickedInsideDropdown && $currentDropdown && $currentDropdown.hasClass('opened')) { - $currentDropdown.removeClass('opened'); - currentDropdown = null; - } -}; + if (!isClickedInsideDropdown && $currentDropdown && $currentDropdown.hasClass('opened')) { + $currentDropdown.removeClass('opened'); + currentDropdown = null; + } + }; -// Event Listeners -$(document).on('click', closeDropdownFromOutside); -$listOfOptions.on('click', selectOption); -$dropdowns.on('click', toggleDropdown); + const navigateOptions = (event) => { + if (!currentDropdown) return; -// MULTISELECT -$('.multiselect option').mousedown(function(e) { - e.preventDefault(); - var originalScrollTop = $(this).parent().scrollTop(); - console.log(originalScrollTop); - $(this).prop('selected', $(this).prop('selected') ? false : true); - var self = this; - $(this).parent().focus(); - setTimeout(function() { - $(self).parent().scrollTop(originalScrollTop); - }, 0); - - return false; -}); \ No newline at end of file + const $options = currentDropdown.find('.option'); + switch (event.key) { + case 'ArrowDown': + event.preventDefault(); + currentIndex = (currentIndex + 1) % $options.length; + $options.eq(currentIndex).focus(); + break; + case 'ArrowUp': + event.preventDefault(); + currentIndex = (currentIndex - 1 + $options.length) % $options.length; + $options.eq(currentIndex).focus(); + break; + case 'Enter': + event.preventDefault(); + $options.eq(currentIndex).click(); + break; + case 'Escape': + currentDropdown.removeClass('opened'); + currentDropdown = null; + currentIndex = -1; + break; + } + }; + + // Event Listeners + $(document).on('click', closeDropdownFromOutside); + $listOfOptions.on('click', selectOption); + $dropdowns.on('click', 'input', toggleDropdown); + $dropdowns.on('keydown', 'input', function(event) { + if (event.key === 'Enter') { + toggleDropdown(event); + } + }); + $dropdowns.on('keydown', '.option', navigateOptions); + + // MULTISELECT + $('.multiselect option').mousedown(function(e) { + e.preventDefault(); + var originalScrollTop = $(this).parent().scrollTop(); + $(this).prop('selected', $(this).prop('selected') ? false : true); + var self = this; + $(this).parent().focus(); + setTimeout(function() { + $(self).parent().scrollTop(originalScrollTop); + }, 0); + + return false; + }); +}); diff --git a/web/js/init.js b/web/js/init.js index 18b5575..ba89cc5 100644 --- a/web/js/init.js +++ b/web/js/init.js @@ -1,9 +1,9 @@ -var currentDate = new Date('Jul 21, 2024 22:00:00'); +var currentDate = new Date('Jul 31, 2024 17:00:00'); var day = currentDate.getDate(); var month = currentDate.getMonth() + 1; // Months are zero-indexed, so add 1 var year = currentDate.getFullYear(); var formattedDate = day + '/' + month + '/' + year; -var currentVersion = 'v1.2.5 [' + formattedDate + ']'; +var currentVersion = 'v1.2.6 [' + formattedDate + ']'; getInitialSettings(); diff --git a/web/js/main.js b/web/js/main.js index 060e9dd..6186273 100644 --- a/web/js/main.js +++ b/web/js/main.js @@ -432,7 +432,8 @@ function checkKey(e) { if ($('#password:focus').length > 0 || $('#chat-send-message:focus').length > 0 || $('#volumeSlider:focus').length > 0 - || $('#chat-nickname:focus').length > 0) { + || $('#chat-nickname:focus').length > 0 + || $('.option:focus').length > 0) { return; } @@ -612,7 +613,7 @@ function findOnMaps() { function updateSignalUnits(parsedData, averageSignal) { const signalUnit = localStorage.getItem('signalUnit'); let currentSignal; - let highestSignal = parsedData.highestSignal; + let highestSignal = parsedData.sigTop; currentSignal = averageSignal let signalText = $('.signal-units'); @@ -720,7 +721,7 @@ const updateDataElements = throttle(function(parsedData) { stereoColor = 'var(--color-3)'; } - if(parsedData.st_forced) { + if(parsedData.stForced) { stereoColor = 'gray'; } $dataSt.css('border', '2px solid ' + stereoColor); @@ -747,14 +748,14 @@ const updateDataElements = throttle(function(parsedData) { $dataBwInput.val($('#data-bw li[data-value="' + parsedData.bw + '"]').text()); } - if (parsedData.txInfo.station.length > 1) { - updateTextIfChanged($('#data-station-name'), parsedData.txInfo.station.replace(/%/g, '%25')); + if (parsedData.txInfo.tx.length > 1) { + updateTextIfChanged($('#data-station-name'), parsedData.txInfo.tx.replace(/%/g, '%25')); updateTextIfChanged($('#data-station-erp'), parsedData.txInfo.erp); updateTextIfChanged($('#data-station-city'), parsedData.txInfo.city); updateTextIfChanged($('#data-station-itu'), parsedData.txInfo.itu); updateTextIfChanged($('#data-station-pol'), parsedData.txInfo.pol); - updateTextIfChanged($('#data-station-distance'), parsedData.txInfo.distance); - updateTextIfChanged($('#data-station-azimuth'), parsedData.txInfo.azimuth); + updateTextIfChanged($('#data-station-distance'), parsedData.txInfo.dist); + updateTextIfChanged($('#data-station-azimuth'), parsedData.txInfo.azi); $dataStationContainer.css('display', 'block'); } else { $dataStationContainer.removeAttr('style'); @@ -786,7 +787,7 @@ let isEventListenerAdded = false; function updatePanels(parsedData) { updateCounter++; - signalData.push(parsedData.signal); + signalData.push(parsedData.sig); if (signalData.length > 8) { signalData.shift(); // Remove the oldest element } @@ -840,8 +841,10 @@ function updateButtonState(buttonId, value) { var button = $("#" + buttonId); if (value == 0) { button.hasClass("btn-disabled") ? null : button.addClass("btn-disabled"); + button.attr('aria-description', 'Off'); } else { button.hasClass("btn-disabled") ? button.removeClass("btn-disabled") : null; + button.attr('aria-description', 'On'); } } @@ -856,7 +859,7 @@ function toggleButtonState(buttonId) { function toggleForcedStereo() { var message = "B"; - message += parsedData.st_forced = (parsedData.st_forced == "1") ? "0" : "1"; + message += parsedData.stForced = (parsedData.stForced == "1") ? "0" : "1"; socket.send(message); } @@ -865,7 +868,7 @@ function toggleAdminLock() { if($adminLockButton.hasClass('active')) { socket.send('wL0'); - $adminLockButton.attr('aria-label', '"ock Tuner (Admin)') + $adminLockButton.attr('aria-label', 'Lock Tuner (Admin)') $adminLockButton.removeClass('active'); } else { socket.send('wL1'); diff --git a/web/js/settings.js b/web/js/settings.js index 57006c2..c9e2680 100644 --- a/web/js/settings.js +++ b/web/js/settings.js @@ -33,6 +33,12 @@ $(document).ready(() => { if(defaultTheme && themes[defaultTheme]) { setTheme(defaultTheme); } + + const themeParameter = getQueryParameter('theme'); + if(themeParameter && themes[themeParameter]) { + setTheme(themeParameter); + themeSelector.find('input').val(themeSelector.find('.option[data-value="' + themeParameter + '"]').text()); + } if (savedTheme && themes[savedTheme]) { setTheme(savedTheme); @@ -49,6 +55,12 @@ $(document).ready(() => { const signalSelector = $('#signal-selector'); + const signalParameter = getQueryParameter('signalUnits'); + if(signalParameter) { + signalSelector.find('input').val($(signalParameter).text()); + localStorage.setItem('signalUnit', signalParameter); + } + if (localStorage.getItem('signalUnit')) { signalSelector.find('input').val(signalSelector.find('.option[data-value="' + savedUnit + '"]').text()); } @@ -123,9 +135,16 @@ $(document).ready(() => { localStorage.setItem("extendedFreqRange", isChecked); }); - var extendedFreqRange = localStorage.getItem("psUnderscores"); - if (extendedFreqRange === "true") { - $("#ps-underscores").prop("checked", true); + const psUnderscoreParameter = getQueryParameter('psUnderscores'); + if(psUnderscoreParameter) { + $("#ps-underscores").prop("checked", psUnderscoreParameter); + localStorage.setItem("psUnderscores", psUnderscoreParameter); + } + + var psUnderscores = localStorage.getItem("psUnderscores"); + if (psUnderscores) { + $("#ps-underscores").prop("checked", psUnderscores); + localStorage.setItem("psUnderscores", psUnderscores); } $("#ps-underscores").change(function() { @@ -138,6 +157,10 @@ $(document).ready(() => { setBg(); }); +function getQueryParameter(name) { + const urlParams = new URLSearchParams(window.location.search); + return urlParams.get(name); +} function setTheme(themeName) { const themeColors = themes[themeName]; @@ -162,7 +185,8 @@ function setTheme(themeName) { } function setBg() { - if(localStorage.getItem('bgImage').length > 5 && localStorage.getItem('theme') != 'theme9') { + const disableBackgroundParameter = getQueryParameter('disableBackground'); + if(localStorage.getItem('bgImage').length > 5 && localStorage.getItem('theme') != 'theme9' && disableBackgroundParameter != 'true') { $('body').css('background', 'url(' + localStorage.getItem('bgImage') + ') top center / cover fixed no-repeat var(--color-main)'); } else { $('body').css('background', 'var(--color-main)'); diff --git a/web/setup.ejs b/web/setup.ejs index 0c1fd28..26aa86e 100644 --- a/web/setup.ejs +++ b/web/setup.ejs @@ -101,15 +101,15 @@

Maintenance

- +
- - + +
- +

@@ -145,7 +145,7 @@
- +
@@ -277,17 +277,17 @@
@@ -296,12 +296,12 @@

Antenna options

- +

- +
@@ -310,7 +310,7 @@

- +
@@ -319,7 +319,7 @@

- +
@@ -328,7 +328,7 @@

- +
@@ -344,7 +344,7 @@

Tuning options

- +

@@ -354,7 +354,7 @@

If you want to limit which frequencies the users can tune to,
you can set the lower and upper limit here.
Enter frequencies in MHz.

-
+

@@ -372,7 +372,7 @@

RDS Mode

You can switch between American (RBDS) / Global (RDS) mode here.

- +
@@ -403,7 +403,7 @@

Chat options

- +
@@ -443,18 +443,18 @@

- +

@@ -491,7 +491,7 @@

If your location information is filled,
you can add your tuner to a public list.

- +

diff --git a/web/wizard.ejs b/web/wizard.ejs index e69fa8c..e9fe5e2 100644 --- a/web/wizard.ejs +++ b/web/wizard.ejs @@ -70,7 +70,7 @@

Tuner connection: