"Fossies" - the Fresh Open Source Software Archive

Member "jitsi-meet-7319/react/features/security/components/security-dialog/web/PasswordSection.tsx" (6 Jun 2023, 11467 Bytes) of package /linux/misc/jitsi-meet-7319.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) TSX (TypeScript with React) source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "PasswordSection.tsx": jitsi-meet_8319_vs_jitsi-meet_8615.

    1 /* eslint-disable react/jsx-no-bind */
    2 import React, { useRef, useState } from 'react';
    3 import { WithTranslation } from 'react-i18next';
    4 
    5 import { translate } from '../../../../base/i18n/functions';
    6 import { copyText } from '../../../../base/util/copyText.web';
    7 import { LOCKED_LOCALLY } from '../../../../room-lock/constants';
    8 import { NOTIFY_CLICK_MODE } from '../../../../toolbox/constants';
    9 
   10 import PasswordForm from './PasswordForm';
   11 import { INotifyClick } from './SecurityDialog';
   12 
   13 const DIGITS_ONLY = /^\d+$/;
   14 const KEY = 'add-passcode';
   15 
   16 interface IProps extends WithTranslation {
   17 
   18     /**
   19      * Toolbar buttons which have their click exposed through the API.
   20      */
   21     buttonsWithNotifyClick: Array<string | INotifyClick>;
   22 
   23     /**
   24      * Whether or not the current user can modify the current password.
   25      */
   26     canEditPassword: boolean;
   27 
   28     /**
   29      * The JitsiConference for which to display a lock state and change the
   30      * password.
   31      */
   32     conference: any;
   33 
   34     /**
   35      * The value for how the conference is locked (or undefined if not locked)
   36      * as defined by room-lock constants.
   37      */
   38     locked?: string;
   39 
   40     /**
   41      * The current known password for the JitsiConference.
   42      */
   43     password?: string;
   44 
   45     /**
   46      * Whether or not to show the password in editing mode.
   47      */
   48     passwordEditEnabled: boolean;
   49 
   50     /**
   51      * The number of digits to be used in the password.
   52      */
   53     passwordNumberOfDigits?: number;
   54 
   55     /**
   56      * Action that sets the conference password.
   57      */
   58     setPassword: Function;
   59 
   60     /**
   61      * Method that sets whether the password editing is enabled or not.
   62      */
   63     setPasswordEditEnabled: Function;
   64 }
   65 
   66 /**
   67  * Component that handles the password manipulation from the invite dialog.
   68  *
   69  * @returns {React$Element<any>}
   70  */
   71 function PasswordSection({
   72     buttonsWithNotifyClick,
   73     canEditPassword,
   74     conference,
   75     locked,
   76     password,
   77     passwordEditEnabled,
   78     passwordNumberOfDigits,
   79     setPassword,
   80     setPasswordEditEnabled,
   81     t }: IProps) {
   82 
   83     const formRef = useRef<HTMLDivElement>(null);
   84     const [ passwordVisible, setPasswordVisible ] = useState(false);
   85 
   86     /**
   87      * Callback invoked to set a password on the current JitsiConference.
   88      *
   89      * @param {string} enteredPassword - The new password to be used to lock the
   90      * current JitsiConference.
   91      * @private
   92      * @returns {void}
   93      */
   94     function onPasswordSubmit(enteredPassword: string) {
   95         if (enteredPassword && passwordNumberOfDigits && !DIGITS_ONLY.test(enteredPassword)) {
   96             // Don't set the password.
   97             return;
   98         }
   99         setPassword(conference, conference.lock, enteredPassword);
  100     }
  101 
  102     /**
  103      * Toggles whether or not the password should currently be shown as being
  104      * edited locally.
  105      *
  106      * @private
  107      * @returns {void}
  108      */
  109     function onTogglePasswordEditState() {
  110         if (typeof APP === 'undefined' || !buttonsWithNotifyClick?.length) {
  111             setPasswordEditEnabled(!passwordEditEnabled);
  112 
  113             return;
  114         }
  115 
  116         let notifyMode;
  117         const notify = buttonsWithNotifyClick.find(
  118             (btn: string | INotifyClick) =>
  119                 (typeof btn === 'string' && btn === KEY)
  120                 || (typeof btn === 'object' && btn.key === KEY)
  121         );
  122 
  123         if (notify) {
  124             notifyMode = typeof notify === 'string' || notify.preventExecution
  125                 ? NOTIFY_CLICK_MODE.PREVENT_AND_NOTIFY
  126                 : NOTIFY_CLICK_MODE.ONLY_NOTIFY;
  127             APP.API.notifyToolbarButtonClicked(
  128                 KEY, notifyMode === NOTIFY_CLICK_MODE.PREVENT_AND_NOTIFY
  129             );
  130         }
  131 
  132         if (notifyMode === NOTIFY_CLICK_MODE.ONLY_NOTIFY) {
  133             setPasswordEditEnabled(!passwordEditEnabled);
  134         }
  135     }
  136 
  137     /**
  138      * Method to remotely submit the password from outside of the password form.
  139      *
  140      * @returns {void}
  141      */
  142     function onPasswordSave() {
  143         if (formRef.current) {
  144             // @ts-ignore
  145             const { value } = formRef.current.querySelector('div > input');
  146 
  147             if (value) {
  148                 onPasswordSubmit(value);
  149             }
  150         }
  151     }
  152 
  153     /**
  154      * Callback invoked to unlock the current JitsiConference.
  155      *
  156      * @returns {void}
  157      */
  158     function onPasswordRemove() {
  159         onPasswordSubmit('');
  160     }
  161 
  162     /**
  163      * Copies the password to the clipboard.
  164      *
  165      * @returns {void}
  166      */
  167     function onPasswordCopy() {
  168         copyText(password ?? '');
  169     }
  170 
  171     /**
  172      * Toggles whether or not the password should currently be shown as being
  173      * edited locally.
  174      *
  175      * @param {Object} e - The key event to handle.
  176      *
  177      * @private
  178      * @returns {void}
  179      */
  180     function onTogglePasswordEditStateKeyPressHandler(e: React.KeyboardEvent) {
  181         if (e.key === ' ' || e.key === 'Enter') {
  182             e.preventDefault();
  183             onTogglePasswordEditState();
  184         }
  185     }
  186 
  187     /**
  188      * Method to remotely submit the password from outside of the password form.
  189      *
  190      * @param {Object} e - The key event to handle.
  191      *
  192      * @private
  193      * @returns {void}
  194      */
  195     function onPasswordSaveKeyPressHandler(e: React.KeyboardEvent) {
  196         if (e.key === ' ' || e.key === 'Enter') {
  197             e.preventDefault();
  198             onPasswordSave();
  199         }
  200     }
  201 
  202     /**
  203      * Callback invoked to unlock the current JitsiConference.
  204      *
  205      * @param {Object} e - The key event to handle.
  206      *
  207      * @private
  208      * @returns {void}
  209      */
  210     function onPasswordRemoveKeyPressHandler(e: React.KeyboardEvent) {
  211         if (e.key === ' ' || e.key === 'Enter') {
  212             e.preventDefault();
  213             onPasswordRemove();
  214         }
  215     }
  216 
  217     /**
  218      * Copies the password to the clipboard.
  219      *
  220      * @param {Object} e - The key event to handle.
  221      *
  222      * @private
  223      * @returns {void}
  224      */
  225     function onPasswordCopyKeyPressHandler(e: React.KeyboardEvent) {
  226         if (e.key === ' ' || e.key === 'Enter') {
  227             e.preventDefault();
  228             onPasswordCopy();
  229         }
  230     }
  231 
  232     /**
  233      * Callback invoked to show the current password.
  234      *
  235      * @returns {void}
  236      */
  237     function onPasswordShow() {
  238         setPasswordVisible(true);
  239     }
  240 
  241     /**
  242      * Callback invoked to show the current password.
  243      *
  244      * @param {Object} e - The key event to handle.
  245      *
  246      * @returns {void}
  247      */
  248     function onPasswordShowKeyPressHandler(e: React.KeyboardEvent) {
  249         if (e.key === ' ' || e.key === 'Enter') {
  250             e.preventDefault();
  251             setPasswordVisible(true);
  252         }
  253     }
  254 
  255     /**
  256      * Callback invoked to hide the current password.
  257      *
  258      * @returns {void}
  259      */
  260     function onPasswordHide() {
  261         setPasswordVisible(false);
  262     }
  263 
  264     /**
  265      * Callback invoked to hide the current password.
  266      *
  267      * @param {Object} e - The key event to handle.
  268      *
  269      * @returns {void}
  270      */
  271     function onPasswordHideKeyPressHandler(e: React.KeyboardEvent) {
  272         if (e.key === ' ' || e.key === 'Enter') {
  273             e.preventDefault();
  274             setPasswordVisible(false);
  275         }
  276     }
  277 
  278     /**
  279      * Method that renders the password action(s) based on the current
  280      * locked-status of the conference.
  281      *
  282      * @returns {React$Element<any>}
  283      */
  284     function renderPasswordActions() {
  285         if (!canEditPassword) {
  286             return null;
  287         }
  288 
  289         if (passwordEditEnabled) {
  290             return (
  291                 <>
  292                     <a
  293                         aria-label = { t('dialog.Cancel') }
  294                         onClick = { onTogglePasswordEditState }
  295                         onKeyPress = { onTogglePasswordEditStateKeyPressHandler }
  296                         role = 'button'
  297                         tabIndex = { 0 }>{ t('dialog.Cancel') }</a>
  298                     <a
  299                         aria-label = { t('dialog.add') }
  300                         onClick = { onPasswordSave }
  301                         onKeyPress = { onPasswordSaveKeyPressHandler }
  302                         role = 'button'
  303                         tabIndex = { 0 }>{ t('dialog.add') }</a>
  304                 </>
  305             );
  306         }
  307 
  308         if (locked) {
  309             return (
  310                 <>
  311                     <a
  312                         aria-label = { t('dialog.Remove') }
  313                         className = 'remove-password'
  314                         onClick = { onPasswordRemove }
  315                         onKeyPress = { onPasswordRemoveKeyPressHandler }
  316                         role = 'button'
  317                         tabIndex = { 0 }>{ t('dialog.Remove') }</a>
  318                     {
  319 
  320                         // There are cases like lobby and grant moderator when password is not available
  321                         password ? <>
  322                             <a
  323                                 aria-label = { t('dialog.copy') }
  324                                 className = 'copy-password'
  325                                 onClick = { onPasswordCopy }
  326                                 onKeyPress = { onPasswordCopyKeyPressHandler }
  327                                 role = 'button'
  328                                 tabIndex = { 0 }>{ t('dialog.copy') }</a>
  329                         </> : null
  330                     }
  331                     {locked === LOCKED_LOCALLY && (
  332                         <a
  333                             aria-label = { t(passwordVisible ? 'dialog.hide' : 'dialog.show') }
  334                             onClick = { passwordVisible ? onPasswordHide : onPasswordShow }
  335                             onKeyPress = { passwordVisible
  336                                 ? onPasswordHideKeyPressHandler
  337                                 : onPasswordShowKeyPressHandler
  338                             }
  339                             role = 'button'
  340                             tabIndex = { 0 }>{t(passwordVisible ? 'dialog.hide' : 'dialog.show')}</a>
  341                     )}
  342                 </>
  343             );
  344         }
  345 
  346         return (
  347             <a
  348                 aria-label = { t('info.addPassword') }
  349                 className = 'add-password'
  350                 onClick = { onTogglePasswordEditState }
  351                 onKeyPress = { onTogglePasswordEditStateKeyPressHandler }
  352                 role = 'button'
  353                 tabIndex = { 0 }>{ t('info.addPassword') }</a>
  354         );
  355     }
  356 
  357     return (
  358         <div className = 'security-dialog password-section'>
  359             <p className = 'description'>
  360                 { t(canEditPassword ? 'security.about' : 'security.aboutReadOnly') }
  361             </p>
  362             <div className = 'security-dialog password'>
  363                 <div
  364                     className = 'info-dialog info-dialog-column info-dialog-password'
  365                     ref = { formRef }>
  366                     <PasswordForm
  367                         editEnabled = { passwordEditEnabled }
  368                         locked = { locked }
  369                         onSubmit = { onPasswordSubmit }
  370                         password = { password }
  371                         passwordNumberOfDigits = { passwordNumberOfDigits }
  372                         visible = { passwordVisible } />
  373                 </div>
  374                 <div className = 'security-dialog password-actions'>
  375                     { renderPasswordActions() }
  376                 </div>
  377             </div>
  378         </div>
  379     );
  380 }
  381 
  382 export default translate(PasswordSection);