feat(lobby,notifications) refactor lobby notifications
This commit is contained in:
parent
a84130d67d
commit
28f5ddc81d
|
@ -41,64 +41,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#notification-participant-list {
|
|
||||||
background-color: $newToolbarBackgroundColor;
|
|
||||||
border: 1px solid rgba(255, 255, 255, .4);
|
|
||||||
border-radius: 8px;
|
|
||||||
left: 0;
|
|
||||||
margin: 20px;
|
|
||||||
max-height: 600px;
|
|
||||||
overflow: hidden;
|
|
||||||
overflow-y: auto;
|
|
||||||
position: fixed;
|
|
||||||
top: 30px;
|
|
||||||
z-index: $toolbarZ + 1;
|
|
||||||
|
|
||||||
&:empty {
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.toolbox-visible {
|
|
||||||
// Same as toolbox subject position
|
|
||||||
top: 120px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
background-color: rgba(0, 0, 0, .2);
|
|
||||||
font-size: 1.2em;
|
|
||||||
padding: 15px
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
align-self: stretch;
|
|
||||||
margin-bottom: 8px 0;
|
|
||||||
padding: 12px;
|
|
||||||
transition: .2s transform ease;
|
|
||||||
|
|
||||||
&:disabled {
|
|
||||||
opacity: .5;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
transform: scale(1.05);
|
|
||||||
|
|
||||||
&:disabled {
|
|
||||||
transform: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.borderLess {
|
|
||||||
background-color: transparent;
|
|
||||||
border-width: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.primary {
|
|
||||||
background-color: rgb(3, 118, 218);
|
|
||||||
border-width: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.knocking-participants-container {
|
.knocking-participants-container {
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
padding: 0 15px 15px 15px;
|
padding: 0 15px 15px 15px;
|
||||||
|
|
|
@ -642,6 +642,8 @@
|
||||||
"oldElectronClientDescription1": "You appear to be using an old version of the Jitsi Meet client which has known security vulnerabilities. Please make sure you update to our ",
|
"oldElectronClientDescription1": "You appear to be using an old version of the Jitsi Meet client which has known security vulnerabilities. Please make sure you update to our ",
|
||||||
"oldElectronClientDescription2": "latest build",
|
"oldElectronClientDescription2": "latest build",
|
||||||
"oldElectronClientDescription3": " now!",
|
"oldElectronClientDescription3": " now!",
|
||||||
|
"participantWantsToJoin": "Wants to join the meeting",
|
||||||
|
"participantsWantToJoin": "Want to join the meeting",
|
||||||
"passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) removed by another participant",
|
"passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) removed by another participant",
|
||||||
"passwordSetRemotely": "$t(lockRoomPasswordUppercase) set by another participant",
|
"passwordSetRemotely": "$t(lockRoomPasswordUppercase) set by another participant",
|
||||||
"raiseHandAction": "Raise hand",
|
"raiseHandAction": "Raise hand",
|
||||||
|
@ -661,7 +663,9 @@
|
||||||
"videoMutedRemotelyDescription": "You can always turn it on again.",
|
"videoMutedRemotelyDescription": "You can always turn it on again.",
|
||||||
"videoMutedRemotelyTitle": "Your video has been turned off by {{participantDisplayName}}",
|
"videoMutedRemotelyTitle": "Your video has been turned off by {{participantDisplayName}}",
|
||||||
"videoUnmuteBlockedDescription": "Camera unmute and desktop sharing operation have been temporarily blocked because of system limits.",
|
"videoUnmuteBlockedDescription": "Camera unmute and desktop sharing operation have been temporarily blocked because of system limits.",
|
||||||
"videoUnmuteBlockedTitle": "Camera unmute and desktop sharing blocked!"
|
"videoUnmuteBlockedTitle": "Camera unmute and desktop sharing blocked!",
|
||||||
|
"viewLobby": "View lobby",
|
||||||
|
"waitingParticipants": "{{waitingParticipants}} people"
|
||||||
},
|
},
|
||||||
"participantsPane": {
|
"participantsPane": {
|
||||||
"actions": {
|
"actions": {
|
||||||
|
|
|
@ -20,7 +20,7 @@ import {
|
||||||
} from '../../../filmstrip';
|
} from '../../../filmstrip';
|
||||||
import { CalleeInfoContainer } from '../../../invite';
|
import { CalleeInfoContainer } from '../../../invite';
|
||||||
import { LargeVideo } from '../../../large-video';
|
import { LargeVideo } from '../../../large-video';
|
||||||
import { KnockingParticipantList } from '../../../lobby';
|
import { KnockingParticipantList } from '../../../lobby/components/native';
|
||||||
import { getIsLobbyVisible } from '../../../lobby/functions';
|
import { getIsLobbyVisible } from '../../../lobby/functions';
|
||||||
import { BackButtonRegistry } from '../../../mobile/back-button';
|
import { BackButtonRegistry } from '../../../mobile/back-button';
|
||||||
import { Captions } from '../../../subtitles';
|
import { Captions } from '../../../subtitles';
|
||||||
|
|
|
@ -14,10 +14,9 @@ import { Chat } from '../../../chat';
|
||||||
import { Filmstrip } from '../../../filmstrip';
|
import { Filmstrip } from '../../../filmstrip';
|
||||||
import { CalleeInfoContainer } from '../../../invite';
|
import { CalleeInfoContainer } from '../../../invite';
|
||||||
import { LargeVideo } from '../../../large-video';
|
import { LargeVideo } from '../../../large-video';
|
||||||
import { KnockingParticipantList, LobbyScreen } from '../../../lobby';
|
import { LobbyScreen } from '../../../lobby';
|
||||||
import { getIsLobbyVisible } from '../../../lobby/functions';
|
import { getIsLobbyVisible } from '../../../lobby/functions';
|
||||||
import { ParticipantsPane } from '../../../participants-pane/components/web';
|
import { ParticipantsPane } from '../../../participants-pane/components/web';
|
||||||
import { getParticipantsPaneOpen } from '../../../participants-pane/functions';
|
|
||||||
import { Prejoin, isPrejoinPageVisible } from '../../../prejoin';
|
import { Prejoin, isPrejoinPageVisible } from '../../../prejoin';
|
||||||
import { toggleToolboxVisible } from '../../../toolbox/actions.any';
|
import { toggleToolboxVisible } from '../../../toolbox/actions.any';
|
||||||
import { fullScreenChanged, showToolbox } from '../../../toolbox/actions.web';
|
import { fullScreenChanged, showToolbox } from '../../../toolbox/actions.web';
|
||||||
|
@ -72,11 +71,6 @@ type Props = AbstractProps & {
|
||||||
*/
|
*/
|
||||||
_backgroundAlpha: number,
|
_backgroundAlpha: number,
|
||||||
|
|
||||||
/**
|
|
||||||
* If participants pane is visible or not.
|
|
||||||
*/
|
|
||||||
_isParticipantsPaneVisible: boolean,
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The CSS class to apply to the root of {@link Conference} to modify the
|
* The CSS class to apply to the root of {@link Conference} to modify the
|
||||||
* application layout.
|
* application layout.
|
||||||
|
@ -216,7 +210,6 @@ class Conference extends AbstractConference<Props, *> {
|
||||||
*/
|
*/
|
||||||
render() {
|
render() {
|
||||||
const {
|
const {
|
||||||
_isParticipantsPaneVisible,
|
|
||||||
_layoutClassName,
|
_layoutClassName,
|
||||||
_notificationsVisible,
|
_notificationsVisible,
|
||||||
_overflowDrawer,
|
_overflowDrawer,
|
||||||
|
@ -242,10 +235,6 @@ class Conference extends AbstractConference<Props, *> {
|
||||||
id = 'videospace'
|
id = 'videospace'
|
||||||
onTouchStart = { this._onVidespaceTouchStart }>
|
onTouchStart = { this._onVidespaceTouchStart }>
|
||||||
<LargeVideo />
|
<LargeVideo />
|
||||||
{!_isParticipantsPaneVisible
|
|
||||||
&& <div id = 'notification-participant-list'>
|
|
||||||
<KnockingParticipantList />
|
|
||||||
</div>}
|
|
||||||
<Filmstrip />
|
<Filmstrip />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -401,7 +390,6 @@ function _mapStateToProps(state) {
|
||||||
return {
|
return {
|
||||||
...abstractMapStateToProps(state),
|
...abstractMapStateToProps(state),
|
||||||
_backgroundAlpha: backgroundAlpha,
|
_backgroundAlpha: backgroundAlpha,
|
||||||
_isParticipantsPaneVisible: getParticipantsPaneOpen(state),
|
|
||||||
_layoutClassName: LAYOUT_CLASSNAMES[getCurrentLayout(state)],
|
_layoutClassName: LAYOUT_CLASSNAMES[getCurrentLayout(state)],
|
||||||
_mouseMoveCallbackInterval: mouseMoveCallbackInterval,
|
_mouseMoveCallbackInterval: mouseMoveCallbackInterval,
|
||||||
_overflowDrawer: overflowDrawer,
|
_overflowDrawer: overflowDrawer,
|
||||||
|
|
|
@ -1,78 +0,0 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
import { PureComponent } from 'react';
|
|
||||||
|
|
||||||
import { isLocalParticipantModerator } from '../../base/participants';
|
|
||||||
import { setKnockingParticipantApproval } from '../actions';
|
|
||||||
import { getKnockingParticipants, getLobbyEnabled } from '../functions';
|
|
||||||
|
|
||||||
export type Props = {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The list of participants.
|
|
||||||
*/
|
|
||||||
_participants: Array<Object>,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* True if the list should be rendered.
|
|
||||||
*/
|
|
||||||
_visible: boolean,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Redux Dispatch function.
|
|
||||||
*/
|
|
||||||
dispatch: Function,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to be used to translate i18n labels.
|
|
||||||
*/
|
|
||||||
t: Function
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract class to encapsulate the platform common code of the {@code KnockingParticipantList}.
|
|
||||||
*/
|
|
||||||
export default class AbstractKnockingParticipantList<P: Props = Props> extends PureComponent<P> {
|
|
||||||
/**
|
|
||||||
* Instantiates a new component.
|
|
||||||
*
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
constructor(props: P) {
|
|
||||||
super(props);
|
|
||||||
|
|
||||||
this._onRespondToParticipant = this._onRespondToParticipant.bind(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
_onRespondToParticipant: (string, boolean) => Function;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function that constructs a callback for the response handler button.
|
|
||||||
*
|
|
||||||
* @param {string} id - The id of the knocking participant.
|
|
||||||
* @param {boolean} approve - The response for the knocking.
|
|
||||||
* @returns {Function}
|
|
||||||
*/
|
|
||||||
_onRespondToParticipant(id, approve) {
|
|
||||||
return () => {
|
|
||||||
this.props.dispatch(setKnockingParticipantApproval(id, approve));
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Maps part of the Redux state to the props of this component.
|
|
||||||
*
|
|
||||||
* @param {Object} state - The Redux state.
|
|
||||||
* @returns {Props}
|
|
||||||
*/
|
|
||||||
export function mapStateToProps(state: Object): $Shape<Props> {
|
|
||||||
const lobbyEnabled = getLobbyEnabled(state);
|
|
||||||
const knockingParticipants = getKnockingParticipants(state);
|
|
||||||
|
|
||||||
return {
|
|
||||||
_participants: knockingParticipants,
|
|
||||||
_visible: lobbyEnabled && isLocalParticipantModerator(state)
|
|
||||||
&& Boolean(knockingParticipants && knockingParticipants.length)
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,23 +1,60 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
import React from 'react';
|
import React, { PureComponent } from 'react';
|
||||||
import { ScrollView, Text, View, TouchableOpacity } from 'react-native';
|
import { ScrollView, Text, View, TouchableOpacity } from 'react-native';
|
||||||
|
|
||||||
import { Avatar } from '../../../base/avatar';
|
import { Avatar } from '../../../base/avatar';
|
||||||
import { translate } from '../../../base/i18n';
|
import { translate } from '../../../base/i18n';
|
||||||
|
import { isLocalParticipantModerator } from '../../../base/participants';
|
||||||
import { connect } from '../../../base/redux';
|
import { connect } from '../../../base/redux';
|
||||||
|
import { setKnockingParticipantApproval } from '../../actions';
|
||||||
import { HIDDEN_EMAILS } from '../../constants';
|
import { HIDDEN_EMAILS } from '../../constants';
|
||||||
import AbstractKnockingParticipantList, {
|
import { getKnockingParticipants, getLobbyEnabled } from '../../functions';
|
||||||
mapStateToProps as abstractMapStateToProps,
|
|
||||||
type Props
|
|
||||||
} from '../AbstractKnockingParticipantList';
|
|
||||||
|
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Props type of the component.
|
||||||
|
*/
|
||||||
|
export type Props = {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of participants.
|
||||||
|
*/
|
||||||
|
_participants: Array<Object>,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if the list should be rendered.
|
||||||
|
*/
|
||||||
|
_visible: boolean,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Redux Dispatch function.
|
||||||
|
*/
|
||||||
|
dispatch: Function,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to be used to translate i18n labels.
|
||||||
|
*/
|
||||||
|
t: Function
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component to render a list for the actively knocking participants.
|
* Component to render a list for the actively knocking participants.
|
||||||
*/
|
*/
|
||||||
class KnockingParticipantList extends AbstractKnockingParticipantList {
|
class KnockingParticipantList extends PureComponent<Props> {
|
||||||
|
/**
|
||||||
|
* Instantiates a new component.
|
||||||
|
*
|
||||||
|
* @param {Object} props - The read-only properties with which the new
|
||||||
|
* instance is to be initialized.
|
||||||
|
*/
|
||||||
|
constructor(props: Props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this._onRespondToParticipant = this._onRespondToParticipant.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements {@code PureComponent#render}.
|
* Implements {@code PureComponent#render}.
|
||||||
*
|
*
|
||||||
|
@ -78,6 +115,19 @@ class KnockingParticipantList extends AbstractKnockingParticipantList {
|
||||||
}
|
}
|
||||||
|
|
||||||
_onRespondToParticipant: (string, boolean) => Function;
|
_onRespondToParticipant: (string, boolean) => Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function that constructs a callback for the response handler button.
|
||||||
|
*
|
||||||
|
* @param {string} id - The id of the knocking participant.
|
||||||
|
* @param {boolean} approve - The response for the knocking.
|
||||||
|
* @returns {Function}
|
||||||
|
*/
|
||||||
|
_onRespondToParticipant(id, approve) {
|
||||||
|
return () => {
|
||||||
|
this.props.dispatch(setKnockingParticipantApproval(id, approve));
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -86,14 +136,15 @@ class KnockingParticipantList extends AbstractKnockingParticipantList {
|
||||||
* @param {Object} state - The Redux state.
|
* @param {Object} state - The Redux state.
|
||||||
* @returns {Props}
|
* @returns {Props}
|
||||||
*/
|
*/
|
||||||
function _mapStateToProps(state: Object): $Shape<Props> {
|
function _mapStateToProps(state): Object {
|
||||||
const abstractProps = abstractMapStateToProps(state);
|
const lobbyEnabled = getLobbyEnabled(state);
|
||||||
|
const knockingParticipants = getKnockingParticipants(state);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...abstractProps,
|
_visible: lobbyEnabled && isLocalParticipantModerator(state),
|
||||||
|
|
||||||
// On mobile we only show a portion of the list for screen real estate reasons
|
// On mobile we only show a portion of the list for screen real estate reasons
|
||||||
_participants: abstractProps._participants.slice(0, 2)
|
_participants: knockingParticipants.slice(0, 2)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,57 +0,0 @@
|
||||||
// @flow
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
|
|
||||||
import { translate } from '../../../base/i18n';
|
|
||||||
import { connect } from '../../../base/redux';
|
|
||||||
import NotificationWithParticipants from '../../../notifications/components/web/NotificationWithParticipants';
|
|
||||||
import { approveKnockingParticipant, rejectKnockingParticipant } from '../../actions';
|
|
||||||
import AbstractKnockingParticipantList, {
|
|
||||||
mapStateToProps as abstractMapStateToProps,
|
|
||||||
type Props as AbstractProps
|
|
||||||
} from '../AbstractKnockingParticipantList';
|
|
||||||
|
|
||||||
type Props = AbstractProps & {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* True if the toolbox is visible, so we need to adjust the position.
|
|
||||||
*/
|
|
||||||
_toolboxVisible: boolean
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Component to render a list for the actively knocking participants.
|
|
||||||
*/
|
|
||||||
class KnockingParticipantList extends AbstractKnockingParticipantList<Props> {
|
|
||||||
/**
|
|
||||||
* Implements {@code PureComponent#render}.
|
|
||||||
*
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
render() {
|
|
||||||
const { _participants, _visible, t } = this.props;
|
|
||||||
|
|
||||||
if (!_visible) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div id = 'knocking-participant-list'>
|
|
||||||
<div className = 'title'>
|
|
||||||
{ t('lobby.knockingParticipantList') }
|
|
||||||
</div>
|
|
||||||
<NotificationWithParticipants
|
|
||||||
approveButtonText = { t('lobby.allow') }
|
|
||||||
onApprove = { approveKnockingParticipant }
|
|
||||||
onReject = { rejectKnockingParticipant }
|
|
||||||
participants = { _participants }
|
|
||||||
rejectButtonText = { t('lobby.reject') }
|
|
||||||
testIdPrefix = 'lobby' />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
_onRespondToParticipant: (string, boolean) => Function;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default translate(connect(abstractMapStateToProps)(KnockingParticipantList));
|
|
|
@ -1,5 +1,4 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
export { default as KnockingParticipantList } from './KnockingParticipantList';
|
|
||||||
export { default as LobbySection } from './LobbySection';
|
export { default as LobbySection } from './LobbySection';
|
||||||
export { default as LobbyScreen } from './LobbyScreen';
|
export { default as LobbyScreen } from './LobbyScreen';
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// @flow
|
// @flow
|
||||||
|
|
||||||
|
import i18n from 'i18next';
|
||||||
import { batch } from 'react-redux';
|
import { batch } from 'react-redux';
|
||||||
|
|
||||||
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../base/app';
|
import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../base/app';
|
||||||
|
@ -13,11 +14,17 @@ import { getFirstLoadableAvatarUrl, getParticipantDisplayName } from '../base/pa
|
||||||
import { MiddlewareRegistry, StateListenerRegistry } from '../base/redux';
|
import { MiddlewareRegistry, StateListenerRegistry } from '../base/redux';
|
||||||
import { playSound, registerSound, unregisterSound } from '../base/sounds';
|
import { playSound, registerSound, unregisterSound } from '../base/sounds';
|
||||||
import { isTestModeEnabled } from '../base/testing';
|
import { isTestModeEnabled } from '../base/testing';
|
||||||
|
import { approveKnockingParticipant, rejectKnockingParticipant } from '../lobby/actions';
|
||||||
import {
|
import {
|
||||||
|
LOBBY_NOTIFICATION_ID,
|
||||||
|
NOTIFICATION_ICON,
|
||||||
NOTIFICATION_TIMEOUT_TYPE,
|
NOTIFICATION_TIMEOUT_TYPE,
|
||||||
NOTIFICATION_TYPE,
|
NOTIFICATION_TYPE,
|
||||||
|
hideNotification,
|
||||||
showNotification
|
showNotification
|
||||||
} from '../notifications';
|
} from '../notifications';
|
||||||
|
import { open as openParticipantsPane } from '../participants-pane/actions';
|
||||||
|
import { getParticipantsPaneOpen } from '../participants-pane/functions';
|
||||||
import { shouldAutoKnock } from '../prejoin/functions';
|
import { shouldAutoKnock } from '../prejoin/functions';
|
||||||
|
|
||||||
import { KNOCKING_PARTICIPANT_ARRIVED_OR_UPDATED } from './actionTypes';
|
import { KNOCKING_PARTICIPANT_ARRIVED_OR_UPDATED } from './actionTypes';
|
||||||
|
@ -31,6 +38,7 @@ import {
|
||||||
setPasswordJoinFailed
|
setPasswordJoinFailed
|
||||||
} from './actions';
|
} from './actions';
|
||||||
import { KNOCKING_PARTICIPANT_SOUND_ID } from './constants';
|
import { KNOCKING_PARTICIPANT_SOUND_ID } from './constants';
|
||||||
|
import { getKnockingParticipants } from './functions';
|
||||||
import { KNOCKING_PARTICIPANT_FILE } from './sounds';
|
import { KNOCKING_PARTICIPANT_FILE } from './sounds';
|
||||||
|
|
||||||
declare var APP: Object;
|
declare var APP: Object;
|
||||||
|
@ -81,6 +89,55 @@ StateListenerRegistry.register(
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
dispatch(playSound(KNOCKING_PARTICIPANT_SOUND_ID));
|
dispatch(playSound(KNOCKING_PARTICIPANT_SOUND_ID));
|
||||||
|
|
||||||
|
const isParticipantsPaneVisible = getParticipantsPaneOpen(getState());
|
||||||
|
|
||||||
|
if (navigator.product === 'ReactNative' || isParticipantsPaneVisible) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let notificationTitle;
|
||||||
|
let customActionNameKey;
|
||||||
|
let customActionHandler;
|
||||||
|
let descriptionKey;
|
||||||
|
let icon;
|
||||||
|
|
||||||
|
const knockingParticipants = getKnockingParticipants(getState());
|
||||||
|
const firstParticipant = knockingParticipants[0];
|
||||||
|
|
||||||
|
if (knockingParticipants.length > 1) {
|
||||||
|
descriptionKey = 'notify.participantsWantToJoin';
|
||||||
|
notificationTitle = i18n.t('notify.waitingParticipants', {
|
||||||
|
waitingParticipants: knockingParticipants.length
|
||||||
|
});
|
||||||
|
icon = NOTIFICATION_ICON.PARTICIPANTS;
|
||||||
|
customActionNameKey = [ 'notify.viewLobby' ];
|
||||||
|
customActionHandler = [ () => batch(() => {
|
||||||
|
dispatch(hideNotification(LOBBY_NOTIFICATION_ID));
|
||||||
|
dispatch(openParticipantsPane());
|
||||||
|
}) ];
|
||||||
|
} else {
|
||||||
|
descriptionKey = 'notify.participantWantsToJoin';
|
||||||
|
notificationTitle = firstParticipant.name;
|
||||||
|
icon = NOTIFICATION_ICON.PARTICIPANT;
|
||||||
|
customActionNameKey = [ 'lobby.admit', 'lobby.reject' ];
|
||||||
|
customActionHandler = [ () => batch(() => {
|
||||||
|
dispatch(hideNotification(LOBBY_NOTIFICATION_ID));
|
||||||
|
dispatch(approveKnockingParticipant(firstParticipant.id));
|
||||||
|
}),
|
||||||
|
() => batch(() => {
|
||||||
|
dispatch(hideNotification(LOBBY_NOTIFICATION_ID));
|
||||||
|
dispatch(rejectKnockingParticipant(firstParticipant.id));
|
||||||
|
}) ];
|
||||||
|
}
|
||||||
|
dispatch(showNotification({
|
||||||
|
title: notificationTitle,
|
||||||
|
descriptionKey,
|
||||||
|
uid: LOBBY_NOTIFICATION_ID,
|
||||||
|
customActionNameKey,
|
||||||
|
customActionHandler,
|
||||||
|
icon
|
||||||
|
}, NOTIFICATION_TIMEOUT_TYPE.STICKY));
|
||||||
|
|
||||||
if (typeof APP !== 'undefined') {
|
if (typeof APP !== 'undefined') {
|
||||||
APP.API.notifyKnockingParticipant({
|
APP.API.notifyKnockingParticipant({
|
||||||
id,
|
id,
|
||||||
|
|
|
@ -5,6 +5,8 @@ import EditorErrorIcon from '@atlaskit/icon/glyph/editor/error';
|
||||||
import EditorInfoIcon from '@atlaskit/icon/glyph/editor/info';
|
import EditorInfoIcon from '@atlaskit/icon/glyph/editor/info';
|
||||||
import EditorSuccessIcon from '@atlaskit/icon/glyph/editor/success';
|
import EditorSuccessIcon from '@atlaskit/icon/glyph/editor/success';
|
||||||
import EditorWarningIcon from '@atlaskit/icon/glyph/editor/warning';
|
import EditorWarningIcon from '@atlaskit/icon/glyph/editor/warning';
|
||||||
|
import PeopleIcon from '@atlaskit/icon/glyph/people';
|
||||||
|
import PersonIcon from '@atlaskit/icon/glyph/person';
|
||||||
import QuestionsIcon from '@atlaskit/icon/glyph/questions';
|
import QuestionsIcon from '@atlaskit/icon/glyph/questions';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
|
@ -171,6 +173,12 @@ class Notification extends AbstractNotification<Props> {
|
||||||
case NOTIFICATION_ICON.MESSAGE:
|
case NOTIFICATION_ICON.MESSAGE:
|
||||||
Icon = QuestionsIcon;
|
Icon = QuestionsIcon;
|
||||||
break;
|
break;
|
||||||
|
case NOTIFICATION_ICON.PARTICIPANT:
|
||||||
|
Icon = PersonIcon;
|
||||||
|
break;
|
||||||
|
case NOTIFICATION_ICON.PARTICIPANTS:
|
||||||
|
Icon = PeopleIcon;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
Icon = EditorInfoIcon;
|
Icon = EditorInfoIcon;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -53,9 +53,18 @@ export const NOTIFICATION_TYPE_PRIORITIES = {
|
||||||
*/
|
*/
|
||||||
export const NOTIFICATION_ICON = {
|
export const NOTIFICATION_ICON = {
|
||||||
...NOTIFICATION_TYPE,
|
...NOTIFICATION_TYPE,
|
||||||
MESSAGE: 'message'
|
MESSAGE: 'message',
|
||||||
|
PARTICIPANT: 'participant',
|
||||||
|
PARTICIPANTS: 'participants'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The identifier of the lobby notification.
|
||||||
|
*
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
export const LOBBY_NOTIFICATION_ID = 'LOBBY_NOTIFICATION';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The identifier of the raise hand notification.
|
* The identifier of the raise hand notification.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue