dify/web/app/components/base/audio-btn/index.tsx
Stephen Zhou a84c2d36a3
style: format with vp fmt (#38803)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-07-12 15:57:46 +00:00

115 lines
3.7 KiB
TypeScript

'use client'
import { Tooltip, TooltipContent, TooltipTrigger } from '@langgenius/dify-ui/tooltip'
import { t } from 'i18next'
import { useState } from 'react'
import { AudioPlayerManager } from '@/app/components/base/audio-btn/audio.player.manager'
import Loading from '@/app/components/base/loading'
import { isInstalledAppPath } from '@/app/components/explore/installed-app/routes'
import { useParams, usePathname } from '@/next/navigation'
import s from './style.module.css'
type AudioBtnProps = {
id?: string
voice?: string
value?: string
className?: string
isAudition?: boolean
noCache?: boolean
}
type AudioState = 'initial' | 'loading' | 'playing' | 'paused' | 'ended'
const AudioBtn = ({ id, voice, value, className, isAudition }: AudioBtnProps) => {
const [audioState, setAudioState] = useState<AudioState>('initial')
const params = useParams()
const pathname = usePathname()
const audio_finished_call = (event: string): void => {
switch (event) {
case 'ended':
setAudioState('ended')
break
case 'paused':
setAudioState('ended')
break
case 'loaded':
setAudioState('loading')
break
case 'play':
setAudioState('playing')
break
case 'error':
setAudioState('ended')
break
}
}
let url = ''
let isPublic = false
if (params.token) {
url = '/text-to-audio'
isPublic = true
} else if (params.appId) {
if (isInstalledAppPath(pathname)) url = `/installed-apps/${params.appId}/text-to-audio`
else url = `/apps/${params.appId}/text-to-audio`
}
const handleToggle = async () => {
if (audioState === 'playing' || audioState === 'loading') {
setTimeout(() => setAudioState('paused'), 1)
AudioPlayerManager.getInstance()
.getAudioPlayer(url, isPublic, id, value, voice, audio_finished_call)
.pauseAudio()
} else {
setTimeout(() => setAudioState('loading'), 1)
AudioPlayerManager.getInstance()
.getAudioPlayer(url, isPublic, id, value, voice, audio_finished_call)
.playAudio()
}
}
const tooltipContent = {
initial: t(($) => $.play, { ns: 'appApi' }),
ended: t(($) => $.play, { ns: 'appApi' }),
paused: t(($) => $.pause, { ns: 'appApi' }),
playing: t(($) => $.playing, { ns: 'appApi' }),
loading: t(($) => $.loading, { ns: 'appApi' }),
}[audioState]
return (
<div
className={`inline-flex items-center justify-center ${audioState === 'loading' || audioState === 'playing' ? 'mr-1' : className}`}
>
<Tooltip>
<TooltipTrigger
render={
<span className="inline-flex">
<button
type="button"
aria-label={tooltipContent}
disabled={audioState === 'loading'}
className={`box-border flex size-6 cursor-pointer items-center justify-center border-none bg-transparent ${isAudition ? 'p-0.5' : 'rounded-md bg-white p-0'}`}
onClick={handleToggle}
>
{audioState === 'loading' ? (
<div className="flex size-full items-center justify-center rounded-md">
<Loading />
</div>
) : (
<div className="flex size-full items-center justify-center rounded-md hover:bg-gray-50">
<div
className={`size-4 ${audioState === 'playing' ? s.pauseIcon : s.playIcon}`}
></div>
</div>
)}
</button>
</span>
}
/>
<TooltipContent>{tooltipContent}</TooltipContent>
</Tooltip>
</div>
)
}
export default AudioBtn