Files
chat-with-gpt/src/components/input.tsx

124 lines
4.1 KiB
TypeScript
Raw Normal View History

2023-03-06 05:30:58 -08:00
import styled from '@emotion/styled';
import { Button, ActionIcon, Textarea } from '@mantine/core';
2023-03-08 13:30:11 -08:00
import { useCallback, useMemo } from 'react';
import { useLocation } from 'react-router-dom';
2023-03-06 05:30:58 -08:00
import { useAppContext } from '../context';
2023-03-10 14:00:37 -08:00
import { useAppDispatch, useAppSelector } from '../store';
import { selectMessage, setMessage } from '../store/message';
import { selectTemperature } from '../store/parameters';
import { openSystemPromptPanel, openTemperaturePanel } from '../store/settings-ui';
2023-03-06 05:30:58 -08:00
const Container = styled.div`
background: #292933;
border-top: thin solid #393933;
padding: 1rem 1rem 0 1rem;
.inner {
max-width: 50rem;
margin: auto;
text-align: right;
}
.settings-button {
margin: 0.5rem -0.4rem 0.5rem 1rem;
font-size: 0.7rem;
color: #999;
}
`;
export declare type OnSubmit = (name?: string) => Promise<boolean>;
function PaperPlaneSubmitButton(props: { onSubmit: any, disabled?: boolean }) {
return (
2023-03-08 13:30:11 -08:00
<ActionIcon size="sm"
disabled={props.disabled}
loading={props.disabled}
onClick={props.onSubmit}>
2023-03-06 05:30:58 -08:00
<i className="fa fa-paper-plane" style={{ fontSize: '90%' }} />
</ActionIcon>
);
}
export interface MessageInputProps {
disabled?: boolean;
}
export default function MessageInput(props: MessageInputProps) {
2023-03-10 14:00:37 -08:00
const temperature = useAppSelector(selectTemperature);
const message = useAppSelector(selectMessage);
2023-03-06 05:30:58 -08:00
const context = useAppContext();
2023-03-10 14:00:37 -08:00
const dispatch = useAppDispatch();
2023-03-06 05:30:58 -08:00
2023-03-10 14:01:45 -08:00
const onCustomizeSystemPromptClick = useCallback(() => dispatch(openSystemPromptPanel()), [dispatch]);
const onTemperatureClick = useCallback(() => dispatch(openTemperaturePanel()), [dispatch]);
2023-03-06 05:30:58 -08:00
const onChange = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {
2023-03-10 14:00:37 -08:00
dispatch(setMessage(e.target.value));
2023-03-10 14:01:45 -08:00
}, [dispatch]);
2023-03-10 14:00:37 -08:00
const pathname = useLocation().pathname;
2023-03-06 05:30:58 -08:00
const onSubmit = useCallback(async () => {
2023-03-10 14:00:37 -08:00
if (await context.onNewMessage(message)) {
dispatch(setMessage(''));
2023-03-06 05:30:58 -08:00
}
2023-03-10 14:00:37 -08:00
}, [context, message, dispatch]);
2023-03-06 05:30:58 -08:00
const onKeyDown = useCallback((e: React.KeyboardEvent<HTMLTextAreaElement>) => {
2023-03-08 13:30:11 -08:00
if (e.key === 'Enter' && e.shiftKey === false && !props.disabled) {
2023-03-06 05:30:58 -08:00
e.preventDefault();
onSubmit();
}
}, [onSubmit, props.disabled]);
const rightSection = useMemo(() => {
return (
<div style={{
opacity: '0.8',
paddingRight: '0.4rem',
}}>
<PaperPlaneSubmitButton onSubmit={onSubmit} disabled={props.disabled} />
</div>
);
}, [onSubmit, props.disabled]);
2023-03-08 13:30:11 -08:00
const messagesToDisplay = context.currentChat.messagesToDisplay;
const disabled = context.generating
|| messagesToDisplay[messagesToDisplay.length - 1]?.role === 'user'
|| (messagesToDisplay.length > 0 && !messagesToDisplay[messagesToDisplay.length - 1]?.done);
const isLandingPage = pathname === '/';
if (context.isShare || (!isLandingPage && !context.id)) {
return null;
}
2023-03-10 14:00:37 -08:00
2023-03-06 05:30:58 -08:00
return <Container>
<div className="inner">
2023-03-08 13:30:11 -08:00
<Textarea disabled={props.disabled || disabled}
2023-03-06 05:30:58 -08:00
autosize
minRows={3}
maxRows={12}
placeholder={"Enter a message here..."}
2023-03-10 14:00:37 -08:00
value={message}
2023-03-06 05:30:58 -08:00
onChange={onChange}
rightSection={rightSection}
onKeyDown={onKeyDown} />
<div>
2023-03-08 13:30:11 -08:00
<Button variant="subtle"
className="settings-button"
size="xs"
compact
2023-03-10 14:00:37 -08:00
onClick={onCustomizeSystemPromptClick}>
2023-03-06 05:30:58 -08:00
<span>Customize system prompt</span>
</Button>
2023-03-08 13:30:11 -08:00
<Button variant="subtle"
className="settings-button"
size="xs"
compact
2023-03-10 14:00:37 -08:00
onClick={onTemperatureClick}>
<span>Temperature: {temperature.toFixed(1)}</span>
2023-03-06 05:30:58 -08:00
</Button>
</div>
</div>
</Container>;
}