Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F117840631
D2299.1775308644.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Authored By
Unknown
Size
11 KB
Referenced Files
None
Subscribers
None
D2299.1775308644.diff
View Options
diff --git a/src/resources/js/meet/app.js b/src/resources/js/meet/app.js
--- a/src/resources/js/meet/app.js
+++ b/src/resources/js/meet/app.js
@@ -41,6 +41,7 @@
let containerHeight
let chatCount = 0
let volumeElement
+ let publishersContainer
let subscribersContainer
let scrollStop
@@ -107,6 +108,10 @@
* onMediaSetup - Called when user clicks the Media setup button
*/
function joinRoom(data) {
+ // Create a container for subscribers and publishers
+ publishersContainer = $('<div id="meet-publishers">').appendTo(container).get(0)
+ subscribersContainer = $('<div id="meet-subscribers">').appendTo(container).get(0)
+
resize();
volumeMeterStop()
@@ -115,11 +120,6 @@
// avatar: undefined // avatar image
}
- // Create a container for subscribers
- if (!subscribersContainer) {
- subscribersContainer = $('<div id="meet-subscribers">').appendTo(container).get(0)
- }
-
// TODO: Make sure all supported callbacks exist, so we don't have to check
// their existence everywhere anymore
@@ -185,6 +185,12 @@
// Subscribe to the Stream to receive it
let subscriber = session.subscribe(event.stream, metadata.element, props);
+ Object.assign(metadata, {
+ audioActive: event.stream.audioActive,
+ videoActive: event.stream.videoActive,
+ videoDimensions: event.stream.videoDimensions
+ })
+
subscriber.on('videoElementCreated', event => {
$(event.element).prop({
tabindex: -1
@@ -193,9 +199,6 @@
resize()
})
- metadata.audioActive = event.stream.audioActive
- metadata.videoActive = event.stream.videoActive
-
// Update the wrapper controls/status
participantUpdate(metadata.element, metadata)
})
@@ -213,7 +216,12 @@
if (metadata) {
metadata[event.changedProperty] = event.newValue
- participantUpdate(metadata.element, metadata)
+
+ if (event.changedProperty == 'videoDimensions') {
+ resize()
+ } else {
+ participantUpdate(metadata.element, metadata)
+ }
}
})
@@ -991,6 +999,8 @@
* @param content Optional content to prepend to the element
*/
function publisherCreate(params, content) {
+ let isScreen = params.role & Roles.SCREEN
+
// Create the element
let wrapper = $(
'<div class="meet-video">'
@@ -1015,6 +1025,10 @@
wrapper.prepend(content)
}
+ if (isScreen) {
+ wrapper.addClass('screen')
+ }
+
if (params.isSelf) {
if (sessionData.onMediaSetup) {
wrapper.find('.link-setup').removeClass('hidden')
@@ -1055,7 +1069,9 @@
// Remove the subscriber element, if exists
$('#subscriber-' + params.connectionId).remove()
- return wrapper[params.isSelf ? 'prependTo' : 'appendTo'](container)
+ let prio = params.isSelf || (isScreen && !$(publishersContainer).children('.screen').length)
+
+ return wrapper[prio ? 'prependTo' : 'appendTo'](publishersContainer)
.attr('id', 'publisher-' + params.connectionId)
.get(0)
}
@@ -1357,12 +1373,8 @@
* Window onresize event handler (updates room layout)
*/
function resize() {
- containerWidth = container.offsetWidth
- containerHeight = container.offsetHeight
-
- if (subscribersContainer) {
- containerHeight -= subscribersContainer.offsetHeight
- }
+ containerWidth = publishersContainer.offsetWidth
+ containerHeight = publishersContainer.offsetHeight
updateLayout()
$(container).parent()[window.screen.width <= 768 ? 'addClass' : 'removeClass']('mobile')
@@ -1372,12 +1384,59 @@
* Update the room "matrix" layout
*/
function updateLayout() {
- let numOfVideos = $(container).find('.meet-video').length
+ let publishers = $(publishersContainer).find('.meet-video')
+ let numOfVideos = publishers.length
+
if (!numOfVideos) {
return
}
- let css, rows, cols, height
+ let css, rows, cols, height, padding = 0
+
+ // Make the first screen sharing tile big
+ let screenVideo = publishers.filter('.screen').find('video').get(0)
+
+ if (screenVideo) {
+ let element = screenVideo.parentNode
+ let connId = element.id.replace(/^publisher-/, '')
+ let connection = connections[connId]
+
+ // We know the shared screen video dimensions, we can calculate
+ // width/height of the tile in the matrix
+ if (connection && connection.videoDimensions) {
+ let screenWidth = connection.videoDimensions.width
+ let screenHeight = containerHeight
+
+ // TODO: When the shared window is minimized the width/height is set to 1 (or 2)
+ // - at least on my system. We might need to handle this case nicer. Right now
+ // it create a 1-2px line on the left of the matrix - not a big issue.
+ // TODO: Make the 0.666 factor bigger for wide screen and small number of participants?
+ let maxWidth = Math.ceil(containerWidth * 0.666)
+
+ if (screenWidth > maxWidth) {
+ screenWidth = maxWidth
+ }
+
+ // Set the tile position and size
+ $(element).css({
+ width: screenWidth + 'px',
+ height: screenHeight + 'px',
+ position: 'absolute',
+ top: 0,
+ left: 0
+ })
+
+ padding = screenWidth + 'px'
+
+ // Now the estate for the rest of participants is what's left on the right side
+ containerWidth -= screenWidth
+ publishers = publishers.not(element)
+ numOfVideos -= 1
+ }
+ }
+
+ // Compensate the shared screen estate with a padding
+ $(publishersContainer).css('padding-left', padding)
const factor = containerWidth / containerHeight
@@ -1420,27 +1479,12 @@
// console.log('factor=' + factor, 'num=' + numOfVideos, 'cols = '+cols, 'rows=' + rows);
- height = containerHeight / rows
- css = {
- width: (100 / cols) + '%',
+ // Update all tiles (except the main shared screen) in the matrix
+ publishers.css({
+ width: (containerWidth / cols) + 'px',
// Height must be in pixels to make object-fit:cover working
- height: height + 'px'
- }
-
- // Update the matrix
- $(container).find('.meet-video').css(css)
- /*
- .each((idx, elem) => {
- let video = $(elem).children('video')[0]
-
- if (video && video.videoWidth && video.videoHeight && video.videoWidth > video.videoHeight) {
- // Set max-width to keep the original aspect ratio in cases
- // when there's enough room to display the element
- let maxWidth = height * video.videoWidth / video.videoHeight
- $(elem).css('max-width', maxWidth)
- }
- })
- */
+ height: (containerHeight / rows) + 'px'
+ })
}
/**
diff --git a/src/resources/themes/meet.scss b/src/resources/themes/meet.scss
--- a/src/resources/themes/meet.scss
+++ b/src/resources/themes/meet.scss
@@ -65,6 +65,12 @@
}
}
+ &.screen video {
+ // For shared screen videos we use the original aspect ratio
+ object-fit: scale-down;
+ background: none;
+ }
+
&.fullscreen {
video {
// We don't want the video to be cut in fullscreen
@@ -195,42 +201,20 @@
overflow: hidden;
}
-#meet-session {
- display: flex;
- justify-content: center;
- flex-wrap: wrap;
- flex: 1;
- position: relative; // for #meet-subscribers positioning
+#meet-publishers {
+ height: 100%;
+ position: relative;
}
#meet-subscribers {
- display: flex;
- flex-wrap: wrap;
- order: 999;
padding: 0.15em;
- width: 100%;
overflow-y: auto;
- &:empty {
- display: none;
- }
-
.meet-subscriber {
margin: 0.15em;
max-width: calc(25% - 0.4em);
}
- // when the subscribers list is the only child this means
- // there's no publisher videos in the room yet
- &:only-child {
- justify-content: center;
- align-content: center;
- }
-
- &:not(:only-child) {
- max-height: 30%;
- }
-
// Language interpreters will be displayed as subscribers, but will have still
// the video element that we will hide
video {
@@ -238,6 +222,37 @@
}
}
+#meet-session {
+ display: flex;
+ flex-direction: column;
+ flex: 1;
+ overflow: hidden;
+
+ & > div {
+ display: flex;
+ flex-wrap: wrap;
+ width: 100%;
+
+ &:empty {
+ display: none;
+ }
+ }
+
+ #meet-publishers:empty {
+ & + #meet-subscribers {
+ justify-content: center;
+ align-content: center;
+ flex: 1;
+ }
+ }
+
+ #meet-publishers:not(:empty) {
+ & + #meet-subscribers {
+ max-height: 30%;
+ }
+ }
+}
+
#meet-chat {
width: 0;
display: none;
diff --git a/src/tests/Browser/Meet/RoomControlsTest.php b/src/tests/Browser/Meet/RoomControlsTest.php
--- a/src/tests/Browser/Meet/RoomControlsTest.php
+++ b/src/tests/Browser/Meet/RoomControlsTest.php
@@ -362,7 +362,7 @@
->assertToolbarButtonState('screen', RoomPage::BUTTON_ACTIVE | RoomPage::BUTTON_ENABLED);
$guest
- ->whenAvailable('div.meet-video:nth-child(3)', function (Browser $browser) {
+ ->whenAvailable('div.meet-video.screen', function (Browser $browser) {
$browser->waitFor('video')
->assertSeeIn('.meet-nickname', 'john')
->assertVisible('.controls button.link-fullscreen')
diff --git a/src/tests/Browser/Meet/RoomModeratorTest.php b/src/tests/Browser/Meet/RoomModeratorTest.php
--- a/src/tests/Browser/Meet/RoomModeratorTest.php
+++ b/src/tests/Browser/Meet/RoomModeratorTest.php
@@ -78,7 +78,7 @@
->assertMissing('@session div.meet-subscriber:not(.self) svg.user') // owner
->assertVisible('@session div.meet-subscriber:not(.self) svg.moderator') // owner
->click('@session div.meet-subscriber.self .meet-nickname')
- ->whenAvailable('@session .dropdown-menu', function (Browser $browser) {
+ ->whenAvailable('@session div.meet-subscriber.self .dropdown-menu', function (Browser $browser) {
$browser->assertMissing('.permissions');
})
->click('@session div.meet-subscriber:not(.self) .meet-nickname')
@@ -101,7 +101,7 @@
->assertMissing('@session div.meet-subscriber.self svg.user') // self
->assertVisible('@session div.meet-subscriber.self svg.moderator') // self
->click('@session div.meet-subscriber.self .meet-nickname')
- ->whenAvailable('@session .dropdown-menu', function (Browser $browser) {
+ ->whenAvailable('@session div.meet-subscriber.self .dropdown-menu', function (Browser $browser) {
$browser->assertChecked('.action-role-moderator input')
->assertDisabled('.action-role-moderator input');
})
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Apr 4, 1:17 PM (19 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18806577
Default Alt Text
D2299.1775308644.diff (11 KB)
Attached To
Mode
D2299: Meet: Display shared screen bigger
Attached
Detach File
Event Timeline