Changeset View
Changeset View
Standalone View
Standalone View
src/resources/js/meet/app.js
Show First 20 Lines • Show All 715 Lines • ▼ Show 20 Lines | function Meet(container) | ||||
* Update participant connection state | * Update participant connection state | ||||
*/ | */ | ||||
function connectionUpdate(data) { | function connectionUpdate(data) { | ||||
let conn = connections[data.connectionId] | let conn = connections[data.connectionId] | ||||
// It's me | // It's me | ||||
if (session.connection.connectionId == data.connectionId) { | if (session.connection.connectionId == data.connectionId) { | ||||
const rolePublisher = data.role && data.role & Roles.PUBLISHER | const rolePublisher = data.role && data.role & Roles.PUBLISHER | ||||
const roleModerator = data.role && data.role & Roles.MODERATOR | |||||
const isPublisher = sessionData.role & Roles.PUBLISHER | const isPublisher = sessionData.role & Roles.PUBLISHER | ||||
const isModerator = sessionData.role & Roles.MODERATOR | |||||
// Inform the vue component, so it can update some UI controls | // Inform the vue component, so it can update some UI controls | ||||
let update = () => { | let update = () => { | ||||
if (sessionData.onSessionDataUpdate) { | if (sessionData.onSessionDataUpdate) { | ||||
sessionData.onSessionDataUpdate(data) | sessionData.onSessionDataUpdate(data) | ||||
} | } | ||||
} | } | ||||
// demoted to a subscriber | // demoted to a subscriber | ||||
if ('role' in data && isPublisher && !rolePublisher) { | if ('role' in data && isPublisher && !rolePublisher) { | ||||
session.unpublish(publisher) | session.unpublish(publisher) | ||||
// FIXME: There's a reference in OpenVidu to a video element that should not | // FIXME: There's a reference in OpenVidu to a video element that should not | ||||
// exist anymore. It causes issues when we try to do publish/unpublish | // exist anymore. It causes issues when we try to do publish/unpublish | ||||
// sequence multiple times in a row. So, we're clearing the reference here. | // sequence multiple times in a row. So, we're clearing the reference here. | ||||
let videos = publisher.stream.streamManager.videos | let videos = publisher.stream.streamManager.videos | ||||
publisher.stream.streamManager.videos = videos.filter(video => video.video.parentNode != null) | publisher.stream.streamManager.videos = videos.filter(video => video.video.parentNode != null) | ||||
} | } | ||||
// merge the changed data into internal session metadata object | // merge the changed data into internal session metadata object | ||||
Object.keys(data).forEach(key => { sessionData[key] = data[key] }) | Object.keys(data).forEach(key => { sessionData[key] = data[key] }) | ||||
// update the participant element | // update the participant element | ||||
sessionData.element = participantUpdate(sessionData.element, sessionData) | sessionData.element = participantUpdate(sessionData.element, sessionData) | ||||
// promoted/demoted to/from a moderator | |||||
if ('role' in data) { | |||||
if ((!isModerator && roleModerator) || (isModerator && !roleModerator)) { | |||||
// Update all participants, to enable/disable the popup menu | |||||
Object.keys(connections).forEach(key => { | |||||
const conn = connections[key] | |||||
participantUpdate(conn.element, conn) | |||||
}) | |||||
} | |||||
} | |||||
// promoted to a publisher | // promoted to a publisher | ||||
if ('role' in data && !isPublisher && rolePublisher) { | if ('role' in data && !isPublisher && rolePublisher) { | ||||
publisher.createVideoElement(sessionData.element, 'PREPEND') | publisher.createVideoElement(sessionData.element, 'PREPEND') | ||||
session.publish(publisher).then(() => { | session.publish(publisher).then(() => { | ||||
data.audioActive = publisher.stream.audioActive | data.audioActive = publisher.stream.audioActive | ||||
data.videoActive = publisher.stream.videoActive | data.videoActive = publisher.stream.videoActive | ||||
update() | update() | ||||
}) | }) | ||||
▲ Show 20 Lines • Show All 132 Lines • ▼ Show 20 Lines | function Meet(container) | ||||
* | * | ||||
* @param wrapper The wrapper element | * @param wrapper The wrapper element | ||||
* @param params Connection metadata/params | * @param params Connection metadata/params | ||||
*/ | */ | ||||
function participantUpdate(wrapper, params) { | function participantUpdate(wrapper, params) { | ||||
const element = $(wrapper) | const element = $(wrapper) | ||||
const isModerator = sessionData.role & Roles.MODERATOR | const isModerator = sessionData.role & Roles.MODERATOR | ||||
const isSelf = session.connection.connectionId == params.connectionId | const isSelf = session.connection.connectionId == params.connectionId | ||||
const rolePublisher = params.role & Roles.PUBLISHER | |||||
const roleModerator = params.role & Roles.MODERATOR | |||||
const roleScreen = params.role & Roles.SCREEN | |||||
const roleOwner = params.role & Roles.OWNER | |||||
// Handle publisher-to-subscriber and subscriber-to-publisher change | // Handle publisher-to-subscriber and subscriber-to-publisher change | ||||
if ('role' in params && !(params.role & Roles.SCREEN)) { | if (!roleScreen) { | ||||
const rolePublisher = params.role & Roles.PUBLISHER | |||||
const isPublisher = element.is('.meet-video') | const isPublisher = element.is('.meet-video') | ||||
if ((rolePublisher && !isPublisher) || (!rolePublisher && isPublisher)) { | if ((rolePublisher && !isPublisher) || (!rolePublisher && isPublisher)) { | ||||
element.remove() | element.remove() | ||||
return participantCreate(params) | return participantCreate(params) | ||||
} | } | ||||
element.find('.action-role-publisher input').prop('checked', params.role & Roles.PUBLISHER) | |||||
} | } | ||||
if ('audioActive' in params) { | if ('audioActive' in params) { | ||||
element.find('.status-audio')[params.audioActive ? 'addClass' : 'removeClass']('hidden') | element.find('.status-audio')[params.audioActive ? 'addClass' : 'removeClass']('hidden') | ||||
} | } | ||||
if ('videoActive' in params) { | if ('videoActive' in params) { | ||||
element.find('.status-video')[params.videoActive ? 'addClass' : 'removeClass']('hidden') | element.find('.status-video')[params.videoActive ? 'addClass' : 'removeClass']('hidden') | ||||
} | } | ||||
if ('nickname' in params) { | if ('nickname' in params) { | ||||
element.find('.meet-nickname > .content').text(params.nickname) | element.find('.meet-nickname > .content').text(params.nickname) | ||||
} | } | ||||
if (isSelf) { | if (isSelf) { | ||||
element.addClass('self') | element.addClass('self') | ||||
} | } | ||||
if (isModerator) { | if (isModerator) { | ||||
element.addClass('moderated') | element.addClass('moderated') | ||||
} | } | ||||
element.find('.dropdown-menu')[isSelf || isModerator ? 'removeClass' : 'addClass']('hidden') | const withPerm = isModerator && !roleScreen && !(roleOwner && !isSelf); | ||||
element.find('.permissions')[isModerator ? 'removeClass' : 'addClass']('hidden') | const withMenu = isSelf || (isModerator && !roleOwner) | ||||
if ('role' in params && params.role & Roles.SCREEN) { | let elements = { | ||||
element.find('.permissions').addClass('hidden') | '.dropdown-menu': withMenu, | ||||
'.permissions': withPerm, | |||||
'svg.moderator': roleModerator, | |||||
'svg.user': !roleModerator | |||||
} | } | ||||
Object.keys(elements).forEach(key => { | |||||
element.find(key)[elements[key] ? 'removeClass' : 'addClass']('hidden') | |||||
}) | |||||
element.find('.action-role-publisher input').prop('checked', rolePublisher) | |||||
element.find('.action-role-moderator input').prop('checked', roleModerator) | |||||
.prop('disabled', roleOwner) | |||||
return wrapper | return wrapper | ||||
} | } | ||||
/** | /** | ||||
* Create a tag-like element for a subscriber participant | * Create a tag-like element for a subscriber participant | ||||
* | * | ||||
* @param params Connection metadata/params | * @param params Connection metadata/params | ||||
*/ | */ | ||||
Show All 14 Lines | function Meet(container) | ||||
* @param object params Connection metadata/params | * @param object params Connection metadata/params | ||||
*/ | */ | ||||
function nicknameWidget(params) { | function nicknameWidget(params) { | ||||
// Create the element | // Create the element | ||||
let element = $( | let element = $( | ||||
'<div class="dropdown">' | '<div class="dropdown">' | ||||
+ '<a href="#" class="meet-nickname btn" aria-haspopup="true" aria-expanded="false" role="button">' | + '<a href="#" class="meet-nickname btn" aria-haspopup="true" aria-expanded="false" role="button">' | ||||
+ '<span class="content"></span>' | + '<span class="content"></span>' | ||||
+ '<span class="icon">' + svgIcon('user') + '</span>' | + '<span class="icon">' | ||||
+ svgIcon('user', null, 'user') | |||||
+ svgIcon('crown', null, 'moderator hidden') | |||||
+ '</span>' | |||||
+ '</a>' | + '</a>' | ||||
+ '<div class="dropdown-menu">' | + '<div class="dropdown-menu">' | ||||
+ '<a class="dropdown-item action-nickname" href="#">Nickname</a>' | + '<a class="dropdown-item action-nickname" href="#">Nickname</a>' | ||||
+ '<a class="dropdown-item action-dismiss" href="#">Dismiss</a>' | + '<a class="dropdown-item action-dismiss" href="#">Dismiss</a>' | ||||
+ '<div class="dropdown-divider permissions"></div>' | + '<div class="dropdown-divider permissions"></div>' | ||||
+ '<div class="permissions">' | + '<div class="permissions">' | ||||
+ '<h6 class="dropdown-header">Permissions</h6>' | + '<h6 class="dropdown-header">Permissions</h6>' | ||||
+ '<label class="dropdown-item action-role-publisher custom-control custom-switch">' | + '<label class="dropdown-item action-role-publisher custom-control custom-switch">' | ||||
+ '<input type="checkbox" class="custom-control-input">' | + '<input type="checkbox" class="custom-control-input">' | ||||
+ ' <span class="custom-control-label">Audio & Video publishing</span>' | + ' <span class="custom-control-label">Audio & Video publishing</span>' | ||||
+ '</label>' | + '</label>' | ||||
//+ '<label class="dropdown-item action-role-moderator custom-control custom-switch">' | + '<label class="dropdown-item action-role-moderator custom-control custom-switch">' | ||||
// + '<input type="checkbox" class="custom-control-input">' | + '<input type="checkbox" class="custom-control-input">' | ||||
// + ' <span class="custom-control-label">Moderation</span>' | + ' <span class="custom-control-label">Moderation</span>' | ||||
//+ '</label>' | + '</label>' | ||||
+ '</div>' | + '</div>' | ||||
+ '</div>' | + '</div>' | ||||
+ '</div>' | + '</div>' | ||||
) | ) | ||||
let nickname = element.find('.meet-nickname') | let nickname = element.find('.meet-nickname') | ||||
.addClass('btn btn-outline-' + (params.isSelf ? 'primary' : 'secondary')) | .addClass('btn btn-outline-' + (params.isSelf ? 'primary' : 'secondary')) | ||||
.attr({title: 'Options', 'data-toggle': 'dropdown'}) | .attr({title: 'Options', 'data-toggle': 'dropdown'}) | ||||
Show All 29 Lines | function nicknameWidget(params) { | ||||
element.find('.action-dismiss').on('click', e => { | element.find('.action-dismiss').on('click', e => { | ||||
if (sessionData.onDismiss) { | if (sessionData.onDismiss) { | ||||
sessionData.onDismiss(params.connectionId) | sessionData.onDismiss(params.connectionId) | ||||
} | } | ||||
}) | }) | ||||
} | } | ||||
let connectionRole = () => { | |||||
if (params.isSelf) { | |||||
return sessionData.role | |||||
} | |||||
if (params.connectionId in connections) { | |||||
return connections[params.connectionId].role | |||||
} | |||||
return 0 | |||||
} | |||||
// Don't close the menu on permission change | // Don't close the menu on permission change | ||||
element.find('.dropdown-menu > label').on('click', e => { e.stopPropagation() }) | element.find('.dropdown-menu > label').on('click', e => { e.stopPropagation() }) | ||||
if (sessionData.onConnectionChange) { | if (sessionData.onConnectionChange) { | ||||
element.find('.action-role-publisher input').on('change', e => { | element.find('.action-role-publisher input').on('change', e => { | ||||
const enabled = e.target.checked | const enabled = e.target.checked | ||||
let role = params.role | let role = connectionRole() | ||||
if (enabled) { | if (enabled) { | ||||
role |= Roles.PUBLISHER | role |= Roles.PUBLISHER | ||||
} else { | } else { | ||||
role |= Roles.SUBSCRIBER | role |= Roles.SUBSCRIBER | ||||
if (role & Roles.PUBLISHER) { | if (role & Roles.PUBLISHER) { | ||||
role ^= Roles.PUBLISHER | role ^= Roles.PUBLISHER | ||||
} | } | ||||
} | } | ||||
sessionData.onConnectionChange(params.connectionId, { role }) | sessionData.onConnectionChange(params.connectionId, { role }) | ||||
}) | }) | ||||
element.find('.action-role-moderator input').on('change', e => { | element.find('.action-role-moderator input').on('change', e => { | ||||
const enabled = e.target.checked | const enabled = e.target.checked | ||||
let role = params.role | let role = connectionRole() | ||||
if (enabled) { | if (enabled) { | ||||
role |= Roles.MODERATOR | role |= Roles.MODERATOR | ||||
} else if (role & Roles.MODERATOR) { | } else if (role & Roles.MODERATOR) { | ||||
role ^= Roles.MODERATOR | role ^= Roles.MODERATOR | ||||
} | } | ||||
sessionData.onConnectionChange(params.connectionId, { role }) | sessionData.onConnectionChange(params.connectionId, { role }) | ||||
▲ Show 20 Lines • Show All 242 Lines • Show Last 20 Lines |