import React, {useCallback, useState} from 'react' import {Keyboard, StyleProp, View, ViewStyle} from 'react-native' import RNPickerSelect from 'react-native-picker-select' import {msg, Trans} from '@lingui/macro' import {useLingui} from '@lingui/react' import {MAX_ALT_TEXT} from '#/lib/constants' import {useEnforceMaxGraphemeCount} from '#/lib/strings/helpers' import {LANGUAGES} from '#/locale/languages' import {isAndroid, isWeb} from '#/platform/detection' import {useLanguagePrefs} from '#/state/preferences' import {atoms as a, useTheme, web} from '#/alf' import {Button, ButtonIcon, ButtonText} from '#/components/Button' import * as Dialog from '#/components/Dialog' import * as TextField from '#/components/forms/TextField' import {CC_Stroke2_Corner0_Rounded as CCIcon} from '#/components/icons/CC' import {PageText_Stroke2_Corner0_Rounded as PageTextIcon} from '#/components/icons/PageText' import {TimesLarge_Stroke2_Corner0_Rounded as X} from '#/components/icons/Times' import {Warning_Stroke2_Corner0_Rounded as WarningIcon} from '#/components/icons/Warning' import {Text} from '#/components/Typography' import {SubtitleFilePicker} from './SubtitleFilePicker' interface Props { defaultAltText: string captions: {lang: string; file: File}[] saveAltText: (altText: string) => void setCaptions: React.Dispatch< React.SetStateAction<{lang: string; file: File}[]> > } export function SubtitleDialogBtn(props: Props) { const control = Dialog.useDialogControl() const {_} = useLingui() return ( ) } function SubtitleDialogInner({ defaultAltText, saveAltText, captions, setCaptions, }: Props) { const control = Dialog.useDialogContext() const {_} = useLingui() const t = useTheme() const enforceLen = useEnforceMaxGraphemeCount() const {primaryLanguage} = useLanguagePrefs() const [altText, setAltText] = useState(defaultAltText) const handleSelectFile = useCallback( (file: File) => { setCaptions(subs => [ ...subs, { lang: subs.some(s => s.lang === primaryLanguage) ? '' : primaryLanguage, file, }, ]) }, [setCaptions, primaryLanguage], ) const subtitleMissingLanguage = captions.some(sub => sub.lang === '') return ( Alt text setAltText(enforceLen(evt, MAX_ALT_TEXT))} maxLength={MAX_ALT_TEXT * 10} multiline style={{maxHeight: 300}} numberOfLines={3} onKeyPress={({nativeEvent}) => { if (nativeEvent.key === 'Escape') { control.close() } }} /> {isWeb && ( <> Captions (.vtt) = 4} /> {captions.map((subtitle, i) => ( langCode(lang) === subtitle.lang || !captions.some(s => s.lang === langCode(lang)), )} style={[i % 2 === 0 && t.atoms.bg_contrast_25]} /> ))} {subtitleMissingLanguage && ( Ensure you have selected a language for each subtitle file. )} )} ) } function SubtitleFileRow({ language, file, otherLanguages, setCaptions, style, }: { language: string file: File otherLanguages: {code2: string; code3: string; name: string}[] setCaptions: React.Dispatch< React.SetStateAction<{lang: string; file: File}[]> > style: StyleProp }) { const {_} = useLingui() const t = useTheme() const handleValueChange = useCallback( (lang: string) => { if (lang) { setCaptions(subs => subs.map(s => (s.lang === language ? {lang, file: s.file} : s)), ) } }, [setCaptions, language], ) return ( {language === '' ? ( ) : ( )} {file.name} ({ label: `${lang.name} (${langCode(lang)})`, value: langCode(lang), }))} style={{viewContainer: {maxWidth: 200, flex: 1}}} /> ) } function langCode(lang: {code2: string; code3: string}) { return lang.code2 || lang.code3 }