Skip to content

Commit

Permalink
use highlight js instead of syntax highlighter (#538)
Browse files Browse the repository at this point in the history
* use highlight js instead of syntax highlighter

* fix test

* prettify code snippets

* remove unused prop
  • Loading branch information
willydouhard authored Nov 14, 2023
1 parent f2974b2 commit c17ec59
Show file tree
Hide file tree
Showing 13 changed files with 705 additions and 724 deletions.
2 changes: 1 addition & 1 deletion cypress/e2e/on_chat_start/spec.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ describe('on_chat_start', () => {
messages.should('have.length', 1);

messages.eq(0).should('contain.text', 'Hello!');
messages.eq(0).should('contain.html', '<code class="language-python"');
messages.eq(0).should('contain.html', '<code class="language-python hljs"');
});
});
1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"react-router-dom": "^6.15.0",
"react-speech-recognition": "^3.10.0",
"recoil": "^0.7.6",
"regenerator-runtime": "^0.14.0",
"socket.io-client": "^4.7.2",
"swr": "^2.2.2",
"usehooks-ts": "^2.9.1",
Expand Down
249 changes: 126 additions & 123 deletions frontend/pnpm-lock.yaml

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const UploadButton = ({
const { getRootProps, getInputProps, uploading } = upload;

return (
<Tooltip title="Upload files">
<Tooltip title="Attach files">
<span>
<input id="upload-button-input" {...getInputProps()} />
<IconButton
Expand Down
72 changes: 11 additions & 61 deletions frontend/src/components/organisms/chat/inputBox/input.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import { memo, useCallback, useEffect, useRef, useState } from 'react';
import SpeechRecognition, {
useSpeechRecognition
} from 'react-speech-recognition';
import { useRecoilState, useSetRecoilState } from 'recoil';
import 'regenerator-runtime';

import KeyboardVoiceIcon from '@mui/icons-material/KeyboardVoice';
import StopCircleIcon from '@mui/icons-material/StopCircle';
import SendIcon from '@mui/icons-material/Telegram';
import TuneIcon from '@mui/icons-material/Tune';
import { Box, IconButton, Stack, TextField } from '@mui/material';
Expand All @@ -26,6 +22,7 @@ import { chatHistoryState } from 'state/chatHistory';
import { chatSettingsOpenState, projectSettingsState } from 'state/project';

import UploadButton from './UploadButton';
import SpeechButton from './speechButton';

interface Props {
fileSpec: FileSpec;
Expand Down Expand Up @@ -53,17 +50,11 @@ const Input = memo(

const ref = useRef<HTMLDivElement>(null);
const { loading, askUser, chatSettingsInputs, disabled } = useChatData();
const { transcript, browserSupportsSpeechRecognition } =
useSpeechRecognition();

const [value, setValue] = useState('');
const [isComposing, setIsComposing] = useState(false);
const [isRecording, setIsRecording] = useState(false);
const [lastTranscript, setLastTranscript] = useState('');
const [timer, setTimer] = useState<NodeJS.Timeout | null>(null);

const showTextToSpeech =
pSettings?.features.speech_to_text?.enabled &&
browserSupportsSpeechRecognition;
const showTextToSpeech = pSettings?.features.speech_to_text?.enabled;

useEffect(() => {
const pasteEvent = (event: ClipboardEvent) => {
Expand Down Expand Up @@ -113,27 +104,6 @@ const Input = memo(
}
}, [loading, disabled]);

useEffect(() => {
if (lastTranscript.length < transcript.length) {
setValue((text) => text + transcript.slice(lastTranscript.length));
}
setLastTranscript(transcript);
}, [transcript]);

useEffect(() => {
if (isRecording) {
if (timer) {
clearTimeout(timer);
}
setTimer(
setTimeout(() => {
setIsRecording(false);
SpeechRecognition.stopListening();
}, 2000) // stop after 3 seconds of silence
);
}
}, [transcript, isRecording]);

const submit = useCallback(() => {
if (value === '' || disabled) {
return;
Expand Down Expand Up @@ -191,33 +161,13 @@ const Input = memo(
<TuneIcon />
</IconButton>
)}
{showTextToSpeech &&
(isRecording ? (
<IconButton
disabled={disabled}
color="inherit"
onClick={() => {
setIsRecording(false);
SpeechRecognition.stopListening();
}}
>
<StopCircleIcon />
</IconButton>
) : (
<IconButton
disabled={disabled}
color="inherit"
onClick={() => {
setIsRecording(true);
SpeechRecognition.startListening({
continuous: true,
language: pSettings?.features.speech_to_text?.language
});
}}
>
<KeyboardVoiceIcon />
</IconButton>
))}
{showTextToSpeech ? (
<SpeechButton
onSpeech={(transcript) => setValue((text) => text + transcript)}
language={pSettings.features?.speech_to_text?.language}
disabled={disabled}
/>
) : null}
<UploadButton
disabled={disabled}
fileSpec={fileSpec}
Expand Down
83 changes: 83 additions & 0 deletions frontend/src/components/organisms/chat/inputBox/speechButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { useEffect, useState } from 'react';
import SpeechRecognition, {
useSpeechRecognition
} from 'react-speech-recognition';

import KeyboardVoiceIcon from '@mui/icons-material/KeyboardVoice';
import StopCircleIcon from '@mui/icons-material/StopCircle';
import { IconButton, Tooltip } from '@mui/material';

interface Props {
onSpeech: (text: string) => void;
language?: string;
disabled?: boolean;
}

const SpeechButton = ({ onSpeech, language, disabled }: Props) => {
const { transcript, browserSupportsSpeechRecognition } =
useSpeechRecognition();
const [isRecording, setIsRecording] = useState(false);
const [lastTranscript, setLastTranscript] = useState('');
const [timer, setTimer] = useState<NodeJS.Timeout | null>(null);

useEffect(() => {
if (lastTranscript.length < transcript.length) {
onSpeech(transcript.slice(lastTranscript.length));
}
setLastTranscript(transcript);
}, [transcript]);

useEffect(() => {
if (isRecording) {
if (timer) {
clearTimeout(timer);
}
setTimer(
setTimeout(() => {
setIsRecording(false);
SpeechRecognition.stopListening();
}, 2000) // stop after 3 seconds of silence
);
}
}, [transcript, isRecording]);

if (!browserSupportsSpeechRecognition) {
return null;
}

return isRecording ? (
<Tooltip title="Stop recording">
<span>
<IconButton
disabled={disabled}
color="inherit"
onClick={() => {
setIsRecording(false);
SpeechRecognition.stopListening();
}}
>
<StopCircleIcon />
</IconButton>
</span>
</Tooltip>
) : (
<Tooltip title="Start recording">
<span>
<IconButton
disabled={disabled}
color="inherit"
onClick={() => {
setIsRecording(true);
SpeechRecognition.startListening({
continuous: true,
language: language
});
}}
>
<KeyboardVoiceIcon />
</IconButton>
</span>
</Tooltip>
);
};
export default SpeechButton;
3 changes: 1 addition & 2 deletions libs/components/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
"@types/lodash": "^4.14.199",
"@types/react-file-icon": "^1.0.2",
"@types/react-resizable": "^3.0.4",
"@types/react-syntax-highlighter": "^15.5.7",
"@types/uuid": "^9.0.3",
"@vitejs/plugin-react": "^4.0.4",
"@vitejs/plugin-react-swc": "^3.3.2",
Expand Down Expand Up @@ -65,6 +64,7 @@
"dependencies": {
"draft-js": "^0.11.7",
"formik": "^2.4.3",
"highlight.js": "^11.9.0",
"lodash": "^4.17.21",
"mui-chips-input": "2.0.0",
"plotly.js": "^2.27.0",
Expand All @@ -74,7 +74,6 @@
"react-password-checklist": "^1.5.0",
"react-plotly.js": "^2.6.0",
"react-resizable": "^3.0.5",
"react-syntax-highlighter": "^15.5.0",
"rehype-katex": "^7.0.0",
"remark-gfm": "^4.0.0",
"remark-math": "^6.0.0",
Expand Down
Loading

0 comments on commit c17ec59

Please sign in to comment.