2023-02-11 21:49:07 +00:00
const path = require ( "path" ) ;
const { ipcRenderer } = require ( "electron" ) ;
const { v4 : uuidv4 } = require ( "uuid" ) ;
2023-02-25 22:23:59 +00:00
const imageCompression = require ( "browser-image-compression" ) ;
2023-02-26 07:48:51 +00:00
const blobUtil = require ( "blob-util" ) ;
2023-03-03 03:05:45 +00:00
const FD = require ( "./freedata" ) ;
2023-03-05 21:16:43 +00:00
const fs = require ( "fs" ) ;
2023-02-26 07:48:51 +00:00
2021-11-19 16:30:17 +00:00
// https://stackoverflow.com/a/26227660
2023-02-11 21:49:07 +00:00
var appDataFolder =
process . env . APPDATA ||
( process . platform == "darwin"
? process . env . HOME + "/Library/Application Support"
: process . env . HOME + "/.config" ) ;
2021-11-19 16:30:17 +00:00
var configFolder = path . join ( appDataFolder , "FreeDATA" ) ;
2023-02-11 21:49:07 +00:00
var configPath = path . join ( configFolder , "config.json" ) ;
2023-03-04 15:47:42 +00:00
var config = require ( configPath ) ;
2022-03-10 20:29:30 +00:00
// set date format
2023-02-25 00:04:19 +00:00
const dateFormat = new Intl . DateTimeFormat ( navigator . language , {
2023-02-11 21:49:07 +00:00
timeStyle : "long" ,
2023-02-23 10:48:19 +00:00
dateStyle : "short" ,
2022-03-10 20:29:30 +00:00
} ) ;
2022-03-24 19:49:13 +00:00
// set date format information
2023-02-25 00:04:19 +00:00
const dateFormatShort = new Intl . DateTimeFormat ( navigator . language , {
2023-02-11 21:49:07 +00:00
year : "numeric" ,
month : "numeric" ,
day : "numeric" ,
hour : "numeric" ,
minute : "numeric" ,
second : "numeric" ,
hour12 : false ,
2022-03-24 19:49:13 +00:00
} ) ;
2022-04-02 16:40:12 +00:00
2023-02-25 00:04:19 +00:00
const dateFormatHours = new Intl . DateTimeFormat ( navigator . language , {
2023-02-11 21:49:07 +00:00
hour : "numeric" ,
minute : "numeric" ,
hour12 : false ,
2022-04-02 16:40:12 +00:00
} ) ;
2022-03-10 20:29:30 +00:00
// split character
2023-02-11 21:49:07 +00:00
const split _char = "\0;\1;" ;
2022-03-24 19:49:13 +00:00
// global for our selected file we want to transmit
2022-03-29 20:24:35 +00:00
// ----------------- some chat globals
2023-02-11 21:49:07 +00:00
var filetype = "" ;
var file = "" ;
var filename = "" ;
2022-03-29 20:24:35 +00:00
var callsign _counter = 0 ;
2023-02-11 21:49:07 +00:00
var selected _callsign = "" ;
2023-02-12 23:15:12 +00:00
var lastIsWritingBroadcast = new Date ( ) . getTime ( ) ;
2023-02-28 19:07:10 +00:00
var defaultUserIcon =
"data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0iY3VycmVudENvbG9yIiBjbGFzcz0iYmkgYmktcGVyc29uLWJvdW5kaW5nLWJveCIgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8cGF0aCBkPSJNMS41IDFhLjUuNSAwIDAgMC0uNS41djNhLjUuNSAwIDAgMS0xIDB2LTNBMS41IDEuNSAwIDAgMSAxLjUgMGgzYS41LjUgMCAwIDEgMCAxaC0zek0xMSAuNWEuNS41IDAgMCAxIC41LS41aDNBMS41IDEuNSAwIDAgMSAxNiAxLjV2M2EuNS41IDAgMCAxLTEgMHYtM2EuNS41IDAgMCAwLS41LS41aC0zYS41LjUgMCAwIDEtLjUtLjV6TS41IDExYS41LjUgMCAwIDEgLjUuNXYzYS41LjUgMCAwIDAgLjUuNWgzYS41LjUgMCAwIDEgMCAxaC0zQTEuNSAxLjUgMCAwIDEgMCAxNC41di0zYS41LjUgMCAwIDEgLjUtLjV6bTE1IDBhLjUuNSAwIDAgMSAuNS41djNhMS41IDEuNSAwIDAgMS0xLjUgMS41aC0zYS41LjUgMCAwIDEgMC0xaDNhLjUuNSAwIDAgMCAuNS0uNXYtM2EuNS41IDAgMCAxIC41LS41eiIvPgogIDxwYXRoIGQ9Ik0zIDE0cy0xIDAtMS0xIDEtNCA2LTQgNiAzIDYgNC0xIDEtMSAxSDN6bTgtOWEzIDMgMCAxIDEtNiAwIDMgMyAwIDAgMSA2IDB6Ii8+Cjwvc3ZnPg==" ;
2023-02-28 19:06:39 +00:00
2022-03-29 20:24:35 +00:00
// -----------------------------------
2023-02-28 14:19:41 +00:00
// Initially fill sharedFolderFileList
//TODO: Make this automatically ever N seconds
2023-02-28 14:20:17 +00:00
var sharedFolderFileList = "" ;
2023-02-28 14:19:41 +00:00
ipcRenderer . send ( "read-files-in-folder" , {
2023-02-28 14:20:17 +00:00
folder : config . shared _folder _path ,
} ) ;
2022-04-03 13:26:24 +00:00
2023-02-11 21:49:07 +00:00
var chatDB = path . join ( configFolder , "chatDB" ) ;
2023-02-19 13:36:29 +00:00
var userDB = path . join ( configFolder , "userDB" ) ;
2022-03-10 20:29:30 +00:00
// ---- MessageDB
2023-02-11 21:49:07 +00:00
try {
var PouchDB = require ( "pouchdb" ) ;
} catch ( err ) {
console . log ( err ) ;
2022-06-15 12:34:17 +00:00
2023-02-11 21:49:07 +00:00
/ *
2022-06-15 12:34:17 +00:00
This is a fix for raspberryPi where we get an error when loading pouchdb because of
leveldown package isnt running on ARM devices .
pouchdb - browser does not depend on leveldb and seems to be working .
* /
2023-02-11 21:49:07 +00:00
console . log ( "using pouchdb-browser fallback" ) ;
var PouchDB = require ( "pouchdb-browser" ) ;
2022-06-15 12:34:17 +00:00
}
2023-02-11 21:49:07 +00:00
PouchDB . plugin ( require ( "pouchdb-find" ) ) ;
2022-12-26 19:41:58 +00:00
//PouchDB.plugin(require('pouchdb-replication'));
2023-05-09 08:36:30 +00:00
PouchDB . plugin ( require ( "pouchdb-upsert" ) ) ;
2022-12-26 19:41:58 +00:00
2022-03-10 20:29:30 +00:00
var db = new PouchDB ( chatDB ) ;
2023-02-18 18:55:13 +00:00
var users = new PouchDB ( userDB ) ;
2022-11-17 21:17:50 +00:00
2023-02-19 13:36:29 +00:00
/* -------- CREATE DATABASE INDEXES */
2023-02-20 17:55:21 +00:00
createChatIndex ( ) ;
createUserIndex ( ) ;
2023-02-19 13:36:29 +00:00
2023-02-25 22:23:59 +00:00
// REMOTE SYNC ATTEMPTS
2022-12-26 19:41:58 +00:00
2023-02-25 22:23:59 +00:00
//var remoteDB = new PouchDB('http://172.20.10.4:5984/chatDB')
/ *
2022-12-26 19:41:58 +00:00
// we need express packages for running pouchdb sync "express-pouchdb"
var express = require ( 'express' ) ;
var app = express ( ) ;
2023-02-25 22:23:59 +00:00
app . use ( '/chatDB' , require ( 'express-pouchdb' ) ( PouchDB ) ) ;
app . listen ( 5984 ) ;
2022-12-26 19:41:58 +00:00
app . use ( '/chatDB' , require ( 'pouchdb-express-router' ) ( PouchDB ) ) ;
app . listen ( 5984 ) ;
db . sync ( 'http://172.20.10.4:5984/jojo' , {
//var sync = PouchDB.sync('chatDB', 'http://172.20.10.4:5984/chatDB', {
2022-11-17 21:17:50 +00:00
live : true ,
2022-12-26 19:41:58 +00:00
retry : false
2022-11-17 21:17:50 +00:00
} ) . on ( 'change' , function ( change ) {
// yo, something changed!
console . log ( change )
2022-12-26 19:41:58 +00:00
} ) . on ( 'paused' , function ( err ) {
2022-11-17 21:17:50 +00:00
// replication was paused, usually because of a lost connection
2022-12-26 19:41:58 +00:00
console . log ( err )
2022-11-17 21:17:50 +00:00
} ) . on ( 'active' , function ( info ) {
// replication was resumed
console . log ( info )
} ) . on ( 'error' , function ( err ) {
// totally unhandled error (shouldn't happen)
2022-12-26 19:41:58 +00:00
console . log ( err )
} ) . on ( 'denied' , function ( err ) {
// a document failed to replicate (e.g. due to permissions)
console . log ( err )
} ) . on ( 'complete' , function ( info ) {
// handle complete;
console . log ( info )
2022-11-17 21:17:50 +00:00
} ) ;
2022-12-26 19:41:58 +00:00
* /
2022-11-17 21:17:50 +00:00
2022-03-10 20:29:30 +00:00
var dxcallsigns = new Set ( ) ;
2023-03-04 15:26:17 +00:00
//Set default chat filter
2023-02-20 17:55:21 +00:00
var chatFilter = [
{ type : "newchat" } ,
{ type : "received" } ,
{ type : "transmit" } ,
{ type : "ping-ack" } ,
2023-03-04 15:26:17 +00:00
//{ type: "request" },
//{ type: "response" },
2023-02-20 17:55:21 +00:00
] ;
2023-02-19 13:36:29 +00:00
2023-02-19 14:37:51 +00:00
updateAllChat ( false ) ;
2022-11-17 21:17:50 +00:00
2021-11-19 16:30:17 +00:00
// WINDOW LISTENER
2023-02-11 21:49:07 +00:00
window . addEventListener ( "DOMContentLoaded" , ( ) => {
// theme selector
2023-03-16 07:59:54 +00:00
changeGuiDesign ( config . theme ) ;
2023-02-11 21:49:07 +00:00
2023-02-19 14:59:38 +00:00
const userInfoFields = [
2023-02-26 09:48:21 +00:00
"user_info_image" ,
2023-02-19 14:59:38 +00:00
"user_info_callsign" ,
"user_info_gridsquare" ,
"user_info_name" ,
"user_info_age" ,
"user_info_location" ,
"user_info_radio" ,
"user_info_antenna" ,
"user_info_email" ,
"user_info_website" ,
"user_info_comments" ,
] ;
2023-02-18 18:55:13 +00:00
users
. find ( {
selector : {
2023-02-19 14:37:51 +00:00
user _info _callsign : config . mycall ,
2023-02-18 18:55:13 +00:00
} ,
} )
. then ( function ( result ) {
2023-02-26 10:04:14 +00:00
console . log ( result ) ;
2023-02-20 17:55:21 +00:00
if ( typeof result . docs [ 0 ] !== "undefined" ) {
// handle result
userInfoFields . forEach ( function ( elem ) {
2023-02-26 10:04:14 +00:00
if ( elem !== "user_info_image" ) {
document . getElementById ( elem ) . value = result . docs [ 0 ] [ elem ] ;
} else {
document . getElementById ( elem ) . src = result . docs [ 0 ] [ elem ] ;
}
2023-02-20 17:55:21 +00:00
} ) ;
2023-02-23 11:13:49 +00:00
} else {
2023-02-23 11:14:31 +00:00
console . log (
config . mycall + " not found in user db - creating new entry"
) ;
// add initial entry for own callsign and grid
let obj = new Object ( ) ;
obj . user _info _callsign = config . mycall ;
obj . user _info _gridsquare = config . mygrid ;
addUserToDatabaseIfNotExists ( obj ) ;
2023-02-23 11:13:49 +00:00
2023-02-23 11:14:31 +00:00
document . getElementById ( "user_info_callsign" ) . value = config . mycall ;
document . getElementById ( "user_info_gridsquare" ) . value = config . mygrid ;
2023-02-19 14:59:38 +00:00
}
2023-02-18 18:55:13 +00:00
} )
. catch ( function ( err ) {
console . log ( err ) ;
} ) ;
2023-02-26 10:04:14 +00:00
//save user info
2023-02-26 09:48:21 +00:00
document . getElementById ( "userInfoSave" ) . addEventListener ( "click" , ( ) => {
let obj = new Object ( ) ;
2023-02-26 10:04:14 +00:00
userInfoFields . forEach ( function ( subelem ) {
if ( subelem !== "user_info_image" ) {
obj [ subelem ] = document . getElementById ( subelem ) . value ;
} else {
obj [ subelem ] = document . getElementById ( subelem ) . src ;
}
} ) ;
addUserToDatabaseIfNotExists ( obj ) ;
2023-02-18 18:55:13 +00:00
} ) ;
2023-02-19 07:06:28 +00:00
//Add event listener for filter apply button
2023-02-20 17:55:21 +00:00
document . getElementById ( "btnFilter" ) . addEventListener ( "click" , ( ) => {
chatFilter = [ { type : "newchat" } ] ;
if ( document . getElementById ( "chkMessage" ) . checked == true )
chatFilter . push ( { type : "received" } , { type : "transmit" } ) ;
if ( document . getElementById ( "chkPing" ) . checked == true )
chatFilter . push ( { type : "ping" } ) ;
if ( document . getElementById ( "chkPingAck" ) . checked == true )
chatFilter . push ( { type : "ping-ack" } ) ;
if ( document . getElementById ( "chkBeacon" ) . checked == true )
chatFilter . push ( { type : "beacon" } ) ;
2023-02-26 15:27:55 +00:00
if ( document . getElementById ( "chkRequest" ) . checked == true )
2023-02-26 14:41:49 +00:00
chatFilter . push ( { type : "request" } ) ;
2023-02-26 15:27:55 +00:00
if ( document . getElementById ( "chkResponse" ) . checked == true )
2023-02-26 15:26:24 +00:00
chatFilter . push ( { type : "response" } ) ;
2023-02-19 07:06:28 +00:00
updateAllChat ( true ) ;
} ) ;
2023-02-19 13:36:29 +00:00
2023-02-11 21:49:07 +00:00
document
. querySelector ( "emoji-picker" )
. addEventListener ( "emoji-click" , ( event ) => {
var msg = document . getElementById ( "chatModuleMessage" ) ;
//Convert to utf-8--so we can just use utf-8 everywhere
msg . setRangeText ( event . detail . emoji . unicode . toString ( "utf-8" ) ) ;
//console.log(event.detail);
//msg.focus();
} ) ;
document . getElementById ( "emojipickerbutton" ) . addEventListener ( "click" , ( ) => {
var element = document . getElementById ( "emojipickercontainer" ) ;
console . log ( element . style . display ) ;
if ( element . style . display === "none" ) {
element . style . display = "block" ;
} else {
element . style . display = "none" ;
2022-04-03 13:26:24 +00:00
}
2023-02-11 21:49:07 +00:00
} ) ;
document
. getElementById ( "delete_selected_chat" )
. addEventListener ( "click" , ( ) => {
db . find ( {
selector : {
dxcallsign : selected _callsign ,
} ,
} )
. then ( function ( result ) {
// handle result
if ( typeof result !== "undefined" ) {
result . docs . forEach ( function ( item ) {
console . log ( item ) ;
db . get ( item . _id )
. then ( function ( doc ) {
db . remove ( doc )
. then ( function ( doc ) {
return location . reload ( ) ;
} )
. catch ( function ( err ) {
console . log ( err ) ;
2022-03-29 20:24:35 +00:00
} ) ;
2023-02-11 21:49:07 +00:00
} )
. catch ( function ( err ) {
console . log ( err ) ;
2022-03-29 20:24:35 +00:00
} ) ;
2023-02-11 21:49:07 +00:00
} ) ;
}
} )
. catch ( function ( err ) {
console . log ( err ) ;
2022-03-29 20:24:35 +00:00
} ) ;
2023-02-11 21:49:07 +00:00
} ) ;
document . getElementById ( "selectFilesButton" ) . addEventListener ( "click" , ( ) => {
//document.getElementById('selectFiles').click();
ipcRenderer . send ( "select-file" , {
title : "Title" ,
} ) ;
} ) ;
2022-11-08 18:53:14 +00:00
2023-02-26 13:08:26 +00:00
document . getElementById ( "requestUserInfo" ) . addEventListener ( "click" , ( ) => {
ipcRenderer . send ( "run-tnc-command" , {
command : "requestUserInfo" ,
dxcallsign : selected _callsign ,
} ) ;
2023-02-26 16:54:21 +00:00
2023-02-28 19:37:55 +00:00
pauseButton ( document . getElementById ( "requestUserInfo" ) , 60000 ) ;
2023-02-26 13:08:26 +00:00
} ) ;
2023-02-11 21:49:07 +00:00
document . getElementById ( "ping" ) . addEventListener ( "click" , ( ) => {
ipcRenderer . send ( "run-tnc-command" , {
command : "ping" ,
dxcallsign : selected _callsign ,
} ) ;
} ) ;
2022-11-08 18:53:14 +00:00
2023-02-11 21:49:07 +00:00
document . addEventListener ( "keyup" , function ( event ) {
// Number 13 == Enter
2023-02-20 17:55:21 +00:00
if (
event . keyCode === 13 &&
! event . shiftKey &&
document . activeElement . id == "chatModuleMessage"
2023-02-19 14:37:51 +00:00
) {
2023-02-11 21:49:07 +00:00
// Cancel the default action, if needed
event . preventDefault ( ) ;
// Trigger the button element with a click
document . getElementById ( "sendMessage" ) . click ( ) ;
}
} ) ;
2022-11-08 18:53:14 +00:00
2023-02-11 21:49:07 +00:00
// ADJUST TEXTAREA SIZE
document . getElementById ( "chatModuleMessage" ) . addEventListener ( "input" , ( ) => {
var textarea = document . getElementById ( "chatModuleMessage" ) ;
var text = textarea . value ;
2022-11-08 18:53:14 +00:00
2023-02-11 21:49:07 +00:00
if ( document . getElementById ( "expand_textarea" ) . checked ) {
var lines = 6 ;
} else {
var lines = text . split ( "\n" ) . length ;
2022-11-08 18:53:14 +00:00
2023-02-11 21:49:07 +00:00
if ( lines >= 6 ) {
lines = 6 ;
}
}
var message _container _height _offset = 130 + 20 * lines ;
var message _container _height = ` calc(100% - ${ message _container _height _offset } px) ` ;
document . getElementById ( "message-container" ) . style . height =
message _container _height ;
textarea . rows = lines ;
console . log ( textarea . value ) ;
2023-05-09 11:15:39 +00:00
if ( lastIsWritingBroadcast < new Date ( ) . getTime ( ) - 5 * 2000 ) {
2023-02-12 23:15:12 +00:00
//console.log("Sending FECIsWriting");
2023-02-14 15:00:34 +00:00
console . log ( config . enable _is _writing ) ;
if ( config . enable _is _writing == "True" ) {
2023-02-14 15:00:10 +00:00
ipcRenderer . send ( "tnc-fec-iswriting" ) ;
}
2023-02-12 23:15:12 +00:00
lastIsWritingBroadcast = new Date ( ) . getTime ( ) ;
}
2023-02-11 21:49:07 +00:00
} ) ;
document . getElementById ( "expand_textarea" ) . addEventListener ( "click" , ( ) => {
var textarea = document . getElementById ( "chatModuleMessage" ) ;
if ( document . getElementById ( "expand_textarea" ) . checked ) {
var lines = 6 ;
document . getElementById ( "expand_textarea_button" ) . className =
"bi bi-chevron-compact-down" ;
} else {
var lines = 1 ;
document . getElementById ( "expand_textarea_button" ) . className =
"bi bi-chevron-compact-up" ;
}
2022-04-02 12:54:43 +00:00
2023-02-11 21:49:07 +00:00
var message _container _height _offset = 130 + 20 * lines ;
//var message_container_height_offset = 90 + (23*lines);
var message _container _height = ` calc(100% - ${ message _container _height _offset } px) ` ;
document . getElementById ( "message-container" ) . style . height =
message _container _height ;
textarea . rows = lines ;
console . log ( textarea . rows ) ;
} ) ;
// NEW CHAT
document
. getElementById ( "createNewChatButton" )
. addEventListener ( "click" , ( ) => {
var dxcallsign = document . getElementById ( "chatModuleNewDxCall" ) . value ;
var uuid = uuidv4 ( ) ;
db . post ( {
_id : uuid ,
timestamp : Math . floor ( Date . now ( ) / 1000 ) ,
dxcallsign : dxcallsign . toUpperCase ( ) ,
dxgrid : "---" ,
msg : "null" ,
checksum : "null" ,
type : "newchat" ,
status : "null" ,
uuid : uuid ,
} )
. then ( function ( response ) {
// handle response
console . log ( "new database entry" ) ;
console . log ( response ) ;
} )
. catch ( function ( err ) {
console . log ( err ) ;
2022-04-02 12:54:43 +00:00
} ) ;
2023-02-11 21:49:07 +00:00
update _chat _obj _by _uuid ( uuid ) ;
2022-04-02 12:54:43 +00:00
} ) ;
2022-06-07 09:31:59 +00:00
2023-02-25 22:24:28 +00:00
// open file selector for user image
document . getElementById ( "userImageSelector" ) . addEventListener ( "click" , ( ) => {
ipcRenderer . send ( "select-user-image" , {
2023-02-25 22:23:59 +00:00
title : "Title" ,
} ) ;
2023-02-25 22:24:28 +00:00
} ) ;
2023-02-25 22:23:59 +00:00
2023-02-28 12:55:11 +00:00
// open file selector for shared folder
2023-02-28 12:55:54 +00:00
document
. getElementById ( "sharedFolderButton" )
. addEventListener ( "click" , ( ) => {
ipcRenderer . send ( "read-files-in-folder" , {
folder : config . shared _folder _path ,
} ) ;
2023-02-28 12:55:11 +00:00
} ) ;
document
. getElementById ( "openSharedFilesFolder" )
. addEventListener ( "click" , ( ) => {
ipcRenderer . send ( "open-folder" , {
path : config . shared _folder _path ,
} ) ;
} ) ;
2023-02-28 14:20:17 +00:00
document
2023-02-28 14:19:41 +00:00
. getElementById ( "requestSharedFolderList" )
. addEventListener ( "click" , ( ) => {
2023-02-28 14:20:17 +00:00
ipcRenderer . send ( "run-tnc-command" , {
command : "requestSharedFolderList" ,
dxcallsign : selected _callsign ,
} ) ;
2023-02-28 19:37:55 +00:00
pauseButton ( document . getElementById ( "requestSharedFolderList" ) , 60000 ) ;
2023-02-28 14:19:41 +00:00
} ) ;
2023-02-11 21:49:07 +00:00
// SEND MSG
document . getElementById ( "sendMessage" ) . addEventListener ( "click" , ( ) => {
document . getElementById ( "emojipickercontainer" ) . style . display = "none" ;
var dxcallsign = selected _callsign . toUpperCase ( ) ;
var textarea = document . getElementById ( "chatModuleMessage" ) ;
var chatmessage = textarea . value ;
//Remove non-printable chars from begining and end of string--should save us a byte here and there
chatmessage = chatmessage . toString ( ) . trim ( ) ;
// reset textarea size
var message _container _height _offset = 150 ;
var message _container _height = ` calc(100% - ${ message _container _height _offset } px) ` ;
document . getElementById ( "message-container" ) . style . height =
message _container _height ;
textarea . rows = 1 ;
document . getElementById ( "expand_textarea_button" ) . className =
"bi bi-chevron-compact-up" ;
document . getElementById ( "expand_textarea" ) . checked = false ;
console . log ( file ) ;
console . log ( filename ) ;
console . log ( filetype ) ;
if ( filetype == "" ) {
filetype = "plain/text" ;
}
var timestamp = Math . floor ( Date . now ( ) / 1000 ) ;
var file _checksum = crc32 ( file ) . toString ( 16 ) . toUpperCase ( ) ;
console . log ( file _checksum ) ;
var data _with _attachment =
timestamp +
split _char +
chatmessage +
split _char +
filename +
split _char +
filetype +
split _char +
file ;
document . getElementById ( "selectFilesButton" ) . innerHTML = ` ` ;
var uuid = uuidv4 ( ) ;
let uuidlast = uuid . lastIndexOf ( "-" ) ;
uuidlast += 1 ;
if ( uuidlast > 0 ) {
uuid = uuid . substring ( uuidlast ) ;
}
console . log ( data _with _attachment ) ;
let Data = {
2023-02-26 15:26:24 +00:00
command : "msg" ,
2023-02-11 21:49:07 +00:00
dxcallsign : dxcallsign ,
mode : 255 ,
2023-04-25 13:46:17 +00:00
frames : 5 ,
2023-02-11 21:49:07 +00:00
data : data _with _attachment ,
checksum : file _checksum ,
uuid : uuid ,
} ;
ipcRenderer . send ( "run-tnc-command" , Data ) ;
db . post ( {
_id : uuid ,
timestamp : timestamp ,
dxcallsign : dxcallsign ,
dxgrid : "null" ,
msg : chatmessage ,
checksum : file _checksum ,
type : "transmit" ,
status : "transmit" ,
2023-05-09 08:35:50 +00:00
attempt : 1 ,
2023-02-11 21:49:07 +00:00
uuid : uuid ,
_attachments : {
[ filename ] : {
content _type : filetype ,
//data: btoa(file)
2023-03-03 03:05:45 +00:00
data : FD . btoa _FD ( file ) ,
2023-02-11 21:49:07 +00:00
} ,
} ,
2021-11-19 16:30:17 +00:00
} )
2023-02-11 21:49:07 +00:00
. then ( function ( response ) {
// handle response
console . log ( "new database entry" ) ;
console . log ( response ) ;
} )
. catch ( function ( err ) {
console . log ( err ) ;
} ) ;
update _chat _obj _by _uuid ( uuid ) ;
// clear input
document . getElementById ( "chatModuleMessage" ) . value = "" ;
// after adding file data to our attachment variable, delete it from global
filetype = "" ;
file = "" ;
filename = "" ;
} ) ;
// cleanup after transmission
filetype = "" ;
file = "" ;
filename = "" ;
2022-03-24 19:49:13 +00:00
} ) ;
2023-02-28 12:55:11 +00:00
2023-02-11 21:49:07 +00:00
ipcRenderer . on ( "return-selected-files" , ( event , arg ) => {
filetype = arg . mime ;
console . log ( filetype ) ;
2022-06-09 12:54:42 +00:00
2023-02-11 21:49:07 +00:00
file = arg . data ;
filename = arg . filename ;
document . getElementById ( "selectFilesButton" ) . innerHTML = `
2022-04-03 13:26:24 +00:00
< span class = "position-absolute top-0 start-85 translate-middle p-2 bg-danger border border-light rounded-circle" >
2022-03-24 19:49:13 +00:00
< span class = "visually-hidden" > New file selected < / s p a n >
2023-02-18 18:55:13 +00:00
< / s p a n >
2022-03-24 19:49:13 +00:00
` ;
2022-03-14 19:21:15 +00:00
} ) ;
2023-02-25 22:23:59 +00:00
2023-02-28 12:55:11 +00:00
ipcRenderer . on ( "return-shared-folder-files" , ( event , arg ) => {
2023-02-28 12:55:54 +00:00
console . log ( arg ) ;
2023-02-28 14:20:17 +00:00
sharedFolderFileList = arg . files ;
2023-02-28 12:55:11 +00:00
var tbl = document . getElementById ( "sharedFolderTable" ) ;
2023-03-04 16:12:28 +00:00
if ( tbl == undefined ) return ;
2023-02-28 12:55:11 +00:00
tbl . innerHTML = "" ;
2023-02-28 12:55:54 +00:00
let counter = 0 ;
arg . files . forEach ( ( file ) => {
2023-03-19 15:18:32 +00:00
//console.log(file["name"]);
2023-02-28 12:55:54 +00:00
var row = document . createElement ( "tr" ) ;
let id = document . createElement ( "td" ) ;
let idText = document . createElement ( "span" ) ;
idText . innerText = counter += 1 ;
id . appendChild ( idText ) ;
row . appendChild ( id ) ;
let filename = document . createElement ( "td" ) ;
let filenameText = document . createElement ( "span" ) ;
filenameText . innerText = file [ "name" ] ;
filename . appendChild ( filenameText ) ;
row . appendChild ( filename ) ;
let filetype = document . createElement ( "td" ) ;
let filetypeText = document . createElement ( "span" ) ;
filetypeText . innerHTML = `
< i class = "bi bi-filetype-${file[" extension "]}" style = "font-size: 1.8rem" > < / i >
2023-02-28 12:55:11 +00:00
` ;
2023-02-28 12:55:54 +00:00
filetype . appendChild ( filetypeText ) ;
row . appendChild ( filetype ) ;
2023-02-28 12:55:11 +00:00
2023-02-28 12:55:54 +00:00
let filesize = document . createElement ( "td" ) ;
let filesizeText = document . createElement ( "span" ) ;
2023-03-04 12:24:37 +00:00
filesizeText . innerText = formatBytes ( file [ "size" ] , 2 ) ;
2023-02-28 12:55:54 +00:00
filesize . appendChild ( filesizeText ) ;
row . appendChild ( filesize ) ;
2023-02-28 12:55:11 +00:00
2023-02-28 12:55:54 +00:00
tbl . appendChild ( row ) ;
2023-02-28 12:55:11 +00:00
} ) ;
} ) ;
2023-02-25 22:23:59 +00:00
ipcRenderer . on ( "return-select-user-image" , ( event , arg ) => {
2023-02-26 07:48:51 +00:00
let imageFiletype = arg . mime ;
let imageFile = arg . data ;
2023-02-25 22:23:59 +00:00
2023-02-26 07:49:19 +00:00
imageFile = blobUtil . base64StringToBlob ( imageFile , imageFiletype ) ;
2023-02-25 22:23:59 +00:00
var options = {
2023-02-26 17:31:11 +00:00
maxSizeMB : 0.01 ,
2023-02-26 17:30:52 +00:00
maxWidthOrHeight : 125 ,
2023-02-26 07:48:51 +00:00
useWebWorker : false ,
2023-02-25 22:24:28 +00:00
} ;
2023-02-25 22:23:59 +00:00
imageCompression ( imageFile , options )
. then ( function ( compressedFile ) {
2023-02-25 22:24:28 +00:00
console . log (
"compressedFile instanceof Blob" ,
compressedFile instanceof Blob
) ; // true
console . log (
` compressedFile size ${ compressedFile . size / 1024 / 1024 } MB `
) ; // smaller than maxSizeMB
2023-02-25 22:23:59 +00:00
console . log ( compressedFile . size ) ;
2023-02-26 08:18:13 +00:00
2023-02-26 08:22:38 +00:00
blobUtil
. blobToBase64String ( compressedFile )
. then ( function ( base64String ) {
2023-02-26 08:18:13 +00:00
// update image
2023-02-26 09:48:21 +00:00
document . getElementById ( "user_info_image" ) . src =
2023-02-26 08:22:38 +00:00
"data:" + imageFiletype + ";base64," + base64String ;
} )
. catch ( function ( err ) {
2023-02-26 09:48:21 +00:00
document . getElementById ( "user_info_image" ) . src = "img/icon.png" ;
2023-02-26 08:18:13 +00:00
} ) ;
2023-02-25 22:23:59 +00:00
} )
. catch ( function ( error ) {
console . log ( error . message ) ;
} ) ;
} ) ;
2023-02-11 21:49:07 +00:00
ipcRenderer . on ( "action-update-transmission-status" , ( event , arg ) => {
var data = arg [ "data" ] [ 0 ] ;
console . log ( data . status ) ;
2023-02-27 17:10:11 +00:00
if ( data . uuid !== "no-uuid" ) {
db . get ( data . uuid , {
attachments : true ,
} )
. then ( function ( doc ) {
return db . put ( {
_id : doc . uuid . toString ( ) ,
_rev : doc . _rev ,
timestamp : doc . timestamp ,
dxcallsign : doc . dxcallsign ,
dxgrid : doc . dxgrid ,
msg : doc . msg ,
checksum : doc . checksum ,
type : "transmit" ,
status : data . status ,
percent : data . percent ,
bytesperminute : data . bytesperminute ,
uuid : doc . uuid ,
_attachments : doc . _attachments ,
2023-02-27 17:09:26 +00:00
} ) ;
2023-02-27 17:10:11 +00:00
} )
. then ( function ( response ) {
update _chat _obj _by _uuid ( data . uuid ) ;
} )
. catch ( function ( err ) {
console . log ( err ) ;
console . log ( data ) ;
} ) ;
}
2022-03-10 20:29:30 +00:00
} ) ;
2023-02-14 03:49:26 +00:00
//Render is typing message in correct chat window
2023-02-14 03:50:05 +00:00
ipcRenderer . on ( "action-show-feciswriting" , ( event , arg ) => {
2023-02-14 03:49:26 +00:00
//console.log("In action-show-feciswriting");
//console.log(arg);
let uuid = uuidv4 . toString ( ) ;
let dxcallsign = arg [ "data" ] [ 0 ] [ "dxcallsign" ] ;
var new _message = `
2023-02-14 14:31:08 +00:00
< div class = "m-auto mt-1 p-0 w-25 rounded bg-secondary bg-gradient" id = "msg-${uuid}" >
< p class = "text-white mb-0 text-break" style = "font-size: 0.7rem;" > < i class = "m-1 bi bi-pencil" > < /i><i id="msg-${uuid}-icon" class="m-1 bi bi-wifi-1"></i > $ { dxcallsign } is typing ... . < / p >
2023-02-18 18:55:13 +00:00
2023-02-14 03:49:26 +00:00
< / d i v >
` ;
var id = "chat-" + dxcallsign ;
let chatwin = document . getElementById ( id ) ;
if ( chatwin == undefined ) {
//console.log("Element not found!!!!! :(");
return ;
}
chatwin . insertAdjacentHTML ( "beforeend" , new _message ) ;
scrollMessagesToBottom ( ) ;
let animIcon = document . getElementById ( "msg-" + uuid + "-icon" ) ;
//Remove notification after about 4.5 seconds hopefully enough time before a second notification can come in
setTimeout ( function ( ) {
2023-02-14 03:50:05 +00:00
animIcon . classList = "m-1 bi bi-wifi-2" ;
2023-02-14 03:49:26 +00:00
} , 1000 ) ;
setTimeout ( function ( ) {
2023-02-14 03:50:05 +00:00
animIcon . classList = "m-1 bi bi-wifi" ;
2023-02-14 03:49:26 +00:00
} , 2000 ) ;
setTimeout ( function ( ) {
2023-02-14 03:50:05 +00:00
animIcon . classList = "m-1 bi bi-wifi-2" ;
2023-02-14 03:49:26 +00:00
} , 3000 ) ;
setTimeout ( function ( ) {
2023-02-14 03:50:05 +00:00
animIcon . classList = "m-1 bi bi-wifi-1" ;
2023-02-14 03:49:26 +00:00
} , 4000 ) ;
setTimeout ( ( ) => {
2023-02-14 03:50:05 +00:00
let feciw = document . getElementById ( "msg-" + uuid ) ;
2023-02-14 03:49:26 +00:00
feciw . remove ( ) ;
} , 4500 ) ;
} ) ;
2023-02-11 21:49:07 +00:00
ipcRenderer . on ( "action-new-msg-received" , ( event , arg ) => {
console . log ( arg . data ) ;
var new _msg = arg . data ;
new _msg . forEach ( function ( item ) {
console . log ( item . status ) ;
let obj = new Object ( ) ;
//handle ping
if ( item . ping == "received" ) {
obj . timestamp = parseInt ( item . timestamp ) ;
obj . dxcallsign = item . dxcallsign ;
obj . dxgrid = item . dxgrid ;
obj . uuid = item . uuid ;
obj . command = "ping" ;
obj . checksum = "null" ;
obj . msg = "null" ;
obj . status = item . status ;
obj . snr = item . snr ;
obj . type = "ping" ;
obj . filename = "null" ;
obj . filetype = "null" ;
obj . file = "null" ;
add _obj _to _database ( obj ) ;
update _chat _obj _by _uuid ( obj . uuid ) ;
2023-02-19 05:02:06 +00:00
// handle beacon
2023-05-09 08:36:30 +00:00
} else if ( item . ping == "acknowledge" ) {
2023-02-19 05:02:06 +00:00
obj . timestamp = parseInt ( item . timestamp ) ;
obj . dxcallsign = item . dxcallsign ;
obj . dxgrid = item . dxgrid ;
obj . uuid = item . uuid ;
obj . command = "ping-ack" ;
obj . checksum = "null" ;
obj . msg = "null" ;
obj . status = item . status ;
obj . snr = item . dxsnr + "/" + item . snr ;
obj . type = "ping-ack" ;
obj . filename = "null" ;
obj . filetype = "null" ;
obj . file = "null" ;
add _obj _to _database ( obj ) ;
update _chat _obj _by _uuid ( obj . uuid ) ;
2023-02-11 21:49:07 +00:00
// handle beacon
2023-05-09 08:36:30 +00:00
} else if ( item . beacon == "received" ) {
2023-02-11 21:49:07 +00:00
obj . timestamp = parseInt ( item . timestamp ) ;
obj . dxcallsign = item . dxcallsign ;
obj . dxgrid = item . dxgrid ;
obj . uuid = item . uuid ;
obj . command = "beacon" ;
obj . checksum = "null" ;
obj . msg = "null" ;
obj . status = item . status ;
obj . snr = item . snr ;
obj . type = "beacon" ;
obj . filename = "null" ;
obj . filetype = "null" ;
obj . file = "null" ;
add _obj _to _database ( obj ) ;
update _chat _obj _by _uuid ( obj . uuid ) ;
// handle ARQ transmission
2023-05-09 08:36:30 +00:00
} else if ( item . arq == "transmission" && item . status == "received" ) {
2023-02-11 21:49:07 +00:00
//var encoded_data = atob(item.data);
//var encoded_data = Buffer.from(item.data,'base64').toString('utf-8');
2023-03-03 03:05:45 +00:00
var encoded _data = FD . atob _FD ( item . data ) ;
2023-02-11 21:49:07 +00:00
var splitted _data = encoded _data . split ( split _char ) ;
console . log ( splitted _data ) ;
2023-02-26 15:27:55 +00:00
if ( splitted _data [ 1 ] == "msg" ) {
obj . timestamp = parseInt ( splitted _data [ 4 ] ) ;
obj . dxcallsign = item . dxcallsign ;
obj . dxgrid = item . dxgrid ;
obj . command = splitted _data [ 1 ] ;
obj . checksum = splitted _data [ 2 ] ;
obj . uuid = splitted _data [ 3 ] ;
obj . msg = splitted _data [ 5 ] ;
obj . status = "null" ;
obj . snr = "null" ;
obj . type = "received" ;
obj . filename = splitted _data [ 6 ] ;
obj . filetype = splitted _data [ 7 ] ;
//obj.file = btoa(splitted_data[8]);
2023-03-03 03:05:45 +00:00
obj . file = FD . btoa _FD ( splitted _data [ 8 ] ) ;
2023-05-09 08:36:30 +00:00
} else if ( splitted _data [ 1 ] == "req" && splitted _data [ 2 ] == "0" ) {
2023-02-26 15:27:55 +00:00
obj . uuid = uuidv4 ( ) . toString ( ) ;
obj . timestamp = Math . floor ( Date . now ( ) / 1000 ) ;
obj . dxcallsign = item . dxcallsign ;
obj . command = splitted _data [ 1 ] ;
obj . type = "request" ;
obj . status = "received" ;
obj . snr = "null" ;
2023-03-05 21:16:03 +00:00
obj . msg = "Request for station info" ;
2023-02-26 15:27:55 +00:00
obj . filename = "null" ;
obj . filetype = "null" ;
obj . file = "null" ;
2023-02-28 12:55:54 +00:00
if ( config . enable _request _profile == "True" ) {
sendUserData ( item . dxcallsign ) ;
2023-02-28 12:55:11 +00:00
}
2023-05-09 08:36:30 +00:00
} else if ( splitted _data [ 1 ] == "req" && splitted _data [ 2 ] == "1" ) {
2023-02-28 14:19:41 +00:00
obj . uuid = uuidv4 ( ) . toString ( ) ;
obj . timestamp = Math . floor ( Date . now ( ) / 1000 ) ;
obj . dxcallsign = item . dxcallsign ;
obj . command = splitted _data [ 1 ] ;
obj . type = "request" ;
obj . status = "received" ;
obj . snr = "null" ;
2023-03-05 21:16:03 +00:00
obj . msg = "Request for shared folder list" ;
2023-02-28 14:19:41 +00:00
obj . filename = "null" ;
obj . filetype = "null" ;
obj . file = "null" ;
if ( config . enable _request _shared _folder == "True" ) {
sendSharedFolderList ( item . dxcallsign ) ;
}
2023-05-09 08:36:30 +00:00
} else if (
splitted _data [ 1 ] == "req" &&
splitted _data [ 2 ] . substring ( 0 , 1 ) == "2"
) {
2023-03-05 21:16:03 +00:00
let name = splitted _data [ 2 ] . substring ( 1 ) ;
//console.log("In handle req for shared folder file");
2023-02-28 14:19:41 +00:00
obj . uuid = uuidv4 ( ) . toString ( ) ;
obj . timestamp = Math . floor ( Date . now ( ) / 1000 ) ;
obj . dxcallsign = item . dxcallsign ;
obj . command = splitted _data [ 1 ] ;
obj . type = "request" ;
obj . status = "received" ;
obj . snr = "null" ;
2023-03-05 21:16:03 +00:00
obj . msg = "Request for shared file " + name ;
2023-02-28 14:19:41 +00:00
obj . filename = "null" ;
obj . filetype = "null" ;
obj . file = "null" ;
if ( config . enable _request _shared _folder == "True" ) {
2023-03-05 21:16:43 +00:00
sendSharedFolderFile ( item . dxcallsign , name ) ;
2023-02-28 14:19:41 +00:00
}
2023-05-09 08:36:30 +00:00
} else if ( splitted _data [ 1 ] == "res-0" ) {
2023-02-26 15:27:55 +00:00
obj . uuid = uuidv4 ( ) . toString ( ) ;
obj . timestamp = Math . floor ( Date . now ( ) / 1000 ) ;
obj . dxcallsign = item . dxcallsign ;
obj . command = splitted _data [ 1 ] ;
obj . type = "response" ;
obj . status = "received" ;
obj . snr = "null" ;
2023-03-05 21:16:03 +00:00
obj . msg = "Response for station info" ;
2023-02-26 15:27:55 +00:00
obj . filename = "null" ;
obj . filetype = "null" ;
obj . file = "null" ;
console . log ( splitted _data ) ;
2023-02-26 15:26:24 +00:00
let userData = new Object ( ) ;
userData . user _info _image = splitted _data [ 2 ] ;
2023-02-27 14:18:17 +00:00
userData . user _info _callsign = splitted _data [ 3 ] ;
2023-02-26 15:26:24 +00:00
userData . user _info _gridsquare = splitted _data [ 4 ] ;
userData . user _info _name = splitted _data [ 5 ] ;
userData . user _info _age = splitted _data [ 6 ] ;
userData . user _info _location = splitted _data [ 7 ] ;
userData . user _info _radio = splitted _data [ 8 ] ;
userData . user _info _antenna = splitted _data [ 9 ] ;
userData . user _info _email = splitted _data [ 10 ] ;
userData . user _info _website = splitted _data [ 11 ] ;
userData . user _info _comments = splitted _data [ 12 ] ;
addUserToDatabaseIfNotExists ( userData ) ;
2023-03-19 16:22:55 +00:00
getSetUserInformation ( splitted _data [ 3 ] ) ;
2023-05-09 08:36:30 +00:00
} else if ( splitted _data [ 1 ] == "res-1" ) {
2023-02-28 14:19:41 +00:00
obj . uuid = uuidv4 ( ) . toString ( ) ;
obj . timestamp = Math . floor ( Date . now ( ) / 1000 ) ;
obj . dxcallsign = item . dxcallsign ;
obj . command = splitted _data [ 1 ] ;
obj . type = "response" ;
obj . status = "received" ;
obj . snr = "null" ;
2023-03-05 21:16:03 +00:00
obj . msg = "Response for shared file list" ;
2023-02-28 14:19:41 +00:00
obj . filename = "null" ;
obj . filetype = "null" ;
obj . file = "null" ;
2023-02-28 14:20:17 +00:00
console . log ( splitted _data ) ;
2023-02-28 19:06:39 +00:00
let userData = new Object ( ) ;
2023-03-04 19:20:50 +00:00
userData . user _info _callsign = obj . dxcallsign ;
2023-02-28 19:06:39 +00:00
let filelist = JSON . parse ( splitted _data [ 3 ] ) ;
2023-02-28 14:20:17 +00:00
console . log ( filelist ) ;
2023-02-28 19:07:10 +00:00
userData . user _shared _folder = filelist ;
addFileListToUserDatabaseIfNotExists ( userData ) ;
2023-03-19 15:32:57 +00:00
getSetUserSharedFolder ( obj . dxcallsign ) ;
2023-03-19 15:18:32 +00:00
//getSetUserInformation(selected_callsign);
2023-05-09 08:36:30 +00:00
} else if ( splitted _data [ 1 ] == "res-2" ) {
2023-03-05 21:16:03 +00:00
console . log ( "In received respons-2" ) ;
2023-03-05 21:16:43 +00:00
let sharedFileInfo = splitted _data [ 2 ] . split ( "/" , 2 ) ;
2023-03-05 21:16:03 +00:00
obj . uuid = uuidv4 ( ) . toString ( ) ;
obj . timestamp = Math . floor ( Date . now ( ) / 1000 ) ;
obj . dxcallsign = item . dxcallsign ;
obj . command = splitted _data [ 1 ] ;
obj . type = "received" ;
obj . status = "received" ;
obj . snr = "null" ;
obj . msg = "Response for shared file download" ;
obj . filename = sharedFileInfo [ 0 ] ;
obj . filetype = "application/octet-stream" ;
obj . file = FD . btoa _FD ( sharedFileInfo [ 1 ] ) ;
2023-05-09 08:36:30 +00:00
} else {
console . log ( "no rule matched for handling received data!" ) ;
2023-02-26 14:41:49 +00:00
}
2023-02-11 21:49:07 +00:00
add _obj _to _database ( obj ) ;
update _chat _obj _by _uuid ( obj . uuid ) ;
}
} ) ;
//window.location = window.location;
2022-03-10 20:29:30 +00:00
} ) ;
2022-06-07 09:31:59 +00:00
2022-03-10 20:29:30 +00:00
// Update chat list
2023-02-11 21:49:07 +00:00
update _chat = function ( obj ) {
var dxcallsign = obj . dxcallsign ;
var timestamp = dateFormat . format ( obj . timestamp * 1000 ) ;
2023-02-24 03:42:57 +00:00
//var timestampShort = dateFormatShort.format(obj.timestamp * 1000);
2023-02-11 21:49:07 +00:00
var timestampHours = dateFormatHours . format ( obj . timestamp * 1000 ) ;
var dxgrid = obj . dxgrid ;
2023-05-09 12:45:58 +00:00
// check if obj.attempt exists
2023-05-09 12:49:46 +00:00
if ( typeof obj . attempt == "undefined" ) {
db . upsert ( obj . _id , function ( doc ) {
if ( ! doc . attempt ) {
doc . attempt = 1 ;
}
return doc ;
} ) ;
obj . attempt = 1 ;
}
2023-05-09 12:45:58 +00:00
2023-05-09 08:36:30 +00:00
// define attempts
2023-05-09 08:35:50 +00:00
if ( typeof obj . attempt == "undefined" ) {
2023-05-09 08:36:30 +00:00
var attempt = 1 ;
2023-05-09 08:35:50 +00:00
} else {
2023-05-09 08:36:30 +00:00
var attempt = obj . attempt ;
2023-05-09 08:35:50 +00:00
}
2023-05-09 10:27:51 +00:00
if ( typeof config . max _retry _attempts == "undefined" ) {
var max _retry _attempts = 3 ;
} else {
var max _retry _attempts = parseInt ( config . max _retry _attempts ) ;
}
2023-02-11 21:49:07 +00:00
// define shortmessage
if ( obj . msg == "null" || obj . msg == "NULL" ) {
var shortmsg = obj . type ;
} else {
var shortmsg = obj . msg ;
var maxlength = 30 ;
var shortmsg =
shortmsg . length > maxlength
? shortmsg . substring ( 0 , maxlength - 3 ) + "..."
: shortmsg ;
}
try {
//console.log(Object.keys(obj._attachments)[0].length)
if (
typeof obj . _attachments !== "undefined" &&
Object . keys ( obj . _attachments ) [ 0 ] . length > 0
) {
//var filename = obj._attachments;
var filename = Object . keys ( obj . _attachments ) [ 0 ] ;
var filetype = filename . split ( "." ) [ 1 ] ;
var filesize = obj . _attachments [ filename ] [ "length" ] + " Bytes" ;
if ( filesize == "undefined Bytes" ) {
// get filesize of new submitted data
// not that nice....
// we really should avoid converting back from base64 for performance reasons...
//var filesize = Math.ceil(atob(obj._attachments[filename]["data"]).length) + "Bytes";
var filesize =
2023-03-03 03:05:45 +00:00
Math . ceil ( FD . atob _FD ( obj . _attachments [ filename ] [ "data" ] ) . length ) +
2023-02-11 21:49:07 +00:00
" Bytes" ;
}
// check if image, then display it
if ( filetype == "image/png" || filetype == "png" ) {
var fileheader = `
2022-11-11 14:10:31 +00:00
< div class = "card-header border-0 bg-transparent text-end p-0 mb-0 hover-overlay" >
2023-03-03 03:05:45 +00:00
< img class = "w-100 rounded-2" src = " data : image / png ; base64 , $ { FD . atob (
2023-02-24 03:44:24 +00:00
obj . _attachments [ filename ] [ "data" ]
) } " >
2023-03-16 07:28:29 +00:00
< p class = "text-right mb-0 p-1" style = "text-align: right; font-size : 1rem" >
2022-11-11 14:10:31 +00:00
< span class = "p-1" style = "text-align: right; font-size : 0.8rem" > $ { filename } < / s p a n >
< span class = "p-1" style = "text-align: right; font-size : 0.8rem" > $ { filesize } < / s p a n >
< i class = "bi bi-filetype-${filetype}" style = "font-size: 2rem;" > < / i >
< / p >
< / d i v >
< hr class = "m-0 p-0" >
` ;
2023-02-11 21:49:07 +00:00
} else {
var fileheader = `
2022-04-10 09:37:09 +00:00
< div class = "card-header border-0 bg-transparent text-end p-0 mb-0 hover-overlay" >
2023-03-16 07:28:29 +00:00
< p class = "text-right mb-0 p-1" style = "text-align: right; font-size : 1rem" >
2022-04-10 09:37:09 +00:00
< span class = "p-1" style = "text-align: right; font-size : 0.8rem" > $ { filename } < / s p a n >
< span class = "p-1" style = "text-align: right; font-size : 0.8rem" > $ { filesize } < / s p a n >
2022-11-11 14:10:31 +00:00
< i class = "bi bi-filetype-${filetype}" style = "font-size: 2rem;" > < / i >
2022-03-24 19:49:13 +00:00
< / p >
< / d i v >
2022-04-10 09:37:09 +00:00
< hr class = "m-0 p-0" >
` ;
2023-02-11 21:49:07 +00:00
}
2022-11-11 14:10:31 +00:00
2023-02-11 21:49:07 +00:00
var controlarea _transmit = `
2022-04-10 09:37:09 +00:00
< div class = "ms-auto" id = "msg-${obj._id}-control-area" >
2023-03-19 00:24:39 +00:00
< button class = "btn bg-transparent p-1 m-1" > < i class = "bi bi-arrow-repeat link-secondary" id = "retransmit-msg-${obj._id}" style = "font-size: 1.2rem;" > < / i > < / b u t t o n >
< button class = "btn bg-transparent p-1 m-1" > < i class = "bi bi-download link-secondary" id = "save-file-msg-${obj._id}" style = "font-size: 1.2rem;" > < / i > < / b u t t o n >
< button class = "btn bg-transparent p-1 m-1" > < i class = "bi bi-trash link-secondary" id = "del-msg-${obj._id}" style = "font-size: 1.2rem;" > < / i > < / b u t t o n >
2022-04-10 09:37:09 +00:00
< / d i v >
2022-03-24 19:49:13 +00:00
` ;
2022-04-10 09:37:09 +00:00
2023-02-11 21:49:07 +00:00
var controlarea _receive = `
2023-02-18 18:55:13 +00:00
2022-04-10 09:37:09 +00:00
< div class = "me-auto" id = "msg-${obj._id}-control-area" >
2023-03-19 00:24:39 +00:00
< button class = "btn bg-transparent p-1 m-1" > < i class = "bi bi-download link-secondary" id = "save-file-msg-${obj._id}" style = "font-size: 1.2rem;" > < / i > < / b u t t o n >
< button class = "btn bg-transparent p-1 m-1" > < i class = "bi bi-trash link-secondary" id = "del-msg-${obj._id}" style = "font-size: 1.2rem;" > < / i > < / b u t t o n >
2022-04-10 09:37:09 +00:00
< / d i v >
2023-02-11 21:49:07 +00:00
` ;
} else {
var filename = "" ;
var fileheader = "" ;
var filetype = "text/plain" ;
var controlarea _transmit = `
2022-04-10 09:37:09 +00:00
< div class = "ms-auto" id = "msg-${obj._id}-control-area" >
2023-03-19 00:24:39 +00:00
< button class = "btn bg-transparent p-1 m-1" > < i class = "bi bi-arrow-repeat link-secondary" id = "retransmit-msg-${obj._id}" style = "font-size: 1.2rem;" > < / i > < / b u t t o n >
< button class = "btn bg-transparent p-1 m-1" > < i class = "bi bi-trash link-secondary" id = "del-msg-${obj._id}" style = "font-size: 1.2rem;" > < / i > < / b u t t o n >
2022-04-10 09:37:09 +00:00
< / d i v >
` ;
2023-02-19 02:02:13 +00:00
var controlarea _receive = `
< div class = "float-start" id = "msg-${obj._id}-control-area" >
2023-03-19 00:24:39 +00:00
< button class = "btn bg-transparent p-1 m-1" > < i class = "bi bi-trash link-secondary" id = "del-msg-${obj._id}" style = "font-size: 1.2rem;" > < / i > < / b u t t o n >
2023-02-19 02:02:13 +00:00
< / d i v >
` ;
2023-02-11 21:49:07 +00:00
}
} catch ( err ) {
console . log ( "error with database parsing..." ) ;
console . log ( err ) ;
}
// CALLSIGN LIST
if ( ! document . getElementById ( "chat-" + dxcallsign + "-list" ) ) {
// increment callsign counter
callsign _counter ++ ;
2023-02-25 01:00:34 +00:00
dxcallsigns . add ( dxcallsign ) ;
2023-02-25 05:29:09 +00:00
if (
( callsign _counter == 1 && selected _callsign == "" ) ||
selected _callsign == dxcallsign
) {
2023-02-11 21:49:07 +00:00
var callsign _selected = "active show" ;
//document.getElementById('chatModuleDxCall').value = dxcallsign;
selected _callsign = dxcallsign ;
2022-03-27 19:04:04 +00:00
}
2023-02-11 21:49:07 +00:00
2023-02-27 17:32:30 +00:00
getSetUserInformation ( dxcallsign ) ;
2023-03-22 21:32:37 +00:00
getSetUserSharedFolder ( dxcallsign ) ;
2023-02-11 21:49:07 +00:00
var new _callsign = `
2022-03-29 15:42:54 +00:00
< a class = "list-group-item list-group-item-action rounded-4 rounded-top rounded-bottom border-1 mb-2 ${callsign_selected}" id = "chat-${dxcallsign}-list" data - bs - toggle = "list" href = "#chat-${dxcallsign}" role = "tab" aria - controls = "chat-${dxcallsign}" >
2023-02-18 18:55:13 +00:00
2022-03-10 20:29:30 +00:00
< div class = "d-flex w-100 justify-content-between" >
2022-04-02 12:54:43 +00:00
< div class = "rounded-circle p-0" >
2023-02-28 08:07:38 +00:00
< img id = "user-image-${dxcallsign}" class = "p-1 rounded-circle" src = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0iY3VycmVudENvbG9yIiBjbGFzcz0iYmkgYmktcGVyc29uLWNpcmNsZSIgdmlld0JveD0iMCAwIDE2IDE2Ij4KICA8cGF0aCBkPSJNMTEgNmEzIDMgMCAxIDEtNiAwIDMgMyAwIDAgMSA2IDB6Ii8+CiAgPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMCA4YTggOCAwIDEgMSAxNiAwQTggOCAwIDAgMSAwIDh6bTgtN2E3IDcgMCAwIDAtNS40NjggMTEuMzdDMy4yNDIgMTEuMjI2IDQuODA1IDEwIDggMTBzNC43NTcgMS4yMjUgNS40NjggMi4zN0E3IDcgMCAwIDAgOCAxeiIvPgo8L3N2Zz4=" > < / i m g >
2023-02-27 17:32:01 +00:00
<!-- < i class = "bi bi-person-circle p-1" style = "font-size:2rem;" > < / i > - - >
2022-04-02 12:54:43 +00:00
< / d i v >
2022-04-02 16:40:12 +00:00
2023-02-28 08:07:38 +00:00
< span style = "font-size:1.2rem;" > < strong > $ { dxcallsign } < / s t r o n g > < / s p a n >
2023-02-18 18:55:13 +00:00
< span class = "badge bg-secondary text-white p-1 h-100" id = "chat-${dxcallsign}-list-dxgrid" > < small > $ { dxgrid } < / s m a l l > < / s p a n >
2022-04-02 16:40:12 +00:00
< span style = "font-size:0.8rem;" id = "chat-${dxcallsign}-list-time" > $ { timestampHours } < / s p a n >
< span class = "position-absolute m-2 bottom-0 end-0" style = "font-size:0.8rem;" id = "chat-${dxcallsign}-list-shortmsg" > $ { shortmsg } < / s p a n >
2022-03-10 20:29:30 +00:00
< / d i v >
2022-04-02 16:40:12 +00:00
2022-03-10 20:29:30 +00:00
< / a >
2021-11-19 17:49:36 +00:00
2022-03-10 20:29:30 +00:00
` ;
2023-02-27 17:32:01 +00:00
2023-02-11 21:49:07 +00:00
document
. getElementById ( "list-tab" )
. insertAdjacentHTML ( "beforeend" , new _callsign ) ;
var message _area = `
2023-02-18 18:55:13 +00:00
< div class = "tab-pane fade ${callsign_selected}" id = "chat-${dxcallsign}" role = "tabpanel" aria - labelledby = "chat-${dxcallsign}-list" > < / d i v >
2022-03-10 20:29:30 +00:00
` ;
2023-02-11 21:49:07 +00:00
document
. getElementById ( "nav-tabContent" )
. insertAdjacentHTML ( "beforeend" , message _area ) ;
2023-02-26 11:15:29 +00:00
2023-02-28 08:08:09 +00:00
// finally get and set user information to first selected item
getSetUserInformation ( selected _callsign ) ;
2023-03-22 21:32:37 +00:00
getSetUserSharedFolder ( selected _callsign ) ;
2023-02-28 08:07:38 +00:00
2023-02-11 21:49:07 +00:00
// create eventlistener for listening on clicking on a callsign
document
. getElementById ( "chat-" + dxcallsign + "-list" )
. addEventListener ( "click" , function ( ) {
//document.getElementById('chatModuleDxCall').value = dxcallsign;
selected _callsign = dxcallsign ;
setTimeout ( scrollMessagesToBottom , 200 ) ;
2023-02-26 11:15:29 +00:00
//get user information
getSetUserInformation ( selected _callsign ) ;
2023-03-22 21:32:37 +00:00
getSetUserSharedFolder ( selected _callsign ) ;
2023-02-11 21:49:07 +00:00
} ) ;
2022-09-05 12:03:10 +00:00
2022-04-02 16:40:12 +00:00
// if callsign entry already exists - update
2023-02-11 21:49:07 +00:00
} else {
// gridsquare - update only on receive
if ( obj . type !== "transmit" ) {
document . getElementById ( "chat-" + dxcallsign + "-list-dxgrid" ) . innerHTML =
dxgrid ;
2022-03-10 20:29:30 +00:00
}
2023-02-11 21:49:07 +00:00
// time
document . getElementById ( "chat-" + dxcallsign + "-list-time" ) . innerHTML =
timestampHours ;
// short message
document . getElementById ( "chat-" + dxcallsign + "-list-shortmsg" ) . innerHTML =
shortmsg ;
}
// APPEND MESSAGES TO CALLSIGN
if ( ! document . getElementById ( "msg-" + obj . _id ) ) {
if ( obj . type == "ping" ) {
2023-05-09 10:27:51 +00:00
// check for messages which failed and try to transmit them
2023-05-09 10:29:28 +00:00
if ( config . enable _auto _retry . toUpperCase ( ) == "TRUE" ) {
checkForWaitingMessages ( obj . dxcallsign ) ;
}
2023-05-09 10:27:51 +00:00
2023-02-11 21:49:07 +00:00
var new _message = `
2023-02-18 18:55:13 +00:00
< div class = "m-auto mt-1 p-0 w-50 rounded bg-secondary bg-gradient" id = "msg-${obj._id}" >
2022-04-10 09:37:09 +00:00
< p class = "text-small text-white mb-0 text-break" style = "font-size: 0.7rem;" > < i class = "m-3 bi bi-arrow-left-right" > < / i > s n r : $ { o b j . s n r } - $ { t i m e s t a m p } < / p >
2023-02-19 05:02:06 +00:00
< / d i v >
` ;
}
if ( obj . type == "ping-ack" ) {
var new _message = `
< div class = "m-auto mt-1 p-0 w-50 rounded bg-secondary bg-gradient" id = "msg-${obj._id}" >
< p class = "text-small text-white mb-0 text-break" style = "font-size: 0.7rem;" > < i class = "m-3 bi bi-check-lg" > < / i > P i n g a c k d x / m i n e s n r : $ { o b j . s n r } - $ { t i m e s t a m p } < / p >
2022-03-24 19:49:13 +00:00
< / d i v >
` ;
2023-02-11 21:49:07 +00:00
}
if ( obj . type == "beacon" ) {
2023-05-09 10:29:28 +00:00
// check for messages which failed and try to transmit them
if ( config . enable _auto _retry . toUpperCase ( ) == "TRUE" ) {
checkForWaitingMessages ( obj . dxcallsign ) ;
}
2023-02-11 21:49:07 +00:00
var new _message = `
2023-02-18 18:55:13 +00:00
< div class = "p-0 rounded m-auto mt-1 w-50 bg-info bg-gradient" id = "msg-${obj._id}" >
2022-04-10 09:37:09 +00:00
< p class = "text-small text-white text-break" style = "font-size: 0.7rem;" > < i class = "m-3 bi bi-broadcast" > < / i > s n r : $ { o b j . s n r } - $ { t i m e s t a m p } < / p >
2022-03-24 19:49:13 +00:00
< / d i v >
` ;
2023-02-11 21:49:07 +00:00
}
2023-02-26 14:41:49 +00:00
if ( obj . type == "request" ) {
var new _message = `
< div class = "p-0 rounded m-auto mt-1 w-50 bg-warning bg-gradient" id = "msg-${obj._id}" >
2023-03-05 21:16:03 +00:00
< p class = "text-small text-white text-break" style = "font-size: 0.7rem;" > < i class = "m-3 bi bi-info" > < / i > $ { o b j . m s g } - $ { t i m e s t a m p } < / p >
2023-02-26 14:41:49 +00:00
< / d i v >
` ;
}
2023-02-26 15:26:24 +00:00
if ( obj . type == "response" ) {
var new _message = `
< div class = "p-0 rounded m-auto mt-1 w-50 bg-warning bg-gradient" id = "msg-${obj._id}" >
< p class = "text-small text-white text-break" style = "font-size: 0.7rem;" > < i class = "m-3 bi bi-info" > < / i > R e s p o n s e - $ { t i m e s t a m p } < / p >
< / d i v >
` ;
}
2023-02-11 21:49:07 +00:00
if ( obj . type == "newchat" ) {
var new _message = `
2023-02-18 18:55:13 +00:00
< div class = "p-0 rounded m-auto mt-1 w-50 bg-light bg-gradient" id = "msg-${obj._id}" >
2022-04-10 17:20:58 +00:00
< p class = "text-small text-dark text-break" style = "font-size: 0.7rem;" > < i class = "m-3 bi bi-file-earmark-plus" > < / i > n e w c h a t o p e n e d - $ { t i m e s t a m p } < / p >
2022-04-02 12:54:43 +00:00
< / d i v >
` ;
2023-02-11 21:49:07 +00:00
}
// CHECK FOR NEW LINE AND REPLACE WITH <br>
var message _html = obj . msg . replaceAll ( /\n/g , "<br>" ) ;
if ( obj . type == "received" ) {
var new _message = `
2022-04-10 09:37:09 +00:00
< div class = "d-flex align-items-center" style = "margin-left: auto;" > <!-- max - width : 75 % ; -- >
2023-02-18 18:55:13 +00:00
< div class = "mt-3 rounded-3 mb-0" style = "max-width: 75%;" id = "msg-${obj._id}" >
2022-03-24 19:49:13 +00:00
<!-- < p class = "font-monospace text-small mb-0 text-muted text-break" > $ { timestamp } < / p > - - >
2022-03-12 14:06:49 +00:00
< div class = "card border-light bg-light" id = "msg-${obj._id}" >
2022-03-24 19:49:13 +00:00
$ { fileheader }
2023-02-18 18:55:13 +00:00
2022-11-10 12:02:17 +00:00
< div class = "card-body rounded-3 p-0" >
2022-04-03 13:26:24 +00:00
< p class = "card-text p-2 mb-0 text-break text-wrap" > $ { message _html } < / p >
2022-03-24 19:49:13 +00:00
< p class = "text-right mb-0 p-1 text-white" style = "text-align: left; font-size : 0.9rem" >
2023-02-18 18:55:13 +00:00
< span class = "badge bg-light text-muted" > $ { timestamp } < / s p a n >
2022-03-24 19:49:13 +00:00
< / p >
2022-03-12 14:06:49 +00:00
< / d i v >
< / d i v >
2022-04-10 09:37:09 +00:00
< / d i v >
2023-02-19 13:36:29 +00:00
$ { controlarea _receive }
2022-03-10 20:29:30 +00:00
< / d i v >
` ;
2023-02-11 21:49:07 +00:00
}
if ( obj . type == "transmit" ) {
//console.log('msg-' + obj._id + '-status')
if ( obj . status == "failed" ) {
var progressbar _bg = "bg-danger" ;
2023-03-22 21:49:30 +00:00
var percent _value = "TRANSMISSION FAILED" ;
} else if ( obj . status == "transmitted" ) {
var progressbar _bg = "bg-success" ;
var percent _value = "TRANSMITTED" ;
2023-02-11 21:49:07 +00:00
} else {
var progressbar _bg = "bg-primary" ;
2023-03-22 21:45:57 +00:00
var percent _value = obj . percent ;
2023-02-11 21:49:07 +00:00
}
//Sneak in low graphics mode if so enabled for progress bars
if ( config . high _graphics . toString ( ) . toUpperCase ( ) != "TRUE" ) {
progressbar _bg += " disable-effects" ;
//console.log("Low graphics enabled for chat module");
}
2023-02-18 18:55:13 +00:00
2023-05-09 08:35:50 +00:00
var new _message = `
< div class = "d-flex align-items-center" >
2022-04-10 09:37:09 +00:00
$ { controlarea _transmit }
2023-05-09 08:35:50 +00:00
< div class = "rounded-3 mt-3 mb-0 me-2" style = "max-width: 75%;" >
< div class = "card border-primary bg-primary" id = "msg-${obj._id}" >
2022-03-24 19:49:13 +00:00
$ { fileheader }
2023-05-09 08:35:50 +00:00
< div class = "card-body rounded-3 p-0 text-right bg-primary" >
2022-04-10 09:37:09 +00:00
< p class = "card-text p-1 mb-0 text-white text-break text-wrap" > $ { message _html } < / p >
2022-03-24 19:49:13 +00:00
< p class = "text-right mb-0 p-1 text-white" style = "text-align: right; font-size : 0.9rem" >
2022-04-07 09:19:29 +00:00
< span class = "text-light" style = "font-size: 0.7rem;" > $ { timestamp } - < / s p a n >
2023-05-09 10:29:28 +00:00
< span class = "text-white" id = " msg - $ {
obj . _id
} - status " style=" font - size : 0.8 rem ; " > $ { get _icon _for _state (
obj . status
) } < / s p a n >
2022-03-24 19:49:13 +00:00
< / p >
2023-05-09 10:29:28 +00:00
< span id = " msg - $ {
obj . _id
} - attempts - badge " class=" position - absolute top - 0 start - 100 translate - middle badge rounded - 1 bg - primary border border - white " >
2023-05-09 08:35:50 +00:00
2023-05-09 10:29:28 +00:00
< span id = " msg - $ {
obj . _id
} - attempts " class=" " > $ { attempt } / $ { max _retry _attempts } < / s p a n >
2023-05-09 08:35:50 +00:00
< span class = "visually-hidden" > retries < / s p a n >
< / s p a n >
< div class = "progress p-0 m-0 rounded-0 rounded-bottom bg-secondary" style = "height: 10px;" >
2023-05-09 08:36:30 +00:00
< div class = "progress-bar progress-bar-striped ${progressbar_bg} p-0 m-0 rounded-0 force-gpu" id = " msg - $ {
obj . _id
} - progress " role=" progressbar " style=" width : $ {
obj . percent
} % ; " aria-valuenow=" $ {
obj . percent
} " aria-valuemin=" 0 " aria-valuemax=" 100 " > < / d i v >
< p class = "justify-content-center d-flex position-absolute m-0 p-0 w-100 text-white" style = "font-size: xx-small" id = " msg - $ {
obj . _id
} - progress - information " > $ { percent _value } % - $ {
obj . bytesperminute
} Bpm < / p >
2023-05-09 08:35:50 +00:00
< / d i v >
2022-03-12 14:06:49 +00:00
< / d i v >
2022-04-10 09:37:09 +00:00
< / d i v >
2023-05-09 08:35:50 +00:00
< / d i v >
< / d i v >
` ;
2023-02-11 21:49:07 +00:00
}
// CHECK CHECK CHECK --> This could be done better
var id = "chat-" + obj . dxcallsign ;
document . getElementById ( id ) . insertAdjacentHTML ( "beforeend" , new _message ) ;
2022-04-07 09:19:29 +00:00
2022-06-09 12:11:39 +00:00
/* UPDATE EXISTING ELEMENTS */
2023-02-11 21:49:07 +00:00
} else if ( document . getElementById ( "msg-" + obj . _id ) ) {
console . log ( "element already exists......" ) ;
console . log ( obj ) ;
console . log (
document
. getElementById ( "msg-" + obj . _id + "-progress" )
. getAttribute ( "aria-valuenow" )
) ;
document . getElementById ( "msg-" + obj . _id + "-status" ) . innerHTML =
get _icon _for _state ( obj . status ) ;
document
. getElementById ( "msg-" + obj . _id + "-progress" )
. setAttribute ( "aria-valuenow" , obj . percent ) ;
document
. getElementById ( "msg-" + obj . _id + "-progress" )
. setAttribute ( "style" , "width:" + obj . percent + "%;" ) ;
document . getElementById (
"msg-" + obj . _id + "-progress-information"
) . innerHTML = obj . percent + "% - " + obj . bytesperminute + " Bpm" ;
2023-05-09 08:36:30 +00:00
document . getElementById ( "msg-" + obj . _id + "-attempts" ) . innerHTML =
2023-05-09 10:27:51 +00:00
obj . attempt + "/" + max _retry _attempts ;
2023-05-09 08:35:50 +00:00
2023-03-23 12:06:49 +00:00
if ( obj . status == "transmitted" ) {
2023-02-11 21:49:07 +00:00
//document.getElementById('msg-' + obj._id + '-progress').classList.remove("progress-bar-striped");
document
. getElementById ( "msg-" + obj . _id + "-progress" )
. classList . remove ( "progress-bar-animated" ) ;
document
. getElementById ( "msg-" + obj . _id + "-progress" )
. classList . remove ( "bg-danger" ) ;
document
. getElementById ( "msg-" + obj . _id + "-progress" )
2023-03-23 12:06:49 +00:00
. classList . add ( "bg-success" ) ;
2023-02-11 21:49:07 +00:00
document . getElementById ( "msg-" + obj . _id + "-progress" ) . innerHTML = "" ;
2023-03-23 12:10:51 +00:00
document . getElementById (
"msg-" + obj . _id + "-progress-information"
) . innerHTML = "TRANSMITTED - " + obj . bytesperminute + " Bpm" ;
2023-02-11 21:49:07 +00:00
} else {
document
. getElementById ( "msg-" + obj . _id + "-progress" )
. classList . add ( "progress-bar-striped" ) ;
document
. getElementById ( "msg-" + obj . _id + "-progress" )
. classList . add ( "progress-bar-animated" ) ;
2022-03-24 19:49:13 +00:00
}
2023-02-11 21:49:07 +00:00
if ( obj . status == "failed" ) {
//document.getElementById('msg-' + obj._id + '-progress').classList.remove("progress-bar-striped");
document
. getElementById ( "msg-" + obj . _id + "-progress" )
. classList . remove ( "progress-bar-animated" ) ;
document
. getElementById ( "msg-" + obj . _id + "-progress" )
. classList . remove ( "bg-primary" ) ;
document
. getElementById ( "msg-" + obj . _id + "-progress" )
. classList . add ( "bg-danger" ) ;
2023-03-23 12:06:49 +00:00
2023-03-23 12:10:51 +00:00
document . getElementById (
"msg-" + obj . _id + "-progress-information"
) . innerHTML = "TRANSMISSION FAILED - " + obj . bytesperminute + " Bpm" ;
2022-03-24 19:49:13 +00:00
}
2023-02-11 21:49:07 +00:00
//document.getElementById(id).className = message_class;
}
2023-02-20 17:55:21 +00:00
//Delete message event listener
if (
document . getElementById ( "del-msg-" + obj . _id ) &&
! document
. getElementById ( "del-msg-" + obj . _id )
. hasAttribute ( "listenerOnClick" )
) {
// set Attribute to determine if we already created an EventListener for this element
document
. getElementById ( "del-msg-" + obj . _id )
. setAttribute ( "listenerOnClick" , "true" ) ;
document
. getElementById ( "del-msg-" + obj . _id )
. addEventListener ( "click" , ( ) => {
db . get ( obj . _id , {
attachments : true ,
2023-02-19 02:02:13 +00:00
} )
2023-02-20 17:55:21 +00:00
. then ( function ( doc ) {
db . remove ( doc . _id , doc . _rev , function ( err ) {
if ( err ) console . log ( "Error removing item " + err ) ;
} ) ;
} )
. catch ( function ( err ) {
console . log ( err ) ;
} ) ;
2023-02-19 13:36:29 +00:00
2023-02-20 17:55:21 +00:00
document . getElementById ( "msg-" + obj . _id ) . remove ( ) ;
document . getElementById ( "msg-" + obj . _id + "-control-area" ) . remove ( ) ;
console . log ( "Removed message " + obj . _id . toString ( ) ) ;
2023-03-22 22:03:31 +00:00
// stop transmission if deleted message is still in progress
2023-03-22 22:03:52 +00:00
if ( obj . status == "transmitting" ) {
let Data = {
command : "stop_transmission" ,
} ;
ipcRenderer . send ( "run-tnc-command" , Data ) ;
2023-03-22 22:03:31 +00:00
}
2023-02-20 17:55:21 +00:00
} ) ;
//scrollMessagesToBottom();
}
2023-02-19 02:02:13 +00:00
2023-02-11 21:49:07 +00:00
// CREATE SAVE TO FOLDER EVENT LISTENER
if (
document . getElementById ( "save-file-msg-" + obj . _id ) &&
! document
. getElementById ( "save-file-msg-" + obj . _id )
. hasAttribute ( "listenerOnClick" )
) {
// set Attribute to determine if we already created an EventListener for this element
document
. getElementById ( "save-file-msg-" + obj . _id )
. setAttribute ( "listenerOnClick" , "true" ) ;
document
. getElementById ( "save-file-msg-" + obj . _id )
. addEventListener ( "click" , ( ) => {
saveFileToFolder ( obj . _id ) ;
} ) ;
}
// CREATE RESEND MSG EVENT LISTENER
// check if element exists and if we already created NOT created an event listener
if (
document . getElementById ( "retransmit-msg-" + obj . _id ) &&
! document
. getElementById ( "retransmit-msg-" + obj . _id )
. hasAttribute ( "listenerOnClick" )
) {
// set Attribute to determine if we already created an EventListener for this element
document
. getElementById ( "retransmit-msg-" + obj . _id )
. setAttribute ( "listenerOnClick" , "true" ) ;
document
. getElementById ( "retransmit-msg-" + obj . _id )
. addEventListener ( "click" , ( ) => {
2023-05-09 08:36:30 +00:00
// increment attempt
db . upsert ( obj . _id , function ( doc ) {
2023-05-09 08:35:50 +00:00
if ( ! doc . attempt ) {
doc . attempt = 1 ;
}
doc . attempt ++ ;
return doc ;
2023-05-09 08:36:30 +00:00
} )
. then ( function ( res ) {
// success, res is {rev: '1-xxx', updated: true, id: 'myDocId'}
console . log ( res ) ;
update _chat _obj _by _uuid ( obj . uuid ) ;
} )
. catch ( function ( err ) {
// error
console . log ( err ) ;
} ) ;
2023-05-09 08:35:50 +00:00
2023-02-11 21:49:07 +00:00
db . get ( obj . _id , {
attachments : true ,
} )
. then ( function ( doc ) {
// handle doc
console . log ( doc ) ;
var filename = Object . keys ( obj . _attachments ) [ 0 ] ;
var filetype = filename . content _type ;
console . log ( filename ) ;
console . log ( filetype ) ;
var file = obj . _attachments [ filename ] . data ;
console . log ( file ) ;
console . log ( Object . keys ( obj . _attachments ) [ 0 ] . data ) ;
//var file = atob(obj._attachments[filename]["data"])
db . getAttachment ( obj . _id , filename ) . then ( function ( data ) {
console . log ( data ) ;
//Rewrote this part to use buffers to ensure encoding is corect -- n1qm
2023-03-03 03:05:45 +00:00
var binaryString = FD . atob _FD ( data ) ;
2023-02-11 21:49:07 +00:00
console . log ( binaryString ) ;
var data _with _attachment =
doc . timestamp +
split _char +
doc . msg +
split _char +
filename +
split _char +
filetype +
split _char +
binaryString ;
let Data = {
2023-02-26 15:26:24 +00:00
command : "msg" ,
2023-02-11 21:49:07 +00:00
dxcallsign : doc . dxcallsign ,
mode : 255 ,
2023-04-25 13:46:17 +00:00
frames : 5 ,
2023-02-11 21:49:07 +00:00
data : data _with _attachment ,
checksum : doc . checksum ,
uuid : doc . uuid ,
} ;
console . log ( Data ) ;
ipcRenderer . send ( "run-tnc-command" , Data ) ;
} ) ;
/ *
2022-12-08 19:21:44 +00:00
// convert blob data to binary string
blobUtil . blobToBinaryString ( data ) . then ( function ( binaryString ) {
2022-12-09 09:22:03 +00:00
console . log ( binaryString )
2022-12-08 19:21:44 +00:00
} ) . catch ( function ( err ) {
// error
console . log ( err ) ;
2022-12-09 09:22:03 +00:00
binaryString = blobUtil . arrayBufferToBinaryString ( data ) ;
2023-02-18 18:55:13 +00:00
2022-12-09 10:24:39 +00:00
} ) . then ( function ( ) {
2022-12-08 19:21:44 +00:00
2022-12-09 09:22:03 +00:00
console . log ( binaryString )
2022-12-27 08:53:21 +00:00
console . log ( binaryString . length )
2022-12-28 11:27:09 +00:00
var data _with _attachment = doc . timestamp + split _char + utf8 . encode ( doc . msg ) + split _char + filename + split _char + filetype + split _char + binaryString ;
2022-12-09 09:22:03 +00:00
let Data = {
2023-02-26 15:26:24 +00:00
command : "msg" ,
2022-12-09 09:22:03 +00:00
dxcallsign : doc . dxcallsign ,
mode : 255 ,
frames : 1 ,
data : data _with _attachment ,
checksum : doc . checksum ,
uuid : doc . uuid
} ;
console . log ( Data )
ipcRenderer . send ( 'run-tnc-command' , Data ) ;
2022-04-06 08:15:14 +00:00
2022-12-09 09:22:03 +00:00
} ) ;
2022-03-27 19:04:04 +00:00
} ) ;
2023-02-04 17:12:15 +00:00
* /
2023-02-11 21:49:07 +00:00
} )
. catch ( function ( err ) {
console . log ( err ) ;
} ) ;
} ) ;
}
//window.location = window.location
2022-06-07 09:31:59 +00:00
2023-02-11 21:49:07 +00:00
// scroll to bottom on new message
scrollMessagesToBottom ( ) ;
} ;
2022-03-14 19:21:15 +00:00
2022-03-27 19:04:04 +00:00
function saveFileToFolder ( id ) {
2023-02-11 21:49:07 +00:00
db . get ( id , {
attachments : true ,
} )
. then ( function ( obj ) {
console . log ( obj ) ;
console . log ( Object . keys ( obj . _attachments ) [ 0 ] . content _type ) ;
var filename = Object . keys ( obj . _attachments ) [ 0 ] ;
var filetype = filename . content _type ;
var file = filename . data ;
console . log ( file ) ;
console . log ( filename . data ) ;
db . getAttachment ( id , filename )
. then ( function ( data ) {
// handle result
console . log ( data . length ) ;
//data = new Blob([data.buffer], { type: 'image/png' } /* (1) */)
console . log ( data ) ;
// we need to encode data because of error "an object could not be cloned"
let Data = {
file : data ,
filename : filename ,
filetype : filetype ,
} ;
console . log ( Data ) ;
ipcRenderer . send ( "save-file-to-folder" , Data ) ;
} )
. catch ( function ( err ) {
console . log ( err ) ;
return false ;
2022-03-29 20:24:35 +00:00
} ) ;
2023-02-11 21:49:07 +00:00
} )
. catch ( function ( err ) {
console . log ( err ) ;
2022-03-24 19:49:13 +00:00
} ) ;
}
2022-04-07 09:19:29 +00:00
2022-11-11 14:39:24 +00:00
// function for setting an ICON to the corresponding state
2022-04-07 09:19:29 +00:00
function get _icon _for _state ( state ) {
2023-02-11 21:49:07 +00:00
if ( state == "transmit" ) {
var status _icon = '<i class="bi bi-check" style="font-size:1rem;"></i>' ;
} else if ( state == "transmitting" ) {
//var status_icon = '<i class="bi bi-arrow-left-right" style="font-size:0.8rem;"></i>';
var status _icon = `
2022-06-09 12:11:39 +00:00
< i class = "spinner-border ms-auto" style = "width: 0.8rem; height: 0.8rem;" role = "status" aria - hidden = "true" > < / i >
` ;
2023-02-11 21:49:07 +00:00
} else if ( state == "failed" ) {
var status _icon =
'<i class="bi bi-exclamation-circle" style="font-size:1rem;"></i>' ;
} else if ( state == "transmitted" ) {
var status _icon = '<i class="bi bi-check-all" style="font-size:1rem;"></i>' ;
} else {
var status _icon = '<i class="bi bi-question" style="font-size:1rem;"></i>' ;
}
return status _icon ;
2022-06-15 12:34:17 +00:00
}
2022-06-07 09:31:59 +00:00
2023-02-11 21:49:07 +00:00
update _chat _obj _by _uuid = function ( uuid ) {
db . get ( uuid , {
attachments : true ,
} )
. then ( function ( doc ) {
update _chat ( doc ) ;
//return doc
} )
. catch ( function ( err ) {
console . log ( err ) ;
2022-06-07 09:31:59 +00:00
} ) ;
2023-02-11 21:49:07 +00:00
} ;
2022-06-07 09:31:59 +00:00
2023-02-11 21:49:07 +00:00
add _obj _to _database = function ( obj ) {
2023-02-26 15:27:55 +00:00
console . log ( obj ) ;
2023-02-11 21:49:07 +00:00
db . put ( {
_id : obj . uuid ,
timestamp : parseInt ( obj . timestamp ) ,
uuid : obj . uuid ,
dxcallsign : obj . dxcallsign ,
dxgrid : obj . dxgrid ,
msg : obj . msg ,
checksum : obj . checksum ,
type : obj . type ,
command : obj . command ,
status : obj . status ,
snr : obj . snr ,
2023-05-09 08:35:50 +00:00
attempt : obj . attempt ,
2023-02-11 21:49:07 +00:00
_attachments : {
[ obj . filename ] : {
content _type : obj . filetype ,
data : obj . file ,
} ,
} ,
} )
. then ( function ( response ) {
console . log ( "new database entry" ) ;
console . log ( response ) ;
} )
. catch ( function ( err ) {
2023-05-09 08:35:50 +00:00
console . log ( "already exists" ) ;
2023-02-11 21:49:07 +00:00
console . log ( err ) ;
2022-06-07 09:31:59 +00:00
} ) ;
2023-02-11 21:49:07 +00:00
} ;
2022-09-05 12:03:10 +00:00
2023-02-18 18:55:13 +00:00
/* users database functions */
addUserToDatabaseIfNotExists = function ( obj ) {
/ *
"user_info_callsign" ,
"user_info_gridsquare" ,
"user_info_name" ,
"user_info_age" ,
"user_info_location" ,
"user_info_radio" ,
"user_info_antenna" ,
"user_info_email" ,
"user_info_website" ,
"user_info_comments" ,
* /
2023-02-20 17:55:21 +00:00
console . log ( obj ) ;
2023-02-18 18:55:13 +00:00
users
. find ( {
selector : {
2023-02-19 14:37:51 +00:00
user _info _callsign : obj . user _info _callsign ,
2023-02-18 18:55:13 +00:00
} ,
} )
. then ( function ( result ) {
// handle result
2023-03-23 09:16:26 +00:00
console . log ( result ) ;
2023-02-18 18:55:13 +00:00
if ( result . docs . length > 0 ) {
users
. put ( {
_id : result . docs [ 0 ] . _id ,
_rev : result . docs [ 0 ] . _rev ,
2023-02-19 14:37:51 +00:00
user _info _callsign : obj . user _info _callsign ,
user _info _gridsquare : obj . user _info _gridsquare ,
user _info _name : obj . user _info _name ,
user _info _age : obj . user _info _age ,
user _info _location : obj . user _info _location ,
user _info _radio : obj . user _info _radio ,
user _info _antenna : obj . user _info _antenna ,
user _info _email : obj . user _info _email ,
user _info _website : obj . user _info _website ,
user _info _comments : obj . user _info _comments ,
2023-02-26 09:48:21 +00:00
user _info _image : obj . user _info _image ,
2023-02-18 18:55:13 +00:00
} )
. then ( function ( response ) {
console . log ( "UPDATED USER" ) ;
2023-02-23 11:13:49 +00:00
console . log ( response ) ;
console . log ( obj ) ;
2023-02-18 18:55:13 +00:00
} )
. catch ( function ( err ) {
console . log ( err ) ;
} ) ;
} else {
users
. post ( {
2023-02-19 14:37:51 +00:00
user _info _callsign : obj . user _info _callsign ,
user _info _gridsquare : obj . user _info _gridsquare ,
user _info _name : obj . user _info _name ,
user _info _age : obj . user _info _age ,
user _info _location : obj . user _info _location ,
user _info _radio : obj . user _info _radio ,
user _info _antenna : obj . user _info _antenna ,
user _info _email : obj . user _info _email ,
user _info _website : obj . user _info _website ,
user _info _comments : obj . user _info _comments ,
2023-02-18 18:55:13 +00:00
} )
. then ( function ( response ) {
console . log ( "NEW USER ADDED" ) ;
} )
. catch ( function ( err ) {
console . log ( err ) ;
} ) ;
}
} )
. catch ( function ( err ) {
console . log ( err ) ;
} ) ;
} ;
2023-02-28 19:06:39 +00:00
addFileListToUserDatabaseIfNotExists = function ( obj ) {
console . log ( obj ) ;
users
. find ( {
selector : {
user _info _callsign : obj . user _info _callsign ,
} ,
} )
. then ( function ( result ) {
// handle result
if ( result . docs . length > 0 ) {
users
. put ( {
_id : result . docs [ 0 ] . _id ,
_rev : result . docs [ 0 ] . _rev ,
user _shared _folder : obj . user _shared _folder ,
2023-03-23 09:14:12 +00:00
user _info _callsign : result . docs [ 0 ] . user _info _callsign ,
user _info _gridsquare : result . docs [ 0 ] . user _info _gridsquare ,
user _info _name : result . docs [ 0 ] . user _info _name ,
user _info _age : result . docs [ 0 ] . user _info _age ,
user _info _location : result . docs [ 0 ] . user _info _location ,
user _info _radio : result . docs [ 0 ] . user _info _radio ,
user _info _antenna : result . docs [ 0 ] . user _info _antenna ,
user _info _email : result . docs [ 0 ] . user _info _email ,
user _info _website : result . docs [ 0 ] . user _info _website ,
user _info _comments : result . docs [ 0 ] . user _info _comments ,
2023-02-28 19:06:39 +00:00
} )
. then ( function ( response ) {
2023-03-04 19:20:50 +00:00
console . log ( "File List: UPDATED USER" ) ;
2023-02-28 19:06:39 +00:00
console . log ( response ) ;
console . log ( obj ) ;
2023-03-23 08:53:58 +00:00
getSetUserSharedFolder ( obj . user _info _callsign ) ;
2023-02-28 19:06:39 +00:00
} )
. catch ( function ( err ) {
console . log ( err ) ;
} ) ;
} else {
users
. post ( {
user _info _callsign : obj . user _info _callsign ,
user _shared _folder : obj . user _shared _folder ,
} )
. then ( function ( response ) {
2023-03-04 19:20:50 +00:00
console . log ( "File List: NEW USER ADDED" ) ;
2023-03-23 08:53:58 +00:00
getSetUserSharedFolder ( obj . user _info _callsign ) ;
2023-02-28 19:06:39 +00:00
} )
. catch ( function ( err ) {
console . log ( err ) ;
} ) ;
}
} )
. catch ( function ( err ) {
console . log ( err ) ;
} ) ;
} ;
2022-09-05 12:03:10 +00:00
// Scroll to bottom of message-container
function scrollMessagesToBottom ( ) {
2023-02-11 21:49:07 +00:00
var messageBody = document . getElementById ( "message-container" ) ;
messageBody . scrollTop = messageBody . scrollHeight - messageBody . clientHeight ;
2022-12-09 09:22:03 +00:00
}
2022-12-27 21:57:54 +00:00
2022-12-27 22:30:15 +00:00
// CRC CHECKSUMS
2022-12-27 21:57:54 +00:00
// https://stackoverflow.com/a/50579690
// crc32 calculation
//console.log(crc32('abc'));
2022-12-27 22:30:15 +00:00
//var crc32=function(r){for(var a,o=[],c=0;c<256;c++){a=c;for(var f=0;f<8;f++)a=1&a?3988292384^a>>>1:a>>>1;o[c]=a}for(var n=-1,t=0;t<r.length;t++)n=n>>>8^o[255&(n^r.charCodeAt(t))];return(-1^n)>>>0};
2022-12-27 21:57:54 +00:00
//console.log(crc32('abc').toString(16).toUpperCase()); // hex
2022-12-27 22:30:15 +00:00
2023-02-11 21:49:07 +00:00
var makeCRCTable = function ( ) {
var c ;
var crcTable = [ ] ;
for ( var n = 0 ; n < 256 ; n ++ ) {
c = n ;
for ( var k = 0 ; k < 8 ; k ++ ) {
c = c & 1 ? 0xedb88320 ^ ( c >>> 1 ) : c >>> 1 ;
2022-12-27 22:30:15 +00:00
}
2023-02-11 21:49:07 +00:00
crcTable [ n ] = c ;
}
return crcTable ;
} ;
2022-12-27 22:30:15 +00:00
2023-02-11 21:49:07 +00:00
var crc32 = function ( str ) {
var crcTable = window . crcTable || ( window . crcTable = makeCRCTable ( ) ) ;
var crc = 0 ^ - 1 ;
2022-12-27 22:30:15 +00:00
2023-02-11 21:49:07 +00:00
for ( var i = 0 ; i < str . length ; i ++ ) {
crc = ( crc >>> 8 ) ^ crcTable [ ( crc ^ str . charCodeAt ( i ) ) & 0xff ] ;
}
2022-12-27 22:30:15 +00:00
2023-02-11 21:49:07 +00:00
return ( crc ^ - 1 ) >>> 0 ;
2023-02-05 03:26:44 +00:00
} ;
2023-03-03 03:05:45 +00:00
2023-02-19 14:37:51 +00:00
function returnObjFromCallsign ( database , callsign ) {
2023-02-26 11:15:29 +00:00
return new Promise ( ( resolve , reject ) => {
2023-02-26 11:20:01 +00:00
users
. find ( {
selector : {
user _info _callsign : callsign ,
} ,
} )
. then ( function ( result ) {
//return new Promise((resolve, reject) => {
if ( typeof result . docs [ 0 ] !== "undefined" ) {
resolve ( result . docs [ 0 ] ) ;
} else {
reject ( "Promise rejected" ) ;
}
/ *
2023-02-20 17:55:21 +00:00
if ( typeof result . docs [ 0 ] !== "undefined" ) {
return result . docs [ 0 ] ;
2023-02-26 11:15:29 +00:00
2023-02-20 17:55:21 +00:00
} else {
return false ;
}
2023-02-26 11:15:29 +00:00
* /
2023-02-26 11:20:01 +00:00
} )
. catch ( function ( err ) {
console . log ( err ) ;
} ) ;
} ) ;
2023-02-19 13:36:29 +00:00
}
2023-02-20 17:55:21 +00:00
function createChatIndex ( ) {
db . createIndex ( {
2023-02-19 13:36:29 +00:00
index : {
fields : [
"timestamp" ,
2023-02-20 17:55:21 +00:00
"uuid" ,
"dxcallsign" ,
"dxgrid" ,
"msg" ,
"checksum" ,
"type" ,
"command" ,
"status" ,
"percent" ,
2023-05-09 08:35:50 +00:00
"attempt" ,
2023-02-20 17:55:21 +00:00
"bytesperminute" ,
2023-02-19 13:36:29 +00:00
"_attachments" ,
] ,
} ,
} )
2023-02-20 17:55:21 +00:00
. then ( function ( result ) {
// handle result
console . log ( result ) ;
} )
. catch ( function ( err ) {
console . log ( err ) ;
} ) ;
}
function createUserIndex ( ) {
users
. createIndex ( {
index : {
fields : [
"timestamp" ,
"user_info_callsign" ,
"user_info_gridsquare" ,
"user_info_name" ,
"user_info_age" ,
"user_info_location" ,
"user_info_radio" ,
"user_info_antenna" ,
"user_info_email" ,
"user_info_website" ,
"user_info_comments" ,
2023-02-26 09:48:21 +00:00
"user_info_image" ,
2023-02-20 17:55:21 +00:00
] ,
} ,
} )
. then ( function ( result ) {
// handle result
console . log ( result ) ;
return true ;
} )
. catch ( function ( err ) {
console . log ( err ) ;
return false ;
} ) ;
2023-02-19 14:37:51 +00:00
}
2023-02-19 13:36:29 +00:00
2023-02-25 01:00:34 +00:00
async function updateAllChat ( clear ) {
2023-02-20 17:55:21 +00:00
if ( clear == true ) {
2023-02-19 14:37:51 +00:00
filetype = "" ;
file = "" ;
filename = "" ;
callsign _counter = 0 ;
2023-02-25 01:00:34 +00:00
//selected_callsign = "";
dxcallsigns . clear ( ) ;
2023-02-20 17:55:21 +00:00
document . getElementById ( "list-tab" ) . innerHTML = "" ;
document . getElementById ( "nav-tabContent" ) . innerHTML = "" ;
2023-02-19 14:37:51 +00:00
//document.getElementById("list-tab").childNodes.remove();
//document.getElementById("nav-tab-content").childrenNodes.remove();
}
2023-02-19 19:26:52 +00:00
//Ensure we create an index before running db.find
//We can't rely on the default index existing before we get here...... :'(
2023-02-25 05:29:09 +00:00
await db
. createIndex ( {
index : {
fields : [ { timestamp : "asc" } ] ,
} ,
} )
2023-02-25 01:00:34 +00:00
. then ( async function ( result ) {
2023-02-19 19:26:52 +00:00
// handle result
2023-02-25 05:29:09 +00:00
await db
. find ( {
selector : {
$and : [ { timestamp : { $exists : true } } , { $or : chatFilter } ] ,
//$or: chatFilter
2023-02-19 19:26:52 +00:00
} ,
2023-02-25 05:29:09 +00:00
sort : [
{
timestamp : "asc" ,
} ,
] ,
} )
2023-02-19 19:26:52 +00:00
. then ( async function ( result ) {
// handle result async
2023-03-22 22:46:43 +00:00
//document.getElementById("blurOverlay").classList.add("bg-primary");
2023-03-22 22:46:13 +00:00
2023-02-19 19:26:52 +00:00
if ( typeof result !== "undefined" ) {
2023-02-20 17:55:21 +00:00
for ( const item of result . docs ) {
//await otherwise history will not be in chronological order
await db
. get ( item . _id , {
2023-02-19 19:26:52 +00:00
attachments : true ,
2023-02-20 17:55:21 +00:00
} )
. then ( function ( item _with _attachments ) {
2023-02-19 19:26:52 +00:00
update _chat ( item _with _attachments ) ;
} ) ;
2023-02-20 17:55:21 +00:00
}
2023-02-19 14:37:51 +00:00
}
2023-03-22 22:46:43 +00:00
} )
2023-02-19 19:26:52 +00:00
. catch ( function ( err ) {
console . log ( err ) ;
} ) ;
2023-02-19 14:37:51 +00:00
} )
. catch ( function ( err ) {
console . log ( err ) ;
} ) ;
2023-02-25 05:29:09 +00:00
if ( clear == true && dxcallsigns . has ( selected _callsign ) == false ) {
//Selected call sign is not visible, reset to first call sign
let tmp = dxcallsigns . entries ( ) . next ( ) . value [ 0 ] ;
selected _callsign = tmp ;
document
. getElementById ( "chat-" + tmp + "-list" )
. classList . add ( "active" , "show" ) ;
document . getElementById ( "chat-" + tmp ) . classList . add ( "active" , "show" ) ;
scrollMessagesToBottom ( ) ;
}
2023-02-19 14:37:51 +00:00
}
2023-02-26 11:15:29 +00:00
2023-03-19 15:33:19 +00:00
function getSetUserSharedFolder ( selected _callsign ) {
2023-03-22 12:32:49 +00:00
// TODO: This is a dirty hotfix for avoiding, this function is canceld too fast.
console . log ( "get set user information:" + selected _callsign ) ;
2023-03-22 12:27:59 +00:00
2023-03-04 18:49:59 +00:00
if (
selected _callsign == "" ||
selected _callsign == null ||
typeof selected _callsign == "undefined"
2023-03-22 12:53:04 +00:00
) {
console . log ( "return triggered" ) ;
2023-03-04 18:49:59 +00:00
return ;
2023-03-22 12:53:04 +00:00
}
2023-02-26 11:20:01 +00:00
returnObjFromCallsign ( users , selected _callsign )
. then ( function ( data ) {
2023-03-19 15:33:19 +00:00
console . log ( data ) ;
2023-02-28 19:06:39 +00:00
2023-02-28 19:07:10 +00:00
console . log ( data . user _shared _folder ) ;
if ( typeof data . user _shared _folder !== "undefined" ) {
// shared folder table
2023-03-05 06:38:36 +00:00
var icons = [
"aac" ,
"ai" ,
"bmp" ,
"cs" ,
"css" ,
"csv" ,
"doc" ,
"docx" ,
"exe" ,
"gif" ,
"heic" ,
"html" ,
"java" ,
"jpg" ,
"js" ,
"json" ,
"jsx" ,
"key" ,
"m4p" ,
"md" ,
"mdx" ,
"mov" ,
"mp3" ,
"mp4" ,
"otf" ,
"pdf" ,
"php" ,
"png" ,
"ppt" ,
"pptx" ,
"psd" ,
"py" ,
"raw" ,
"rb" ,
"sass" ,
"scss" ,
"sh" ,
"sql" ,
"svg" ,
"tiff" ,
"tsx" ,
"ttf" ,
"txt" ,
"wav" ,
"woff" ,
"xls" ,
"xlsx" ,
"xml" ,
"yml" ,
] ;
2023-02-28 19:07:10 +00:00
var tbl = document . getElementById ( "sharedFolderTableDX" ) ;
tbl . innerHTML = "" ;
let counter = 0 ;
data . user _shared _folder . forEach ( ( file ) => {
var row = document . createElement ( "tr" ) ;
2023-03-05 06:38:36 +00:00
2023-03-05 06:32:22 +00:00
let dxcall = selected _callsign ;
let name = file [ "name" ] ;
let type = file [ "extension" ] ;
2023-03-05 06:38:36 +00:00
if ( icons . indexOf ( type ) == - 1 ) {
type = "bi-file-earmark" ;
2023-03-05 06:32:22 +00:00
} else {
2023-03-05 06:38:36 +00:00
type = "bi-filetype-" + type ;
2023-03-05 06:32:22 +00:00
}
2023-02-28 19:07:10 +00:00
let id = document . createElement ( "td" ) ;
let idText = document . createElement ( "span" ) ;
2023-03-05 06:32:22 +00:00
counter += 1 ;
2023-03-05 06:38:36 +00:00
idText . innerHTML +=
2023-03-05 06:56:03 +00:00
'<i class="bi bi-file-earmark-arrow-down" style="font-size: 1.8rem;cursor: pointer"></i> ' +
2023-03-05 06:38:36 +00:00
counter ;
2023-02-28 19:07:10 +00:00
id . appendChild ( idText ) ;
row . appendChild ( id ) ;
let filename = document . createElement ( "td" ) ;
let filenameText = document . createElement ( "span" ) ;
filenameText . innerText = file [ "name" ] ;
filename . appendChild ( filenameText ) ;
row . appendChild ( filename ) ;
let filetype = document . createElement ( "td" ) ;
let filetypeText = document . createElement ( "span" ) ;
2023-03-05 06:32:22 +00:00
filetypeText . innerHTML = ` <i class="bi ${ type } " style="font-size: 1.8rem"></i> ` ;
2023-02-28 19:07:10 +00:00
filetype . appendChild ( filetypeText ) ;
row . appendChild ( filetype ) ;
let filesize = document . createElement ( "td" ) ;
let filesizeText = document . createElement ( "span" ) ;
2023-03-04 12:24:37 +00:00
filesizeText . innerText = formatBytes ( file [ "size" ] , 2 ) ;
2023-02-28 19:07:10 +00:00
filesize . appendChild ( filesizeText ) ;
row . appendChild ( filesize ) ;
2023-03-05 06:56:03 +00:00
id . addEventListener ( "click" , function ( ) {
2023-03-05 06:32:22 +00:00
//console.log(name," clicked");
2023-03-05 06:38:36 +00:00
sendFileReq ( dxcall , name ) ;
2023-03-05 06:32:22 +00:00
} ) ;
2023-02-28 19:07:10 +00:00
tbl . appendChild ( row ) ;
} ) ;
} else {
document . getElementById ( "sharedFolderTableDX" ) . innerHTML = "no data" ;
}
2023-02-26 11:20:01 +00:00
} )
2023-03-19 15:32:57 +00:00
. catch ( function ( err ) {
2023-03-23 09:28:08 +00:00
console . log ( err ) ;
2023-03-19 15:32:57 +00:00
document . getElementById ( "sharedFolderTableDX" ) . innerHTML = "no data" ;
} ) ;
}
2023-02-26 11:20:01 +00:00
function getSetUserInformation ( selected _callsign ) {
//Get user information
2023-03-22 12:45:37 +00:00
console . log ( "get set user information:" + selected _callsign ) ;
2023-03-04 18:49:19 +00:00
2023-03-04 18:49:59 +00:00
if (
selected _callsign == "" ||
selected _callsign == null ||
typeof selected _callsign == "undefined"
2023-03-22 12:53:04 +00:00
) {
console . log ( "return triggered" ) ;
2023-03-04 18:49:59 +00:00
return ;
2023-03-22 12:53:04 +00:00
}
2023-02-26 11:20:01 +00:00
document . getElementById ( "dx_user_info_callsign" ) . innerHTML =
selected _callsign ;
returnObjFromCallsign ( users , selected _callsign )
. then ( function ( data ) {
2023-03-19 15:33:19 +00:00
console . log ( data ) ;
2023-03-19 15:32:57 +00:00
2023-02-28 19:06:39 +00:00
// image
2023-02-28 19:07:10 +00:00
if ( typeof data . user _info _image !== "undefined" ) {
2023-03-19 16:17:29 +00:00
try {
2023-03-22 12:45:37 +00:00
console . log ( "try checking for image if base64 data" ) ;
2023-03-19 16:39:15 +00:00
// determine if we have a base64 encoded image
2023-03-22 21:08:42 +00:00
console . log ( data . user _info _image ) ;
2023-03-22 21:19:23 +00:00
console . log ( data . user _info _image . split ( ";base64," ) [ 1 ] ) ;
// split data string by "base64" for separating image type from base64 string
atob ( data . user _info _image . split ( ";base64," ) [ 1 ] ) ;
2023-03-19 16:30:02 +00:00
2023-03-19 16:17:29 +00:00
document . getElementById ( "dx_user_info_image" ) . src =
data . user _info _image ;
document . getElementById ( "user-image-" + selected _callsign ) . src =
data . user _info _image ;
} catch ( e ) {
console . log ( e ) ;
console . log ( "corrupted image data" ) ;
document . getElementById ( "user-image-" + selected _callsign ) . src =
defaultUserIcon ;
2023-03-23 08:47:53 +00:00
document . getElementById ( "dx_user_info_image" ) . src = defaultUserIcon ;
2023-03-19 16:17:29 +00:00
}
2023-02-28 19:06:39 +00:00
} else {
2023-03-19 07:25:52 +00:00
// throw error and use placeholder data
2023-03-23 08:47:53 +00:00
// throw new Error("Data not available or corrupted");
document . getElementById ( "dx_user_info_image" ) . src = defaultUserIcon ;
document . getElementById ( "user-image-" + selected _callsign ) . src =
defaultUserIcon ;
2023-02-28 19:06:39 +00:00
}
2023-02-28 08:08:09 +00:00
// Callsign list elements
document . getElementById (
"chat-" + selected _callsign + "-list-dxgrid"
) . innerHTML = "<small>" + data . user _info _gridsquare + "</small>" ;
document . getElementById ( "user-image-" + selected _callsign ) . className =
"p-1 rounded-circle" ;
document . getElementById ( "user-image-" + selected _callsign ) . style =
"width: 60px" ;
2023-02-28 08:07:38 +00:00
2023-02-28 08:08:09 +00:00
// DX Station tab
2023-02-26 11:20:01 +00:00
document . getElementById ( "dx_user_info_name" ) . innerHTML =
data . user _info _name ;
document . getElementById ( "dx_user_info_age" ) . innerHTML =
data . user _info _age ;
document . getElementById ( "dx_user_info_gridsquare" ) . innerHTML =
data . user _info _gridsquare ;
document . getElementById ( "dx_user_info_location" ) . innerHTML =
data . user _info _location ;
document . getElementById ( "dx_user_info_email" ) . innerHTML =
data . user _info _email ;
document . getElementById ( "dx_user_info_website" ) . innerHTML =
data . user _info _website ;
document . getElementById ( "dx_user_info_radio" ) . innerHTML =
data . user _info _radio ;
document . getElementById ( "dx_user_info_antenna" ) . innerHTML =
data . user _info _antenna ;
document . getElementById ( "dx_user_info_comments" ) . innerHTML =
data . user _info _comments ;
2023-02-28 19:06:39 +00:00
2023-02-26 11:20:01 +00:00
document . getElementById ( "dx_user_info_gridsquare" ) . className = "" ;
2023-02-26 13:01:21 +00:00
document . getElementById ( "dx_user_info_name" ) . className =
"badge bg-secondary" ;
document . getElementById ( "dx_user_info_age" ) . className =
"badge bg-secondary" ;
2023-02-26 11:20:01 +00:00
document . getElementById ( "dx_user_info_gridsquare" ) . className = "" ;
document . getElementById ( "dx_user_info_location" ) . className = "" ;
document . getElementById ( "dx_user_info_email" ) . className = "" ;
document . getElementById ( "dx_user_info_website" ) . className = "" ;
document . getElementById ( "dx_user_info_radio" ) . className = "" ;
document . getElementById ( "dx_user_info_antenna" ) . className = "" ;
document . getElementById ( "dx_user_info_comments" ) . className = "" ;
} )
. catch ( function ( err ) {
2023-03-22 21:08:42 +00:00
console . log ( "writing user info to modal failed" ) ;
console . log ( err ) ;
2023-03-22 21:08:12 +00:00
2023-02-28 08:07:38 +00:00
// Callsign list elements
2023-02-28 19:07:10 +00:00
document . getElementById ( "user-image-" + selected _callsign ) . src =
defaultUserIcon ;
document . getElementById ( "user-image-" + selected _callsign ) . className =
2023-02-27 17:32:01 +00:00
"p-1 rounded-circle w-100" ;
document . getElementById ( "user-image-" + selected _callsign ) . style =
"height:60px" ;
2023-02-28 08:08:09 +00:00
document . getElementById (
"chat-" + selected _callsign + "-list-dxgrid"
) . innerHTML = "<small>no grid</small>" ;
2023-02-27 17:32:01 +00:00
2023-02-28 08:07:38 +00:00
// DX Station tab
2023-02-28 19:06:39 +00:00
document . getElementById ( "dx_user_info_image" ) . src = defaultUserIcon ;
2023-02-28 19:07:10 +00:00
document . getElementById ( "dx_user_info_gridsquare" ) . className =
2023-02-26 11:20:01 +00:00
"placeholder col-4" ;
document . getElementById ( "dx_user_info_name" ) . className =
"placeholder col-4" ;
document . getElementById ( "dx_user_info_age" ) . className =
"placeholder col-2" ;
document . getElementById ( "dx_user_info_gridsquare" ) . className =
"placeholder col-3" ;
document . getElementById ( "dx_user_info_location" ) . className =
"placeholder col-3" ;
document . getElementById ( "dx_user_info_email" ) . className =
"placeholder col-7" ;
document . getElementById ( "dx_user_info_website" ) . className =
"placeholder col-7" ;
document . getElementById ( "dx_user_info_radio" ) . className =
"placeholder col-4" ;
document . getElementById ( "dx_user_info_antenna" ) . className =
"placeholder col-4" ;
document . getElementById ( "dx_user_info_comments" ) . className =
"placeholder col-7" ;
} ) ;
}
2023-02-26 15:26:24 +00:00
2023-02-28 14:20:17 +00:00
function sendSharedFolderList ( dxcallsign ) {
ipcRenderer . send ( "read-files-in-folder" , {
folder : config . shared _folder _path ,
} ) ;
2023-02-28 14:19:41 +00:00
2023-02-28 14:20:17 +00:00
console . log ( sharedFolderFileList ) ;
2023-02-28 19:07:10 +00:00
let fileListWithCallsign = "" ;
fileListWithCallsign += dxcallsign ;
fileListWithCallsign += split _char ;
fileListWithCallsign += JSON . stringify ( sharedFolderFileList ) ;
2023-02-28 19:06:39 +00:00
console . log ( fileListWithCallsign ) ;
2023-02-28 14:20:17 +00:00
ipcRenderer . send ( "run-tnc-command" , {
2023-02-28 14:19:41 +00:00
command : "responseSharedFolderList" ,
2023-03-05 02:59:28 +00:00
dxcallsign : dxcallsign ,
2023-02-28 19:06:39 +00:00
folderFileList : fileListWithCallsign ,
2023-02-28 14:19:41 +00:00
} ) ;
}
2023-03-05 21:16:43 +00:00
function sendSharedFolderFile ( dxcallsign , filename ) {
let filePath = path . join ( config . shared _folder _path , filename ) ;
2023-03-19 15:53:23 +00:00
console . log ( "In function sendSharedFolderFile " , filePath ) ;
2023-03-05 21:16:43 +00:00
//Make sure nothing sneaky is going on
2023-03-05 21:16:03 +00:00
if ( ! filePath . startsWith ( config . shared _folder _path ) ) {
console . error ( "File is outside of shared folder path!" ) ;
return ;
}
2023-03-05 21:16:43 +00:00
2023-03-05 21:16:03 +00:00
if ( ! fs . existsSync ( filePath ) ) {
2023-03-05 21:16:43 +00:00
console . warn ( "File doesn't seem to exist" ) ;
2023-03-05 21:16:03 +00:00
return ;
}
//Read file's data
let fileData = null ;
try {
//Has to be binary
2023-03-05 21:16:43 +00:00
let data = fs . readFileSync ( filePath ) ;
fileData = data . toString ( "utf-8" ) ;
2023-03-05 21:16:03 +00:00
} catch ( err ) {
console . log ( err ) ;
return ;
}
2023-03-05 21:16:43 +00:00
ipcRenderer . send ( "run-tnc-command" , {
command : "responseSharedFile" ,
dxcallsign : dxcallsign ,
file : filename ,
filedata : fileData ,
} ) ;
2023-02-28 14:19:41 +00:00
}
2023-02-26 15:27:55 +00:00
function sendUserData ( dxcallsign ) {
2023-02-26 15:26:24 +00:00
const userInfoFields = [
"user_info_image" ,
"user_info_callsign" ,
"user_info_gridsquare" ,
"user_info_name" ,
"user_info_age" ,
"user_info_location" ,
"user_info_radio" ,
"user_info_antenna" ,
"user_info_email" ,
"user_info_website" ,
"user_info_comments" ,
] ;
2023-02-26 15:27:55 +00:00
let info = "" ;
userInfoFields . forEach ( function ( subelem ) {
if ( subelem !== "user_info_image" ) {
info += document . getElementById ( subelem ) . value ;
info += split _char ;
} else {
info += document . getElementById ( subelem ) . src ;
info += split _char ;
}
} ) ;
2023-02-26 15:26:24 +00:00
2023-02-26 15:27:55 +00:00
console . log ( info ) ;
2023-02-26 15:26:24 +00:00
2023-02-26 15:27:55 +00:00
ipcRenderer . send ( "run-tnc-command" , {
command : "responseUserInfo" ,
dxcallsign : selected _callsign ,
userinfo : info ,
} ) ;
}
2023-02-26 16:54:21 +00:00
//Temporarily disable a button with timeout
function pauseButton ( btn , timems ) {
btn . disabled = true ;
var curText = btn . innerHTML ;
if ( config . high _graphics . toUpperCase ( ) == "TRUE" ) {
btn . innerHTML =
'<span class="spinner-grow spinner-grow-sm force-gpu" role="status" aria-hidden="true">' ;
}
setTimeout ( ( ) => {
btn . innerHTML = curText ;
btn . disabled = false ;
} , timems ) ;
2023-02-26 16:54:49 +00:00
}
2023-03-03 03:06:25 +00:00
ipcRenderer . on ( "update-config" , ( event , data ) => {
config = data ;
2023-03-03 03:05:45 +00:00
} ) ;
2023-03-04 12:24:37 +00:00
// https://stackoverflow.com/a/18650828
function formatBytes ( bytes , decimals = 2 ) {
2023-03-04 12:25:09 +00:00
if ( ! + bytes ) return "0 Bytes" ;
2023-03-04 12:24:37 +00:00
2023-03-04 12:25:09 +00:00
const k = 1024 ;
const dm = decimals < 0 ? 0 : decimals ;
const sizes = [ "Bytes" , "KB" , "MB" , "GB" , "TB" , "PB" , "EB" , "ZB" , "YB" ] ;
2023-03-04 12:24:37 +00:00
2023-03-04 12:25:09 +00:00
const i = Math . floor ( Math . log ( bytes ) / Math . log ( k ) ) ;
2023-03-04 12:24:37 +00:00
2023-03-04 12:25:09 +00:00
return ` ${ parseFloat ( ( bytes / Math . pow ( k , i ) ) . toFixed ( dm ) ) } ${ sizes [ i ] } ` ;
}
2023-03-05 06:32:22 +00:00
function sendFileReq ( dxcall , file ) {
//console.log(file," clicked");
ipcRenderer . send ( "run-tnc-command" , {
command : "requestSharedFile" ,
dxcallsign : dxcall ,
2023-03-05 06:38:36 +00:00
file : file ,
} ) ;
}
2023-03-16 07:59:32 +00:00
2023-03-16 07:59:54 +00:00
function changeGuiDesign ( design ) {
console . log ( design ) ;
if (
2023-03-16 07:59:32 +00:00
design != "default" &&
design != "default_light" &&
design != "default_dark" &&
design != "default_auto"
) {
var theme _path =
"../node_modules/bootswatch/dist/" + design + "/bootstrap.min.css" ;
document . getElementById ( "bootstrap_theme" ) . href = escape ( theme _path ) ;
} else if ( design == "default" || design == "default_light" ) {
var theme _path = "../node_modules/bootstrap/dist/css/bootstrap.min.css" ;
document . getElementById ( "bootstrap_theme" ) . href = escape ( theme _path ) ;
document . documentElement . setAttribute ( "data-bs-theme" , "light" ) ;
} else if ( design == "default_dark" ) {
var theme _path = "../node_modules/bootstrap/dist/css/bootstrap.min.css" ;
document . getElementById ( "bootstrap_theme" ) . href = escape ( theme _path ) ;
document . querySelector ( "html" ) . setAttribute ( "data-bs-theme" , "dark" ) ;
} else if ( design == "default_auto" ) {
var theme _path = "../node_modules/bootstrap/dist/css/bootstrap.min.css" ;
document . getElementById ( "bootstrap_theme" ) . href = escape ( theme _path ) ;
// https://stackoverflow.com/a/57795495
// check if dark mode or light mode used in OS
if (
window . matchMedia &&
window . matchMedia ( "(prefers-color-scheme: dark)" ) . matches
) {
// dark mode
document . documentElement . setAttribute ( "data-bs-theme" , "dark" ) ;
} else {
document . documentElement . setAttribute ( "data-bs-theme" , "light" ) ;
}
// also register event listener for automatic change
window
. matchMedia ( "(prefers-color-scheme: dark)" )
. addEventListener ( "change" , ( event ) => {
let newColorScheme = event . matches ? "dark" : "light" ;
if ( newColorScheme == "dark" ) {
document . documentElement . setAttribute ( "data-bs-theme" , "dark" ) ;
} else {
document . documentElement . setAttribute ( "data-bs-theme" , "light" ) ;
}
} ) ;
} else {
var theme _path = "../node_modules/bootstrap/dist/css/bootstrap.min.css" ;
document . getElementById ( "bootstrap_theme" ) . href = escape ( theme _path ) ;
document . documentElement . setAttribute ( "data-bs-theme" , "light" ) ;
}
//update path to css file
2023-03-16 07:59:54 +00:00
document . getElementById ( "bootstrap_theme" ) . href = escape ( theme _path ) ;
}
2023-05-09 10:27:51 +00:00
function checkForWaitingMessages ( dxcall ) {
2023-05-09 10:29:28 +00:00
console . log ( dxcall ) ;
db . find ( {
selector : {
dxcallsign : dxcall ,
type : "transmit" ,
status : "failed" ,
//attempt: { $lt: parseInt(config.max_retry_attempts) }
} ,
} )
2023-05-09 10:27:51 +00:00
. then ( function ( result ) {
// handle result
if ( result . docs . length > 0 ) {
2023-05-09 10:29:28 +00:00
// only want to process the first available item object, then return
// this ensures, we are only sending one message at once
2023-05-09 10:27:51 +00:00
2023-05-09 10:29:28 +00:00
if ( typeof result . docs [ 0 ] . attempt == "undefined" ) {
2023-05-09 11:24:37 +00:00
db . upsert ( result . docs [ 0 ] . _id , function ( doc ) {
2023-05-09 10:29:28 +00:00
if ( ! doc . attempt ) {
doc . attempt = 1 ;
2023-05-09 10:27:51 +00:00
}
2023-05-09 10:29:28 +00:00
doc . attempt ++ ;
return doc ;
} ) ;
console . log ( "old message found - adding attempt field" ) ;
result . docs [ 0 ] . attempt = 1 ;
2023-05-09 10:27:51 +00:00
}
2023-05-09 10:29:28 +00:00
if ( result . docs [ 0 ] . attempt < config . max _retry _attempts ) {
console . log ( "RESENDING MESSAGE TRIGGERED BY BEACON OR PING" ) ;
console . log ( result . docs [ 0 ] ) ;
document
. getElementById ( "retransmit-msg-" + result . docs [ 0 ] . _id )
. click ( ) ;
} else {
console . log ( "max retries reached...can't auto repeat" ) ;
document
. getElementById ( "msg-" + result . docs [ 0 ] . _id + "-attempts-badge" )
. classList . remove ( "bg-primary" ) ;
document
. getElementById ( "msg-" + result . docs [ 0 ] . _id + "-attempts-badge" )
. classList . add ( "bg-danger" ) ;
}
return ;
} else {
console . log ( "nope" ) ;
}
} )
. catch ( function ( err ) {
console . log ( err ) ;
} ) ;
}