diff --git a/src/client/chat--center.jsx b/src/client/chat--center.jsx index 4d9c493..5a34fb9 100644 --- a/src/client/chat--center.jsx +++ b/src/client/chat--center.jsx @@ -2,9 +2,13 @@ import './chat--center.scss'; import React from 'react'; +import ChatMessages from './chat--messages'; + export default function ChatCenter() { return ( -
+
+ +
); } diff --git a/src/client/chat--center.scss b/src/client/chat--center.scss index 3068644..3eee874 100644 --- a/src/client/chat--center.scss +++ b/src/client/chat--center.scss @@ -1,3 +1,3 @@ -.chat__center { +.center { flex-grow: 1; } diff --git a/src/client/chat--message.jsx b/src/client/chat--message.jsx new file mode 100644 index 0000000..9e53942 --- /dev/null +++ b/src/client/chat--message.jsx @@ -0,0 +1,56 @@ +import './chat--message.scss'; + +import classnames from 'classnames'; +import PropTypes from 'prop-types'; +import React from 'react'; +import ReactMarkdown from 'react-markdown'; + +export default function PlayersChatMessageSpace(props) { + const {message: {owner, text, timestamp}, isShort} = props; + const ownerMap = { + 1: 'cha0s', + 2: 'BabeHasHiccups', + }; + const dtf = new Intl.DateTimeFormat(undefined, { + hour: '2-digit', + minute: '2-digit', + }); + const date = new Date(timestamp); + const $messageTime = ( +
+ {dtf.format(date)} +
+ ); + return ( +
+ { + !isShort && ( +
+
{ownerMap[owner]}
+ {$messageTime} +
+ ) + } +
+
+ +
+ {isShort && $messageTime} +
+
+ ); +} + +PlayersChatMessageSpace.propTypes = { + isShort: PropTypes.bool.isRequired, + message: PropTypes.shape({ + text: PropTypes.string, + timestamp: PropTypes.number, + owner: PropTypes.string, + }).isRequired, +}; diff --git a/src/client/chat--message.scss b/src/client/chat--message.scss new file mode 100644 index 0000000..57dddfc --- /dev/null +++ b/src/client/chat--message.scss @@ -0,0 +1,82 @@ +.chat--message { + margin-top: 0.75rem; + padding: 0.25rem 1rem; +} + +.chat--message, .chat--message * { + font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif; +} + +.chat--message:first-child { + margin-top: 0; +} + +.chat--message.short { + margin-top: 0; + margin-bottom: 0; +} + +.chat--message.short .chat--messageTime { + display: inline; + visibility: hidden; +} + +.chat--message.short:hover .chat--messageTime { + visibility: visible; +} + +.chat--message.short .chat--messageOwner { + display: none; +} + +.chat--message:hover { + background-color: #1c1c1c; +} + +header { + display: flex; + width: 100%; +} + +.chat--messageOwner { + color: #d68030aa; + font-family: Caladea, 'Times New Roman', Times, serif; + font-weight: bold; + margin-bottom: 0.25rem; +} + +.chat--messageTime { + color: #666; + font-size: 0.7rem; + margin-left: 0.5rem; +} + +.chat--message:not(.short) .chat--messageTime { + line-height: 1.25rem; +} + +.chat--messageText { + font-size: 0.9rem; +} + +.chat--messageMarkdown * { + margin: 0; +} + +.chat--messageMarkdown { + h1, h2, h3, h4, h5, h6 { + line-height: 1rem; + } +} + +.chat--messageMarkdown { + display: inline; +} + +.chat--messageMarkdown :first-child { + margin-top: 0; +} + +.chat--messageMarkdown :last-child { + display: inline; +} diff --git a/src/client/chat--messages.jsx b/src/client/chat--messages.jsx new file mode 100644 index 0000000..2966b11 --- /dev/null +++ b/src/client/chat--messages.jsx @@ -0,0 +1,103 @@ +import './chat--messages.scss'; + +import React, {useLayoutEffect, useRef, useState} from 'react'; + +import ChatMessage from './chat--message'; + +export default function PlayersChatSpace() { + const [$form, $messages] = [useRef(null), useRef(null)]; + const [text, setText] = useState(''); + const messages = [ + { + key: 1, + owner: 1, + text: 'Hi!', + timestamp: Date.now(), + }, + { + key: 2, + owner: 2, + text: 'Yo.', + timestamp: Date.now(), + }, + { + key: 3, + owner: 2, + text: 'How have you been?', + timestamp: Date.now(), + }, + { + key: 4, + owner: 1, + text: 'Not too bad.', + timestamp: Date.now(), + }, + ]; + const {current} = $messages; + const isAtTheBottom = !current + ? true + : 0 === current.scrollTop || ( + current.scrollHeight + === current.scrollTop + + ['margin-top', 'margin-bottom'].reduce((r, property) => ( + r + parseInt(window.getComputedStyle(current).getPropertyValue(property), 10) + ), current.offsetHeight) + ); + const heightWatch = current && current.scrollHeight; + const messageCount = messages && messages.length; + useLayoutEffect(() => { + if (isAtTheBottom) { + current?.scrollTo(0, !current ? 0 : current.scrollHeight); + } + }, [current, heightWatch, messageCount, isAtTheBottom]); + let messageOwner = false; + return ( +
+
+
+ {messages && messages.map((message) => { + const $message = ( + + ); + messageOwner = message.owner; + return $message; + })} +
+
{ + event.preventDefault(); + const trimmed = text.slice(0, 1000).trim(); + if (trimmed) { + // socket.send(new ActionPacket(chat({owner: playerId, text: trimmed}, {game: id}))); + } + setText(''); + }} + ref={$form} + > +