feature-bar.tsx 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. import React, { useMemo, useState } from 'react'
  2. import { useTranslation } from 'react-i18next'
  3. import { RiApps2AddLine, RiArrowRightLine, RiSparklingFill } from '@remixicon/react'
  4. import { Citations, ContentModeration, FolderUpload, LoveMessage, MessageFast, Microphone01, TextToAudio, VirtualAssistant } from '@/app/components/base/icons/src/vender/features'
  5. import Button from '@/app/components/base/button'
  6. import Tooltip from '@/app/components/base/tooltip'
  7. import VoiceSettings from '@/app/components/base/features/new-feature-panel/text-to-speech/voice-settings'
  8. import { useFeatures } from '@/app/components/base/features/hooks'
  9. import cn from '@/utils/classnames'
  10. type Props = {
  11. isChatMode?: boolean
  12. showFileUpload?: boolean
  13. disabled?: boolean
  14. onFeatureBarClick?: (state: boolean) => void
  15. }
  16. const FeatureBar = ({
  17. isChatMode = true,
  18. showFileUpload = true,
  19. disabled,
  20. onFeatureBarClick,
  21. }: Props) => {
  22. const { t } = useTranslation()
  23. const features = useFeatures(s => s.features)
  24. const [modalOpen, setModalOpen] = useState(false)
  25. const noFeatureEnabled = useMemo(() => {
  26. // completion app citation is always true but not enabled for setting
  27. const data = {
  28. ...features,
  29. citation: { enabled: isChatMode ? features.citation?.enabled : false },
  30. file: showFileUpload ? features.file! : { enabled: false },
  31. }
  32. return !Object.values(data).some(f => f.enabled)
  33. }, [features, isChatMode, showFileUpload])
  34. return (
  35. <div className='-translate-y-2 m-1 mt-0 px-2.5 py-2 pt-4 bg-util-colors-indigo-indigo-50 rounded-b-[10px] border-l border-b border-r border-components-panel-border-subtle'>
  36. {noFeatureEnabled && (
  37. <div className='flex items-end gap-1 cursor-pointer' onClick={() => onFeatureBarClick?.(true)}>
  38. <RiApps2AddLine className='w-3.5 h-3.5 text-text-accent' />
  39. <div className='text-text-accent body-xs-medium'>{t('appDebug.feature.bar.empty')}</div>
  40. <RiArrowRightLine className='w-3.5 h-3.5 text-text-accent' />
  41. </div>
  42. )}
  43. {!noFeatureEnabled && (
  44. <div className='flex items-center gap-2'>
  45. <div className='shrink-0 flex items-center gap-0.5'>
  46. {!!features.moreLikeThis?.enabled && (
  47. <Tooltip
  48. popupContent={t('appDebug.feature.moreLikeThis.title')}
  49. >
  50. <div className='shrink-0 p-1 rounded-lg border-[0.5px] border-divider-subtle shadow-xs bg-util-colors-blue-light-blue-light-500'>
  51. <RiSparklingFill className='w-3.5 h-3.5 text-text-primary-on-surface' />
  52. </div>
  53. </Tooltip>
  54. )}
  55. {!!features.opening?.enabled && (
  56. <Tooltip
  57. popupContent={t('appDebug.feature.conversationOpener.title')}
  58. >
  59. <div className='shrink-0 p-1 rounded-lg border-[0.5px] border-divider-subtle shadow-xs bg-util-colors-blue-light-blue-light-500'>
  60. <LoveMessage className='w-3.5 h-3.5 text-text-primary-on-surface' />
  61. </div>
  62. </Tooltip>
  63. )}
  64. {!!features.moderation?.enabled && (
  65. <Tooltip
  66. popupContent={t('appDebug.feature.moderation.title')}
  67. >
  68. <div className='shrink-0 p-1 rounded-lg border-[0.5px] border-divider-subtle shadow-xs bg-text-success'>
  69. <ContentModeration className='w-3.5 h-3.5 text-text-primary-on-surface' />
  70. </div>
  71. </Tooltip>
  72. )}
  73. {!!features.speech2text?.enabled && (
  74. <Tooltip
  75. popupContent={t('appDebug.feature.speechToText.title')}
  76. >
  77. <div className='shrink-0 p-1 rounded-lg border-[0.5px] border-divider-subtle shadow-xs bg-util-colors-violet-violet-600'>
  78. <Microphone01 className='w-3.5 h-3.5 text-text-primary-on-surface' />
  79. </div>
  80. </Tooltip>
  81. )}
  82. {!!features.text2speech?.enabled && (
  83. <VoiceSettings placementLeft={false} open={modalOpen && !disabled} onOpen={setModalOpen}>
  84. <Tooltip
  85. popupContent={t('appDebug.feature.textToSpeech.title')}
  86. >
  87. <div className={cn('shrink-0 p-1 rounded-lg border-[0.5px] border-divider-subtle shadow-xs bg-util-colors-violet-violet-600', !disabled && 'cursor-pointer')}>
  88. <TextToAudio className='w-3.5 h-3.5 text-text-primary-on-surface' />
  89. </div>
  90. </Tooltip>
  91. </VoiceSettings>
  92. )}
  93. {showFileUpload && !!features.file?.enabled && (
  94. <Tooltip
  95. popupContent={t('appDebug.feature.fileUpload.title')}
  96. >
  97. <div className='shrink-0 p-1 rounded-lg border-[0.5px] border-divider-subtle shadow-xs bg-util-colors-blue-blue-600'>
  98. <FolderUpload className='w-3.5 h-3.5 text-text-primary-on-surface' />
  99. </div>
  100. </Tooltip>
  101. )}
  102. {!!features.suggested?.enabled && (
  103. <Tooltip
  104. popupContent={t('appDebug.feature.suggestedQuestionsAfterAnswer.title')}
  105. >
  106. <div className='shrink-0 p-1 rounded-lg border-[0.5px] border-divider-subtle shadow-xs bg-util-colors-blue-light-blue-light-500'>
  107. <VirtualAssistant className='w-3.5 h-3.5 text-text-primary-on-surface' />
  108. </div>
  109. </Tooltip>
  110. )}
  111. {isChatMode && !!features.citation?.enabled && (
  112. <Tooltip
  113. popupContent={t('appDebug.feature.citation.title')}
  114. >
  115. <div className='shrink-0 p-1 rounded-lg border-[0.5px] border-divider-subtle shadow-xs bg-util-colors-warning-warning-500'>
  116. <Citations className='w-4 h-4 text-text-primary-on-surface' />
  117. </div>
  118. </Tooltip>
  119. )}
  120. {isChatMode && !!features.annotationReply?.enabled && (
  121. <Tooltip
  122. popupContent={t('appDebug.feature.annotation.title')}
  123. >
  124. <div className='shrink-0 p-1 rounded-lg border-[0.5px] border-divider-subtle shadow-xs bg-util-colors-indigo-indigo-600'>
  125. <MessageFast className='w-3.5 h-3.5 text-text-primary-on-surface' />
  126. </div>
  127. </Tooltip>
  128. )}
  129. </div>
  130. <div className='grow text-text-tertiary body-xs-regular'>{t('appDebug.feature.bar.enableText')}</div>
  131. <Button className='shrink-0' variant='ghost-accent' size='small' onClick={() => onFeatureBarClick?.(true)}>
  132. <div className='mx-1'>{t('appDebug.feature.bar.manage')}</div>
  133. <RiArrowRightLine className='w-3.5 h-3.5 text-text-accent' />
  134. </Button>
  135. </div>
  136. )}
  137. </div>
  138. )
  139. }
  140. export default FeatureBar