This repository has been archived on 2023-11-14. You can view files and clone it, but cannot push or open issues/pull-requests.
viscord/packages/renderer/src/pages/Chat.tsx

149 lines
3.8 KiB
TypeScript
Raw Normal View History

2022-07-22 17:09:28 -04:00
import { useCallback, useContext, useEffect, useRef, useState } from 'react';
2022-07-20 16:04:09 -04:00
import { v4 } from 'uuid';
2022-07-23 17:37:24 -04:00
import { useApi } from '../lib/useApi';
2022-07-25 21:23:40 -04:00
import { ChannelContext, ClientIdContext } from './App';
2022-07-21 15:22:00 -04:00
import type { IMessage} from './Message';
import { Message } from './Message';
2022-07-29 00:01:01 -04:00
import { MdSend } from 'react-icons/md';
2022-07-20 16:04:09 -04:00
2022-07-22 20:29:24 -04:00
function createMessage(from: string, text: string,
channel: string, t = 0): IMessage {
2022-07-20 16:04:09 -04:00
return {
text,
from,
timestamp: Date.now() - t * 1000,
uid: v4(),
2022-07-22 17:09:28 -04:00
channel,
2022-07-20 16:04:09 -04:00
};
}
export default () => {
2022-07-21 15:22:00 -04:00
const [messages, setMessages] = useState<IMessage[]>([]);
2022-07-21 05:38:58 -04:00
const [hist, setHist] = useState(false);
2022-07-23 17:37:24 -04:00
2022-07-25 21:23:40 -04:00
const CHATBOX_SIZE = 64;
const PADDING = 8;
2022-07-20 16:04:09 -04:00
const textBoxRef = useRef<HTMLDivElement>(null);
2022-07-23 17:37:24 -04:00
2022-07-25 21:23:40 -04:00
const { channel, setChannel } = useContext(ChannelContext);
const { clientId } = useContext(ClientIdContext);
2022-07-20 16:04:09 -04:00
2022-07-23 17:37:24 -04:00
const { send } = useApi({
2022-07-22 20:29:24 -04:00
'message:message'(data: IMessage) {
if(data.channel !== channel) return;
2022-07-23 17:37:24 -04:00
2022-07-22 20:29:24 -04:00
setMessages([...messages, data]);
},
'message:recent'(data: { messages: IMessage[] }) {
2022-07-23 17:37:24 -04:00
setMessages(data.messages.reverse());
2022-07-22 20:29:24 -04:00
},
2022-07-20 16:04:09 -04:00
}, [messages]);
2022-07-21 04:18:39 -04:00
useEffect(() => {
2022-07-22 17:09:28 -04:00
send('message:recent', { channel });
}, [channel]);
2022-07-21 04:18:39 -04:00
2022-07-20 16:04:09 -04:00
const sendMessage = useCallback(() => {
if(textBoxRef.current === null) return;
2022-07-22 17:09:28 -04:00
if(channel === null) return;
2022-07-23 17:37:24 -04:00
if(clientId === null) return;
2022-07-22 20:29:24 -04:00
send(
'message:message',
createMessage(
2022-07-23 17:37:24 -04:00
clientId,
2022-07-22 20:29:24 -04:00
textBoxRef.current.innerText,
channel,
),
);
2022-07-20 16:04:09 -04:00
textBoxRef.current.innerText = '';
2022-07-22 17:09:28 -04:00
}, [channel]);
2022-07-20 16:04:09 -04:00
const keyDown = useCallback((evt: any) => {
if(evt.key === 'Enter') {
sendMessage();
}
}, [sendMessage]);
return (
2022-07-25 03:33:49 -04:00
<div
style={{
height: '100%',
width: '100%',
display: 'grid',
2022-07-25 21:23:40 -04:00
gridTemplateColumns: `1fr ${CHATBOX_SIZE}px`,
gridTemplateRows: `1fr ${CHATBOX_SIZE}px`,
2022-07-25 03:33:49 -04:00
gridTemplateAreas: '"content content" "message send"',
}}
>
<div style={{
// borderBottom: '1px solid #bd93f9',
gridArea: 'content',
position: 'relative',
2022-07-25 21:23:40 -04:00
// borderBottom: '1px solid white'
2022-07-25 03:33:49 -04:00
}}>
2022-07-20 16:04:09 -04:00
<div style={{
2022-07-25 03:33:49 -04:00
position: 'absolute',
bottom: '0px',
width: '100%',
2022-07-20 16:04:09 -04:00
}}>
2022-07-25 03:33:49 -04:00
{messages.map(message => (
<Message key={message.uid} message={message}></Message>
))}
2022-07-20 16:04:09 -04:00
</div>
2022-07-25 03:33:49 -04:00
</div>
<div onClick={() => {
textBoxRef.current?.focus();
}}style={{
2022-07-25 21:23:40 -04:00
margin: PADDING + 'px',
marginRight: '0px',
borderRadius: ((CHATBOX_SIZE - PADDING*2) / 2) + 'px',
2022-07-25 03:33:49 -04:00
background: '#343746',
gridArea: 'message',
display: 'grid',
placeItems: 'center center',
padding: '0px 16px',
cursor: 'text',
overflow: 'auto',
}}>
<div
ref={textBoxRef}
onKeyDown={keyDown}
className="input"
role="textbox"
contentEditable
style={{
background: 'inherit',
outline: 'none',
boxSizing: 'border-box',
2022-07-25 21:23:40 -04:00
// borderRadius: '8px',
// borderRadius: '50%',
2022-07-25 03:33:49 -04:00
width: '100%',
resize: 'none',
2022-07-25 21:23:40 -04:00
// border: '1px solid white',
2022-07-25 03:33:49 -04:00
}}
></div>
</div>
<div style={{
width: '100%',
height: '100%',
padding: '8px',
boxSizing: 'border-box',
}}>
<div onClick={sendMessage} style={{
background: '#bd93f9',
width: '100%',
height: '100%',
2022-07-25 21:23:40 -04:00
borderRadius: '50%',
// borderRadius: '8px',
2022-07-25 03:33:49 -04:00
cursor: 'pointer',
2022-07-20 16:04:09 -04:00
display: 'grid',
placeItems: 'center center',
2022-07-25 03:33:49 -04:00
fontSize: '32px',
2022-07-20 16:04:09 -04:00
}}>
2022-07-25 21:23:40 -04:00
<MdSend></MdSend>
2022-07-20 16:04:09 -04:00
</div>
</div>
2022-07-25 03:33:49 -04:00
</div>
2022-07-20 16:04:09 -04:00
);
};