| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  | 'use client' | 
					
						
							| 
									
										
										
										
											2023-05-31 16:24:30 +08:00
										 |  |  | import type { FC } from 'react' | 
					
						
							|  |  |  | import React, { useEffect, useRef, useState } from 'react' | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  | import { useTranslation } from 'react-i18next' | 
					
						
							|  |  |  | import cn from 'classnames' | 
					
						
							| 
									
										
										
										
											2023-09-25 10:20:50 +08:00
										 |  |  | import { useBoolean, useClickAway } from 'ahooks' | 
					
						
							| 
									
										
										
										
											2023-05-31 16:24:30 +08:00
										 |  |  | import { XMarkIcon } from '@heroicons/react/24/outline' | 
					
						
							|  |  |  | import TabHeader from '../../base/tab-header' | 
					
						
							|  |  |  | import Button from '../../base/button' | 
					
						
							| 
									
										
										
										
											2023-07-11 15:21:20 +08:00
										 |  |  | import { checkOrSetAccessToken } from '../utils' | 
					
						
							| 
									
										
										
										
											2023-09-25 10:20:50 +08:00
										 |  |  | import { AlertCircle } from '../../base/icons/src/vender/solid/alertsAndFeedback' | 
					
						
							| 
									
										
										
										
											2023-05-31 16:24:30 +08:00
										 |  |  | import s from './style.module.css' | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  | import RunBatch from './run-batch' | 
					
						
							| 
									
										
										
										
											2023-07-13 09:30:16 +08:00
										 |  |  | import ResDownload from './run-batch/res-download' | 
					
						
							| 
									
										
										
										
											2023-05-31 16:24:30 +08:00
										 |  |  | import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  | import RunOnce from '@/app/components/share/text-generation/run-once' | 
					
						
							|  |  |  | import { fetchSavedMessage as doFetchSavedMessage, fetchAppInfo, fetchAppParams, removeMessage, saveMessage } from '@/service/share' | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  | import type { SiteInfo } from '@/models/share' | 
					
						
							| 
									
										
										
										
											2024-01-24 01:05:37 +08:00
										 |  |  | import type { | 
					
						
							|  |  |  |   MoreLikeThisConfig, | 
					
						
							|  |  |  |   PromptConfig, | 
					
						
							|  |  |  |   SavedMessage, | 
					
						
							|  |  |  |   TextToSpeechConfig, | 
					
						
							|  |  |  | } from '@/models/debug' | 
					
						
							| 
									
										
										
										
											2023-05-26 15:26:56 +08:00
										 |  |  | import AppIcon from '@/app/components/base/app-icon' | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  | import { changeLanguage } from '@/i18n/i18next-config' | 
					
						
							|  |  |  | import Loading from '@/app/components/base/loading' | 
					
						
							|  |  |  | import { userInputsFormToPromptVariables } from '@/utils/model-config' | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  | import Res from '@/app/components/share/text-generation/result' | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  | import SavedItems from '@/app/components/app/text-generate/saved-items' | 
					
						
							| 
									
										
										
										
											2023-05-31 16:24:30 +08:00
										 |  |  | import type { InstalledApp } from '@/models/explore' | 
					
						
							| 
									
										
										
										
											2023-09-10 00:12:34 +08:00
										 |  |  | import { DEFAULT_VALUE_MAX_LEN, appDefaultIconBackground } from '@/config' | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  | import Toast from '@/app/components/base/toast' | 
					
						
							| 
									
										
										
										
											2023-11-13 22:32:39 +08:00
										 |  |  | import type { VisionFile, VisionSettings } from '@/types/app' | 
					
						
							|  |  |  | import { Resolution, TransferMethod } from '@/types/app' | 
					
						
							| 
									
										
										
										
											2023-11-06 19:36:32 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-25 10:20:50 +08:00
										 |  |  | const GROUP_SIZE = 5 // to avoid RPM(Request per minute) limit. The group task finished then the next group.
 | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  | enum TaskStatus { | 
					
						
							|  |  |  |   pending = 'pending', | 
					
						
							|  |  |  |   running = 'running', | 
					
						
							|  |  |  |   completed = 'completed', | 
					
						
							| 
									
										
										
										
											2023-09-25 10:20:50 +08:00
										 |  |  |   failed = 'failed', | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type TaskParam = { | 
					
						
							|  |  |  |   inputs: Record<string, any> | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type Task = { | 
					
						
							|  |  |  |   id: number | 
					
						
							|  |  |  |   status: TaskStatus | 
					
						
							|  |  |  |   params: TaskParam | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2023-05-25 16:59:47 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | export type IMainProps = { | 
					
						
							| 
									
										
										
										
											2023-05-31 16:24:30 +08:00
										 |  |  |   isInstalledApp?: boolean | 
					
						
							|  |  |  |   installedAppInfo?: InstalledApp | 
					
						
							| 
									
										
										
										
											2023-05-25 16:59:47 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const TextGeneration: FC<IMainProps> = ({ | 
					
						
							|  |  |  |   isInstalledApp = false, | 
					
						
							| 
									
										
										
										
											2023-05-31 16:24:30 +08:00
										 |  |  |   installedAppInfo, | 
					
						
							| 
									
										
										
										
											2023-05-25 16:59:47 +08:00
										 |  |  | }) => { | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |   const { notify } = Toast | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |   const { t } = useTranslation() | 
					
						
							|  |  |  |   const media = useBreakpoints() | 
					
						
							|  |  |  |   const isPC = media === MediaType.pc | 
					
						
							|  |  |  |   const isTablet = media === MediaType.tablet | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |   const isMobile = media === MediaType.mobile | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   const [currTab, setCurrTab] = useState<string>('create') | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |   // Notice this situation isCallBatchAPI but not in batch tab
 | 
					
						
							|  |  |  |   const [isCallBatchAPI, setIsCallBatchAPI] = useState(false) | 
					
						
							|  |  |  |   const isInBatchTab = currTab === 'batch' | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |   const [inputs, setInputs] = useState<Record<string, any>>({}) | 
					
						
							|  |  |  |   const [appId, setAppId] = useState<string>('') | 
					
						
							|  |  |  |   const [siteInfo, setSiteInfo] = useState<SiteInfo | null>(null) | 
					
						
							| 
									
										
										
										
											2023-12-13 20:21:11 +08:00
										 |  |  |   const [canReplaceLogo, setCanReplaceLogo] = useState<boolean>(false) | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |   const [promptConfig, setPromptConfig] = useState<PromptConfig | null>(null) | 
					
						
							| 
									
										
										
										
											2023-06-06 14:58:56 +08:00
										 |  |  |   const [moreLikeThisConfig, setMoreLikeThisConfig] = useState<MoreLikeThisConfig | null>(null) | 
					
						
							| 
									
										
										
										
											2024-01-24 01:05:37 +08:00
										 |  |  |   const [textToSpeechConfig, setTextToSpeechConfig] = useState<TextToSpeechConfig | null>(null) | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |   // save message
 | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |   const [savedMessages, setSavedMessages] = useState<SavedMessage[]>([]) | 
					
						
							|  |  |  |   const fetchSavedMessage = async () => { | 
					
						
							| 
									
										
										
										
											2023-05-25 16:59:47 +08:00
										 |  |  |     const res: any = await doFetchSavedMessage(isInstalledApp, installedAppInfo?.id) | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |     setSavedMessages(res.data) | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   const handleSaveMessage = async (messageId: string) => { | 
					
						
							| 
									
										
										
										
											2023-05-25 16:59:47 +08:00
										 |  |  |     await saveMessage(messageId, isInstalledApp, installedAppInfo?.id) | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |     notify({ type: 'success', message: t('common.api.saved') }) | 
					
						
							|  |  |  |     fetchSavedMessage() | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   const handleRemoveSavedMessage = async (messageId: string) => { | 
					
						
							| 
									
										
										
										
											2023-05-25 16:59:47 +08:00
										 |  |  |     await removeMessage(messageId, isInstalledApp, installedAppInfo?.id) | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |     notify({ type: 'success', message: t('common.api.remove') }) | 
					
						
							|  |  |  |     fetchSavedMessage() | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |   // send message task
 | 
					
						
							|  |  |  |   const [controlSend, setControlSend] = useState(0) | 
					
						
							|  |  |  |   const [controlStopResponding, setControlStopResponding] = useState(0) | 
					
						
							| 
									
										
										
										
											2023-11-13 22:32:39 +08:00
										 |  |  |   const [visionConfig, setVisionConfig] = useState<VisionSettings>({ | 
					
						
							|  |  |  |     enabled: false, | 
					
						
							|  |  |  |     number_limits: 2, | 
					
						
							|  |  |  |     detail: Resolution.low, | 
					
						
							|  |  |  |     transfer_methods: [TransferMethod.local_file], | 
					
						
							|  |  |  |   }) | 
					
						
							|  |  |  |   const [completionFiles, setCompletionFiles] = useState<VisionFile[]>([]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |   const handleSend = () => { | 
					
						
							|  |  |  |     setIsCallBatchAPI(false) | 
					
						
							|  |  |  |     setControlSend(Date.now()) | 
					
						
							|  |  |  |     // eslint-disable-next-line @typescript-eslint/no-use-before-define
 | 
					
						
							|  |  |  |     setAllTaskList([]) // clear batch task running status
 | 
					
						
							| 
									
										
										
										
											2023-07-11 17:16:28 +08:00
										 |  |  |     // eslint-disable-next-line @typescript-eslint/no-use-before-define
 | 
					
						
							|  |  |  |     showResSidebar() | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-25 10:20:50 +08:00
										 |  |  |   const [controlRetry, setControlRetry] = useState(0) | 
					
						
							|  |  |  |   const handleRetryAllFailedTask = () => { | 
					
						
							|  |  |  |     setControlRetry(Date.now()) | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   const [allTaskList, doSetAllTaskList] = useState<Task[]>([]) | 
					
						
							|  |  |  |   const allTaskListRef = useRef<Task[]>([]) | 
					
						
							|  |  |  |   const getLatestTaskList = () => allTaskListRef.current | 
					
						
							|  |  |  |   const setAllTaskList = (taskList: Task[]) => { | 
					
						
							|  |  |  |     doSetAllTaskList(taskList) | 
					
						
							|  |  |  |     allTaskListRef.current = taskList | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |   const pendingTaskList = allTaskList.filter(task => task.status === TaskStatus.pending) | 
					
						
							|  |  |  |   const noPendingTask = pendingTaskList.length === 0 | 
					
						
							|  |  |  |   const showTaskList = allTaskList.filter(task => task.status !== TaskStatus.pending) | 
					
						
							| 
									
										
										
										
											2023-09-25 10:20:50 +08:00
										 |  |  |   const [currGroupNum, doSetCurrGroupNum] = useState(0) | 
					
						
							|  |  |  |   const currGroupNumRef = useRef(0) | 
					
						
							|  |  |  |   const setCurrGroupNum = (num: number) => { | 
					
						
							|  |  |  |     doSetCurrGroupNum(num) | 
					
						
							|  |  |  |     currGroupNumRef.current = num | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   const getCurrGroupNum = () => { | 
					
						
							|  |  |  |     return currGroupNumRef.current | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   const allSuccessTaskList = allTaskList.filter(task => task.status === TaskStatus.completed) | 
					
						
							|  |  |  |   const allFailedTaskList = allTaskList.filter(task => task.status === TaskStatus.failed) | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |   const allTaskFinished = allTaskList.every(task => task.status === TaskStatus.completed) | 
					
						
							| 
									
										
										
										
											2023-09-25 10:20:50 +08:00
										 |  |  |   const allTaskRuned = allTaskList.every(task => [TaskStatus.completed, TaskStatus.failed].includes(task.status)) | 
					
						
							|  |  |  |   const [batchCompletionRes, doSetBatchCompletionRes] = useState<Record<string, string>>({}) | 
					
						
							|  |  |  |   const batchCompletionResRef = useRef<Record<string, string>>({}) | 
					
						
							|  |  |  |   const setBatchCompletionRes = (res: Record<string, string>) => { | 
					
						
							|  |  |  |     doSetBatchCompletionRes(res) | 
					
						
							|  |  |  |     batchCompletionResRef.current = res | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   const getBatchCompletionRes = () => batchCompletionResRef.current | 
					
						
							| 
									
										
										
										
											2023-07-13 09:30:16 +08:00
										 |  |  |   const exportRes = allTaskList.map((task) => { | 
					
						
							|  |  |  |     const batchCompletionResLatest = getBatchCompletionRes() | 
					
						
							|  |  |  |     const res: Record<string, string> = {} | 
					
						
							| 
									
										
										
										
											2023-09-10 00:12:34 +08:00
										 |  |  |     const { inputs } = task.params | 
					
						
							| 
									
										
										
										
											2023-07-13 09:30:16 +08:00
										 |  |  |     promptConfig?.prompt_variables.forEach((v) => { | 
					
						
							|  |  |  |       res[v.name] = inputs[v.key] | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |     res[t('share.generation.completionResult')] = batchCompletionResLatest[task.id] | 
					
						
							|  |  |  |     return res | 
					
						
							|  |  |  |   }) | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |   const checkBatchInputs = (data: string[][]) => { | 
					
						
							|  |  |  |     if (!data || data.length === 0) { | 
					
						
							|  |  |  |       notify({ type: 'error', message: t('share.generation.errorMsg.empty') }) | 
					
						
							|  |  |  |       return false | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     const headerData = data[0] | 
					
						
							|  |  |  |     let isMapVarName = true | 
					
						
							|  |  |  |     promptConfig?.prompt_variables.forEach((item, index) => { | 
					
						
							|  |  |  |       if (!isMapVarName) | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |         return | 
					
						
							| 
									
										
										
										
											2023-05-31 16:24:30 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |       if (item.name !== headerData[index]) | 
					
						
							|  |  |  |         isMapVarName = false | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |     }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |     if (!isMapVarName) { | 
					
						
							|  |  |  |       notify({ type: 'error', message: t('share.generation.errorMsg.fileStructNotMatch') }) | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |       return false | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |     let payloadData = data.slice(1) | 
					
						
							|  |  |  |     if (payloadData.length === 0) { | 
					
						
							|  |  |  |       notify({ type: 'error', message: t('share.generation.errorMsg.atLeastOne') }) | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |       return false | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |     // check middle empty line
 | 
					
						
							|  |  |  |     const allEmptyLineIndexes = payloadData.filter(item => item.every(i => i === '')).map(item => payloadData.indexOf(item)) | 
					
						
							|  |  |  |     if (allEmptyLineIndexes.length > 0) { | 
					
						
							|  |  |  |       let hasMiddleEmptyLine = false | 
					
						
							|  |  |  |       let startIndex = allEmptyLineIndexes[0] - 1 | 
					
						
							|  |  |  |       allEmptyLineIndexes.forEach((index) => { | 
					
						
							|  |  |  |         if (hasMiddleEmptyLine) | 
					
						
							|  |  |  |           return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (startIndex + 1 !== index) { | 
					
						
							|  |  |  |           hasMiddleEmptyLine = true | 
					
						
							|  |  |  |           return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         startIndex++ | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (hasMiddleEmptyLine) { | 
					
						
							|  |  |  |         notify({ type: 'error', message: t('share.generation.errorMsg.emptyLine', { rowIndex: startIndex + 2 }) }) | 
					
						
							|  |  |  |         return false | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |     // check row format
 | 
					
						
							|  |  |  |     payloadData = payloadData.filter(item => !item.every(i => i === '')) | 
					
						
							|  |  |  |     // after remove empty rows in the end, checked again
 | 
					
						
							|  |  |  |     if (payloadData.length === 0) { | 
					
						
							|  |  |  |       notify({ type: 'error', message: t('share.generation.errorMsg.atLeastOne') }) | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |       return false | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |     let errorRowIndex = 0 | 
					
						
							|  |  |  |     let requiredVarName = '' | 
					
						
							| 
									
										
										
										
											2023-09-10 00:12:34 +08:00
										 |  |  |     let moreThanMaxLengthVarName = '' | 
					
						
							|  |  |  |     let maxLength = 0 | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |     payloadData.forEach((item, index) => { | 
					
						
							|  |  |  |       if (errorRowIndex !== 0) | 
					
						
							|  |  |  |         return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       promptConfig?.prompt_variables.forEach((varItem, varIndex) => { | 
					
						
							|  |  |  |         if (errorRowIndex !== 0) | 
					
						
							|  |  |  |           return | 
					
						
							| 
									
										
										
										
											2023-09-10 00:12:34 +08:00
										 |  |  |         if (varItem.type === 'string') { | 
					
						
							|  |  |  |           const maxLen = varItem.max_length || DEFAULT_VALUE_MAX_LEN | 
					
						
							|  |  |  |           if (item[varIndex].length > maxLen) { | 
					
						
							|  |  |  |             moreThanMaxLengthVarName = varItem.name | 
					
						
							|  |  |  |             maxLength = maxLen | 
					
						
							|  |  |  |             errorRowIndex = index + 1 | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2024-01-24 01:05:37 +08:00
										 |  |  |         if (!varItem.required) | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |           return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (item[varIndex].trim() === '') { | 
					
						
							|  |  |  |           requiredVarName = varItem.name | 
					
						
							|  |  |  |           errorRowIndex = index + 1 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  |     }) | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |     if (errorRowIndex !== 0) { | 
					
						
							| 
									
										
										
										
											2023-09-10 00:12:34 +08:00
										 |  |  |       if (requiredVarName) | 
					
						
							|  |  |  |         notify({ type: 'error', message: t('share.generation.errorMsg.invalidLine', { rowIndex: errorRowIndex + 1, varName: requiredVarName }) }) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (moreThanMaxLengthVarName) | 
					
						
							|  |  |  |         notify({ type: 'error', message: t('share.generation.errorMsg.moreThanMaxLengthLine', { rowIndex: errorRowIndex + 1, varName: moreThanMaxLengthVarName, maxLength }) }) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |       return false | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |     return true | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   const handleRunBatch = (data: string[][]) => { | 
					
						
							|  |  |  |     if (!checkBatchInputs(data)) | 
					
						
							|  |  |  |       return | 
					
						
							|  |  |  |     if (!allTaskFinished) { | 
					
						
							|  |  |  |       notify({ type: 'info', message: t('appDebug.errorMessage.waitForBatchResponse') }) | 
					
						
							|  |  |  |       return | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const payloadData = data.filter(item => !item.every(i => i === '')).slice(1) | 
					
						
							|  |  |  |     const varLen = promptConfig?.prompt_variables.length || 0 | 
					
						
							|  |  |  |     setIsCallBatchAPI(true) | 
					
						
							|  |  |  |     const allTaskList: Task[] = payloadData.map((item, i) => { | 
					
						
							|  |  |  |       const inputs: Record<string, string> = {} | 
					
						
							|  |  |  |       if (varLen > 0) { | 
					
						
							|  |  |  |         item.slice(0, varLen).forEach((input, index) => { | 
					
						
							|  |  |  |           inputs[promptConfig?.prompt_variables[index].key as string] = input | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return { | 
					
						
							|  |  |  |         id: i + 1, | 
					
						
							| 
									
										
										
										
											2023-09-25 10:20:50 +08:00
										 |  |  |         status: i < GROUP_SIZE ? TaskStatus.running : TaskStatus.pending, | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |         params: { | 
					
						
							|  |  |  |           inputs, | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |     setAllTaskList(allTaskList) | 
					
						
							| 
									
										
										
										
											2024-01-05 14:47:00 +08:00
										 |  |  |     setCurrGroupNum(0) | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |     setControlSend(Date.now()) | 
					
						
							|  |  |  |     // clear run once task status
 | 
					
						
							|  |  |  |     setControlStopResponding(Date.now()) | 
					
						
							| 
									
										
										
										
											2023-07-11 17:16:28 +08:00
										 |  |  |     // eslint-disable-next-line @typescript-eslint/no-use-before-define
 | 
					
						
							|  |  |  |     showResSidebar() | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-09-25 10:20:50 +08:00
										 |  |  |   const handleCompleted = (completionRes: string, taskId?: number, isSuccess?: boolean) => { | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |     const allTasklistLatest = getLatestTaskList() | 
					
						
							| 
									
										
										
										
											2023-07-13 09:30:16 +08:00
										 |  |  |     const batchCompletionResLatest = getBatchCompletionRes() | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |     const pendingTaskList = allTasklistLatest.filter(task => task.status === TaskStatus.pending) | 
					
						
							| 
									
										
										
										
											2023-09-25 10:20:50 +08:00
										 |  |  |     const hadRunedTaskNum = 1 + allTasklistLatest.filter(task => [TaskStatus.completed, TaskStatus.failed].includes(task.status)).length | 
					
						
							|  |  |  |     const needToAddNextGroupTask = (getCurrGroupNum() !== hadRunedTaskNum) && pendingTaskList.length > 0 && (hadRunedTaskNum % GROUP_SIZE === 0 || (allTasklistLatest.length - hadRunedTaskNum < GROUP_SIZE)) | 
					
						
							|  |  |  |     // avoid add many task at the same time
 | 
					
						
							|  |  |  |     if (needToAddNextGroupTask) | 
					
						
							|  |  |  |       setCurrGroupNum(hadRunedTaskNum) | 
					
						
							| 
									
										
										
										
											2024-01-05 14:47:00 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-25 10:20:50 +08:00
										 |  |  |     const nextPendingTaskIds = needToAddNextGroupTask ? pendingTaskList.slice(0, GROUP_SIZE).map(item => item.id) : [] | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |     const newAllTaskList = allTasklistLatest.map((item) => { | 
					
						
							|  |  |  |       if (item.id === taskId) { | 
					
						
							|  |  |  |         return { | 
					
						
							|  |  |  |           ...item, | 
					
						
							| 
									
										
										
										
											2023-09-25 10:20:50 +08:00
										 |  |  |           status: isSuccess ? TaskStatus.completed : TaskStatus.failed, | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2023-09-25 10:20:50 +08:00
										 |  |  |       if (needToAddNextGroupTask && nextPendingTaskIds.includes(item.id)) { | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |         return { | 
					
						
							|  |  |  |           ...item, | 
					
						
							|  |  |  |           status: TaskStatus.running, | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return item | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |     }) | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |     setAllTaskList(newAllTaskList) | 
					
						
							| 
									
										
										
										
											2023-07-13 09:30:16 +08:00
										 |  |  |     if (taskId) { | 
					
						
							|  |  |  |       setBatchCompletionRes({ | 
					
						
							|  |  |  |         ...batchCompletionResLatest, | 
					
						
							|  |  |  |         [`${taskId}`]: completionRes, | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-05-25 16:59:47 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-11 15:21:20 +08:00
										 |  |  |   const fetchInitData = async () => { | 
					
						
							| 
									
										
										
										
											2023-07-11 17:07:52 +08:00
										 |  |  |     if (!isInstalledApp) | 
					
						
							|  |  |  |       await checkOrSetAccessToken() | 
					
						
							| 
									
										
										
										
											2023-07-11 15:21:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-31 16:24:30 +08:00
										 |  |  |     return Promise.all([isInstalledApp | 
					
						
							|  |  |  |       ? { | 
					
						
							|  |  |  |         app_id: installedAppInfo?.id, | 
					
						
							|  |  |  |         site: { | 
					
						
							|  |  |  |           title: installedAppInfo?.app.name, | 
					
						
							|  |  |  |           prompt_public: false, | 
					
						
							|  |  |  |           copyright: '', | 
					
						
							|  |  |  |         }, | 
					
						
							|  |  |  |         plan: 'basic', | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2023-07-11 15:21:20 +08:00
										 |  |  |       : fetchAppInfo(), fetchAppParams(isInstalledApp, installedAppInfo?.id), fetchSavedMessage()]) | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   useEffect(() => { | 
					
						
							|  |  |  |     (async () => { | 
					
						
							| 
									
										
										
										
											2023-05-25 16:59:47 +08:00
										 |  |  |       const [appData, appParams]: any = await fetchInitData() | 
					
						
							| 
									
										
										
										
											2023-12-13 20:21:11 +08:00
										 |  |  |       const { app_id: appId, site: siteInfo, can_replace_logo } = appData | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |       setAppId(appId) | 
					
						
							|  |  |  |       setSiteInfo(siteInfo as SiteInfo) | 
					
						
							| 
									
										
										
										
											2023-12-13 20:21:11 +08:00
										 |  |  |       setCanReplaceLogo(can_replace_logo) | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |       changeLanguage(siteInfo.default_language) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-24 01:05:37 +08:00
										 |  |  |       const { user_input_form, more_like_this, file_upload, text_to_speech, sensitive_word_avoidance }: any = appParams | 
					
						
							| 
									
										
										
										
											2023-11-13 22:32:39 +08:00
										 |  |  |       setVisionConfig({ | 
					
						
							|  |  |  |         ...file_upload.image, | 
					
						
							|  |  |  |         image_file_size_limit: appParams?.system_parameters?.image_file_size_limit, | 
					
						
							|  |  |  |       }) | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |       const prompt_variables = userInputsFormToPromptVariables(user_input_form) | 
					
						
							|  |  |  |       setPromptConfig({ | 
					
						
							|  |  |  |         prompt_template: '', // placeholder for feture
 | 
					
						
							|  |  |  |         prompt_variables, | 
					
						
							|  |  |  |       } as PromptConfig) | 
					
						
							| 
									
										
										
										
											2023-06-06 14:58:56 +08:00
										 |  |  |       setMoreLikeThisConfig(more_like_this) | 
					
						
							| 
									
										
										
										
											2024-01-24 01:05:37 +08:00
										 |  |  |       setTextToSpeechConfig(text_to_speech) | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |     })() | 
					
						
							|  |  |  |   }, []) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-31 16:24:30 +08:00
										 |  |  |   // Can Use metadata(https://beta.nextjs.org/docs/api-reference/metadata) to set title. But it only works in server side client.
 | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |   useEffect(() => { | 
					
						
							| 
									
										
										
										
											2023-12-13 20:21:11 +08:00
										 |  |  |     if (siteInfo?.title) { | 
					
						
							|  |  |  |       if (canReplaceLogo) | 
					
						
							|  |  |  |         document.title = `${siteInfo.title}` | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         document.title = `${siteInfo.title} - Powered by Dify` | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }, [siteInfo?.title, canReplaceLogo]) | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-04 14:07:38 +08:00
										 |  |  |   const [isShowResSidebar, { setTrue: doShowResSidebar, setFalse: hideResSidebar }] = useBoolean(false) | 
					
						
							|  |  |  |   const showResSidebar = () => { | 
					
						
							|  |  |  |     // fix: useClickAway hideResSidebar will close sidebar
 | 
					
						
							|  |  |  |     setTimeout(() => { | 
					
						
							|  |  |  |       doShowResSidebar() | 
					
						
							|  |  |  |     }, 0) | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |   const resRef = useRef<HTMLDivElement>(null) | 
					
						
							|  |  |  |   useClickAway(() => { | 
					
						
							| 
									
										
										
										
											2023-05-31 16:24:30 +08:00
										 |  |  |     hideResSidebar() | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |   }, resRef) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |   const renderRes = (task?: Task) => (<Res | 
					
						
							|  |  |  |     key={task?.id} | 
					
						
							|  |  |  |     isCallBatchAPI={isCallBatchAPI} | 
					
						
							|  |  |  |     isPC={isPC} | 
					
						
							|  |  |  |     isMobile={isMobile} | 
					
						
							| 
									
										
										
										
											2024-01-24 01:05:37 +08:00
										 |  |  |     isInstalledApp={isInstalledApp} | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |     installedAppInfo={installedAppInfo} | 
					
						
							| 
									
										
										
										
											2023-09-25 10:20:50 +08:00
										 |  |  |     isError={task?.status === TaskStatus.failed} | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |     promptConfig={promptConfig} | 
					
						
							|  |  |  |     moreLikeThisEnabled={!!moreLikeThisConfig?.enabled} | 
					
						
							|  |  |  |     inputs={isCallBatchAPI ? (task as Task).params.inputs : inputs} | 
					
						
							|  |  |  |     controlSend={controlSend} | 
					
						
							| 
									
										
										
										
											2023-09-25 10:20:50 +08:00
										 |  |  |     controlRetry={task?.status === TaskStatus.failed ? controlRetry : 0} | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |     controlStopResponding={controlStopResponding} | 
					
						
							|  |  |  |     onShowRes={showResSidebar} | 
					
						
							|  |  |  |     handleSaveMessage={handleSaveMessage} | 
					
						
							|  |  |  |     taskId={task?.id} | 
					
						
							|  |  |  |     onCompleted={handleCompleted} | 
					
						
							| 
									
										
										
										
											2023-11-13 22:32:39 +08:00
										 |  |  |     visionConfig={visionConfig} | 
					
						
							|  |  |  |     completionFiles={completionFiles} | 
					
						
							| 
									
										
										
										
											2024-01-24 01:05:37 +08:00
										 |  |  |     isShowTextToSpeech={!!textToSpeechConfig?.enabled} | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |   />) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const renderBatchRes = () => { | 
					
						
							|  |  |  |     return (showTaskList.map(task => renderRes(task))) | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-04 14:07:38 +08:00
										 |  |  |   const resWrapClassNames = (() => { | 
					
						
							|  |  |  |     if (isPC) | 
					
						
							|  |  |  |       return 'grow h-full' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!isShowResSidebar) | 
					
						
							|  |  |  |       return 'none' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return cn('fixed z-50 inset-0', isTablet ? 'pl-[128px]' : 'pl-6') | 
					
						
							|  |  |  |   })() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |   const renderResWrap = ( | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |     <div | 
					
						
							|  |  |  |       ref={resRef} | 
					
						
							|  |  |  |       className={ | 
					
						
							| 
									
										
										
										
											2023-05-25 16:59:47 +08:00
										 |  |  |         cn( | 
					
						
							| 
									
										
										
										
											2023-05-31 16:24:30 +08:00
										 |  |  |           'flex flex-col h-full shrink-0', | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |           isPC ? 'px-10 py-8' : 'bg-gray-50', | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |           isTablet && 'p-6', isMobile && 'p-4') | 
					
						
							| 
									
										
										
										
											2023-05-31 16:24:30 +08:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |     > | 
					
						
							|  |  |  |       <> | 
					
						
							|  |  |  |         <div className='shrink-0 flex items-center justify-between'> | 
					
						
							|  |  |  |           <div className='flex items-center space-x-3'> | 
					
						
							|  |  |  |             <div className={s.starIcon}></div> | 
					
						
							|  |  |  |             <div className='text-lg text-gray-800 font-semibold'>{t('share.generation.title')}</div> | 
					
						
							|  |  |  |           </div> | 
					
						
							| 
									
										
										
										
											2023-07-13 09:30:16 +08:00
										 |  |  |           <div className='flex items-center space-x-2'> | 
					
						
							| 
									
										
										
										
											2023-09-25 10:20:50 +08:00
										 |  |  |             {allFailedTaskList.length > 0 && ( | 
					
						
							|  |  |  |               <div className='flex items-center'> | 
					
						
							|  |  |  |                 <AlertCircle className='w-4 h-4 text-[#D92D20]' /> | 
					
						
							|  |  |  |                 <div className='ml-1 text-[#D92D20]'>{t('share.generation.batchFailed.info', { num: allFailedTaskList.length })}</div> | 
					
						
							|  |  |  |                 <Button | 
					
						
							|  |  |  |                   type='primary' | 
					
						
							|  |  |  |                   className='ml-2 !h-8 !px-3' | 
					
						
							|  |  |  |                   onClick={handleRetryAllFailedTask} | 
					
						
							|  |  |  |                 >{t('share.generation.batchFailed.retry')}</Button> | 
					
						
							|  |  |  |                 <div className='mx-3 w-[1px] h-3.5 bg-gray-200'></div> | 
					
						
							|  |  |  |               </div> | 
					
						
							|  |  |  |             )} | 
					
						
							|  |  |  |             {allSuccessTaskList.length > 0 && ( | 
					
						
							| 
									
										
										
										
											2023-07-13 09:30:16 +08:00
										 |  |  |               <ResDownload | 
					
						
							|  |  |  |                 isMobile={isMobile} | 
					
						
							|  |  |  |                 values={exportRes} | 
					
						
							|  |  |  |               /> | 
					
						
							|  |  |  |             )} | 
					
						
							|  |  |  |             {!isPC && ( | 
					
						
							|  |  |  |               <div | 
					
						
							|  |  |  |                 className='flex items-center justify-center cursor-pointer' | 
					
						
							|  |  |  |                 onClick={hideResSidebar} | 
					
						
							|  |  |  |               > | 
					
						
							|  |  |  |                 <XMarkIcon className='w-4 h-4 text-gray-800' /> | 
					
						
							|  |  |  |               </div> | 
					
						
							|  |  |  |             )} | 
					
						
							|  |  |  |           </div> | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |         </div> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-31 16:24:30 +08:00
										 |  |  |         <div className='grow overflow-y-auto'> | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |           {!isCallBatchAPI ? renderRes() : renderBatchRes()} | 
					
						
							|  |  |  |           {!noPendingTask && ( | 
					
						
							|  |  |  |             <div className='mt-4'> | 
					
						
							|  |  |  |               <Loading type='area' /> | 
					
						
							|  |  |  |             </div> | 
					
						
							|  |  |  |           )} | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |         </div> | 
					
						
							|  |  |  |       </> | 
					
						
							|  |  |  |     </div> | 
					
						
							|  |  |  |   ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-09-25 10:20:50 +08:00
										 |  |  |   if (!appId || !siteInfo || !promptConfig) { | 
					
						
							|  |  |  |     return ( | 
					
						
							|  |  |  |       <div className='flex items-center h-screen'> | 
					
						
							|  |  |  |         <Loading type='app' /> | 
					
						
							|  |  |  |       </div>) | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   return ( | 
					
						
							|  |  |  |     <> | 
					
						
							| 
									
										
										
										
											2023-05-25 16:59:47 +08:00
										 |  |  |       <div className={cn( | 
					
						
							|  |  |  |         isPC && 'flex', | 
					
						
							|  |  |  |         isInstalledApp ? s.installedApp : 'h-screen', | 
					
						
							| 
									
										
										
										
											2023-05-31 16:24:30 +08:00
										 |  |  |         'bg-gray-50', | 
					
						
							| 
									
										
										
										
											2023-05-25 16:59:47 +08:00
										 |  |  |       )}> | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |         {/* Left */} | 
					
						
							| 
									
										
										
										
											2023-05-25 16:59:47 +08:00
										 |  |  |         <div className={cn( | 
					
						
							|  |  |  |           isPC ? 'w-[600px] max-w-[50%] p-8' : 'p-4', | 
					
						
							|  |  |  |           isInstalledApp && 'rounded-l-2xl', | 
					
						
							| 
									
										
										
										
											2023-05-31 16:24:30 +08:00
										 |  |  |           'shrink-0 relative flex flex-col pb-10 h-full border-r border-gray-100 bg-white', | 
					
						
							| 
									
										
										
										
											2023-05-25 16:59:47 +08:00
										 |  |  |         )}> | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |           <div className='mb-6'> | 
					
						
							|  |  |  |             <div className='flex justify-between items-center'> | 
					
						
							|  |  |  |               <div className='flex items-center space-x-3'> | 
					
						
							| 
									
										
										
										
											2023-05-26 15:26:56 +08:00
										 |  |  |                 <AppIcon size="small" icon={siteInfo.icon} background={siteInfo.icon_background || appDefaultIconBackground} /> | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |                 <div className='text-lg text-gray-800 font-semibold'>{siteInfo.title}</div> | 
					
						
							|  |  |  |               </div> | 
					
						
							|  |  |  |               {!isPC && ( | 
					
						
							|  |  |  |                 <Button | 
					
						
							|  |  |  |                   className='shrink-0 !h-8 !px-3 ml-2' | 
					
						
							|  |  |  |                   onClick={showResSidebar} | 
					
						
							|  |  |  |                 > | 
					
						
							|  |  |  |                   <div className='flex items-center space-x-2 text-primary-600 text-[13px] font-medium'> | 
					
						
							|  |  |  |                     <div className={s.starIcon}></div> | 
					
						
							|  |  |  |                     <span>{t('share.generation.title')}</span> | 
					
						
							|  |  |  |                   </div> | 
					
						
							|  |  |  |                 </Button> | 
					
						
							|  |  |  |               )} | 
					
						
							|  |  |  |             </div> | 
					
						
							|  |  |  |             {siteInfo.description && ( | 
					
						
							|  |  |  |               <div className='mt-2 text-xs text-gray-500'>{siteInfo.description}</div> | 
					
						
							|  |  |  |             )} | 
					
						
							|  |  |  |           </div> | 
					
						
							|  |  |  |           <TabHeader | 
					
						
							|  |  |  |             items={[ | 
					
						
							|  |  |  |               { id: 'create', name: t('share.generation.tabs.create') }, | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |               { id: 'batch', name: t('share.generation.tabs.batch') }, | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |               { | 
					
						
							| 
									
										
										
										
											2023-05-31 16:24:30 +08:00
										 |  |  |                 id: 'saved', | 
					
						
							|  |  |  |                 name: t('share.generation.tabs.saved'), | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |                 isRight: true, | 
					
						
							| 
									
										
										
										
											2023-05-31 16:24:30 +08:00
										 |  |  |                 extra: savedMessages.length > 0 | 
					
						
							|  |  |  |                   ? ( | 
					
						
							|  |  |  |                     <div className='ml-1 flext items-center h-5 px-1.5 rounded-md border border-gray-200 text-gray-500 text-xs font-medium'> | 
					
						
							|  |  |  |                       {savedMessages.length} | 
					
						
							|  |  |  |                     </div> | 
					
						
							|  |  |  |                   ) | 
					
						
							|  |  |  |                   : null, | 
					
						
							|  |  |  |               }, | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |             ]} | 
					
						
							|  |  |  |             value={currTab} | 
					
						
							|  |  |  |             onChange={setCurrTab} | 
					
						
							|  |  |  |           /> | 
					
						
							|  |  |  |           <div className='grow h-20 overflow-y-auto'> | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |             <div className={cn(currTab === 'create' ? 'block' : 'hidden')}> | 
					
						
							|  |  |  |               <RunOnce | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |                 siteInfo={siteInfo} | 
					
						
							|  |  |  |                 inputs={inputs} | 
					
						
							|  |  |  |                 onInputsChange={setInputs} | 
					
						
							|  |  |  |                 promptConfig={promptConfig} | 
					
						
							|  |  |  |                 onSend={handleSend} | 
					
						
							| 
									
										
										
										
											2023-11-13 22:32:39 +08:00
										 |  |  |                 visionConfig={visionConfig} | 
					
						
							|  |  |  |                 onVisionFilesChange={setCompletionFiles} | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |               /> | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |             </div> | 
					
						
							|  |  |  |             <div className={cn(isInBatchTab ? 'block' : 'hidden')}> | 
					
						
							|  |  |  |               <RunBatch | 
					
						
							|  |  |  |                 vars={promptConfig.prompt_variables} | 
					
						
							|  |  |  |                 onSend={handleRunBatch} | 
					
						
							| 
									
										
										
										
											2023-09-25 10:20:50 +08:00
										 |  |  |                 isAllFinished={allTaskRuned} | 
					
						
							| 
									
										
										
										
											2023-07-07 10:35:05 +08:00
										 |  |  |               /> | 
					
						
							|  |  |  |             </div> | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |             {currTab === 'saved' && ( | 
					
						
							|  |  |  |               <SavedItems | 
					
						
							|  |  |  |                 className='mt-4' | 
					
						
							| 
									
										
										
										
											2024-01-24 01:05:37 +08:00
										 |  |  |                 isShowTextToSpeech={textToSpeechConfig?.enabled} | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |                 list={savedMessages} | 
					
						
							|  |  |  |                 onRemove={handleRemoveSavedMessage} | 
					
						
							|  |  |  |                 onStartCreateContent={() => setCurrTab('create')} | 
					
						
							|  |  |  |               /> | 
					
						
							|  |  |  |             )} | 
					
						
							|  |  |  |           </div> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           {/* copyright */} | 
					
						
							| 
									
										
										
										
											2023-05-25 16:59:47 +08:00
										 |  |  |           <div className={cn( | 
					
						
							|  |  |  |             isInstalledApp ? 'left-[248px]' : 'left-8', | 
					
						
							| 
									
										
										
										
											2023-05-31 16:24:30 +08:00
										 |  |  |             'fixed  bottom-4  flex space-x-2 text-gray-400 font-normal text-xs', | 
					
						
							|  |  |  |           )}> | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |             <div className="">© {siteInfo.copyright || siteInfo.title} {(new Date()).getFullYear()}</div> | 
					
						
							|  |  |  |             {siteInfo.privacy_policy && ( | 
					
						
							|  |  |  |               <> | 
					
						
							|  |  |  |                 <div>·</div> | 
					
						
							|  |  |  |                 <div>{t('share.chat.privacyPolicyLeft')} | 
					
						
							|  |  |  |                   <a | 
					
						
							|  |  |  |                     className='text-gray-500' | 
					
						
							|  |  |  |                     href={siteInfo.privacy_policy} | 
					
						
							| 
									
										
										
										
											2024-02-02 15:24:17 +08:00
										 |  |  |                     target='_blank' rel='noopener noreferrer'>{t('share.chat.privacyPolicyMiddle')}</a> | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |                   {t('share.chat.privacyPolicyRight')} | 
					
						
							|  |  |  |                 </div> | 
					
						
							|  |  |  |               </> | 
					
						
							|  |  |  |             )} | 
					
						
							|  |  |  |           </div> | 
					
						
							|  |  |  |         </div> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         {/* Result */} | 
					
						
							| 
									
										
										
										
											2024-01-04 14:07:38 +08:00
										 |  |  |         <div | 
					
						
							|  |  |  |           className={resWrapClassNames} | 
					
						
							|  |  |  |           style={{ | 
					
						
							|  |  |  |             background: (!isPC && isShowResSidebar) ? 'rgba(35, 56, 118, 0.2)' : 'none', | 
					
						
							|  |  |  |           }} | 
					
						
							|  |  |  |         > | 
					
						
							|  |  |  |           {renderResWrap} | 
					
						
							|  |  |  |         </div> | 
					
						
							| 
									
										
										
										
											2023-05-15 08:51:32 +08:00
										 |  |  |       </div> | 
					
						
							|  |  |  |     </> | 
					
						
							|  |  |  |   ) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export default TextGeneration |