diff --git a/receivers/common/web/main/Renderer.ts b/receivers/common/web/main/Renderer.ts index 6b20636..17bd996 100644 --- a/receivers/common/web/main/Renderer.ts +++ b/receivers/common/web/main/Renderer.ts @@ -3,12 +3,16 @@ import QRCode from 'modules/qrcode'; import { onQRCodeRendered } from 'src/main/Renderer'; import { toast, ToastIcon } from '../components/Toast'; -const connectionStatusText = document.getElementById("connection-status-text"); -const connectionStatusSpinner = document.getElementById("connection-spinner"); -const connectionStatusCheck = document.getElementById("connection-check"); +const connectionStatusText = document.getElementById('connection-status-text'); +const connectionStatusSpinner = document.getElementById('connection-spinner'); +const connectionStatusCheck = document.getElementById('connection-check'); let connections = []; let renderedConnectionInfo = false; let renderedAddresses = null; +let qrCodeUrl = null; +let qrWidth = null; + +window.addEventListener('resize', (event) => calculateQRCodeWidth()); // Window might be re-created while devices are still connected window.targetAPI.onPing((_event, value: any) => { @@ -33,17 +37,17 @@ window.targetAPI.onDisconnect((_event, value: any) => { connectionStatusText.textContent = 'Waiting for a connection'; connectionStatusSpinner.style.display = 'inline-block'; connectionStatusCheck.style.display = 'none'; - toast("Device disconnected", ToastIcon.INFO); + toast('Device disconnected', ToastIcon.INFO); } else { connectionStatusText.textContent = connections.length > 1 ? 'Multiple devices connected:\r\n Ready to cast' : 'Connected: Ready to cast'; - toast("A device has disconnected", ToastIcon.INFO); + toast('A device has disconnected', ToastIcon.INFO); } } }); if(window.targetAPI.getDeviceInfo()) { - console.log("device info already present"); + console.log('device info already present'); renderIPsAndQRCode(); } @@ -56,7 +60,7 @@ function onConnect(value: any) { function renderIPsAndQRCode() { const value = window.targetAPI.getDeviceInfo(); - console.log("device info", value); + console.log(`Network Interface Info: ${value}`); const addresses = []; value.interfaces.forEach((e) => addresses.push(e.address)); @@ -64,14 +68,14 @@ function renderIPsAndQRCode() { const connError = document.getElementById('connection-error'); if (renderedAddresses !== null && addresses.length > 0) { - toast("Network connections has changed, please reconnect sender devices to receiver if you experience issues", ToastIcon.WARNING); + toast('Network connections has changed, please reconnect sender devices to receiver if you experience issues', ToastIcon.WARNING); } else if (addresses.length === 0) { connInfo.style.display = 'none'; connError.style.display = 'block'; if (renderedAddresses !== null) { - toast("Lost network connection, please reconnect to a network", ToastIcon.ERROR); + toast('Lost network connection, please reconnect to a network', ToastIcon.ERROR); } renderedAddresses = [] @@ -102,36 +106,15 @@ function renderIPsAndQRCode() { const json = JSON.stringify(fcastConfig); let base64 = btoa(json); base64 = base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, ''); - const url = `fcast://r/${base64}`; - console.log("qr", {json, url, base64}); - - const qrCodeElement = document.getElementById('qr-code'); - QRCode.toCanvas(qrCodeElement, url, { - margin: 0, - width: 256, - color: { - dark : "#000000", - light : "#ffffff", - }, - errorCorrectionLevel : "M", - }, - (err) => { - if (err) { - console.error(`Error rendering QR Code: ${err}`); - toast(`Error rendering QR Code: ${err}`, ToastIcon.ERROR); - } - else { - console.log(`Rendered QR Code`); - } - }); + qrCodeUrl = `fcast://r/${base64}`; + console.log('QR Code:', {json, qrCodeUrl, base64}); + calculateQRCodeWidth(); if (!renderedConnectionInfo) { const connInfoLoading = document.getElementById('connection-information-loading'); connInfoLoading.style.display = 'none'; connInfo.style.display = 'block'; } - - onQRCodeRendered(); } function renderIPs(interfaces: any) { @@ -148,7 +131,7 @@ function renderIPs(interfaces: any) { ipsNameColumn.innerHTML = ''; for (const iface of interfaces) { - const ipIcon = document.createElement("div"); + const ipIcon = document.createElement('div'); let icon = 'iconSize '; if (iface.type === 'wired') { icon += 'ip-wired-icon'; @@ -172,15 +155,63 @@ function renderIPs(interfaces: any) { ipIcon.className = icon; ipsIconColumn.append(ipIcon); - const ipText = document.createElement("div"); + const ipText = document.createElement('div'); ipText.className = 'ip-entry-text'; ipText.textContent = iface.address; ipsTextColumn.append(ipText); - const ipName = document.createElement("div"); + const ipName = document.createElement('div'); ipName.className = 'ip-entry-text'; ipName.textContent = iface.name; ipsNameColumn.append(ipName); } } } + +function calculateQRCodeWidth() { + if (qrCodeUrl !== null) { + let changedQrWidth = null; + + if ((window.innerWidth >= 2560) || (window.innerHeight >= 1440)) { + changedQrWidth = 384; + } + if ((window.innerWidth >= 1920 && window.innerWidth < 2560) || (window.innerHeight >= 1080 && window.innerHeight < 1440)) { + changedQrWidth = 256; + } + if ((window.innerWidth >= 1280 && window.innerWidth < 1920) || (window.innerHeight >= 720 && window.innerHeight < 1080)) { + changedQrWidth = 192; + } + if (window.innerWidth < 1280 || window.innerHeight < 720) { + changedQrWidth = 128; + } + + if (qrWidth !== changedQrWidth) { + qrWidth = changedQrWidth; + renderQRCode(qrCodeUrl); + } + } +} + +function renderQRCode(url: string) { + const qrCodeElement = document.getElementById('qr-code'); + QRCode.toCanvas(qrCodeElement, url, { + margin: 0, + width: qrWidth, + color: { + dark : '#000000', + light : '#ffffff', + }, + errorCorrectionLevel : 'M', + }, + (err) => { + if (err) { + console.error(`Error rendering QR Code: ${err}`); + toast(`Error rendering QR Code: ${err}`, ToastIcon.ERROR); + } + else { + console.log(`Rendered QR Code`); + } + }); + + onQRCodeRendered(); +} diff --git a/receivers/common/web/main/common.css b/receivers/common/web/main/common.css index 69ea3c1..4f2b1b1 100644 --- a/receivers/common/web/main/common.css +++ b/receivers/common/web/main/common.css @@ -25,7 +25,6 @@ body, html { text-align: center; background-color: rgba(20, 20, 20, 0.5); - padding: 25px; border-radius: 10px; border: 1px solid #2E2E2E; scrollbar-width: thin; @@ -34,8 +33,6 @@ body, html { .card-title { font-weight: 700; - line-height: 24px; - margin: 10px; } .card-title-separator { @@ -46,8 +43,6 @@ body, html { } .iconSize { - width: 32px; - height: 32px; background-size: cover; } @@ -69,10 +64,8 @@ body, html { align-items: center; justify-content: center; color: white; - gap: 15vw; font-family: InterVariable; - font-size: 28px; font-style: normal; font-weight: 400; } @@ -89,7 +82,6 @@ body, html { #title-text { font-family: Outfit; - font-size: 140px; font-weight: 800; text-align: center; @@ -100,16 +92,11 @@ body, html { } #title-icon { - width: 124px; - height: 124px; - background-image: url(../assets/icons/app/icon.svg); background-size: cover; - margin-right: 25px; } #connection-status { - padding: 25px; text-align: center; } @@ -130,7 +117,6 @@ body, html { width: 84px; height: 84px; margin: auto; - margin-top: 20px; background-image: url(../assets/icons/app/error.svg); background-size: cover; @@ -150,7 +136,6 @@ body, html { #connection-information-loading-text { width: auto; height: auto; - margin: 10px 20px; } #connection-information { @@ -161,16 +146,13 @@ body, html { } #scan-to-connect { - margin-top: 20px; font-weight: bold; } #qr-code { display: flex; - margin: 20px auto; flex-direction: column; align-items: center; - padding: 20px; background-color: white; } @@ -200,11 +182,6 @@ body, html { align-items: start; } -.ip-entry-text { - margin-top: 4px; - margin-bottom: 4px; -} - .ip-wired-icon { background-image: url(../assets/icons/app/network-light.svg); } @@ -233,10 +210,8 @@ body, html { color: #666666; position: absolute; bottom: 0; - margin-bottom: 20px; font-family: InterVariable; - font-size: 24px; font-style: normal; font-weight: 400; } @@ -244,15 +219,11 @@ body, html { .lds-ring { display: inline-block; position: relative; - width: 120px; - height: 120px; } .lds-ring div { box-sizing: border-box; display: block; position: absolute; - width: 104px; - height: 104px; margin: 8px; border: 8px solid #fff; border-radius: 50%; @@ -281,8 +252,6 @@ body, html { /* display: inline-block; */ display: none; position: relative; - width: 104px; - height: 104px; margin: 18px; padding: 10px; @@ -381,3 +350,418 @@ body, html { opacity: 0; } } + +/* Display scaling (Minimum supported resolution is 960x540) */ +@media only screen and ((min-width: 2560px) or (min-height: 1440px)) { + .card { + padding: 25px; + } + + .card-title { + line-height: 24px; + margin: 10px; + } + + .card-title-separator { + margin: 5px 0px; + margin-top: 10px; + } + + .iconSize { + width: 48px; + height: 48px; + } + + #overlay { + gap: 15vw; + font-size: 32px; + } + + #title-text { + font-size: 180px; + } + + #title-icon { + width: 164px; + height: 164px; + margin-right: 30px; + } + + #connection-status { + padding: 35px; + } + + #connection-error-icon { + margin-top: 20px; + } + + #connection-information-loading-text { + margin: 20px; + } + + #scan-to-connect { + margin-top: 20px; + } + + #qr-code { + width: 384px; + height: 384px; + margin: 25px auto; + padding: 20px; + } + + #connection-details-separator { + margin-top: 15px; + } + + #ips { + margin-top: 20px; + gap: 15px; + } + + .ip-entry-text { + margin-top: 4.5px; + margin-bottom: 4.5px; + } + + #window-can-be-closed { + margin-bottom: 20px; + font-size: 28px; + } + + .lds-ring { + width: 140px; + height: 140px; + } + .lds-ring div { + width: 124px; + height: 124px; + } + + #connection-check { + width: 124px; + height: 124px; + } + + #toast-notification { + padding: 16px; + top: -225px; + } + + #toast-icon { + width: 108px; + height: 108px; + margin: 5px 10px; + } + + #toast-text { + font-size: 32px; + } +} + +@media only screen and ((max-width: 2559px) or (max-height: 1439px)) { + .card { + padding: 25px; + } + + .card-title { + line-height: 24px; + margin: 10px; + } + + .card-title-separator { + margin: 3px 0px; + } + + .iconSize { + width: 48px; + height: 48px; + } + + #overlay { + gap: 15vw; + font-size: 28px; + } + + #title-text { + font-size: 140px; + } + + #title-icon { + width: 124px; + height: 124px; + margin-right: 25px; + } + + #connection-status { + padding: 25px; + } + + #connection-error-icon { + margin-top: 20px; + } + + #connection-information-loading-text { + margin: 20px; + } + + #scan-to-connect { + margin-top: 20px; + } + + #qr-code { + width: 256px; + height: 256px; + margin: 20px auto; + padding: 16px; + } + + #connection-details-separator { + margin-top: 15px; + } + + #ips { + margin-top: 20px; + gap: 15px; + } + + .ip-entry-text { + margin-top: 7px; + margin-bottom: 7px; + } + + #window-can-be-closed { + margin-bottom: 20px; + font-size: 24px; + } + + .lds-ring { + width: 120px; + height: 120px; + } + .lds-ring div { + width: 104px; + height: 104px; + } + + #connection-check { + width: 104px; + height: 104px; + } + + #toast-notification { + padding: 16px; + top: -200px; + } + + #toast-icon { + width: 88px; + height: 88px; + margin: 5px 10px; + } + + #toast-text { + font-size: 28px; + } +} + +@media only screen and ((max-width: 1919px) or (max-height: 1079px)) { + .card { + padding: 15px; + } + + .card-title { + line-height: 20px; + margin: 5px; + margin-bottom: 10px; + } + + .card-title-separator { + margin: 3px 0px; + } + + .iconSize { + width: 32px; + height: 32px; + } + + #overlay { + gap: 12.5vw; + font-size: 20px; + } + + #title-text { + font-size: 100px; + } + + #title-icon { + width: 84px; + height: 84px; + margin-right: 15px; + } + + #connection-status { + padding: 15px; + } + + #connection-error-icon { + margin-top: 10px; + } + + #connection-information-loading-text { + margin: 10px; + } + + #scan-to-connect { + margin-top: 10px; + } + + #qr-code { + width: 192px; + height: 192px; + margin: 15px auto; + padding: 12px; + } + + #ips { + margin-top: 10px; + } + + .ip-entry-text { + margin-top: 4px; + margin-bottom: 4px; + } + + #window-can-be-closed { + margin-bottom: 15px; + font-size: 18px; + } + + .lds-ring { + width: 100px; + height: 100px; + } + .lds-ring div { + width: 84px; + height: 84px; + } + + #connection-check { + width: 84px; + height: 84px; + } + + #toast-notification { + padding: 12px; + top: -150px; + } + + #toast-icon { + width: 68px; + height: 68px; + } + + #toast-text { + font-size: 20px; + } +} + +@media only screen and ((max-width: 1279px) or (max-height: 719px)) { + .card { + padding: 15px; + } + + .card-title { + line-height: 18px; + margin: 5px; + } + + .card-title-separator { + margin: 3px 0px; + } + + .iconSize { + width: 24px; + height: 24px; + } + + #overlay { + gap: 10vw; + font-size: 18px; + } + + #title-text { + font-size: 80px; + } + + #title-icon { + width: 64px; + height: 64px; + margin-right: 15px; + } + + #connection-status { + padding: 15px; + } + + #connection-error-icon { + margin-top: 10px; + } + + #connection-information-loading-text { + margin: 10px; + } + + #scan-to-connect { + margin-top: 10px; + } + + #qr-code { + width: 128px; + height: 128px; + margin: 15px auto; + padding: 8px; + } + + #ips { + margin-top: 10px; + } + + .ip-entry-text { + margin-top: 1.5px; + margin-bottom: 1.5px; + } + + #window-can-be-closed { + margin-bottom: 10px; + font-size: 16px; + } + + .lds-ring { + width: 80px; + height: 80px; + } + .lds-ring div { + width: 64px; + height: 64px; + } + + #connection-check { + width: 64px; + height: 64px; + } + + #toast-notification { + padding: 8px; + top: -125px; + } + + #toast-icon { + width: 48px; + height: 48px; + } + + #toast-text { + font-size: 18px; + } +} diff --git a/receivers/common/web/player/common.css b/receivers/common/web/player/common.css index 087b8f5..79fec0c 100644 --- a/receivers/common/web/player/common.css +++ b/receivers/common/web/player/common.css @@ -405,11 +405,10 @@ body { position: absolute; bottom: 80px; right: 60px; - height: calc(55vh); max-height: 368px; background-color: #141414; - padding: 12px; + padding: 8px; border-radius: 10px; border: 1px solid #2E2E2E; scrollbar-width: thin; @@ -427,11 +426,13 @@ body { font-weight: 700; line-height: 24px; margin: 10px; + user-select: none; } .speedMenuEntry { display: flex; - padding: 10px 15px; + padding: 5px 10px; + user-select: none; } .speedMenuEntry:hover { diff --git a/receivers/electron/src/Main.ts b/receivers/electron/src/Main.ts index 3a6bc31..f798c71 100644 --- a/receivers/electron/src/Main.ts +++ b/receivers/electron/src/Main.ts @@ -155,8 +155,6 @@ export class Main { Main.playerWindow = new BrowserWindow({ fullscreen: true, autoHideMenuBar: true, - minWidth: 515, - minHeight: 290, icon: path.join(__dirname, 'icon512.png'), webPreferences: { preload: path.join(__dirname, 'player/preload.js') @@ -295,8 +293,6 @@ export class Main { fullscreen: Main.startFullscreen, autoHideMenuBar: true, icon: path.join(__dirname, 'icon512.png'), - minWidth: 1100, - minHeight: 800, webPreferences: { preload: path.join(__dirname, 'main/preload.js') } diff --git a/receivers/electron/src/main/index.html b/receivers/electron/src/main/index.html index 5fd566f..28e9c20 100644 --- a/receivers/electron/src/main/index.html +++ b/receivers/electron/src/main/index.html @@ -3,6 +3,7 @@