diff --git a/.env.template b/.env.template index d27fac38..13f4e663 100644 --- a/.env.template +++ b/.env.template @@ -1,5 +1,5 @@ # ==================================================== -# MiroTalk P2P v.1.7.45 - Environment Configuration +# MiroTalk P2P v.1.7.46 - Environment Configuration # ==================================================== # App environment diff --git a/app/src/config.template.js b/app/src/config.template.js index df463c92..a1577347 100644 --- a/app/src/config.template.js +++ b/app/src/config.template.js @@ -2,7 +2,7 @@ /** * ============================================== - * MiroTalk P2P v.1.7.45 - Configuration File + * MiroTalk P2P v.1.7.46 - Configuration File * ============================================== * * This file is the central configuration source. diff --git a/app/src/server.js b/app/src/server.js index 58a6d464..b81efdbd 100755 --- a/app/src/server.js +++ b/app/src/server.js @@ -45,7 +45,7 @@ dependencies: { * @license For commercial use or closed source, contact us at license.mirotalk@gmail.com or purchase directly from CodeCanyon * @license CodeCanyon: https://codecanyon.net/item/mirotalk-p2p-webrtc-realtime-video-conferences/38376661 * @author Miroslav Pejic - miroslav.pejic.85@gmail.com - * @version 1.7.45 + * @version 1.7.46 * */ @@ -354,13 +354,22 @@ const views = { activeRooms: path.join(__dirname, '../../', 'public/views/activeRooms.html'), customizeRoom: path.join(__dirname, '../../', 'public/views/customizeRoom.html'), stunTurn: path.join(__dirname, '../../', 'public/views/testStunTurn.html'), + waitingRoom: path.join(__dirname, '../../', 'public/views/waitingRoom.html'), }; // Branding configuration const brandHtmlInjection = config.brand?.htmlInjection ?? true; // File to cache and inject custom HTML data like OG tags and any other elements. -const filesPath = [views.landing, views.newCall, views.client, views.login, views.activeRooms, views.customizeRoom]; +const filesPath = [ + views.landing, + views.newCall, + views.client, + views.login, + views.activeRooms, + views.customizeRoom, + views.waitingRoom, +]; const htmlInjector = new HtmlInjector(filesPath, config.brand || null); const channels = {}; // collect channels @@ -682,10 +691,11 @@ app.get('/join/:roomId', function (req, res) { if (allowRoomAccess) { htmlInjector.injectHtml(views.client, res); + } else if (!OIDC.enabled && hostCfg.protected) { + // Guest arrived before host opened the room — show waiting page + htmlInjector.injectHtml(views.waitingRoom, res); } else { - !OIDC.enabled && hostCfg.protected - ? res.redirect('/login?room=' + encodeURIComponent(roomId)) - : res.redirect('/'); + res.redirect('/'); } }); diff --git a/package-lock.json b/package-lock.json index 36d207fb..3c537fe8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "mirotalk", - "version": "1.7.45", + "version": "1.7.46", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "mirotalk", - "version": "1.7.45", + "version": "1.7.46", "license": "AGPL-3.0", "dependencies": { "@mattermost/client": "11.4.0", diff --git a/package.json b/package.json index e8f53ba8..4fad6765 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mirotalk", - "version": "1.7.45", + "version": "1.7.46", "description": "A free WebRTC browser-based video call", "main": "server.js", "scripts": { diff --git a/public/css/waitingRoom.css b/public/css/waitingRoom.css new file mode 100644 index 00000000..a898fa35 --- /dev/null +++ b/public/css/waitingRoom.css @@ -0,0 +1,135 @@ +/* Waiting Room Card */ +.waiting-card { + max-width: 460px; + margin: 0 auto; + padding: 48px 36px 40px; + background: + radial-gradient(900px circle at 20% 15%, rgba(70, 120, 249, 0.12) 0%, rgba(70, 120, 249, 0) 55%), + radial-gradient(700px circle at 80% 85%, rgba(70, 120, 249, 0.08) 0%, rgba(70, 120, 249, 0) 52%), + linear-gradient(135deg, rgba(0, 0, 0, 0.95) 60%, rgba(70, 120, 249, 0.15) 100%); + border: 1px solid rgba(255, 255, 255, 0.06); + border-radius: 16px; + box-shadow: + 0 12px 40px rgba(0, 0, 0, 0.5), + inset 0 1px 0 rgba(255, 255, 255, 0.04); + text-align: center; +} + +/* Icon */ +.waiting-icon { + width: 64px; + height: 64px; + margin: 0 auto 24px; + border-radius: 50%; + background: linear-gradient(135deg, rgba(70, 120, 249, 0.2), rgba(70, 120, 249, 0.05)); + border: 1px solid rgba(70, 120, 249, 0.25); + display: flex; + align-items: center; + justify-content: center; + animation: iconPulse 3s ease-in-out infinite; +} +.waiting-icon i { + font-size: 24px; + color: #4678f9; +} +@keyframes iconPulse { + 0%, + 100% { + box-shadow: 0 0 0 0 rgba(70, 120, 249, 0.3); + } + 50% { + box-shadow: 0 0 0 12px rgba(70, 120, 249, 0); + } +} + +/* Title */ +.waiting-title { + font-size: 24px; + font-weight: 600; + color: #f9faff; + margin: 0 0 8px; +} + +/* Description */ +.waiting-description { + color: #9ca9b3; + font-size: 15px; + line-height: 1.6; + margin: 0 0 28px; +} + +/* Spinner */ +.waiting-spinner { + display: flex; + justify-content: center; + gap: 8px; + margin: 0 0 20px; +} +.waiting-spinner-dot { + width: 10px; + height: 10px; + background-color: #4678f9; + border-radius: 50%; + animation: bounce 1.4s ease-in-out infinite both; +} +.waiting-spinner-dot:nth-child(1) { + animation-delay: -0.32s; +} +.waiting-spinner-dot:nth-child(2) { + animation-delay: -0.16s; +} +@keyframes bounce { + 0%, + 80%, + 100% { + transform: scale(0.4); + opacity: 0.4; + } + 40% { + transform: scale(1); + opacity: 1; + } +} + +/* Status */ +.waiting-status { + color: #6b7a85; + font-size: 13px; + margin: 0 0 6px; + min-height: 20px; + transition: color 0.3s ease; +} +.waiting-status.ready { + color: #2dce89; +} + +/* Divider */ +.waiting-divider { + border: none; + border-top: 1px solid rgba(255, 255, 255, 0.06); + margin: 24px 0 20px; +} + +/* Host link */ +.host-login-link { + color: #6b7a85; + font-size: 13px; + margin: 0; +} +.host-login-link a { + color: #4678f9; + text-decoration: none; + font-weight: 600; + transition: color 0.2s ease; +} +.host-login-link a:hover { + color: #5a8aff; + text-decoration: underline; +} + +/* Layout */ +@media (min-width: 641px) { + .hero .split-wrap .split-item { + min-height: 492px; + } +} diff --git a/public/js/brand.js b/public/js/brand.js index e22184ce..1eac3a67 100644 --- a/public/js/brand.js +++ b/public/js/brand.js @@ -79,7 +79,7 @@ let brand = { }, about: { imageUrl: '../images/mirotalk-logo.gif', - title: 'WebRTC P2P v1.7.45', + title: 'WebRTC P2P v1.7.46', html: `