chore: stt player ui
This commit is contained in:
Generated
+4
-28
@@ -4894,7 +4894,7 @@ packages:
|
||||
dependencies:
|
||||
'@babel/core': 7.24.5
|
||||
postcss: 7.0.39
|
||||
postcss-syntax: 0.36.2(postcss@7.0.39)
|
||||
postcss-syntax: 0.36.2(postcss@8.4.38)
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
dev: false
|
||||
@@ -4935,7 +4935,7 @@ packages:
|
||||
postcss-syntax: '>=0.36.2'
|
||||
dependencies:
|
||||
postcss: 7.0.39
|
||||
postcss-syntax: 0.36.2(postcss@7.0.39)
|
||||
postcss-syntax: 0.36.2(postcss@8.4.38)
|
||||
remark: 13.0.0
|
||||
unist-util-find-all-after: 3.0.2
|
||||
transitivePeerDependencies:
|
||||
@@ -14301,7 +14301,7 @@ packages:
|
||||
dependencies:
|
||||
htmlparser2: 3.10.1
|
||||
postcss: 7.0.39
|
||||
postcss-syntax: 0.36.2(postcss@7.0.39)
|
||||
postcss-syntax: 0.36.2(postcss@8.4.38)
|
||||
dev: false
|
||||
|
||||
/postcss-image-set-function@4.0.7(postcss@8.4.38):
|
||||
@@ -14775,30 +14775,6 @@ packages:
|
||||
lodash: 4.17.21
|
||||
postcss: 8.4.38
|
||||
|
||||
/postcss-syntax@0.36.2(postcss@7.0.39):
|
||||
resolution: {integrity: sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==}
|
||||
peerDependencies:
|
||||
postcss: '>=5.0.0'
|
||||
postcss-html: '*'
|
||||
postcss-jsx: '*'
|
||||
postcss-less: '*'
|
||||
postcss-markdown: '*'
|
||||
postcss-scss: '*'
|
||||
peerDependenciesMeta:
|
||||
postcss-html:
|
||||
optional: true
|
||||
postcss-jsx:
|
||||
optional: true
|
||||
postcss-less:
|
||||
optional: true
|
||||
postcss-markdown:
|
||||
optional: true
|
||||
postcss-scss:
|
||||
optional: true
|
||||
dependencies:
|
||||
postcss: 7.0.39
|
||||
dev: false
|
||||
|
||||
/postcss-syntax@0.36.2(postcss@8.4.38):
|
||||
resolution: {integrity: sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==}
|
||||
peerDependencies:
|
||||
@@ -18099,7 +18075,7 @@ packages:
|
||||
postcss-sass: 0.4.4
|
||||
postcss-scss: 2.1.1
|
||||
postcss-selector-parser: 6.0.16
|
||||
postcss-syntax: 0.36.2(postcss@7.0.39)
|
||||
postcss-syntax: 0.36.2(postcss@8.4.38)
|
||||
postcss-value-parser: 4.2.0
|
||||
resolve-from: 5.0.0
|
||||
slash: 3.0.0
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
.player-wrap {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
background-color: var(--ant-color-fill-quaternary);
|
||||
// background-color: var(--ant-color-fill-quaternary);
|
||||
border-radius: 6px;
|
||||
|
||||
.player-ui {
|
||||
@@ -13,10 +13,10 @@
|
||||
}
|
||||
|
||||
.controls {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-inline: 10px;
|
||||
}
|
||||
|
||||
.play-btn {
|
||||
@@ -43,7 +43,6 @@
|
||||
|
||||
.slider-inner {
|
||||
flex: 1;
|
||||
margin-inline: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,8 +54,11 @@
|
||||
}
|
||||
|
||||
.time {
|
||||
width: 52px;
|
||||
text-align: right;
|
||||
|
||||
&.current {
|
||||
margin-left: 6px;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +67,7 @@
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
|
||||
.slider {
|
||||
|
||||
@@ -25,6 +25,7 @@ interface AudioPlayerProps {
|
||||
height?: number;
|
||||
width?: number;
|
||||
duration?: number;
|
||||
extra?: React.ReactNode;
|
||||
}
|
||||
|
||||
const speedOptions = [
|
||||
@@ -42,7 +43,7 @@ const speedConfig = {
|
||||
|
||||
const AudioPlayer: React.FC<AudioPlayerProps> = forwardRef((props, ref) => {
|
||||
const intl = useIntl();
|
||||
const { autoplay = false, speed: defaultSpeed = 1 } = props;
|
||||
const { autoplay = false, speed: defaultSpeed = 1, extra } = props;
|
||||
const audioRef = React.useRef<HTMLAudioElement>(null);
|
||||
const [audioState, setAudioState] = React.useState<{
|
||||
currentTime: number;
|
||||
@@ -206,76 +207,89 @@ const AudioPlayer: React.FC<AudioPlayerProps> = forwardRef((props, ref) => {
|
||||
<div className="progress-bar">
|
||||
<span className="file-name">{props.name}</span>
|
||||
<div className="slider">
|
||||
<span className="time current">
|
||||
{/* <span className="time current">
|
||||
{' '}
|
||||
{formatTime(audioState.currentTime)}
|
||||
</span>
|
||||
</span> */}
|
||||
<div className="slider-inner">
|
||||
<Slider
|
||||
tooltip={{ open: false }}
|
||||
min={0}
|
||||
step={1}
|
||||
styles={{
|
||||
rail: {
|
||||
// height: 6
|
||||
}
|
||||
}}
|
||||
max={audioState.duration}
|
||||
value={audioState.currentTime}
|
||||
onChange={handleCurrentChange}
|
||||
/>
|
||||
</div>
|
||||
<span className="time">{formatTime(audioState.duration)}</span>
|
||||
{/* <span className="time">{formatTime(audioState.duration)}</span> */}
|
||||
</div>
|
||||
<div className="controls">
|
||||
<Tooltip
|
||||
title={intl.formatMessage({
|
||||
id: 'playground.audio.button.slow'
|
||||
})}
|
||||
>
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
className="backward"
|
||||
disabled={
|
||||
speed === speedConfig.min || speed < speedConfig.min
|
||||
}
|
||||
onClick={handleReduceSpeed}
|
||||
<div className="audio-control flex-center">
|
||||
<span className="time current">
|
||||
{' '}
|
||||
{formatTime(audioState.currentTime)}
|
||||
</span>
|
||||
<Tooltip
|
||||
title={intl.formatMessage({
|
||||
id: 'playground.audio.button.slow'
|
||||
})}
|
||||
>
|
||||
<FastBackwardOutlined className="font-size-20" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<span className="play-btn">
|
||||
<Button
|
||||
size="middle"
|
||||
type="text"
|
||||
onClick={handlePlay}
|
||||
disabled={!audioState?.duration}
|
||||
icon={
|
||||
!playOn ? (
|
||||
<PlayCircleFilled
|
||||
style={{ fontSize: '22px' }}
|
||||
></PlayCircleFilled>
|
||||
) : (
|
||||
<PauseCircleFilled
|
||||
style={{ fontSize: '22px' }}
|
||||
></PauseCircleFilled>
|
||||
)
|
||||
}
|
||||
></Button>
|
||||
</span>
|
||||
<Tooltip
|
||||
title={intl.formatMessage({
|
||||
id: 'playground.audio.button.fast'
|
||||
})}
|
||||
>
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
className="forward"
|
||||
disabled={
|
||||
speed === speedConfig.max || speed > speedConfig.max
|
||||
}
|
||||
onClick={handleAddSpeed}
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
className="backward"
|
||||
disabled={
|
||||
speed === speedConfig.min || speed < speedConfig.min
|
||||
}
|
||||
onClick={handleReduceSpeed}
|
||||
>
|
||||
<FastBackwardOutlined className="font-size-20" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<span className="play-btn">
|
||||
<Button
|
||||
size="middle"
|
||||
type="text"
|
||||
onClick={handlePlay}
|
||||
disabled={!audioState?.duration}
|
||||
icon={
|
||||
!playOn ? (
|
||||
<PlayCircleFilled
|
||||
style={{ fontSize: '22px' }}
|
||||
></PlayCircleFilled>
|
||||
) : (
|
||||
<PauseCircleFilled
|
||||
style={{ fontSize: '22px' }}
|
||||
></PauseCircleFilled>
|
||||
)
|
||||
}
|
||||
></Button>
|
||||
</span>
|
||||
<Tooltip
|
||||
title={intl.formatMessage({
|
||||
id: 'playground.audio.button.fast'
|
||||
})}
|
||||
>
|
||||
<FastForwardOutlined className="font-size-20" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
className="forward"
|
||||
disabled={
|
||||
speed === speedConfig.max || speed > speedConfig.max
|
||||
}
|
||||
onClick={handleAddSpeed}
|
||||
>
|
||||
<FastForwardOutlined className="font-size-20" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<span className="time">{formatTime(audioState.duration)}</span>
|
||||
</div>
|
||||
{extra}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -139,7 +139,11 @@ const LogsList: React.FC<LogsListProps> = forwardRef((props, ref) => {
|
||||
<div className={classNames('content')}>
|
||||
{_.map(dataList, (item: any, index: number) => {
|
||||
return (
|
||||
<div key={item.uid} className={classNames('text')}>
|
||||
<div
|
||||
key={item.uid}
|
||||
className={classNames('text')}
|
||||
data-uid={item.uid}
|
||||
>
|
||||
{item.content}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -4,6 +4,10 @@ const removeBrackets = (str: string) => {
|
||||
return str?.replace?.(/^\(…\)/, '');
|
||||
};
|
||||
|
||||
const removeBracketsFromLine = (row: string) => {
|
||||
return row.startsWith('(…)') ? row.slice(3) : row;
|
||||
};
|
||||
|
||||
class AnsiParser {
|
||||
private cursorRow: number = 0;
|
||||
private cursorCol: number = 0;
|
||||
@@ -12,6 +16,8 @@ class AnsiParser {
|
||||
private uid: number = 0;
|
||||
private isProcessing: boolean = false;
|
||||
private taskQueue: string[] = [];
|
||||
private page: number = 1;
|
||||
private pageSize: number = 500;
|
||||
private colorMap = {
|
||||
'30': 'black',
|
||||
'31': 'red',
|
||||
@@ -33,6 +39,11 @@ class AnsiParser {
|
||||
this.screen = [['']];
|
||||
this.rawDataRows = 0;
|
||||
this.uid = this.uid + 1;
|
||||
this.page = 1;
|
||||
}
|
||||
|
||||
public setPage(page: number) {
|
||||
this.page = page;
|
||||
}
|
||||
|
||||
private setId() {
|
||||
@@ -125,9 +136,9 @@ class AnsiParser {
|
||||
const remainingText = input.slice(lastIndex);
|
||||
this.handleText(remainingText);
|
||||
|
||||
const result = this.screen.map((row) => ({
|
||||
content: removeBrackets(row.join('')),
|
||||
uid: this.setId()
|
||||
const result = this.screen.map((row, index) => ({
|
||||
content: removeBracketsFromLine(row.join('')),
|
||||
uid: `${this.page}-${index}`
|
||||
}));
|
||||
|
||||
return {
|
||||
@@ -176,7 +187,8 @@ class AnsiParser {
|
||||
const parser = new AnsiParser();
|
||||
|
||||
self.onmessage = function (event) {
|
||||
const { inputStr, reset } = event.data;
|
||||
const { inputStr, reset, page } = event.data;
|
||||
parser.setPage(page);
|
||||
if (reset) {
|
||||
parser.reset();
|
||||
}
|
||||
|
||||
@@ -133,6 +133,7 @@ const LogsViewer: React.FC<LogsViewerProps> = forwardRef((props, ref) => {
|
||||
}
|
||||
logParseWorker.current.postMessage({
|
||||
inputStr: data,
|
||||
page: pageRef.current,
|
||||
reset: clearScreen.current
|
||||
});
|
||||
clearScreen.current = false;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import useSetChunkRequest from '@/hooks/use-chunk-request';
|
||||
import { FitAddon } from '@xterm/addon-fit';
|
||||
import { WebglAddon } from '@xterm/addon-webgl';
|
||||
import { Terminal } from '@xterm/xterm';
|
||||
import '@xterm/xterm/css/xterm.css';
|
||||
import classNames from 'classnames';
|
||||
@@ -126,7 +125,6 @@ const LogsViewer: React.FC<LogsViewerProps> = forwardRef((props, ref) => {
|
||||
});
|
||||
fitAddonRef.current = new FitAddon();
|
||||
termRef.current.loadAddon(fitAddonRef.current);
|
||||
termRef.current.loadAddon(new WebglAddon());
|
||||
termRef.current.open(termwrapRef.current);
|
||||
|
||||
// add event
|
||||
|
||||
@@ -11,6 +11,10 @@
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
b {
|
||||
font-weight: var(--font-weight-bold);
|
||||
}
|
||||
|
||||
h1,
|
||||
h2,
|
||||
h3,
|
||||
@@ -80,6 +84,10 @@
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
img[src^="https://img.shields.io/"], img[src*="badge.svg"]
|
||||
{
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
video {
|
||||
max-width: 100%;
|
||||
|
||||
@@ -45,10 +45,6 @@ const MarkdownViewer: React.FC<MarkdownViewerProps> = ({
|
||||
// 'bibtex'
|
||||
];
|
||||
|
||||
// renderer.link = ({ href, title, text }) => {
|
||||
// return `<a href="${href}" title="${title || ''}" target="_blank" rel="noopener noreferrer">${text}</a>`;
|
||||
// };
|
||||
|
||||
const isValidURL = useCallback((url: string) => {
|
||||
const pattern = /^(https?:\/\/|\/\/)([^\s/$.?#].[^\s]*)$/;
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
export default {};
|
||||
@@ -307,7 +307,7 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
|
||||
{!isRecording && (
|
||||
<UploadAudio
|
||||
type="default"
|
||||
accept={SpeechToTextFormat.join(',')}
|
||||
accept={SpeechToTextFormat.join(', ')}
|
||||
onChange={handleUploadChange}
|
||||
></UploadAudio>
|
||||
)}
|
||||
@@ -322,18 +322,40 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
|
||||
</div>
|
||||
|
||||
{audioData ? (
|
||||
<div
|
||||
className="flex-between flex-center justify-center relative"
|
||||
style={{ paddingInline: 80 }}
|
||||
>
|
||||
<div className="flex-between flex-center justify-center relative">
|
||||
<div style={{ width: 600 }}>
|
||||
<AudioPlayer
|
||||
url={audioData.url}
|
||||
name={audioData.name}
|
||||
duration={audioData.duration}
|
||||
extra={
|
||||
<Tooltip
|
||||
title={
|
||||
loading
|
||||
? intl.formatMessage({
|
||||
id: 'playground.audio.generating'
|
||||
})
|
||||
: intl.formatMessage({
|
||||
id: 'playground.audio.button.generate'
|
||||
})
|
||||
}
|
||||
>
|
||||
{
|
||||
<Button
|
||||
disabled={!audioData}
|
||||
loading={loading}
|
||||
type="primary"
|
||||
size="middle"
|
||||
shape="circle"
|
||||
onClick={handleOnGenerate}
|
||||
icon={<SendOutlined></SendOutlined>}
|
||||
></Button>
|
||||
}
|
||||
</Tooltip>
|
||||
}
|
||||
></AudioPlayer>
|
||||
</div>
|
||||
<div
|
||||
{/* <div
|
||||
style={{
|
||||
padding: '16px',
|
||||
textAlign: 'right',
|
||||
@@ -365,7 +387,7 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
|
||||
></Button>
|
||||
}
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
) : (
|
||||
renderAniamtion()
|
||||
@@ -385,15 +407,14 @@ const GroundLeft: React.FC<MessageProps> = forwardRef((props, ref) => {
|
||||
className="message-list-wrap"
|
||||
style={{
|
||||
flex: 1,
|
||||
position: 'relative',
|
||||
borderTop: '1px solid var(--ant-color-split)'
|
||||
position: 'relative'
|
||||
}}
|
||||
>
|
||||
{messageList?.length > 0 && (
|
||||
<span
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
top: 20,
|
||||
right: 2
|
||||
}}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user