Merge pull request #271 from nextcloud/select-screensharing

Select-Screensharing feature
This commit is contained in:
Joas Schilling 2017-04-11 12:00:43 +02:00 коммит произвёл GitHub
Родитель 78ff2f0e5b b106fce792
Коммит 7d70cd643e
5 изменённых файлов: 236 добавлений и 29 удалений

Просмотреть файл

@ -225,7 +225,7 @@ video {
display: none;
}
.videoContainer.promoted .muteIndicator {
.videoContainer.promoted .mediaIndicator {
display: none !important;
}
@ -268,10 +268,26 @@ video {
display: none;
}
.participants-1 #toggleScreensharing {
.participants-1 #screensharing-button {
display: none;
}
#screensharing-menu {
bottom: 44px;
left: calc(50% - 40px);
right: initial;
color: initial;
text-shadow: initial;
font-size: 13px;
}
#screensharing-menu.app-navigation-entry-menu:after {
top: 100%;
left: calc(50% - 5px);
border-top-color: #fff;
border-bottom-color: transparent;
}
/* big speaker video */
.participants-1 .videoContainer,
.participants-2 .videoContainer,
@ -399,22 +415,33 @@ video {
opacity: .7;
}
.muteIndicator {
.mediaIndicator {
position: absolute;
width: 100%;
bottom: 44px;
left: 0;
background-size: 22px;
padding: 12px;
opacity: .7;
text-align: center;
}
.muteIndicator.audio-on {
.muteIndicator,
.screensharingIndicator {
position: relative;
display: inline-block;
background-color: transparent !important;
border: none;
width: 32px;
height: 32px;
background-size: 22px;
}
.muteIndicator.audio-on,
.screensharingIndicator.screen-off {
display: none;
}
.muteIndicator.audio-off {
display: block;
opacity: .7;
}
#app-content:-webkit-full-screen {

Просмотреть файл

@ -220,16 +220,17 @@
var screensharingStopped = function() {
console.log("Screensharing now stopped");
$('#toggleScreensharing').attr('data-original-title', 'Enable screensharing')
$('#screensharing-button').attr('data-original-title', 'Enable screensharing')
.addClass('screensharing-disabled icon-screen-off-white')
.removeClass('icon-screen-white');
$('#screensharing-menu').toggleClass('open', false);
};
OCA.SpreedMe.webrtc.on('localScreenStopped', function() {
screensharingStopped();
});
$('#toggleScreensharing').click(function() {
$('#screensharing-button').click(function() {
var webrtc = OCA.SpreedMe.webrtc;
if (!webrtc.capabilities.supportScreenSharing) {
OC.Notification.showTemporary(t('spreed', 'Screensharing is not supported by your browser.'));
@ -237,13 +238,11 @@
}
if (webrtc.getLocalScreen()) {
webrtc.stopScreenShare();
screensharingStopped();
$('#screensharing-menu').toggleClass('open');
} else {
webrtc.shareScreen(function(err) {
if (!err) {
OC.Notification.showTemporary(t('spreed', 'Screensharing is about to start…'));
$('#toggleScreensharing').attr('data-original-title', 'Stop screensharing')
$('#screensharing-button').attr('data-original-title', 'Screensharing options')
.removeClass('screensharing-disabled icon-screen-off-white')
.addClass('icon-screen-white');
return;
@ -256,7 +255,6 @@
case "PERMISSION_DENIED":
case "NotAllowedError":
case "CEF_GETSCREENMEDIA_CANCELED": // Experimental, may go away in the future.
OC.Notification.showTemporary(t('spreed', 'The screensharing request has been cancelled.'));
break;
case "EXTENSION_UNAVAILABLE":
var extensionURL = null;
@ -284,6 +282,18 @@
}
});
$("#show-screen-button").on('click', function() {
var currentUser = OCA.SpreedMe.webrtc.connection.getSessionid();
OCA.SpreedMe.sharedScreens.switchScreenToId(currentUser);
$('#screensharing-menu').toggleClass('open', false);
});
$("#stop-screen-button").on('click', function() {
OCA.SpreedMe.webrtc.stopScreenShare();
screensharingStopped();
});
$("#guestName").on('click', function() {
$('#guestName').addClass('hidden');
$("#guestNameInput").removeClass('hidden');

Просмотреть файл

@ -152,7 +152,9 @@ var spreedMappingTable = [];
OCA.SpreedMe.webrtc = webrtc;
var spreedListofSpeakers = {};
var spreedListofSharedScreens = {};
var latestSpeakerId = null;
var latestScreenId = null;
var screenSharingActive = false;
window.addEventListener('resize', function() {
@ -234,7 +236,7 @@ var spreedMappingTable = [];
$('<div>')
.addClass('videoContainer videoContainer-dummy')
.append(newContainer.find('.nameIndicator').clone())
.append(newContainer.find('.muteIndicator').clone())
.append(newContainer.find('.mediaIndicator').clone())
.append(newContainer.find('.speakingIndicator').clone())
);
@ -310,6 +312,106 @@ var spreedMappingTable = [];
}
};
OCA.SpreedMe.sharedScreens = {
getContainerId: function(id) {
var currentUser = OCA.SpreedMe.webrtc.connection.getSessionid();
if (currentUser === id) {
return '#localScreenContainer';
} else {
var sanitizedId = id.replace(/[!"#$%&'()*+,.\/:;<=>?@[\\\]^`{|}~]/g, "\\$&");
return '#container_' + sanitizedId + '_screen_incoming';
}
},
switchScreenToId: function(id) {
var selectedScreen = $(OCA.SpreedMe.sharedScreens.getContainerId(id));
if(selectedScreen.find('video').length === 0) {
console.warn('promote: no screen video found for ID', id);
return;
}
if(latestScreenId === id) {
console.log('promote: no need to repromote same screen');
return;
}
var screenContainerId = null;
for (var currentId in spreedListofSharedScreens) {
// skip loop if the property is from prototype
if (!spreedListofSharedScreens.hasOwnProperty(currentId)) {
continue;
}
// skip non-string ids
if (!(typeof currentId === 'string' || currentId instanceof String)) {
continue;
}
screenContainerId = OCA.SpreedMe.sharedScreens.getContainerId(currentId);
if (currentId === id) {
$(screenContainerId).removeClass('hidden');
} else {
$(screenContainerId).addClass('hidden');
}
}
// Add screen visible icon to video container
$('#videos').find('.screensharingIndicator').removeClass('screen-visible');
$(OCA.SpreedMe.speakers.getContainerId(id)).find('.screensharingIndicator').addClass('screen-visible');
latestScreenId = id;
},
add: function(id) {
if (!(typeof id === 'string' || id instanceof String)) {
return;
}
spreedListofSharedScreens[id] = (new Date()).getTime();
var screensharingIndicator = $(OCA.SpreedMe.speakers.getContainerId(id)).find('.screensharingIndicator');
screensharingIndicator.removeClass('screen-off');
screensharingIndicator.addClass('screen-on');
OCA.SpreedMe.sharedScreens.switchScreenToId(id);
},
remove: function(id) {
if (!(typeof id === 'string' || id instanceof String)) {
return;
}
delete spreedListofSharedScreens[id];
var screensharingIndicator = $(OCA.SpreedMe.speakers.getContainerId(id)).find('.screensharingIndicator');
screensharingIndicator.addClass('screen-off');
screensharingIndicator.removeClass('screen-on');
var mostRecentTime = 0,
mostRecentId = null;
for (var currentId in spreedListofSharedScreens) {
// skip loop if the property is from prototype
if (!spreedListofSharedScreens.hasOwnProperty(currentId)) {
continue;
}
// skip non-string ids
if (!(typeof currentId === 'string' || currentId instanceof String)) {
continue;
}
var currentTime = spreedListofSharedScreens[currentId];
if (currentTime > mostRecentTime) {
mostRecentTime = currentTime;
mostRecentId = currentId;
}
}
if (mostRecentId !== null) {
OCA.SpreedMe.sharedScreens.switchScreenToId(mostRecentId);
} else {
console.log('No screens to promote');
}
}
};
OCA.SpreedMe.webrtc.on('createdPeer', function (peer) {
peer.pc.on('PeerConnectionTrace', function (event) {
console.log('trace', event);
@ -415,10 +517,37 @@ var spreedMappingTable = [];
avatarContainer.className = 'avatar-container hidden';
avatarContainer.appendChild(avatar);
// Mute indicator
var muteIndicator = document.createElement('div');
muteIndicator.className = 'muteIndicator icon-audio-off-white audio-on';
muteIndicator.textContent = '';
// Media indicators
var mediaIndicator = document.createElement('div');
mediaIndicator.className = 'mediaIndicator';
var muteIndicator = document.createElement('button');
muteIndicator.className = 'muteIndicator icon-audio-off-white audio-off';
muteIndicator.disabled = true;
var screenSharingIndicator = document.createElement('button');
screenSharingIndicator.className = 'screensharingIndicator icon-screen-white screen-off';
screenSharingIndicator.setAttribute('data-original-title', 'Show screen');
screenSharingIndicator.onclick = function() {
if (!this.classList.contains('screen-visible')) {
OCA.SpreedMe.sharedScreens.switchScreenToId(peer.id);
}
$(this).tooltip('hide');
};
$(screenSharingIndicator).tooltip({
placement: 'top',
trigger: 'hover'
});
// Check if there is a screen from that user already added.
if (spreedListofSharedScreens.hasOwnProperty(peer.id)) {
$(screenSharingIndicator).removeClass('screen-off').addClass('screen-on');
}
mediaIndicator.appendChild(muteIndicator);
mediaIndicator.appendChild(screenSharingIndicator);
// Generic container
var container = document.createElement('div');
@ -427,7 +556,7 @@ var spreedMappingTable = [];
container.appendChild(video);
container.appendChild(avatarContainer);
container.appendChild(userIndicator);
container.appendChild(muteIndicator);
container.appendChild(mediaIndicator);
video.oncontextmenu = function() {
return false;
};
@ -514,11 +643,12 @@ var spreedMappingTable = [];
// a peer was removed
OCA.SpreedMe.webrtc.on('videoRemoved', function(video, peer) {
if (peer) {
if (peer.type === 'video') {
// a removed peer can't speak anymore ;)
OCA.SpreedMe.speakers.remove(peer, true);
} else if (peer.type === 'screen') {
OCA.SpreedMe.sharedScreens.remove(peer.id);
}
var remotes = document.getElementById(peer.type === 'screen' ? 'screens' : 'videos');
@ -537,6 +667,8 @@ var spreedMappingTable = [];
if (screens && localScreenContainer) {
screens.removeChild(localScreenContainer);
}
OCA.SpreedMe.sharedScreens.remove(OCA.SpreedMe.webrtc.connection.getSessionid());
}
// Check if there are still some screens
@ -573,12 +705,12 @@ var spreedMappingTable = [];
userIndicator.className = 'nameIndicator';
if (peer) {
if (peer.nick) {
userIndicator.textContent = peer.nick;
userIndicator.textContent = t('spreed', "{participantName}'s screen", {participantName: peer.nick});
} else {
userIndicator.textContent = t('spreed', 'Guest');
userIndicator.textContent = t('spreed', "Guest's screen");
}
} else {
userIndicator.textContent = t('spreed', 'My screen');
userIndicator.textContent = t('spreed', 'Your screen');
}
// Generic container
@ -591,6 +723,14 @@ var spreedMappingTable = [];
return false;
};
$(container).prependTo($('#screens'));
if (peer) {
OCA.SpreedMe.sharedScreens.add(peer.id);
} else {
OCA.SpreedMe.sharedScreens.add(OCA.SpreedMe.webrtc.connection.getSessionid());
}
// show the ice connection state
if (peer && peer.pc) {
peer.pc.on('iceConnectionStateChange', function () {
@ -631,8 +771,6 @@ var spreedMappingTable = [];
}
});
}
$(container).prependTo($('#screens'));
}
});
@ -662,7 +800,7 @@ var spreedMappingTable = [];
var screenNameIndicator = $(screen).find('.nameIndicator');
videoNameIndicator.text(data.name);
screenNameIndicator.text(data.name);
screenNameIndicator.text(t('spreed', "{participantName}'s screen", {participantName: data.name}));
if (latestSpeakerId === data.id) {
OCA.SpreedMe.speakers.updateVideoContainerDummy(data.id);

Просмотреть файл

@ -67,7 +67,23 @@ script(
<div class="nameIndicator">
<button id="mute" class="icon-audio-white" data-placement="top" data-toggle="tooltip" data-original-title="<?php p($l->t('Mute audio')) ?>"></button>
<button id="hideVideo" class="icon-video-white" data-placement="top" data-toggle="tooltip" data-original-title="<?php p($l->t('Disable video')) ?>"></button>
<button id="toggleScreensharing" class="icon-screen-off-white screensharing-disabled" data-placement="top" data-toggle="tooltip" data-original-title="<?php p($l->t('Share screen')) ?>"></button>
<button id="screensharing-button" class="app-navigation-entry-utils-menu-button icon-screen-off-white screensharing-disabled" data-placement="top" data-toggle="tooltip" data-original-title="<?php p($l->t('Share screen')) ?>"></button>
<div id="screensharing-menu" class="app-navigation-entry-menu">
<ul>
<li>
<button id="show-screen-button">
<span class="icon-screen"></span>
<span><?php p($l->t('Show your screen'));?></span>
</button>
</li>
<li>
<button id="stop-screen-button">
<span class="icon-screen-off"></span>
<span><?php p($l->t('Stop screensharing'));?></span>
</button>
</li>
</ul>
</div>
</div>
</div>
</div>

Просмотреть файл

@ -50,7 +50,23 @@ script(
<div class="nameIndicator">
<button id="mute" class="icon-audio-white" data-placement="top" data-toggle="tooltip" data-original-title="<?php p($l->t('Mute audio')) ?>"></button>
<button id="hideVideo" class="icon-video-white" data-placement="top" data-toggle="tooltip" data-original-title="<?php p($l->t('Disable video')) ?>"></button>
<button id="toggleScreensharing" class="icon-screen-off-white screensharing-disabled" data-placement="top" data-toggle="tooltip" data-original-title="<?php p($l->t('Share screen')) ?>"></button>
<button id="screensharing-button" class="app-navigation-entry-utils-menu-button icon-screen-off-white screensharing-disabled" data-placement="top" data-toggle="tooltip" data-original-title="<?php p($l->t('Share screen')) ?>"></button>
<div id="screensharing-menu" class="app-navigation-entry-menu">
<ul>
<li>
<button id="show-screen-button">
<span class="icon-screen"></span>
<span><?php p($l->t('Show your screen'));?></span>
</button>
</li>
<li>
<button id="stop-screen-button">
<span class="icon-screen-off"></span>
<span><?php p($l->t('Stop screensharing'));?></span>
</button>
</li>
</ul>
</div>
</div>
</div>
</div>