jiti-meet/react/features/subtitles/components/LanguageSelectorDialog.web.tsx

147 lines
5.1 KiB
TypeScript

/* eslint-disable lines-around-comment */
import { Theme } from '@mui/material';
import i18next from 'i18next';
import React, { useCallback, useEffect, useState } from 'react';
import { WithTranslation } from 'react-i18next';
import { useDispatch } from 'react-redux';
import { makeStyles } from 'tss-react/mui';
import { IReduxState } from '../../app/types';
// @ts-ignore
import { TRANSLATION_LANGUAGES, TRANSLATION_LANGUAGES_HEAD } from '../../base/i18n';
import { translate, translateToHTML } from '../../base/i18n/functions';
import { connect } from '../../base/redux/functions';
import Dialog from '../../base/ui/components/web/Dialog';
// @ts-ignore
import { openSettingsDialog } from '../../settings/actions';
import { SETTINGS_TABS } from '../../settings/constants';
// @ts-ignore
import { setRequestingSubtitles, toggleLanguageSelectorDialog, updateTranslationLanguage } from '../actions';
import LanguageList from './LanguageList';
interface ILanguageSelectorDialogProps extends WithTranslation {
_language: string;
_translationLanguages: Array<string>;
_translationLanguagesHead: Array<string>;
}
const useStyles = makeStyles()((theme: Theme) => {
return {
paragraphWrapper: {
fontSize: 14,
margin: '10px 0px',
color: theme.palette.text01
},
spanWrapper: {
fontWeight: 700,
cursor: 'pointer',
color: theme.palette.link01,
'&:hover': {
backgroundColor: theme.palette.ui04,
color: theme.palette.link01Hover
}
}
};
});
/**
* Component that renders the subtitle language selector dialog.
*
* @returns {React$Element<any>}
*/
const LanguageSelectorDialog = ({
t,
_language,
_translationLanguages,
_translationLanguagesHead
}: ILanguageSelectorDialogProps) => {
const { classes: styles } = useStyles();
const dispatch = useDispatch();
const off = 'transcribing.subtitlesOff';
const [ language, setLanguage ] = useState(off);
const languagesHead = _translationLanguagesHead.map((lang: string) => `translation-languages:${lang}`);
// The off and the head languages are always on the top of the list. But once you are selecting
// a language from the translationLanguages, that language is moved under the fixedItems list,
// until a new languages is selected. FixedItems keep their positions.
const fixedItems = [ off, ...languagesHead ];
const languages = _translationLanguages
.map((lang: string) => `translation-languages:${lang}`)
.filter((lang: string) => !(lang === language || languagesHead.includes(lang)));
const listItems = (fixedItems.includes(language)
? [ ...fixedItems, ...languages ]
: [ ...fixedItems, language, ...languages ])
.map((lang, index) => {
return {
id: lang + index,
lang,
selected: lang === language
};
});
useEffect(() => {
_language ? setLanguage(_language) : setLanguage(off);
}, []);
const onLanguageSelected = useCallback((e: string) => {
setLanguage(e);
dispatch(updateTranslationLanguage(e));
dispatch(setRequestingSubtitles(e !== off));
dispatch(toggleLanguageSelectorDialog());
}, [ _language ]);
const onSourceLanguageClick = useCallback(() => {
dispatch(openSettingsDialog(SETTINGS_TABS.MORE, false));
}, []);
return (
<Dialog
cancel = {{ hidden: true }}
ok = {{ hidden: true }}
titleKey = 'transcribing.subtitles'>
<p className = { styles.paragraphWrapper } >
{
translateToHTML(t, 'transcribing.sourceLanguageDesc', {
'sourceLanguage': t(`languages:${i18next.language}`).toLowerCase()
})
}<span
className = { styles.spanWrapper }
onClick = { onSourceLanguageClick }>{t('transcribing.sourceLanguageHere')}.</span>
</p>
<LanguageList
items = { listItems }
onLanguageSelected = { onLanguageSelected }
selectedLanguage = { language } />
</Dialog>
);
};
/**
* Maps (parts of) the Redux state to the associated props for the
* {@code LanguageSelectorDialog} component.
*
* @param {Object} state - The Redux state.
* @private
* @returns {Props}
*/
function mapStateToProps(state: IReduxState) {
const { conference } = state['features/base/conference'];
const { _language } = state['features/subtitles'];
const { transcription } = state['features/base/config'];
const languages = transcription?.translationLanguages ?? TRANSLATION_LANGUAGES;
const languagesHead = transcription?.translationLanguagesHead ?? TRANSLATION_LANGUAGES_HEAD;
return {
_conference: conference,
_language,
_translationLanguages: languages,
_translationLanguagesHead: languagesHead
};
}
export default translate(connect(mapStateToProps)(LanguageSelectorDialog));