feat(subject): UI
This commit is contained in:
parent
2715e81f1d
commit
cb8e9eed5e
|
@ -38,6 +38,7 @@ import {
|
||||||
conferenceFailed,
|
conferenceFailed,
|
||||||
conferenceJoined,
|
conferenceJoined,
|
||||||
conferenceLeft,
|
conferenceLeft,
|
||||||
|
conferenceSubjectChanged,
|
||||||
conferenceWillJoin,
|
conferenceWillJoin,
|
||||||
conferenceWillLeave,
|
conferenceWillLeave,
|
||||||
dataChannelOpened,
|
dataChannelOpened,
|
||||||
|
@ -45,8 +46,7 @@ import {
|
||||||
onStartMutedPolicyChanged,
|
onStartMutedPolicyChanged,
|
||||||
p2pStatusChanged,
|
p2pStatusChanged,
|
||||||
sendLocalParticipant,
|
sendLocalParticipant,
|
||||||
setDesktopSharingEnabled,
|
setDesktopSharingEnabled
|
||||||
setSubject
|
|
||||||
} from './react/features/base/conference';
|
} from './react/features/base/conference';
|
||||||
import {
|
import {
|
||||||
getAvailableDevices,
|
getAvailableDevices,
|
||||||
|
@ -1834,7 +1834,7 @@ export default {
|
||||||
APP.UI.showToolbar(6000);
|
APP.UI.showToolbar(6000);
|
||||||
});
|
});
|
||||||
room.on(JitsiConferenceEvents.SUBJECT_CHANGED,
|
room.on(JitsiConferenceEvents.SUBJECT_CHANGED,
|
||||||
subject => APP.API.notifySubjectChanged(subject));
|
subject => APP.store.dispatch(conferenceSubjectChanged(subject)));
|
||||||
|
|
||||||
room.on(
|
room.on(
|
||||||
JitsiConferenceEvents.LAST_N_ENDPOINTS_CHANGED,
|
JitsiConferenceEvents.LAST_N_ENDPOINTS_CHANGED,
|
||||||
|
@ -2767,16 +2767,6 @@ export default {
|
||||||
APP.API.notifyAudioMutedStatusChanged(muted);
|
APP.API.notifyAudioMutedStatusChanged(muted);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Changes the subject of the conference.
|
|
||||||
* Note: available only for moderator.
|
|
||||||
*
|
|
||||||
* @param subject {string} the new subject for the conference.
|
|
||||||
*/
|
|
||||||
setSubject(subject) {
|
|
||||||
APP.store.dispatch(setSubject(subject));
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dispatches the passed in feedback for submission. The submitted score
|
* Dispatches the passed in feedback for submission. The submitted score
|
||||||
* should be a number inclusively between 1 through 5, or -1 for no score.
|
* should be a number inclusively between 1 through 5, or -1 for no score.
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
.subject {
|
||||||
|
top: -120px;
|
||||||
|
transition: top .3s ease-in;
|
||||||
|
height: 95px;
|
||||||
|
width: 100%;
|
||||||
|
position: absolute;
|
||||||
|
padding: 25px 140px 0 140px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 17px;
|
||||||
|
color: #fff;
|
||||||
|
z-index: $toolbarBackgroundZ;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
box-sizing: border-box;
|
||||||
|
white-space: nowrap;
|
||||||
|
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0));
|
||||||
|
|
||||||
|
&.visible {
|
||||||
|
top: 0px;
|
||||||
|
}
|
||||||
|
}
|
|
@ -49,6 +49,7 @@ $flagsImagePath: "/images/";
|
||||||
@import 'modals/local-recording/local-recording';
|
@import 'modals/local-recording/local-recording';
|
||||||
@import 'videolayout_default';
|
@import 'videolayout_default';
|
||||||
@import 'notice';
|
@import 'notice';
|
||||||
|
@import 'subject';
|
||||||
@import 'popup_menu';
|
@import 'popup_menu';
|
||||||
@import 'recording';
|
@import 'recording';
|
||||||
@import 'login_menu';
|
@import 'login_menu';
|
||||||
|
|
|
@ -5,6 +5,7 @@ import {
|
||||||
createApiEvent,
|
createApiEvent,
|
||||||
sendAnalytics
|
sendAnalytics
|
||||||
} from '../../react/features/analytics';
|
} from '../../react/features/analytics';
|
||||||
|
import { setSubject } from '../../react/features/base/conference';
|
||||||
import { parseJWTFromURLParams } from '../../react/features/base/jwt';
|
import { parseJWTFromURLParams } from '../../react/features/base/jwt';
|
||||||
import { invite } from '../../react/features/invite';
|
import { invite } from '../../react/features/invite';
|
||||||
import { getJitsiMeetTransport } from '../transport';
|
import { getJitsiMeetTransport } from '../transport';
|
||||||
|
@ -65,7 +66,7 @@ function initCommands() {
|
||||||
},
|
},
|
||||||
'subject': subject => {
|
'subject': subject => {
|
||||||
sendAnalytics(createApiEvent('subject.changed'));
|
sendAnalytics(createApiEvent('subject.changed'));
|
||||||
APP.conference.setSubject(subject);
|
APP.store.dispatch(setSubject(subject));
|
||||||
},
|
},
|
||||||
'submit-feedback': feedback => {
|
'submit-feedback': feedback => {
|
||||||
sendAnalytics(createApiEvent('submit.feedback'));
|
sendAnalytics(createApiEvent('submit.feedback'));
|
||||||
|
|
|
@ -548,7 +548,7 @@ export default class JitsiMeetExternalAPI extends EventEmitter {
|
||||||
* {@code displayName} - Sets the display name of the local participant to
|
* {@code displayName} - Sets the display name of the local participant to
|
||||||
* the value passed in the arguments array.
|
* the value passed in the arguments array.
|
||||||
* {@code subject} - Sets the subject of the conference, the value passed
|
* {@code subject} - Sets the subject of the conference, the value passed
|
||||||
* in the arguments array. Note: available only for moderator.
|
* in the arguments array. Note: Available only for moderator.
|
||||||
*
|
*
|
||||||
* {@code toggleAudio} - Mutes / unmutes audio with no arguments.
|
* {@code toggleAudio} - Mutes / unmutes audio with no arguments.
|
||||||
* {@code toggleVideo} - Mutes / unmutes video with no arguments.
|
* {@code toggleVideo} - Mutes / unmutes video with no arguments.
|
||||||
|
|
|
@ -42,6 +42,16 @@ export const CONFERENCE_JOINED = Symbol('CONFERENCE_JOINED');
|
||||||
*/
|
*/
|
||||||
export const CONFERENCE_LEFT = Symbol('CONFERENCE_LEFT');
|
export const CONFERENCE_LEFT = Symbol('CONFERENCE_LEFT');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of (redux) action, which indicates conference subject changes.
|
||||||
|
*
|
||||||
|
* {
|
||||||
|
* type: CONFERENCE_SUBJECT_CHANGED
|
||||||
|
* subject: string
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
export const CONFERENCE_SUBJECT_CHANGED = Symbol('CONFERENCE_SUBJECT_CHANGED');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of (redux) action which signals that a specific conference will be
|
* The type of (redux) action which signals that a specific conference will be
|
||||||
* joined.
|
* joined.
|
||||||
|
@ -119,16 +129,6 @@ export const P2P_STATUS_CHANGED = Symbol('P2P_STATUS_CHANGED');
|
||||||
*/
|
*/
|
||||||
export const SET_AUDIO_ONLY = Symbol('SET_AUDIO_ONLY');
|
export const SET_AUDIO_ONLY = Symbol('SET_AUDIO_ONLY');
|
||||||
|
|
||||||
/**
|
|
||||||
* The type of (redux) action, which indicates to set conference subject.
|
|
||||||
*
|
|
||||||
* {
|
|
||||||
* type: SET_CONFERENCE_SUBJECT
|
|
||||||
* subject: string
|
|
||||||
* }
|
|
||||||
*/
|
|
||||||
export const SET_CONFERENCE_SUBJECT = Symbol('SET_CONFERENCE_SUBJECT');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of (redux) action which sets the desktop sharing enabled flag for
|
* The type of (redux) action which sets the desktop sharing enabled flag for
|
||||||
* the current conference.
|
* the current conference.
|
||||||
|
@ -199,6 +199,16 @@ export const SET_PASSWORD = Symbol('SET_PASSWORD');
|
||||||
*/
|
*/
|
||||||
export const SET_PASSWORD_FAILED = Symbol('SET_PASSWORD_FAILED');
|
export const SET_PASSWORD_FAILED = Symbol('SET_PASSWORD_FAILED');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of (redux) action which signals for pending subject changes.
|
||||||
|
*
|
||||||
|
* {
|
||||||
|
* type: SET_PENDING_SUBJECT_CHANGE,
|
||||||
|
* subject: string
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
export const SET_PENDING_SUBJECT_CHANGE = Symbol('SET_PENDING_SUBJECT_CHANGE');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of (redux) action which sets the preferred maximum video height that
|
* The type of (redux) action which sets the preferred maximum video height that
|
||||||
* should be received from remote participants.
|
* should be received from remote participants.
|
||||||
|
|
|
@ -26,6 +26,7 @@ import {
|
||||||
CONFERENCE_FAILED,
|
CONFERENCE_FAILED,
|
||||||
CONFERENCE_JOINED,
|
CONFERENCE_JOINED,
|
||||||
CONFERENCE_LEFT,
|
CONFERENCE_LEFT,
|
||||||
|
CONFERENCE_SUBJECT_CHANGED,
|
||||||
CONFERENCE_WILL_JOIN,
|
CONFERENCE_WILL_JOIN,
|
||||||
CONFERENCE_WILL_LEAVE,
|
CONFERENCE_WILL_LEAVE,
|
||||||
DATA_CHANNEL_OPENED,
|
DATA_CHANNEL_OPENED,
|
||||||
|
@ -33,7 +34,6 @@ import {
|
||||||
LOCK_STATE_CHANGED,
|
LOCK_STATE_CHANGED,
|
||||||
P2P_STATUS_CHANGED,
|
P2P_STATUS_CHANGED,
|
||||||
SET_AUDIO_ONLY,
|
SET_AUDIO_ONLY,
|
||||||
SET_CONFERENCE_SUBJECT,
|
|
||||||
SET_DESKTOP_SHARING_ENABLED,
|
SET_DESKTOP_SHARING_ENABLED,
|
||||||
SET_FOLLOW_ME,
|
SET_FOLLOW_ME,
|
||||||
SET_LASTN,
|
SET_LASTN,
|
||||||
|
@ -42,6 +42,7 @@ import {
|
||||||
SET_PASSWORD_FAILED,
|
SET_PASSWORD_FAILED,
|
||||||
SET_PREFERRED_RECEIVER_VIDEO_QUALITY,
|
SET_PREFERRED_RECEIVER_VIDEO_QUALITY,
|
||||||
SET_ROOM,
|
SET_ROOM,
|
||||||
|
SET_PENDING_SUBJECT_CHANGE,
|
||||||
SET_START_MUTED_POLICY
|
SET_START_MUTED_POLICY
|
||||||
} from './actionTypes';
|
} from './actionTypes';
|
||||||
import {
|
import {
|
||||||
|
@ -272,6 +273,22 @@ export function conferenceLeft(conference: Object) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Signals that the conference subject has been changed.
|
||||||
|
*
|
||||||
|
* @param {string} subject - The new subject.
|
||||||
|
* @returns {{
|
||||||
|
* type: CONFERENCE_SUBJECT_CHANGED,
|
||||||
|
* subject: string
|
||||||
|
* }}
|
||||||
|
*/
|
||||||
|
export function conferenceSubjectChanged(subject: string) {
|
||||||
|
return {
|
||||||
|
type: CONFERENCE_SUBJECT_CHANGED,
|
||||||
|
subject
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds any existing local tracks to a specific conference before the conference
|
* Adds any existing local tracks to a specific conference before the conference
|
||||||
* is joined. Then signals the intention of the application to have the local
|
* is joined. Then signals the intention of the application to have the local
|
||||||
|
@ -736,9 +753,21 @@ export function toggleAudioOnly() {
|
||||||
* @param {string} subject - The new subject.
|
* @param {string} subject - The new subject.
|
||||||
* @returns {void}
|
* @returns {void}
|
||||||
*/
|
*/
|
||||||
export function setSubject(subject: String) {
|
export function setSubject(subject: string = '') {
|
||||||
return {
|
return (dispatch: Dispatch<*>, getState: Function) => {
|
||||||
type: SET_CONFERENCE_SUBJECT,
|
const { conference } = getState()['features/base/conference'];
|
||||||
|
|
||||||
|
if (conference) {
|
||||||
|
dispatch({
|
||||||
|
type: SET_PENDING_SUBJECT_CHANGE,
|
||||||
|
subject: undefined
|
||||||
|
});
|
||||||
|
conference.setSubject(subject);
|
||||||
|
} else {
|
||||||
|
dispatch({
|
||||||
|
type: SET_PENDING_SUBJECT_CHANGE,
|
||||||
subject
|
subject
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,15 +27,16 @@ import {
|
||||||
conferenceLeft,
|
conferenceLeft,
|
||||||
conferenceWillLeave,
|
conferenceWillLeave,
|
||||||
createConference,
|
createConference,
|
||||||
setLastN
|
setLastN,
|
||||||
|
setSubject
|
||||||
} from './actions';
|
} from './actions';
|
||||||
import {
|
import {
|
||||||
CONFERENCE_FAILED,
|
CONFERENCE_FAILED,
|
||||||
CONFERENCE_JOINED,
|
CONFERENCE_JOINED,
|
||||||
|
CONFERENCE_SUBJECT_CHANGED,
|
||||||
CONFERENCE_WILL_LEAVE,
|
CONFERENCE_WILL_LEAVE,
|
||||||
DATA_CHANNEL_OPENED,
|
DATA_CHANNEL_OPENED,
|
||||||
SET_AUDIO_ONLY,
|
SET_AUDIO_ONLY,
|
||||||
SET_CONFERENCE_SUBJECT,
|
|
||||||
SET_LASTN,
|
SET_LASTN,
|
||||||
SET_ROOM
|
SET_ROOM
|
||||||
} from './actionTypes';
|
} from './actionTypes';
|
||||||
|
@ -75,6 +76,9 @@ MiddlewareRegistry.register(store => next => action => {
|
||||||
case CONNECTION_FAILED:
|
case CONNECTION_FAILED:
|
||||||
return _connectionFailed(store, next, action);
|
return _connectionFailed(store, next, action);
|
||||||
|
|
||||||
|
case CONFERENCE_SUBJECT_CHANGED:
|
||||||
|
return _conferenceSubjectChanged(store, next, action);
|
||||||
|
|
||||||
case CONFERENCE_WILL_LEAVE:
|
case CONFERENCE_WILL_LEAVE:
|
||||||
_conferenceWillLeave();
|
_conferenceWillLeave();
|
||||||
break;
|
break;
|
||||||
|
@ -91,9 +95,6 @@ MiddlewareRegistry.register(store => next => action => {
|
||||||
case SET_AUDIO_ONLY:
|
case SET_AUDIO_ONLY:
|
||||||
return _setAudioOnly(store, next, action);
|
return _setAudioOnly(store, next, action);
|
||||||
|
|
||||||
case SET_CONFERENCE_SUBJECT:
|
|
||||||
return _setSubject(store, next, action);
|
|
||||||
|
|
||||||
case SET_LASTN:
|
case SET_LASTN:
|
||||||
return _setLastN(store, next, action);
|
return _setLastN(store, next, action);
|
||||||
|
|
||||||
|
@ -192,7 +193,15 @@ function _conferenceFailed(store, next, action) {
|
||||||
function _conferenceJoined({ dispatch, getState }, next, action) {
|
function _conferenceJoined({ dispatch, getState }, next, action) {
|
||||||
const result = next(action);
|
const result = next(action);
|
||||||
|
|
||||||
const { audioOnly, conference } = getState()['features/base/conference'];
|
const {
|
||||||
|
audioOnly,
|
||||||
|
conference,
|
||||||
|
pendingSubjectChange
|
||||||
|
} = getState()['features/base/conference'];
|
||||||
|
|
||||||
|
if (pendingSubjectChange) {
|
||||||
|
dispatch(setSubject(pendingSubjectChange));
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME On Web the audio only mode for "start audio only" is toggled before
|
// FIXME On Web the audio only mode for "start audio only" is toggled before
|
||||||
// conference is added to the redux store ("on conference joined" action)
|
// conference is added to the redux store ("on conference joined" action)
|
||||||
|
@ -305,6 +314,29 @@ function _connectionFailed({ dispatch, getState }, next, action) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies the feature base/conference that the action
|
||||||
|
* {@code CONFERENCE_SUBJECT_CHANGED} is being dispatched within a specific
|
||||||
|
* redux store.
|
||||||
|
*
|
||||||
|
* @param {Store} store - The redux store in which the specified {@code action}
|
||||||
|
* is being dispatched.
|
||||||
|
* @param {Dispatch} next - The redux {@code dispatch} function to dispatch the
|
||||||
|
* specified {@code action} to the specified {@code store}.
|
||||||
|
* @param {Action} action - The redux action {@code CONFERENCE_SUBJECT_CHANGED}
|
||||||
|
* which is being dispatched in the specified {@code store}.
|
||||||
|
* @private
|
||||||
|
* @returns {Object} The value returned by {@code next(action)}.
|
||||||
|
*/
|
||||||
|
function _conferenceSubjectChanged({ getState }, next, action) {
|
||||||
|
const result = next(action);
|
||||||
|
const { subject } = getState()['features/base/conference'];
|
||||||
|
|
||||||
|
typeof APP === 'object' && APP.API.notifySubjectChanged(subject);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies the feature base/conference that the action
|
* Notifies the feature base/conference that the action
|
||||||
* {@code CONFERENCE_WILL_LEAVE} is being dispatched within a specific redux
|
* {@code CONFERENCE_WILL_LEAVE} is being dispatched within a specific redux
|
||||||
|
@ -683,26 +715,3 @@ function _updateLocalParticipantInConference({ getState }, next, action) {
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Changing conference subject.
|
|
||||||
*
|
|
||||||
* @param {Store} store - The redux store in which the specified {@code action}
|
|
||||||
* is being dispatched.
|
|
||||||
* @param {Dispatch} next - The redux {@code dispatch} function to dispatch the
|
|
||||||
* specified {@code action} to the specified {@code store}.
|
|
||||||
* @param {Action} action - The redux action which is being dispatched in the
|
|
||||||
* specified {@code store}.
|
|
||||||
* @private
|
|
||||||
* @returns {Object} The value returned by {@code next(action)}.
|
|
||||||
*/
|
|
||||||
function _setSubject({ getState }, next, action) {
|
|
||||||
const { conference } = getState()['features/base/conference'];
|
|
||||||
const { subject } = action;
|
|
||||||
|
|
||||||
if (subject) {
|
|
||||||
conference.setSubject(subject);
|
|
||||||
}
|
|
||||||
|
|
||||||
return next(action);
|
|
||||||
}
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ import {
|
||||||
CONFERENCE_FAILED,
|
CONFERENCE_FAILED,
|
||||||
CONFERENCE_JOINED,
|
CONFERENCE_JOINED,
|
||||||
CONFERENCE_LEFT,
|
CONFERENCE_LEFT,
|
||||||
|
CONFERENCE_SUBJECT_CHANGED,
|
||||||
CONFERENCE_WILL_JOIN,
|
CONFERENCE_WILL_JOIN,
|
||||||
CONFERENCE_WILL_LEAVE,
|
CONFERENCE_WILL_LEAVE,
|
||||||
LOCK_STATE_CHANGED,
|
LOCK_STATE_CHANGED,
|
||||||
|
@ -19,6 +20,7 @@ import {
|
||||||
SET_FOLLOW_ME,
|
SET_FOLLOW_ME,
|
||||||
SET_MAX_RECEIVER_VIDEO_QUALITY,
|
SET_MAX_RECEIVER_VIDEO_QUALITY,
|
||||||
SET_PASSWORD,
|
SET_PASSWORD,
|
||||||
|
SET_PENDING_SUBJECT_CHANGE,
|
||||||
SET_PREFERRED_RECEIVER_VIDEO_QUALITY,
|
SET_PREFERRED_RECEIVER_VIDEO_QUALITY,
|
||||||
SET_ROOM,
|
SET_ROOM,
|
||||||
SET_SIP_GATEWAY_ENABLED,
|
SET_SIP_GATEWAY_ENABLED,
|
||||||
|
@ -55,6 +57,9 @@ ReducerRegistry.register(
|
||||||
case CONFERENCE_JOINED:
|
case CONFERENCE_JOINED:
|
||||||
return _conferenceJoined(state, action);
|
return _conferenceJoined(state, action);
|
||||||
|
|
||||||
|
case CONFERENCE_SUBJECT_CHANGED:
|
||||||
|
return set(state, 'subject', action.subject);
|
||||||
|
|
||||||
case CONFERENCE_LEFT:
|
case CONFERENCE_LEFT:
|
||||||
case CONFERENCE_WILL_LEAVE:
|
case CONFERENCE_WILL_LEAVE:
|
||||||
return _conferenceLeftOrWillLeave(state, action);
|
return _conferenceLeftOrWillLeave(state, action);
|
||||||
|
@ -92,6 +97,9 @@ ReducerRegistry.register(
|
||||||
case SET_PASSWORD:
|
case SET_PASSWORD:
|
||||||
return _setPassword(state, action);
|
return _setPassword(state, action);
|
||||||
|
|
||||||
|
case SET_PENDING_SUBJECT_CHANGE:
|
||||||
|
return set(state, 'pendingSubjectChange', action.subject);
|
||||||
|
|
||||||
case SET_PREFERRED_RECEIVER_VIDEO_QUALITY:
|
case SET_PREFERRED_RECEIVER_VIDEO_QUALITY:
|
||||||
return set(
|
return set(
|
||||||
state,
|
state,
|
||||||
|
|
|
@ -31,6 +31,7 @@ import { maybeShowSuboptimalExperienceNotification } from '../../functions';
|
||||||
|
|
||||||
import Labels from './Labels';
|
import Labels from './Labels';
|
||||||
import { default as Notice } from './Notice';
|
import { default as Notice } from './Notice';
|
||||||
|
import { default as Subject } from './Subject';
|
||||||
|
|
||||||
declare var APP: Object;
|
declare var APP: Object;
|
||||||
declare var config: Object;
|
declare var config: Object;
|
||||||
|
@ -217,6 +218,7 @@ class Conference extends Component<Props> {
|
||||||
id = 'videoconference_page'
|
id = 'videoconference_page'
|
||||||
onMouseMove = { this._onShowToolbar }>
|
onMouseMove = { this._onShowToolbar }>
|
||||||
<Notice />
|
<Notice />
|
||||||
|
<Subject />
|
||||||
<div id = 'videospace'>
|
<div id = 'videospace'>
|
||||||
<LargeVideo />
|
<LargeVideo />
|
||||||
{ hideVideoQualityLabel
|
{ hideVideoQualityLabel
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
/* @flow */
|
||||||
|
|
||||||
|
import React, { Component } from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
|
import { isToolboxVisible } from '../../../toolbox';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of the React {@code Component} props of {@link Subject}.
|
||||||
|
*/
|
||||||
|
type Props = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The subject of the conference.
|
||||||
|
*/
|
||||||
|
_subject: string,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether the component should be visible or not.
|
||||||
|
*/
|
||||||
|
_visible: boolean
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subject react component.
|
||||||
|
*
|
||||||
|
* @class Subject
|
||||||
|
*/
|
||||||
|
class Subject extends Component<Props> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements React's {@link Component#render()}.
|
||||||
|
*
|
||||||
|
* @inheritdoc
|
||||||
|
* @returns {ReactElement}
|
||||||
|
*/
|
||||||
|
render() {
|
||||||
|
const { _subject, _visible } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className = { `subject ${_visible ? 'visible' : ''}` }>
|
||||||
|
{ _subject }
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps (parts of) the Redux state to the associated
|
||||||
|
* {@code Subject}'s props.
|
||||||
|
*
|
||||||
|
* @param {Object} state - The Redux state.
|
||||||
|
* @private
|
||||||
|
* @returns {{
|
||||||
|
* _subject: string,
|
||||||
|
* _visible: boolean
|
||||||
|
* }}
|
||||||
|
*/
|
||||||
|
function _mapStateToProps(state) {
|
||||||
|
const { subject } = state['features/base/conference'];
|
||||||
|
|
||||||
|
return {
|
||||||
|
_subject: subject,
|
||||||
|
_visible: isToolboxVisible(state)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
export default connect(_mapStateToProps)(Subject);
|
|
@ -55,6 +55,7 @@ import {
|
||||||
setToolbarHovered
|
setToolbarHovered
|
||||||
} from '../../actions';
|
} from '../../actions';
|
||||||
import AudioMuteButton from '../AudioMuteButton';
|
import AudioMuteButton from '../AudioMuteButton';
|
||||||
|
import { isToolboxVisible } from '../../functions';
|
||||||
import HangupButton from '../HangupButton';
|
import HangupButton from '../HangupButton';
|
||||||
import OverflowMenuButton from './OverflowMenuButton';
|
import OverflowMenuButton from './OverflowMenuButton';
|
||||||
import OverflowMenuProfileItem from './OverflowMenuProfileItem';
|
import OverflowMenuProfileItem from './OverflowMenuProfileItem';
|
||||||
|
@ -1281,11 +1282,8 @@ function _mapStateToProps(state) {
|
||||||
} = state['features/base/config'];
|
} = state['features/base/config'];
|
||||||
const sharedVideoStatus = state['features/shared-video'].status;
|
const sharedVideoStatus = state['features/shared-video'].status;
|
||||||
const {
|
const {
|
||||||
alwaysVisible,
|
|
||||||
fullScreen,
|
fullScreen,
|
||||||
overflowMenuVisible,
|
overflowMenuVisible
|
||||||
timeoutID,
|
|
||||||
visible
|
|
||||||
} = state['features/toolbox'];
|
} = state['features/toolbox'];
|
||||||
const localParticipant = getLocalParticipant(state);
|
const localParticipant = getLocalParticipant(state);
|
||||||
const localRecordingStates = state['features/local-recording'];
|
const localRecordingStates = state['features/local-recording'];
|
||||||
|
@ -1333,7 +1331,7 @@ function _mapStateToProps(state) {
|
||||||
_sharingVideo: sharedVideoStatus === 'playing'
|
_sharingVideo: sharedVideoStatus === 'playing'
|
||||||
|| sharedVideoStatus === 'start'
|
|| sharedVideoStatus === 'start'
|
||||||
|| sharedVideoStatus === 'pause',
|
|| sharedVideoStatus === 'pause',
|
||||||
_visible: Boolean(timeoutID || visible || alwaysVisible),
|
_visible: isToolboxVisible(state),
|
||||||
|
|
||||||
// XXX: We are not currently using state here, but in the future, when
|
// XXX: We are not currently using state here, but in the future, when
|
||||||
// interfaceConfig is part of redux we will.
|
// interfaceConfig is part of redux we will.
|
||||||
|
|
|
@ -1,17 +0,0 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
import { toState } from '../base/redux';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the toolbox is visible.
|
|
||||||
*
|
|
||||||
* @param {Object | Function} stateful - A function or object that can be
|
|
||||||
* resolved to Redux state by the function {@code toState}.
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
export function isToolboxVisible(stateful: Object | Function) {
|
|
||||||
const { alwaysVisible, enabled, visible }
|
|
||||||
= toState(stateful)['features/toolbox'];
|
|
||||||
|
|
||||||
return enabled && (alwaysVisible || visible);
|
|
||||||
}
|
|
|
@ -1,3 +1,17 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
export * from './functions.any';
|
import { toState } from '../base/redux';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the toolbox is visible.
|
||||||
|
*
|
||||||
|
* @param {Object | Function} stateful - A function or object that can be
|
||||||
|
* resolved to Redux state by the function {@code toState}.
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
export function isToolboxVisible(stateful: Object | Function) {
|
||||||
|
const { alwaysVisible, enabled, visible }
|
||||||
|
= toState(stateful)['features/toolbox'];
|
||||||
|
|
||||||
|
return enabled && (alwaysVisible || visible);
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
export * from './functions.any';
|
|
||||||
|
|
||||||
declare var interfaceConfig: Object;
|
declare var interfaceConfig: Object;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,3 +24,21 @@ export function getToolboxHeight() {
|
||||||
export function isButtonEnabled(name: string) {
|
export function isButtonEnabled(name: string) {
|
||||||
return interfaceConfig.TOOLBAR_BUTTONS.indexOf(name) !== -1;
|
return interfaceConfig.TOOLBAR_BUTTONS.indexOf(name) !== -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if the toolbox is visible or not.
|
||||||
|
*
|
||||||
|
* @param {string} state - The state from the Redux store.
|
||||||
|
* @returns {boolean} - True to indicate that the toolbox is visible, false -
|
||||||
|
* otherwise.
|
||||||
|
*/
|
||||||
|
export function isToolboxVisible(state: Object) {
|
||||||
|
const {
|
||||||
|
alwaysVisible,
|
||||||
|
timeoutID,
|
||||||
|
visible
|
||||||
|
} = state['features/toolbox'];
|
||||||
|
|
||||||
|
return Boolean(timeoutID || visible || alwaysVisible);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue