'use client' import type { OnFeaturesChange } from '@/app/components/base/features/types' import type { Item } from '@/app/components/base/select' import { Listbox, ListboxButton, ListboxOption, ListboxOptions, Transition } from '@headlessui/react' import { produce } from 'immer' import * as React from 'react' import { Fragment } from 'react' import { useTranslation } from 'react-i18next' import { replace } from 'string-ts' import AudioBtn from '@/app/components/base/audio-btn' import { useFeatures, useFeaturesStore } from '@/app/components/base/features/hooks' import Switch from '@/app/components/base/switch' import Tooltip from '@/app/components/base/tooltip' import { languages } from '@/i18n-config/language' import { usePathname } from '@/next/navigation' import { useAppVoices } from '@/service/use-apps' import { TtsAutoPlay } from '@/types/app' import { cn } from '@/utils/classnames' type VoiceParamConfigProps = { onClose: () => void onChange?: OnFeaturesChange } const VoiceParamConfig = ({ onClose, onChange, }: VoiceParamConfigProps) => { const { t } = useTranslation() const pathname = usePathname() const matched = /\/app\/([^/]+)/.exec(pathname) const appId = (matched?.length && matched[1]) ? matched[1] : '' const text2speech = useFeatures(state => state.features.text2speech) const featuresStore = useFeaturesStore() let languageItem = languages.find(item => item.value === text2speech?.language) if (languages && !languageItem) languageItem = languages[0] const localLanguagePlaceholder = languageItem?.name || t('placeholder.select', { ns: 'common' }) const language = languageItem?.value const { data: voiceItems } = useAppVoices(appId, language) let voiceItem = voiceItems?.find(item => item.value === text2speech?.voice) if (voiceItems && !voiceItem) voiceItem = voiceItems[0] const localVoicePlaceholder = voiceItem?.name || t('placeholder.select', { ns: 'common' }) const handleChange = (value: Record) => { const { features, setFeatures, } = featuresStore!.getState() const newFeatures = produce(features, (draft) => { draft.text2speech = { ...draft.text2speech, ...value, } }) setFeatures(newFeatures) if (onChange) onChange() } return ( <>
{t('voice.voiceSettings.title', { ns: 'appDebug' })}
{ if (e.key === 'Enter' || e.key === ' ') { e.preventDefault() onClose() } }} >
{t('voice.voiceSettings.language', { ns: 'appDebug' })} {t('voice.voiceSettings.resolutionTooltip', { ns: 'appDebug' }).split('\n').map(item => (
{item}
))}
)} />
{ handleChange({ language: String(value.value), }) }} >
{languageItem?.name ? t(`voice.language.${replace(languageItem?.value ?? '', '-', '')}`, languageItem?.name, { ns: 'common' as const }) : localLanguagePlaceholder} {languages.map(item => ( {({ /* active, */ selected }) => ( <> {t(`voice.language.${replace((item.value), '-', '')}`, item.name, { ns: 'common' as const })} {(selected || item.value === text2speech?.language) && ( )} )} ))}
{t('voice.voiceSettings.voice', { ns: 'appDebug' })}
{ handleChange({ voice: String(value.value), }) }} >
{voiceItem?.name ?? localVoicePlaceholder} {voiceItems?.map((item: Item) => ( {({ /* active, */ selected }) => ( <> {item.name} {(selected || item.value === text2speech?.voice) && ( )} )} ))}
{languageItem?.example && (
)}
{t('voice.voiceSettings.autoPlay', { ns: 'appDebug' })}
{ handleChange({ autoPlay: value ? TtsAutoPlay.enabled : TtsAutoPlay.disabled, }) }} />
) } export default React.memo(VoiceParamConfig)