Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Responsive Chat #207

Merged
merged 10 commits into from
Mar 29, 2024
29 changes: 29 additions & 0 deletions src/theme.js
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,20 @@ const lightTheme = createTheme({
...(props.type === "mic" && props.activate ? micAnimation : {}),
}),
},
{
props: { variant: "transparent" },
style: {
backgroundColor: alpha(base.grey[300], 0.8),
color: base.grey[900],
"&:hover": {
backgroundColor: alpha(base.grey[700], 0.8),
color: base.grey[200],
},
"&:disabled": {
color: base.grey[700],
},
},
},
],
styleOverrides: {
root: {
Expand Down Expand Up @@ -539,6 +553,21 @@ const darkTheme = createTheme({
...(props.type === "mic" && props.activate ? micAnimation : {}),
}),
},
{
props: { variant: "transparent" },
style: {
backgroundColor: alpha(base.grey[900], 0.8),
color: base.grey[400],
"&:hover": {
backgroundColor: alpha(base.grey[400], 0.8),
color: base.grey[900],
},
"&.Mui-disabled": {
backgroundColor: base.grey[900],
color: base.grey[700],
},
},
},
],
styleOverrides: {
root: {
Expand Down
65 changes: 40 additions & 25 deletions src/widgets/Chat/ChatDisplay.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import ChatEditor from "./ChatEditor";
import ErrorMessage from "./components/ErrorMessage";
import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown";
import MessageBox from "./components/MessageBox";
import WelcomeMessage from "./components/WelcomeMessage";

import {
Box,
Expand All @@ -9,6 +11,7 @@ import {
Dialog,
DialogContent,
DialogTitle,
Fab,
useTheme,
} from "@mui/material";
import React, { useEffect, useRef, useState } from "react";
Expand All @@ -23,6 +26,8 @@ const ChatDisplay = ({
const theme = useTheme();
const [openDialog, setOpenDialog] = useState(false);
const [selectedCode, setSelectedCode] = useState("");
const [showScrollToBottomButton, setShowScrollToBottomButton] =
useState(false);
const messagesContainerRef = useRef(null);

const handleOpenDialog = (code) => {
Expand All @@ -46,13 +51,9 @@ const ChatDisplay = ({
const { scrollTop, scrollHeight, clientHeight } =
messagesContainerRef.current;
const atBottom = Math.abs(scrollTop + clientHeight - scrollHeight) < 1;

const scrollToBottomButton = document.getElementById(
"scrollToBottomButton"
setShowScrollToBottomButton(
!atBottom && window.innerWidth >= 960 && chat.messages.length > 0
);
if (scrollToBottomButton) {
scrollToBottomButton.style.display = atBottom ? "none" : "block";
}
}
};

Expand All @@ -72,51 +73,64 @@ const ChatDisplay = ({
sx={{
overflow: "auto",
flex: 1,
padding: "20px",
display: "flex",
flexDirection: "column",
alignItems: "center",
backgroundColor: theme.palette.background.paper,
paddingX: { xs: "8px", sm: "16px", md: "20px" },
paddingY: "20px",
}}
ref={messagesContainerRef}
onScroll={handleScroll}
>
{chat &&
{chat && chat.messages.length === 0 ? (
<WelcomeMessage />
) : (
chat &&
chat.messages.map((message, index) => (
<MessageBox
key={index}
message={message}
handleOpenDialog={handleOpenDialog}
/>
))}
))
)}
{loading && <MessageBox onlyUser currentMessage={currentUserMessage} />}
<ErrorMessage
show={error.status}
content={error.content}
type={error.type}
refreshChat={refreshChat}
/>
<Button
onClick={scrollToBottom}
sx={{ position: "fixed", bottom: 20, right: 20 }}
id="scrollToBottomButton"
style={{ display: "none" }}
>
Scroll to Bottom
</Button>
{showScrollToBottomButton && (
<Fab
onClick={scrollToBottom}
variant="transparent"
size="small"
sx={{
position: "absolute",
bottom: { xs: 16, sm: 24, md: 94 },
left: "50%",
transform: "translateX(-50%)",
zIndex: 1,
display: { xs: "none", md: "block" },
"& > *": {
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
},
}}
>
<KeyboardArrowDownIcon />
</Fab>
)}
{loading && <CircularProgress />}
<Dialog
open={openDialog}
onClose={handleCloseDialog}
maxWidth="md"
fullWidth={true}
sx={{
"& .MuiDialog-paper": {
minHeight: "30vh",
maxHeight: "60vh",
width: "60%",
},
}}
fullWidth
>
<DialogTitle>Code Analysis</DialogTitle>
<DialogContent dividers>
Expand All @@ -129,4 +143,5 @@ const ChatDisplay = ({
</Box>
);
};

export default ChatDisplay;
4 changes: 4 additions & 0 deletions src/widgets/Chat/ChatMainArea.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,7 @@
background-color: initial;
}
}

.pulse-animation {
animation: pulseAnimationWithColor 2s ease-in-out;
}
44 changes: 21 additions & 23 deletions src/widgets/Chat/MessageInput.jsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import CodeIcon from "@mui/icons-material/Code";
import SendIcon from "@mui/icons-material/Send";
import codeImage from "../../images/code.png";

import {
Box,
Fab,
IconButton,
TextField,
Tooltip,
Expand All @@ -12,6 +11,7 @@ import {
} from "@mui/material";
import React, {
forwardRef,
useEffect,
useImperativeHandle,
useRef,
useState,
Expand All @@ -22,14 +22,19 @@ const MessageInput = forwardRef((props, ref) => {
const { loading } = props;
const theme = useTheme();
const [showProjectIcon, setShowProjectIcon] = useState(false);
const [playAnimation, setPlayAnimation] = useState(true);
const [isAnimating, setIsAnimating] = useState(false);
const [isInputEmpty, setIsInputEmpty] = useState(true);

const inputRef = useRef(null);

const handleHover = () => {
setPlayAnimation(false);
};
useEffect(() => {
if (showProjectIcon) {
setIsAnimating(true);
const timer = setTimeout(() => {
setIsAnimating(false);
}, 2000);
return () => clearTimeout(timer);
}
}, [showProjectIcon]);

useImperativeHandle(ref, () => ({
getValue: () => inputRef.current.value,
Expand All @@ -50,7 +55,6 @@ const MessageInput = forwardRef((props, ref) => {

const onSend = (event) => {
event.preventDefault();

handleSendMessage();
};

Expand All @@ -74,10 +78,10 @@ const MessageInput = forwardRef((props, ref) => {
display: "flex",
alignItems: "center",
justifyContent: "center",
width: "70%",
width: { xs: "100%", sm: "90%", md: "80%" },
borderRadius: theme.custom.chat.inputBorderRadius,
padding: "10px",
border: `1px solid `,
border: `1px solid`,
borderColor: theme.palette.grey[500],
backgroundColor: theme.palette.background.default,
}}
Expand Down Expand Up @@ -110,21 +114,14 @@ const MessageInput = forwardRef((props, ref) => {
}
placement="top"
>
<Fab
color="primary"
size="small"
<IconButton
type="submit"
onClick={handleProjectIconClick}
onMouseEnter={handleHover}
sx={{
backgroundColor: theme.palette.grey[600],

animation: playAnimation
? "pulseAnimationWithColor 2s infinite"
: "none",
}}
className={isAnimating ? "pulse-animation" : ""}
sx={{ ml: 1 }}
>
<img src={codeImage} alt={"Code"} style={{ width: "100%" }} />
</Fab>
<CodeIcon />
</IconButton>
</Tooltip>
)}
<IconButton
Expand All @@ -138,4 +135,5 @@ const MessageInput = forwardRef((props, ref) => {
</Box>
);
});

export default MessageInput;
23 changes: 12 additions & 11 deletions src/widgets/Chat/components/ErrorMessage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,16 @@ const ErrorMessage = ({ show, content, type, refreshChat }) => {
sx={{
backgroundColor: alpha("#f44336", 0.1),
border: "1px solid #f44336",
width: "60%",
marginBottom: "20px",
width: {
xs: "100%",
sm: "90%",
md: "80%",
},
marginBottom: {
xs: "12px",
sm: "16px",
md: "20px",
},
padding: "10px",
borderRadius: "10px",
textAlign: "left",
Expand All @@ -31,10 +39,7 @@ const ErrorMessage = ({ show, content, type, refreshChat }) => {
>
<Typography
variant="subtitle1"
sx={{
fontWeight: "bold",
userSelect: "text",
}}
sx={{ fontWeight: "bold", userSelect: "text" }}
>
EXPERT ERROR
</Typography>
Expand All @@ -51,11 +56,7 @@ const ErrorMessage = ({ show, content, type, refreshChat }) => {
</Stack>
<Typography
variant="subtitle2"
sx={{
fontWeight: "bold",
my: "8px",
userSelect: "text",
}}
sx={{ fontWeight: "bold", my: "8px", userSelect: "text" }}
>
{type}
</Typography>
Expand Down
19 changes: 12 additions & 7 deletions src/widgets/Chat/components/MessageBox.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,20 @@ function MessageBox({
if (onlyUser) {
message.content = currentMessage;
}

return (
<Box
sx={{
width: "60%",
marginBottom: "20px",
width: {
xs: "100%",
sm: "90%",
md: "80%",
},
marginBottom: {
xs: "12px",
sm: "16px",
md: "20px",
},
padding: "10px",
borderRadius: "10px",
textAlign: "left",
Expand All @@ -28,11 +37,7 @@ function MessageBox({
>
<Typography
variant="subtitle2"
sx={{
fontWeight: "bold",
marginBottom: "8px",
userSelect: "text",
}}
sx={{ fontWeight: "bold", marginBottom: "8px", userSelect: "text" }}
>
{message.role}
</Typography>
Expand Down
35 changes: 35 additions & 0 deletions src/widgets/Chat/components/WelcomeMessage.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import Logo from "../../../components/Logo";

import { Box, Typography } from "@mui/material";

const WelcomeMessage = () => {
return (
<Box
sx={{
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
height: "100%",
textAlign: "center",
}}
>
<Box
sx={{
display: "flex",
alignItems: "center",
justifyContent: "center",
marginBottom: "8px",
}}
>
<Logo beta={false} />
</Box>
<Typography variant="h4" gutterBottom sx={{ marginBottom: "4px" }}>
Welcome to the NucChat!
</Typography>
<Typography variant="subtitle1">This is subtitle</Typography>
</Box>
);
};

export default WelcomeMessage;
Loading
Loading