Room lock update (#4394)

* Adds a notification when remote lock happens.

* Updates translations.

Removes unused strings and extracts room password to separate translation, to be able to change it when deployment uses only digits.

* Formats the conference pin when showing it.

* Removes member from translation in favour of participant.

* Updates formatting of the pin.

* Adds a notification when password is remotely removed.
This commit is contained in:
Дамян Минков 2019-07-02 14:14:58 +01:00 committed by GitHub
parent 681782ed20
commit 625d268373
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 84 additions and 59 deletions

View File

@ -4,7 +4,7 @@
"countryNotSupported": "We do not support this destination yet.",
"countryReminder": "Calling outside the US? Please make sure you start with the country code!",
"disabled": "You can't invite people.",
"failedToAdd": "Failed to add members",
"failedToAdd": "Failed to add participants",
"footerText": "Dialing out is disabled.",
"invite": "Invite",
"loading": "Searching for people and phone numbers",
@ -112,7 +112,6 @@
"transport_plural": "Transports:",
"turn": " (turn)"
},
"contactlist_plural": "__count__ Members",
"dateUtils": {
"earlier": "Earlier",
"today": "Today",
@ -148,7 +147,7 @@
"liveStreaming": "Live Stream"
},
"allow": "Allow",
"alreadySharedVideoMsg": "Another member is already sharing a video. This conference allows only one shared video at a time.",
"alreadySharedVideoMsg": "Another participant is already sharing a video. This conference allows only one shared video at a time.",
"alreadySharedVideoTitle": "Only one shared video is allowed at a time",
"applicationWindow": "Application window",
"Back": "Back",
@ -173,7 +172,6 @@
"connecting": "Connecting",
"contactSupport": "Contact support",
"copy": "Copy",
"currentPassword": "The current password is",
"defaultError": "There was some kind of error",
"detectext": "Error when trying to detect desktopsharing extension.",
"dismiss": "Dismiss",
@ -200,18 +198,18 @@
"kickMessage": "You can contact __participantDisplayName__ for more details.",
"kickParticipantButton": "Kick",
"kickParticipantDialog": "Are you sure you want to kick this participant?",
"kickParticipantTitle": "Kick this member?",
"kickParticipantTitle": "Kick this participant?",
"kickTitle": "Ouch! __participantDisplayName__ kicked you out of the meeting",
"liveStreaming": "Live Streaming",
"liveStreamingDisabledForGuestTooltip": "Guests can't start live streaming.",
"liveStreamingDisabledTooltip": "Start live stream disabled.",
"lockMessage": "Failed to lock the conference.",
"lockRoom": "Add meeting password",
"lockRoom": "Add meeting $t(lockRoomPasswordUppercase)",
"lockTitle": "Lock failed",
"logoutQuestion": "Are you sure you want to logout and stop the conference?",
"logoutTitle": "Logout",
"maxUsersLimitReached": "The limit for maximum number of members has been reached. The conference is full. Please contact the meeting owner or try again later!",
"maxUsersLimitReachedTitle": "Maximum members limit reached",
"maxUsersLimitReached": "The limit for maximum number of participants has been reached. The conference is full. Please contact the meeting owner or try again later!",
"maxUsersLimitReachedTitle": "Maximum participants limit reached",
"micConstraintFailedError": "Your microphone does not satisfy some of the required constraints.",
"micNotFoundError": "Microphone was not found.",
"micNotSendingData": "Go to your computer's settings to unmute your mic and adjust its level",
@ -221,17 +219,13 @@
"muteParticipantBody": "You won't be able to unmute them, but they can unmute themselves at any time.",
"muteParticipantButton": "Mute",
"muteParticipantDialog": "Are you sure you want to mute this participant? You won't be able to unmute them, but they can unmute themselves at any time.",
"muteParticipantTitle": "Mute this member?",
"muteParticipantTitle": "Mute this participant?",
"Ok": "Ok",
"oops": "Oops!",
"password": "Enter password",
"passwordError": "This conversation is currently protected by a password. Only the owner of the conference can set a password.",
"passwordError2": "This conversation isn't currently protected by a password. Only the owner of the conference can set a password.",
"passwordErrorTitle": "Password Error",
"passwordLabel": "Password",
"passwordNotSupported": "Setting a meeting password is not supported.",
"passwordNotSupportedTitle": "Password not supported",
"passwordRequired": "Password required",
"passwordLabel": "$t(lockRoomPasswordUppercase)",
"passwordNotSupported": "Setting a meeting $t(lockRoomPassword) is not supported.",
"passwordNotSupportedTitle": "$t(lockRoomPasswordUppercase) not supported",
"passwordRequired": "$t(lockRoomPasswordUppercase) required",
"permissionDenied": "Permission Denied",
"popupError": "Your browser is blocking pop-up windows from this site. Please enable pop-ups in your browser's security settings and try again.",
"popupErrorTitle": "Pop-up blocked",
@ -248,7 +242,7 @@
"remoteControlStopMessage": "The remote control session ended!",
"remoteControlTitle": "Remote desktop control",
"Remove": "Remove",
"removePassword": "Remove password",
"removePassword": "Remove $t(lockRoomPassword)",
"removeSharedVideoMsg": "Are you sure you would like to remove your shared video?",
"removeSharedVideoTitle": "Remove shared video",
"reservationError": "Reservation system error",
@ -286,7 +280,7 @@
"tokenAuthFailedTitle": "Authentication failed",
"transcribing": "Transcribing",
"unableToSwitch": "Unable to switch video stream.",
"unlockRoom": "Remove meeting password",
"unlockRoom": "Remove meeting $t(lockRoomPassword)",
"userPassword": "user password",
"WaitForHostMsg": "The conference <b>__room__</b> has not yet started. If you are the host then please authenticate. Otherwise, please wait for the host to arrive.",
"WaitForHostMsgWOk": "The conference <b>__room__</b> has not yet started. If you are the host then please press Ok to authenticate. Otherwise, please wait for the host to arrive.",
@ -298,34 +292,6 @@
"dialOut": {
"statusMessage": "is now __status__"
},
"email": {
"and": "and",
"body": [
" Note that __appName__ is currently only supported by __supportedBrowsers__, so you need to be using one of these browsers.",
"",
"",
"",
"",
"",
"",
"",
"",
"Hey there, I%27d like to invite you to a __appName__ conference I%27ve just set up.",
"Please click on the following link in order to join the conference.",
"Talk to you in a sec!",
"__roomUrl__",
"__sharedKeyText__"
],
"sharedKey": [
"",
"",
"",
"",
"This conference is password-protected. Please use the following pin when joining:",
"__sharedKey__"
],
"subject": "Invitation to a __appName__ (__conferenceName__)"
},
"feedback": {
"average": "Average",
"bad": "Bad",
@ -344,8 +310,8 @@
},
"info": {
"accessibilityLabel": "Show info",
"addPassword": "Add password",
"cancelPassword": "Cancel password",
"addPassword": "Add $t(lockRoomPassword)",
"cancelPassword": "Cancel $t(lockRoomPassword)",
"conferenceURL": "Link:",
"country": "Country",
"dialANumber": "To join your meeting, dial one of these numbers and then enter the pin.",
@ -367,7 +333,7 @@
"noPassword": "None",
"noRoom": "No room was specified to dial-in into.",
"numbers": "Dial-in Numbers",
"password": "Password:",
"password": "$t(lockRoomPasswordUppercase):",
"title": "Share",
"tooltip": "Share link and dial-in info for this meeting",
"label": "Meeting info"
@ -463,6 +429,8 @@
"stop": "Stop Recording",
"yes": "Yes"
},
"lockRoomPassword": "password",
"lockRoomPasswordUppercase": "Password",
"me": "me",
"notify": {
"connectedOneMember": "__name__ joined the meeting",
@ -482,6 +450,8 @@
"mutedTitle": "You're muted!",
"mutedRemotelyTitle": "You have been muted by __participantDisplayName__!",
"mutedRemotelyDescription": "You can always unmute when you're ready to speak. Mute back when you're done to keep noise away from the meeting.",
"passwordRemovedRemotely": "$t(lockRoomPasswordUppercase) removed by another participant",
"passwordSetRemotely": "$t(lockRoomPasswordUppercase) set by another participant",
"raisedHand": "__name__ would like to speak.",
"somebody": "Somebody",
"startSilentTitle": "You joined with no audio output!",
@ -493,7 +463,7 @@
"newDeviceAudioTitle": "New audio device detected",
"newDeviceAction": "Use"
},
"passwordSetRemotely": "set by another member",
"passwordSetRemotely": "set by another participant",
"passwordDigitsOnly": "Up to __number__ digits",
"poweredby": "powered by",
"presenceStatus": {
@ -568,7 +538,6 @@
"more": "More",
"name": "Name",
"noDevice": "None",
"password": "SET PASSWORD",
"selectAudioOutput": "Audio output",
"selectCamera": "Camera",
"selectMic": "Microphone",
@ -685,7 +654,7 @@
"raiseYourHand": "Raise your hand",
"Settings": "Settings",
"sharedvideo": "Share a YouTube video",
"sharedVideoMutedPopup": "Your shared video has been muted so that you can talk to the other members.",
"sharedVideoMutedPopup": "Your shared video has been muted so that you can talk to the other participants.",
"shareRoom": "Invite someone",
"shortcuts": "View shortcuts",
"sip": "Call SIP number",
@ -765,11 +734,11 @@
"flip": "Flip",
"kick": "Kick out",
"moderator": "Moderator",
"mute": "Member is muted",
"mute": "Participant is muted",
"muted": "Muted",
"remoteControl": "Remote control",
"show": "Show on stage",
"videomute": "Member has stopped the camera"
"videomute": "Participant has stopped the camera"
},
"welcomepage": {
"accessibilityLabel": {

View File

@ -0,0 +1,28 @@
// @flow
/**
* Utility class with no dependencies. Used in components that are stripped in separate bundles
* and requires as less dependencies as possible.
*/
/**
* Formats the conference pin in readable way for UI to display it.
* Formats the pin in 3 groups of digits:
* XXXX XXXX XX or XXXXX XXXXX XXX.
* The length of first and second group is Math.ceil(pin.length / 3)
*
* @param {Object} conferenceID - The conference id to format, string or number.
* @returns {string} - The formatted conference pin.
* @private
*/
export function _formatConferenceIDPin(conferenceID: Object) {
const conferenceIDStr = conferenceID.toString();
// let's split the conferenceID in 3 parts, to be easier to read
const partLen = Math.ceil(conferenceIDStr.length / 3);
return `${
conferenceIDStr.substring(0, partLen)} ${
conferenceIDStr.substring(partLen, 2 * partLen)} ${
conferenceIDStr.substring(2 * partLen, conferenceIDStr.length)}`;
}

View File

@ -4,6 +4,8 @@ import React, { Component } from 'react';
import { translate } from '../../../../base/i18n';
import { _formatConferenceIDPin } from '../../../_utils';
/**
* The type of the React {@code Component} props of {@link ConferenceID}.
*/
@ -49,7 +51,7 @@ class ConferenceID extends Component<Props> {
{ t('info.dialANumber') }
</div>
<div className = 'dial-in-conference-pin'>
{ `${t('info.dialInConferenceID')} ${conferenceID}` }
{ `${t('info.dialInConferenceID')} ${_formatConferenceIDPin(conferenceID)}` }
</div>
</div>
);

View File

@ -4,6 +4,8 @@ import React, { Component } from 'react';
import { translate } from '../../../../base/i18n';
import { _formatConferenceIDPin } from '../../../_utils';
/**
* The type of the React {@code Component} props of {@link DialInNumber}.
*/
@ -61,7 +63,7 @@ class DialInNumber extends Component<Props> {
</span>
<span className = 'spacer'>&nbsp;</span>
<span className = 'info-value'>
{ `${conferenceID}#` }
{ `${_formatConferenceIDPin(conferenceID)}#` }
</span>
</span>
</div>

View File

@ -8,10 +8,15 @@ import {
import { hideDialog } from '../base/dialog';
import { JitsiConferenceErrors } from '../base/lib-jitsi-meet';
import { MiddlewareRegistry } from '../base/redux';
import {
NOTIFICATION_TIMEOUT,
showNotification
} from '../notifications';
import UIEvents from '../../../service/UI/UIEvents';
import { _openPasswordRequiredPrompt } from './actions';
import { PasswordRequiredPrompt, RoomLockPrompt } from './components';
import { LOCKED_REMOTELY } from './constants';
declare var APP: Object;
@ -29,14 +34,33 @@ MiddlewareRegistry.register(store => next => action => {
case CONFERENCE_FAILED:
return _conferenceFailed(store, next, action);
case LOCK_STATE_CHANGED:
case LOCK_STATE_CHANGED: {
// TODO Remove this logic when all components interested in the lock
// state change event are moved into react/redux.
if (typeof APP !== 'undefined') {
APP.UI.emitEvent(UIEvents.TOGGLE_ROOM_LOCK, action.locked);
}
break;
const previousLockedState = store.getState()['features/base/conference'].locked;
const result = next(action);
const currentLockedState = store.getState()['features/base/conference'].locked;
if (currentLockedState === LOCKED_REMOTELY) {
store.dispatch(
showNotification({
titleKey: 'notify.passwordSetRemotely'
}, NOTIFICATION_TIMEOUT));
} else if (previousLockedState === LOCKED_REMOTELY && !currentLockedState) {
store.dispatch(
showNotification({
titleKey: 'notify.passwordRemovedRemotely'
}, NOTIFICATION_TIMEOUT));
}
return result;
}
case SET_PASSWORD_FAILED:
return _setPasswordFailed(store, next, action);
}