diff --git a/.env.template b/.env.template index 81849de..19c50e7 100644 --- a/.env.template +++ b/.env.template @@ -9,6 +9,7 @@ PORT=8000 # Logging +LOGS_DEBUG=true # true or false LOGS_JSON=false # Enable JSON formatted logs (true/false) LOGS_JSON_PRETTY=false # Enable pretty JSON formatted logs (true/false) @@ -50,10 +51,6 @@ NGROK_AUTH_TOKEN=YourNgrokAuthToken TZ=UTC -# Logs - -DEBUG=true # true or false - # API API_KEY_SECRET=call_me_api_key_secret # change me diff --git a/app/logs.js b/app/logs.js index 467bce0..654d10f 100644 --- a/app/logs.js +++ b/app/logs.js @@ -4,6 +4,7 @@ const util = require('util'); const colors = require('colors'); colors.enable(); // colors.disable(); +const LOGS_DEBUG = process.env.LOGS_DEBUG !== undefined ? process.env.LOGS_DEBUG === 'true' : true; const LOGS_JSON = process.env.LOGS_JSON ? process.env.LOGS_JSON === 'true' : false; const LOGS_JSON_PRETTY = process.env.LOGS_JSON_PRETTY ? process.env.LOGS_JSON_PRETTY === 'true' : false; @@ -15,7 +16,7 @@ const options = { module.exports = class Logs { constructor(appName = 'call-me') { this.appName = colors.yellow(appName); - this.debugOn = process.env.DEBUG !== undefined ? process.env.DEBUG === 'true' : true; + this.debugOn = LOGS_DEBUG; this.timeStart = Date.now(); this.timeEnd = null; this.timeElapsedMs = null; diff --git a/package-lock.json b/package-lock.json index 0c6dc68..12ee72f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "call-me", - "version": "1.2.89", + "version": "1.2.90", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "call-me", - "version": "1.2.89", + "version": "1.2.90", "license": "AGPLv3", "dependencies": { "@ngrok/ngrok": "1.7.0", diff --git a/package.json b/package.json index 7652ff7..27ad3b9 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "call-me", - "version": "1.2.89", + "version": "1.2.90", "description": "Your Go-To for Instant Video Calls", "author": "Miroslav Pejic - miroslav.pejic.85@gmail.com", "license": "AGPLv3", diff --git a/public/client.js b/public/client.js index 443a9e5..6d46d3a 100755 --- a/public/client.js +++ b/public/client.js @@ -182,6 +182,8 @@ async function checkHostPassword(maxRetries = 3, attempts = 0) { if (config.isPasswordRequired) { // Show prompt for the password const { value: password } = await Swal.fire({ + heightAuto: false, + scrollbarPadding: false, title: 'Host Protected', text: 'Please enter the host password:', input: 'password', @@ -216,6 +218,8 @@ async function checkHostPassword(maxRetries = 3, attempts = 0) { if (validationResult.success) { await Swal.fire({ + heightAuto: false, + scrollbarPadding: false, position: 'top', icon: 'success', title: 'Access Granted', @@ -228,6 +232,8 @@ async function checkHostPassword(maxRetries = 3, attempts = 0) { attempts++; if (attempts < maxRetries) { await Swal.fire({ + heightAuto: false, + scrollbarPadding: false, position: 'top', icon: 'error', title: 'Invalid Password', @@ -237,6 +243,8 @@ async function checkHostPassword(maxRetries = 3, attempts = 0) { await checkHostPassword(maxRetries, attempts); } else { await Swal.fire({ + heightAuto: false, + scrollbarPadding: false, position: 'top', icon: 'warning', title: 'Too Many Attempts', @@ -251,6 +259,8 @@ async function checkHostPassword(maxRetries = 3, attempts = 0) { } catch (error) { console.error('Error:', error); Swal.fire({ + heightAuto: false, + scrollbarPadding: false, position: 'top', icon: 'error', title: 'Error', @@ -460,12 +470,12 @@ async function handleEnumerateDevices() { const videoInputs = devices.filter((device) => device.kind === 'videoinput'); if (videoInputs.length > 1 && userInfo.device.isMobile) { swapCameraBtn.addEventListener('click', swapCamera); - elemDisplay(swapCameraBtn, true, 'inline'); + elemDisplay(swapCameraBtn, true, 'inline-flex'); } // Check if screen sharing is supported if (navigator.mediaDevices && navigator.mediaDevices.getDisplayMedia) { - elemDisplay(screenShareBtn, true, 'inline'); + elemDisplay(screenShareBtn, true, 'inline-flex'); } else { elemDisplay(screenShareBtn, false); console.log('Screen sharing not supported in this browser'); @@ -1217,6 +1227,8 @@ function handleMediaStreamError(error) { } Swal.fire({ + heightAuto: false, + scrollbarPadding: false, position: 'top', icon: 'warning', html: errorMessage, @@ -1343,6 +1355,8 @@ function offerAccept(data) { } Swal.fire({ + heightAuto: false, + scrollbarPadding: false, position: 'top', imageUrl: 'assets/ring.png', imageWidth: 284, @@ -1617,17 +1631,15 @@ function handleLeave(disconnect = true) { // Display toast messages function toast(message, icon = 'info', position = 'top', timer = 3000) { - const Toast = Swal.mixin({ - toast: true, - position: position, - icon: icon, - showConfirmButton: false, + Swal.fire({ + heightAuto: false, + scrollbarPadding: false, + position, + icon, + html: message, + timer, timerProgressBar: true, - timer: timer, - }); - Toast.fire({ - icon: icon, - title: message, + showConfirmButton: false, showClass: { popup: 'animate__animated animate__fadeInDown' }, hideClass: { popup: 'animate__animated animate__fadeOutUp' }, }); @@ -1638,6 +1650,8 @@ function handleError(message, error = false, position = 'top', timer = 6000) { if (error) console.error(error); Swal.fire({ + heightAuto: false, + scrollbarPadding: false, position, icon: 'warning', html: message, @@ -1653,6 +1667,8 @@ function handleError(message, error = false, position = 'top', timer = 6000) { // Display Message to user function popupMsg(message, position = 'top', timer = 4000) { Swal.fire({ + heightAuto: false, + scrollbarPadding: false, position, html: message, timerProgressBar: true, @@ -1767,8 +1783,21 @@ function setupDataChannel(channel) { console.log('Data channel closed'); }; - dataChannel.onerror = (error) => { - console.error('Data channel error:', error); + dataChannel.onerror = (event) => { + // Some browsers emit an error event during/after close (e.g. "User-Initiated Abort, reason=Close called"). + // That's expected during hang-up/teardown and shouldn't be shown to the user. + const rtcError = event?.error; + const message = (rtcError && (rtcError.message || rtcError.reason)) || ''; + const isClosingOrClosed = dataChannel?.readyState && dataChannel.readyState !== 'open'; + const isBenignCloseError = + rtcError?.name === 'OperationError' && /close called|user-initiated abort|abort/i.test(String(message)); + + if (isClosingOrClosed || isBenignCloseError) { + console.debug('Ignoring data channel close-related error:', event); + return; + } + + console.error('Data channel error:', event); toast('Data channel error occurred', 'warning', 'top', 3000); }; @@ -1985,7 +2014,8 @@ function renderUserList() { if (isInActiveCall) { // Show hang-up button only if in active call (user has answered) - actionBtnEl.className = 'btn btn-custom btn-danger btn-s hangup-user-btn fas fa-phone-slash'; + actionBtnEl.className = 'btn btn-custom btn-danger btn-s hangup-user-btn'; + actionBtnEl.innerHTML = ''; actionBtnEl.title = `Hang up call with ${user}`; actionBtnEl.addEventListener('click', (e) => { e.stopPropagation(); @@ -1998,7 +2028,8 @@ function renderUserList() { }); } else { // Show call button if not in active call - actionBtnEl.className = 'btn btn-custom btn-warning btn-s call-user-btn fas fa-phone'; + actionBtnEl.className = 'btn btn-custom btn-warning btn-s call-user-btn'; + actionBtnEl.innerHTML = ''; actionBtnEl.title = `Call ${user}`; actionBtnEl.addEventListener('click', (e) => { e.stopPropagation(); @@ -2013,7 +2044,8 @@ function renderUserList() { // Send file button const sendFileBtn = document.createElement('button'); - sendFileBtn.className = 'btn btn-custom btn-secondary btn-s fas fa-paperclip'; + sendFileBtn.className = 'btn btn-custom btn-secondary btn-s'; + sendFileBtn.innerHTML = ''; sendFileBtn.style.marginRight = '10px'; sendFileBtn.style.cursor = 'pointer'; sendFileBtn.setAttribute('data-toggle', 'tooltip'); @@ -2538,6 +2570,8 @@ function handleClearChatClick() { } Swal.fire({ + heightAuto: false, + scrollbarPadding: false, position: 'center', icon: 'question', title: 'Clear Chat Messages', diff --git a/public/i18n.js b/public/i18n.js index c567a1b..8535085 100644 --- a/public/i18n.js +++ b/public/i18n.js @@ -249,6 +249,8 @@ function updateCustomTranslations() { function showTranslatedAlert(titleKey, textKey, icon = 'info') { if (typeof Swal !== 'undefined') { Swal.fire({ + heightAuto: false, + scrollbarPadding: false, title: t(titleKey), text: t(textKey), icon: icon, diff --git a/public/index.html b/public/index.html index f0df2b0..06017ab 100755 --- a/public/index.html +++ b/public/index.html @@ -61,29 +61,25 @@ -
-
-
-
-
-

Call-me

-
- -
- - -
- - +
+
+
+
+

Call-me

+
+ +
+ +
+ +
@@ -91,7 +87,7 @@
-
+
0s @@ -111,89 +107,87 @@
-
-
- - - - - - - - - - - - - - - - -
+
+ + + + + + + + + + + + + + + +
@@ -233,7 +227,7 @@
-
+