Merge pull request #1775 from jitsi/start_screen
Add config.startScreenSharing
This commit is contained in:
commit
c97daff506
490
conference.js
490
conference.js
|
@ -72,11 +72,6 @@ let connection;
|
|||
let localAudio, localVideo;
|
||||
let initialAudioMutedState = false, initialVideoMutedState = false;
|
||||
|
||||
/**
|
||||
* Indicates whether extension external installation is in progress or not.
|
||||
*/
|
||||
let DSExternalInstallationInProgress = false;
|
||||
|
||||
import {VIDEO_CONTAINER_TYPE} from "./modules/UI/videolayout/VideoContainer";
|
||||
|
||||
/*
|
||||
|
@ -118,68 +113,6 @@ 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,
|
||||
videoOnlyError;
|
||||
|
||||
JitsiMeetJS.mediaDevices.addEventListener(
|
||||
JitsiMeetJS.events.mediaDevices.PERMISSION_PROMPT_IS_SHOWN,
|
||||
browser =>
|
||||
APP.store.dispatch(
|
||||
mediaPermissionPromptVisibilityChanged(true, 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 => {
|
||||
audioOnlyError = err;
|
||||
|
||||
// Try video only...
|
||||
return createLocalTracks({ devices: ['video'] }, true);
|
||||
})
|
||||
.catch(err => {
|
||||
videoOnlyError = err;
|
||||
|
||||
return [];
|
||||
});
|
||||
|
||||
return Promise.all([ tryCreateLocalTracks, connect(roomName) ])
|
||||
.then(([tracks, con]) => {
|
||||
APP.store.dispatch(mediaPermissionPromptVisibilityChanged(false));
|
||||
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, videoOnlyError);
|
||||
} 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
|
||||
|
@ -567,6 +500,106 @@ export default {
|
|||
* Whether the local participant is the dominant speaker in the conference.
|
||||
*/
|
||||
isDominantSpeaker: false,
|
||||
|
||||
/**
|
||||
* Creates local media tracks and connects to a room. Will show error
|
||||
* dialogs in case accessing the 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
|
||||
* @param {object} options
|
||||
* @param {boolean} options.startScreenSharing - if <tt>true</tt> should
|
||||
* start with screensharing instead of camera video.
|
||||
* @returns {Promise.<JitsiLocalTrack[], JitsiConnection>}
|
||||
*/
|
||||
createInitialLocalTracksAndConnect(roomName, options = {}) {
|
||||
let audioAndVideoError,
|
||||
audioOnlyError,
|
||||
screenSharingError,
|
||||
videoOnlyError;
|
||||
|
||||
JitsiMeetJS.mediaDevices.addEventListener(
|
||||
JitsiMeetJS.events.mediaDevices.PERMISSION_PROMPT_IS_SHOWN,
|
||||
browser =>
|
||||
APP.store.dispatch(
|
||||
mediaPermissionPromptVisibilityChanged(true, browser))
|
||||
);
|
||||
|
||||
// First try to retrieve both audio and video.
|
||||
let tryCreateLocalTracks;
|
||||
|
||||
// FIXME the logic about trying to go audio only on error is duplicated
|
||||
if (options.startScreenSharing) {
|
||||
tryCreateLocalTracks = this._createDesktopTrack()
|
||||
.then(desktopStream => {
|
||||
return createLocalTracks({ devices: ['audio'] }, true)
|
||||
.then(([audioStream]) => {
|
||||
return [desktopStream, audioStream];
|
||||
})
|
||||
.catch(error => {
|
||||
audioOnlyError = error;
|
||||
return [desktopStream];
|
||||
});
|
||||
}).catch(error => {
|
||||
logger.error('Failed to obtain desktop stream', error);
|
||||
screenSharingError = error;
|
||||
return createLocalTracks({ devices: ['audio'] }, true);
|
||||
}).catch(error => {
|
||||
audioOnlyError = error;
|
||||
return [];
|
||||
});
|
||||
} else {
|
||||
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 => {
|
||||
audioOnlyError = err;
|
||||
|
||||
// Try video only...
|
||||
return createLocalTracks({devices: ['video']}, true);
|
||||
})
|
||||
.catch(err => {
|
||||
videoOnlyError = err;
|
||||
|
||||
return [];
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.all([ tryCreateLocalTracks, connect(roomName) ])
|
||||
.then(([tracks, con]) => {
|
||||
APP.store.dispatch(
|
||||
mediaPermissionPromptVisibilityChanged(false));
|
||||
// FIXME If there will be microphone error it will cover any
|
||||
// screensharing dialog, but it's still better than in
|
||||
// the reverse order where the screensharing dialog will
|
||||
// sometimes be closing the microphone alert ($.prompt.close();
|
||||
// is called). Need to figure out dialogs chaining to fix that.
|
||||
if (screenSharingError) {
|
||||
this._handleScreenSharingError(screenSharingError);
|
||||
}
|
||||
if (audioAndVideoError || audioOnlyError) {
|
||||
if (audioOnlyError || videoOnlyError) {
|
||||
// If both requests for 'audio' + 'video' and 'audio'
|
||||
// only failed, we assume that there are some problems
|
||||
// with user's microphone and show corresponding dialog.
|
||||
APP.UI.showDeviceErrorDialog(
|
||||
audioOnlyError, videoOnlyError);
|
||||
} 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];
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Open new connection and join to the conference.
|
||||
* @param {object} options
|
||||
|
@ -602,7 +635,10 @@ export default {
|
|||
{enableAnalyticsLogging: analytics.isEnabled()}, config)
|
||||
).then(() => {
|
||||
analytics.init();
|
||||
return createInitialLocalTracksAndConnect(options.roomName);
|
||||
return this.createInitialLocalTracksAndConnect(
|
||||
options.roomName, {
|
||||
startScreenSharing: config.startScreenSharing
|
||||
});
|
||||
}).then(([tracks, con]) => {
|
||||
tracks.forEach(track => {
|
||||
if((track.isAudioTrack() && initialAudioMutedState)
|
||||
|
@ -1215,7 +1251,6 @@ export default {
|
|||
|
||||
/**
|
||||
* Toggles between screensharing and camera video.
|
||||
* @param {boolean} [shareScreen]
|
||||
* @param {Object} [options] - Screen sharing options that will be passed to
|
||||
* createLocalTracks.
|
||||
* @param {Array<string>} [options.desktopSharingSources] - Array with the
|
||||
|
@ -1239,119 +1274,207 @@ export default {
|
|||
}
|
||||
|
||||
if (!this._untoggleScreenSharing) {
|
||||
this.videoSwitchInProgress = true;
|
||||
let externalInstallation = false;
|
||||
const didHaveVideo = Boolean(localVideo);
|
||||
const wasVideoMuted = this.videoMuted;
|
||||
|
||||
return createLocalTracks({
|
||||
desktopSharingSources: options.desktopSharingSources,
|
||||
devices: ['desktop'],
|
||||
desktopSharingExtensionExternalInstallation: {
|
||||
interval: 500,
|
||||
checkAgain: () => {
|
||||
return DSExternalInstallationInProgress;
|
||||
},
|
||||
listener: (status, url) => {
|
||||
switch(status) {
|
||||
case "waitingForExtension":
|
||||
DSExternalInstallationInProgress = true;
|
||||
externalInstallation = true;
|
||||
APP.UI.showExtensionExternalInstallationDialog(
|
||||
url);
|
||||
break;
|
||||
case "extensionFound":
|
||||
if(externalInstallation) //close the dialog
|
||||
$.prompt.close();
|
||||
break;
|
||||
default:
|
||||
//Unknown status
|
||||
}
|
||||
}
|
||||
}
|
||||
}).then(([stream]) => {
|
||||
// Stores the "untoggle" handler which remembers whether was
|
||||
// there any video before and whether was it muted.
|
||||
this._untoggleScreenSharing
|
||||
= this._turnScreenSharingOff
|
||||
.bind(this, didHaveVideo, wasVideoMuted);
|
||||
DSExternalInstallationInProgress = false;
|
||||
// close external installation dialog on success.
|
||||
if(externalInstallation)
|
||||
$.prompt.close();
|
||||
stream.on(
|
||||
TrackEvents.LOCAL_TRACK_STOPPED,
|
||||
() => {
|
||||
// If the stream was stopped during screen sharing
|
||||
// session then we should switch back to video.
|
||||
if (this.isSharingScreen){
|
||||
this._untoggleScreenSharing
|
||||
&& this._untoggleScreenSharing();
|
||||
}
|
||||
}
|
||||
);
|
||||
return this.useVideoStream(stream);
|
||||
}).then(() => {
|
||||
this.videoSwitchInProgress = false;
|
||||
JitsiMeetJS.analytics.sendEvent(
|
||||
'conference.sharingDesktop.start');
|
||||
logger.log('sharing local desktop');
|
||||
}).catch(err => {
|
||||
// close external installation dialog to show the error.
|
||||
if(externalInstallation)
|
||||
$.prompt.close();
|
||||
this.videoSwitchInProgress = false;
|
||||
|
||||
if (err.name === TrackErrors.CHROME_EXTENSION_USER_CANCELED) {
|
||||
return Promise.reject(err);
|
||||
}
|
||||
|
||||
// Pawel: With this call I'm trying to preserve the original
|
||||
// behaviour although it is not clear why would we "untoggle"
|
||||
// on failure. I suppose it was to restore video in case there
|
||||
// was some problem during "this.useVideoStream(desktopStream)".
|
||||
// It's important to note that the handler will not be available
|
||||
// if we fail early on trying to get desktop media (which makes
|
||||
// sense, because the camera video is still being used, so
|
||||
// nothing to "untoggle").
|
||||
if (this._untoggleScreenSharing) {
|
||||
this._untoggleScreenSharing();
|
||||
}
|
||||
|
||||
logger.error('failed to share local desktop', err);
|
||||
|
||||
if (err.name === TrackErrors.FIREFOX_EXTENSION_NEEDED) {
|
||||
APP.UI.showExtensionRequiredDialog(
|
||||
config.desktopSharingFirefoxExtensionURL
|
||||
);
|
||||
return Promise.reject(err);
|
||||
}
|
||||
|
||||
// Handling:
|
||||
// TrackErrors.PERMISSION_DENIED
|
||||
// TrackErrors.CHROME_EXTENSION_INSTALLATION_ERROR
|
||||
// TrackErrors.GENERAL
|
||||
// and any other
|
||||
let dialogTxt;
|
||||
let dialogTitleKey;
|
||||
|
||||
if (err.name === TrackErrors.PERMISSION_DENIED) {
|
||||
dialogTxt = APP.translation.generateTranslationHTML(
|
||||
"dialog.screenSharingPermissionDeniedError");
|
||||
dialogTitleKey = "dialog.error";
|
||||
} else {
|
||||
dialogTxt = APP.translation.generateTranslationHTML(
|
||||
"dialog.failtoinstall");
|
||||
dialogTitleKey = "dialog.permissionDenied";
|
||||
}
|
||||
|
||||
APP.UI.messageHandler.openDialog(
|
||||
dialogTitleKey, dialogTxt, false);
|
||||
});
|
||||
return this._switchToScreenSharing(options);
|
||||
} else {
|
||||
return this._untoggleScreenSharing();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates desktop (screensharing) {@link JitsiLocalTrack}
|
||||
* @param {Object} [options] - Screen sharing options that will be passed to
|
||||
* createLocalTracks.
|
||||
*
|
||||
* @return {Promise.<JitsiLocalTrack>} - A Promise resolved with
|
||||
* {@link JitsiLocalTrack} for the screensharing or rejected with
|
||||
* {@link JitsiTrackError}.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_createDesktopTrack(options = {}) {
|
||||
let externalInstallation = false;
|
||||
let DSExternalInstallationInProgress = false;
|
||||
const didHaveVideo = Boolean(localVideo);
|
||||
const wasVideoMuted = this.videoMuted;
|
||||
|
||||
return createLocalTracks({
|
||||
desktopSharingSources: options.desktopSharingSources,
|
||||
devices: ['desktop'],
|
||||
desktopSharingExtensionExternalInstallation: {
|
||||
interval: 500,
|
||||
checkAgain: () => {
|
||||
return DSExternalInstallationInProgress;
|
||||
},
|
||||
listener: (status, url) => {
|
||||
switch(status) {
|
||||
case "waitingForExtension": {
|
||||
DSExternalInstallationInProgress = true;
|
||||
externalInstallation = true;
|
||||
const listener = () => {
|
||||
// Wait a little bit more just to be sure that
|
||||
// we won't miss the extension installation
|
||||
setTimeout(
|
||||
() => {
|
||||
DSExternalInstallationInProgress = false;
|
||||
}, 500);
|
||||
APP.UI.removeListener(
|
||||
UIEvents.EXTERNAL_INSTALLATION_CANCELED,
|
||||
listener);
|
||||
};
|
||||
APP.UI.addListener(
|
||||
UIEvents.EXTERNAL_INSTALLATION_CANCELED,
|
||||
listener);
|
||||
APP.UI.showExtensionExternalInstallationDialog(url);
|
||||
break;
|
||||
}
|
||||
case "extensionFound": {
|
||||
if (externalInstallation) { //close the dialog
|
||||
$.prompt.close();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
//Unknown status
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}).then(([desktopStream]) => {
|
||||
// Stores the "untoggle" handler which remembers whether was
|
||||
// there any video before and whether was it muted.
|
||||
this._untoggleScreenSharing
|
||||
= this._turnScreenSharingOff
|
||||
.bind(this, didHaveVideo, wasVideoMuted);
|
||||
desktopStream.on(
|
||||
TrackEvents.LOCAL_TRACK_STOPPED,
|
||||
() => {
|
||||
// If the stream was stopped during screen sharing
|
||||
// session then we should switch back to video.
|
||||
if (this.isSharingScreen) {
|
||||
this._untoggleScreenSharing
|
||||
&& this._untoggleScreenSharing();
|
||||
}
|
||||
}
|
||||
);
|
||||
// close external installation dialog on success.
|
||||
if (externalInstallation) {
|
||||
$.prompt.close();
|
||||
}
|
||||
return desktopStream;
|
||||
}, error => {
|
||||
DSExternalInstallationInProgress = false;
|
||||
// close external installation dialog on success.
|
||||
if (externalInstallation) {
|
||||
$.prompt.close();
|
||||
}
|
||||
throw error;
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Tries to switch to the screenshairng mode by disposing camera stream and
|
||||
* replacing it with a desktop one.
|
||||
*
|
||||
* @param {Object} [options] - Screen sharing options that will be passed to
|
||||
* createLocalTracks.
|
||||
*
|
||||
* @return {Promise} - A Promise resolved if the operation succeeds or
|
||||
* rejected with some unknown type of error in case it fails. Promise will
|
||||
* be rejected immediately if {@link videoSwitchInProgress} is true.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
_switchToScreenSharing(options = {}) {
|
||||
if (this.videoSwitchInProgress) {
|
||||
return Promise.reject('Switch in progress.');
|
||||
}
|
||||
|
||||
this.videoSwitchInProgress = true;
|
||||
return this._createDesktopTrack(options).then(stream => {
|
||||
return this.useVideoStream(stream);
|
||||
}).then(() => {
|
||||
this.videoSwitchInProgress = false;
|
||||
JitsiMeetJS.analytics.sendEvent('conference.sharingDesktop.start');
|
||||
logger.log('sharing local desktop');
|
||||
}).catch(error => {
|
||||
this.videoSwitchInProgress = false;
|
||||
// Pawel: With this call I'm trying to preserve the original
|
||||
// behaviour although it is not clear why would we "untoggle"
|
||||
// on failure. I suppose it was to restore video in case there
|
||||
// was some problem during "this.useVideoStream(desktopStream)".
|
||||
// It's important to note that the handler will not be available
|
||||
// if we fail early on trying to get desktop media (which makes
|
||||
// sense, because the camera video is still being used, so
|
||||
// nothing to "untoggle").
|
||||
if (this._untoggleScreenSharing) {
|
||||
this._untoggleScreenSharing();
|
||||
}
|
||||
|
||||
// FIXME the code inside of _handleScreenSharingError is
|
||||
// asynchronous, but does not return a Promise and is not part of
|
||||
// the current Promise chain.
|
||||
this._handleScreenSharingError(error);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles {@link JitsiTrackError} returned by the lib-jitsi-meet when
|
||||
* trying to create screensharing track. It will either do nothing if
|
||||
* the dialog was canceled on user's request or display inline installation
|
||||
* dialog and ask the user to install the extension, once the extension is
|
||||
* installed it will switch the conference to screensharing. The last option
|
||||
* is that an unrecoverable error dialog will be displayed.
|
||||
* @param {JitsiTrackError} error - The error returned by
|
||||
* {@link _createDesktopTrack} Promise.
|
||||
* @private
|
||||
*/
|
||||
_handleScreenSharingError(error) {
|
||||
if (error.name === TrackErrors.CHROME_EXTENSION_USER_CANCELED) {
|
||||
return;
|
||||
}
|
||||
|
||||
logger.error('failed to share local desktop', error);
|
||||
|
||||
if (error.name === TrackErrors.CHROME_EXTENSION_USER_GESTURE_REQUIRED) {
|
||||
// If start with screen sharing the extension will fail to install
|
||||
// (if not found), because the request has been triggered by the
|
||||
// script. Show a dialog which asks user to click "install" and try
|
||||
// again switching to the screen sharing.
|
||||
APP.UI.showExtensionInlineInstallationDialog(
|
||||
() => {
|
||||
this.toggleScreenSharing();
|
||||
}
|
||||
);
|
||||
|
||||
return;
|
||||
} else if (error.name === TrackErrors.FIREFOX_EXTENSION_NEEDED) {
|
||||
APP.UI.showExtensionRequiredDialog(
|
||||
config.desktopSharingFirefoxExtensionURL
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Handling:
|
||||
// TrackErrors.PERMISSION_DENIED
|
||||
// TrackErrors.CHROME_EXTENSION_INSTALLATION_ERROR
|
||||
// TrackErrors.GENERAL
|
||||
// and any other
|
||||
let dialogTxt;
|
||||
let dialogTitleKey;
|
||||
|
||||
if (error.name === TrackErrors.PERMISSION_DENIED) {
|
||||
dialogTxt = APP.translation.generateTranslationHTML(
|
||||
"dialog.screenSharingPermissionDeniedError");
|
||||
dialogTitleKey = "dialog.error";
|
||||
} else {
|
||||
dialogTxt = APP.translation.generateTranslationHTML(
|
||||
"dialog.failtoinstall");
|
||||
dialogTitleKey = "dialog.permissionDenied";
|
||||
}
|
||||
|
||||
APP.UI.messageHandler.openDialog(dialogTitleKey, dialogTxt, false);
|
||||
},
|
||||
/**
|
||||
* Setup interaction between conference and UI.
|
||||
*/
|
||||
|
@ -1637,17 +1760,6 @@ export default {
|
|||
APP.UI.updateDTMFSupport(isDTMFSupported);
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.EXTERNAL_INSTALLATION_CANCELED, () => {
|
||||
// Wait a little bit more just to be sure that we won't miss the
|
||||
// extension installation
|
||||
setTimeout(() => DSExternalInstallationInProgress = false, 500);
|
||||
});
|
||||
APP.UI.addListener(UIEvents.OPEN_EXTENSION_STORE, (url) => {
|
||||
window.open(
|
||||
url, "extension_store_window",
|
||||
"resizable,scrollbars=yes,status=1");
|
||||
});
|
||||
|
||||
APP.UI.addListener(UIEvents.AUDIO_MUTED, muteLocalAudio);
|
||||
APP.UI.addListener(UIEvents.VIDEO_MUTED, muted => {
|
||||
if (this.isAudioOnly() && !muted) {
|
||||
|
|
|
@ -72,6 +72,7 @@ var config = { // eslint-disable-line no-unused-vars
|
|||
// page redirection when call is hangup
|
||||
disableSimulcast: false,
|
||||
// requireDisplayName: true, // Forces the participants that doesn't have display name to enter it when they enter the room.
|
||||
startScreenSharing: false, // Will try to start with screensharing instead of camera
|
||||
// startAudioMuted: 10, // every participant after the Nth will start audio muted
|
||||
// startVideoMuted: 10, // every participant after the Nth will start video muted
|
||||
// defaultLanguage: "en",
|
||||
|
|
|
@ -333,6 +333,8 @@
|
|||
"goToStore": "Go to the webstore",
|
||||
"externalInstallationTitle": "Extension required",
|
||||
"externalInstallationMsg": "You need to install our desktop sharing extension.",
|
||||
"inlineInstallationMsg": "You need to install our desktop sharing extension.",
|
||||
"inlineInstallExtension": "Install now",
|
||||
"muteParticipantTitle": "Mute this participant?",
|
||||
"muteParticipantBody": "You won't be able to unmute them, but they can unmute themselves at any time.",
|
||||
"muteParticipantButton": "Mute",
|
||||
|
|
|
@ -1158,15 +1158,34 @@ UI.showExtensionRequiredDialog = function (url) {
|
|||
* @param url {string} the url of the extension.
|
||||
*/
|
||||
UI.showExtensionExternalInstallationDialog = function (url) {
|
||||
let openedWindow = null;
|
||||
|
||||
let submitFunction = function(e,v){
|
||||
if (v) {
|
||||
e.preventDefault();
|
||||
eventEmitter.emit(UIEvents.OPEN_EXTENSION_STORE, url);
|
||||
if (openedWindow === null || openedWindow.closed) {
|
||||
openedWindow
|
||||
= window.open(
|
||||
url,
|
||||
"extension_store_window",
|
||||
"resizable,scrollbars=yes,status=1");
|
||||
} else {
|
||||
openedWindow.focus();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let closeFunction = function () {
|
||||
eventEmitter.emit(UIEvents.EXTERNAL_INSTALLATION_CANCELED);
|
||||
let closeFunction = function (e, v) {
|
||||
if (openedWindow) {
|
||||
// Ideally we would close the popup, but this does not seem to work
|
||||
// on Chrome. Leaving it uncommented in case it could work
|
||||
// in some version.
|
||||
openedWindow.close();
|
||||
openedWindow = null;
|
||||
}
|
||||
if (!v) {
|
||||
eventEmitter.emit(UIEvents.EXTERNAL_INSTALLATION_CANCELED);
|
||||
}
|
||||
};
|
||||
|
||||
messageHandler.openTwoButtonDialog({
|
||||
|
@ -1179,6 +1198,36 @@ UI.showExtensionExternalInstallationDialog = function (url) {
|
|||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Shows a dialog which asks user to install the extension. This one is
|
||||
* displayed after installation is triggered from the script, but fails because
|
||||
* it must be initiated by user gesture.
|
||||
* @param callback {function} function to be executed after user clicks
|
||||
* the install button - it should make another attempt to install the extension.
|
||||
*/
|
||||
UI.showExtensionInlineInstallationDialog = function (callback) {
|
||||
let submitFunction = function(e,v){
|
||||
if (v) {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
let closeFunction = function (e, v) {
|
||||
if (!v) {
|
||||
eventEmitter.emit(UIEvents.EXTERNAL_INSTALLATION_CANCELED);
|
||||
}
|
||||
};
|
||||
|
||||
messageHandler.openTwoButtonDialog({
|
||||
titleKey: 'dialog.externalInstallationTitle',
|
||||
msgKey: 'dialog.inlineInstallationMsg',
|
||||
leftButtonKey: 'dialog.inlineInstallExtension',
|
||||
submitFunction,
|
||||
loadedFunction: $.noop,
|
||||
closeFunction
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Shows dialog with combined information about camera and microphone errors.
|
||||
|
|
|
@ -97,12 +97,6 @@ export default {
|
|||
// changed.
|
||||
RESOLUTION_CHANGED: "UI.resolution_changed",
|
||||
|
||||
/**
|
||||
* Notifies that the button "Go to webstore" is pressed on the dialog for
|
||||
* external extension installation.
|
||||
*/
|
||||
OPEN_EXTENSION_STORE: "UI.open_extension_store",
|
||||
|
||||
/**
|
||||
* Notifies that the button "Cancel" is pressed on the dialog for
|
||||
* external extension installation.
|
||||
|
|
Loading…
Reference in New Issue