Skip to content
Open

Main #21

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
195 changes: 194 additions & 1 deletion console/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const defaultConfig = {
Radios: [],
Autoconnect: false,
ClockFormat: "UTC",
CallLogFormat: "Card",
Audio: {
ButtonSounds: true,
UnselectedVol: -9.0,
Expand Down Expand Up @@ -247,6 +248,7 @@ function pageLoad() {

// Setup clock timer
setInterval(updateClock, 100);

}

/**
Expand Down Expand Up @@ -493,7 +495,177 @@ window.electronAPI.saveMidiConfig((event, data) => {
/***********************************************************************************
Radio UI Functions
***********************************************************************************/
/**
* Setup the caller log toggles
* @param {HTMLElement[]} radios the radio cards to setup
* @returns {void}
* */
function setupCallerLog(radios){
if (config.CallLogFormat == "Drawer") {
$("#navbar-call-log").show();
//hide the caller-log-wrap
radios.forEach((radio, idx) => {
$(`#radio${idx} .caller-log-wrap`).removeClass('expanded');
$(`#radio${idx}`).removeClass('log-open');
$(`#radio${idx} .caller-log-wrap`).hide();
$(`#radio${idx} .caller-log-toggle`).hide();
$(`#radio${idx} .upper-content .icon-stack`).removeClass('call-chevron');
});
} else {
$("#navbar-call-log").hide();
$("#caller-drawer").removeClass('open');
radios.forEach((radio, idx) => {
$(`#radio${idx} .caller-log-wrap`).show();
$(`#radio${idx} .caller-log-toggle`).show();
$(`#radio${idx} .upper-content .icon-stack`).addClass('call-chevron');
});
}
}

/**
* Toggle the caller log on the radio card
* @param {HTMLElement} toggleAnchor the anchor element that was clicked
* @returns {void}
* */
function toggleCallerLog(toggleAnchor){
const cardEl = toggleAnchor.closest('.radio-card');

/* — use bottom drawer — */
if (config.CallLogFormat === "Drawer") {

const drawer = document.getElementById('caller-drawer');

//check if the drawer is open
if (drawer.classList.contains('open')){
//if it is, close it
closeCallerDrawer();
//set the toggle text
toggleAnchor.title = 'Show caller log';
return;
}
//open the drawer
openCallerDrawer(cardEl);
//set the toggle text
toggleAnchor.title = 'Hide caller log';
return; // skip inline behaviour
}
/* — use inline log — */
const wrap = toggleAnchor.previousElementSibling;

wrap.classList.toggle('expanded');
cardEl.classList.toggle('log-open', wrap.classList.contains('expanded'));

// tooltip text
toggleAnchor.title = wrap.classList.contains('expanded')
? 'Hide caller log' : 'Show caller log';
}

/************************************************************************
* Caller-log overlay drawer
***********************************************************************/

// holds a reference to the card whose log is showing – or null
let drawerCard = null;

function refreshCallerDrawer(cardEl){
if (config.CallLogFormat !== "Drawer") return; // feature not enabled
if (!drawerCard || drawerCard !== cardEl) return; // other card / closed

const body = document.getElementById('drawer-body');
const drawerTitle = document.getElementById('drawer-title');
const radioName = cardEl.querySelector('.radio-name').textContent;
const history = cardEl.querySelector('.caller-log');

body.innerHTML = '';
body.appendChild(history.cloneNode(true));

drawerTitle.innerHTML = `<ion-icon name="reader-outline"></ion-icon><span class="radio-name">&nbsp;${radioName}</span>`;
}

function selectDrawerCard(cardEl){
if (config.CallLogFormat !== "Drawer") return; // feature not enabled
drawerCard = cardEl;
//check if the drawer is open
const drawer = document.getElementById('caller-drawer');
if (drawer.classList.contains('open')){
// if it is, refresh the drawer
refreshCallerDrawer(cardEl);
}
}

function openCallerDrawer(cardEl){
drawerCard = cardEl;
refreshCallerDrawer(cardEl); // ← just do this
document.getElementById('caller-drawer').classList.add('open');
}

/** close the drawer */
function closeCallerDrawer(){
document.getElementById('caller-drawer').classList.remove('open');
drawerCard = null;
}
document.getElementById('drawer-close').onclick = closeCallerDrawer;

/**
* Show live caller-ID while the radio is Receiving.
* Only when the call *finishes* does the ID get added to the scroll-back.
*
* @param {HTMLElement} cardEl – the .radio-card element
* @param {string|null} idStr – the current caller-ID (null/"" when idle)
*/
function updateCallerId(cardEl, idStr){
// this object lives for the lifetime of the element
if (!cardEl._cidState){
cardEl._cidState = {
liveId : "", // ID currently shown in live line
active : false // true while RX is up
};
}
const st = cardEl._cidState;
const live = cardEl.querySelector('.callerid-live');
const log = cardEl.querySelector('.caller-log');

/* ── radio is Receiving ─────────────────────────────────────────── */
if (idStr){ // non-empty ⇒ still RX’ing
live.textContent = idStr; // update live line
st.liveId = idStr; // remember it
st.active = true; // mark "call in progress"

/* ── radio just went idle – append the *previous* ID ────────────── */
} else if (st.active){ // we *were* RXing and just stopped
st.active = false;

const timeStr =
(config?.ClockFormat === "UTC")
? getTimeUTC("HH:mm:ss")
: getTimeLocal("HH:mm:ss");

// build one <li> row and stick it on top of the UL
const li = document.createElement('li');
li.innerHTML =
`<span class="cid">${st.liveId}</span>
<span class="cidtime">${timeStr}</span>
<span class="cidlabel">PTT&nbsp;ID</span>`;
log.prepend(li);



var logLength = 3;
if (config.CallLogFormat === "Drawer"){
logLength = 10;
}
while (log.children.length > logLength){
log.removeChild(log.lastChild);
}

// clear the live line
live.textContent = "";
st.liveId = "";

// update the drawer if it's open
refreshCallerDrawer(cardEl);
}
}
/**
* Select a radio
* @param {string} id the id of the radio to select
Expand Down Expand Up @@ -521,6 +693,8 @@ function selectRadio(id) {
selectedRadioIdx = null;
// Update stream volumes
updateRadioAudio();
// Update the call log drawer
selectDrawerCard($(`#${id}`)[0]);
} else {
// Deselect all radio cards
deselectRadios();
Expand All @@ -532,6 +706,7 @@ function selectRadio(id) {
// Update controls
updateRadioControls();
updateRadioAudio();
selectDrawerCard($(`#${id}`)[0]);
}
// Update the extension
exUpdateSelected();
Expand Down Expand Up @@ -888,6 +1063,10 @@ function updateRadioCard(idx) {
const shortChan = radio.status.ChannelName.substring(0,19);
radioCard.find("#channel-text").html(shortChan);
}
// Update caller ID
if (radio.status.CallerId != null) {
updateCallerId(radioCard[0], radio.status.CallerId);
}

// Remove all current classes
setTimeout(function() {
Expand Down Expand Up @@ -1620,6 +1799,8 @@ async function readConfig() {
$("#daemon-autoconnect").prop('checked', config.Autoconnect);
// Clock Format
$("#client-timeformat").val(config.ClockFormat);
// Call log format
$("#client-call-log").val(config.CallLogFormat);
// Audio stuff
$("#client-rxagc").prop("checked", config.Audio.UseAGC);
// Unselected Volume
Expand Down Expand Up @@ -1676,16 +1857,23 @@ async function readConfig() {
if (config.Autoconnect) {
connectAllButton();
}

//setup call log
setupCallerLog(radios);

}

async function saveConfig() {

// Client config values
const clockFormat = $("#client-timeformat").val();
const callLogFormat = $("#client-call-log").val();
const useAgc = $("#client-rxagc").is(":checked");
const unselectedVol = $("#unselected-vol").val();
const toneVol = $("#tone-vol").val();
config.ClockFormat = clockFormat;

config.ClockFormat = clockFormat;
config.CallLogFormat = callLogFormat;
config.Audio.UseAGC = useAgc;
config.Audio.UnselectedVol = parseFloat(unselectedVol);
config.Audio.ToneVolume = parseFloat(toneVol);
Expand All @@ -1705,13 +1893,18 @@ async function saveConfig() {
if (audio.context) {
updateRadioAudio();
}
// Update the call log format
setupCallerLog(config.Radios);

const result = await window.electronAPI.saveConfig(JSON.stringify(config, null, 4));

if (result != true)
{
alert("Failed to save config: " + result);
}



}

function newRadioClear() {
Expand Down
Loading
Loading