feat(jwt) deprecate and remove enableFeaturesBasedOnToken

The new behavior is as follows:

IF a user has a token and `features` is not set, we treat it as if the
feature was enabled.

IF a user has a token and `features` is set, we check if the feature
name has a value of "true".

`isJwtFeatureEnabled` also provides a way to specify the default value
in case there is no token.
This commit is contained in:
Saúl Ibarra Corretgé 2022-08-16 14:53:53 +02:00 committed by Saúl Ibarra Corretgé
parent bf222c5094
commit 77d687952d
12 changed files with 50 additions and 193 deletions

View File

@ -618,9 +618,6 @@ var config = {
// Hides the email section under profile settings. // Hides the email section under profile settings.
// hideEmailInSettings: false, // hideEmailInSettings: false,
// Whether or not some features are checked based on token.
// enableFeaturesBasedOnToken: false,
// When enabled the password used for locking a room is restricted to up to the number of digits specified // When enabled the password used for locking a room is restricted to up to the number of digits specified
// default: roomPasswordNumberOfDigits: false, // default: roomPasswordNumberOfDigits: false,
// roomPasswordNumberOfDigits: 10, // roomPasswordNumberOfDigits: 10,

View File

@ -11,7 +11,6 @@
"defaultEmail": "Your Default Email", "defaultEmail": "Your Default Email",
"disabled": "You can't invite people.", "disabled": "You can't invite people.",
"failedToAdd": "Failed to add participants", "failedToAdd": "Failed to add participants",
"footerText": "Dialing out is disabled.",
"googleEmail": "Google Email", "googleEmail": "Google Email",
"inviteMoreHeader": "You are the only one in the meeting", "inviteMoreHeader": "You are the only one in the meeting",
"inviteMoreMailSubject": "Join {{appName}} meeting", "inviteMoreMailSubject": "Join {{appName}} meeting",
@ -286,7 +285,6 @@
"linkMeetingTitle": "Link meeting to Salesforce", "linkMeetingTitle": "Link meeting to Salesforce",
"liveStreaming": "Live Streaming", "liveStreaming": "Live Streaming",
"liveStreamingDisabledBecauseOfActiveRecordingTooltip": "Not possible while recording is active", "liveStreamingDisabledBecauseOfActiveRecordingTooltip": "Not possible while recording is active",
"liveStreamingDisabledTooltip": "Start live stream disabled.",
"localUserControls": "Local user controls", "localUserControls": "Local user controls",
"lockMessage": "Failed to lock the conference.", "lockMessage": "Failed to lock the conference.",
"lockRoom": "Add meeting $t(lockRoomPassword)", "lockRoom": "Add meeting $t(lockRoomPassword)",
@ -341,7 +339,6 @@
"recentlyUsedObjects": "Your recently used objects", "recentlyUsedObjects": "Your recently used objects",
"recording": "Recording", "recording": "Recording",
"recordingDisabledBecauseOfActiveLiveStreamingTooltip": "Not possible while a live stream is active", "recordingDisabledBecauseOfActiveLiveStreamingTooltip": "Not possible while a live stream is active",
"recordingDisabledTooltip": "Start recording disabled.",
"rejoinNow": "Rejoin now", "rejoinNow": "Rejoin now",
"remoteControlAllowedMessage": "{{user}} accepted your remote control request!", "remoteControlAllowedMessage": "{{user}} accepted your remote control request!",
"remoteControlDeniedMessage": "{{user}} rejected your remote control request!", "remoteControlDeniedMessage": "{{user}} rejected your remote control request!",

View File

@ -260,7 +260,6 @@ export interface IConfig {
enableDisplayNameInStats?: boolean; enableDisplayNameInStats?: boolean;
enableEmailInStats?: boolean; enableEmailInStats?: boolean;
enableEncodedTransformSupport?: boolean; enableEncodedTransformSupport?: boolean;
enableFeaturesBasedOnToken?: boolean;
enableForcedReload?: boolean; enableForcedReload?: boolean;
enableIceRestart?: boolean; enableIceRestart?: boolean;
enableInsecureRoomNameWarning?: boolean; enableInsecureRoomNameWarning?: boolean;

View File

@ -2,6 +2,7 @@
import jwtDecode from 'jwt-decode'; import jwtDecode from 'jwt-decode';
import { getLocalParticipant } from '../participants/functions';
import { parseURLParams } from '../util'; import { parseURLParams } from '../util';
import { MEET_FEATURES } from './constants'; import { MEET_FEATURES } from './constants';
@ -31,6 +32,31 @@ export function getJwtName(state: Object) {
return user?.name; return user?.name;
} }
/**
* Check if the given JWT feature is enabled.
*
* @param {Object} state - The app state.
* @param {string} feature - The feature we want to check.
* @param {boolean} ifNoToken - Default value if there is no token.
* @returns {string}
*/
export function isJwtFeatureEnabled(state: Object, feature: string, ifNoToken: boolean = false) {
const { jwt } = state['features/base/jwt'];
if (!jwt) {
return ifNoToken;
}
const { features } = getLocalParticipant(state) || {};
// If `features` is undefined, act as if everything is enabled.
if (typeof features === 'undefined') {
return true;
}
return String(features[feature]) === 'true';
}
/** /**
* Checks whether a given timestamp is a valid UNIX timestamp in seconds. * Checks whether a given timestamp is a valid UNIX timestamp in seconds.
* We convert to miliseconds during the check since `Date` works with miliseconds for UNIX timestamp values. * We convert to miliseconds during the check since `Date` works with miliseconds for UNIX timestamp values.

View File

@ -402,17 +402,6 @@ export function getParticipantPresenceStatus(
return participantById.presence; return participantById.presence;
} }
/**
* Returns true if there is at least 1 participant with screen sharing feature and false otherwise.
*
* @param {(Function|Object)} stateful - The (whole) redux state, or redux's
* {@code getState} function to be used to retrieve the state.
* @returns {boolean}
*/
export function haveParticipantWithScreenSharingFeature(stateful: IStore | Function) {
return toState(stateful)['features/base/participants'].haveParticipantWithScreenSharingFeature;
}
/** /**
* Selectors for getting all remote participants. * Selectors for getting all remote participants.
* *

View File

@ -101,7 +101,6 @@ const DEFAULT_STATE = {
dominantSpeaker: undefined, dominantSpeaker: undefined,
everyoneIsModerator: false, everyoneIsModerator: false,
fakeParticipants: new Map(), fakeParticipants: new Map(),
haveParticipantWithScreenSharingFeature: false,
local: undefined, local: undefined,
localScreenShare: undefined, localScreenShare: undefined,
overwrittenNameList: {}, overwrittenNameList: {},
@ -118,7 +117,6 @@ export interface IParticipantsState {
dominantSpeaker?: string; dominantSpeaker?: string;
everyoneIsModerator: boolean; everyoneIsModerator: boolean;
fakeParticipants: Map<string, Participant>; fakeParticipants: Map<string, Participant>;
haveParticipantWithScreenSharingFeature: boolean;
local?: LocalParticipant; local?: LocalParticipant;
localScreenShare?: Participant; localScreenShare?: Participant;
overwrittenNameList: Object; overwrittenNameList: Object;
@ -255,14 +253,6 @@ ReducerRegistry.register('features/base/participants', (state: IParticipantsStat
} else if (!state.everyoneIsModerator && isModerator) { } else if (!state.everyoneIsModerator && isModerator) {
state.everyoneIsModerator = _isEveryoneModerator(state); state.everyoneIsModerator = _isEveryoneModerator(state);
} }
// haveParticipantWithScreenSharingFeature calculation:
const { features = {} } = participant;
// Currently we use only PARTICIPANT_UPDATED to set a feature to enabled and we never disable it.
if (String(features['screen-sharing']) === 'true') {
state.haveParticipantWithScreenSharingFeature = true;
}
} }
return { return {
@ -401,26 +391,6 @@ ReducerRegistry.register('features/base/participants', (state: IParticipantsStat
state.everyoneIsModerator = _isEveryoneModerator(state); state.everyoneIsModerator = _isEveryoneModerator(state);
} }
const { features = {} } = oldParticipant || {};
if (state.haveParticipantWithScreenSharingFeature && String(features['screen-sharing']) === 'true') {
const { features: localFeatures = {} } = state.local || {};
if (String(localFeatures['screen-sharing']) !== 'true') {
state.haveParticipantWithScreenSharingFeature = false;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
for (const [ key, participant ] of state.remote) {
const { features: f = {} } = participant;
if (String(f['screen-sharing']) === 'true') {
state.haveParticipantWithScreenSharingFeature = true;
break;
}
}
}
}
if (dominantSpeaker === id) { if (dominantSpeaker === id) {
state.dominantSpeaker = undefined; state.dominantSpeaker = undefined;
} }

View File

@ -5,9 +5,8 @@ import React from 'react';
import type { Dispatch } from 'redux'; import type { Dispatch } from 'redux';
import { Avatar } from '../../../../base/avatar'; import { Avatar } from '../../../../base/avatar';
import { translate, translateToHTML } from '../../../../base/i18n'; import { translate } from '../../../../base/i18n';
import { Icon, IconPhone } from '../../../../base/icons'; import { Icon, IconPhone } from '../../../../base/icons';
import { getLocalParticipant } from '../../../../base/participants';
import { MultiSelectAutocomplete } from '../../../../base/react'; import { MultiSelectAutocomplete } from '../../../../base/react';
import { connect } from '../../../../base/redux'; import { connect } from '../../../../base/redux';
import { isVpaasMeeting } from '../../../../jaas/functions'; import { isVpaasMeeting } from '../../../../jaas/functions';
@ -28,11 +27,6 @@ type Props = AbstractProps & {
*/ */
_conference: Object, _conference: Object,
/**
* Whether to show a footer text after the search results as a last element.
*/
_footerTextEnabled: boolean,
/** /**
* Whether the meeting belongs to JaaS user. * Whether the meeting belongs to JaaS user.
*/ */
@ -83,7 +77,6 @@ class InviteContactsForm extends AbstractAddPeopleDialog<Props, State> {
this._onSubmitKeyPress = this._onSubmitKeyPress.bind(this); this._onSubmitKeyPress = this._onSubmitKeyPress.bind(this);
this._parseQueryResults = this._parseQueryResults.bind(this); this._parseQueryResults = this._parseQueryResults.bind(this);
this._setMultiSelectElement = this._setMultiSelectElement.bind(this); this._setMultiSelectElement = this._setMultiSelectElement.bind(this);
this._renderFooterText = this._renderFooterText.bind(this);
this._onKeyDown = this._onKeyDown.bind(this); this._onKeyDown = this._onKeyDown.bind(this);
this._resourceClient = { this._resourceClient = {
@ -135,7 +128,6 @@ class InviteContactsForm extends AbstractAddPeopleDialog<Props, State> {
_sipInviteEnabled, _sipInviteEnabled,
t t
} = this.props; } = this.props;
const footerText = this._renderFooterText();
let isMultiSelectDisabled = this.state.addToCallInProgress; let isMultiSelectDisabled = this.state.addToCallInProgress;
const loadingMessage = 'addPeople.searching'; const loadingMessage = 'addPeople.searching';
const noMatches = 'addPeople.noResults'; const noMatches = 'addPeople.noResults';
@ -163,7 +155,6 @@ class InviteContactsForm extends AbstractAddPeopleDialog<Props, State> {
onKeyDown = { this._onKeyDown }> onKeyDown = { this._onKeyDown }>
{ this._renderErrorMessage() } { this._renderErrorMessage() }
<MultiSelectAutocomplete <MultiSelectAutocomplete
footer = { footerText }
isDisabled = { isMultiSelectDisabled } isDisabled = { isMultiSelectDisabled }
loadingMessage = { t(loadingMessage) } loadingMessage = { t(loadingMessage) }
noMatchesFound = { t(noMatches) } noMatchesFound = { t(noMatches) }
@ -404,33 +395,6 @@ class InviteContactsForm extends AbstractAddPeopleDialog<Props, State> {
_query: (string) => Promise<Array<Object>>; _query: (string) => Promise<Array<Object>>;
_renderFooterText: () => Object;
/**
* Sets up the rendering of the footer text, if enabled.
*
* @returns {Object | undefined}
*/
_renderFooterText() {
const { _footerTextEnabled, t } = this.props;
let footerText;
if (_footerTextEnabled) {
footerText = {
content: <div className = 'footer-text-wrap'>
<div>
<span className = 'footer-telephone-icon'>
<Icon src = { IconPhone } />
</span>
</div>
{ translateToHTML(t, 'addPeople.footerText') }
</div>
};
}
return footerText;
}
_onClearItems: () => void; _onClearItems: () => void;
/** /**
@ -580,20 +544,8 @@ class InviteContactsForm extends AbstractAddPeopleDialog<Props, State> {
* @returns {Props} * @returns {Props}
*/ */
function _mapStateToProps(state) { function _mapStateToProps(state) {
const { enableFeaturesBasedOnToken } = state['features/base/config'];
let footerTextEnabled = false;
if (enableFeaturesBasedOnToken) {
const { features = {} } = getLocalParticipant(state);
if (String(features['outbound-call']) !== 'true') {
footerTextEnabled = true;
}
}
return { return {
..._abstractMapStateToProps(state), ..._abstractMapStateToProps(state),
_footerTextEnabled: footerTextEnabled,
_isVpaas: isVpaasMeeting(state) _isVpaas: isVpaasMeeting(state)
}; };
} }

View File

@ -5,6 +5,7 @@ import { getRoomName } from '../base/conference';
import { getInviteURL } from '../base/connection'; import { getInviteURL } from '../base/connection';
import { isIosMobileBrowser } from '../base/environment/utils'; import { isIosMobileBrowser } from '../base/environment/utils';
import { i18next } from '../base/i18n'; import { i18next } from '../base/i18n';
import { isJwtFeatureEnabled } from '../base/jwt/functions';
import { JitsiRecordingConstants } from '../base/lib-jitsi-meet'; import { JitsiRecordingConstants } from '../base/lib-jitsi-meet';
import { getLocalParticipant, isLocalParticipantModerator } from '../base/participants'; import { getLocalParticipant, isLocalParticipantModerator } from '../base/participants';
import { toState } from '../base/redux'; import { toState } from '../base/redux';
@ -410,11 +411,8 @@ export function isDialOutEnabled(state: Object): boolean {
*/ */
export function isSipInviteEnabled(state: Object): boolean { export function isSipInviteEnabled(state: Object): boolean {
const { sipInviteUrl } = state['features/base/config']; const { sipInviteUrl } = state['features/base/config'];
const { features = {} } = getLocalParticipant(state) || {};
return state['features/base/jwt'].jwt return isJwtFeatureEnabled(state, 'sip-outbound-call') && Boolean(sipInviteUrl);
&& Boolean(sipInviteUrl)
&& String(features['sip-outbound-call']) === 'true';
} }
/** /**

View File

@ -1,11 +1,9 @@
// @flow // @flow
import { IconLiveStreaming } from '../../../base/icons'; import { IconLiveStreaming } from '../../../base/icons';
import { isJwtFeatureEnabled } from '../../../base/jwt/functions';
import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet'; import { JitsiRecordingConstants } from '../../../base/lib-jitsi-meet';
import { import { isLocalParticipantModerator } from '../../../base/participants';
getLocalParticipant,
isLocalParticipantModerator
} from '../../../base/participants';
import { AbstractButton, type AbstractButtonProps } from '../../../base/toolbox/components'; import { AbstractButton, type AbstractButtonProps } from '../../../base/toolbox/components';
import { isInBreakoutRoom } from '../../../breakout-rooms/functions'; import { isInBreakoutRoom } from '../../../breakout-rooms/functions';
import { maybeShowPremiumFeatureDialog } from '../../../jaas/actions'; import { maybeShowPremiumFeatureDialog } from '../../../jaas/actions';
@ -134,36 +132,22 @@ export function _mapStateToProps(state: Object, ownProps: Props) {
// A button can be disabled/enabled only if enableFeaturesBasedOnToken // A button can be disabled/enabled only if enableFeaturesBasedOnToken
// is on or if the recording is running. // is on or if the recording is running.
let _disabled; let _disabled = false;
let _tooltip = ''; let _tooltip = '';
if (typeof visible === 'undefined') { if (typeof visible === 'undefined') {
// If the containing component provides the visible prop, that is one // If the containing component provides the visible prop, that is one
// above all, but if not, the button should be autonomus and decide on // above all, but if not, the button should be autonomous and decide on
// its own to be visible or not. // its own to be visible or not.
const isModerator = isLocalParticipantModerator(state); const isModerator = isLocalParticipantModerator(state);
const {
enableFeaturesBasedOnToken
} = state['features/base/config'];
const liveStreaming = getLiveStreaming(state); const liveStreaming = getLiveStreaming(state);
const { features = {} } = getLocalParticipant(state);
visible = isModerator && liveStreaming.enabled; visible = isModerator && liveStreaming.enabled;
visible = isJwtFeatureEnabled(state, 'livestreaming', visible);
if (enableFeaturesBasedOnToken) {
visible = visible && String(features.livestreaming) === 'true';
_disabled = String(features.livestreaming) === 'disabled';
if (!visible && !_disabled) {
_disabled = true;
visible = true;
_tooltip = 'dialog.liveStreamingDisabledTooltip';
}
}
} }
// disable the button if the recording is running. // disable the button if the recording is running.
if (getActiveSession(state, JitsiRecordingConstants.mode.FILE)) { if (visible && getActiveSession(state, JitsiRecordingConstants.mode.FILE)) {
_disabled = true; _disabled = true;
_tooltip = 'dialog.liveStreamingDisabledBecauseOfActiveRecordingTooltip'; _tooltip = 'dialog.liveStreamingDisabledBecauseOfActiveRecordingTooltip';
} }
@ -176,8 +160,7 @@ export function _mapStateToProps(state: Object, ownProps: Props) {
return { return {
_disabled, _disabled,
_isLiveStreamRunning: Boolean( _isLiveStreamRunning: Boolean(getActiveSession(state, JitsiRecordingConstants.mode.STREAM)),
getActiveSession(state, JitsiRecordingConstants.mode.STREAM)),
_tooltip, _tooltip,
visible visible
}; };

View File

@ -1,6 +1,7 @@
// @flow // @flow
import { isMobileBrowser } from '../base/environment/utils'; import { isMobileBrowser } from '../base/environment/utils';
import { isJwtFeatureEnabled } from '../base/jwt/functions';
import { JitsiRecordingConstants, browser } from '../base/lib-jitsi-meet'; import { JitsiRecordingConstants, browser } from '../base/lib-jitsi-meet';
import { getLocalParticipant, getRemoteParticipants, isLocalParticipantModerator } from '../base/participants'; import { getLocalParticipant, getRemoteParticipants, isLocalParticipantModerator } from '../base/participants';
import { isInBreakoutRoom } from '../breakout-rooms/functions'; import { isInBreakoutRoom } from '../breakout-rooms/functions';
@ -153,7 +154,7 @@ export function getRecordButtonProps(state: Object): ?string {
// a button can be disabled/enabled if enableFeaturesBasedOnToken // a button can be disabled/enabled if enableFeaturesBasedOnToken
// is on or if the livestreaming is running. // is on or if the livestreaming is running.
let disabled; let disabled = false;
let tooltip = ''; let tooltip = '';
// If the containing component provides the visible prop, that is one // If the containing component provides the visible prop, that is one
@ -161,29 +162,18 @@ export function getRecordButtonProps(state: Object): ?string {
// its own to be visible or not. // its own to be visible or not.
const isModerator = isLocalParticipantModerator(state); const isModerator = isLocalParticipantModerator(state);
const { const {
enableFeaturesBasedOnToken,
recordingService, recordingService,
localRecording localRecording
} = state['features/base/config']; } = state['features/base/config'];
const { features = {} } = getLocalParticipant(state);
const localRecordingEnabled = !localRecording?.disable && supportsLocalRecording(); const localRecordingEnabled = !localRecording?.disable && supportsLocalRecording();
const dropboxEnabled = isDropboxEnabled(state); const dropboxEnabled = isDropboxEnabled(state);
visible = isModerator && (recordingService?.enabled || localRecordingEnabled || dropboxEnabled); visible = isModerator && (recordingService?.enabled || localRecordingEnabled || dropboxEnabled);
visible = isJwtFeatureEnabled(state, 'recording', visible);
if (enableFeaturesBasedOnToken) {
visible = visible && String(features.recording) === 'true';
disabled = String(features.recording) === 'disabled';
if (!visible && !disabled) {
disabled = true;
visible = true;
tooltip = 'dialog.recordingDisabledTooltip';
}
}
// disable the button if the livestreaming is running. // disable the button if the livestreaming is running.
if (getActiveSession(state, JitsiRecordingConstants.mode.STREAM)) { if (visible && getActiveSession(state, JitsiRecordingConstants.mode.STREAM)) {
disabled = true; disabled = true;
tooltip = 'dialog.recordingDisabledBecauseOfActiveLiveStreamingTooltip'; tooltip = 'dialog.recordingDisabledBecauseOfActiveLiveStreamingTooltip';
} }

View File

@ -10,26 +10,20 @@ import { isDesktopShareButtonDisabled } from '../../functions';
type Props = AbstractButtonProps & { type Props = AbstractButtonProps & {
/** /**
* Whether or not screensharing is initialized. * Whether or not screensharing is initialized.
*/ */
_desktopSharingEnabled: boolean, _desktopSharingEnabled: boolean,
/**
* The tooltip key to use when screensharing is disabled. Or undefined
* if non to be shown and the button to be hidden.
*/
_desktopSharingDisabledTooltipKey: string,
/** /**
* Whether or not the local participant is screensharing. * Whether or not the local participant is screensharing.
*/ */
_screensharing: boolean, _screensharing: boolean,
/** /**
* The redux {@code dispatch} function. * The redux {@code dispatch} function.
*/ */
dispatch: Function, dispatch: Function,
}; };
/** /**
@ -46,7 +40,7 @@ class ShareDesktopButton extends AbstractButton<Props, *> {
* Retrieves tooltip dynamically. * Retrieves tooltip dynamically.
*/ */
get tooltip() { get tooltip() {
const { _desktopSharingDisabledTooltipKey, _desktopSharingEnabled, _screensharing } = this.props; const { _desktopSharingEnabled, _screensharing } = this.props;
if (_desktopSharingEnabled) { if (_desktopSharingEnabled) {
if (_screensharing) { if (_screensharing) {
@ -56,7 +50,7 @@ class ShareDesktopButton extends AbstractButton<Props, *> {
return 'toolbar.startScreenSharing'; return 'toolbar.startScreenSharing';
} }
return _desktopSharingDisabledTooltipKey; return 'dialog.shareYourScreenDisabled';
} }
/** /**
@ -98,23 +92,12 @@ class ShareDesktopButton extends AbstractButton<Props, *> {
* @returns {Object} * @returns {Object}
*/ */
const mapStateToProps = state => { const mapStateToProps = state => {
let desktopSharingEnabled = JitsiMeetJS.isDesktopSharingEnabled();
const { enableFeaturesBasedOnToken } = state['features/base/config'];
let desktopSharingDisabledTooltipKey;
if (enableFeaturesBasedOnToken) {
// we enable desktop sharing if any participant already have this
// feature enabled
desktopSharingEnabled = state['features/base/participants'].haveParticipantWithScreenSharingFeature;
desktopSharingDisabledTooltipKey = 'dialog.shareYourScreenDisabled';
}
// Disable the screenshare button if the video sender limit is reached and there is no video or media share in // Disable the screenshare button if the video sender limit is reached and there is no video or media share in
// progress. // progress.
desktopSharingEnabled = desktopSharingEnabled && !isDesktopShareButtonDisabled(state); const desktopSharingEnabled
= JitsiMeetJS.isDesktopSharingEnabled() && !isDesktopShareButtonDisabled(state);
return { return {
_desktopSharingDisabledTooltipKey: desktopSharingDisabledTooltipKey,
_desktopSharingEnabled: desktopSharingEnabled, _desktopSharingEnabled: desktopSharingEnabled,
_screensharing: isScreenVideoShared(state) _screensharing: isScreenVideoShared(state)
}; };

View File

@ -21,7 +21,6 @@ import JitsiMeetJS from '../../../base/lib-jitsi-meet';
import { import {
getLocalParticipant, getLocalParticipant,
hasRaisedHand, hasRaisedHand,
haveParticipantWithScreenSharingFeature,
raiseHand raiseHand
} from '../../../base/participants'; } from '../../../base/participants';
import { connect } from '../../../base/redux'; import { connect } from '../../../base/redux';
@ -133,12 +132,6 @@ type Props = {
*/ */
_desktopSharingButtonDisabled: boolean, _desktopSharingButtonDisabled: boolean,
/**
* The tooltip key to use when screensharing is disabled. Or undefined
* if non to be shown and the button to be hidden.
*/
_desktopSharingDisabledTooltipKey: boolean,
/** /**
* Whether or not screensharing is initialized. * Whether or not screensharing is initialized.
*/ */
@ -1274,12 +1267,7 @@ class Toolbox extends Component<Props> {
* @returns {boolean} * @returns {boolean}
*/ */
_showDesktopSharingButton() { _showDesktopSharingButton() {
const { return this.props._desktopSharingEnabled;
_desktopSharingEnabled,
_desktopSharingDisabledTooltipKey
} = this.props;
return _desktopSharingEnabled || _desktopSharingDisabledTooltipKey;
} }
/** /**
@ -1408,12 +1396,10 @@ class Toolbox extends Component<Props> {
*/ */
function _mapStateToProps(state, ownProps) { function _mapStateToProps(state, ownProps) {
const { conference } = state['features/base/conference']; const { conference } = state['features/base/conference'];
let desktopSharingEnabled = JitsiMeetJS.isDesktopSharingEnabled();
const { const {
buttonsWithNotifyClick, buttonsWithNotifyClick,
callStatsID, callStatsID,
disableProfile, disableProfile,
enableFeaturesBasedOnToken,
iAmRecorder, iAmRecorder,
iAmSipGateway iAmSipGateway
} = state['features/base/config']; } = state['features/base/config'];
@ -1425,18 +1411,6 @@ function _mapStateToProps(state, ownProps) {
const localParticipant = getLocalParticipant(state); const localParticipant = getLocalParticipant(state);
const localVideo = getLocalVideoTrack(state['features/base/tracks']); const localVideo = getLocalVideoTrack(state['features/base/tracks']);
const { clientWidth } = state['features/base/responsive-ui']; const { clientWidth } = state['features/base/responsive-ui'];
let desktopSharingDisabledTooltipKey;
if (enableFeaturesBasedOnToken) {
if (desktopSharingEnabled) {
// we enable desktop sharing if any participant already have this
// feature enabled and if the user supports it.
desktopSharingEnabled = haveParticipantWithScreenSharingFeature(state);
desktopSharingDisabledTooltipKey = 'dialog.shareYourScreenDisabled';
}
}
const toolbarButtons = ownProps.toolbarButtons || getToolbarButtons(state); const toolbarButtons = ownProps.toolbarButtons || getToolbarButtons(state);
return { return {
@ -1445,9 +1419,8 @@ function _mapStateToProps(state, ownProps) {
_chatOpen: state['features/chat'].isOpen, _chatOpen: state['features/chat'].isOpen,
_clientWidth: clientWidth, _clientWidth: clientWidth,
_conference: conference, _conference: conference,
_desktopSharingEnabled: desktopSharingEnabled, _desktopSharingEnabled: JitsiMeetJS.isDesktopSharingEnabled(),
_desktopSharingButtonDisabled: isDesktopShareButtonDisabled(state), _desktopSharingButtonDisabled: isDesktopShareButtonDisabled(state),
_desktopSharingDisabledTooltipKey: desktopSharingDisabledTooltipKey,
_dialog: Boolean(state['features/base/dialog'].component), _dialog: Boolean(state['features/base/dialog'].component),
_disabled: Boolean(iAmRecorder || iAmSipGateway), _disabled: Boolean(iAmRecorder || iAmSipGateway),
_feedbackConfigured: Boolean(callStatsID), _feedbackConfigured: Boolean(callStatsID),