index.tsx 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. 'use client'
  2. import { useRef, useState } from 'react'
  3. import { t } from 'i18next'
  4. import { useParams, usePathname } from 'next/navigation'
  5. import s from './style.module.css'
  6. import Tooltip from '@/app/components/base/tooltip'
  7. import { randomString } from '@/utils'
  8. import Loading from '@/app/components/base/loading'
  9. import { AudioPlayerManager } from '@/app/components/base/audio-btn/audio.player.manager'
  10. type AudioBtnProps = {
  11. id?: string
  12. voice?: string
  13. value?: string
  14. className?: string
  15. isAudition?: boolean
  16. noCache?: boolean
  17. }
  18. type AudioState = 'initial' | 'loading' | 'playing' | 'paused' | 'ended'
  19. const AudioBtn = ({
  20. id,
  21. voice,
  22. value,
  23. className,
  24. isAudition,
  25. }: AudioBtnProps) => {
  26. const [audioState, setAudioState] = useState<AudioState>('initial')
  27. const selector = useRef(`play-tooltip-${randomString(4)}`)
  28. const params = useParams()
  29. const pathname = usePathname()
  30. const audio_finished_call = (event: string): any => {
  31. switch (event) {
  32. case 'ended':
  33. setAudioState('ended')
  34. break
  35. case 'paused':
  36. setAudioState('ended')
  37. break
  38. case 'loaded':
  39. setAudioState('loading')
  40. break
  41. case 'play':
  42. setAudioState('playing')
  43. break
  44. case 'error':
  45. setAudioState('ended')
  46. break
  47. }
  48. }
  49. let url = ''
  50. let isPublic = false
  51. if (params.token) {
  52. url = '/text-to-audio'
  53. isPublic = true
  54. }
  55. else if (params.appId) {
  56. if (pathname.search('explore/installed') > -1)
  57. url = `/installed-apps/${params.appId}/text-to-audio`
  58. else
  59. url = `/apps/${params.appId}/text-to-audio`
  60. }
  61. const handleToggle = async () => {
  62. if (audioState === 'playing' || audioState === 'loading') {
  63. setTimeout(() => setAudioState('paused'), 1)
  64. AudioPlayerManager.getInstance().getAudioPlayer(url, isPublic, id, value, voice, audio_finished_call).pauseAudio()
  65. }
  66. else {
  67. setTimeout(() => setAudioState('loading'), 1)
  68. AudioPlayerManager.getInstance().getAudioPlayer(url, isPublic, id, value, voice, audio_finished_call).playAudio()
  69. }
  70. }
  71. const tooltipContent = {
  72. initial: t('appApi.play'),
  73. ended: t('appApi.play'),
  74. paused: t('appApi.pause'),
  75. playing: t('appApi.playing'),
  76. loading: t('appApi.loading'),
  77. }[audioState]
  78. return (
  79. <div className={`inline-flex items-center justify-center ${(audioState === 'loading' || audioState === 'playing') ? 'mr-1' : className}`}>
  80. <Tooltip
  81. popupContent={tooltipContent}
  82. >
  83. <button
  84. disabled={audioState === 'loading'}
  85. className={`box-border w-6 h-6 flex items-center justify-center cursor-pointer ${isAudition ? 'p-0.5' : 'p-0 rounded-md bg-white'}`}
  86. onClick={handleToggle}
  87. >
  88. {audioState === 'loading'
  89. ? (
  90. <div className='w-full h-full rounded-md flex items-center justify-center'>
  91. <Loading />
  92. </div>
  93. )
  94. : (
  95. <div className={`w-full h-full rounded-md flex items-center justify-center ${!isAudition ? 'hover:bg-gray-50' : 'hover:bg-gray-50'}`}>
  96. <div className={`w-4 h-4 ${(audioState === 'playing') ? s.pauseIcon : s.playIcon}`}></div>
  97. </div>
  98. )}
  99. </button>
  100. </Tooltip>
  101. </div>
  102. )
  103. }
  104. export default AudioBtn