Show dialog for GUM errors
This commit is contained in:
parent
48b219111d
commit
448fcf36b6
111
conference.js
111
conference.js
|
@ -375,17 +375,39 @@ export default {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let audioAndVideoError, audioOnlyError;
|
||||||
|
|
||||||
return JitsiMeetJS.init(config).then(() => {
|
return JitsiMeetJS.init(config).then(() => {
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
// try to retrieve audio and video
|
// try to retrieve audio and video
|
||||||
createLocalTracks(['audio', 'video'])
|
createLocalTracks(['audio', 'video'])
|
||||||
// if failed then try to retrieve only audio
|
// if failed then try to retrieve only audio
|
||||||
.catch(() => createLocalTracks(['audio']))
|
.catch(err => {
|
||||||
|
audioAndVideoError = err;
|
||||||
|
return createLocalTracks(['audio']);
|
||||||
|
})
|
||||||
// if audio also failed then just return empty array
|
// if audio also failed then just return empty array
|
||||||
.catch(() => []),
|
.catch(err => {
|
||||||
|
audioOnlyError = err;
|
||||||
|
return [];
|
||||||
|
}),
|
||||||
connect(options.roomName)
|
connect(options.roomName)
|
||||||
]);
|
]);
|
||||||
}).then(([tracks, con]) => {
|
}).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('microphone', audioOnlyError);
|
||||||
|
} 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('camera', audioAndVideoError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
console.log('initialized with %s local tracks', tracks.length);
|
console.log('initialized with %s local tracks', tracks.length);
|
||||||
APP.connection = connection = con;
|
APP.connection = connection = con;
|
||||||
this._createRoom(tracks);
|
this._createRoom(tracks);
|
||||||
|
@ -541,9 +563,11 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
function createNewTracks(type, cameraDeviceId, micDeviceId) {
|
function createNewTracks(type, cameraDeviceId, micDeviceId) {
|
||||||
|
let audioOnlyError, videoOnlyError;
|
||||||
|
|
||||||
return createLocalTracks(type, cameraDeviceId, micDeviceId)
|
return createLocalTracks(type, cameraDeviceId, micDeviceId)
|
||||||
.then(onTracksCreated)
|
.then(onTracksCreated)
|
||||||
.catch(() => {
|
.catch((err) => {
|
||||||
// if we tried to create both audio and video tracks
|
// if we tried to create both audio and video tracks
|
||||||
// at once and failed, let's try again only with
|
// at once and failed, let's try again only with
|
||||||
// audio. Such situation may happen in case if we
|
// audio. Such situation may happen in case if we
|
||||||
|
@ -553,16 +577,21 @@ export default {
|
||||||
&& type.indexOf('video') !== -1) {
|
&& type.indexOf('video') !== -1) {
|
||||||
return createLocalTracks(['audio'], null,
|
return createLocalTracks(['audio'], null,
|
||||||
micDeviceId);
|
micDeviceId);
|
||||||
|
} else if (type.indexOf('audio') !== -1) {
|
||||||
|
audioOnlyError = err;
|
||||||
|
} else if (type.indexOf('video') !== -1) {
|
||||||
|
videoOnlyError = err;
|
||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
.then(onTracksCreated)
|
.then(onTracksCreated)
|
||||||
.catch(() => {
|
.catch((err) => {
|
||||||
// if we tried to create both audio and video tracks
|
// if we tried to create both audio and video tracks
|
||||||
// at once and failed, let's try again only with
|
// at once and failed, let's try again only with
|
||||||
// video. Such situation may happen in case if we
|
// video. Such situation may happen in case if we
|
||||||
// granted access only to camera, but not to
|
// granted access only to camera, but not to
|
||||||
// microphone.
|
// microphone.
|
||||||
|
audioOnlyError = err;
|
||||||
if (type.indexOf('audio') !== -1
|
if (type.indexOf('audio') !== -1
|
||||||
&& type.indexOf('video') !== -1) {
|
&& type.indexOf('video') !== -1) {
|
||||||
return createLocalTracks(['video'],
|
return createLocalTracks(['video'],
|
||||||
|
@ -571,8 +600,18 @@ export default {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then(onTracksCreated)
|
.then(onTracksCreated)
|
||||||
.catch(() => {
|
.catch((err) => {
|
||||||
// can't do anything in this case, so just ignore;
|
videoOnlyError = err;
|
||||||
|
|
||||||
|
if (videoOnlyError) {
|
||||||
|
APP.UI.showDeviceErrorDialog(
|
||||||
|
'camera', videoOnlyError);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (audioOnlyError) {
|
||||||
|
APP.UI.showDeviceErrorDialog(
|
||||||
|
'microphone', audioOnlyError);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -896,13 +935,13 @@ export default {
|
||||||
this.isSharingScreen = stream.videoType === 'desktop';
|
this.isSharingScreen = stream.videoType === 'desktop';
|
||||||
|
|
||||||
APP.UI.addLocalStream(stream);
|
APP.UI.addLocalStream(stream);
|
||||||
|
|
||||||
|
stream.videoType === 'camera' && APP.UI.enableCameraButton();
|
||||||
} else {
|
} else {
|
||||||
this.videoMuted = false;
|
this.videoMuted = false;
|
||||||
this.isSharingScreen = false;
|
this.isSharingScreen = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream.videoType === 'camera' && APP.UI.enableCameraButton();
|
|
||||||
|
|
||||||
APP.UI.setVideoMuted(this.localId, this.videoMuted);
|
APP.UI.setVideoMuted(this.localId, this.videoMuted);
|
||||||
|
|
||||||
APP.UI.updateDesktopSharingButtons();
|
APP.UI.updateDesktopSharingButtons();
|
||||||
|
@ -990,21 +1029,22 @@ export default {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: handle Permission error
|
|
||||||
|
|
||||||
// Handling:
|
// Handling:
|
||||||
|
// TrackErrors.PERMISSION_DENIED
|
||||||
// TrackErrors.CHROME_EXTENSION_INSTALLATION_ERROR
|
// TrackErrors.CHROME_EXTENSION_INSTALLATION_ERROR
|
||||||
// TrackErrors.GENERAL
|
// TrackErrors.GENERAL
|
||||||
// and any other
|
// and any other
|
||||||
let dialogTxt = APP.translation
|
let dialogTxt = APP.translation.generateTranslationHTML(
|
||||||
.generateTranslationHTML("dialog.failtoinstall");
|
err.name === TrackErrors.PERMISSION_DENIED
|
||||||
let dialogTitle = APP.translation
|
? "dialog.screenSharingPermissionDeniedError"
|
||||||
.generateTranslationHTML("dialog.error");
|
: "dialog.failtoinstall");
|
||||||
APP.UI.messageHandler.openDialog(
|
|
||||||
dialogTitle,
|
let dialogTitle = APP.translation.generateTranslationHTML(
|
||||||
dialogTxt,
|
err.name === TrackErrors.PERMISSION_DENIED
|
||||||
false
|
? "dialog.permissionDenied"
|
||||||
);
|
: "dialog.error");
|
||||||
|
|
||||||
|
APP.UI.messageHandler.openDialog(dialogTitle, dialogTxt, false);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
createLocalTracks(['video']).then(
|
createLocalTracks(['video']).then(
|
||||||
|
@ -1016,6 +1056,8 @@ export default {
|
||||||
this.useVideoStream(null);
|
this.useVideoStream(null);
|
||||||
this.videoSwitchInProgress = false;
|
this.videoSwitchInProgress = false;
|
||||||
console.error('failed to share local video', err);
|
console.error('failed to share local video', err);
|
||||||
|
|
||||||
|
APP.UI.showDeviceErrorDialog('camera', err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1357,22 +1399,32 @@ export default {
|
||||||
APP.UI.addListener(
|
APP.UI.addListener(
|
||||||
UIEvents.VIDEO_DEVICE_CHANGED,
|
UIEvents.VIDEO_DEVICE_CHANGED,
|
||||||
(cameraDeviceId) => {
|
(cameraDeviceId) => {
|
||||||
APP.settings.setCameraDeviceId(cameraDeviceId);
|
createLocalTracks(['video'])
|
||||||
createLocalTracks(['video']).then(([stream]) => {
|
.then(([stream]) => {
|
||||||
this.useVideoStream(stream);
|
this.useVideoStream(stream);
|
||||||
console.log('switched local video device');
|
console.log('switched local video device');
|
||||||
});
|
APP.settings.setCameraDeviceId(cameraDeviceId);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
APP.UI.showDeviceErrorDialog('camera', err);
|
||||||
|
APP.UI.setSelectedCameraFromSettings();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
APP.UI.addListener(
|
APP.UI.addListener(
|
||||||
UIEvents.AUDIO_DEVICE_CHANGED,
|
UIEvents.AUDIO_DEVICE_CHANGED,
|
||||||
(micDeviceId) => {
|
(micDeviceId) => {
|
||||||
APP.settings.setMicDeviceId(micDeviceId);
|
createLocalTracks(['audio'])
|
||||||
createLocalTracks(['audio']).then(([stream]) => {
|
.then(([stream]) => {
|
||||||
this.useAudioStream(stream);
|
this.useAudioStream(stream);
|
||||||
console.log('switched local audio device');
|
console.log('switched local audio device');
|
||||||
});
|
APP.settings.setMicDeviceId(micDeviceId);
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
APP.UI.showDeviceErrorDialog('microphone', err);
|
||||||
|
APP.UI.setSelectedMicFromSettings();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1383,6 +1435,7 @@ export default {
|
||||||
.then(() => console.log('changed audio output device'))
|
.then(() => console.log('changed audio output device'))
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.error('failed to set audio output device', err);
|
console.error('failed to set audio output device', err);
|
||||||
|
APP.UI.setSelectedAudioOutputFromSettings();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -222,7 +222,19 @@
|
||||||
"stopStreamingWarning": "Are you sure you would like to stop the live streaming?",
|
"stopStreamingWarning": "Are you sure you would like to stop the live streaming?",
|
||||||
"stopRecordingWarning": "Are you sure you would like to stop the recording?",
|
"stopRecordingWarning": "Are you sure you would like to stop the recording?",
|
||||||
"stopLiveStreaming": "Stop live streaming",
|
"stopLiveStreaming": "Stop live streaming",
|
||||||
"stopRecording": "Stop recording"
|
"stopRecording": "Stop recording",
|
||||||
|
"doNotShowWarningAgain": "Don't show this warning again",
|
||||||
|
"permissionDenied": "Permission Denied",
|
||||||
|
"screenSharingPermissionDeniedError": "You have not granted permission to share your screen.",
|
||||||
|
"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.",
|
||||||
|
"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.",
|
||||||
|
"micNotFoundError": "Requested microphone was not found.",
|
||||||
|
"micConstraintFailedError": "Yor microphone does not satisfy some of required constraints."
|
||||||
},
|
},
|
||||||
"email":
|
"email":
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* global APP, $, config, interfaceConfig, toastr */
|
/* global APP, JitsiMeetJS, $, config, interfaceConfig, toastr */
|
||||||
/* jshint -W101 */
|
/* jshint -W101 */
|
||||||
var UI = {};
|
var UI = {};
|
||||||
|
|
||||||
|
@ -38,6 +38,32 @@ let sharedVideoManager;
|
||||||
|
|
||||||
let followMeHandler;
|
let followMeHandler;
|
||||||
|
|
||||||
|
const TrackErrors = JitsiMeetJS.errors.track;
|
||||||
|
|
||||||
|
const JITSI_TRACK_ERROR_TO_MESSAGE_KEY_MAP = {
|
||||||
|
microphone: {},
|
||||||
|
camera: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
JITSI_TRACK_ERROR_TO_MESSAGE_KEY_MAP.camera[TrackErrors.UNSUPPORTED_RESOLUTION]
|
||||||
|
= "dialog.cameraUnsupportedResolutionError";
|
||||||
|
JITSI_TRACK_ERROR_TO_MESSAGE_KEY_MAP.camera[TrackErrors.GENERAL]
|
||||||
|
= "dialog.cameraUnknownError";
|
||||||
|
JITSI_TRACK_ERROR_TO_MESSAGE_KEY_MAP.camera[TrackErrors.PERMISSION_DENIED]
|
||||||
|
= "dialog.cameraPermissionDeniedError";
|
||||||
|
JITSI_TRACK_ERROR_TO_MESSAGE_KEY_MAP.camera[TrackErrors.NOT_FOUND]
|
||||||
|
= "dialog.cameraNotFoundError";
|
||||||
|
JITSI_TRACK_ERROR_TO_MESSAGE_KEY_MAP.camera[TrackErrors.CONSTRAINT_FAILED]
|
||||||
|
= "dialog.cameraConstraintFailedError";
|
||||||
|
JITSI_TRACK_ERROR_TO_MESSAGE_KEY_MAP.microphone[TrackErrors.GENERAL]
|
||||||
|
= "dialog.micUnknownError";
|
||||||
|
JITSI_TRACK_ERROR_TO_MESSAGE_KEY_MAP.microphone[TrackErrors.PERMISSION_DENIED]
|
||||||
|
= "dialog.micPermissionDeniedError";
|
||||||
|
JITSI_TRACK_ERROR_TO_MESSAGE_KEY_MAP.microphone[TrackErrors.NOT_FOUND]
|
||||||
|
= "dialog.micNotFoundError";
|
||||||
|
JITSI_TRACK_ERROR_TO_MESSAGE_KEY_MAP.microphone[TrackErrors.CONSTRAINT_FAILED]
|
||||||
|
= "dialog.micConstraintFailedError";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prompt user for nickname.
|
* Prompt user for nickname.
|
||||||
*/
|
*/
|
||||||
|
@ -1078,6 +1104,28 @@ UI.onAvailableDevicesChanged = function (devices) {
|
||||||
SettingsMenu.changeDevicesList(devices);
|
SettingsMenu.changeDevicesList(devices);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets microphone's <select> element to select microphone ID from settings.
|
||||||
|
*/
|
||||||
|
UI.setSelectedMicFromSettings = function () {
|
||||||
|
SettingsMenu.setSelectedMicFromSettings();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets camera's <select> element to select camera ID from settings.
|
||||||
|
*/
|
||||||
|
UI.setSelectedCameraFromSettings = function () {
|
||||||
|
SettingsMenu.setSelectedCameraFromSettings();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets audio outputs's <select> element to select audio output ID from
|
||||||
|
* settings.
|
||||||
|
*/
|
||||||
|
UI.setSelectedAudioOutputFromSettings = function () {
|
||||||
|
SettingsMenu.setSelectedAudioOutputFromSettings();
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the id of the current video shown on large.
|
* Returns the id of the current video shown on large.
|
||||||
* Currently used by tests (torture).
|
* Currently used by tests (torture).
|
||||||
|
@ -1106,6 +1154,51 @@ UI.showExtensionRequiredDialog = function (url) {
|
||||||
"dialog.firefoxExtensionPrompt", {url: url}));
|
"dialog.firefoxExtensionPrompt", {url: url}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows dialog with information about camera or microphone error.
|
||||||
|
* @param {'microphone'|'camera'} type
|
||||||
|
* @param {JitsiTrackError} error
|
||||||
|
*/
|
||||||
|
UI.showDeviceErrorDialog = function (type, error) {
|
||||||
|
if (type !== "microphone" && type !== "camera") {
|
||||||
|
throw new Error("Invalid device type");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window.localStorage[type + "DoNotShowErrorAgain-" + error.name]
|
||||||
|
=== "true") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let titleKey = error.name === TrackErrors.PERMISSION_DENIED
|
||||||
|
? "dialog.permissionDenied"
|
||||||
|
: "dialog.error",
|
||||||
|
errorMsg = JITSI_TRACK_ERROR_TO_MESSAGE_KEY_MAP[type][error.name],
|
||||||
|
doNotShowAgainMsg = "dialog.doNotShowWarningAgain",
|
||||||
|
title = `<span data-i18n="${titleKey}"></span>`,
|
||||||
|
message = `
|
||||||
|
<h4 data-i18n="${errorMsg}"></h4>
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" id="doNotShowWarningAgain">
|
||||||
|
<span data-i18n="${doNotShowAgainMsg}"></span>
|
||||||
|
</label>`;
|
||||||
|
|
||||||
|
messageHandler.openDialog(
|
||||||
|
title,
|
||||||
|
message,
|
||||||
|
false,
|
||||||
|
{Ok: true},
|
||||||
|
function () {
|
||||||
|
let form = $.prompt.getPrompt(),
|
||||||
|
input = form.find("#doNotShowWarningAgain");
|
||||||
|
|
||||||
|
window.localStorage[type + "DoNotShowErrorAgain-" + error.name]
|
||||||
|
= input.prop("checked");
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
APP.translation.translateElement($(".jqibox"));
|
||||||
|
};
|
||||||
|
|
||||||
UI.updateDevicesAvailability = function (id, devices) {
|
UI.updateDevicesAvailability = function (id, devices) {
|
||||||
VideoLayout.setDeviceAvailabilityIcons(id, devices);
|
VideoLayout.setDeviceAvailabilityIcons(id, devices);
|
||||||
};
|
};
|
||||||
|
|
|
@ -203,6 +203,28 @@ export default {
|
||||||
$('#avatar').attr('src', avatarUrl);
|
$('#avatar').attr('src', avatarUrl);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets microphone's <select> element to select microphone ID from settings.
|
||||||
|
*/
|
||||||
|
setSelectedMicFromSettings () {
|
||||||
|
$('#selectMic').val(Settings.getMicDeviceId());
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets camera's <select> element to select camera ID from settings.
|
||||||
|
*/
|
||||||
|
setSelectedCameraFromSettings () {
|
||||||
|
$('#selectCamera').val(Settings.getCameraDeviceId());
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets audio outputs's <select> element to select audio output ID from
|
||||||
|
* settings.
|
||||||
|
*/
|
||||||
|
setSelectedAudioOutputFromSettings () {
|
||||||
|
$('#selectAudioOutput').val(Settings.getAudioOutputDeviceId());
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change available cameras/microphones or hide selects completely if
|
* Change available cameras/microphones or hide selects completely if
|
||||||
* no devices available.
|
* no devices available.
|
||||||
|
|
Loading…
Reference in New Issue