You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ConnectionStatus.js 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. // @flow
  2. import React, { useCallback, useState } from 'react';
  3. import { translate } from '../../../i18n';
  4. import { Icon, IconArrowDownSmall, IconWifi1Bar, IconWifi2Bars, IconWifi3Bars } from '../../../icons';
  5. import { connect } from '../../../redux';
  6. import { CONNECTION_TYPE } from '../../constants';
  7. import { getConnectionData } from '../../functions';
  8. type Props = {
  9. /**
  10. * List of strings with details about the connection.
  11. */
  12. connectionDetails: string[],
  13. /**
  14. * The type of the connection. Can be: 'none', 'poor', 'nonOptimal' or 'good'.
  15. */
  16. connectionType: string,
  17. /**
  18. * Used for translation.
  19. */
  20. t: Function
  21. }
  22. const CONNECTION_TYPE_MAP = {
  23. [CONNECTION_TYPE.POOR]: {
  24. connectionClass: 'con-status--poor',
  25. icon: IconWifi1Bar,
  26. connectionText: 'prejoin.connection.poor'
  27. },
  28. [CONNECTION_TYPE.NON_OPTIMAL]: {
  29. connectionClass: 'con-status--non-optimal',
  30. icon: IconWifi2Bars,
  31. connectionText: 'prejoin.connection.nonOptimal'
  32. },
  33. [CONNECTION_TYPE.GOOD]: {
  34. connectionClass: 'con-status--good',
  35. icon: IconWifi3Bars,
  36. connectionText: 'prejoin.connection.good'
  37. }
  38. };
  39. /**
  40. * Component displaying information related to the connection & audio/video quality.
  41. *
  42. * @param {Props} props - The props of the component.
  43. * @returns {ReactElement}
  44. */
  45. function ConnectionStatus({ connectionDetails, t, connectionType }: Props) {
  46. if (connectionType === CONNECTION_TYPE.NONE) {
  47. return null;
  48. }
  49. const { connectionClass, icon, connectionText } = CONNECTION_TYPE_MAP[connectionType];
  50. const [ showDetails, toggleDetails ] = useState(false);
  51. const arrowClassName = showDetails
  52. ? 'con-status-arrow con-status-arrow--up'
  53. : 'con-status-arrow';
  54. const detailsText = connectionDetails.map(t).join(' ');
  55. const detailsClassName = showDetails
  56. ? 'con-status-details-visible'
  57. : 'con-status-details-hidden';
  58. const onToggleDetails = useCallback(e => {
  59. e.preventDefault();
  60. toggleDetails(!showDetails);
  61. }, [ showDetails, toggleDetails ]);
  62. const onKeyPressToggleDetails = useCallback(e => {
  63. if (toggleDetails && (e.key === ' ' || e.key === 'Enter')) {
  64. e.preventDefault();
  65. toggleDetails(!showDetails);
  66. }
  67. }, [ showDetails, toggleDetails ]);
  68. return (
  69. <div className = 'con-status'>
  70. <div className = 'con-status-container'>
  71. <div
  72. aria-level = { 1 }
  73. className = 'con-status-header'
  74. role = 'heading'>
  75. <div className = { `con-status-circle ${connectionClass}` }>
  76. <Icon
  77. size = { 16 }
  78. src = { icon } />
  79. </div>
  80. <span
  81. aria-hidden = { !showDetails }
  82. className = 'con-status-text'
  83. id = 'connection-status-description'>{t(connectionText)}</span>
  84. <Icon
  85. ariaDescribedBy = 'connection-status-description'
  86. ariaPressed = { showDetails }
  87. className = { arrowClassName }
  88. onClick = { onToggleDetails }
  89. onKeyPress = { onKeyPressToggleDetails }
  90. role = 'button'
  91. size = { 24 }
  92. src = { IconArrowDownSmall }
  93. tabIndex = { 0 } />
  94. </div>
  95. <div
  96. aria-level = '2'
  97. className = { `con-status-details ${detailsClassName}` }
  98. role = 'heading'>
  99. {detailsText}</div>
  100. </div>
  101. </div>
  102. );
  103. }
  104. /**
  105. * Maps (parts of) the redux state to the React {@code Component} props.
  106. *
  107. * @param {Object} state - The redux state.
  108. * @returns {Object}
  109. */
  110. function mapStateToProps(state): Object {
  111. const { connectionDetails, connectionType } = getConnectionData(state);
  112. return {
  113. connectionDetails,
  114. connectionType
  115. };
  116. }
  117. export default translate(connect(mapStateToProps)(ConnectionStatus));