From 002d0fed42e8a356ee74930ea85c2362c7094284 Mon Sep 17 00:00:00 2001 From: Robert Pintilii Date: Thu, 4 Aug 2022 11:26:13 +0300 Subject: [PATCH] ref(security-dialog) Use new input component for password (#11946) --- css/modals/invite/_info.scss | 13 --- css/modals/security/_security.scss | 10 +- .../features/base/ui/components/web/Input.tsx | 12 +++ .../web/{PasswordForm.js => PasswordForm.tsx} | 100 ++++++++---------- ...PasswordSection.js => PasswordSection.tsx} | 46 ++++---- .../{SecurityDialog.js => SecurityDialog.tsx} | 21 ++-- .../toolbox/{constants.js => constants.ts} | 0 7 files changed, 101 insertions(+), 101 deletions(-) rename react/features/security/components/security-dialog/web/{PasswordForm.js => PasswordForm.tsx} (67%) rename react/features/security/components/security-dialog/web/{PasswordSection.js => PasswordSection.tsx} (90%) rename react/features/security/components/security-dialog/web/{SecurityDialog.js => SecurityDialog.tsx} (91%) rename react/features/toolbox/{constants.js => constants.ts} (100%) diff --git a/css/modals/invite/_info.scss b/css/modals/invite/_info.scss index 9eed4e5b68..7992206c8c 100644 --- a/css/modals/invite/_info.scss +++ b/css/modals/invite/_info.scss @@ -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; } diff --git a/css/modals/security/_security.scss b/css/modals/security/_security.scss index cc8ea66c09..cf04ba6ded 100644 --- a/css/modals/security/_security.scss +++ b/css/modals/security/_security.scss @@ -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; } } } diff --git a/react/features/base/ui/components/web/Input.tsx b/react/features/base/ui/components/web/Input.tsx index 20b67915c2..702f65d734 100644 --- a/react/features/base/ui/components/web/Input.tsx +++ b/react/features/base/ui/components/web/Input.tsx @@ -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 } />} diff --git a/react/features/security/components/security-dialog/web/PasswordForm.js b/react/features/security/components/security-dialog/web/PasswordForm.tsx similarity index 67% rename from react/features/security/components/security-dialog/web/PasswordForm.js rename to react/features/security/components/security-dialog/web/PasswordForm.tsx index c9577ac66d..beae933dc6 100644 --- a/react/features/security/components/security-dialog/web/PasswordForm.js +++ b/react/features/security/components/security-dialog/web/PasswordForm.tsx @@ -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 { * * @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 { * @returns {ReactElement} */ render() { - const { t } = this.props; - return (
- - { t('info.password') } - -   - - { this._renderPasswordField() } - + {this._renderPassword()} + {this._renderPasswordField()}
); } + /** ......... + * Renders the password if there is any. + * + * @returns {ReactElement} + */ + _renderPassword() { + const { locked, t } = this.props; + + return locked && <> + + {t('info.password')} + +   + + {locked === LOCKED_LOCALLY ? ( +
+ {this.props.password} +
+ ) : ( +
+ {this.props.t('passwordSetRemotely')} +
+ ) } + {this._renderPasswordField()} +
+ ; + } + /** * 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 { */ _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 { return (
-
); - } else if (this.props.locked === LOCKED_LOCALLY) { - return ( -
- { this.props.password } -
- ); - } else if (this.props.locked) { - return ( -
- { this.props.t('passwordSetRemotely') } -
- ); } - - return ( -
- { this.props.t('info.noPassword') } -
- ); } - _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 { * @private * @returns {void} */ - _onKeyPress(event) { + _onKeyPress(event: React.KeyboardEvent) { if (event.key === 'Enter') { event.preventDefault(); event.stopPropagation(); diff --git a/react/features/security/components/security-dialog/web/PasswordSection.js b/react/features/security/components/security-dialog/web/PasswordSection.tsx similarity index 90% rename from react/features/security/components/security-dialog/web/PasswordSection.js rename to react/features/security/components/security-dialog/web/PasswordSection.tsx index 56d1add1c8..422961f97d 100644 --- a/react/features/security/components/security-dialog/web/PasswordSection.js +++ b/react/features/security/components/security-dialog/web/PasswordSection.tsx @@ -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, + buttonsWithNotifyClick: Array, /** * 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, - - /** - * Invoked to obtain translated strings. - */ - t: Function -}; + setPasswordEditEnabled: 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(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(); diff --git a/react/features/security/components/security-dialog/web/SecurityDialog.js b/react/features/security/components/security-dialog/web/SecurityDialog.tsx similarity index 91% rename from react/features/security/components/security-dialog/web/SecurityDialog.js rename to react/features/security/components/security-dialog/web/SecurityDialog.tsx index 3c0d5aeac4..a2886b4a9c 100644 --- a/react/features/security/components/security-dialog/web/SecurityDialog.js +++ b/react/features/security/components/security-dialog/web/SecurityDialog.tsx @@ -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, + _buttonsWithNotifyClick: Array, /** * 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, diff --git a/react/features/toolbox/constants.js b/react/features/toolbox/constants.ts similarity index 100% rename from react/features/toolbox/constants.js rename to react/features/toolbox/constants.ts