diff --git a/package-lock.json b/package-lock.json index 13cfa42..fb673ad 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "call-me", - "version": "1.2.55", + "version": "1.2.56", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "call-me", - "version": "1.2.55", + "version": "1.2.56", "license": "AGPLv3", "dependencies": { "@ngrok/ngrok": "1.5.2", diff --git a/package.json b/package.json index d69180f..639baa5 100755 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "call-me", - "version": "1.2.55", + "version": "1.2.56", "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 19bba33..83dc955 100755 --- a/public/client.js +++ b/public/client.js @@ -622,6 +622,36 @@ async function handleScreenShareClick() { } } +// Update remote video styling based on screen sharing state +function updateRemoteVideoStyling(isScreenSharing) { + if (isScreenSharing) { + remoteVideo.classList.add('screen-share'); + remoteVideo.classList.remove('camera-feed'); + console.log('Remote screen share detected via data channel, classes:', remoteVideo.className); + } else { + remoteVideo.classList.add('camera-feed'); + remoteVideo.classList.remove('screen-share'); + console.log('Remote camera feed detected via data channel, classes:', remoteVideo.className); + } +} + +// Send screen sharing state to remote peer +function sendScreenShareState(isSharing) { + if (thisConnection && thisConnection.dataChannel && thisConnection.dataChannel.readyState === 'open') { + try { + thisConnection.dataChannel.send( + JSON.stringify({ + type: 'screenShareState', + isScreenSharing: isSharing, + }) + ); + console.log('Sent screen share state:', isSharing); + } catch (error) { + console.error('Error sending screen share state:', error); + } + } +} + // Start screen sharing async function startScreenSharing() { try { @@ -669,6 +699,9 @@ async function startScreenSharing() { screenShareBtn.title = 'Stop screen sharing'; screenShareBtn.innerHTML = ''; + // Send screen sharing state to remote peer + sendScreenShareState(true); + // Listen for screen share end (user clicks browser's stop sharing) screenStream.getVideoTracks()[0].onended = () => { stopScreenSharing(); @@ -731,6 +764,9 @@ async function stopScreenSharing() { screenShareBtn.title = 'Start screen sharing'; screenShareBtn.innerHTML = ''; + // Send screen sharing state to remote peer + sendScreenShareState(false); + // Reset original stream reference originalStream = null; @@ -996,6 +1032,50 @@ function initializeConnection() { stream.getTracks().forEach((track) => thisConnection.addTrack(track, stream)); + // Create data channel for screen sharing state communication + thisConnection.dataChannel = thisConnection.createDataChannel('screenShareState', { + ordered: true, + }); + + thisConnection.dataChannel.onopen = () => { + console.log('Data channel opened'); + // Send current screen sharing state + thisConnection.dataChannel.send( + JSON.stringify({ + type: 'screenShareState', + isScreenSharing: isScreenSharing, + }) + ); + }; + + thisConnection.dataChannel.onmessage = (event) => { + try { + const data = JSON.parse(event.data); + if (data.type === 'screenShareState') { + console.log('Received screen share state:', data.isScreenSharing); + updateRemoteVideoStyling(data.isScreenSharing); + } + } catch (error) { + console.error('Error parsing data channel message:', error); + } + }; + + // Handle incoming data channels + thisConnection.ondatachannel = (event) => { + const channel = event.channel; + channel.onmessage = (event) => { + try { + const data = JSON.parse(event.data); + if (data.type === 'screenShareState') { + console.log('Received screen share state via incoming channel:', data.isScreenSharing); + updateRemoteVideoStyling(data.isScreenSharing); + } + } catch (error) { + console.error('Error parsing incoming data channel message:', error); + } + }; + }; + thisConnection.ontrack = (e) => { if (e.streams && e.streams[0]) { const remoteStream = e.streams[0]; @@ -1005,78 +1085,13 @@ function initializeConnection() { remoteVideo.autoplay = true; remoteVideo.controls = false; - // Detect if remote stream is screen share based on video track settings - const videoTrack = remoteStream.getVideoTracks()[0]; - if (videoTrack) { - const settings = videoTrack.getSettings(); - console.log('Remote video track settings:', settings); - - // Enhanced screen share detection - const isScreenShare = - // Direct indicators - settings.displaySurface === 'monitor' || - settings.displaySurface === 'window' || - settings.displaySurface === 'application' || - // Resolution-based detection (common screen resolutions) - settings.width >= 1920 || - settings.height >= 1080 || - // Aspect ratio detection (wider than typical cameras) - (settings.width && settings.height && settings.width / settings.height > 1.7) || - // Frame rate detection (screens often use lower frame rates) - (settings.frameRate && settings.frameRate <= 15); - - console.log('Screen share detection result:', isScreenShare); - console.log('Detection factors:', { - displaySurface: settings.displaySurface, - width: settings.width, - height: settings.height, - aspectRatio: - settings.width && settings.height ? (settings.width / settings.height).toFixed(2) : 'unknown', - frameRate: settings.frameRate, - }); - - if (isScreenShare) { - remoteVideo.classList.add('screen-share'); - remoteVideo.classList.remove('camera-feed'); - console.log('Remote screen share detected, classes:', remoteVideo.className); - } else { - remoteVideo.classList.add('camera-feed'); - remoteVideo.classList.remove('screen-share'); - console.log('Remote camera feed detected, classes:', remoteVideo.className); - } - - // Force a style refresh - remoteVideo.style.display = 'none'; - remoteVideo.offsetHeight; // Trigger reflow - remoteVideo.style.display = 'block'; - } + // Initial styling - will be updated via data channel + remoteVideo.classList.add('camera-feed'); + remoteVideo.classList.remove('screen-share'); startSessionTime(); renderUserList(); // Update UI to show hang-up button - // Retry screen share detection after video loads - setTimeout(() => { - const videoTrack = remoteStream.getVideoTracks()[0]; - if (videoTrack) { - const settings = videoTrack.getSettings(); - console.log('Delayed remote video track settings:', settings); - - const isScreenShare = - settings.displaySurface === 'monitor' || - settings.displaySurface === 'window' || - settings.displaySurface === 'application' || - settings.width >= 1920 || - settings.height >= 1080 || - (settings.width && settings.height && settings.width / settings.height > 1.7); - - if (isScreenShare && !remoteVideo.classList.contains('screen-share')) { - remoteVideo.classList.add('screen-share'); - remoteVideo.classList.remove('camera-feed'); - console.log('Delayed detection: Remote screen share detected, classes:', remoteVideo.className); - } - } - }, 1000); - console.log('Remote stream set to video element'); } else { handleError('No stream available in the ontrack event.');