Merge remote-tracking branch 'remotes/upstream/master' into jitsi_track_error_refactoring
This commit is contained in:
commit
25b3545c14
237
conference.js
237
conference.js
|
@ -57,6 +57,58 @@ function connect(roomName) {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates local media tracks and connects to room. Will show error
|
||||
* dialogs in case if accessing local microphone and/or camera failed. Will
|
||||
* show guidance overlay for users on how to give access to camera and/or
|
||||
* microphone,
|
||||
* @param {string} roomName
|
||||
* @returns {Promise.<JitsiLocalTrack[], JitsiConnection>}
|
||||
*/
|
||||
function createInitialLocalTracksAndConnect(roomName) {
|
||||
let audioAndVideoError,
|
||||
audioOnlyError;
|
||||
|
||||
JitsiMeetJS.mediaDevices.addEventListener(
|
||||
JitsiMeetJS.events.mediaDevices.PERMISSION_PROMPT_IS_SHOWN,
|
||||
browser => APP.UI.showUserMediaPermissionsGuidanceOverlay(browser));
|
||||
|
||||
// First try to retrieve both audio and video.
|
||||
let tryCreateLocalTracks = createLocalTracks(
|
||||
{ devices: ['audio', 'video'] }, true)
|
||||
.catch(err => {
|
||||
// If failed then try to retrieve only audio.
|
||||
audioAndVideoError = err;
|
||||
return createLocalTracks({ devices: ['audio'] }, true);
|
||||
})
|
||||
.catch(err => {
|
||||
// If audio failed too then just return empty array for tracks.
|
||||
audioOnlyError = err;
|
||||
return [];
|
||||
});
|
||||
|
||||
return Promise.all([ tryCreateLocalTracks, connect(roomName) ])
|
||||
.then(([tracks, con]) => {
|
||||
APP.UI.hideUserMediaPermissionsGuidanceOverlay();
|
||||
|
||||
if (audioAndVideoError) {
|
||||
if (audioOnlyError) {
|
||||
// If both requests for 'audio' + 'video' and 'audio' only
|
||||
// failed, we assume that there is some problems with user's
|
||||
// microphone and show corresponding dialog.
|
||||
APP.UI.showDeviceErrorDialog(audioOnlyError, null);
|
||||
} else {
|
||||
// If request for 'audio' + 'video' failed, but request for
|
||||
// 'audio' only was OK, we assume that we had problems with
|
||||
// camera and show corresponding dialog.
|
||||
APP.UI.showDeviceErrorDialog(null, audioAndVideoError);
|
||||
}
|
||||
}
|
||||
|
||||
return [tracks, con];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Share data to other users.
|
||||
* @param command the command
|
||||
|
@ -183,32 +235,42 @@ function hangup (requestFeedback = false) {
|
|||
|
||||
/**
|
||||
* Create local tracks of specified types.
|
||||
* @param {string[]} devices - required track types ('audio', 'video' etc.)
|
||||
* @param {string|null} [cameraDeviceId] - camera device id, if undefined - one
|
||||
* from settings will be used
|
||||
* @param {string|null} [micDeviceId] - microphone device id, if undefined - one
|
||||
* from settings will be used
|
||||
* @param {Object} options
|
||||
* @param {string[]} options.devices - required track types
|
||||
* ('audio', 'video' etc.)
|
||||
* @param {string|null} (options.cameraDeviceId) - camera device id, if
|
||||
* undefined - one from settings will be used
|
||||
* @param {string|null} (options.micDeviceId) - microphone device id, if
|
||||
* undefined - one from settings will be used
|
||||
* @param {boolean} (checkForPermissionPrompt) - if lib-jitsi-meet should check
|
||||
* for gUM permission prompt
|
||||
* @returns {Promise<JitsiLocalTrack[]>}
|
||||
*/
|
||||
function createLocalTracks (devices, cameraDeviceId, micDeviceId) {
|
||||
return JitsiMeetJS.createLocalTracks({
|
||||
// copy array to avoid mutations inside library
|
||||
devices: devices.slice(0),
|
||||
resolution: config.resolution,
|
||||
cameraDeviceId: typeof cameraDeviceId === 'undefined'
|
||||
|| cameraDeviceId === null
|
||||
function createLocalTracks (options, checkForPermissionPrompt) {
|
||||
options || (options = {});
|
||||
|
||||
return JitsiMeetJS
|
||||
.createLocalTracks({
|
||||
// copy array to avoid mutations inside library
|
||||
devices: options.devices.slice(0),
|
||||
resolution: config.resolution,
|
||||
cameraDeviceId: typeof options.cameraDeviceId === 'undefined' ||
|
||||
options.cameraDeviceId === null
|
||||
? APP.settings.getCameraDeviceId()
|
||||
: cameraDeviceId,
|
||||
micDeviceId: typeof micDeviceId === 'undefined' || micDeviceId === null
|
||||
? APP.settings.getMicDeviceId()
|
||||
: micDeviceId,
|
||||
// adds any ff fake device settings if any
|
||||
firefox_fake_device: config.firefox_fake_device
|
||||
}).catch(function (err) {
|
||||
console.error('failed to create local tracks', ...devices, err);
|
||||
return Promise.reject(err);
|
||||
});
|
||||
}
|
||||
: options.cameraDeviceId,
|
||||
micDeviceId: typeof options.micDeviceId === 'undefined' ||
|
||||
options.micDeviceId === null
|
||||
? APP.settings.getMicDeviceId()
|
||||
: options.micDeviceId,
|
||||
// adds any ff fake device settings if any
|
||||
firefox_fake_device: config.firefox_fake_device
|
||||
}, checkForPermissionPrompt)
|
||||
.catch(function (err) {
|
||||
console.error(
|
||||
'failed to create local tracks', options.devices, err);
|
||||
return Promise.reject(err);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the email for the local user
|
||||
|
@ -407,7 +469,6 @@ export default {
|
|||
* @returns {Promise}
|
||||
*/
|
||||
init(options) {
|
||||
let self = this;
|
||||
this.roomName = options.roomName;
|
||||
JitsiMeetJS.setLogLevel(JitsiMeetJS.logLevels.TRACE);
|
||||
|
||||
|
@ -433,65 +494,35 @@ export default {
|
|||
};
|
||||
}
|
||||
|
||||
let audioAndVideoError, audioOnlyError;
|
||||
return JitsiMeetJS.init(config)
|
||||
.then(() => createInitialLocalTracksAndConnect(options.roomName))
|
||||
.then(([tracks, con]) => {
|
||||
console.log('initialized with %s local tracks', tracks.length);
|
||||
APP.connection = connection = con;
|
||||
this._createRoom(tracks);
|
||||
this.isDesktopSharingEnabled =
|
||||
JitsiMeetJS.isDesktopSharingEnabled();
|
||||
|
||||
return JitsiMeetJS.init(config).then(() => {
|
||||
return Promise.all([
|
||||
// try to retrieve audio and video
|
||||
createLocalTracks(['audio', 'video'])
|
||||
// if failed then try to retrieve only audio
|
||||
.catch(err => {
|
||||
audioAndVideoError = err;
|
||||
return createLocalTracks(['audio']);
|
||||
})
|
||||
// if audio also failed then just return empty array
|
||||
.catch(err => {
|
||||
audioOnlyError = err;
|
||||
return [];
|
||||
}),
|
||||
connect(options.roomName)
|
||||
]);
|
||||
}).then(([tracks, con]) => {
|
||||
if (audioAndVideoError) {
|
||||
if (audioOnlyError) {
|
||||
// If both requests for 'audio' + 'video' and 'audio' only
|
||||
// failed, we assume that there is some problems with user's
|
||||
// microphone and show corresponding dialog.
|
||||
APP.UI.showDeviceErrorDialog(audioOnlyError, null);
|
||||
} else {
|
||||
// If request for 'audio' + 'video' failed, but request for
|
||||
// 'audio' only was OK, we assume that we had problems with
|
||||
// camera and show corresponding dialog.
|
||||
APP.UI.showDeviceErrorDialog(null, audioAndVideoError);
|
||||
// if user didn't give access to mic or camera or doesn't have
|
||||
// them at all, we disable corresponding toolbar buttons
|
||||
if (!tracks.find((t) => t.isAudioTrack())) {
|
||||
APP.UI.disableMicrophoneButton();
|
||||
}
|
||||
}
|
||||
|
||||
console.log('initialized with %s local tracks', tracks.length);
|
||||
APP.connection = connection = con;
|
||||
this._createRoom(tracks);
|
||||
this.isDesktopSharingEnabled =
|
||||
JitsiMeetJS.isDesktopSharingEnabled();
|
||||
if (!tracks.find((t) => t.isVideoTrack())) {
|
||||
APP.UI.disableCameraButton();
|
||||
}
|
||||
|
||||
// if user didn't give access to mic or camera or doesn't have
|
||||
// them at all, we disable corresponding toolbar buttons
|
||||
if (!tracks.find((t) => t.isAudioTrack())) {
|
||||
APP.UI.disableMicrophoneButton();
|
||||
}
|
||||
this._initDeviceList();
|
||||
|
||||
if (!tracks.find((t) => t.isVideoTrack())) {
|
||||
APP.UI.disableCameraButton();
|
||||
}
|
||||
if (config.iAmRecorder)
|
||||
this.recorder = new Recorder();
|
||||
|
||||
this._initDeviceList();
|
||||
|
||||
if (config.iAmRecorder)
|
||||
this.recorder = new Recorder();
|
||||
|
||||
// XXX The API will take care of disconnecting from the XMPP server
|
||||
// (and, thus, leaving the room) on unload.
|
||||
return new Promise((resolve, reject) => {
|
||||
(new ConferenceConnector(resolve, reject)).connect();
|
||||
});
|
||||
// XXX The API will take care of disconnecting from the XMPP
|
||||
// server (and, thus, leaving the room) on unload.
|
||||
return new Promise((resolve, reject) => {
|
||||
(new ConferenceConnector(resolve, reject)).connect();
|
||||
});
|
||||
});
|
||||
},
|
||||
/**
|
||||
|
@ -835,7 +866,7 @@ export default {
|
|||
this.videoSwitchInProgress = true;
|
||||
|
||||
if (shareScreen) {
|
||||
createLocalTracks(['desktop']).then(([stream]) => {
|
||||
createLocalTracks({ devices: ['desktop'] }).then(([stream]) => {
|
||||
stream.on(
|
||||
TrackEvents.LOCAL_TRACK_STOPPED,
|
||||
() => {
|
||||
|
@ -893,7 +924,7 @@ export default {
|
|||
APP.UI.messageHandler.openDialog(dialogTitle, dialogTxt, false);
|
||||
});
|
||||
} else {
|
||||
createLocalTracks(['video']).then(
|
||||
createLocalTracks({ devices: ['video'] }).then(
|
||||
([stream]) => this.useVideoStream(stream)
|
||||
).then(() => {
|
||||
this.videoSwitchInProgress = false;
|
||||
|
@ -1249,32 +1280,40 @@ export default {
|
|||
APP.UI.addListener(
|
||||
UIEvents.VIDEO_DEVICE_CHANGED,
|
||||
(cameraDeviceId) => {
|
||||
createLocalTracks(['video'], cameraDeviceId, null)
|
||||
.then(([stream]) => {
|
||||
this.useVideoStream(stream);
|
||||
console.log('switched local video device');
|
||||
APP.settings.setCameraDeviceId(cameraDeviceId);
|
||||
})
|
||||
.catch((err) => {
|
||||
APP.UI.showDeviceErrorDialog(null, err);
|
||||
APP.UI.setSelectedCameraFromSettings();
|
||||
});
|
||||
createLocalTracks({
|
||||
devices: ['video'],
|
||||
cameraDeviceId: cameraDeviceId,
|
||||
micDeviceId: null
|
||||
})
|
||||
.then(([stream]) => {
|
||||
this.useVideoStream(stream);
|
||||
console.log('switched local video device');
|
||||
APP.settings.setCameraDeviceId(cameraDeviceId);
|
||||
})
|
||||
.catch((err) => {
|
||||
APP.UI.showDeviceErrorDialog(null, err);
|
||||
APP.UI.setSelectedCameraFromSettings();
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
APP.UI.addListener(
|
||||
UIEvents.AUDIO_DEVICE_CHANGED,
|
||||
(micDeviceId) => {
|
||||
createLocalTracks(['audio'], null, micDeviceId)
|
||||
.then(([stream]) => {
|
||||
this.useAudioStream(stream);
|
||||
console.log('switched local audio device');
|
||||
APP.settings.setMicDeviceId(micDeviceId);
|
||||
})
|
||||
.catch((err) => {
|
||||
APP.UI.showDeviceErrorDialog(err, null);
|
||||
APP.UI.setSelectedMicFromSettings();
|
||||
});
|
||||
createLocalTracks({
|
||||
devices: ['audio'],
|
||||
cameraDeviceId: null,
|
||||
micDeviceId: micDeviceId
|
||||
})
|
||||
.then(([stream]) => {
|
||||
this.useAudioStream(stream);
|
||||
console.log('switched local audio device');
|
||||
APP.settings.setMicDeviceId(micDeviceId);
|
||||
})
|
||||
.catch((err) => {
|
||||
APP.UI.showDeviceErrorDialog(err, null);
|
||||
APP.UI.setSelectedMicFromSettings();
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
|
|
|
@ -8,11 +8,15 @@
|
|||
text-align: left;
|
||||
padding: 7px 10px;
|
||||
margin: 2px;
|
||||
color: #00ccff;
|
||||
color: #21B9FC;
|
||||
font-size: 11pt;
|
||||
border-bottom: 1px solid #676767;
|
||||
}
|
||||
|
||||
#contactlist>div.title>span {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
#contactlist>ul#contacts {
|
||||
position: absolute;
|
||||
top: 31px;
|
||||
|
|
12
css/font.css
12
css/font.css
|
@ -1,3 +1,15 @@
|
|||
@font-face {
|
||||
font-family: 'open_sanslight';
|
||||
src: url('../fonts/OpenSans-Light-webfont.eot');
|
||||
src: url('../fonts/OpenSans-Light-webfont.eot?#iefix') format('embedded-opentype'),
|
||||
url('../fonts/OpenSans-Light-webfont.woff') format('woff'),
|
||||
url('../fonts/OpenSans-Light-webfont.ttf') format('truetype'),
|
||||
url('../fonts/OpenSans-Light-webfont.svg#open_sanslight') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'jitsi';
|
||||
src:url('../fonts/jitsi.eot?94d075');
|
||||
|
|
|
@ -86,12 +86,12 @@
|
|||
|
||||
.jitsipopover_blue
|
||||
{
|
||||
color: #06a5df;
|
||||
color: #21B9FC;
|
||||
}
|
||||
|
||||
.jitsipopover_showmore
|
||||
{
|
||||
background-color: #06a5df;
|
||||
background-color: #21B9FC;
|
||||
color: #ffffff;
|
||||
cursor: pointer;
|
||||
border-radius: 3px;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*Initialize*/
|
||||
ul.loginmenu {
|
||||
font-family:'Helvetica Neue', Helvetica, sans-serif;
|
||||
font-family: inherit;
|
||||
display:none;
|
||||
position: absolute;
|
||||
margin: 0;
|
||||
|
|
46
css/main.css
46
css/main.css
|
@ -7,12 +7,19 @@ html, body{
|
|||
margin:0px;
|
||||
height:100%;
|
||||
color: #424242;
|
||||
font-family:'Helvetica Neue', Helvetica, sans-serif;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
background: #000000;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
html, body, input, textarea, keygen, select, button {
|
||||
font-family: 'open_sanslight',
|
||||
'Helvetica Neue',
|
||||
Helvetica,
|
||||
sans-serif !important;
|
||||
}
|
||||
|
||||
.right-panel {
|
||||
display:none;
|
||||
position:absolute;
|
||||
|
@ -58,7 +65,7 @@ html, body{
|
|||
text-align: center;
|
||||
text-shadow: 0 1px 0 rgba(255,255,255,.3), 0 -1px 0 rgba(0,0,0,.6);
|
||||
z-index: 1;
|
||||
font-size: 1.22em !important;
|
||||
font-size: 1.44em !important;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
|
@ -82,18 +89,18 @@ html, body{
|
|||
}
|
||||
/*#ffde00*/
|
||||
#toolbar_button_chat.active, #contactListButton.glowing, #chatBottomButton.glowing {
|
||||
-webkit-text-shadow: -1px 0 10px #00ccff,
|
||||
0 1px 10px #00ccff,
|
||||
1px 0 10px #00ccff,
|
||||
0 -1px 10px #00ccff;
|
||||
-moz-text-shadow: 1px 0 10px #00ccff,
|
||||
0 1px 10px #00ccff,
|
||||
1px 0 10px #00ccff,
|
||||
0 -1px 10px #00ccff;
|
||||
text-shadow: -1px 0 10px #00ccff,
|
||||
0 1px 10px #00ccff,
|
||||
1px 0 10px #00ccff,
|
||||
0 -1px 10px #00ccff;
|
||||
-webkit-text-shadow: -1px 0 10px #21B9FC,
|
||||
0 1px 10px #21B9FC,
|
||||
1px 0 10px #21B9FC,
|
||||
0 -1px 10px #21B9FC;
|
||||
-moz-text-shadow: 1px 0 10px #21B9FC,
|
||||
0 1px 10px #21B9FC,
|
||||
1px 0 10px #21B9FC,
|
||||
0 -1px 10px #21B9FC;
|
||||
text-shadow: -1px 0 10px #21B9FC,
|
||||
0 1px 10px #21B9FC,
|
||||
1px 0 10px #21B9FC,
|
||||
0 -1px 10px #21B9FC;
|
||||
}
|
||||
|
||||
#toolbar_button_hangup {
|
||||
|
@ -116,7 +123,7 @@ html, body{
|
|||
}
|
||||
|
||||
#contactListButton.active #numberOfParticipants {
|
||||
color: #00ccff;
|
||||
color: #21B9FC;
|
||||
}
|
||||
|
||||
#toolbar {
|
||||
|
@ -365,16 +372,11 @@ div.feedbackButton:hover {
|
|||
}
|
||||
|
||||
.connected {
|
||||
color: forestgreen;
|
||||
color: #21B9FC;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.disconnected {
|
||||
color: darkred;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.lastN {
|
||||
.lastN, .disconnected {
|
||||
color: #a3a3a3;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
|
|
@ -6,11 +6,15 @@
|
|||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 1013;
|
||||
background: #000000; /* Old browsers */
|
||||
background: #21B9FC; /* Old browsers */
|
||||
opacity: 0.75;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.overlay_transparent {
|
||||
background: rgba(22, 185, 252, .9);
|
||||
}
|
||||
|
||||
.overlay_container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
@ -46,6 +50,17 @@
|
|||
position: relative;
|
||||
width: 400px;
|
||||
z-index: 1013;
|
||||
margin-top: 20px;
|
||||
margin-top: 50px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.overlay_text_small {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.overlay_icon {
|
||||
position: relative;
|
||||
z-index: 1013;
|
||||
float: none;
|
||||
font-size: 100px;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#settingsmenu {
|
||||
display: none;
|
||||
background: black;
|
||||
color: #00ccff;
|
||||
color: #21B9FC;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,18 @@
|
|||
color: #a7a7a7;
|
||||
}
|
||||
|
||||
#settingsmenu>div.title {
|
||||
text-align: left;
|
||||
padding: 7px 10px;
|
||||
margin: 2px;
|
||||
font-size: 11pt;
|
||||
border-bottom: 1px solid #676767;
|
||||
}
|
||||
|
||||
#settingsmenu>div.title>span {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
#settingsmenu .arrow-up {
|
||||
width: 0;
|
||||
height: 0;
|
||||
|
@ -35,10 +47,6 @@
|
|||
position: relative;
|
||||
}
|
||||
|
||||
#settingsmenu .icon-settings {
|
||||
padding: 34px;
|
||||
}
|
||||
|
||||
#languages_selectbox {
|
||||
height: 40px;
|
||||
cursor: pointer;
|
||||
|
|
|
@ -95,7 +95,7 @@ button.toast-close-button {
|
|||
}
|
||||
#toast-container > div {
|
||||
margin: 0 0 6px;
|
||||
padding: 15px 15px 15px 50px;
|
||||
padding: 15px 15px 15px 15px;
|
||||
width: 300px;
|
||||
-moz-border-radius: 3px 3px 3px 3px;
|
||||
-webkit-border-radius: 3px 3px 3px 3px;
|
||||
|
@ -119,21 +119,17 @@ button.toast-close-button {
|
|||
filter: alpha(opacity=100);
|
||||
cursor: pointer;
|
||||
}
|
||||
#toast-container > .toast-info {
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGwSURBVEhLtZa9SgNBEMc9sUxxRcoUKSzSWIhXpFMhhYWFhaBg4yPYiWCXZxBLERsLRS3EQkEfwCKdjWJAwSKCgoKCcudv4O5YLrt7EzgXhiU3/4+b2ckmwVjJSpKkQ6wAi4gwhT+z3wRBcEz0yjSseUTrcRyfsHsXmD0AmbHOC9Ii8VImnuXBPglHpQ5wwSVM7sNnTG7Za4JwDdCjxyAiH3nyA2mtaTJufiDZ5dCaqlItILh1NHatfN5skvjx9Z38m69CgzuXmZgVrPIGE763Jx9qKsRozWYw6xOHdER+nn2KkO+Bb+UV5CBN6WC6QtBgbRVozrahAbmm6HtUsgtPC19tFdxXZYBOfkbmFJ1VaHA1VAHjd0pp70oTZzvR+EVrx2Ygfdsq6eu55BHYR8hlcki+n+kERUFG8BrA0BwjeAv2M8WLQBtcy+SD6fNsmnB3AlBLrgTtVW1c2QN4bVWLATaIS60J2Du5y1TiJgjSBvFVZgTmwCU+dAZFoPxGEEs8nyHC9Bwe2GvEJv2WXZb0vjdyFT4Cxk3e/kIqlOGoVLwwPevpYHT+00T+hWwXDf4AJAOUqWcDhbwAAAAASUVORK5CYII=") !important;
|
||||
}
|
||||
#toast-container > .toast-error {
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAHOSURBVEhLrZa/SgNBEMZzh0WKCClSCKaIYOED+AAKeQQLG8HWztLCImBrYadgIdY+gIKNYkBFSwu7CAoqCgkkoGBI/E28PdbLZmeDLgzZzcx83/zZ2SSXC1j9fr+I1Hq93g2yxH4iwM1vkoBWAdxCmpzTxfkN2RcyZNaHFIkSo10+8kgxkXIURV5HGxTmFuc75B2RfQkpxHG8aAgaAFa0tAHqYFfQ7Iwe2yhODk8+J4C7yAoRTWI3w/4klGRgR4lO7Rpn9+gvMyWp+uxFh8+H+ARlgN1nJuJuQAYvNkEnwGFck18Er4q3egEc/oO+mhLdKgRyhdNFiacC0rlOCbhNVz4H9FnAYgDBvU3QIioZlJFLJtsoHYRDfiZoUyIxqCtRpVlANq0EU4dApjrtgezPFad5S19Wgjkc0hNVnuF4HjVA6C7QrSIbylB+oZe3aHgBsqlNqKYH48jXyJKMuAbiyVJ8KzaB3eRc0pg9VwQ4niFryI68qiOi3AbjwdsfnAtk0bCjTLJKr6mrD9g8iq/S/B81hguOMlQTnVyG40wAcjnmgsCNESDrjme7wfftP4P7SP4N3CJZdvzoNyGq2c/HWOXJGsvVg+RA/k2MC/wN6I2YA2Pt8GkAAAAASUVORK5CYII=") !important;
|
||||
}
|
||||
#toast-container > .toast-success {
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADsSURBVEhLY2AYBfQMgf///3P8+/evAIgvA/FsIF+BavYDDWMBGroaSMMBiE8VC7AZDrIFaMFnii3AZTjUgsUUWUDA8OdAH6iQbQEhw4HyGsPEcKBXBIC4ARhex4G4BsjmweU1soIFaGg/WtoFZRIZdEvIMhxkCCjXIVsATV6gFGACs4Rsw0EGgIIH3QJYJgHSARQZDrWAB+jawzgs+Q2UO49D7jnRSRGoEFRILcdmEMWGI0cm0JJ2QpYA1RDvcmzJEWhABhD/pqrL0S0CWuABKgnRki9lLseS7g2AlqwHWQSKH4oKLrILpRGhEQCw2LiRUIa4lwAAAABJRU5ErkJggg==") !important;
|
||||
}
|
||||
#toast-container > .toast-warning {
|
||||
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAGYSURBVEhL5ZSvTsNQFMbXZGICMYGYmJhAQIJAICYQPAACiSDB8AiICQQJT4CqQEwgJvYASAQCiZiYmJhAIBATCARJy+9rTsldd8sKu1M0+dLb057v6/lbq/2rK0mS/TRNj9cWNAKPYIJII7gIxCcQ51cvqID+GIEX8ASG4B1bK5gIZFeQfoJdEXOfgX4QAQg7kH2A65yQ87lyxb27sggkAzAuFhbbg1K2kgCkB1bVwyIR9m2L7PRPIhDUIXgGtyKw575yz3lTNs6X4JXnjV+LKM/m3MydnTbtOKIjtz6VhCBq4vSm3ncdrD2lk0VgUXSVKjVDJXJzijW1RQdsU7F77He8u68koNZTz8Oz5yGa6J3H3lZ0xYgXBK2QymlWWA+RWnYhskLBv2vmE+hBMCtbA7KX5drWyRT/2JsqZ2IvfB9Y4bWDNMFbJRFmC9E74SoS0CqulwjkC0+5bpcV1CZ8NMej4pjy0U+doDQsGyo1hzVJttIjhQ7GnBtRFN1UarUlH8F3xict+HY07rEzoUGPlWcjRFRr4/gChZgc3ZL2d8oAAAAASUVORK5CYII=") !important;
|
||||
#toast-container .toast-info,
|
||||
#toast-container .toast-success,
|
||||
#toast-container .toast-error,
|
||||
#toast-container .toast-warning
|
||||
{
|
||||
padding: 10px 10px 10px 10px !important;
|
||||
}
|
||||
|
||||
#toast-container.toast-top-full-width > div,
|
||||
#toast-container.toast-bottom-full-width > div {
|
||||
width: 96%;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
}
|
||||
.toast {
|
||||
|
@ -154,7 +150,7 @@ button.toast-close-button {
|
|||
/*Responsive Design*/
|
||||
@media all and (max-width: 240px) {
|
||||
#toast-container > div {
|
||||
padding: 8px 8px 8px 50px;
|
||||
padding: 8px 8px 8px 8px;
|
||||
width: 11em;
|
||||
}
|
||||
#toast-container .toast-close-button {
|
||||
|
@ -164,7 +160,7 @@ button.toast-close-button {
|
|||
}
|
||||
@media all and (min-width: 241px) and (max-width: 480px) {
|
||||
#toast-container > div {
|
||||
padding: 8px 8px 8px 50px;
|
||||
padding: 8px 8px 8px 8px;
|
||||
width: 18em;
|
||||
}
|
||||
#toast-container .toast-close-button {
|
||||
|
@ -174,7 +170,7 @@ button.toast-close-button {
|
|||
}
|
||||
@media all and (min-width: 481px) and (max-width: 768px) {
|
||||
#toast-container > div {
|
||||
padding: 15px 15px 15px 50px;
|
||||
padding: 15px 15px 15px 15px;
|
||||
width: 25em;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@ body {
|
|||
height:100%;
|
||||
background-color: white;
|
||||
color: #424242;
|
||||
font-family:Helvetica,'YanoneKaffeesatzLight',Verdana,Tahoma,Arial;
|
||||
font-family: 'open_sanslight', 'Helvetica Neue', Helvetica, sans-serif;
|
||||
font-size: 28px;
|
||||
margin:0;
|
||||
padding:0;
|
||||
|
|
|
@ -318,7 +318,7 @@
|
|||
z-index: 3;
|
||||
text-align: center;
|
||||
border-radius: 50%;
|
||||
background: #0cf;
|
||||
background: #21B9FC;
|
||||
margin: 5px;
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
-moz-user-select: none;
|
||||
background-repeat: no-repeat;
|
||||
font-weight: 500;
|
||||
font-family: Helvetica;
|
||||
font-size: 16px;
|
||||
color: #acacac;
|
||||
z-index: 2;
|
||||
|
@ -35,7 +34,6 @@
|
|||
-moz-user-select: none;
|
||||
background-repeat: no-repeat;
|
||||
font-weight: 500;
|
||||
font-family: Helvetica;
|
||||
font-size: 16px;
|
||||
color: #acacac;
|
||||
z-index: 2;
|
||||
|
@ -56,21 +54,21 @@
|
|||
#domain_name
|
||||
{
|
||||
float: left;
|
||||
padding: 20px 0px 10px 20px;
|
||||
height: 55px;
|
||||
line-height: 55px;
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
font-family: Helvetica;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
#enter_room_field {
|
||||
font-size: 15px;
|
||||
padding: 15px 0px 10px 10px;
|
||||
border: none;
|
||||
-webkit-appearance: none;
|
||||
width: 228px;
|
||||
height: 55px;
|
||||
line-height: 55px;
|
||||
font-weight: 500;
|
||||
font-family: Helvetica;
|
||||
box-shadow: none;
|
||||
float: left;
|
||||
background-color: #FFFFFF;
|
||||
|
@ -81,7 +79,7 @@
|
|||
#enter_room_button {
|
||||
width: 73px;
|
||||
height: 45px;
|
||||
background-color: #16a8fe;
|
||||
background-color: #21B9FC;
|
||||
moz-border-radius: 1px;
|
||||
-webkit-border-radius: 1px;
|
||||
color: #ffffff;
|
||||
|
@ -89,7 +87,6 @@
|
|||
border: none;
|
||||
margin-top: 5px;
|
||||
font-size: 19px;
|
||||
font-family: Helvetica;
|
||||
padding-top: 6px;
|
||||
outline: none;
|
||||
float:left;
|
||||
|
@ -136,7 +133,6 @@
|
|||
width: 885px;
|
||||
height: 100px;
|
||||
color: #ffffff;
|
||||
font-family: Helvetica;
|
||||
font-size: 24px;
|
||||
text-align: center;
|
||||
margin: 0px auto 0px auto;
|
||||
|
@ -171,7 +167,6 @@
|
|||
background-repeat: no-repeat;
|
||||
width: 169px;
|
||||
height: 169px;
|
||||
font-family: Helvetica;
|
||||
color: #ffffff;
|
||||
font-size: 22px;
|
||||
/*font-weight: bold;*/
|
||||
|
@ -183,7 +178,6 @@
|
|||
.feature_description
|
||||
{
|
||||
width: 190px;
|
||||
font-family: Helvetica;
|
||||
color: #ffffff;
|
||||
font-size: 16px;
|
||||
padding-top: 30px;
|
||||
|
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 114 KiB |
Binary file not shown.
Binary file not shown.
|
@ -231,12 +231,16 @@
|
|||
</div>
|
||||
<div id="contactlist" class="right-panel" style="display:none;">
|
||||
<div class="title">
|
||||
<i class="icon-contactList"><span data-i18n="contactlist"></span></i>
|
||||
<i class="icon-contactList"></i>
|
||||
<span data-i18n="contactlist"></span>
|
||||
</div>
|
||||
<ul id="contacts"></ul>
|
||||
</div>
|
||||
<div id="settingsmenu" class="right-panel" style="display:none;">
|
||||
<div class="icon-settings" data-i18n="settings.title"></div>
|
||||
<div class="title">
|
||||
<i class="icon-settings"></i>
|
||||
<span data-i18n="settings.title"></span>
|
||||
</div>
|
||||
<img id="avatar" src="images/avatar2.png"/>
|
||||
<div class="arrow-up"></div>
|
||||
<input type="text" id="setDisplayName" data-i18n="[placeholder]settings.name" placeholder="Name">
|
||||
|
|
|
@ -12,6 +12,16 @@
|
|||
"defaultNickname": "ex. Jane Pink",
|
||||
"defaultLink": "e.g. __url__",
|
||||
"calling": "Calling __name__ ...",
|
||||
"userMedia": {
|
||||
"react-nativeGrantPermissions": "Please grant permissions to use your camera and microphone by pressing <b><i>Allow</i></b> button",
|
||||
"chromeGrantPermissions": "Please grant permissions to use your camera and microphone by pressing <b><i>Allow</i></b> button",
|
||||
"androidGrantPermissions": "Please grant permissions to use your camera and microphone by pressing <b><i>Allow</i></b> button",
|
||||
"firefoxGrantPermissions": "Please grant permissions to use your camera and microphone by pressing <b><i>Share Selected Device</i></b> button",
|
||||
"operaGrantPermissions": "Please grant permissions to use your camera and microphone by pressing <b><i>Allow</i></b> button",
|
||||
"iexplorerGrantPermissions": "Please grant permissions to use your camera and microphone by pressing <b><i>OK</i></b> button",
|
||||
"safariGrantPermissions": "Please grant permissions to use your camera and microphone by pressing <b><i>OK</i></b> button",
|
||||
"nwjsGrantPermissions": "Please grant permissions to use your camera and microphone"
|
||||
},
|
||||
"keyboardShortcuts": {
|
||||
"keyboardShortcuts": "Keyboard shortcuts:",
|
||||
"raiseHand": "Raise your hand.",
|
||||
|
@ -247,11 +257,11 @@
|
|||
"cameraErrorPresent": "There was an error connecting to your camera.",
|
||||
"cameraUnsupportedResolutionError": "Your camera does not support required video resolution.",
|
||||
"cameraUnknownError": "Cannot use camera for a unknown reason.",
|
||||
"cameraPermissionDeniedError": "You have not granted permission to use your camera.",
|
||||
"cameraPermissionDeniedError": "You have not granted permission to use your camera. You can still join the conference but others won't see you. Use the camera button in the address bar to fix this.",
|
||||
"cameraNotFoundError": "Requested camera was not found.",
|
||||
"cameraConstraintFailedError": "Yor camera does not satisfy some of required constraints.",
|
||||
"micUnknownError": "Cannot use microphone for a unknown reason.",
|
||||
"micPermissionDeniedError": "You have not granted permission to use your microphone.",
|
||||
"micPermissionDeniedError": "You have not granted permission to use your microphone. You can still join the conference but others won't hear you. Use the camera button in the address bar to fix this.",
|
||||
"micNotFoundError": "Requested microphone was not found.",
|
||||
"micConstraintFailedError": "Yor microphone does not satisfy some of required constraints."
|
||||
},
|
||||
|
|
|
@ -15,6 +15,7 @@ import CQEvents from '../../service/connectionquality/CQEvents';
|
|||
import EtherpadManager from './etherpad/Etherpad';
|
||||
import SharedVideoManager from './shared_video/SharedVideo';
|
||||
import Recording from "./recording/Recording";
|
||||
import GumPermissionsOverlay from './gum_overlay/UserMediaPermissionsGuidanceOverlay';
|
||||
|
||||
import VideoLayout from "./videolayout/VideoLayout";
|
||||
import FilmStrip from "./videolayout/FilmStrip";
|
||||
|
@ -1420,6 +1421,22 @@ UI.hideRingOverLay = function () {
|
|||
FilmStrip.toggleFilmStrip(true);
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows browser-specific overlay with guidance how to proceed with gUM prompt.
|
||||
* @param {string} browser - name of browser for which to show the guidance
|
||||
* overlay.
|
||||
*/
|
||||
UI.showUserMediaPermissionsGuidanceOverlay = function (browser) {
|
||||
GumPermissionsOverlay.show(browser);
|
||||
};
|
||||
|
||||
/**
|
||||
* Hides browser-specific overlay with guidance how to proceed with gUM prompt.
|
||||
*/
|
||||
UI.hideUserMediaPermissionsGuidanceOverlay = function () {
|
||||
GumPermissionsOverlay.hide();
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows or hides the keyboard shortcuts panel, depending on the current state.'
|
||||
*/
|
||||
|
|
|
@ -52,7 +52,8 @@ function doXmppAuth (room, lockPassword) {
|
|||
// (this will store sessionId in the localStorage)
|
||||
// 3. close new connection
|
||||
// 4. reallocate focus in current room
|
||||
openConnection({id, password}).then(function (connection) {
|
||||
openConnection({id, password, roomName: room.getName()}).then(
|
||||
function (connection) {
|
||||
// open room
|
||||
let newRoom = connection.initJitsiConference(
|
||||
room.getName(), APP.conference._getConferenceOptions()
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/* global $, APP, JitsiMeetJS */
|
||||
|
||||
let $overlay;
|
||||
|
||||
/**
|
||||
* Internal function that constructs overlay with guidance how to proceed with
|
||||
* gUM prompt.
|
||||
* @param {string} browser - name of browser for which to construct the
|
||||
* guidance overlay.
|
||||
*/
|
||||
function buildOverlayHtml(browser) {
|
||||
$overlay = $(`
|
||||
<div class='overlay_container'>
|
||||
<div class='overlay overlay_transparent' />
|
||||
<div class='overlay_content'>
|
||||
<span class="overlay_icon icon-microphone"></span>
|
||||
<span class="overlay_icon icon-camera"></span>
|
||||
<span data-i18n='[html]userMedia.${browser}GrantPermissions'
|
||||
class='overlay_text overlay_text_small'></span>
|
||||
</div>
|
||||
</div>`);
|
||||
|
||||
APP.translation.translateElement($overlay);
|
||||
}
|
||||
|
||||
export default {
|
||||
/**
|
||||
* Shows browser-specific overlay with guidance how to proceed with
|
||||
* gUM prompt.
|
||||
* @param {string} browser - name of browser for which to show the
|
||||
* guidance overlay.
|
||||
*/
|
||||
show(browser) {
|
||||
!$overlay && buildOverlayHtml(browser);
|
||||
|
||||
!$overlay.parents('body').length && $overlay.appendTo('body');
|
||||
},
|
||||
|
||||
/**
|
||||
* Hides browser-specific overlay with guidance how to proceed with
|
||||
* gUM prompt.
|
||||
*/
|
||||
hide() {
|
||||
$overlay && $overlay.detach();
|
||||
}
|
||||
};
|
|
@ -99,7 +99,7 @@ export default {
|
|||
|
||||
var newVal = 100 - data.packetLoss.total;
|
||||
var oldVal = remoteConnectionQuality[id];
|
||||
remoteConnectionQuality[id] = calculateQuality(newVal, oldVal);
|
||||
remoteConnectionQuality[id] = calculateQuality(newVal, oldVal || 100);
|
||||
|
||||
eventEmitter.emit(
|
||||
CQEvents.REMOTESTATS_UPDATED, id, remoteConnectionQuality[id],
|
||||
|
|
|
@ -191,8 +191,11 @@ export default {
|
|||
|
||||
if (audioRequested && videoRequested) {
|
||||
// First we try to create both audio and video tracks together.
|
||||
return createLocalTracks(
|
||||
['audio', 'video'], cameraDeviceId, micDeviceId)
|
||||
return createLocalTracks({
|
||||
devices: ['audio', 'video'],
|
||||
cameraDeviceId: cameraDeviceId,
|
||||
micDeviceId: micDeviceId
|
||||
})
|
||||
// If we fail to do this, try to create them separately.
|
||||
.catch(() => Promise.all([
|
||||
createAudioTrack(false).then(([stream]) => stream),
|
||||
|
@ -215,7 +218,11 @@ export default {
|
|||
}
|
||||
|
||||
function createAudioTrack(showError) {
|
||||
return createLocalTracks(['audio'], null, micDeviceId)
|
||||
return createLocalTracks({
|
||||
devices: ['audio'],
|
||||
cameraDeviceId: null,
|
||||
micDeviceId: micDeviceId
|
||||
})
|
||||
.catch(err => {
|
||||
audioTrackError = err;
|
||||
showError && APP.UI.showDeviceErrorDialog(err, null);
|
||||
|
@ -224,7 +231,11 @@ export default {
|
|||
}
|
||||
|
||||
function createVideoTrack(showError) {
|
||||
return createLocalTracks(['video'], cameraDeviceId, null)
|
||||
return createLocalTracks({
|
||||
devices: ['video'],
|
||||
cameraDeviceId: cameraDeviceId,
|
||||
micDeviceId: null
|
||||
})
|
||||
.catch(err => {
|
||||
videoTrackError = err;
|
||||
showError && APP.UI.showDeviceErrorDialog(null, err);
|
||||
|
|
Loading…
Reference in New Issue