/* * Copyright 2025 coze-dev Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import React, { useEffect, useState } from 'react'; import { useRequest } from 'ahooks'; import { I18n } from '@coze-arch/i18n'; import { IconCozPauseFill, IconCozPlus, IconCozTrashCan, IconCozVolume, } from '@coze-arch/coze-design/icons'; import { Avatar, Button, IconButton } from '@coze-arch/coze-design'; import { useSpaceStore } from '@coze-arch/bot-studio-store'; import { type VoiceDetail } from '@coze-arch/bot-api/multimedia_api'; import { MultimediaApi } from '@coze-arch/bot-api'; import { useSelectVoiceModal, useAudioPlayer, } from '@coze-workflow/resources-adapter'; interface CardProps { voice: VoiceDetail | null; onDelete?: () => void; disabled?: boolean; } const VoiceCard = ({ voice, onDelete, disabled }: CardProps) => { const { isPlaying, togglePlayPause } = useAudioPlayer(voice?.preview_audio); if (!voice) { return null; } return (
{voice.voice_name} {isPlaying ? ( } /> ) : ( } /> )}
} />
); }; const useVoiceSource = (id?: string) => { const [voice, setVoice] = useState(null); const { loading } = useRequest( () => { if (!id) { return Promise.resolve(null).then(() => { setVoice(null); return null; }); } return MultimediaApi.APIMGetVoice({ voice_ids: [id], }) .then(data => { const v = data?.data?.voices?.[0]; setVoice(data?.data?.voices?.[0]); return v; }) .catch(() => { setVoice(null); return null; }); }, { refreshDeps: [id], }, ); return { voice, setVoice, loading, }; }; interface Props { value?: string; onChange?: (v?: string) => void; disabled?: boolean; } const VoiceSelect: React.FC = props => { const { value, onChange, disabled } = props; const [voiceId, setVoiceId] = useState(value); const spaceId = useSpaceStore(store => store.space.id) || ''; const { voice, setVoice } = useVoiceSource(voiceId); useEffect(() => { setVoiceId(value); }, [value]); const { open: openSelectVoiceModal, modal: selectVoiceModal } = useSelectVoiceModal({ spaceId, onSelectVoice: v => { setVoice(v); onChange?.(v.voice_id); }, }); return ( <> {!voice?.voice_id ? ( ) : ( { setVoice(null); onChange?.(undefined); }} /> )} {selectVoiceModal} ); }; export { VoiceSelect };