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.

AbstractLanguageSelectorDialog.tsx 3.1KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. import React, { ComponentType, useCallback, useEffect, useState } from 'react';
  2. import { useTranslation } from 'react-i18next';
  3. import { useDispatch, useSelector } from 'react-redux';
  4. import { IReduxState, IStore } from '../../app/types';
  5. import {
  6. TRANSLATION_LANGUAGES,
  7. TRANSLATION_LANGUAGES_HEAD
  8. } from '../../base/i18n/i18next';
  9. import { setRequestingSubtitles, updateTranslationLanguage } from '../actions.any';
  10. export interface IAbstractLanguageSelectorDialogProps {
  11. dispatch: IStore['dispatch'];
  12. language: string;
  13. listItems: Array<any>;
  14. onLanguageSelected: (e: string) => void;
  15. subtitles: string;
  16. t: Function;
  17. }
  18. /**
  19. * Higher Order Component taking in a concrete LanguageSelector component and
  20. * augmenting it with state/behavior common to both web and native implementations.
  21. *
  22. * @param {React.Component} Component - The concrete component.
  23. * @returns {React.Component}
  24. */
  25. const AbstractLanguageSelectorDialog = (Component: ComponentType<IAbstractLanguageSelectorDialogProps>) => () => {
  26. const dispatch = useDispatch();
  27. const { t } = useTranslation();
  28. const off = 'transcribing.subtitlesOff';
  29. const [ subtitles, setSubtiles ] = useState(off);
  30. const language = useSelector((state: IReduxState) => state['features/subtitles']._language);
  31. const transcription = useSelector((state: IReduxState) => state['features/base/config'].transcription);
  32. const translationLanguagesHead = transcription?.translationLanguagesHead ?? TRANSLATION_LANGUAGES_HEAD;
  33. const languagesHead = translationLanguagesHead?.map((lang: string) => `translation-languages:${lang}`);
  34. // The off and the head languages are always on the top of the list. But once you are selecting
  35. // a language from the translationLanguages, that language is moved under the fixedItems list,
  36. // until a new languages is selected. FixedItems keep their positions.
  37. const fixedItems = [ off, ...languagesHead ];
  38. const translationLanguages = transcription?.translationLanguages ?? TRANSLATION_LANGUAGES;
  39. const languages = translationLanguages
  40. .map((lang: string) => `translation-languages:${lang}`)
  41. .filter((lang: string) => !(lang === subtitles || languagesHead?.includes(lang)));
  42. const listItems = (fixedItems?.includes(subtitles)
  43. ? [ ...fixedItems, ...languages ]
  44. : [ ...fixedItems, subtitles, ...languages ])
  45. .map((lang, index) => {
  46. return {
  47. id: lang + index,
  48. lang,
  49. selected: lang === subtitles
  50. };
  51. });
  52. useEffect(() => {
  53. language ? setSubtiles(language) : setSubtiles(off);
  54. }, []);
  55. const onLanguageSelected = useCallback((e: string) => {
  56. setSubtiles(e);
  57. dispatch(updateTranslationLanguage(e));
  58. dispatch(setRequestingSubtitles(e !== off));
  59. }, [ language ]);
  60. return (
  61. <Component
  62. dispatch = { dispatch }
  63. language = { language }
  64. listItems = { listItems }
  65. onLanguageSelected = { onLanguageSelected }
  66. subtitles = { subtitles }
  67. t = { t } />
  68. );
  69. };
  70. export default AbstractLanguageSelectorDialog;