Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

DisplayName.tsx 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. import React, { useCallback, useEffect, useRef, useState } from 'react';
  2. import { useTranslation } from 'react-i18next';
  3. import { useDispatch, useSelector } from 'react-redux';
  4. import { makeStyles } from 'tss-react/mui';
  5. import { IReduxState } from '../../../app/types';
  6. import {
  7. getParticipantById,
  8. getParticipantDisplayName
  9. } from '../../../base/participants/functions';
  10. import { updateSettings } from '../../../base/settings/actions';
  11. import { withPixelLineHeight } from '../../../base/styles/functions.web';
  12. import Tooltip from '../../../base/tooltip/components/Tooltip';
  13. import { getIndicatorsTooltipPosition } from '../../../filmstrip/functions.web';
  14. import { appendSuffix } from '../../functions';
  15. /**
  16. * The type of the React {@code Component} props of {@link DisplayName}.
  17. */
  18. interface IProps {
  19. /**
  20. * Whether or not the display name should be editable on click.
  21. */
  22. allowEditing: boolean;
  23. /**
  24. * A string to append to the displayName, if provided.
  25. */
  26. displayNameSuffix: string;
  27. /**
  28. * The ID attribute to add to the component. Useful for global querying for
  29. * the component by legacy components and torture tests.
  30. */
  31. elementID: string;
  32. /**
  33. * The ID of the participant whose name is being displayed.
  34. */
  35. participantID: string;
  36. /**
  37. * The type of thumbnail.
  38. */
  39. thumbnailType?: string;
  40. }
  41. const useStyles = makeStyles()(theme => {
  42. return {
  43. displayName: {
  44. ...withPixelLineHeight(theme.typography.labelBold),
  45. color: theme.palette.text01,
  46. overflow: 'hidden',
  47. textOverflow: 'ellipsis',
  48. whiteSpace: 'nowrap'
  49. },
  50. editDisplayName: {
  51. outline: 'none',
  52. border: 'none',
  53. background: 'none',
  54. boxShadow: 'none',
  55. padding: 0,
  56. ...withPixelLineHeight(theme.typography.labelBold),
  57. color: theme.palette.text01
  58. }
  59. };
  60. });
  61. const DisplayName = ({
  62. allowEditing,
  63. displayNameSuffix,
  64. elementID,
  65. participantID,
  66. thumbnailType
  67. }: IProps) => {
  68. const { classes } = useStyles();
  69. const configuredDisplayName = useSelector((state: IReduxState) =>
  70. getParticipantById(state, participantID))?.name ?? '';
  71. const nameToDisplay = useSelector((state: IReduxState) => getParticipantDisplayName(state, participantID));
  72. const [ editDisplayNameValue, setEditDisplayNameValue ] = useState('');
  73. const [ isEditing, setIsEditing ] = useState(false);
  74. const dispatch = useDispatch();
  75. const { t } = useTranslation();
  76. const nameInputRef = useRef<HTMLInputElement | null>(null);
  77. useEffect(() => {
  78. if (isEditing && nameInputRef.current) {
  79. nameInputRef.current.select();
  80. }
  81. }, [ isEditing ]);
  82. const onClick = useCallback((e: React.MouseEvent) => {
  83. e.stopPropagation();
  84. }, []);
  85. const onChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
  86. setEditDisplayNameValue(event.target.value);
  87. }, []);
  88. const onSubmit = useCallback(() => {
  89. dispatch(updateSettings({
  90. displayName: editDisplayNameValue
  91. }));
  92. setEditDisplayNameValue('');
  93. setIsEditing(false);
  94. nameInputRef.current = null;
  95. }, [ editDisplayNameValue, nameInputRef ]);
  96. const onKeyDown = useCallback((event: React.KeyboardEvent) => {
  97. if (event.key === 'Enter') {
  98. onSubmit();
  99. }
  100. }, [ onSubmit ]);
  101. const onStartEditing = useCallback((e: React.MouseEvent) => {
  102. if (allowEditing) {
  103. e.stopPropagation();
  104. setIsEditing(true);
  105. setEditDisplayNameValue(configuredDisplayName);
  106. }
  107. }, [ allowEditing ]);
  108. if (allowEditing && isEditing) {
  109. return (
  110. <input
  111. autoFocus = { true }
  112. className = { classes.editDisplayName }
  113. id = 'editDisplayName'
  114. onBlur = { onSubmit }
  115. onChange = { onChange }
  116. onClick = { onClick }
  117. onKeyDown = { onKeyDown }
  118. placeholder = { t('defaultNickname') }
  119. ref = { nameInputRef }
  120. spellCheck = { 'false' }
  121. type = 'text'
  122. value = { editDisplayNameValue } />
  123. );
  124. }
  125. return (
  126. <Tooltip
  127. content = { appendSuffix(nameToDisplay, displayNameSuffix) }
  128. position = { getIndicatorsTooltipPosition(thumbnailType) }>
  129. <span
  130. className = { `displayname ${classes.displayName}` }
  131. id = { elementID }
  132. onClick = { onStartEditing }>
  133. {appendSuffix(nameToDisplay, displayNameSuffix)}
  134. </span>
  135. </Tooltip>
  136. );
  137. };
  138. export default DisplayName;