UNPKG

general-assistant

Version:

General Assistant components

615 lines (614 loc) 41.1 kB
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import classNames from 'classnames'; import { Button, Divider, Flex, Input, Progress } from 'datastellar-chatui'; import { debounce, defaultsDeep, each, extend, find, set } from 'lodash'; import Upload from 'rc-upload'; import { forwardRef, useEffect, useRef, useState, useContext } from 'react'; import { useTranslation } from 'react-i18next'; import { useStore } from 'zustand'; import StoreContext from '../_store/StoreContext'; import { blobToFile, getFileGeneralSize, getFileName, getFileTypeIcon, getMedia, RandomString, sendRequestWithConfig, } from '../_utils/tools'; import { placeholder as en_placeholder } from '../i18n/en-us.json'; import { placeholder as zh_placeholder } from '../i18n/zh-cn.json'; import StreamWave from '../StreamWave'; import Tooltip from '../Tooltips'; import { IoIosWarning } from "react-icons/io"; import ComposerRightAddition from './component/RightAddition'; import ComposerLeftAddition from './component/LeftAddition'; import ComposerToast from './component/ToastInfo'; import ComposerCitationContent from './component/CitationContent'; import ComposerCautionContent from './component/CautionContent'; const defaultVoiceProps = { minduration: 150, maxduration: 30000, warnduration: 3000 }; let isWaitToText = false; let controller = null; let assistantMediaRecorder = null; let chunks = []; let assistantTimer = null; let isObsolete = false; let effectiveTime = 0; const InputComposer = forwardRef(({ onSend, inputOptions }, inputRef) => { const { t, i18n: i18nContext } = useTranslation(); const dataStore = useContext(StoreContext); const { MyHandlers, getDeviceInfo, getRequestConfig, getConfig, GlobalCtxs, sourceList, setSourceList, stopBroadAudio, getCitation, setCitationInfo, selectedAite, setSelectedAite, confirmAite, setConfirmAite, getConfirmAite, isShowAite, getShowAite, setShowAite, } = useStore(dataStore, (state) => ({ MyHandlers: state.MyHandlers, getDeviceInfo: state.getDeviceInfo, getRequestConfig: state.getRequestConfig, getConfig: state.getConfig, GlobalCtxs: state.GlobalCtxs, sourceList: state.sourceList, setSourceList: state.updateList, stopBroadAudio: state.stopBroadAudio, getCitation: state.getCitation, setCitationInfo: state.setCitationInfo, selectedAite: state.selectedAite, setSelectedAite: state.setSelectedAite, confirmAite: state.confirmAite, setConfirmAite: state.setConfirmAite, getConfirmAite: state.getConfirmAite, isShowAite: state.isShowAite, getShowAite: state.getShowAite, setShowAite: state.setShowAite, })); const { onFileChange, beforeSpeechToText, onselectionchange } = MyHandlers; const { timeout, method, headers, speechToText } = getRequestConfig(); const { inputProps } = getConfig(); const { isShowInput, disabled, allowVoice, voiceProps, text: defVal, placeholder, allowUpload, uploadProps, completeAreaClass, inputAreaClass, inputClass, operateLeftCustomIcon, operateRightCustomIcon } = inputProps; useEffect(() => { if (inputRef && inputRef.current) inputRef.current.rows = 1; }, [isShowInput]); useEffect(() => { if (inputRef.current) { const textarea = inputRef.current; textarea.addEventListener('selectionchange', () => { const start = textarea.selectionStart; const end = textarea.selectionEnd; typeof onselectionchange === 'function' ? onselectionchange({ value: inputRef.current.value, start, end }, GlobalCtxs) : ''; }); } }, [inputRef]); const [myPlaceholder, setMyPlaceholder] = useState(placeholder); useEffect(() => { if (placeholder === zh_placeholder || placeholder === en_placeholder) { if (i18nContext.language === 'zh') setMyPlaceholder(zh_placeholder); if (i18nContext.language === 'en') setMyPlaceholder(en_placeholder); } else { setMyPlaceholder(placeholder); } }, [placeholder, i18nContext.language]); const [myInputRows, setMyInputRows] = useState(1); const [myCautionSearch, setMyCautionSearch] = useState(''); function substrAiteToCursor(_inputV) { const _ref = inputRef.current; const _selectEndIndex = _ref.selectionEnd; const _preSelectStr = _inputV.substring(0, _selectEndIndex); const _lastAiteIndex = _preSelectStr.lastIndexOf('@'); return _preSelectStr.substring(_lastAiteIndex); } function isAiteOrder(_inputV, _newV) { if (_newV === '@') return _newV; if (_inputV.toString().indexOf('@') === -1) return ''; return substrAiteToCursor(_inputV); } function onInputValueChange(_value, syntheticBaseEvent) { if (_value === '') { setMyInputRows(1); setShowAite(false); setSelectedAite(confirmAite); if (inputRef && inputRef.current) inputRef.current.rows = 1; return; } if (syntheticBaseEvent) { const { nativeEvent } = syntheticBaseEvent; const { data: newStr } = nativeEvent; const _substr = isAiteOrder(_value, newStr); let _flag = (_substr.toString().startsWith('@')); if (_flag) { setSelectedAite(confirmAite); setMyCautionSearch(_substr); setShowAite(true); } else { setShowAite(false); } } const _findCode = _value.match(/[\u000A]/g); const _textRows = _findCode ? _findCode.length + 1 : 1; let _naxRows = _textRows; if (inputRef && inputRef.current) { const _refrows = inputRef.current.rows; if (_refrows > _textRows) _naxRows = _refrows; } setMyInputRows(_naxRows); if (inputRef && inputRef.current && _naxRows < 4) inputRef.current.rows = _naxRows; } const [isFullScreenInput, setIsFullScreenInput] = useState(false); const { isMobile } = getDeviceInfo(); const [hasText, setHasText] = useState(!!defVal); const { pattern } = inputOptions; const [isDis, setIsDis] = useState(disabled || pattern === 'stop'); const [toastInfo, setToastInfo] = useState(null); const MyOnFileChange = (ev, fileList) => typeof onFileChange === 'function' ? onFileChange(ev, fileList, GlobalCtxs) : () => ''; const getNewFileItem = (file) => { const _file = extend({}, { uid: RandomString(), percent: 0, response: '', error: '', type: 'url', size: 0, name: '', }, file); return _file; }; const [uploadErrorMessage, setUploadErrorMessage] = useState(''); useEffect(() => { if (sourceList.length === 0) { const _thisInfo = getNewFileItem(); setSourceList([_thisInfo]); } else { } }, [sourceList]); function onBeforeUpload(_file, _fl) { console.log('?onBeforeUpload', _file, _fl); let hasError = false; const { multiple, maxNumber, maxByte } = uploadProps; const _realyNum = sourceList.filter((e) => e.response).length; const _restNum = Number(maxNumber - _realyNum); if (_fl.length > _restNum) { setUploadErrorMessage('numberOver'); return false; } each(_fl, (e) => { if (e.size > maxByte) hasError = true; }); if (hasError) { setUploadErrorMessage('bytesOver'); return false; } } function onBatchStart(fileList) { console.log('?onBatchStart', fileList); const hasError = fileList.some(({ parsedFile }) => !parsedFile); if (hasError) return; let _oldlist = [].concat(sourceList); let findIndexStart = 0; const _nlist = []; each(fileList, ({ parsedFile }) => { const { uid, name, type, size } = parsedFile; const _oldItem = find(_oldlist, (_item, index) => { if (!_item.response) { findIndexStart = index + 1; return true; } }, findIndexStart); const _newItem = { uid, name, type, size, percent: 0, error: '', response: '' }; if (_oldItem) extend(_oldItem, _newItem); else _nlist.push(_newItem); }); setSourceList(_oldlist.concat(_nlist)); } function onProgress(event, file) { const { uid } = file; const { percent } = event; file.percent = percent; console.log('文件上传进度:', percent, file); set(find(sourceList, (_item) => _item.uid === uid), 'percent', percent); setSourceList(sourceList.concat([])); } function onSuccess(response, file) { const { uid, name, type } = file; const fileItem = find(sourceList, (_item) => _item.uid === uid); extend(fileItem, {}, { percent: 100, error: '', response }); console.log('修改之后的fileItem: ', fileItem); setSourceList(sourceList.concat([])); MyOnFileChange('success', sourceList); } function onError(err, ret, file) { console.log('文件上传出现错误:', err, ret, file); const { message } = err; const { uid, name, type, size } = file; const _thisInfo = { uid, name, type, size, percent: 0, error: err, response: name }; const _nlist = sourceList.map((_item) => (_item.uid === uid ? _thisInfo : _item)); setSourceList(_nlist); MyOnFileChange('error', _nlist); } function getErrorTip(err) { if (err.includes('500')) return '上传失败, 网络连接不稳定或已断开'; if (err.includes('404')) return '上传失败, 请求地址错误'; return err; } const [myAllowUpload, setMyAllowUpload] = useState(allowUpload); useEffect(() => { setMyAllowUpload(allowUpload); }, [allowUpload]); const [myUploadProps, setMyUploadProps] = useState(defaultsDeep(uploadProps, { disabled: isDis })); useEffect(() => { setMyUploadProps(uploadProps); }, [uploadProps]); const MyBeforeSpeechToText = (options) => typeof beforeSpeechToText === 'function' ? beforeSpeechToText(options) : { next: true }; const [myAllowVoice, setMyAllowVoice] = useState(allowVoice); useEffect(() => { setMyAllowVoice(allowVoice); }, [allowVoice]); function lessVoiceProps() { const { minduration, warnduration, maxduration } = defaultsDeep(voiceProps, defaultVoiceProps); if (minduration < 0 || warnduration < 0 || maxduration < 0) { return defaultVoiceProps; } if (maxduration <= minduration) { return defaultVoiceProps; } if (warnduration >= maxduration) { return defaultVoiceProps; } return { minduration, warnduration, maxduration }; } const [myVoiceProps, setMyVoiceProps] = useState(lessVoiceProps()); useEffect(() => { setMyVoiceProps(lessVoiceProps()); }, [voiceProps]); const [isToText, setIsToText] = useState(false); const [toTextErr, setToTextErr] = useState(''); const [myMediaStream, setMyMediaStream] = useState(null); const [timeWarning, setTimeWarning] = useState(''); useEffect(() => { if (myMediaStream === null && assistantMediaRecorder !== null) { assistantMediaRecorder.stop(); assistantMediaRecorder = null; } if (myMediaStream !== null) { const _pir = 100; assistantTimer = setInterval(() => { effectiveTime = effectiveTime + _pir; console.log('语音输入计时', myVoiceProps.minduration, effectiveTime, myVoiceProps.maxduration); const _diff = myVoiceProps.maxduration - effectiveTime; if (_diff <= myVoiceProps.warnduration) { setTimeWarning(t('timeWarning', { time: Math.ceil(_diff / 1000) })); } else { setTimeWarning(''); } if (_diff <= 0) stopMediaTracks(), (isWaitToText = true); }, _pir); return () => clearInterval(assistantTimer); } }, [myMediaStream]); async function dealVioceStart() { stopBroadAudio(); const _media = (await getMedia()); console.log('getMedia response:', _media); if (typeof _media === 'string') { if (_media === 'Not support') openToast(t('NotSupport')); if (_media === 'Requested device not found') openToast(t('mediaNotFound')); if (_media === 'Permission denied') openToast(t('mediaDenied')); setMyMediaStream(null); return; } if (isObsolete) { stopMediaTracks(); isObsolete = false; effectiveTime = 0; setText(''); setIsDis(false); return; } isObsolete = false; effectiveTime = 0; setIsDis(true); setText(t('voiceInput')); setMyMediaStream(_media); if (assistantMediaRecorder === null) { chunks = []; assistantMediaRecorder = new MediaRecorder(_media); assistantMediaRecorder.ondataavailable = event => { chunks.push(event.data); }; assistantMediaRecorder.onstop = event => { if (isWaitToText) dealAllSpeechToText(); }; assistantMediaRecorder.start(); } } function dealBeforeSpeechToText(_preSpeechToText) { const _nextOrSuc = MyBeforeSpeechToText(_preSpeechToText); if (!_nextOrSuc.next) { if (_nextOrSuc.succeed) { setIsToText(false); setToTextErr(''); setText(''); setIsDis(false); effectiveTime = 0; assistantMediaRecorder = null; chunks = []; } else { setText(t('voiceToTextFail')); setToTextErr('1'); } } return _nextOrSuc.next; } async function defaultSpeechToText(_preSpeechToText) { const _reqConfig = speechToText(_preSpeechToText); const { mimeType, body: _cusFdOrObj } = _reqConfig; let _formData = null; if (mimeType === false) { _formData = _cusFdOrObj; } else { const _formFile = await blobToFile(_reqConfig.mimeType, chunks); if (_formFile instanceof FormData) { if (Object.keys(_cusFdOrObj).length > 0) { for (const key in _cusFdOrObj) { _formFile.append(key, _cusFdOrObj[key]); } } _formData = _formFile; } else { openToast(_formFile.toString()); } } controller = new AbortController(); sendRequestWithConfig({ commonOpt: { timeout, method, headers }, parameter: Object.assign({}, _reqConfig, { body: _formData }), isFecth: true, controller, onResponse(response) { const { status, message, data } = response; if (effectiveTime !== 0) { if (status === 200) { setText(data?.text); setToTextErr(''); setIsDis(false); effectiveTime = 0; if (inputRef.current) inputRef.current.rows = 4; } else { setText(t('voiceToTextFail')); setToTextErr(message); openToast(message); } } }, onCatch(err) { if (effectiveTime !== 0) { setText(t('voiceToTextFail')); setToTextErr(err); openToast(err); } }, onFinally() { setIsToText(false); }, }); } async function dealAllSpeechToText() { console.log('看看本次预备发送的chunks:', chunks); const _preSpeechToText = { data: { voice: chunks }, ctx: GlobalCtxs }; const _next = dealBeforeSpeechToText(_preSpeechToText); if (!_next) return; if (typeof speechToText !== 'function') { openToast(t('missVoiceToText')); setIsDis(false); setText(''); isObsolete = false; effectiveTime = 0; return; } setText(t('voiceToText')); isObsolete = false; setIsDis(true); setIsToText(true); setToTextErr(''); await defaultSpeechToText(_preSpeechToText); } function stopMediaTracks() { if (myMediaStream !== null) { if (myMediaStream !== 1) { myMediaStream.getTracks().forEach(function (track) { track.stop(); setMyMediaStream(null); }); } clearInterval(assistantTimer); assistantTimer = null; } } async function dealVioceEnd() { if (effectiveTime === 0 && (myMediaStream === null || myMediaStream === 1)) isObsolete = true; if (effectiveTime < myVoiceProps.minduration) { if (myMediaStream !== 1) stopMediaTracks(); setIsDis(false); effectiveTime = 0; setText(''); assistantMediaRecorder = null; chunks = []; isWaitToText = false; openToast(t('voiceTooShort')); return; } stopMediaTracks(); isWaitToText = true; } function stopToText() { setIsToText(false); setMyMediaStream(null); effectiveTime = 0; setText(''); setToTextErr(''); if (controller && controller.abort) { controller.abort(); controller = null; } } function openToast(text, type = 'info') { if (text) setToastInfo({ text, type }); setTimeout(() => { setToastInfo(null); }, 2000); } function handleSend() { const _val = inputRef.current?.value; if (_val) { onSend('text', _val); } } function handleBreak() { onSend('stop', ''); } const handleKeyDown = (event) => { if (!getShowAite() && !event.shiftKey && event.key === 'Enter') { event.preventDefault(); handleSend(); } }; function setText(_nv) { if (inputRef && inputRef.current) { inputRef.current.value = _nv; setHasText(_nv !== ''); if (_nv !== '') { onInputValueChange(_nv); } else { inputRef.current.rows = 1; setShowAite(false); setSelectedAite(confirmAite); } } } function setCitation(option) { if (!option) return; if (typeof option._id !== 'string') return; setCitationInfo(option); } function replaceStr() { const _ref = inputRef.current; const _oldV = _ref.value; const _selectEndIndexInAll = _ref.selectionEnd; const _preSelectStr = _oldV.substring(0, _selectEndIndexInAll); const _findAiteIndexInPre = _preSelectStr.lastIndexOf('@'); const _preRV = _oldV.substring(0, _findAiteIndexInPre); const _fixRV = _oldV.substring(_selectEndIndexInAll); inputRef.current.value = _preRV + _fixRV; inputRef.current.focus(); } useEffect(() => { if (inputRef && inputRef.current) { inputRef.current.ele = { getText: () => inputRef.current.value, setText: (_nv) => { setText(_nv); return inputRef.current.ele; }, handleSend: () => { handleSend(); return inputRef.current.ele; }, setCitation: (option) => { setCitation(option); return inputRef.current.ele; }, focus: () => { inputRef.current.focus(); return inputRef.current.ele; }, blur: () => { inputRef.current.blur(); return inputRef.current.ele; }, getCitation, getConfirmAite, getShowAite, setShowAite: (boo) => { setShowAite(boo); return inputRef.current.ele; }, showAiteList: (show, resetSearch) => { resetSearch && setMyCautionSearch(''); setShowAite(show); return inputRef.current.ele; }, }; } if (defVal) setText(defVal), onInputValueChange(defVal); }, []); useEffect(() => { setIsDis(disabled || pattern === 'stop' || myMediaStream || isToText || toTextErr !== ''); }, [pattern, disabled, isToText, toTextErr, myMediaStream]); const fileUrlListRef = useRef(null); return (_jsxs("div", { className: classNames('DS-GA-relative DS-GA-w-full DS-GA-flex', completeAreaClass, isShowInput ? '' : 'DS-GA-hidden'), children: [_jsx(Flex, { className: 'DS-GA-w-full DS-GA-absolute -DS-GA-mt-12', justify: 'center', children: pattern === 'stop' && _jsx(Button, { label: "\u505C\u6B62\u751F\u6210", size: 'lg', onClick: handleBreak }) }), _jsx(ComposerLeftAddition, {}), _jsxs("div", { className: classNames('DS-GA-grow DS-GA-relative !DS-GA-overflow-visible DS-GA-shadow-full-shal', inputAreaClass), children: [_jsx(ComposerRightAddition, {}), _jsxs("div", { id: 'rComposer', className: classNames('DS-GA-w-full DS-GA-relative Composer DS-GA-flex-col DS-GA-bg-area-mode DS-GA-rounded-lg DS-GA-border-0', inputClass), onKeyDown: handleKeyDown, children: [_jsx(ComposerToast, { data: toastInfo }), myAllowUpload && sourceList.length > 0 && (_jsx("div", { className: 'DS-GA-w-full DS-GA-flex DS-GA-flex-wrap DS-GA-flex-shrink-0 DS-GA-gap-1', children: sourceList.map((item) => { const { uid, name, type, percent, error } = item; const { suf, color, icon } = getFileTypeIcon(type, name); return (name !== '' && (_jsx(Tooltip, { title: name, children: _jsxs("div", { className: classNames('DS-GA-relative DS-GA-group DS-GA-w-20 DS-GA-h-20 DS-GA-rounded-md DS-GA-rounded-b-none DS-GA-overflow-hidden', 'DS-GA-flex DS-GA-flex-col DS-GA-justify-between DS-GA-items-center', 'hover:DS-GA-bg-theme-shal-2'), children: [_jsx("div", { className: 'DS-GA-max-w-[80%] DS-GA-w-fit DS-GA-text-base DS-GA-leading-[70px] DS-GA-text-text-deep-7 o-text', children: getFileName(name) }), suf && (_jsx("span", { className: classNames('DS-GA-text-xs DS-GA-tracking-tighter DS-GA-font-medium DS-GA-opacity-60', `${color}`), children: suf })), _jsx("i", { className: classNames('DS-GA-absolute DS-GA-top-0 DS-GA-left-[-3px] DS-GA-text-[86px] DS-GA-w-full DS-GA-h-full iconfont-assistant DS-GA-opacity-40', `icon-${icon} ${color}`) }), _jsx("i", { className: classNames('DS-GA-invisible group-hover:DS-GA-visible', 'iconfont-assistant icon-del DS-GA-text-xxs', 'DS-GA-absolute DS-GA--top-4 DS-GA--right-4 DS-GA-w-8 DS-GA-h-8 DS-GA-p-0 DS-GA-pl-[6px] DS-GA-leading-[45px] DS-GA-rounded-full', 'DS-GA-bg-theme-deep-3 DS-GA-text-zinc-400 hover:DS-GA-text-zinc-500 DS-GA-cursor-pointer'), onClick: () => { const _nlist = sourceList.filter((_item) => _item.uid !== uid); setSourceList(_nlist); MyOnFileChange('delete', _nlist); } })] }, uid) }, uid))); }) })), _jsxs("div", { className: 'DS-GA-w-full DS-GA-flex DS-GA-my-2', children: [_jsx(Input, { disabled: isDis, ref: inputRef, size: 20, autoSize: true, maxRows: 4, placeholder: myPlaceholder || t('sendToAssistant'), onChange: debounce((v, ev) => (setHasText(v !== ''), onInputValueChange(v, ev)), 200), className: classNames('DS-GA-grow DS-GA-border-0 DS-GA-no-scrollbar DS-GA-bg-area-mode DS-GA-text-text-deep-9', isDis ? 'DS-GA-cursor-not-allowed' : '', !isDis && isFullScreenInput ? 'DS-GA-z-50 DS-GA-fixed DS-GA-top-0 DS-GA-left-0 DS-GA-pt-8 DS-GA-w-screen DS-GA-h-screen' : '') }), hasText && !isDis && (_jsx("div", { className: 'DS-GA-self-center DS-GA-h-4 DS-GA-w-4 DS-GA-mr-[2px] DS-GA-flex DS-GA-text-text-reverse-9 DS-GA-bg-zinc-300 hover:DS-GA-bg-zinc-400 DS-GA-rounded-full DS-GA-cursor-pointer', onClick: () => setText(''), children: _jsx(Tooltip, { title: t('clearText'), children: _jsx("i", { className: 'iconfont-assistant icon-del DS-GA-text-xxs DS-GA-m-auto' }) }) })), myMediaStream && !isToText && toTextErr === '' && (_jsxs("div", { className: 'DS-GA-pointer-events-none DS-GA-absolute DS-GA-w-full DS-GA-h-full DS-GA-top-0 DS-GA-left-0 DS-GA-rounded-lg DS-GA-overflow-hidden', children: [timeWarning !== '' && (_jsx("div", { className: 'DS-GA-absolute DS-GA-top-1/2 DS-GA-left-0 DS-GA-w-full DS-GA-h-full DS-GA-text-xs DS-GA-text-red-400 DS-GA-text-center', children: timeWarning })), _jsx(StreamWave, { className: 'DS-GA-absolute DS-GA-top-1/2 DS-GA-left-0 DS-GA-w-full DS-GA-h-full DS-GA-text-theme-shal-8', color: 'DS-GA-text-theme-shal-8', stream: myMediaStream })] }))] }), _jsx(ComposerCitationContent, {}), _jsxs("div", { className: 'composer-icon DS-GA-w-full DS-GA-rounded-b-lg DS-GA-relative DS-GA-flex DS-GA-justify-between DS-GA-items-end DS-GA-align-middle', children: [_jsxs("div", { className: 'DS-GA-flex DS-GA-justify-center DS-GA-items-center DS-GA-gap-2 DS-GA-text-theme-shal-7', children: [_jsx("i", { onClick: () => (setIsFullScreenInput(!isFullScreenInput), !isFullScreenInput && inputRef && inputRef.current && inputRef.current.focus()), className: classNames('md:DS-GA-hidden', myInputRows > 1 ? 'DS-GA-visible' : 'DS-GA-hidden', isFullScreenInput ? 'DS-GA-z-[51] DS-GA-w-screen DS-GA-h-6 DS-GA-pl-4 DS-GA-fixed DS-GA-top-0 DS-GA-left-0 DS-GA-bg-text-reverse-10' : 'DS-GA-top-[10px] DS-GA-left-[6px]'), children: _jsx(Tooltip, { title: isFullScreenInput ? t('exitfull') : t('fullscreen'), place: 'top', children: _jsx("span", { className: classNames('DS-GA-block iconfont-assistant DS-GA-text-lg DS-GA-text-text-deep-8 hover:DS-GA-text-theme-shal-9', isFullScreenInput ? 'DS-GA-absolute icon-down' : 'icon-up') }) }) }), GlobalCtxs && Array.isArray(operateLeftCustomIcon) && operateLeftCustomIcon.length > 0 && operateLeftCustomIcon.map((RenderIcon, _index) => _jsx(RenderIcon, { ctx: GlobalCtxs }, _index))] }), _jsxs("div", { className: 'DS-GA-flex DS-GA-justify-center DS-GA-items-center DS-GA-gap-2 DS-GA-text-theme-shal-7', children: [GlobalCtxs && Array.isArray(operateRightCustomIcon) && operateRightCustomIcon.length > 0 && operateRightCustomIcon.map((RenderIcon, _index) => _jsx(RenderIcon, { ctx: GlobalCtxs }, _index)), myAllowUpload && (_jsx(Tooltip, { delayHide: 350, delayShow: 350, noArrow: true, className: classNames('DS-GA--ml-3 DS-GA-border-solid DS-GA-border-gray-300 DS-GA-border-[1px] !DS-GA-bg-text-reverse-10'), offset: 15, place: 'top-start', variant: 'light', openOnClick: true, title: _jsxs("div", { className: 'DS-GA-w-72 DS-GA-p-1 DS-GA-flex DS-GA-flex-col DS-GA-justify-center DS-GA-items-center', children: [_jsx("div", { ref: fileUrlListRef, className: 'DS-GA-w-full DS-GA-h-fit DS-GA-max-h-60 DS-GA-overflow-y-auto DS-GA-flex DS-GA-flex-col DS-GA-justify-items-center DS-GA-items-end gap-1', children: sourceList.map((_web, _ind) => { const { uid: thisUid, response: thisResponse, name, percent, error } = _web; const _numLimit = myUploadProps.multiple === true ? myUploadProps.maxNumber : 1; const _realyNum = sourceList.filter((e) => e.name !== '').length; const _restNum = Number(_numLimit - _realyNum); const _allowAdd = _realyNum < _numLimit && sourceList.length < _numLimit; const _hasErr = !!error; return (_jsxs("div", { className: 'DS-GA-w-full DS-GA-flex DS-GA-flex-col', children: [_jsxs("div", { className: classNames('DS-GA-w-full DS-GA-p-1 DS-GA-flex DS-GA-items-center DS-GA-gap-1 DS-GA-rounded-xl', 'DS-GA-border DS-GA-border-theme-shal-3 hover:DS-GA-border-theme-shal-6 DS-GA-relative', _hasErr ? '!DS-GA-border-red-500 !hover:DS-GA-border-red-500' : ''), children: [_jsx(Progress, { value: percent, status: percent < 100 ? 'active' : 'success', className: classNames('DS-GA-opacity-25 DS-GA-absolute DS-GA-h-full DS-GA-left-0 DS-GA-right-0 DS-GA-top-0 DS-GA-bottom-0 DS-GA-rounded-[inherit] DS-GA-bg-transparent', !percent || percent >= 100 ? 'DS-GA-hidden' : '') }), _jsx(Input, { id: thisUid, placeholder: t('uploadPlaceholder'), className: 'DS-GA-p-0 DS-GA-pl-1 DS-GA-text-xs DS-GA-border-none', defaultValue: thisResponse?.data || thisResponse || name, onChange: debounce(_wv => { const _thisInfo = { response: _wv, type: 'url', error: '' }; const _newlist = sourceList.map((_e) => (_e.uid === thisUid ? Object.assign({}, _e, _thisInfo) : _e)); setSourceList(_newlist); MyOnFileChange('success', _newlist); }, 500) }), thisResponse && thisResponse.toString().replace(/ /g, '') !== '' && (_jsx("i", { className: 'iconfont-assistant icon-del DS-GA-self-center DS-GA-w-4 DS-GA-h-4 DS-GA-px-1 DS-GA-py-0 DS-GA-text-xxs DS-GA-leading-4 DS-GA-text-text-reverse-9 DS-GA-bg-zinc-300 hover:DS-GA-bg-zinc-400 DS-GA-rounded-full', onClick: () => { const _inpdom = document.getElementById(thisUid); _inpdom.value = ''; const _thisInfo = { response: '', name: '', error: '' }; const _newlist = sourceList.map((_e) => (_e.uid === thisUid ? Object.assign({}, _e, _thisInfo) : _e)); setSourceList(_newlist); MyOnFileChange('change', _newlist); } })), (sourceList.length === 1 || sourceList.length === _ind + 1) && myUploadProps.multiple && (_jsx("span", { className: classNames('DS-GA-px-1 DS-GA-mr-1 iconfont-assistant icon-add DS-GA-text-xxs DS-GA-leading-4 DS-GA-rounded-full DS-GA-bg-theme-deep-8 DS-GA-text-text-reverse-9 hover:DS-GA-bg-theme-deep-9', _allowAdd ? '' : 'DS-GA-cursor-not-allowed'), onClick: () => { if (!_allowAdd) return; let _newCache = sourceList.concat(getNewFileItem()); setSourceList(_newCache); setTimeout(() => { const lastElementChild = fileUrlListRef.current?.lastElementChild; lastElementChild?.scrollIntoView({ behavior: 'smooth', block: 'end' }); lastElementChild.querySelector('input').focus(); }, 0); } })), sourceList.length !== 1 && sourceList.length !== _ind + 1 && (_jsx("span", { className: 'DS-GA-px-1 DS-GA-mr-1 iconfont-assistant icon-minus DS-GA-text-xxs DS-GA-leading-4 DS-GA-rounded-full DS-GA-bg-red-500 DS-GA-text-text-reverse-9 hover:DS-GA-bg-red-600', onClick: () => { const _nlist = sourceList.filter((_e) => _e.uid !== thisUid); setSourceList(_nlist); MyOnFileChange('delete', _nlist); } }))] }), _hasErr && _jsx("span", { className: 'DS-GA-pl-1 DS-GA-self-start o-text DS-GA-text-xs DS-GA-text-red-500', children: getErrorTip(error.toString()) })] }, RandomString())); }) }), _jsx(Divider, { className: 'DS-GA-w-full', children: "OR" }), _jsx(Upload, { className: classNames('DS-GA-grow-0 DS-GA-w-fit', sourceList.filter((e) => e.name !== '').length < (myUploadProps.multiple === true ? myUploadProps.maxNumber : 1) ? '' : 'DS-GA-cursor-not-allowed'), openFileDialogOnClick: sourceList.filter((e) => e.name !== '').length < (myUploadProps.multiple === true ? myUploadProps.maxNumber : 1), beforeUpload: onBeforeUpload, onBatchStart: onBatchStart, onSuccess: onSuccess, onProgress: onProgress, onError: onError, ...myUploadProps, children: _jsx("span", { className: 'DS-GA-p-2 DS-GA-text-xs DS-GA-rounded-lg DS-GA-bg-theme-deep-8 DS-GA-text-text-reverse-9 hover:DS-GA-bg-theme-deep-9', children: t('upload') }) }), _jsxs("div", { className: 'DS-GA-self-start DS-GA-w-full DS-GA-mt-4 DS-GA-text-xs DS-GA-text-left DS-GA-flex DS-GA-flex-col DS-GA-gap-1', children: [_jsx("div", { className: 'DS-GA-w-full DS-GA-w-max-full DS-GA-flex DS-GA-justify-between', children: (() => { const _numLimit = myUploadProps.multiple === true ? myUploadProps.maxNumber : 1; const _realyNum = sourceList.filter((e) => e.name !== '').length; return (_jsxs(_Fragment, { children: [_jsx("p", { className: 'DS-GA-grow o-text DS-GA-inline-flex', children: t('fileNumberLimit', { limit: _numLimit }).split(':').map((_t, _i) => _jsx("span", { className: classNames('DS-GA-py-1 DS-GA-px-2 DS-GA-rounded-md', _i === 0 ? 'DS-GA-w-fit DS-GA-bg-theme-shal-1' : ''), children: _t }, _i)) }), _jsxs("span", { className: classNames('DS-GA-w-fit DS-GA-flex', _realyNum > _numLimit ? 'DS-GA-text-amber-400' : 'DS-GA-text-theme-shal-9'), children: [uploadErrorMessage !== '' && _jsx(Tooltip, { isOpen: uploadErrorMessage !== '', afterShow: () => setTimeout(() => { setUploadErrorMessage(''); }, 5000), className: '!DS-GA-text-red-500', title: t(uploadErrorMessage), children: _jsx(IoIosWarning, { className: 'DS-GA-text-red-500 DS-GA-text-base', onMouseLeave: () => setUploadErrorMessage('') }) }), "(", _realyNum, "/", _numLimit, ")"] })] })); })() }), _jsx("p", { className: 'DS-GA-w-full DS-GA-w-max-full DS-GA-flex', children: t('fileBytesLimit', { limit: getFileGeneralSize(myUploadProps.maxByte) }).split(':').map((_t, _i) => _jsx("span", { className: classNames('DS-GA-py-1 DS-GA-px-2 DS-GA-rounded-md', _i === 0 ? 'DS-GA-w-fit DS-GA-bg-theme-shal-1' : ''), children: _t }, _i)) }), _jsx("p", { className: 'DS-GA-w-full DS-GA-w-max-full DS-GA-flex', children: t('fileTypeLimit', { limit: myUploadProps.accept.toString().replace(/,/g, ' ') || t('unlimited') }).split(':').map((_t, _i) => _i === 0 ? _jsx("span", { className: 'DS-GA-py-1 DS-GA-px-2 DS-GA-rounded-md DS-GA-w-fit DS-GA-h-fit DS-GA-min-w-16 DS-GA-bg-theme-shal-1', children: _t }, _i) : _jsx(Tooltip, { className: '!DS-GA-whitespace-normal !DS-GA-max-w-full', title: _t, children: _jsx("span", { className: 'DS-GA-py-1 DS-GA-px-2 DS-GA-rounded-sm DS-GA-grow', children: _t }, _i) }, _i)) })] })] }), children: _jsx("i", { className: classNames('iconfont-assistant icon-upload DS-GA-text-text-deep-9 DS-GA-text-2xl DS-GA-cursor-pointer') }) })), !isMobile && myAllowVoice && !hasText && !isDis && (_jsx(Tooltip, { title: t('voiceStart'), children: _jsx("i", { className: 'iconfont-assistant DS-GA-text-xl icon-mic hover:DS-GA-text-theme-shal-10', onClick: dealVioceStart }) })), !isMobile && myAllowVoice && myMediaStream && isDis && !isToText && toTextErr === '' && (_jsx(Tooltip, { title: t('voiceStop'), children: _jsx("i", { className: classNames('iconfont-assistant icon-stop DS-GA-mb-1 DS-GA-p-1 DS-GA-text-xs DS-GA-w-5 DS-GA-h-5 !DS-GA-leading-3 DS-GA-rounded-xl DS-GA-text-white DS-GA-bg-neutral-800 hover:DS-GA-bg-black', isToText ? 'DS-GA-cursor-not-allowed' : ''), onClick: isToText ? null : dealVioceEnd }) })), myAllowVoice && toTextErr !== '' && (_jsx(Tooltip, { title: t('voiceReToText'), children: _jsx("i", { className: 'iconfont-assistant icon-fresh DS-GA-text-lg hover:DS-GA-text-theme-shal-10', onClick: dealAllSpeechToText }) })), myAllowVoice && (isToText || toTextErr !== '') && (_jsx(Tooltip, { title: t('voiceCancelToText'), children: _jsx("i", { className: 'iconfont-assistant icon-del DS-GA-text-sm DS-GA-text-zinc-400 hover:DS-GA-text-zinc-500', onClick: stopToText }) })), isMobile && myAllowVoice && pattern !== 'stop' && (!hasText || (isDis && myMediaStream && !isToText && toTextErr === '')) && (_jsx(Tooltip, { title: t('voiceLongStart'), children: _jsx("i", { className: 'iconfont-assistant DS-GA-text-xl icon-mic hover:DS-GA-text-theme-shal-10', onTouchStart: dealVioceStart, onTouchEnd: dealVioceEnd, onTouchMove: dealVioceEnd, onTouchCancel: dealVioceEnd }) })), hasText && !isDis && (_jsx(Tooltip, { title: t('sendText'), children: _jsx("i", { className: 'iconfont-assistant icon-send DS-GA-text-xl hover:DS-GA-text-theme-shal-10', onClick: handleSend }) })), pattern === 'stop' && (_jsx(Tooltip, { title: t('interrupt'), children: _jsx("i", { className: 'iconfont-assistant icon-stop DS-GA-text-2xl DS-GA-bg-neutral-800 DS-GA-text-white DS-GA-w-8 DS-GA-h-8 DS-GA-line-8 DS-GA-rounded-2xl DS-GA-text-center', onClick: handleBreak }) }))] })] })] })] }), _jsx(ComposerCautionContent, { search: myCautionSearch, inputRef: inputRef, cancel: () => (setSelectedAite(confirmAite), setShowAite(false)), confirm: (_opt) => (setShowAite(false), replaceStr()) })] })); }); export default InputComposer;