ref(security-dialog) Use new input component for password (#11946)
This commit is contained in:
parent
873cdbb404
commit
002d0fed42
|
@ -38,19 +38,6 @@
|
|||
color: #fff;
|
||||
}
|
||||
|
||||
.info-password-input {
|
||||
width: 100%;
|
||||
background-color: #0E1624;
|
||||
border-radius: 3px;
|
||||
border: 2px solid #202B3D;
|
||||
color: inherit;
|
||||
padding-left: 0;
|
||||
}
|
||||
.info-password-input:focus ,
|
||||
.info-password-input:active {
|
||||
border: 2px solid #B8C7E0;
|
||||
}
|
||||
|
||||
.info-password-local {
|
||||
user-select: text;
|
||||
}
|
||||
|
|
|
@ -13,12 +13,14 @@
|
|||
}
|
||||
|
||||
.password {
|
||||
align-items: center;
|
||||
align-items: flex-start;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
justify-content: flex-start;
|
||||
margin-top: 15px;
|
||||
flex-direction: column;
|
||||
|
||||
&-actions {
|
||||
margin-top: 10px;
|
||||
a {
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
|
@ -26,8 +28,8 @@
|
|||
color: #6FB1EA;
|
||||
}
|
||||
|
||||
& > :first-child:not(:last-child) {
|
||||
margin-right: 24px;
|
||||
& > :first-child:not(:last-child) {
|
||||
margin-right: 24px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,10 +10,14 @@ import { Theme } from '../../../ui/types';
|
|||
import { InputProps } from '../types';
|
||||
|
||||
interface IInputProps extends InputProps {
|
||||
accessibilityLabel?: string;
|
||||
autoFocus?: boolean;
|
||||
bottomLabel?: string;
|
||||
className?: string;
|
||||
id?: string;
|
||||
maxLength?: number;
|
||||
name?: string;
|
||||
onKeyPress?: (e: React.KeyboardEvent) => void;
|
||||
type?: 'text' | 'email' | 'number' | 'password';
|
||||
}
|
||||
|
||||
|
@ -115,6 +119,8 @@ const useStyles = makeStyles((theme: Theme) => {
|
|||
});
|
||||
|
||||
const Input = ({
|
||||
accessibilityLabel,
|
||||
autoFocus,
|
||||
bottomLabel,
|
||||
className,
|
||||
clearable = false,
|
||||
|
@ -123,8 +129,10 @@ const Input = ({
|
|||
icon,
|
||||
id,
|
||||
label,
|
||||
maxLength,
|
||||
name,
|
||||
onChange,
|
||||
onKeyPress,
|
||||
placeholder,
|
||||
type = 'text',
|
||||
value
|
||||
|
@ -145,12 +153,16 @@ const Input = ({
|
|||
size = { 20 }
|
||||
src = { icon } />}
|
||||
<input
|
||||
aria-label = { accessibilityLabel }
|
||||
autoFocus = { autoFocus }
|
||||
className = { clsx(styles.input, isMobile && 'is-mobile',
|
||||
error && 'error', clearable && styles.clearableInput, icon && styles.iconInput) }
|
||||
disabled = { disabled }
|
||||
{ ...(id ? { id } : {}) }
|
||||
maxLength = { maxLength }
|
||||
name = { name }
|
||||
onChange = { handleChange }
|
||||
onKeyPress = { onKeyPress }
|
||||
placeholder = { placeholder }
|
||||
type = { type }
|
||||
value = { value } />
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
// @flow
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
|
||||
import { translate } from '../../../../base/i18n';
|
||||
import { translate } from '../../../../base/i18n/functions';
|
||||
import Input from '../../../../base/ui/components/web/Input';
|
||||
// eslint-disable-next-line lines-around-comment
|
||||
// @ts-ignore
|
||||
import { LOCKED_LOCALLY } from '../../../../room-lock';
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} props of {@link PasswordForm}.
|
||||
*/
|
||||
type Props = {
|
||||
interface Props extends WithTranslation {
|
||||
|
||||
/**
|
||||
* Whether or not to show the password editing field.
|
||||
|
@ -35,13 +37,8 @@ type Props = {
|
|||
/**
|
||||
* The number of digits to be used in the password.
|
||||
*/
|
||||
passwordNumberOfDigits: boolean,
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
passwordNumberOfDigits?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of the React {@code Component} state of {@link PasswordForm}.
|
||||
|
@ -65,7 +62,7 @@ class PasswordForm extends Component<Props, State> {
|
|||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
static getDerivedStateFromProps(props, state) {
|
||||
static getDerivedStateFromProps(props: Props, state: State) {
|
||||
return {
|
||||
enteredPassword: props.editEnabled ? state.enteredPassword : ''
|
||||
};
|
||||
|
@ -96,21 +93,42 @@ class PasswordForm extends Component<Props, State> {
|
|||
* @returns {ReactElement}
|
||||
*/
|
||||
render() {
|
||||
const { t } = this.props;
|
||||
|
||||
return (
|
||||
<div className = 'info-password'>
|
||||
<span className = 'info-label'>
|
||||
{ t('info.password') }
|
||||
</span>
|
||||
<span className = 'spacer'> </span>
|
||||
<span className = 'info-password-field info-value'>
|
||||
{ this._renderPasswordField() }
|
||||
</span>
|
||||
{this._renderPassword()}
|
||||
{this._renderPasswordField()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/** .........
|
||||
* Renders the password if there is any.
|
||||
*
|
||||
* @returns {ReactElement}
|
||||
*/
|
||||
_renderPassword() {
|
||||
const { locked, t } = this.props;
|
||||
|
||||
return locked && <>
|
||||
<span className = 'info-label'>
|
||||
{t('info.password')}
|
||||
</span>
|
||||
<span className = 'spacer'> </span>
|
||||
<span className = 'info-password-field info-value'>
|
||||
{locked === LOCKED_LOCALLY ? (
|
||||
<div className = 'info-password-local'>
|
||||
{this.props.password}
|
||||
</div>
|
||||
) : (
|
||||
<div className = 'info-password-remote'>
|
||||
{this.props.t('passwordSetRemotely')}
|
||||
</div>
|
||||
) }
|
||||
{this._renderPasswordField()}
|
||||
</span>
|
||||
</>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a ReactElement for showing the current state of the password or
|
||||
* for editing the current password.
|
||||
|
@ -120,7 +138,7 @@ class PasswordForm extends Component<Props, State> {
|
|||
*/
|
||||
_renderPasswordField() {
|
||||
if (this.props.editEnabled) {
|
||||
let placeHolderText;
|
||||
let placeHolderText = this.props.t('dialog.password');
|
||||
|
||||
if (this.props.passwordNumberOfDigits) {
|
||||
placeHolderText = this.props.t('passwordDigitsOnly', {
|
||||
|
@ -130,55 +148,31 @@ class PasswordForm extends Component<Props, State> {
|
|||
return (
|
||||
<div
|
||||
className = 'info-password-form'>
|
||||
<input
|
||||
aria-label = { this.props.t('info.addPassword') }
|
||||
<Input
|
||||
accessibilityLabel = { this.props.t('info.addPassword') }
|
||||
autoFocus = { true }
|
||||
className = 'info-password-input'
|
||||
id = 'info-password-input'
|
||||
maxLength = { this.props.passwordNumberOfDigits }
|
||||
onChange = { this._onEnteredPasswordChange }
|
||||
onKeyPress = { this._onKeyPress }
|
||||
placeholder = { placeHolderText }
|
||||
spellCheck = { 'false' }
|
||||
type = 'text'
|
||||
value = { this.state.enteredPassword } />
|
||||
</div>
|
||||
);
|
||||
} else if (this.props.locked === LOCKED_LOCALLY) {
|
||||
return (
|
||||
<div className = 'info-password-local'>
|
||||
{ this.props.password }
|
||||
</div>
|
||||
);
|
||||
} else if (this.props.locked) {
|
||||
return (
|
||||
<div className = 'info-password-remote'>
|
||||
{ this.props.t('passwordSetRemotely') }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className = 'info-password-none'>
|
||||
{ this.props.t('info.noPassword') }
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
_onEnteredPasswordChange: (Object) => void;
|
||||
|
||||
/**
|
||||
* Updates the internal state of entered password.
|
||||
*
|
||||
* @param {Object} event - DOM Event for value change.
|
||||
* @param {string} value - DOM Event for value change.
|
||||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_onEnteredPasswordChange(event) {
|
||||
this.setState({ enteredPassword: event.target.value });
|
||||
_onEnteredPasswordChange(value: string) {
|
||||
this.setState({ enteredPassword: value });
|
||||
}
|
||||
|
||||
_onKeyPress: (Object) => void;
|
||||
|
||||
/**
|
||||
* Stops the the EnterKey for propagation in order to prevent the dialog
|
||||
* to close.
|
||||
|
@ -187,7 +181,7 @@ class PasswordForm extends Component<Props, State> {
|
|||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
_onKeyPress(event) {
|
||||
_onKeyPress(event: React.KeyboardEvent) {
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
|
@ -1,24 +1,24 @@
|
|||
// @flow
|
||||
|
||||
/* eslint-disable react/no-multi-comp, react/jsx-no-bind */
|
||||
|
||||
/* eslint-disable react/jsx-no-bind */
|
||||
import React, { useRef } from 'react';
|
||||
import { WithTranslation } from 'react-i18next';
|
||||
|
||||
import { translate } from '../../../../base/i18n';
|
||||
import { copyText } from '../../../../base/util';
|
||||
import { translate } from '../../../../base/i18n/functions';
|
||||
import { copyText } from '../../../../base/util/helpers';
|
||||
import { NOTIFY_CLICK_MODE } from '../../../../toolbox/constants';
|
||||
|
||||
// @ts-ignore
|
||||
import PasswordForm from './PasswordForm';
|
||||
import { NotifyClick } from './SecurityDialog';
|
||||
|
||||
const DIGITS_ONLY = /^\d+$/;
|
||||
const KEY = 'add-passcode';
|
||||
|
||||
type Props = {
|
||||
interface Props extends WithTranslation {
|
||||
|
||||
/**
|
||||
* Toolbar buttons which have their click exposed through the API.
|
||||
*/
|
||||
buttonsWithNotifyClick: Array<string | Object>,
|
||||
buttonsWithNotifyClick: Array<string | NotifyClick>,
|
||||
|
||||
/**
|
||||
* Whether or not the current user can modify the current password.
|
||||
|
@ -29,7 +29,7 @@ type Props = {
|
|||
* The JitsiConference for which to display a lock state and change the
|
||||
* password.
|
||||
*/
|
||||
conference: Object,
|
||||
conference: any,
|
||||
|
||||
/**
|
||||
* The value for how the conference is locked (or undefined if not locked)
|
||||
|
@ -50,7 +50,7 @@ type Props = {
|
|||
/**
|
||||
* The number of digits to be used in the password.
|
||||
*/
|
||||
passwordNumberOfDigits: ?number,
|
||||
passwordNumberOfDigits?: number,
|
||||
|
||||
/**
|
||||
* Action that sets the conference password.
|
||||
|
@ -60,15 +60,10 @@ type Props = {
|
|||
/**
|
||||
* Method that sets whether the password editing is enabled or not.
|
||||
*/
|
||||
setPasswordEditEnabled: Function,
|
||||
setPasswordEditEnabled: Function
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked to obtain translated strings.
|
||||
*/
|
||||
t: Function
|
||||
};
|
||||
|
||||
declare var APP: Object;
|
||||
declare let APP: any;
|
||||
|
||||
/**
|
||||
* Component that handles the password manipulation from the invite dialog.
|
||||
|
@ -87,7 +82,7 @@ function PasswordSection({
|
|||
setPasswordEditEnabled,
|
||||
t }: Props) {
|
||||
|
||||
const formRef: Object = useRef(null);
|
||||
const formRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
/**
|
||||
* Callback invoked to set a password on the current JitsiConference.
|
||||
|
@ -97,7 +92,7 @@ function PasswordSection({
|
|||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function onPasswordSubmit(enteredPassword) {
|
||||
function onPasswordSubmit(enteredPassword: string) {
|
||||
if (enteredPassword && passwordNumberOfDigits && !DIGITS_ONLY.test(enteredPassword)) {
|
||||
// Don't set the password.
|
||||
return;
|
||||
|
@ -121,7 +116,7 @@ function PasswordSection({
|
|||
|
||||
let notifyMode;
|
||||
const notify = buttonsWithNotifyClick.find(
|
||||
(btn: string | Object) =>
|
||||
(btn: string | NotifyClick) =>
|
||||
(typeof btn === 'string' && btn === KEY)
|
||||
|| (typeof btn === 'object' && btn.key === KEY)
|
||||
);
|
||||
|
@ -147,6 +142,7 @@ function PasswordSection({
|
|||
*/
|
||||
function onPasswordSave() {
|
||||
if (formRef.current) {
|
||||
// @ts-ignore
|
||||
const { value } = formRef.current.querySelector('div > input');
|
||||
|
||||
if (value) {
|
||||
|
@ -182,7 +178,7 @@ function PasswordSection({
|
|||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function onTogglePasswordEditStateKeyPressHandler(e) {
|
||||
function onTogglePasswordEditStateKeyPressHandler(e: React.KeyboardEvent) {
|
||||
if (e.key === ' ' || e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
onTogglePasswordEditState();
|
||||
|
@ -197,7 +193,7 @@ function PasswordSection({
|
|||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function onPasswordSaveKeyPressHandler(e) {
|
||||
function onPasswordSaveKeyPressHandler(e: React.KeyboardEvent) {
|
||||
if (e.key === ' ' || e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
onPasswordSave();
|
||||
|
@ -212,7 +208,7 @@ function PasswordSection({
|
|||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function onPasswordRemoveKeyPressHandler(e) {
|
||||
function onPasswordRemoveKeyPressHandler(e: React.KeyboardEvent) {
|
||||
if (e.key === ' ' || e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
onPasswordRemove();
|
||||
|
@ -227,7 +223,7 @@ function PasswordSection({
|
|||
* @private
|
||||
* @returns {void}
|
||||
*/
|
||||
function onPasswordCopyKeyPressHandler(e) {
|
||||
function onPasswordCopyKeyPressHandler(e: React.KeyboardEvent) {
|
||||
if (e.key === ' ' || e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
onPasswordCopy();
|
|
@ -1,22 +1,31 @@
|
|||
// @flow
|
||||
|
||||
/* eslint-disable lines-around-comment */
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
// @ts-ignore
|
||||
import { setPassword as setPass } from '../../../../base/conference';
|
||||
// @ts-ignore
|
||||
import { Dialog } from '../../../../base/dialog';
|
||||
// @ts-ignore
|
||||
import { isLocalParticipantModerator } from '../../../../base/participants';
|
||||
import { connect } from '../../../../base/redux';
|
||||
// @ts-ignore
|
||||
import { E2EESection } from '../../../../e2ee/components';
|
||||
// @ts-ignore
|
||||
import { LobbySection } from '../../../../lobby';
|
||||
|
||||
import PasswordSection from './PasswordSection';
|
||||
|
||||
export interface NotifyClick {
|
||||
key: string;
|
||||
preventExecution: boolean;
|
||||
}
|
||||
|
||||
type Props = {
|
||||
|
||||
/**
|
||||
* Toolbar buttons which have their click exposed through the API.
|
||||
*/
|
||||
_buttonsWithNotifyClick: Array<string | Object>,
|
||||
_buttonsWithNotifyClick: Array<string | NotifyClick>,
|
||||
|
||||
/**
|
||||
* Whether or not the current user can modify the current password.
|
||||
|
@ -43,7 +52,7 @@ type Props = {
|
|||
/**
|
||||
* The number of digits to be used in the password.
|
||||
*/
|
||||
_passwordNumberOfDigits: ?number,
|
||||
_passwordNumberOfDigits?: number,
|
||||
|
||||
/**
|
||||
* Indicates whether e2ee will be displayed or not.
|
||||
|
@ -117,7 +126,7 @@ function SecurityDialog({
|
|||
* @private
|
||||
* @returns {Props}
|
||||
*/
|
||||
function mapStateToProps(state) {
|
||||
function mapStateToProps(state: any) {
|
||||
const {
|
||||
conference,
|
||||
e2eeSupported,
|
Loading…
Reference in New Issue