Reworked webchat with new UI

This patch reworks the webchat UI to work in both desktop
and mobile layouts.  Comprimises were made, but there is 1
codebase now between both desktop and mobile.
This patch also includes the new imessage/sms chat look.
This commit is contained in:
Hemna 2023-09-08 11:19:24 -04:00
parent 29f21a9469
commit 14e984c9b4
3 changed files with 118 additions and 159 deletions

View File

@ -1,6 +1,6 @@
body {
background: #eeeeee;
margin: 2em;
margin: 1em;
text-align: center;
font-family: system-ui, sans-serif;
}
@ -11,34 +11,13 @@ footer {
height: 10vh;
}
.ui.segment {
background: #eeeeee;
}
ul.list {
list-style-type: disc;
}
ul.list li {
list-style-position: outside;
}
#left {
margin-right: 2px;
height: 300px;
}
#right {
height: 300px;
}
#center {
height: 300px;
}
#title {
font-size: 4em;
}
#version{
font-size: .5em;
}
#uptime, #aprsis {
font-size: 1em;
}
@ -66,29 +45,3 @@ ul.list li {
width: 16px;
height: 16px;
}
#msgsTabsDiv .ui.tab {
margin:0px;
padding:0px;
display: block;
}
#msgsTabsDiv .header, .tiny.text, .content, .break,
.thumbs.down.outline.icon,
.phone.volume.icon
{
display: inline-block;
float: left;
position: relative;
}
#msgsTabsDiv .tiny.text {
width:100px;
}
#msgsTabsDiv .tiny.header {
width:100px;
text-align: left;
}
#msgsTabsDiv .break {
margin: 2px;
text-align: left;
}

View File

@ -105,9 +105,12 @@ function init_messages() {
console.log("Adding callsign " + callsign);
if (first_callsign === null) {
first_callsign = callsign;
active = true;
console.log("first_callsign " + first_callsign)
} else {
active = false;
}
create_callsign_tab(callsign);
create_callsign_tab(callsign, active);
}
// and then populate the messages in order
for (callsign in message_list) {
@ -131,27 +134,54 @@ function init_messages() {
}
//Click on the very first tab
/*
if (first_callsign !== null) {
click_div = '#'+tab_string(first_callsign);
callsign_tab_id = callsign_tab(first_callsign);
var click_timer = setTimeout(function() {
console.log("Click on first tab " + click_div);
$(click_div).click();
console.log("Click on first tab " + callsign_tab_id);
$(callsign_tab_id).click();
clearTimeout(click_timer);
}, 500);
}
*/
}
function create_callsign_tab(callsign) {
function create_callsign_tab(callsign, active=false) {
//Create the html for the callsign tab and insert it into the DOM
console.log("create_callsign_tab " + callsign)
var callsignTabs = $("#callsignTabs");
tab_name = tab_string(callsign);
var callsignTabs = $("#msgsTabList");
tab_id = tab_string(callsign);
tab_content = tab_content_name(callsign);
divname = content_divname(callsign);
if (active) {
active_str = "active";
} else {
active_str = "";
}
item_html = '<div class="tablinks" id="'+tab_name+'" onclick="openCallsign(event, \''+callsign+'\');">'+callsign+'</div>';
item_html = '<li class="nav-item" role="presentation">';
item_html += '<button class="nav-link '+active_str+'" id="'+tab_id+'" data-bs-toggle="tab" data-bs-target="#'+tab_content+'" type="button" role="tab" aria-controls="'+callsign+'" aria-selected="true">'+callsign+'</button>';
item_html += '</li>';
console.log(item_html);
callsignTabs.append(item_html);
create_callsign_tab_content(callsign, active);
}
function create_callsign_tab_content(callsign, active=false) {
console.log("create_callsign_tab_content for CALLSIGN=" + callsign)
var callsignTabsContent = $("#msgsTabContent");
tab_id = tab_string(callsign);
tab_content = tab_content_name(callsign);
wrapper_id = tab_content_speech_wrapper(callsign);
if (active) {
active_str = "show active";
} else {
active_str = '';
}
item_html = '<div class="tab-pane fade '+active_str+'" id="'+tab_content+'" role="tabpanel" aria-labelledby="'+tab_id+'">';
item_html += '<div class="speech-wrapper" id="'+wrapper_id+'"></div>';
item_html += '</div>';
callsignTabsContent.append(item_html);
}
function add_callsign(callsign) {
@ -159,7 +189,13 @@ function add_callsign(callsign) {
if (callsign in callsign_list) {
return false
}
create_callsign_tab(callsign);
len = Object.keys(callsign_list).length;
if (len == 0) {
active = true;
} else {
active = false;
}
create_callsign_tab(callsign, active);
callsign_list[callsign] = true;
return true
}
@ -179,9 +215,9 @@ function append_message(callsign, msg, msg_html) {
new_callsign = add_callsign(callsign);
append_message_html(callsign, msg_html, new_callsign);
if (new_callsign) {
//click on the new tab
click_div = '#'+tab_string(callsign);
$(click_div).click();
//Now click the tab
callsign_tab_id = callsign_tab(callsign);
$(callsign_tab_id).click();
}
}
@ -193,50 +229,57 @@ function tab_content_name(callsign) {
return tab_string(callsign)+"Content";
}
function tab_content_speech_wrapper(callsign) {
return tab_string(callsign)+"SpeechWrapper";
}
function tab_content_speech_wrapper_id(callsign) {
return "#"+tab_content_speech_wrapper(callsign);
}
function content_divname(callsign) {
return "#"+tab_content_name(callsign);
}
function callsign_tab(callsign) {
return "#"+tab_string(callsign);
}
function append_message_html(callsign, msg_html, new_callsign) {
var msgsTabs = $('#msgsTabsDiv');
console.log("append_message_html " + callsign + " " + msg_html + " " + new_callsign);
console.log("append_message_html " + callsign + " new callsign? " + new_callsign);
divname_str = tab_content_name(callsign);
divname = content_divname(callsign);
if (new_callsign) {
// we have to add a new DIV
console.log("new callsign, create msg_div_html ");
msg_div_html = '<div class="speech-wrapper" id="'+divname_str+'">'+msg_html+'</div>';
console.log(msg_div_html);
msgsTabs.append(msg_div_html);
} else {
var msgDiv = $(divname);
console.log("Appending ("+ msg_html + ") to " + divname);
console.log(msgDiv);
msgDiv.append(msg_html);
console.log(msgDiv);
}
console.log("divname " + divname);
console.log($(divname).length);
tab_content = tab_content_name(callsign);
wrapper_id = tab_content_speech_wrapper_id(callsign);
if ($(divname).length > 0) {
$(divname).animate({scrollTop: $(divname)[0].scrollHeight}, "fast");
console.log("Appending ("+ msg_html + ") to " + wrapper_id);
$(wrapper_id).append(msg_html);
console.log($(wrapper_id).html());
console.log("wrapper_id " + wrapper_id);
console.log($(wrapper_id).children().length);
if ($(wrapper_id).children().length > 0) {
$(wrapper_id).animate({scrollTop: $(wrapper_id)[0].scrollHeight}, "fast");
}
$(divname).trigger('click');
}
function create_message_html(date, time, from, to, message, ack_id, msg, acked=false) {
div_id = from + "_" + msg.id;
if (ack_id) {
bubble_class = "bubble alt"
bubble_name_class = "bubble-name alt"
alt = " alt"
} else {
bubble_class = "bubble"
bubble_name_class = "bubble-name"
alt = ""
}
bubble_class = "bubble" + alt
bubble_name_class = "bubble-name" + alt
date_str = date + " " + time;
msg_html = '<div class="'+ bubble_class + '">';
msg_html = '<div class="bubble-row'+alt+'">';
msg_html += '<div class="'+ bubble_class + '">';
msg_html += '<div class="bubble-text">';
msg_html += '<p class="'+ bubble_name_class +'">'+from+'&nbsp;&nbsp;';
msg_html += '<span class="bubble-timestamp">'+date_str+'</span>';
@ -257,7 +300,7 @@ function create_message_html(date, time, from, to, message, ack_id, msg, acked=f
msg_html += '<p class="' +bubble_msg_class+ '">'+message+'</p>';
msg_html += '<div class="'+ bubble_arrow_class + '"></div>';
msg_html += "</div></div>";
msg_html += "</div></div></div>";
return msg_html
}
@ -355,34 +398,3 @@ function callsign_select(callsign) {
var tocall = $("#to_call");
tocall.val(callsign);
}
function reset_Tabs() {
tabcontent = document.getElementsByClassName("speech-wrapper");
for (i = 0; i < tabcontent.length; i++) {
tabcontent[i].style.display = "none";
}
}
function openCallsign(evt, callsign) {
// This is called when a callsign tab is clicked
var i, tabcontent, tablinks;
tab_content = tab_content_name(callsign);
console.log("openCallsign " + tab_content);
tabs = document.getElementsByClassName("speech-wrapper");
console.log(tabs);
for (i = 0; i < tabs.length; i++) {
tabs[i].style.display = "none";
}
tablinks = document.getElementsByClassName("tablinks");
console.log(tablinks);
for (i = 0; i < tablinks.length; i++) {
tablinks[i].className = tablinks[i].className.replace(" active", "");
}
//$(tab_content).style.display = "block";
document.getElementById(tab_content).style.display = "block";
evt.target.className += " active";
callsign_select(callsign);
}

View File

@ -10,10 +10,8 @@
<!-- <script src="https://cdn.socket.io/4.1.2/socket.io.min.js" integrity="sha384-toS6mmwu70G0fw54EGlWWeA4z3dyJ+dlXBtSURSKN4vyRFOcxd3Bzjj/AoOwY+Rg" crossorigin="anonymous"></script> -->
<script src="/static/js/upstream/socket.io.min.js"></script>
<!-- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fomantic-ui/2.9.0/semantic.min.css"> -->
<link rel="stylesheet" href="/static/css/upstream/semantic.min.css">
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/fomantic-ui/2.9.0/semantic.min.js"></script> -->
<script src="/static/js/upstream/semantic.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-4bw+/aepP/YC94hEpVNVgiZdgIC5+VKNBQNGCHeKRQN+PtmoHDEXuppvnDJzQIu9" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-HwwvtgBNo3bZJJLYd8oVXjrBZt8cqVSpeBNS5n7C8IVInixGAoxmnlMuBnhbgrkm" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@24,200,1,200">
@ -36,7 +34,7 @@
console.log(initial_stats);
start_update();
init_chat();
reset_Tabs();
//reset_Tabs();
console.log("latitude", latitude);
console.log("longitude", longitude);
@ -55,49 +53,45 @@
</head>
<body>
<div class='ui text container'>
<h1 class='ui dividing header'>APRSD WebChat {{ version }}</h1>
</div>
<div class='ui grid text container'>
<div class='left floated ten wide column'>
<span style='color: green'>{{ callsign }}</span>
connected to
<span style='color: blue' id='aprs_connection'>{{ aprs_connection|safe }}</span>
<div class='container text-center'>
<div class="row">
<div class="column">
<h1>APRSD WebChat {{ version }}</h1>
</div>
</div>
<div class='right floated four wide column'>
<span id='uptime'>NONE</span>
<div class="row">
<div class="column">
<span style='color: green'>{{ callsign }}</span>
connected to
<span style='color: blue' id='aprs_connection'>{{ aprs_connection|safe }}</span>
<span id='uptime'>NONE</span>
</div>
</div>
</div>
<div class="ui container">
<h3 class="ui dividing header">Send Message</h3>
<div id="sendMsgDiv" class="ui mini text">
<form id="sendform" name="sendmsg" action="">
<div class="ui corner labeled input">
<label for="to_call" class="ui label">Callsign</label>
<input type="text" name="to_call" id="to_call" placeholder="To Callsign" size="11" maxlength="9">
<div class="ui corner label">
<i class="asterisk icon"></i>
</div>
<div class="row">
<form class="row gx-3 gy-2 align-items-center" id="sendform" name="sendmsg" action="">
<div class="col-sm-3">
<label for="to_call" class="visually-hidden">Callsign</label>
<input type="text" class="form-control mb-2 mr-sm-2" name="to_call" id="to_call" placeholder="To Callsign" size="11" maxlength="9">
</div>
<div class="ui labeled input">
<label for="message" class="ui label">Message</label>
<input type="text" name="message" id="message" size="40" maxlength="40">
<div class="col-sm-3">
<label for="message" class="visually-hidden">Message</label>
<input type="text" class="form-control mb-2 mr-sm-2" name="message" id="message" size="40" maxlength="40" placeholder="Message">
</div>
<div class="col-auto">
<input type="submit" name="submit" class="btn btn-primary mb-2" id="send_msg" value="Send" />
<button type="button" class="btn btn-primary mb-2" id="send_beacon" value="Send GPS Beacon">Send GPS Beacon</button>
<button type="button" class="btn btn-primary mb-2" id="wipe_local" value="wipe local storage">Wipe LocalStorage</button>
</div>
<input type="submit" name="submit" class="ui button" id="send_msg" value="Send" />
<button type="button" class="ui button" id="send_beacon" value="Send GPS Beacon">Send GPS Beacon</button>
<button type="button" class="ui button" id="wipe_local" value="wipe local storage">Wipe LocalStorage</button>
</form>
</div>
</div>
<div class="ui grid">
<div class="two wide column">
<div class="tab" id="callsignTabs"></div>
</div>
<div class="seven wide column ui raised segment" id="msgsTabsDiv" style="height:450px;padding:0px;">
<div class="row">
<div class="container-sm" style="max-width: 800px;">
<ul class="nav nav-tabs" id="msgsTabList" role="tablist">
</ul>
<div class="tab-content" id="msgsTabContent">
</div>
</div>
</div>
</div>