chat system implementation in the web

This commit is contained in:
Stanislav Lechev [0xAF] 2023-11-20 04:59:59 +02:00
parent 4cc504f001
commit 7f4fa70364
4 changed files with 115 additions and 18 deletions

View File

@ -309,11 +309,30 @@ input[type=range]:disabled {
#openwebrx-log-scroll #openwebrx-log-scroll
{ {
/*overflow-y:auto;*/ /*overflow-y:auto;*/
height: 125px; height: 155px;
max-width: 619px; max-width: 619px;
width: 100%; width: 100%;
} }
#openwebrx-messages .nickname {
color: #bbb;
font-weight: bold;
}
#openwebrx-messages .chatmessage {
}
#openwebrx-chat-inputs {
height: 1.5rem;
position: absolute;
bottom: 0;
width: 99%
}
#openwebrx-log-scroll .nano-content, #openwebrx-log-scroll .nano-pane {
height: 126px;
}
.nano .nano-pane { background: #444; } .nano .nano-pane { background: #444; }
.nano .nano-slider { background: #eee !important; } .nano .nano-slider { background: #eee !important; }

View File

@ -163,15 +163,25 @@
</div> </div>
</div> </div>
<div class="openwebrx-panel" id="openwebrx-panel-log" data-panel-name="debug" style="width: 92%; max-width: 619px;"> <div class="openwebrx-panel" id="openwebrx-panel-log" data-panel-name="debug" style="width: 92%; max-width: 619px;">
<div class="openwebrx-panel-inner nano" id="openwebrx-log-scroll"> <div style="position: relative; height: 100%">
<div class="nano-content"> <div class="openwebrx-panel-inner nano" id="openwebrx-log-scroll">
<div id="openwebrx-client-log-title">OpenWebRX+ client log</div> <div class="nano-content">
<div> <div id="openwebrx-client-log-title">OpenWebRX+ message log</div>
Author contact: <a href="http://fms.komkon.org/" target="_blank">Marat Fayzullin</a> | <div>
<a href="https://www.openwebrx.de" target="_blank">OpenWebRX homepage</a> Author: <a href="http://fms.komkon.org/" target="_blank">Marat Fayzullin</a> |
<a href="https://www.openwebrx.de" target="_blank">OpenWebRX</a>,
Support and information: <a href="https://groups.io/g/openwebrx" target="_blank">Groups.io Mailinglist</a>
</div>
<hr>
<div id="openwebrx-messages"></div>
</div>
</div>
<div id="openwebrx-chat-inputs">
<div class="input-group" style="display: flex; justify-content: space-between;">
<input id="chatCallsign" style="width:15%; margin-right: 0.2rem" placeholder="Callsign" />
<input id="chatMessage" style="width:99%; margin-right: 0.2rem" />
<div class="openwebrx-button" onClick="chatSendMessage()">Send</div>
</div> </div>
<div>Support and information: <a href="https://groups.io/g/openwebrx" target="_blank">Groups.io Mailinglist</a></div>
<div id="openwebrx-debugdiv"></div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -25,6 +25,7 @@ UI.sections = {
// Load UI settings from local storage. // Load UI settings from local storage.
UI.loadSettings = function() { UI.loadSettings = function() {
this.setNickname(LS.has('nickname')? LS.loadStr('nickname') : '');
this.setTheme(LS.has('ui_theme')? LS.loadStr('ui_theme') : 'default'); this.setTheme(LS.has('ui_theme')? LS.loadStr('ui_theme') : 'default');
this.setOpacity(LS.has('ui_opacity')? LS.loadInt('ui_opacity') : 100); this.setOpacity(LS.has('ui_opacity')? LS.loadInt('ui_opacity') : 100);
this.toggleFrame(LS.has('ui_frame')? LS.loadBool('ui_frame') : false); this.toggleFrame(LS.has('ui_frame')? LS.loadBool('ui_frame') : false);
@ -238,3 +239,17 @@ UI.setTheme = function(theme) {
$('body').addClass('has-theme'); $('body').addClass('has-theme');
} }
}; };
// Set user interface theme.
UI.setNickname = function(nickname) {
// Do not set twice
if (this.nickname === nickname) return;
// Save current theme name
this.nickname = nickname;
LS.save('nickname', nickname);
// Set input
$('#chatCallsign').val(nickname);
};

View File

@ -121,8 +121,13 @@ function jumpBySteps(steps) {
} }
function recvChatMessage(sender, text, color = "white") { function recvChatMessage(sender, text, color = "white") {
divlog('<font color="' + color + '"><b>' + sender + ':</b> ' toggle_panel("openwebrx-panel-log", true); //show panel
+ text + '</font>', false); $('#openwebrx-messages')[0].innerHTML +=
"[<span class='nickname' style='color: " + color + "'>" + sender + "</span>]:&nbsp;" +
"<span class='chatmessage'>" + text + "</span><br />";
var nano = $('#openwebrx-log-scroll');
nano.nanoScroller();
nano.nanoScroller({scroll: 'bottom'});
} }
function sendChatMessage(text, sender = "") { function sendChatMessage(text, sender = "") {
@ -131,6 +136,47 @@ function sendChatMessage(text, sender = "") {
})); }));
} }
var lastChatMsg = "";
function chatSendMessage () {
var callsign = $('#chatCallsign').val();
UI.setNickname(callsign);
var msg = $('#chatMessage').val().trim();
if (msg.length > 0) {
lastChatMsg = msg;
sendChatMessage(msg, callsign);
}
$('#chatMessage').val('');
}
function chatKeyDown (event) {
// basic support of last msg
// TODO: make msg history to browse with up/down arrows
var input = $('#chatMessage');
if (event.key == "Enter") {
chatSendMessage();
} else if (event.key == "ArrowUp") {
input.focus().val(lastChatMsg);
} else if (event.key == "ArrowDown") {
input.focus().val('');
}
}
// focus the chat input when the log window is clicked,
// this needs to be handled onLoad, since jQuery is not loaded yet.
document.addEventListener("DOMContentLoaded", function (event) {
$('.nano-content').mouseup(function () {
const selection = window.getSelection().toString();
if (selection === '') {
// it's a click, we focus on the msg input
$('#chatMessage').focus();
} else {
// it's a mouse text-selection, ignore it.
}
});
$('#chatMessage').on('keydown', chatKeyDown)
});
var waterfall_min_level; var waterfall_min_level;
var waterfall_max_level; var waterfall_max_level;
var waterfall_min_level_default; var waterfall_min_level_default;
@ -977,9 +1023,9 @@ function on_ws_recv(evt) {
); );
var versionInfo = 'Unknown server'; var versionInfo = 'Unknown server';
if (params.server && params.server === 'openwebrx' && params.version) { if (params.server && params.server === 'openwebrx' && params.version) {
versionInfo = 'OpenWebRX+ version: ' + params.version; versionInfo = 'OpenWebRX<b>+</b> version: <b>' + params.version + "</b>";
} }
divlog('Server acknowledged WebSocket connection, ' + versionInfo); divlog('Server acknowledged WebSocket connection, ' + versionInfo + "");
} else { } else {
try { try {
var json = JSON.parse(evt.data); var json = JSON.parse(evt.data);
@ -1021,15 +1067,17 @@ function on_ws_recv(evt) {
fft_size = config['fft_size']; fft_size = config['fft_size'];
waterfall_clear(); waterfall_clear();
} }
var streams_msg = "";
if ('audio_compression' in config) { if ('audio_compression' in config) {
var audio_compression = config['audio_compression']; var audio_compression = config['audio_compression'];
audioEngine.setCompression(audio_compression); audioEngine.setCompression(audio_compression);
divlog("Audio stream is " + ((audio_compression === "adpcm") ? "compressed" : "uncompressed") + "."); streams_msg = "Audio stream is <b>" + ((audio_compression === "adpcm") ? "compressed" : "uncompressed") + "</b>. ";
} }
if ('fft_compression' in config) { if ('fft_compression' in config) {
fft_compression = config['fft_compression']; fft_compression = config['fft_compression'];
divlog("FFT stream is " + ((fft_compression === "adpcm") ? "compressed" : "uncompressed") + "."); streams_msg += "FFT stream is <b>" + ((fft_compression === "adpcm") ? "compressed" : "uncompressed") + "</b>.";
} }
if (streams_msg.length) divlog(streams_msg);
if ('max_clients' in config) if ('max_clients' in config)
$('#openwebrx-bar-clients').progressbar().setMaxClients(config['max_clients']); $('#openwebrx-bar-clients').progressbar().setMaxClients(config['max_clients']);
@ -1283,7 +1331,7 @@ function waterfall_measure_minmax_do(what) {
function on_ws_opened() { function on_ws_opened() {
$('#openwebrx-error-overlay').hide(); $('#openwebrx-error-overlay').hide();
ws.send("SERVER DE CLIENT client=openwebrx.js type=receiver"); ws.send("SERVER DE CLIENT client=openwebrx.js type=receiver");
divlog("WebSocket opened to " + ws.url); divlog("WebSocket opened to <b>" + ws.url + "</b>");
if (!networkSpeedMeasurement) { if (!networkSpeedMeasurement) {
networkSpeedMeasurement = new Measurement(); networkSpeedMeasurement = new Measurement();
networkSpeedMeasurement.report(60000, 1000, function(rate){ networkSpeedMeasurement.report(60000, 1000, function(rate){
@ -1311,7 +1359,7 @@ function divlog(what, is_error) {
what = "<span class=\"webrx-error\">" + what + "</span>"; what = "<span class=\"webrx-error\">" + what + "</span>";
toggle_panel("openwebrx-panel-log", true); //show panel if any error is present toggle_panel("openwebrx-panel-log", true); //show panel if any error is present
} }
$('#openwebrx-debugdiv')[0].innerHTML += what + "<br />"; $('#openwebrx-messages')[0].innerHTML += what + "<br />";
var nano = $('#openwebrx-log-scroll'); var nano = $('#openwebrx-log-scroll');
nano.nanoScroller(); nano.nanoScroller();
nano.nanoScroller({scroll: 'bottom'}); nano.nanoScroller({scroll: 'bottom'});
@ -1324,7 +1372,7 @@ var mute = false;
var audio_buffer_maximal_length_sec = 1; //actual number of samples are calculated from sample rate var audio_buffer_maximal_length_sec = 1; //actual number of samples are calculated from sample rate
function onAudioStart(apiType){ function onAudioStart(apiType){
divlog('Web Audio API succesfully initialized, using ' + apiType + ' API, sample rate: ' + audioEngine.getSampleRate() + " Hz"); divlog('Web Audio API initialized, with <b>' + apiType + '</b> API, sample rate: <b>' + audioEngine.getSampleRate() + "</b>Hz");
hideOverlay(); hideOverlay();
@ -1679,6 +1727,11 @@ function toggle_panel(what, on) {
} }
item.style.transitionDuration = "600ms"; item.style.transitionDuration = "600ms";
item.style.transitionDelay = "0ms"; item.style.transitionDelay = "0ms";
if (what === "openwebrx-panel-log") {
setTimeout(function () {
$('#chatMessage').focus();
}, 50);
}
} }
function first_show_panel(panel) { function first_show_panel(panel) {