mirror of
https://github.com/DJ2LS/FreeDATA
synced 2024-05-14 08:04:33 +00:00
[CodeFactor] Apply fixes
This commit is contained in:
parent
c39af3f830
commit
90401e7df5
|
@ -1,10 +1,9 @@
|
|||
import { app, BrowserWindow, shell, ipcMain } from 'electron'
|
||||
import { release, platform } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { autoUpdater } from "electron-updater"
|
||||
import { existsSync } from "fs"
|
||||
import { spawn } from "child_process"
|
||||
|
||||
import { app, BrowserWindow, shell, ipcMain } from "electron";
|
||||
import { release, platform } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { autoUpdater } from "electron-updater";
|
||||
import { existsSync } from "fs";
|
||||
import { spawn } from "child_process";
|
||||
|
||||
// The built directory structure
|
||||
//
|
||||
|
@ -16,22 +15,22 @@ import { spawn } from "child_process"
|
|||
// ├─┬ dist
|
||||
// │ └── index.html > Electron-Renderer
|
||||
//
|
||||
process.env.DIST_ELECTRON = join(__dirname, '..')
|
||||
process.env.DIST = join(process.env.DIST_ELECTRON, '../dist')
|
||||
process.env.DIST_ELECTRON = join(__dirname, "..");
|
||||
process.env.DIST = join(process.env.DIST_ELECTRON, "../dist");
|
||||
process.env.VITE_PUBLIC = process.env.VITE_DEV_SERVER_URL
|
||||
? join(process.env.DIST_ELECTRON, '../public')
|
||||
: process.env.DIST
|
||||
? join(process.env.DIST_ELECTRON, "../public")
|
||||
: process.env.DIST;
|
||||
|
||||
// Disable GPU Acceleration for Windows 7
|
||||
if (release().startsWith('6.1')) app.disableHardwareAcceleration()
|
||||
if (release().startsWith("6.1")) app.disableHardwareAcceleration();
|
||||
|
||||
// Set application name for Windows 10+ notifications
|
||||
if (process.platform === 'win32') app.setAppUserModelId(app.getName())
|
||||
if (process.platform === "win32") app.setAppUserModelId(app.getName());
|
||||
|
||||
if (!app.requestSingleInstanceLock()) {
|
||||
close_sub_processes()
|
||||
app.quit()
|
||||
process.exit(0)
|
||||
close_sub_processes();
|
||||
app.quit();
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Remove electron security warnings
|
||||
|
@ -41,18 +40,18 @@ if (!app.requestSingleInstanceLock()) {
|
|||
|
||||
// set daemon process var
|
||||
var daemonProcess = null;
|
||||
let win: BrowserWindow | null = null
|
||||
let win: BrowserWindow | null = null;
|
||||
// Here, you can also use other preload
|
||||
const preload = join(__dirname, '../preload/index.js')
|
||||
const url = process.env.VITE_DEV_SERVER_URL
|
||||
const indexHtml = join(process.env.DIST, 'index.html')
|
||||
const preload = join(__dirname, "../preload/index.js");
|
||||
const url = process.env.VITE_DEV_SERVER_URL;
|
||||
const indexHtml = join(process.env.DIST, "index.html");
|
||||
|
||||
async function createWindow() {
|
||||
win = new BrowserWindow({
|
||||
title: 'FreeDATA',
|
||||
title: "FreeDATA",
|
||||
width: 1200,
|
||||
height: 670,
|
||||
icon: join(process.env.VITE_PUBLIC, 'icon_cube_border.png'),
|
||||
icon: join(process.env.VITE_PUBLIC, "icon_cube_border.png"),
|
||||
autoHideMenuBar: true,
|
||||
webPreferences: {
|
||||
preload,
|
||||
|
@ -64,29 +63,29 @@ async function createWindow() {
|
|||
nodeIntegration: true,
|
||||
contextIsolation: false,
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
if (process.env.VITE_DEV_SERVER_URL) { // electron-vite-vue#298
|
||||
win.loadURL(url)
|
||||
if (process.env.VITE_DEV_SERVER_URL) {
|
||||
// electron-vite-vue#298
|
||||
win.loadURL(url);
|
||||
// Open devTool if the app is not packaged
|
||||
win.webContents.openDevTools()
|
||||
win.webContents.openDevTools();
|
||||
} else {
|
||||
win.loadFile(indexHtml)
|
||||
win.loadFile(indexHtml);
|
||||
}
|
||||
|
||||
// Test actively push message to the Electron-Renderer
|
||||
win.webContents.on('did-finish-load', () => {
|
||||
win?.webContents.send('main-process-message', new Date().toLocaleString())
|
||||
})
|
||||
win.webContents.on("did-finish-load", () => {
|
||||
win?.webContents.send("main-process-message", new Date().toLocaleString());
|
||||
});
|
||||
|
||||
// Make all links open with the browser, not with the application
|
||||
win.webContents.setWindowOpenHandler(({ url }) => {
|
||||
if (url.startsWith('https:')) shell.openExternal(url)
|
||||
return { action: 'deny' }
|
||||
})
|
||||
if (url.startsWith("https:")) shell.openExternal(url);
|
||||
return { action: "deny" };
|
||||
});
|
||||
// win.webContents.on('will-navigate', (event, url) => { }) #344
|
||||
|
||||
|
||||
win.once("ready-to-show", () => {
|
||||
//autoUpdater.logger = log.scope("updater");
|
||||
//autoUpdater.channel = config.update_channel;
|
||||
|
@ -95,14 +94,11 @@ async function createWindow() {
|
|||
autoUpdater.checkForUpdatesAndNotify();
|
||||
//autoUpdater.quitAndInstall();
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
//app.whenReady().then(
|
||||
app.whenReady().then(() => {
|
||||
|
||||
createWindow()
|
||||
createWindow();
|
||||
|
||||
//Generate daemon binary path
|
||||
var daemonPath = "";
|
||||
|
@ -114,11 +110,7 @@ createWindow()
|
|||
break;
|
||||
case "win32":
|
||||
case "win64":
|
||||
daemonPath = join(
|
||||
process.resourcesPath,
|
||||
"modem",
|
||||
"freedata-daemon.exe",
|
||||
);
|
||||
daemonPath = join(process.resourcesPath, "modem", "freedata-daemon.exe");
|
||||
break;
|
||||
default:
|
||||
console.log("Unhandled OS Platform: ", platform());
|
||||
|
@ -156,59 +148,49 @@ createWindow()
|
|||
console.log("Daemon binary doesn't exist--normal for dev environments.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//)
|
||||
//)
|
||||
});
|
||||
|
||||
app.on("window-all-closed", () => {
|
||||
win = null;
|
||||
if (process.platform !== "darwin") app.quit(close_sub_processes());
|
||||
});
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
win = null
|
||||
if (process.platform !== 'darwin') app.quit(
|
||||
close_sub_processes()
|
||||
|
||||
)
|
||||
})
|
||||
|
||||
app.on('second-instance', () => {
|
||||
app.on("second-instance", () => {
|
||||
if (win) {
|
||||
// Focus on the main window if the user tried to open another
|
||||
if (win.isMinimized()) win.restore()
|
||||
win.focus()
|
||||
if (win.isMinimized()) win.restore();
|
||||
win.focus();
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
app.on('activate', () => {
|
||||
const allWindows = BrowserWindow.getAllWindows()
|
||||
app.on("activate", () => {
|
||||
const allWindows = BrowserWindow.getAllWindows();
|
||||
if (allWindows.length) {
|
||||
allWindows[0].focus()
|
||||
allWindows[0].focus();
|
||||
} else {
|
||||
createWindow()
|
||||
createWindow();
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
// New window example arg: new windows url
|
||||
ipcMain.handle('open-win', (_, arg) => {
|
||||
ipcMain.handle("open-win", (_, arg) => {
|
||||
const childWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
preload,
|
||||
nodeIntegration: true,
|
||||
contextIsolation: false,
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
if (process.env.VITE_DEV_SERVER_URL) {
|
||||
childWindow.loadURL(`${url}#${arg}`)
|
||||
childWindow.loadURL(`${url}#${arg}`);
|
||||
} else {
|
||||
childWindow.loadFile(indexHtml, { hash: arg })
|
||||
childWindow.loadFile(indexHtml, { hash: arg });
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
//restart and install udpate
|
||||
//restart and install udpate
|
||||
ipcMain.on("request-restart-and-install-update", (event, data) => {
|
||||
close_sub_processes();
|
||||
autoUpdater.quitAndInstall();
|
||||
|
@ -275,7 +257,6 @@ autoUpdater.on("error", (error) => {
|
|||
console.log("AUTO UPDATER : " + error);
|
||||
});
|
||||
|
||||
|
||||
function close_sub_processes() {
|
||||
console.log("closing sub processes");
|
||||
|
||||
|
@ -307,4 +288,4 @@ function close_sub_processes() {
|
|||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,34 +1,34 @@
|
|||
import { ipcRenderer } from "electron"
|
||||
import { autoUpdater } from "electron-updater"
|
||||
import { ipcRenderer } from "electron";
|
||||
import { autoUpdater } from "electron-updater";
|
||||
|
||||
|
||||
|
||||
function domReady(condition: DocumentReadyState[] = ['complete', 'interactive']) {
|
||||
function domReady(
|
||||
condition: DocumentReadyState[] = ["complete", "interactive"],
|
||||
) {
|
||||
return new Promise((resolve) => {
|
||||
if (condition.includes(document.readyState)) {
|
||||
resolve(true)
|
||||
resolve(true);
|
||||
} else {
|
||||
document.addEventListener('readystatechange', () => {
|
||||
document.addEventListener("readystatechange", () => {
|
||||
if (condition.includes(document.readyState)) {
|
||||
resolve(true)
|
||||
resolve(true);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
const safeDOM = {
|
||||
append(parent: HTMLElement, child: HTMLElement) {
|
||||
if (!Array.from(parent.children).find(e => e === child)) {
|
||||
return parent.appendChild(child)
|
||||
if (!Array.from(parent.children).find((e) => e === child)) {
|
||||
return parent.appendChild(child);
|
||||
}
|
||||
},
|
||||
remove(parent: HTMLElement, child: HTMLElement) {
|
||||
if (Array.from(parent.children).find(e => e === child)) {
|
||||
return parent.removeChild(child)
|
||||
if (Array.from(parent.children).find((e) => e === child)) {
|
||||
return parent.removeChild(child);
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* https://tobiasahlin.com/spinkit
|
||||
|
@ -37,7 +37,7 @@ const safeDOM = {
|
|||
* https://matejkustec.github.io/SpinThatShit
|
||||
*/
|
||||
function useLoading() {
|
||||
const className = `loaders-css__square-spin`
|
||||
const className = `loaders-css__square-spin`;
|
||||
const styleContent = `
|
||||
@keyframes square-spin {
|
||||
0% {
|
||||
|
@ -82,55 +82,48 @@ function useLoading() {
|
|||
background: #282c34;
|
||||
z-index: 99999;
|
||||
}
|
||||
`
|
||||
const oStyle = document.createElement('style')
|
||||
const oDiv = document.createElement('div')
|
||||
`;
|
||||
const oStyle = document.createElement("style");
|
||||
const oDiv = document.createElement("div");
|
||||
|
||||
oStyle.id = 'app-loading-style'
|
||||
oStyle.innerHTML = styleContent
|
||||
oDiv.className = 'app-loading-wrap'
|
||||
oDiv.innerHTML = `<div class="${className}"><div></div></div>`
|
||||
oStyle.id = "app-loading-style";
|
||||
oStyle.innerHTML = styleContent;
|
||||
oDiv.className = "app-loading-wrap";
|
||||
oDiv.innerHTML = `<div class="${className}"><div></div></div>`;
|
||||
|
||||
return {
|
||||
appendLoading() {
|
||||
safeDOM.append(document.head, oStyle)
|
||||
safeDOM.append(document.body, oDiv)
|
||||
safeDOM.append(document.head, oStyle);
|
||||
safeDOM.append(document.body, oDiv);
|
||||
},
|
||||
removeLoading() {
|
||||
safeDOM.remove(document.head, oStyle)
|
||||
safeDOM.remove(document.body, oDiv)
|
||||
safeDOM.remove(document.head, oStyle);
|
||||
safeDOM.remove(document.body, oDiv);
|
||||
},
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
const { appendLoading, removeLoading } = useLoading()
|
||||
domReady().then(appendLoading)
|
||||
|
||||
const { appendLoading, removeLoading } = useLoading();
|
||||
domReady().then(appendLoading);
|
||||
|
||||
window.onmessage = (ev) => {
|
||||
ev.data.payload === 'removeLoading' && removeLoading()
|
||||
}
|
||||
|
||||
setTimeout(removeLoading, 4999)
|
||||
|
||||
|
||||
|
||||
ev.data.payload === "removeLoading" && removeLoading();
|
||||
};
|
||||
|
||||
setTimeout(removeLoading, 4999);
|
||||
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
// we are using this area for implementing the electron runUpdater
|
||||
// we need access to DOM for displaying updater results in GUI
|
||||
// close app, update and restart
|
||||
// we are using this area for implementing the electron runUpdater
|
||||
// we need access to DOM for displaying updater results in GUI
|
||||
// close app, update and restart
|
||||
document
|
||||
.getElementById("update_and_install")
|
||||
.addEventListener("click", () => {
|
||||
ipcRenderer.send("request-restart-and-install-update");
|
||||
});
|
||||
|
||||
})
|
||||
|
||||
});
|
||||
|
||||
// IPC ACTION FOR AUTO UPDATER
|
||||
ipcRenderer.on("action-updater", (event, arg) => {
|
||||
|
@ -181,11 +174,12 @@ ipcRenderer.on("action-updater", (event, arg) => {
|
|||
//autoUpdater.quitAndInstall();
|
||||
}
|
||||
if (arg.status == "update-not-available") {
|
||||
|
||||
document.getElementById("updater_last_version").innerHTML = arg.info.releaseName
|
||||
document.getElementById("updater_last_update").innerHTML = arg.info.releaseDate
|
||||
document.getElementById("updater_release_notes").innerHTML = arg.info.releaseNotes
|
||||
|
||||
document.getElementById("updater_last_version").innerHTML =
|
||||
arg.info.releaseName;
|
||||
document.getElementById("updater_last_update").innerHTML =
|
||||
arg.info.releaseDate;
|
||||
document.getElementById("updater_release_notes").innerHTML =
|
||||
arg.info.releaseNotes;
|
||||
|
||||
document.getElementById("updater_status").innerHTML =
|
||||
'<i class="bi bi-check2-square ms-1 me-1" style="color: white;"></i>';
|
||||
|
|
|
@ -14,29 +14,30 @@ const state = useStateStore(pinia);
|
|||
import { useChatStore } from "../store/chatStore.js";
|
||||
const chat = useChatStore(pinia);
|
||||
|
||||
import {getNewMessagesByDXCallsign, resetIsNewMessage} from '../js/chatHandler'
|
||||
|
||||
import {
|
||||
getNewMessagesByDXCallsign,
|
||||
resetIsNewMessage,
|
||||
} from "../js/chatHandler";
|
||||
|
||||
import chat_conversations_entry from "./chat_conversations_entry.vue";
|
||||
|
||||
|
||||
function chatSelected(callsign) {
|
||||
chat.selectedCallsign = callsign.toUpperCase();
|
||||
|
||||
// scroll message container to bottom
|
||||
var messageBody = document.getElementById("message-container");
|
||||
if (messageBody != null ) {
|
||||
if (messageBody != null) {
|
||||
// needs sensible defaults
|
||||
messageBody.scrollTop = messageBody.scrollHeight - messageBody.clientHeight;
|
||||
}
|
||||
|
||||
if (getNewMessagesByDXCallsign(callsign)[1] > 0){
|
||||
let messageArray = getNewMessagesByDXCallsign(callsign)[2]
|
||||
console.log(messageArray)
|
||||
if (getNewMessagesByDXCallsign(callsign)[1] > 0) {
|
||||
let messageArray = getNewMessagesByDXCallsign(callsign)[2];
|
||||
console.log(messageArray);
|
||||
|
||||
for (const key in messageArray){
|
||||
resetIsNewMessage(messageArray[key].uuid, false)
|
||||
}
|
||||
for (const key in messageArray) {
|
||||
resetIsNewMessage(messageArray[key].uuid, false);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -58,7 +59,7 @@ function chatSelected(callsign) {
|
|||
<template v-for="(item, key) in chat.callsign_list" :key="item.dxcallsign">
|
||||
<a
|
||||
class="list-group-item list-group-item-action border-0 border-bottom rounded-0"
|
||||
:class="{ active: key == 0}"
|
||||
:class="{ active: key == 0 }"
|
||||
:id="`list-chat-list-${item}`"
|
||||
data-bs-toggle="list"
|
||||
:href="`#list-${item}-messages`"
|
||||
|
@ -66,15 +67,15 @@ function chatSelected(callsign) {
|
|||
aria-controls="list-{{item}}-messages"
|
||||
@click="chatSelected(item)"
|
||||
>
|
||||
|
||||
|
||||
|
||||
<div class="row">
|
||||
<div class="col-9">{{ item }}
|
||||
<span class="badge rounded-pill bg-danger" v-if="getNewMessagesByDXCallsign(item)[1] > 0">
|
||||
{{getNewMessagesByDXCallsign(item)[1]}} new messages
|
||||
<div class="col-9">
|
||||
{{ item }}
|
||||
<span
|
||||
class="badge rounded-pill bg-danger"
|
||||
v-if="getNewMessagesByDXCallsign(item)[1] > 0"
|
||||
>
|
||||
{{ getNewMessagesByDXCallsign(item)[1] }} new messages
|
||||
</span>
|
||||
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<button
|
||||
|
|
|
@ -57,17 +57,13 @@ function getDateTime(timestampRaw) {
|
|||
</div>
|
||||
|
||||
<div v-if="item.type === 'beacon' && item.status === 'received'">
|
||||
<!-- {{ item }} -->
|
||||
<!-- {{ item }} -->
|
||||
</div>
|
||||
|
||||
<div v-if="item.type === 'ping'">
|
||||
{{ item.snr }} dB
|
||||
ping received
|
||||
</div>
|
||||
<div v-if="item.type === 'ping'">{{ item.snr }} dB ping received</div>
|
||||
|
||||
<div v-if="item.type === 'ping-ack'">
|
||||
{{ item.snr }} dB
|
||||
ping-ack received
|
||||
{{ item.snr }} dB ping-ack received
|
||||
</div>
|
||||
|
||||
<div v-if="item.type === 'transmit'">
|
||||
|
|
|
@ -23,8 +23,7 @@
|
|||
|
||||
<!-- Delete button outside of the card -->
|
||||
<div class="col-auto">
|
||||
|
||||
<button
|
||||
<button
|
||||
class="btn btn-outline-secondary border-0 me-1"
|
||||
@click="showMessageInfo"
|
||||
data-bs-target="#messageInfoModal"
|
||||
|
@ -49,42 +48,42 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { deleteMessageFromDB, requestMessageInfo, getMessageAttachment } from "../js/chatHandler";
|
||||
import {atob_FD} from "../js/freedata"
|
||||
import {
|
||||
deleteMessageFromDB,
|
||||
requestMessageInfo,
|
||||
getMessageAttachment,
|
||||
} from "../js/chatHandler";
|
||||
import { atob_FD } from "../js/freedata";
|
||||
|
||||
// pinia store setup
|
||||
import { setActivePinia } from "pinia";
|
||||
import pinia from "../store/index";
|
||||
setActivePinia(pinia);
|
||||
import { saveAs } from 'file-saver';
|
||||
import { saveAs } from "file-saver";
|
||||
|
||||
import { useChatStore } from "../store/chatStore.js";
|
||||
const chat = useChatStore(pinia);
|
||||
|
||||
|
||||
|
||||
|
||||
export default {
|
||||
props: {
|
||||
message: Object,
|
||||
},
|
||||
methods: {
|
||||
|
||||
async downloadAttachment() {
|
||||
async downloadAttachment() {
|
||||
try {
|
||||
// reset file store
|
||||
chat.downloadFileFromDB = [];
|
||||
|
||||
const attachment = await getMessageAttachment(this.message._id);
|
||||
const blob = new Blob([atob_FD(attachment[2])], { type: `${attachment[1]};charset=utf-8` });
|
||||
const blob = new Blob([atob_FD(attachment[2])], {
|
||||
type: `${attachment[1]};charset=utf-8`,
|
||||
});
|
||||
window.focus();
|
||||
saveAs(blob, attachment[0]);
|
||||
} catch (error) {
|
||||
console.error("Failed to download attachment:", error);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
},
|
||||
computed: {
|
||||
getFileContent() {
|
||||
|
@ -112,10 +111,10 @@ async downloadAttachment() {
|
|||
}
|
||||
},
|
||||
showMessageInfo() {
|
||||
requestMessageInfo(this.message._id);
|
||||
//let infoModal = Modal.getOrCreateInstance(document.getElementById('messageInfoModal'))
|
||||
//console.log(this.infoModal)
|
||||
//this.infoModal.show()
|
||||
requestMessageInfo(this.message._id);
|
||||
//let infoModal = Modal.getOrCreateInstance(document.getElementById('messageInfoModal'))
|
||||
//console.log(this.infoModal)
|
||||
//this.infoModal.show()
|
||||
},
|
||||
deleteMessage() {
|
||||
deleteMessageFromDB(this.message._id);
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
<div class="row justify-content-end mb-2">
|
||||
<!-- control area -->
|
||||
<div class="col-auto p-0 m-0">
|
||||
|
||||
|
||||
<button
|
||||
v-if="getFileContent['filesize'] !== 0"
|
||||
class="btn btn-outline-secondary border-0 me-1"
|
||||
|
@ -12,7 +10,6 @@
|
|||
<i class="bi bi-download"></i>
|
||||
</button>
|
||||
|
||||
|
||||
<button
|
||||
class="btn btn-outline-secondary border-0 me-1"
|
||||
@click="repeatMessage"
|
||||
|
@ -74,19 +71,12 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
|
||||
import { Modal } from "bootstrap";
|
||||
import { onMounted, ref } from "vue";
|
||||
import {atob_FD} from "../js/freedata"
|
||||
import { atob_FD } from "../js/freedata";
|
||||
|
||||
import {
|
||||
repeatMessageTransmission,
|
||||
|
@ -95,40 +85,35 @@ import {
|
|||
getMessageAttachment,
|
||||
} from "../js/chatHandler";
|
||||
|
||||
|
||||
// pinia store setup
|
||||
import { setActivePinia } from "pinia";
|
||||
import pinia from "../store/index";
|
||||
setActivePinia(pinia);
|
||||
import { saveAs } from 'file-saver';
|
||||
import { saveAs } from "file-saver";
|
||||
|
||||
import { useChatStore } from "../store/chatStore.js";
|
||||
const chat = useChatStore(pinia);
|
||||
|
||||
|
||||
|
||||
export default {
|
||||
props: {
|
||||
message: Object,
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
|
||||
async downloadAttachment() {
|
||||
async downloadAttachment() {
|
||||
try {
|
||||
// reset file store
|
||||
chat.downloadFileFromDB = [];
|
||||
|
||||
const attachment = await getMessageAttachment(this.message._id);
|
||||
const blob = new Blob([atob_FD(attachment[2])], { type: `${attachment[1]};charset=utf-8` });
|
||||
const blob = new Blob([atob_FD(attachment[2])], {
|
||||
type: `${attachment[1]};charset=utf-8`,
|
||||
});
|
||||
saveAs(blob, attachment[0]);
|
||||
} catch (error) {
|
||||
console.error("Failed to download attachment:", error);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
},
|
||||
computed: {
|
||||
getFileContent() {
|
||||
|
@ -162,20 +147,16 @@ async downloadAttachment() {
|
|||
repeatMessageTransmission(this.message._id);
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
deleteMessage() {
|
||||
deleteMessageFromDB(this.message._id);
|
||||
},
|
||||
showMessageInfo() {
|
||||
requestMessageInfo(this.message._id);
|
||||
//let infoModal = Modal.getOrCreateInstance(document.getElementById('messageInfoModal'))
|
||||
//console.log(this.infoModal)
|
||||
//this.infoModal.show()
|
||||
requestMessageInfo(this.message._id);
|
||||
//let infoModal = Modal.getOrCreateInstance(document.getElementById('messageInfoModal'))
|
||||
//console.log(this.infoModal)
|
||||
//this.infoModal.show()
|
||||
},
|
||||
|
||||
|
||||
getDateTime() {
|
||||
var datetime = new Date(this.message.timestamp * 1000).toLocaleString(
|
||||
navigator.language,
|
||||
|
|
|
@ -16,9 +16,7 @@ const state = useStateStore(pinia);
|
|||
import { useChatStore } from "../store/chatStore.js";
|
||||
const chat = useChatStore(pinia);
|
||||
|
||||
import {getRxBuffer} from '../js/sock.js'
|
||||
|
||||
|
||||
import { getRxBuffer } from "../js/sock.js";
|
||||
|
||||
import {
|
||||
Chart as ChartJS,
|
||||
|
@ -34,11 +32,9 @@ import {
|
|||
|
||||
import { Line, Scatter, Bar } from "vue-chartjs";
|
||||
import { ref, computed } from "vue";
|
||||
import annotationPlugin from 'chartjs-plugin-annotation';
|
||||
|
||||
const newChatCall=ref(null);
|
||||
|
||||
import annotationPlugin from "chartjs-plugin-annotation";
|
||||
|
||||
const newChatCall = ref(null);
|
||||
|
||||
ChartJS.register(
|
||||
CategoryScale,
|
||||
|
@ -48,11 +44,9 @@ ChartJS.register(
|
|||
Tooltip,
|
||||
Legend,
|
||||
BarElement,
|
||||
annotationPlugin
|
||||
annotationPlugin,
|
||||
);
|
||||
|
||||
|
||||
|
||||
var beaconHistogramOptions = {
|
||||
type: "bar",
|
||||
bezierCurve: false, //remove curves from your plot
|
||||
|
@ -68,13 +62,13 @@ var beaconHistogramOptions = {
|
|||
annotation: {
|
||||
annotations: [
|
||||
{
|
||||
type: 'line',
|
||||
mode: 'horizontal',
|
||||
scaleID: 'y',
|
||||
type: "line",
|
||||
mode: "horizontal",
|
||||
scaleID: "y",
|
||||
value: 0,
|
||||
borderColor: 'darkgrey', // Set the color to dark grey for the zero line
|
||||
borderColor: "darkgrey", // Set the color to dark grey for the zero line
|
||||
borderWidth: 0.5, // Set the line width
|
||||
}
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
|
@ -121,15 +115,15 @@ try {
|
|||
const beaconHistogramData = computed(() => ({
|
||||
labels: chat.beaconLabelArray,
|
||||
datasets: [
|
||||
{ data: chat.beaconDataArray, tension: 0.1, borderColor: "rgb(0, 255, 0)",
|
||||
|
||||
backgroundColor: function(context) {
|
||||
var value = context.dataset.data[context.dataIndex];
|
||||
return value >= 0 ? 'green' : 'red';
|
||||
},
|
||||
|
||||
|
||||
{
|
||||
data: chat.beaconDataArray,
|
||||
tension: 0.1,
|
||||
borderColor: "rgb(0, 255, 0)",
|
||||
|
||||
backgroundColor: function (context) {
|
||||
var value = context.dataset.data[context.dataIndex];
|
||||
return value >= 0 ? "green" : "red";
|
||||
},
|
||||
},
|
||||
],
|
||||
}));
|
||||
|
@ -138,17 +132,12 @@ function newChat(obj) {
|
|||
let callsign = this.newChatCall.value;
|
||||
callsign = callsign.toUpperCase();
|
||||
chat.callsign_list.add(callsign);
|
||||
this.newChatCall.value="";
|
||||
this.newChatCall.value = "";
|
||||
}
|
||||
|
||||
|
||||
function syncWithModem(){
|
||||
|
||||
getRxBuffer()
|
||||
function syncWithModem() {
|
||||
getRxBuffer();
|
||||
}
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -163,7 +152,7 @@ getRxBuffer()
|
|||
style="text-transform: uppercase"
|
||||
placeholder="callsign"
|
||||
@keypress.enter="newChat()"
|
||||
ref="newChatCall"
|
||||
ref="newChatCall"
|
||||
/>
|
||||
<button
|
||||
class="btn btn-sm btn-outline-success"
|
||||
|
@ -180,40 +169,35 @@ getRxBuffer()
|
|||
<div class="col-5 ms-2 p-0">
|
||||
<!-- right side of chat nav bar-->
|
||||
|
||||
<div class="input-group mb-0 p-0 w-50">
|
||||
<button type="button" class="btn btn-outline-secondary" disabled>
|
||||
Beacons
|
||||
</button>
|
||||
|
||||
<div class="input-group mb-0 p-0 w-50 ">
|
||||
|
||||
|
||||
<button type="button" class="btn btn-outline-secondary" disabled>
|
||||
Beacons
|
||||
</button>
|
||||
|
||||
<div class="form-floating border border-secondary-subtle border-1 rounded-end">
|
||||
|
||||
<Bar
|
||||
:data="beaconHistogramData"
|
||||
:options="beaconHistogramOptions"
|
||||
width="300"
|
||||
height="50"
|
||||
|
||||
/>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="form-floating border border-secondary-subtle border-1 rounded-end"
|
||||
>
|
||||
<Bar
|
||||
:data="beaconHistogramData"
|
||||
:options="beaconHistogramOptions"
|
||||
width="300"
|
||||
height="50"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-2 ms-2 p-0">
|
||||
|
||||
<div class="input-group mb-0 p-0 ">
|
||||
|
||||
<button type="button" class="btn btn-outline-secondary" @click="syncWithModem()">
|
||||
Modem Sync
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="input-group mb-0 p-0">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-outline-secondary"
|
||||
@click="syncWithModem()"
|
||||
>
|
||||
Modem Sync
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -167,17 +167,10 @@ const scatterChartData = computed(() => ({
|
|||
},
|
||||
],
|
||||
}));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
|
||||
import {initWaterfall} from "../js/waterfallHandler.js"
|
||||
import { initWaterfall } from "../js/waterfallHandler.js";
|
||||
|
||||
export default {
|
||||
mounted() {
|
||||
|
@ -186,16 +179,13 @@ export default {
|
|||
//const myElement = this.$refs.waterfall; // Access the DOM element with ref
|
||||
|
||||
// init waterfall
|
||||
initWaterfall()
|
||||
|
||||
initWaterfall();
|
||||
},
|
||||
}
|
||||
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<div class="card mb-1" style="height: calc(var(--variable-height) - 20px);">
|
||||
<div class="card mb-1" style="height: calc(var(--variable-height) - 20px)">
|
||||
<div class="card-header p-1">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
|
@ -242,7 +232,6 @@ export default {
|
|||
</div>
|
||||
</div>
|
||||
<div class="btn-group" role="group" aria-label="Busy indicators">
|
||||
|
||||
<button
|
||||
class="btn btn-sm ms-1 p-1 disabled"
|
||||
type="button"
|
||||
|
@ -252,7 +241,8 @@ export default {
|
|||
data-bs-html="true"
|
||||
v-bind:class="{
|
||||
'btn-warning': state.getChannelBusySlotState(0) === true,
|
||||
'btn-outline-secondary': state.getChannelBusySlotState(0) === false,
|
||||
'btn-outline-secondary':
|
||||
state.getChannelBusySlotState(0) === false,
|
||||
}"
|
||||
title="Channel busy state: <strong class='text-success'>not busy</strong> / <strong class='text-danger'>busy </strong>"
|
||||
>
|
||||
|
@ -268,7 +258,8 @@ export default {
|
|||
data-bs-html="true"
|
||||
v-bind:class="{
|
||||
'btn-warning': state.getChannelBusySlotState(1) === true,
|
||||
'btn-outline-secondary': state.getChannelBusySlotState(1) === false,
|
||||
'btn-outline-secondary':
|
||||
state.getChannelBusySlotState(1) === false,
|
||||
}"
|
||||
title="Channel busy state: <strong class='text-success'>not busy</strong> / <strong class='text-danger'>busy </strong>"
|
||||
>
|
||||
|
@ -284,7 +275,8 @@ export default {
|
|||
data-bs-html="true"
|
||||
v-bind:class="{
|
||||
'btn-warning': state.getChannelBusySlotState(2) === true,
|
||||
'btn-outline-secondary': state.getChannelBusySlotState(2) === false,
|
||||
'btn-outline-secondary':
|
||||
state.getChannelBusySlotState(2) === false,
|
||||
}"
|
||||
title="Channel busy state: <strong class='text-success'>not busy</strong> / <strong class='text-danger'>busy </strong>"
|
||||
>
|
||||
|
@ -300,7 +292,8 @@ export default {
|
|||
data-bs-html="true"
|
||||
v-bind:class="{
|
||||
'btn-warning': state.getChannelBusySlotState(3) === true,
|
||||
'btn-outline-secondary': state.getChannelBusySlotState(3) === false,
|
||||
'btn-outline-secondary':
|
||||
state.getChannelBusySlotState(3) === false,
|
||||
}"
|
||||
title="Channel busy state: <strong class='text-success'>not busy</strong> / <strong class='text-danger'>busy </strong>"
|
||||
>
|
||||
|
@ -316,7 +309,8 @@ export default {
|
|||
data-bs-html="true"
|
||||
v-bind:class="{
|
||||
'btn-warning': state.getChannelBusySlotState(4) === true,
|
||||
'btn-outline-secondary': state.getChannelBusySlotState(4) === false,
|
||||
'btn-outline-secondary':
|
||||
state.getChannelBusySlotState(4) === false,
|
||||
}"
|
||||
title="Channel busy state: <strong class='text-success'>not busy</strong> / <strong class='text-danger'>busy </strong>"
|
||||
>
|
||||
|
@ -367,7 +361,7 @@ export default {
|
|||
<canvas
|
||||
ref="waterfall"
|
||||
id="waterfall"
|
||||
style="position: relative; z-index: 2;"
|
||||
style="position: relative; z-index: 2"
|
||||
class="force-gpu h-100 w-100"
|
||||
></canvas>
|
||||
</div>
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
<script setup lang="ts">
|
||||
|
||||
import { setActivePinia } from "pinia";
|
||||
import pinia from "../store/index";
|
||||
setActivePinia(pinia);
|
||||
|
||||
import { useStateStore } from "../store/stateStore.js";
|
||||
const state = useStateStore(pinia);
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -26,7 +24,7 @@ const state = useStateStore(pinia);
|
|||
id="ptt_state"
|
||||
type="button"
|
||||
title="Rig PTT state"
|
||||
style="pointer-events: auto;"
|
||||
style="pointer-events: auto"
|
||||
disabled
|
||||
>
|
||||
<i class="bi bi-broadcast-pin" style="font-size: 0.8rem"></i>
|
||||
|
@ -46,7 +44,7 @@ const state = useStateStore(pinia);
|
|||
}"
|
||||
title="Modem state"
|
||||
disabled
|
||||
style="pointer-events: auto;"
|
||||
style="pointer-events: auto"
|
||||
>
|
||||
<i class="bi bi-cpu" style="font-size: 0.8rem"></i>
|
||||
</button>
|
||||
|
@ -64,7 +62,7 @@ const state = useStateStore(pinia);
|
|||
'bg-warning': state.arq_session_state === 'connected',
|
||||
}"
|
||||
disabled
|
||||
style="pointer-events: auto;"
|
||||
style="pointer-events: auto"
|
||||
title="Session state"
|
||||
>
|
||||
<i class="bi bi-arrow-left-right" style="font-size: 0.8rem"></i>
|
||||
|
@ -80,7 +78,7 @@ const state = useStateStore(pinia);
|
|||
'bg-warning': state.arq_state === 'True',
|
||||
}"
|
||||
disabled
|
||||
style="pointer-events: auto;"
|
||||
style="pointer-events: auto"
|
||||
>
|
||||
<i class="bi bi-file-earmark-binary" style="font-size: 0.8rem"></i>
|
||||
</button>
|
||||
|
@ -110,7 +108,7 @@ const state = useStateStore(pinia);
|
|||
'btn-warning': state.channel_busy === 'True',
|
||||
'btn-secondary': state.channel_busy === 'False',
|
||||
}"
|
||||
style="pointer-events: auto;"
|
||||
style="pointer-events: auto"
|
||||
title="Channel busy"
|
||||
>
|
||||
<i class="bi bi-hourglass"></i>
|
||||
|
@ -122,9 +120,9 @@ const state = useStateStore(pinia);
|
|||
class="btn btn-sm btn-secondary me-4 disabled"
|
||||
type="button"
|
||||
title="What's the frequency, Kenneth?"
|
||||
style=" pointer-events: auto;"
|
||||
style="pointer-events: auto"
|
||||
>
|
||||
{{ parseInt(state.frequency) / 1000 }} KHz
|
||||
{{ parseInt(state.frequency) / 1000 }} KHz
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
@ -219,7 +217,9 @@ const state = useStateStore(pinia);
|
|||
aria-valuemin="0"
|
||||
aria-valuemax="100"
|
||||
></div>
|
||||
<p class="justify-content-center m-0 d-flex position-absolute w-100 text-dark">
|
||||
<p
|
||||
class="justify-content-center m-0 d-flex position-absolute w-100 text-dark"
|
||||
>
|
||||
{{ state.arq_seconds_until_finish }}s left
|
||||
</p>
|
||||
</div>
|
||||
|
@ -248,4 +248,4 @@ const state = useStateStore(pinia);
|
|||
</div>
|
||||
</nav>
|
||||
</template>
|
||||
ww
|
||||
ww
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<script setup lang="ts">
|
||||
|
||||
import { setActivePinia } from "pinia";
|
||||
import pinia from "../store/index";
|
||||
setActivePinia(pinia);
|
||||
|
@ -10,8 +9,10 @@ const state = useStateStore(pinia);
|
|||
import { useChatStore } from "../store/chatStore.js";
|
||||
const chat = useChatStore(pinia);
|
||||
|
||||
import { deleteChatByCallsign, getNewMessagesByDXCallsign } from "../js/chatHandler";
|
||||
|
||||
import {
|
||||
deleteChatByCallsign,
|
||||
getNewMessagesByDXCallsign,
|
||||
} from "../js/chatHandler";
|
||||
|
||||
import { sendTestFrame, setTxAudioLevel } from "../js/sock.js";
|
||||
|
||||
|
@ -36,8 +37,8 @@ import {
|
|||
LineElement,
|
||||
Title,
|
||||
Tooltip,
|
||||
Legend
|
||||
} from 'chart.js'
|
||||
Legend,
|
||||
} from "chart.js";
|
||||
import { Line } from "vue-chartjs";
|
||||
import { ref, computed } from "vue";
|
||||
|
||||
|
@ -48,113 +49,172 @@ ChartJS.register(
|
|||
LineElement,
|
||||
Title,
|
||||
Tooltip,
|
||||
Legend
|
||||
)
|
||||
|
||||
|
||||
Legend,
|
||||
);
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- updater release notes-->
|
||||
<div
|
||||
class="modal fade"
|
||||
ref="modalEle"
|
||||
id="updaterReleaseNotes"
|
||||
tabindex="-1"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<span class="input-group-text" id="updater_last_version"></span>
|
||||
<span class="input-group-text ms-1" id="updater_last_update"></span>
|
||||
|
||||
<!-- updater release notes-->
|
||||
<div class="modal fade" ref="modalEle" id="updaterReleaseNotes" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<span class="input-group-text" id="updater_last_version"></span>
|
||||
<span class="input-group-text ms-1" id="updater_last_update"></span>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-close"
|
||||
data-bs-dismiss="modal"
|
||||
aria-label="Close"
|
||||
></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="modal-dialog modal-dialog-scrollable">
|
||||
<div class="" id="updater_release_notes"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="modal-dialog modal-dialog-scrollable">
|
||||
|
||||
<div class="" id="updater_release_notes"></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||
<div class="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary"
|
||||
data-bs-dismiss="modal"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- delete chat modal -->
|
||||
<div class="modal fade" ref="modalEle" id="deleteChatModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title fs-5" id="deleteChatModalLabel">Sub menu for: {{chat.selectedCallsign}}</h1>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
|
||||
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-text" id="basic-addon1">Total Messages</span>
|
||||
<span class="input-group-text" id="basic-addon1">{{getNewMessagesByDXCallsign(chat.selectedCallsign)[0]}}</span>
|
||||
<!-- delete chat modal -->
|
||||
<div
|
||||
class="modal fade"
|
||||
ref="modalEle"
|
||||
id="deleteChatModal"
|
||||
tabindex="-1"
|
||||
aria-labelledby="exampleModalLabel"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title fs-5" id="deleteChatModalLabel">
|
||||
Sub menu for: {{ chat.selectedCallsign }}
|
||||
</h1>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-close"
|
||||
data-bs-dismiss="modal"
|
||||
aria-label="Close"
|
||||
></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-text" id="basic-addon1"
|
||||
>Total Messages</span
|
||||
>
|
||||
<span class="input-group-text" id="basic-addon1">{{
|
||||
getNewMessagesByDXCallsign(chat.selectedCallsign)[0]
|
||||
}}</span>
|
||||
</div>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-text" id="basic-addon1">New Messages</span>
|
||||
<span class="input-group-text" id="basic-addon1">{{getNewMessagesByDXCallsign(chat.selectedCallsign)[1]}}</span>
|
||||
<span class="input-group-text" id="basic-addon1">{{
|
||||
getNewMessagesByDXCallsign(chat.selectedCallsign)[1]
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary"
|
||||
data-bs-dismiss="modal"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-danger"
|
||||
@click="deleteChat"
|
||||
data-bs-dismiss="modal"
|
||||
>
|
||||
Delete Chat
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||
<button type="button" class="btn btn-danger" @click="deleteChat" data-bs-dismiss="modal">Delete Chat</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Message Info Modal -->
|
||||
<div
|
||||
class="modal fade"
|
||||
ref="modalEle"
|
||||
id="messageInfoModal"
|
||||
tabindex="-1"
|
||||
aria-labelledby="exampleModalLabel"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title fs-5" id="messageInfoModalLabel">
|
||||
{{ chat.selectedMessageObject["uuid"] }}
|
||||
</h1>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-close"
|
||||
data-bs-dismiss="modal"
|
||||
aria-label="Close"
|
||||
></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{{ chat.selectedMessageObject }}
|
||||
|
||||
|
||||
|
||||
<!-- Message Info Modal -->
|
||||
<div class="modal fade" ref="modalEle" id="messageInfoModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h1 class="modal-title fs-5" id="messageInfoModalLabel">{{chat.selectedMessageObject["uuid"]}}</h1>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
|
||||
{{chat.selectedMessageObject}}
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-text" id="basic-addon1">Status</span>
|
||||
<span class="input-group-text" id="basic-addon1">{{chat.selectedMessageObject["status"]}}</span>
|
||||
</div>
|
||||
<span class="input-group-text" id="basic-addon1">{{
|
||||
chat.selectedMessageObject["status"]
|
||||
}}</span>
|
||||
</div>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-text" id="basic-addon1">Attempts</span>
|
||||
<span class="input-group-text" id="basic-addon1">{{chat.selectedMessageObject["attempt"]}}</span>
|
||||
</div>
|
||||
<span class="input-group-text" id="basic-addon1">{{
|
||||
chat.selectedMessageObject["attempt"]
|
||||
}}</span>
|
||||
</div>
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-text" id="basic-addon1">Bytes per Minute</span>
|
||||
<span class="input-group-text" id="basic-addon1">{{chat.selectedMessageObject["bytesperminute"]}}</span>
|
||||
<div class="input-group mb-3">
|
||||
<span class="input-group-text" id="basic-addon1"
|
||||
>Bytes per Minute</span
|
||||
>
|
||||
<span class="input-group-text" id="basic-addon1">{{
|
||||
chat.selectedMessageObject["bytesperminute"]
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary"
|
||||
data-bs-dismiss="modal"
|
||||
>
|
||||
Close
|
||||
</button>
|
||||
<button type="button" class="btn btn-primary">Save changes</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||
<button type="button" class="btn btn-primary">Save changes</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- HELP MODALS AUDIO -->
|
||||
<div
|
||||
|
@ -757,7 +817,11 @@ ChartJS.register(
|
|||
<div class="card mb-3">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary" @click="tuneAudio">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-outline-secondary"
|
||||
@click="tuneAudio"
|
||||
>
|
||||
Tune
|
||||
</button>
|
||||
</h5>
|
||||
|
|
|
@ -17,7 +17,6 @@ const settings = useSettingsStore(pinia);
|
|||
</div>
|
||||
<div class="col-3">
|
||||
<strong class="fs-5">Updater</strong>
|
||||
|
||||
</div>
|
||||
<div class="col-7">
|
||||
<div class="progress w-100 ms-1 m-1">
|
||||
|
|
|
@ -15,8 +15,8 @@ import settings_exp from "./settings_exp.vue";
|
|||
>
|
||||
<div class="container">
|
||||
<div class="badge text-bg-warning ms-3">
|
||||
<i class="bi bi-exclamation-triangle"></i> Please restart the modem after
|
||||
changing settings!
|
||||
<i class="bi bi-exclamation-triangle"></i> Please restart the modem
|
||||
after changing settings!
|
||||
</div>
|
||||
<!-- SETTINGS Nav tabs -->
|
||||
<ul class="nav nav-tabs" id="myTab" role="tablist">
|
||||
|
|
|
@ -100,7 +100,6 @@ function saveSettings() {
|
|||
v-model="settings.enable_auto_retry"
|
||||
true-value="True"
|
||||
false-value="False"
|
||||
|
||||
/>
|
||||
</div>
|
||||
</label>
|
||||
|
|
|
@ -94,7 +94,12 @@ function saveSettings() {
|
|||
<label class="input-group-text w-50" for="inputGroupFile02"
|
||||
>Received files folder</label
|
||||
>
|
||||
<input type="text" class="form-control w-50" id="received_files_folder" disabled/>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control w-50"
|
||||
id="received_files_folder"
|
||||
disabled
|
||||
/>
|
||||
</div>
|
||||
<div class="input-group input-group-sm mb-1">
|
||||
<span class="input-group-text w-50">Update channel</span>
|
||||
|
|
|
@ -43,36 +43,32 @@ function saveSettings() {
|
|||
/>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="input-group input-group-sm mb-1">
|
||||
<span class="input-group-text" style="width: 180px"
|
||||
>Rigctld remote ip</span
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
placeholder="rigctld IP"
|
||||
id="hamlib_rigctld_ip"
|
||||
aria-label="Device IP"
|
||||
v-model="settings.hamlib_rigctld_ip"
|
||||
/>
|
||||
<div class="input-group input-group-sm mb-1">
|
||||
<span class="input-group-text" style="width: 180px">Rigctld remote ip</span>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
placeholder="rigctld IP"
|
||||
id="hamlib_rigctld_ip"
|
||||
aria-label="Device IP"
|
||||
v-model="settings.hamlib_rigctld_ip"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="input-group input-group-sm mb-1">
|
||||
<div class="input-group input-group-sm mb-1">
|
||||
<span class="input-group-text" style="width: 180px"
|
||||
>Rigctld remote port</span
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
placeholder="rigctld port"
|
||||
id="hamlib_rigctld_port"
|
||||
aria-label="Device Port"
|
||||
v-model="settings.hamlib_rigctld_port"
|
||||
/>
|
||||
<input
|
||||
type="text"
|
||||
class="form-control"
|
||||
placeholder="rigctld port"
|
||||
id="hamlib_rigctld_port"
|
||||
aria-label="Device Port"
|
||||
v-model="settings.hamlib_rigctld_port"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
<hr class="m-2" />
|
||||
<div class="input-group input-group-sm mb-1">
|
||||
<span class="input-group-text" style="width: 180px"> Radio model </span>
|
||||
|
|
|
@ -17,14 +17,11 @@ const state = useStateStore(pinia);
|
|||
import { useSettingsStore } from "../store/settingsStore.js";
|
||||
const settings = useSettingsStore(pinia);
|
||||
|
||||
|
||||
import { sendMessage, sendBroadcastChannel } from "./sock.js";
|
||||
import { displayToast } from "./popupHandler.js";
|
||||
|
||||
|
||||
//const FD = require("./src/js/freedata.js");
|
||||
import {btoa_FD} from "./freedata.js"
|
||||
|
||||
import { btoa_FD } from "./freedata.js";
|
||||
|
||||
// split character
|
||||
const split_char = "0;1;";
|
||||
|
@ -61,8 +58,7 @@ interface messageDefaultObject {
|
|||
};
|
||||
}
|
||||
|
||||
|
||||
interface beaconDefaultObject{
|
||||
interface beaconDefaultObject {
|
||||
command: string;
|
||||
is_new: boolean;
|
||||
_id: string;
|
||||
|
@ -94,37 +90,36 @@ PouchDB.plugin(require("pouchdb-find"));
|
|||
PouchDB.plugin(require("pouchdb-upsert"));
|
||||
|
||||
// https://stackoverflow.com/a/26227660
|
||||
if(typeof process.env["APPDATA"] !== "undefined"){
|
||||
var appDataFolder = process.env["APPDATA"]
|
||||
console.log(appDataFolder)
|
||||
|
||||
if (typeof process.env["APPDATA"] !== "undefined") {
|
||||
var appDataFolder = process.env["APPDATA"];
|
||||
console.log(appDataFolder);
|
||||
} else {
|
||||
var appDataFolder: string;
|
||||
var appDataFolder: string;
|
||||
|
||||
switch (process.platform) {
|
||||
case "darwin":
|
||||
appDataFolder = process.env["HOME"] + "/Library/Application Support";
|
||||
console.log(appDataFolder);
|
||||
break;
|
||||
case "linux":
|
||||
appDataFolder = process.env["HOME"] + "/.config";
|
||||
console.log(appDataFolder);
|
||||
break;
|
||||
case "win32":
|
||||
appDataFolder = "undefined";
|
||||
break;
|
||||
default:
|
||||
appDataFolder = "undefined";
|
||||
break;
|
||||
}
|
||||
switch (process.platform) {
|
||||
case "darwin":
|
||||
appDataFolder = process.env["HOME"] + "/Library/Application Support";
|
||||
console.log(appDataFolder);
|
||||
break;
|
||||
case "linux":
|
||||
appDataFolder = process.env["HOME"] + "/.config";
|
||||
console.log(appDataFolder);
|
||||
break;
|
||||
case "win32":
|
||||
appDataFolder = "undefined";
|
||||
break;
|
||||
default:
|
||||
appDataFolder = "undefined";
|
||||
break;
|
||||
}
|
||||
}
|
||||
console.log("loading chat database...")
|
||||
console.log("appdata folder:" + appDataFolder)
|
||||
console.log("loading chat database...");
|
||||
console.log("appdata folder:" + appDataFolder);
|
||||
var configFolder = path.join(appDataFolder, "FreeDATA");
|
||||
console.log("config folder:" + configFolder)
|
||||
console.log("config folder:" + configFolder);
|
||||
|
||||
var chatDB = path.join(configFolder, "chatDB");
|
||||
console.log("database path:" + chatDB)
|
||||
console.log("database path:" + chatDB);
|
||||
|
||||
var db = new PouchDB(chatDB);
|
||||
|
||||
|
@ -135,8 +130,7 @@ var db = new PouchDB(chatDB);
|
|||
/* -------- RUN A DATABASE CLEANUP ON STARTUP */
|
||||
//dbClean()
|
||||
|
||||
updateAllChat(true)
|
||||
|
||||
updateAllChat(true);
|
||||
|
||||
// create callsign set for storing unique callsigns
|
||||
chat.callsign_list = new Set();
|
||||
|
@ -147,9 +141,9 @@ export function newBroadcast(broadcastChannel, chatmessage) {
|
|||
var frames = "";
|
||||
var data = "";
|
||||
|
||||
var file = "";
|
||||
var filetype = "text";
|
||||
var filename = "";
|
||||
var file = "";
|
||||
var filetype = "text";
|
||||
var filename = "";
|
||||
|
||||
var file_checksum = ""; //crc32(file).toString(16).toUpperCase();
|
||||
var checksum = "";
|
||||
|
@ -167,37 +161,35 @@ export function newBroadcast(broadcastChannel, chatmessage) {
|
|||
// slice uuid for reducing overhead
|
||||
uuid = uuid.slice(-4);
|
||||
|
||||
let newChatObj: messageDefaultObject = {
|
||||
command: "broadcast",
|
||||
hmac_signed: false,
|
||||
percent: 0,
|
||||
bytesperminute: 0, // You need to assign a value here
|
||||
is_new: false,
|
||||
_id: uuid,
|
||||
timestamp: timestamp,
|
||||
dxcallsign: broadcastChannel,
|
||||
dxgrid: "null",
|
||||
msg: chatmessage,
|
||||
checksum: file_checksum,
|
||||
type: message_type,
|
||||
status: "transmitting",
|
||||
attempt: 1,
|
||||
uuid: uuid,
|
||||
duration: 0,
|
||||
nacks: 0,
|
||||
speed_list: "null",
|
||||
_attachments: {
|
||||
[filename]: {
|
||||
content_type: filetype,
|
||||
data: btoa_FD(file),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
let newChatObj: messageDefaultObject = {
|
||||
command: "broadcast",
|
||||
hmac_signed: false,
|
||||
percent: 0,
|
||||
bytesperminute: 0, // You need to assign a value here
|
||||
is_new: false,
|
||||
_id: uuid,
|
||||
timestamp: timestamp,
|
||||
dxcallsign: broadcastChannel,
|
||||
dxgrid: "null",
|
||||
msg: chatmessage,
|
||||
checksum: file_checksum,
|
||||
type: message_type,
|
||||
status: "transmitting",
|
||||
attempt: 1,
|
||||
uuid: uuid,
|
||||
duration: 0,
|
||||
nacks: 0,
|
||||
speed_list: "null",
|
||||
_attachments: {
|
||||
[filename]: {
|
||||
content_type: filetype,
|
||||
data: btoa_FD(file),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//sendMessage(newChatObj)
|
||||
sendBroadcastChannel(newChatObj)
|
||||
//sendMessage(newChatObj)
|
||||
sendBroadcastChannel(newChatObj);
|
||||
|
||||
addObjToDatabase(newChatObj);
|
||||
}
|
||||
|
@ -216,7 +208,7 @@ export function newMessage(
|
|||
var data = "";
|
||||
var filename = "";
|
||||
var filetype = "";
|
||||
var file=""
|
||||
var file = "";
|
||||
if (typeof chatFile !== "undefined") {
|
||||
file = chatFile;
|
||||
filetype = chatFileType;
|
||||
|
@ -242,33 +234,32 @@ export function newMessage(
|
|||
// slice uuid for reducing overhead
|
||||
uuid = uuid.slice(-8);
|
||||
|
||||
|
||||
let newChatObj: messageDefaultObject = {
|
||||
command: "msg",
|
||||
hmac_signed: false,
|
||||
percent: 0,
|
||||
bytesperminute: 0, // You need to assign a value here
|
||||
is_new: false,
|
||||
_id: uuid,
|
||||
timestamp: timestamp,
|
||||
dxcallsign: dxcallsign,
|
||||
dxgrid: "null",
|
||||
msg: chatmessage,
|
||||
checksum: file_checksum,
|
||||
type: message_type,
|
||||
status: "transmitting",
|
||||
attempt: 1,
|
||||
uuid: uuid,
|
||||
duration: 0,
|
||||
nacks: 0,
|
||||
speed_list: "null",
|
||||
_attachments: {
|
||||
[filename]: {
|
||||
content_type: filetype,
|
||||
data: btoa_FD(file)
|
||||
}
|
||||
}
|
||||
};
|
||||
let newChatObj: messageDefaultObject = {
|
||||
command: "msg",
|
||||
hmac_signed: false,
|
||||
percent: 0,
|
||||
bytesperminute: 0, // You need to assign a value here
|
||||
is_new: false,
|
||||
_id: uuid,
|
||||
timestamp: timestamp,
|
||||
dxcallsign: dxcallsign,
|
||||
dxgrid: "null",
|
||||
msg: chatmessage,
|
||||
checksum: file_checksum,
|
||||
type: message_type,
|
||||
status: "transmitting",
|
||||
attempt: 1,
|
||||
uuid: uuid,
|
||||
duration: 0,
|
||||
nacks: 0,
|
||||
speed_list: "null",
|
||||
_attachments: {
|
||||
[filename]: {
|
||||
content_type: filetype,
|
||||
data: btoa_FD(file),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
sendMessage(newChatObj);
|
||||
addObjToDatabase(newChatObj);
|
||||
|
@ -288,7 +279,9 @@ function sortChatList() {
|
|||
}
|
||||
reorderedData[dxcallsign].push(obj);
|
||||
|
||||
reorderedData[dxcallsign] = reorderedData[dxcallsign].sort(sortByProperty("timestamp"));
|
||||
reorderedData[dxcallsign] = reorderedData[dxcallsign].sort(
|
||||
sortByProperty("timestamp"),
|
||||
);
|
||||
}
|
||||
});
|
||||
//console.log(reorderedData["2LS-0"])
|
||||
|
@ -296,17 +289,14 @@ function sortChatList() {
|
|||
}
|
||||
|
||||
//https://medium.com/@asadise/sorting-a-json-array-according-one-property-in-javascript-18b1d22cd9e9
|
||||
function sortByProperty(property){
|
||||
return function(a,b){
|
||||
if(a[property] > b[property])
|
||||
return 1;
|
||||
else if(a[property] < b[property])
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
function sortByProperty(property) {
|
||||
return function (a, b) {
|
||||
if (a[property] > b[property]) return 1;
|
||||
else if (a[property] < b[property]) return -1;
|
||||
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
export function getMessageAttachment(id) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
|
@ -333,28 +323,29 @@ export function getMessageAttachment(id) {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
//repeat a message
|
||||
export function repeatMessageTransmission(id) {
|
||||
// 1. get message object by ID
|
||||
// 2. Upsert Attempts
|
||||
// 3. send message
|
||||
|
||||
db.find({
|
||||
db.find({
|
||||
selector: {
|
||||
_id: id,
|
||||
},
|
||||
}).then(function (result){
|
||||
console.log(result)
|
||||
let obj = result.docs[0]
|
||||
console.log(obj)
|
||||
obj.attempt += 1
|
||||
databaseUpsert(obj.uuid, "attempt", obj.attempt);
|
||||
updateUnsortedChatListEntry(obj.uuid, "attempt", obj.attempt);
|
||||
sendMessage(obj)
|
||||
}).catch(function (err) {
|
||||
console.log(err);
|
||||
});
|
||||
})
|
||||
.then(function (result) {
|
||||
console.log(result);
|
||||
let obj = result.docs[0];
|
||||
console.log(obj);
|
||||
obj.attempt += 1;
|
||||
databaseUpsert(obj.uuid, "attempt", obj.attempt);
|
||||
updateUnsortedChatListEntry(obj.uuid, "attempt", obj.attempt);
|
||||
sendMessage(obj);
|
||||
})
|
||||
.catch(function (err) {
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
|
||||
// delete a message from databse and gui
|
||||
|
@ -374,7 +365,6 @@ export function deleteMessageFromDB(id) {
|
|||
chat.sorted_chat_list = sortChatList();
|
||||
}
|
||||
|
||||
|
||||
//Function to clean old beacons and optimize database
|
||||
async function dbClean() {
|
||||
//Only keep the most x latest days of beacons
|
||||
|
@ -384,7 +374,6 @@ async function dbClean() {
|
|||
(Date.now() - beaconKeep * 24 * 60 * 60 * 1000) / 1000,
|
||||
);
|
||||
|
||||
|
||||
//Items to purge from database
|
||||
var purgeFilter = [
|
||||
{ type: "beacon" },
|
||||
|
@ -404,7 +393,7 @@ async function dbClean() {
|
|||
//console.log("Purging " + result.docs.length + " beacons received before " + timestampPurge);
|
||||
itemCount = result.docs.length;
|
||||
result.docs.forEach(async function (item) {
|
||||
await deleteMessageFromDB(item._id)
|
||||
await deleteMessageFromDB(item._id);
|
||||
});
|
||||
})
|
||||
.catch(function (err) {
|
||||
|
@ -415,20 +404,13 @@ async function dbClean() {
|
|||
//Too slow on older/slower machines
|
||||
//await db.compact();
|
||||
|
||||
let message = "Database maintenance is complete";
|
||||
displayToast("info", "bi bi-info-circle", message, 5000);
|
||||
|
||||
|
||||
let message = "Database maintenance is complete"
|
||||
displayToast("info", "bi bi-info-circle", message, 5000);
|
||||
|
||||
message = "Removed "+itemCount+" items from database"
|
||||
displayToast("info", "bi bi-info-circle", message, 5000);
|
||||
|
||||
|
||||
message = "Removed " + itemCount + " items from database";
|
||||
displayToast("info", "bi bi-info-circle", message, 5000);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// function to update transmission status
|
||||
export function updateTransmissionStatus(obj) {
|
||||
// update database entries
|
||||
|
@ -436,23 +418,19 @@ export function updateTransmissionStatus(obj) {
|
|||
databaseUpsert(obj.uuid, "bytesperminute", obj.bytesperminute);
|
||||
databaseUpsert(obj.uuid, "status", obj.status);
|
||||
|
||||
|
||||
// update screen rendering / messages
|
||||
updateUnsortedChatListEntry(obj.uuid, "percent", obj.percent);
|
||||
updateUnsortedChatListEntry(obj.uuid, "bytesperminute", obj.bytesperminute);
|
||||
updateUnsortedChatListEntry(obj.uuid, "status", obj.status);
|
||||
|
||||
}
|
||||
|
||||
export function updateUnsortedChatListEntry(uuid, object, value) {
|
||||
|
||||
var data = getFromUnsortedChatListByUUID(uuid)
|
||||
if(data){
|
||||
var data = getFromUnsortedChatListByUUID(uuid);
|
||||
if (data) {
|
||||
data[object] = value;
|
||||
console.log("Entry updated:", data[object]);
|
||||
chat.sorted_chat_list = sortChatList();
|
||||
return data;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -470,43 +448,39 @@ export function updateUnsortedChatListEntry(uuid, object, value) {
|
|||
return null; // Return null if not found
|
||||
}
|
||||
|
||||
function getFromUnsortedChatListByUUID(uuid){
|
||||
for (const entry of chat.unsorted_chat_list) {
|
||||
if (entry.uuid === uuid) {
|
||||
return entry;
|
||||
}
|
||||
function getFromUnsortedChatListByUUID(uuid) {
|
||||
for (const entry of chat.unsorted_chat_list) {
|
||||
if (entry.uuid === uuid) {
|
||||
return entry;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getNewMessagesByDXCallsign(dxcallsign): [number, number, any]{
|
||||
let new_counter = 0
|
||||
let total_counter = 0
|
||||
let item_array = []
|
||||
if (typeof dxcallsign !== 'undefined'){
|
||||
for (const key in chat.sorted_chat_list[dxcallsign]){
|
||||
//console.log(chat.sorted_chat_list[dxcallsign][key])
|
||||
//item_array.push(chat.sorted_chat_list[dxcallsign][key])
|
||||
if(chat.sorted_chat_list[dxcallsign][key].is_new){
|
||||
item_array.push(chat.sorted_chat_list[dxcallsign][key])
|
||||
new_counter += 1
|
||||
|
||||
export function getNewMessagesByDXCallsign(dxcallsign): [number, number, any] {
|
||||
let new_counter = 0;
|
||||
let total_counter = 0;
|
||||
let item_array = [];
|
||||
if (typeof dxcallsign !== "undefined") {
|
||||
for (const key in chat.sorted_chat_list[dxcallsign]) {
|
||||
//console.log(chat.sorted_chat_list[dxcallsign][key])
|
||||
//item_array.push(chat.sorted_chat_list[dxcallsign][key])
|
||||
if (chat.sorted_chat_list[dxcallsign][key].is_new) {
|
||||
item_array.push(chat.sorted_chat_list[dxcallsign][key]);
|
||||
new_counter += 1;
|
||||
}
|
||||
total_counter += 1
|
||||
total_counter += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return [total_counter, new_counter, item_array];
|
||||
}
|
||||
|
||||
return [total_counter, new_counter, item_array];
|
||||
export function resetIsNewMessage(uuid, value) {
|
||||
databaseUpsert(uuid, "is_new", value);
|
||||
updateUnsortedChatListEntry(uuid, "is_new", value);
|
||||
}
|
||||
|
||||
|
||||
export function resetIsNewMessage(uuid, value){
|
||||
databaseUpsert(uuid, "is_new", value)
|
||||
updateUnsortedChatListEntry(uuid, "is_new", value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
export function databaseUpsert(id, object, value) {
|
||||
db.upsert(id, function (doc) {
|
||||
if (!doc[object]) {
|
||||
|
@ -527,70 +501,61 @@ export function databaseUpsert(id, object, value) {
|
|||
|
||||
// function for fetching all messages from chat / updating chat
|
||||
export async function updateAllChat(cleanup) {
|
||||
|
||||
// run cleanup if requested
|
||||
if (cleanup) {
|
||||
await dbClean()
|
||||
}
|
||||
let indexFields = [
|
||||
{dxcallsign: "asc"},
|
||||
{timestamp: "asc"}
|
||||
]
|
||||
// run cleanup if requested
|
||||
if (cleanup) {
|
||||
await dbClean();
|
||||
}
|
||||
let indexFields = [{ dxcallsign: "asc" }, { timestamp: "asc" }];
|
||||
let filter = {
|
||||
selector: {
|
||||
$and: [
|
||||
{ dxcallsign: { $exists: true } },
|
||||
{ timestamp: { $exists: true } },
|
||||
//{ $or: chat.chat_filter },
|
||||
],
|
||||
},
|
||||
sort: [{ dxcallsign: "asc" }, { timestamp: "asc" }],
|
||||
selector: {
|
||||
$and: [
|
||||
{ dxcallsign: { $exists: true } },
|
||||
{ timestamp: { $exists: true } },
|
||||
//{ $or: chat.chat_filter },
|
||||
],
|
||||
},
|
||||
sort: [{ dxcallsign: "asc" }, { timestamp: "asc" }],
|
||||
};
|
||||
//"{ dxcallsign: \"asc\" }, { timestamp: \"asc\" }"
|
||||
await createIndex(indexFields);
|
||||
getFromDBByFilter(filter)
|
||||
.then(function (result) {
|
||||
for (var item of (result as any).docs) {
|
||||
const dxcallsign = item.dxcallsign;
|
||||
// Check if dxcallsign already exists as a property in the result object
|
||||
if (!chat.sorted_beacon_list[dxcallsign]) {
|
||||
// If not, initialize it with an empty array for snr values
|
||||
chat.sorted_beacon_list[dxcallsign] = {
|
||||
dxcallsign,
|
||||
snr: [],
|
||||
timestamp: [],
|
||||
};
|
||||
chat.callsign_list.add(dxcallsign);
|
||||
}
|
||||
//"{ dxcallsign: \"asc\" }, { timestamp: \"asc\" }"
|
||||
await createIndex(indexFields);
|
||||
getFromDBByFilter(filter)
|
||||
.then(function (result) {
|
||||
for (var item of (result as any).docs) {
|
||||
const dxcallsign = item.dxcallsign;
|
||||
// Check if dxcallsign already exists as a property in the result object
|
||||
if (!chat.sorted_beacon_list[dxcallsign]) {
|
||||
// If not, initialize it with an empty array for snr values
|
||||
chat.sorted_beacon_list[dxcallsign] = {
|
||||
dxcallsign,
|
||||
snr: [],
|
||||
timestamp: [],
|
||||
};
|
||||
chat.callsign_list.add(dxcallsign);
|
||||
}
|
||||
|
||||
if (item.type === "beacon") {
|
||||
//console.log(item);
|
||||
if (item.type === "beacon") {
|
||||
//console.log(item);
|
||||
|
||||
// TODO: sort beacon list .... maybe a part for a separate function
|
||||
const jsonData = [item];
|
||||
|
||||
// Process each JSON item step by step
|
||||
jsonData.forEach((jsonitem) => {
|
||||
const { snr, timestamp } = item;
|
||||
// TODO: sort beacon list .... maybe a part for a separate function
|
||||
const jsonData = [item];
|
||||
|
||||
// Push the snr value to the corresponding dxcallsign's snr array
|
||||
chat.sorted_beacon_list[dxcallsign].snr.push(snr);
|
||||
chat.sorted_beacon_list[dxcallsign].timestamp.push(timestamp);
|
||||
});
|
||||
} else {
|
||||
|
||||
chat.unsorted_chat_list.push(item);
|
||||
chat.sorted_chat_list = sortChatList();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})
|
||||
.catch(function (err) {
|
||||
console.log(err);
|
||||
});
|
||||
// Process each JSON item step by step
|
||||
jsonData.forEach((jsonitem) => {
|
||||
const { snr, timestamp } = item;
|
||||
|
||||
// Push the snr value to the corresponding dxcallsign's snr array
|
||||
chat.sorted_beacon_list[dxcallsign].snr.push(snr);
|
||||
chat.sorted_beacon_list[dxcallsign].timestamp.push(timestamp);
|
||||
});
|
||||
} else {
|
||||
chat.unsorted_chat_list.push(item);
|
||||
chat.sorted_chat_list = sortChatList();
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(function (err) {
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
|
||||
function addObjToDatabase(newobj) {
|
||||
|
@ -610,12 +575,10 @@ function addObjToDatabase(newobj) {
|
|||
console.log("new database entry");
|
||||
console.log(response);
|
||||
|
||||
|
||||
if (newobj.command === "msg") {
|
||||
chat.unsorted_chat_list.push(newobj);
|
||||
chat.sorted_chat_list = sortChatList();
|
||||
}
|
||||
|
||||
})
|
||||
.catch(function (err) {
|
||||
console.log(err);
|
||||
|
@ -624,11 +587,8 @@ function addObjToDatabase(newobj) {
|
|||
// try upserting status in case we tried sending a message to our selfes
|
||||
databaseUpsert(newobj.uuid, "status", newobj.status);
|
||||
updateUnsortedChatListEntry(newobj.uuid, "status", newobj.status);
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
/*
|
||||
// upsert footer ...
|
||||
|
||||
|
@ -659,7 +619,7 @@ function createChatIndex() {
|
|||
"is_new",
|
||||
"nacks",
|
||||
"duration",
|
||||
"speed_list"
|
||||
"speed_list",
|
||||
],
|
||||
},
|
||||
})
|
||||
|
@ -681,8 +641,6 @@ export function deleteChatByCallsign(callsign) {
|
|||
deleteFromDatabaseByCallsign(callsign);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function deleteFromDatabaseByCallsign(callsign) {
|
||||
db.find({
|
||||
selector: {
|
||||
|
@ -730,18 +688,18 @@ export function newBeaconReceived(obj) {
|
|||
"mycallsign": "DJ2LS-0"
|
||||
}
|
||||
*/
|
||||
let newChatObj: beaconDefaultObject = {
|
||||
command: "beacon",
|
||||
is_new: false,
|
||||
_id: obj["uuid"],
|
||||
timestamp: obj["timestamp"],
|
||||
dxcallsign: obj["dxcallsign"],
|
||||
dxgrid: obj["dxgrid"],
|
||||
type: "beacon",
|
||||
status: obj["beacon"],
|
||||
uuid: obj["uuid"],
|
||||
snr: obj["snr"], // adding the new field
|
||||
};
|
||||
let newChatObj: beaconDefaultObject = {
|
||||
command: "beacon",
|
||||
is_new: false,
|
||||
_id: obj["uuid"],
|
||||
timestamp: obj["timestamp"],
|
||||
dxcallsign: obj["dxcallsign"],
|
||||
dxgrid: obj["dxgrid"],
|
||||
type: "beacon",
|
||||
status: obj["beacon"],
|
||||
uuid: obj["uuid"],
|
||||
snr: obj["snr"], // adding the new field
|
||||
};
|
||||
|
||||
addObjToDatabase(newChatObj);
|
||||
|
||||
|
@ -769,13 +727,11 @@ let newChatObj: beaconDefaultObject = {
|
|||
});
|
||||
|
||||
// check if auto retry enabled
|
||||
console.log("-----------------------------------------")
|
||||
console.log(settings.enable_auto_retry.toUpperCase())
|
||||
if (settings.enable_auto_retry.toUpperCase() == "TRUE") {
|
||||
console.log("-----------------------------------------");
|
||||
console.log(settings.enable_auto_retry.toUpperCase());
|
||||
if (settings.enable_auto_retry.toUpperCase() == "TRUE") {
|
||||
checkForWaitingMessages(dxcallsign);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// function for handling a received message
|
||||
|
@ -857,33 +813,32 @@ export function newMessageReceived(message, protocol) {
|
|||
*/
|
||||
console.log(protocol);
|
||||
|
||||
let newChatObj: messageDefaultObject = {
|
||||
command: "msg",
|
||||
hmac_signed: protocol["hmac_signed"],
|
||||
percent: 100,
|
||||
bytesperminute: protocol["bytesperminute"],
|
||||
is_new: true,
|
||||
_id: message[3],
|
||||
timestamp: message[4],
|
||||
dxcallsign: protocol["dxcallsign"],
|
||||
dxgrid: protocol["dxgrid"],
|
||||
msg: message[5],
|
||||
checksum: message[2],
|
||||
type: protocol["status"],
|
||||
status: protocol["status"],
|
||||
attempt: 1,
|
||||
uuid: message[3],
|
||||
duration: protocol["duration"],
|
||||
nacks: protocol["nacks"],
|
||||
speed_list: protocol["speed_list"],
|
||||
_attachments: {
|
||||
[message[6]]: {
|
||||
content_type: message[7],
|
||||
data: btoa_FD(message[8])
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let newChatObj: messageDefaultObject = {
|
||||
command: "msg",
|
||||
hmac_signed: protocol["hmac_signed"],
|
||||
percent: 100,
|
||||
bytesperminute: protocol["bytesperminute"],
|
||||
is_new: true,
|
||||
_id: message[3],
|
||||
timestamp: message[4],
|
||||
dxcallsign: protocol["dxcallsign"],
|
||||
dxgrid: protocol["dxgrid"],
|
||||
msg: message[5],
|
||||
checksum: message[2],
|
||||
type: protocol["status"],
|
||||
status: protocol["status"],
|
||||
attempt: 1,
|
||||
uuid: message[3],
|
||||
duration: protocol["duration"],
|
||||
nacks: protocol["nacks"],
|
||||
speed_list: protocol["speed_list"],
|
||||
_attachments: {
|
||||
[message[6]]: {
|
||||
content_type: message[7],
|
||||
data: btoa_FD(message[8]),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// some tweaks for broadcasts
|
||||
if (protocol.fec == "broadcast") {
|
||||
|
@ -906,31 +861,26 @@ export function setStateSuccess() {
|
|||
state.arq_seconds_until_timeout_percent = 100;
|
||||
}
|
||||
|
||||
export function requestMessageInfo(id){
|
||||
|
||||
console.log(id)
|
||||
// id and uuid are the same
|
||||
var data = getFromUnsortedChatListByUUID(id)
|
||||
console.log(data)
|
||||
chat.selectedMessageObject = data
|
||||
|
||||
|
||||
export function requestMessageInfo(id) {
|
||||
console.log(id);
|
||||
// id and uuid are the same
|
||||
var data = getFromUnsortedChatListByUUID(id);
|
||||
console.log(data);
|
||||
chat.selectedMessageObject = data;
|
||||
}
|
||||
|
||||
async function createIndex(myIndexFields)
|
||||
{
|
||||
db.createIndex({
|
||||
index: {
|
||||
fields: myIndexFields,
|
||||
},
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
});
|
||||
async function createIndex(myIndexFields) {
|
||||
db.createIndex({
|
||||
index: {
|
||||
fields: myIndexFields,
|
||||
},
|
||||
}).catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
|
||||
async function getFromDBByFilter(filter) {
|
||||
/*
|
||||
async function getFromDBByFilter(filter) {
|
||||
/*
|
||||
USAGE:
|
||||
|
||||
let filter = {
|
||||
|
@ -951,54 +901,53 @@ getFromDBByFilter(filter)
|
|||
});
|
||||
|
||||
*/
|
||||
return new Promise((resolve, reject) => {
|
||||
return db.find(filter)
|
||||
.then(result => {
|
||||
console.log(result);
|
||||
resolve(result);
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
reject(err);
|
||||
})})
|
||||
return new Promise((resolve, reject) => {
|
||||
return db
|
||||
.find(filter)
|
||||
.then((result) => {
|
||||
console.log(result);
|
||||
resolve(result);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
async function checkForWaitingMessages(dxcall) {
|
||||
|
||||
let filter = {
|
||||
let filter = {
|
||||
selector: {
|
||||
dxcallsign: dxcall,
|
||||
type: "transmit",
|
||||
status: "failed",
|
||||
//attempt: { $lt: parseInt(config.max_retry_attempts) }
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
getFromDBByFilter(filter)
|
||||
.then(result => {
|
||||
// @ts-expect-error
|
||||
let message = "Found " + result.docs.length + " waiting messages for " + dxcall
|
||||
getFromDBByFilter(filter)
|
||||
.then((result) => {
|
||||
// @ts-expect-error
|
||||
let message =
|
||||
"Found " + result.docs.length + " waiting messages for " + dxcall;
|
||||
|
||||
console.log(message);
|
||||
displayToast("info", "bi bi-info-circle", message, 5000);
|
||||
console.log(message);
|
||||
displayToast("info", "bi bi-info-circle", message, 5000);
|
||||
|
||||
// handle result
|
||||
// @ts-expect-error
|
||||
if (result.docs.length > 0) {
|
||||
// only want to process the first available item object, then return
|
||||
// this ensures, we are only sending one message at once
|
||||
// @ts-expect-error
|
||||
// @ts-expect-error
|
||||
if (result.docs[0].attempt < settings.max_retry_attempts) {
|
||||
// @ts-expect-error
|
||||
repeatMessageTransmission(result.docs[0].uuid)
|
||||
// @ts-expect-error
|
||||
repeatMessageTransmission(result.docs[0].uuid);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err)
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -116,14 +116,13 @@ daemon.on("data", function (socketdata) {
|
|||
stackoverflow.com questions 9070700 nodejs-net-createserver-large-amount-of-data-coming-in
|
||||
*/
|
||||
|
||||
socketdata = socketchunk.join("\n") + socketdata.toString("utf8"); //append incoming data to socketchunk
|
||||
//socketdata = socketdata.toString("utf8"); // convert data to string
|
||||
socketdata = socketchunk.join("\n") + socketdata.toString("utf8"); //append incoming data to socketchunk
|
||||
//socketdata = socketdata.toString("utf8"); // convert data to string
|
||||
|
||||
//socketchunk += socketdata; // append data to buffer so we can stick long data together
|
||||
|
||||
// check if we received begin and end of json data
|
||||
if (socketdata.startsWith('{"') && socketdata.endsWith('"}\n')) {
|
||||
|
||||
var data = "";
|
||||
|
||||
// split data into chunks if we received multiple commands
|
||||
|
@ -151,25 +150,19 @@ daemon.on("data", function (socketdata) {
|
|||
}
|
||||
}
|
||||
|
||||
console.log(data)
|
||||
console.log(data);
|
||||
if (data["command"] == "daemon_state") {
|
||||
|
||||
// update audio devices by putting them to audio store
|
||||
audioStore.inputDevices = data["input_devices"];
|
||||
audioStore.outputDevices = data["output_devices"];
|
||||
settings.serial_devices = data["serial_devices"];
|
||||
state.python_version = data["python_version"]
|
||||
state.modem_version = data["version"]
|
||||
state.python_version = data["python_version"];
|
||||
state.modem_version = data["version"];
|
||||
state.modem_running_state = data["daemon_state"][0]["status"];
|
||||
state.rigctld_started = data["rigctld_state"][0]["status"];
|
||||
//state.rigctld_process = data["daemon_state"][0]["rigctld_process"];
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (data["command"] == "test_hamlib") {
|
||||
let Data = {
|
||||
hamlib_result: data["result"],
|
||||
|
@ -246,7 +239,8 @@ export function startModem() {
|
|||
// STOP Modem
|
||||
//exports.stopModem = function () {
|
||||
export function stopModem() {
|
||||
var command = '{"type" : "set", "command": "stop_modem" , "parameter": "---" }';
|
||||
var command =
|
||||
'{"type" : "set", "command": "stop_modem" , "parameter": "---" }';
|
||||
writeDaemonCommand(command);
|
||||
}
|
||||
|
||||
|
@ -289,44 +283,38 @@ function testHamlib(
|
|||
}
|
||||
|
||||
export function startRigctld() {
|
||||
|
||||
var json_command = JSON.stringify({
|
||||
type: "set",
|
||||
command: "start_rigctld",
|
||||
parameter: [
|
||||
{
|
||||
hamlib_deviceid: settings.hamlib_deviceid,
|
||||
hamlib_deviceport: settings.hamlib_deviceport,
|
||||
hamlib_stop_bits: settings.hamlib_stop_bits,
|
||||
hamlib_data_bits: settings.hamlib_data_bits,
|
||||
hamlib_handshake: settings.hamlib_handshake,
|
||||
hamlib_serialspeed: settings.hamlib_serialspeed,
|
||||
hamlib_dtrstate: settings.hamlib_dtrstate,
|
||||
hamlib_pttprotocol: settings.hamlib_pttprotocol,
|
||||
hamlib_ptt_port: settings.hamlib_ptt_port,
|
||||
hamlib_dcd: settings.hamlib_dcd,
|
||||
hamlbib_serialspeed_ptt: settings.hamlib_serialspeed,
|
||||
hamlib_rigctld_port: settings.hamlib_rigctld_port,
|
||||
hamlib_rigctld_ip: settings.hamlib_rigctld_ip,
|
||||
hamlib_rigctld_path: settings.hamlib_rigctld_path,
|
||||
hamlib_rigctld_server_port: settings.hamlib_rigctld_server_port,
|
||||
hamlib_rigctld_custom_args: settings.hamlib_rigctld_custom_args
|
||||
|
||||
hamlib_deviceid: settings.hamlib_deviceid,
|
||||
hamlib_deviceport: settings.hamlib_deviceport,
|
||||
hamlib_stop_bits: settings.hamlib_stop_bits,
|
||||
hamlib_data_bits: settings.hamlib_data_bits,
|
||||
hamlib_handshake: settings.hamlib_handshake,
|
||||
hamlib_serialspeed: settings.hamlib_serialspeed,
|
||||
hamlib_dtrstate: settings.hamlib_dtrstate,
|
||||
hamlib_pttprotocol: settings.hamlib_pttprotocol,
|
||||
hamlib_ptt_port: settings.hamlib_ptt_port,
|
||||
hamlib_dcd: settings.hamlib_dcd,
|
||||
hamlbib_serialspeed_ptt: settings.hamlib_serialspeed,
|
||||
hamlib_rigctld_port: settings.hamlib_rigctld_port,
|
||||
hamlib_rigctld_ip: settings.hamlib_rigctld_ip,
|
||||
hamlib_rigctld_path: settings.hamlib_rigctld_path,
|
||||
hamlib_rigctld_server_port: settings.hamlib_rigctld_server_port,
|
||||
hamlib_rigctld_custom_args: settings.hamlib_rigctld_custom_args,
|
||||
},
|
||||
],
|
||||
});
|
||||
console.log(json_command);
|
||||
writeDaemonCommand(json_command);
|
||||
|
||||
}
|
||||
export function stopRigctld(){
|
||||
export function stopRigctld() {
|
||||
let command = '{"type" : "set", "command": "stop_rigctld"}';
|
||||
writeDaemonCommand(command);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Save myCall
|
||||
function saveMyCall(callsign) {
|
||||
//exports.saveMyCall = function (callsign) {
|
||||
|
@ -344,5 +332,3 @@ function saveMyGrid(grid) {
|
|||
'{"type" : "set", "command": "mygrid" , "parameter": "' + grid + '"}';
|
||||
writeDaemonCommand(command);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -6,24 +6,24 @@ const fs = require("fs");
|
|||
* @returns base64 encoded string
|
||||
*/
|
||||
export function btoa_FD(data) {
|
||||
//exports.btoa_FD = function (data) {
|
||||
//exports.btoa_FD = function (data) {
|
||||
return Buffer.from(data, "utf-8").toString("base64");
|
||||
};
|
||||
}
|
||||
/**
|
||||
* ASCII to Binary replacement
|
||||
* @param {string} data in base64 encoding
|
||||
* @returns utf-8 normal/usual string
|
||||
*/
|
||||
export function atob_FD(data) {
|
||||
//exports.atob_FD = function (data) {
|
||||
//exports.atob_FD = function (data) {
|
||||
return Buffer.from(data, "base64").toString("utf-8");
|
||||
};
|
||||
}
|
||||
/**
|
||||
* UTF8 to ASCII btoa
|
||||
* @param {string} data in base64 encoding
|
||||
* @returns base64 bota compatible data for use in browser
|
||||
*/
|
||||
export function atob(data) {
|
||||
//exports.atob = function (data) {
|
||||
//exports.atob = function (data) {
|
||||
return window.btoa(Buffer.from(data, "base64").toString("utf8"));
|
||||
};
|
||||
}
|
||||
|
|
|
@ -15,43 +15,40 @@ import { useSettingsStore } from "../store/settingsStore.js";
|
|||
const settings = useSettingsStore(pinia);
|
||||
// ---------------------------------
|
||||
|
||||
console.log(process.env)
|
||||
if(typeof process.env["APPDATA"] !== "undefined"){
|
||||
var appDataFolder = process.env["APPDATA"]
|
||||
console.log(appDataFolder)
|
||||
|
||||
console.log(process.env);
|
||||
if (typeof process.env["APPDATA"] !== "undefined") {
|
||||
var appDataFolder = process.env["APPDATA"];
|
||||
console.log(appDataFolder);
|
||||
} else {
|
||||
switch (process.platform) {
|
||||
case "darwin":
|
||||
var appDataFolder = process.env["HOME"] + "/Library/Application Support";
|
||||
console.log(appDataFolder)
|
||||
switch (process.platform) {
|
||||
case "darwin":
|
||||
var appDataFolder = process.env["HOME"] + "/Library/Application Support";
|
||||
console.log(appDataFolder);
|
||||
|
||||
break;
|
||||
case "linux":
|
||||
var appDataFolder = process.env["HOME"] + "/.config";
|
||||
console.log(appDataFolder)
|
||||
break;
|
||||
case "linux":
|
||||
var appDataFolder = process.env["HOME"] + "/.config";
|
||||
console.log(appDataFolder);
|
||||
|
||||
break;
|
||||
case "linux":
|
||||
var appDataFolder = "undefined";
|
||||
break;
|
||||
case "win32":
|
||||
var appDataFolder = "undefined";
|
||||
break;
|
||||
default:
|
||||
var appDataFolder = "undefined";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "linux":
|
||||
var appDataFolder = "undefined";
|
||||
break;
|
||||
case "win32":
|
||||
var appDataFolder = "undefined";
|
||||
break;
|
||||
default:
|
||||
var appDataFolder = "undefined";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var configFolder = path.join(appDataFolder, "FreeDATA");
|
||||
var configPath = path.join(configFolder, "config.json");
|
||||
|
||||
console.log(appDataFolder)
|
||||
console.log(configFolder)
|
||||
console.log(configPath)
|
||||
|
||||
console.log(appDataFolder);
|
||||
console.log(configFolder);
|
||||
console.log(configPath);
|
||||
|
||||
// create config folder if not exists
|
||||
if (!fs.existsSync(configFolder)) {
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
var net = require("net");
|
||||
const path = require("path");
|
||||
//const FD = require("./src/js/freedata.js");
|
||||
import {atob_FD, btoa_FD} from "./freedata"
|
||||
import { atob_FD, btoa_FD } from "./freedata";
|
||||
//import FD from './freedata.js';
|
||||
|
||||
import {addDataToWaterfall} from "../js/waterfallHandler.js"
|
||||
|
||||
import { addDataToWaterfall } from "../js/waterfallHandler.js";
|
||||
|
||||
import {
|
||||
newMessageReceived,
|
||||
|
@ -167,7 +166,7 @@ client.on("data", function (socketdata) {
|
|||
continue;
|
||||
}
|
||||
}
|
||||
//console.log(data)
|
||||
//console.log(data)
|
||||
if (data["command"] == "modem_state") {
|
||||
//console.log(data)
|
||||
// set length of RX Buffer to global variable
|
||||
|
@ -186,9 +185,7 @@ client.on("data", function (socketdata) {
|
|||
stateStore.channel_busy = data["channel_busy"];
|
||||
stateStore.channel_busy_slot = data["channel_busy_slot"];
|
||||
|
||||
addDataToWaterfall(JSON.parse(data["fft"]))
|
||||
|
||||
|
||||
addDataToWaterfall(JSON.parse(data["fft"]));
|
||||
|
||||
if (data["scatter"].length > 0) {
|
||||
stateStore.scatter = data["scatter"];
|
||||
|
@ -253,7 +250,7 @@ client.on("data", function (socketdata) {
|
|||
arq_rx_frame_n_bursts: data["arq_rx_frame_n_bursts"],
|
||||
arq_rx_n_current_arq_frame: data["arq_rx_n_current_arq_frame"],
|
||||
arq_n_arq_frames_per_data_frame:
|
||||
data["arq_n_arq_frames_per_data_frame"],
|
||||
data["arq_n_arq_frames_per_data_frame"],
|
||||
arq_bytes_per_minute: data["arq_bytes_per_minute"],
|
||||
arq_compression_factor: data["arq_compression_factor"],
|
||||
routing_table: data["routing_table"],
|
||||
|
@ -272,7 +269,10 @@ client.on("data", function (socketdata) {
|
|||
if (data["freedata"] == "modem-message") {
|
||||
// break early if we received a dummy callsign
|
||||
// thats a kind of hotfix, as long as the modem isnt handling this better
|
||||
if (data["dxcallsign"] == "AA0AA-0" || data["dxcallsign"] == "ZZ9YY-0") {
|
||||
if (
|
||||
data["dxcallsign"] == "AA0AA-0" ||
|
||||
data["dxcallsign"] == "ZZ9YY-0"
|
||||
) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -334,7 +334,12 @@ client.on("data", function (socketdata) {
|
|||
switch (data["beacon"]) {
|
||||
case "transmitting":
|
||||
// BEACON TRANSMITTING
|
||||
displayToast("success", "bi-broadcast-pin", "Transmitting beacon", 5000);
|
||||
displayToast(
|
||||
"success",
|
||||
"bi-broadcast-pin",
|
||||
"Transmitting beacon",
|
||||
5000,
|
||||
);
|
||||
break;
|
||||
|
||||
case "received":
|
||||
|
@ -357,14 +362,20 @@ client.on("data", function (socketdata) {
|
|||
case "received":
|
||||
// PING RECEIVED
|
||||
message =
|
||||
"Ping request from " + data["dxcallsign"] + " | " + data["dxgrid"];
|
||||
"Ping request from " +
|
||||
data["dxcallsign"] +
|
||||
" | " +
|
||||
data["dxgrid"];
|
||||
displayToast("success", "bi-arrow-right-short", message, 5000);
|
||||
break;
|
||||
|
||||
case "acknowledge":
|
||||
// PING ACKNOWLEDGE
|
||||
message =
|
||||
"Received ping-ack from " + data["dxcallsign"] + " | " + data["dxgrid"];
|
||||
"Received ping-ack from " +
|
||||
data["dxcallsign"] +
|
||||
" | " +
|
||||
data["dxgrid"];
|
||||
displayToast("success", "bi-arrow-left-right", message, 5000);
|
||||
break;
|
||||
}
|
||||
|
@ -485,7 +496,6 @@ client.on("data", function (socketdata) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//finally delete message buffer
|
||||
|
@ -596,24 +606,22 @@ function sendFile(
|
|||
|
||||
// Send Message
|
||||
export function sendMessage(obj) {
|
||||
let dxcallsign = obj.dxcallsign;
|
||||
let checksum = obj.checksum;
|
||||
let uuid = obj.uuid;
|
||||
let command = obj.command;
|
||||
|
||||
let dxcallsign = obj.dxcallsign
|
||||
let checksum = obj.checksum
|
||||
let uuid = obj.uuid
|
||||
let command = obj.command
|
||||
let filename = Object.keys(obj._attachments)[0];
|
||||
//let filetype = filename.split(".")[1]
|
||||
let filetype = obj._attachments[filename].content_type;
|
||||
let file = obj._attachments[filename].data;
|
||||
|
||||
let filename = Object.keys(obj._attachments)[0]
|
||||
//let filetype = filename.split(".")[1]
|
||||
let filetype = obj._attachments[filename].content_type
|
||||
let file = obj._attachments[filename].data
|
||||
//console.log(obj._attachments)
|
||||
//console.log(filename)
|
||||
//console.log(filetype)
|
||||
//console.log(file)
|
||||
|
||||
//console.log(obj._attachments)
|
||||
//console.log(filename)
|
||||
//console.log(filetype)
|
||||
//console.log(file)
|
||||
|
||||
|
||||
let data_with_attachment =
|
||||
let data_with_attachment =
|
||||
obj.timestamp +
|
||||
split_char +
|
||||
obj.msg +
|
||||
|
@ -764,8 +772,7 @@ export function stopTransmission() {
|
|||
export function getRxBuffer() {
|
||||
var command = '{"type" : "get", "command" : "rx_buffer"}';
|
||||
|
||||
writeTncCommand(command);
|
||||
|
||||
writeTncCommand(command);
|
||||
}
|
||||
|
||||
// START BEACON
|
||||
|
@ -827,12 +834,11 @@ export function sendFecIsWriting(mycallsign) {
|
|||
// SEND FEC TO BROADCASTCHANNEL
|
||||
//export function sendBroadcastChannel(channel, data_out, uuid) {
|
||||
export function sendBroadcastChannel(obj) {
|
||||
|
||||
let checksum = obj.checksum;
|
||||
let command = obj.command;
|
||||
let uuid = obj.uuid;
|
||||
let channel = obj.dxcallsign
|
||||
let data_out = obj.msg
|
||||
let channel = obj.dxcallsign;
|
||||
let data_out = obj.msg;
|
||||
|
||||
let data = btoa_FD(
|
||||
"m" +
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import {Spectrum} from "../assets/waterfall/spectrum.js"
|
||||
|
||||
import { Spectrum } from "../assets/waterfall/spectrum.js";
|
||||
|
||||
import { setActivePinia } from "pinia";
|
||||
import pinia from "../store/index";
|
||||
|
@ -8,27 +7,23 @@ setActivePinia(pinia);
|
|||
import { useSettingsStore } from "../store/settingsStore.js";
|
||||
const settings = useSettingsStore(pinia);
|
||||
|
||||
var spectrum = new Object();
|
||||
|
||||
export function initWaterfall() {
|
||||
spectrum = new Spectrum("waterfall", {
|
||||
spectrumPercent: 0,
|
||||
wf_rows: 192, //Assuming 1 row = 1 pixe1, 192 is the height of the spectrum container
|
||||
});
|
||||
|
||||
var spectrum = new Object
|
||||
|
||||
export function initWaterfall(){
|
||||
spectrum = new Spectrum("waterfall", {
|
||||
spectrumPercent: 0,
|
||||
wf_rows: 192, //Assuming 1 row = 1 pixe1, 192 is the height of the spectrum container
|
||||
});
|
||||
|
||||
console.log(settings.wftheme)
|
||||
spectrum.setColorMap(settings.wftheme);
|
||||
|
||||
console.log(settings.wftheme);
|
||||
spectrum.setColorMap(settings.wftheme);
|
||||
}
|
||||
|
||||
export function addDataToWaterfall(data){
|
||||
//console.log(spectrum)
|
||||
try {
|
||||
spectrum.addData(data);
|
||||
} catch (e) {
|
||||
//console.log(e);
|
||||
}
|
||||
|
||||
}
|
||||
export function addDataToWaterfall(data) {
|
||||
//console.log(spectrum)
|
||||
try {
|
||||
spectrum.addData(data);
|
||||
} catch (e) {
|
||||
//console.log(e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,33 +1,29 @@
|
|||
import { createApp } from 'vue'
|
||||
import { createPinia } from 'pinia'
|
||||
import {loadSettings} from './js/settingsHandler'
|
||||
|
||||
import './styles.css'
|
||||
import { createApp } from "vue";
|
||||
import { createPinia } from "pinia";
|
||||
import { loadSettings } from "./js/settingsHandler";
|
||||
|
||||
import "./styles.css";
|
||||
|
||||
// Import all of Bootstrap's JS
|
||||
//import * as bootstrap from 'bootstrap'
|
||||
|
||||
import 'bootstrap/dist/js/bootstrap.bundle.min.js'
|
||||
import 'bootstrap/dist/css/bootstrap.css'
|
||||
import 'bootstrap-icons/font/bootstrap-icons.css'
|
||||
|
||||
import "bootstrap/dist/js/bootstrap.bundle.min.js";
|
||||
import "bootstrap/dist/css/bootstrap.css";
|
||||
import "bootstrap-icons/font/bootstrap-icons.css";
|
||||
|
||||
// Import our custom CSS
|
||||
//import './scss/styles.scss'
|
||||
|
||||
|
||||
|
||||
import App from './App.vue'
|
||||
const app = createApp(App)
|
||||
import App from "./App.vue";
|
||||
const app = createApp(App);
|
||||
//.mount('#app').$nextTick(() => postMessage({ payload: 'removeLoading' }, '*'))
|
||||
const pinia = createPinia()
|
||||
app.mount('#app')
|
||||
const pinia = createPinia();
|
||||
app.mount("#app");
|
||||
|
||||
app.use(pinia)
|
||||
loadSettings()
|
||||
app.use(pinia);
|
||||
loadSettings();
|
||||
|
||||
//import './js/settingsHandler.js'
|
||||
import './js/daemon'
|
||||
import './js/sock.js'
|
||||
import "./js/daemon";
|
||||
import "./js/sock.js";
|
||||
//import './js/settingsHandler.js'
|
||||
|
|
|
@ -12,19 +12,17 @@ export const useAudioStore = defineStore("audioStore", () => {
|
|||
var inputDevices = ref([{ id: 0, name: "no input devices" }]);
|
||||
var outputDevices = ref([{ id: 0, name: "no output devices" }]);
|
||||
|
||||
var startupInputDevice = ref(0)
|
||||
var startupOutputDevice = ref(0)
|
||||
|
||||
var startupInputDevice = ref(0);
|
||||
var startupOutputDevice = ref(0);
|
||||
|
||||
function getInputDevices() {
|
||||
var html = "";
|
||||
for (var key in inputDevices.value) {
|
||||
|
||||
let selected = ''
|
||||
if (inputDevices.value[key]["name"] == settings.rx_audio){
|
||||
selected = "selected"
|
||||
let selected = "";
|
||||
if (inputDevices.value[key]["name"] == settings.rx_audio) {
|
||||
selected = "selected";
|
||||
} else {
|
||||
selected = ''
|
||||
selected = "";
|
||||
}
|
||||
|
||||
html += `<option value=${inputDevices.value[key]["id"]} ${selected}>${inputDevices.value[key]["name"]}</option>`;
|
||||
|
@ -35,17 +33,23 @@ export const useAudioStore = defineStore("audioStore", () => {
|
|||
function getOutputDevices() {
|
||||
var html = "";
|
||||
for (var key in outputDevices.value) {
|
||||
|
||||
let selected = ''
|
||||
if (outputDevices.value[key]["name"] == settings.tx_audio){
|
||||
selected = "selected"
|
||||
let selected = "";
|
||||
if (outputDevices.value[key]["name"] == settings.tx_audio) {
|
||||
selected = "selected";
|
||||
} else {
|
||||
selected = ''
|
||||
selected = "";
|
||||
}
|
||||
html += `<option value=${outputDevices.value[key]["id"]} ${selected}>${outputDevices.value[key]["name"]}</option>`;
|
||||
}
|
||||
return html;
|
||||
}
|
||||
|
||||
return { inputDevices, outputDevices, getInputDevices, getOutputDevices, startupInputDevice, startupOutputDevice };
|
||||
return {
|
||||
inputDevices,
|
||||
outputDevices,
|
||||
getInputDevices,
|
||||
getOutputDevices,
|
||||
startupInputDevice,
|
||||
startupOutputDevice,
|
||||
};
|
||||
});
|
||||
|
|
|
@ -16,31 +16,31 @@ export const useChatStore = defineStore("chatStore", () => {
|
|||
var selectedCallsign = ref();
|
||||
// we need a default value in our ref because of our message info modal
|
||||
var selectedMessageObject = ref({
|
||||
"command": "msg",
|
||||
"hmac_signed": false,
|
||||
"percent": 0,
|
||||
"is_new": false,
|
||||
"_id": "2ead6698",
|
||||
"timestamp": 1697289795,
|
||||
"dxcallsign": "DJ2LS-0",
|
||||
"dxgrid": "null",
|
||||
"msg": "test",
|
||||
"checksum": "",
|
||||
"type": "transmit",
|
||||
"status": "transmitting",
|
||||
"attempt": 1,
|
||||
"uuid": "2ead6698",
|
||||
"duration": 0,
|
||||
"nacks": 0,
|
||||
"speed_list": "null",
|
||||
"_attachments": {
|
||||
"": {
|
||||
"content_type": "text",
|
||||
"data": ""
|
||||
}
|
||||
}
|
||||
});
|
||||
var inputText = ref('');
|
||||
command: "msg",
|
||||
hmac_signed: false,
|
||||
percent: 0,
|
||||
is_new: false,
|
||||
_id: "2ead6698",
|
||||
timestamp: 1697289795,
|
||||
dxcallsign: "DJ2LS-0",
|
||||
dxgrid: "null",
|
||||
msg: "test",
|
||||
checksum: "",
|
||||
type: "transmit",
|
||||
status: "transmitting",
|
||||
attempt: 1,
|
||||
uuid: "2ead6698",
|
||||
duration: 0,
|
||||
nacks: 0,
|
||||
speed_list: "null",
|
||||
_attachments: {
|
||||
"": {
|
||||
content_type: "text",
|
||||
data: "",
|
||||
},
|
||||
},
|
||||
});
|
||||
var inputText = ref("");
|
||||
var inputFile = ref();
|
||||
var inputFileName = ref();
|
||||
var inputFileType = ref();
|
||||
|
@ -62,8 +62,6 @@ export const useChatStore = defineStore("chatStore", () => {
|
|||
var beaconDataArray = ref([]);
|
||||
var beaconLabelArray = ref([]);
|
||||
|
||||
|
||||
|
||||
return {
|
||||
selectedCallsign,
|
||||
selectedMessageObject,
|
||||
|
|
|
@ -3,8 +3,8 @@ import { ref } from "vue";
|
|||
|
||||
export const useSettingsStore = defineStore("settingsStore", () => {
|
||||
// audio
|
||||
var tx_audio = ref()
|
||||
var rx_audio = ref()
|
||||
var tx_audio = ref();
|
||||
var rx_audio = ref();
|
||||
|
||||
// network
|
||||
var modem_host = ref("127.0.0.1");
|
||||
|
@ -77,19 +77,19 @@ export const useSettingsStore = defineStore("settingsStore", () => {
|
|||
var enable_mesh_features = ref("False");
|
||||
var serial_devices = ref();
|
||||
|
||||
|
||||
function getSerialDevices() {
|
||||
if (this.hamlib_deviceport == "ignore")
|
||||
var html = '<option value ="ignore" selected>None - (use custom options for hamlib)</option>';
|
||||
var html =
|
||||
'<option value ="ignore" selected>None - (use custom options for hamlib)</option>';
|
||||
else
|
||||
var html = '<option value ="ignore">None - (use custom options for hamlib)</option>';
|
||||
var html =
|
||||
'<option value ="ignore">None - (use custom options for hamlib)</option>';
|
||||
for (var key in serial_devices.value) {
|
||||
|
||||
let selected = ''
|
||||
if (serial_devices.value[key]["port"] == this. hamlib_deviceport){
|
||||
selected = "selected"
|
||||
let selected = "";
|
||||
if (serial_devices.value[key]["port"] == this.hamlib_deviceport) {
|
||||
selected = "selected";
|
||||
} else {
|
||||
selected = ''
|
||||
selected = "";
|
||||
}
|
||||
|
||||
html += `<option value="${serial_devices.value[key]["port"]}" ${selected}>${serial_devices.value[key]["port"]} - ${serial_devices.value[key]["description"]}</option>`;
|
||||
|
@ -223,6 +223,6 @@ export const useSettingsStore = defineStore("settingsStore", () => {
|
|||
tx_audio,
|
||||
rx_audio,
|
||||
getSerialDevices,
|
||||
serial_devices
|
||||
serial_devices,
|
||||
};
|
||||
});
|
||||
|
|
|
@ -59,24 +59,24 @@ export const useStateStore = defineStore("stateStore", () => {
|
|||
var python_version = ref();
|
||||
var modem_version = ref();
|
||||
|
||||
|
||||
function getChannelBusySlotState(slot){
|
||||
function getChannelBusySlotState(slot) {
|
||||
const slot_state = channel_busy_slot.value;
|
||||
|
||||
if (typeof slot_state !== 'undefined') {
|
||||
if (typeof slot_state !== "undefined") {
|
||||
// Replace 'False' with 'false' to match JavaScript's boolean representation
|
||||
const string = slot_state.replace(/False/g, 'false').replace(/True/g, 'true');
|
||||
const string = slot_state
|
||||
.replace(/False/g, "false")
|
||||
.replace(/True/g, "true");
|
||||
|
||||
// Parse the string to get an array
|
||||
const arr = JSON.parse(string);
|
||||
|
||||
return arr[slot]
|
||||
return arr[slot];
|
||||
} else {
|
||||
// Handle the undefined case
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function updateTncState(state) {
|
||||
modem_connection.value = state;
|
||||
|
@ -175,6 +175,6 @@ function getChannelBusySlotState(slot){
|
|||
rigctld_started,
|
||||
rigctld_process,
|
||||
python_version,
|
||||
modem_version
|
||||
modem_version,
|
||||
};
|
||||
});
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
import { rmSync } from 'node:fs'
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import electron from 'vite-plugin-electron'
|
||||
import renderer from 'vite-plugin-electron-renderer'
|
||||
import { notBundle } from 'vite-plugin-electron/plugin'
|
||||
import pkg from './package.json'
|
||||
import { rmSync } from "node:fs";
|
||||
import { defineConfig } from "vite";
|
||||
import vue from "@vitejs/plugin-vue";
|
||||
import electron from "vite-plugin-electron";
|
||||
import renderer from "vite-plugin-electron-renderer";
|
||||
import { notBundle } from "vite-plugin-electron/plugin";
|
||||
import pkg from "./package.json";
|
||||
|
||||
// https://vitejs.dev/config/
|
||||
export default defineConfig(({ command }) => {
|
||||
rmSync('dist-electron', { recursive: true, force: true })
|
||||
rmSync("dist-electron", { recursive: true, force: true });
|
||||
|
||||
const isServe = command === 'serve'
|
||||
const isBuild = command === 'build'
|
||||
const sourcemap = isServe || !!process.env.VSCODE_DEBUG
|
||||
const isServe = command === "serve";
|
||||
const isBuild = command === "build";
|
||||
const sourcemap = isServe || !!process.env.VSCODE_DEBUG;
|
||||
|
||||
return {
|
||||
plugins: [
|
||||
|
@ -20,25 +20,29 @@ export default defineConfig(({ command }) => {
|
|||
electron([
|
||||
{
|
||||
// Main process entry file of the Electron App.
|
||||
entry: 'electron/main/index.ts',
|
||||
entry: "electron/main/index.ts",
|
||||
onstart({ startup }) {
|
||||
if (process.env.VSCODE_DEBUG) {
|
||||
console.log(/* For `.vscode/.debug.script.mjs` */'[startup] Electron App')
|
||||
console.log(
|
||||
/* For `.vscode/.debug.script.mjs` */ "[startup] Electron App",
|
||||
);
|
||||
} else {
|
||||
startup()
|
||||
startup();
|
||||
}
|
||||
},
|
||||
vite: {
|
||||
build: {
|
||||
sourcemap,
|
||||
minify: isBuild,
|
||||
outDir: 'dist-electron/main',
|
||||
outDir: "dist-electron/main",
|
||||
rollupOptions: {
|
||||
// Some third-party Node.js libraries may not be built correctly by Vite, especially `C/C++` addons,
|
||||
// we can use `external` to exclude them to ensure they work correctly.
|
||||
// Others need to put them in `dependencies` to ensure they are collected into `app.asar` after the app is built.
|
||||
// Of course, this is not absolute, just this way is relatively simple. :)
|
||||
external: Object.keys('dependencies' in pkg ? pkg.dependencies : {}),
|
||||
external: Object.keys(
|
||||
"dependencies" in pkg ? pkg.dependencies : {},
|
||||
),
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
|
@ -49,40 +53,42 @@ export default defineConfig(({ command }) => {
|
|||
},
|
||||
},
|
||||
{
|
||||
entry: 'electron/preload/index.ts',
|
||||
entry: "electron/preload/index.ts",
|
||||
onstart({ reload }) {
|
||||
// Notify the Renderer process to reload the page when the Preload scripts build is complete,
|
||||
// instead of restarting the entire Electron App.
|
||||
reload()
|
||||
reload();
|
||||
},
|
||||
vite: {
|
||||
build: {
|
||||
sourcemap: sourcemap ? 'inline' : undefined, // #332
|
||||
sourcemap: sourcemap ? "inline" : undefined, // #332
|
||||
minify: isBuild,
|
||||
outDir: 'dist-electron/preload',
|
||||
outDir: "dist-electron/preload",
|
||||
rollupOptions: {
|
||||
external: Object.keys('dependencies' in pkg ? pkg.dependencies : {}),
|
||||
external: Object.keys(
|
||||
"dependencies" in pkg ? pkg.dependencies : {},
|
||||
),
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
isServe && notBundle(),
|
||||
],
|
||||
plugins: [isServe && notBundle()],
|
||||
},
|
||||
}
|
||||
},
|
||||
]),
|
||||
// Use Node.js API in the Renderer process
|
||||
renderer(),
|
||||
],
|
||||
server: process.env.VSCODE_DEBUG && (() => {
|
||||
const url = new URL(pkg.debug.env.VITE_DEV_SERVER_URL)
|
||||
return {
|
||||
host: url.hostname,
|
||||
port: +url.port,
|
||||
}
|
||||
})(),
|
||||
define: {
|
||||
'import.meta.env.PACKAGE_VERSION':JSON.stringify(pkg.version)
|
||||
},
|
||||
server:
|
||||
process.env.VSCODE_DEBUG &&
|
||||
(() => {
|
||||
const url = new URL(pkg.debug.env.VITE_DEV_SERVER_URL);
|
||||
return {
|
||||
host: url.hostname,
|
||||
port: +url.port,
|
||||
};
|
||||
})(),
|
||||
define: {
|
||||
"import.meta.env.PACKAGE_VERSION": JSON.stringify(pkg.version),
|
||||
},
|
||||
clearScreen: false,
|
||||
}
|
||||
})
|
||||
};
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue