mirror of
https://github.com/farcasclaudiu/Flowise.git
synced 2026-06-29 09:01:06 +03:00
Update audio recording ui in internal chat
This commit is contained in:
@@ -23,7 +23,7 @@ import {
|
|||||||
Typography
|
Typography
|
||||||
} from '@mui/material'
|
} from '@mui/material'
|
||||||
import { useTheme } from '@mui/material/styles'
|
import { useTheme } from '@mui/material/styles'
|
||||||
import { IconDownload, IconSend, IconMicrophone, IconPhotoPlus, IconCircleDot, IconTrash } from '@tabler/icons'
|
import { IconCircleDot, IconDownload, IconSend, IconMicrophone, IconPhotoPlus, IconSquare, IconTrash, IconX } from '@tabler/icons'
|
||||||
import robotPNG from 'assets/images/robot.png'
|
import robotPNG from 'assets/images/robot.png'
|
||||||
import userPNG from 'assets/images/account.png'
|
import userPNG from 'assets/images/account.png'
|
||||||
import audioUploadSVG from 'assets/images/wave-sound.jpg'
|
import audioUploadSVG from 'assets/images/wave-sound.jpg'
|
||||||
@@ -608,41 +608,6 @@ export const ChatMessage = ({ open, chatflowid, isDialog }) => {
|
|||||||
})}
|
})}
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
{isRecording && (
|
|
||||||
<Box className='drop-overlay'>
|
|
||||||
<div className={'audio-recording-container'}>
|
|
||||||
<Typography variant='h2'>Recording</Typography>
|
|
||||||
<div className='recording-control-buttons-container'>
|
|
||||||
<i className='cancel-recording-button'>
|
|
||||||
<Button variant='outlined' color='error' onClick={onRecordingCancelled}>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
</i>
|
|
||||||
<div className='recording-elapsed-time'>
|
|
||||||
<i className='red-recording-dot'>
|
|
||||||
<IconCircleDot />
|
|
||||||
</i>
|
|
||||||
<p id='elapsed-time'>00:00</p>
|
|
||||||
</div>
|
|
||||||
<i className='stop-recording-button'>
|
|
||||||
<Button variant='outlined' color='primary' onClick={onRecordingStopped}>
|
|
||||||
Send
|
|
||||||
</Button>
|
|
||||||
</i>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{recordingNotSupported && (
|
|
||||||
<div className='overlay hide'>
|
|
||||||
<div className='browser-not-supporting-audio-recording-box'>
|
|
||||||
<p>To record audio, use browsers like Chrome and Firefox that support audio recording.</p>
|
|
||||||
<button type='button' onClick={() => onRecordingCancelled()}>
|
|
||||||
Ok.
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</Box>
|
|
||||||
)}
|
|
||||||
<div className={`${isDialog ? 'cloud-dialog' : 'cloud'}`}>
|
<div className={`${isDialog ? 'cloud-dialog' : 'cloud'}`}>
|
||||||
<div ref={ps} id='messagelist' className={'messagelist'}>
|
<div ref={ps} id='messagelist' className={'messagelist'}>
|
||||||
{messages &&
|
{messages &&
|
||||||
@@ -829,6 +794,8 @@ export const ChatMessage = ({ open, chatflowid, isDialog }) => {
|
|||||||
<Divider />
|
<Divider />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<Divider sx={{ width: '100%' }} />
|
||||||
|
|
||||||
<div className='center'>
|
<div className='center'>
|
||||||
{previews && previews.length > 0 && (
|
{previews && previews.length > 0 && (
|
||||||
<Box sx={{ width: '100%', mb: 1.5 }}>
|
<Box sx={{ width: '100%', mb: 1.5 }}>
|
||||||
@@ -882,70 +849,129 @@ export const ChatMessage = ({ open, chatflowid, isDialog }) => {
|
|||||||
))}
|
))}
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
<form style={{ width: '100%' }} onSubmit={handleSubmit}>
|
{isRecording ? (
|
||||||
<OutlinedInput
|
<>
|
||||||
inputRef={inputRef}
|
{recordingNotSupported && (
|
||||||
// eslint-disable-next-line
|
<div className='overlay hide'>
|
||||||
autoFocus
|
<div className='browser-not-supporting-audio-recording-box'>
|
||||||
sx={{ width: '100%' }}
|
<p>To record audio, use modern browsers like Chrome or Firefox that support audio recording.</p>
|
||||||
disabled={loading || !chatflowid}
|
<Button
|
||||||
onKeyDown={handleEnter}
|
variant='contained'
|
||||||
id='userInput'
|
color='error'
|
||||||
name='userInput'
|
size='small'
|
||||||
placeholder={loading ? 'Waiting for response...' : 'Type your question...'}
|
type='button'
|
||||||
value={userInput}
|
onClick={() => onRecordingCancelled()}
|
||||||
onChange={onChange}
|
>
|
||||||
multiline={true}
|
Okay
|
||||||
maxRows={isDialog ? 7 : 2}
|
</Button>
|
||||||
startAdornment={
|
</div>
|
||||||
isChatFlowAvailableForUploads && (
|
</div>
|
||||||
<InputAdornment position='start' sx={{ pl: 2 }}>
|
)}
|
||||||
<IconButton onClick={handleUploadClick} type='button' disabled={loading || !chatflowid} edge='start'>
|
<Box
|
||||||
<IconPhotoPlus
|
sx={{
|
||||||
color={loading || !chatflowid ? '#9e9e9e' : customization.isDarkMode ? 'white' : '#1e88e5'}
|
width: '100%',
|
||||||
/>
|
height: '54px',
|
||||||
</IconButton>
|
px: 2,
|
||||||
</InputAdornment>
|
borderRadius: 1.5,
|
||||||
)
|
backgroundColor: '#32353b',
|
||||||
}
|
display: 'flex',
|
||||||
endAdornment={
|
alignItems: 'center',
|
||||||
<>
|
justifyContent: 'space-between'
|
||||||
{isChatFlowAvailableForUploads && (
|
}}
|
||||||
<InputAdornment position='end'>
|
>
|
||||||
|
<div className='recording-elapsed-time'>
|
||||||
|
<i className='red-recording-dot'>
|
||||||
|
<IconCircleDot />
|
||||||
|
</i>
|
||||||
|
<p id='elapsed-time'>00:00</p>
|
||||||
|
</div>
|
||||||
|
<div className='recording-control-buttons-container'>
|
||||||
|
<IconButton onClick={onRecordingCancelled} size='small'>
|
||||||
|
<IconX color={loading || !chatflowid ? '#9e9e9e' : customization.isDarkMode ? 'white' : '#1e88e5'} />
|
||||||
|
</IconButton>
|
||||||
|
<IconButton onClick={onRecordingStopped} size='small'>
|
||||||
|
<IconSquare
|
||||||
|
color={loading || !chatflowid ? '#9e9e9e' : customization.isDarkMode ? 'white' : '#1e88e5'}
|
||||||
|
/>
|
||||||
|
</IconButton>
|
||||||
|
</div>
|
||||||
|
</Box>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<form style={{ width: '100%' }} onSubmit={handleSubmit}>
|
||||||
|
<OutlinedInput
|
||||||
|
inputRef={inputRef}
|
||||||
|
// eslint-disable-next-line
|
||||||
|
autoFocus
|
||||||
|
sx={{ width: '100%' }}
|
||||||
|
disabled={loading || !chatflowid}
|
||||||
|
onKeyDown={handleEnter}
|
||||||
|
id='userInput'
|
||||||
|
name='userInput'
|
||||||
|
placeholder={loading ? 'Waiting for response...' : 'Type your question...'}
|
||||||
|
value={userInput}
|
||||||
|
onChange={onChange}
|
||||||
|
multiline={true}
|
||||||
|
maxRows={isDialog ? 7 : 2}
|
||||||
|
startAdornment={
|
||||||
|
isChatFlowAvailableForUploads && (
|
||||||
|
<InputAdornment position='start' sx={{ pl: 2 }}>
|
||||||
<IconButton
|
<IconButton
|
||||||
onClick={() => onMicrophonePressed()}
|
onClick={handleUploadClick}
|
||||||
type='button'
|
type='button'
|
||||||
disabled={loading || !chatflowid}
|
disabled={loading || !chatflowid}
|
||||||
edge='end'
|
edge='start'
|
||||||
>
|
>
|
||||||
<IconMicrophone
|
<IconPhotoPlus
|
||||||
className={'start-recording-button'}
|
|
||||||
color={loading || !chatflowid ? '#9e9e9e' : customization.isDarkMode ? 'white' : '#1e88e5'}
|
color={loading || !chatflowid ? '#9e9e9e' : customization.isDarkMode ? 'white' : '#1e88e5'}
|
||||||
/>
|
/>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</InputAdornment>
|
</InputAdornment>
|
||||||
)}
|
)
|
||||||
<InputAdornment position='end' sx={{ padding: '15px' }}>
|
}
|
||||||
<IconButton type='submit' disabled={loading || !chatflowid} edge='end'>
|
endAdornment={
|
||||||
{loading ? (
|
<>
|
||||||
<div>
|
{isChatFlowAvailableForUploads && (
|
||||||
<CircularProgress color='inherit' size={20} />
|
<InputAdornment position='end'>
|
||||||
</div>
|
<IconButton
|
||||||
) : (
|
onClick={() => onMicrophonePressed()}
|
||||||
// Send icon SVG in input field
|
type='button'
|
||||||
<IconSend
|
disabled={loading || !chatflowid}
|
||||||
color={loading || !chatflowid ? '#9e9e9e' : customization.isDarkMode ? 'white' : '#1e88e5'}
|
edge='end'
|
||||||
/>
|
>
|
||||||
)}
|
<IconMicrophone
|
||||||
</IconButton>
|
className={'start-recording-button'}
|
||||||
</InputAdornment>
|
color={
|
||||||
</>
|
loading || !chatflowid ? '#9e9e9e' : customization.isDarkMode ? 'white' : '#1e88e5'
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
{isChatFlowAvailableForUploads && (
|
</IconButton>
|
||||||
<input style={{ display: 'none' }} multiple ref={fileUploadRef} type='file' onChange={handleFileChange} />
|
</InputAdornment>
|
||||||
)}
|
)}
|
||||||
</form>
|
<InputAdornment position='end' sx={{ padding: '15px' }}>
|
||||||
|
<IconButton type='submit' disabled={loading || !chatflowid} edge='end'>
|
||||||
|
{loading ? (
|
||||||
|
<div>
|
||||||
|
<CircularProgress color='inherit' size={20} />
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
// Send icon SVG in input field
|
||||||
|
<IconSend
|
||||||
|
color={
|
||||||
|
loading || !chatflowid ? '#9e9e9e' : customization.isDarkMode ? 'white' : '#1e88e5'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</IconButton>
|
||||||
|
</InputAdornment>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
{isChatFlowAvailableForUploads && (
|
||||||
|
<input style={{ display: 'none' }} multiple ref={fileUploadRef} type='file' onChange={handleFileChange} />
|
||||||
|
)}
|
||||||
|
</form>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<SourceDocDialog show={sourceDialogOpen} dialogProps={sourceDialogProps} onCancel={() => setSourceDialogOpen(false)} />
|
<SourceDocDialog show={sourceDialogOpen} dialogProps={sourceDialogProps} onCancel={() => setSourceDialogOpen(false)} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,20 +8,6 @@
|
|||||||
* {
|
* {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
.audio-recording-container {
|
|
||||||
width: 100%;
|
|
||||||
/* view port height*/
|
|
||||||
/*targeting Chrome & Safari*/
|
|
||||||
display: -webkit-flex;
|
|
||||||
/*targeting IE10*/
|
|
||||||
display: -ms-flex;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
/*horizontal centering*/
|
|
||||||
align-items: center;
|
|
||||||
background-color: white;
|
|
||||||
}
|
|
||||||
.start-recording-button {
|
.start-recording-button {
|
||||||
font-size: 70px;
|
font-size: 70px;
|
||||||
color: #435f7a;
|
color: #435f7a;
|
||||||
@@ -36,34 +22,13 @@
|
|||||||
/*targeting IE10*/
|
/*targeting IE10*/
|
||||||
display: -ms-flex;
|
display: -ms-flex;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-evenly;
|
justify-content: center;
|
||||||
/*horizontal centering*/
|
/*horizontal centering*/
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 334px;
|
gap: 12px;
|
||||||
margin-bottom: 30px;
|
|
||||||
background-color: white;
|
|
||||||
}
|
|
||||||
.cancel-recording-button,
|
|
||||||
.stop-recording-button {
|
|
||||||
font-size: 70px;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
.cancel-recording-button {
|
|
||||||
color: red;
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
|
||||||
.cancel-recording-button:hover {
|
|
||||||
color: rgb(206, 4, 4);
|
|
||||||
}
|
|
||||||
.stop-recording-button {
|
|
||||||
color: #33cc33;
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
|
||||||
.stop-recording-button:hover {
|
|
||||||
color: #27a527;
|
|
||||||
}
|
}
|
||||||
.recording-elapsed-time {
|
.recording-elapsed-time {
|
||||||
font-size: 32px;
|
font-size: 16px;
|
||||||
/*targeting Chrome & Safari*/
|
/*targeting Chrome & Safari*/
|
||||||
display: -webkit-flex;
|
display: -webkit-flex;
|
||||||
/*targeting IE10*/
|
/*targeting IE10*/
|
||||||
@@ -73,6 +38,15 @@
|
|||||||
/*horizontal centering*/
|
/*horizontal centering*/
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
.recording-elapsed-time #elapsed-time {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.recording-indicator-wrapper {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
}
|
||||||
.red-recording-dot {
|
.red-recording-dot {
|
||||||
font-size: 25px;
|
font-size: 25px;
|
||||||
color: red;
|
color: red;
|
||||||
@@ -136,17 +110,11 @@
|
|||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.elapsed-time {
|
|
||||||
font-size: 32px;
|
|
||||||
}
|
|
||||||
.recording-control-buttons-container.hide {
|
.recording-control-buttons-container.hide {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
.overlay {
|
.overlay {
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: rgba(82, 76, 76, 0.35);
|
|
||||||
/*targeting Chrome & Safari*/
|
/*targeting Chrome & Safari*/
|
||||||
display: -webkit-flex;
|
display: -webkit-flex;
|
||||||
/*targeting IE10*/
|
/*targeting IE10*/
|
||||||
@@ -155,6 +123,7 @@
|
|||||||
justify-content: center;
|
justify-content: center;
|
||||||
/*horizontal centering*/
|
/*horizontal centering*/
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
margin-bottom: 12px;
|
||||||
}
|
}
|
||||||
.overlay.hide {
|
.overlay.hide {
|
||||||
display: none;
|
display: none;
|
||||||
@@ -165,16 +134,15 @@
|
|||||||
/*targeting IE10*/
|
/*targeting IE10*/
|
||||||
display: -ms-flex;
|
display: -ms-flex;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
/*horizontal centering*/
|
/*horizontal centering*/
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 317px;
|
width: 100%;
|
||||||
height: 119px;
|
|
||||||
background-color: white;
|
|
||||||
border-radius: 10px;
|
|
||||||
padding: 15px;
|
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
.browser-not-supporting-audio-recording-box > p {
|
||||||
|
margin: 0;
|
||||||
}
|
}
|
||||||
.close-browser-not-supported-box {
|
.close-browser-not-supported-box {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -219,16 +187,16 @@
|
|||||||
-o-animation-iteration-count: infinite;
|
-o-animation-iteration-count: infinite;
|
||||||
}
|
}
|
||||||
.text-indication-of-audio-playing span:nth-child(2) {
|
.text-indication-of-audio-playing span:nth-child(2) {
|
||||||
animation-delay: .4s;
|
animation-delay: 0.4s;
|
||||||
-webkit-animation-delay: .4s;
|
-webkit-animation-delay: 0.4s;
|
||||||
-moz-animation-delay: .4s;
|
-moz-animation-delay: 0.4s;
|
||||||
-o-animation-delay: .4s;
|
-o-animation-delay: 0.4s;
|
||||||
}
|
}
|
||||||
.text-indication-of-audio-playing span:nth-child(3) {
|
.text-indication-of-audio-playing span:nth-child(3) {
|
||||||
animation-delay: .8s;
|
animation-delay: 0.8s;
|
||||||
-webkit-animation-delay: .8s;
|
-webkit-animation-delay: 0.8s;
|
||||||
-moz-animation-delay: .8s;
|
-moz-animation-delay: 0.8s;
|
||||||
-o-animation-delay: .8s;
|
-o-animation-delay: 0.8s;
|
||||||
}
|
}
|
||||||
/* The animation code */
|
/* The animation code */
|
||||||
@keyframes blinking-dot {
|
@keyframes blinking-dot {
|
||||||
@@ -278,4 +246,4 @@
|
|||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user