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.

AbstractCaptions.tsx 4.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. import React, { Component, ReactElement } from 'react';
  2. import { IReduxState } from '../../app/types';
  3. /**
  4. * {@code AbstractCaptions} Properties.
  5. */
  6. export interface IAbstractCaptionsProps {
  7. /**
  8. * Whether local participant is displaying subtitles.
  9. */
  10. _displaySubtitles: boolean;
  11. /**
  12. * Whether local participant is requesting subtitles.
  13. */
  14. _requestingSubtitles: boolean;
  15. /**
  16. * Transcript texts formatted with participant's name and final content.
  17. * Mapped by id just to have the keys for convenience during the rendering
  18. * process.
  19. */
  20. _transcripts?: Map<string, string>;
  21. }
  22. /**
  23. * Abstract React {@code Component} which can display speech-to-text results
  24. * from Jigasi as subtitles.
  25. */
  26. export class AbstractCaptions<P extends IAbstractCaptionsProps> extends Component<P> {
  27. /**
  28. * Implements React's {@link Component#render()}.
  29. *
  30. * @inheritdoc
  31. * @returns {ReactElement}
  32. */
  33. render(): any {
  34. const { _displaySubtitles, _requestingSubtitles, _transcripts } = this.props;
  35. if (!_requestingSubtitles || !_displaySubtitles || !_transcripts || !_transcripts.size) {
  36. return null;
  37. }
  38. const paragraphs = [];
  39. // @ts-ignore
  40. for (const [ id, text ] of _transcripts ?? []) {
  41. paragraphs.push(this._renderParagraph(id, text));
  42. }
  43. // @ts-ignore
  44. return this._renderSubtitlesContainer(paragraphs);
  45. }
  46. /**
  47. * Renders the transcription text.
  48. *
  49. * @abstract
  50. * @param {string} _id - The ID of the transcript message from which the
  51. * {@code text} has been created.
  52. * @param {string} _text - Subtitles text formatted with the participant's
  53. * name.
  54. * @protected
  55. * @returns {ReactElement} - The React element which displays the text.
  56. */
  57. _renderParagraph(_id: string, _text: string) {
  58. return <></>;
  59. }
  60. /**
  61. * Renders the subtitles container.
  62. *
  63. * @abstract
  64. * @param {Array<ReactElement>} _el - An array of elements created
  65. * for each subtitle using the {@link _renderParagraph} method.
  66. * @protected
  67. * @returns {ReactElement} - The subtitles container.
  68. */
  69. _renderSubtitlesContainer(_el: Array<ReactElement>) {
  70. return <></>;
  71. }
  72. }
  73. /**
  74. * Formats the transcript messages into text by prefixing participant's name to
  75. * avoid duplicating the effort on platform specific component.
  76. *
  77. * @param {Object} state - The redux state.
  78. * @private
  79. * @returns {Map<string, string>} - Formatted transcript subtitles mapped by
  80. * transcript message IDs.
  81. */
  82. function _constructTranscripts(state: IReduxState): Map<string, string> {
  83. const { _transcriptMessages } = state['features/subtitles'];
  84. const transcripts = new Map();
  85. for (const [ id, transcriptMessage ] of _transcriptMessages) {
  86. if (transcriptMessage) {
  87. let text = `${transcriptMessage.participant.name}: `;
  88. if (transcriptMessage.final) {
  89. text += transcriptMessage.final;
  90. } else {
  91. const stable = transcriptMessage.stable || '';
  92. const unstable = transcriptMessage.unstable || '';
  93. text += stable + unstable;
  94. }
  95. transcripts.set(id, text);
  96. }
  97. }
  98. return transcripts;
  99. }
  100. /**
  101. * Maps the transcriptionSubtitles in the redux state to the associated props of
  102. * {@code AbstractCaptions}.
  103. *
  104. * @param {Object} state - The redux state.
  105. * @private
  106. * @returns {{
  107. * _requestingSubtitles: boolean,
  108. * _transcripts: Map<string, string>
  109. * }}
  110. */
  111. export function _abstractMapStateToProps(state: IReduxState) {
  112. const { _displaySubtitles, _requestingSubtitles } = state['features/subtitles'];
  113. const transcripts = _constructTranscripts(state);
  114. return {
  115. _displaySubtitles,
  116. _requestingSubtitles,
  117. // avoid re-renders by setting to prop new empty Map instances.
  118. _transcripts: transcripts.size === 0 ? undefined : transcripts
  119. };
  120. }