Browse Source

Few changes to chat.

Changed the way the background is set on self sent messages and some
styling.

Fixed chat container not scrolling. Added 'go to bottom' button.
pull/2032/head
t1enne 3 years ago
parent
commit
455d8f8169
  1. 10
      web/components/chat/ChatContainer/ChatContainer.module.scss
  2. 42
      web/components/chat/ChatContainer/ChatContainer.tsx
  3. 26
      web/components/chat/ChatUserMessage/ChatUserMessage.module.scss
  4. 18
      web/components/chat/ChatUserMessage/ChatUserMessage.tsx

10
web/components/chat/ChatContainer/ChatContainer.module.scss

@ -1,8 +1,16 @@ @@ -1,8 +1,16 @@
.chatHeader {
text-align: center;
font-weight: bold;
padding: 5px 0;
color: var(--text-color-secondary);
border-bottom: 1px solid var(--color-owncast-gray-700);
font-variant: small-caps;
}
.toBottomWrap {
display: flex;
width: 100%;
justify-content: center;
position: absolute;
bottom: 5px;
}

42
web/components/chat/ChatContainer/ChatContainer.tsx

@ -1,8 +1,7 @@ @@ -1,8 +1,7 @@
import { Spin } from 'antd';
import { Button, Spin } from 'antd';
import { Virtuoso } from 'react-virtuoso';
import { useMemo, useRef } from 'react';
import { LoadingOutlined } from '@ant-design/icons';
import { useState, useMemo, useRef } from 'react';
import { LoadingOutlined, VerticalAlignBottomOutlined } from '@ant-design/icons';
import { MessageType, NameChangeEvent } from '../../../interfaces/socket-events';
import s from './ChatContainer.module.scss';
import { ChatMessage } from '../../../interfaces/chat-message.model';
@ -19,6 +18,8 @@ interface Props { @@ -19,6 +18,8 @@ interface Props {
export default function ChatContainer(props: Props) {
const { messages, loading, usernameToHighlight, chatUserId, isModerator } = props;
const [atBottom, setAtBottom] = useState(false);
// const [showButton, setShowButton] = useState(false);
const chatContainerRef = useRef(null);
const spinIcon = <LoadingOutlined style={{ fontSize: '32px' }} spin />;
@ -34,12 +35,12 @@ export default function ChatContainer(props: Props) { @@ -34,12 +35,12 @@ export default function ChatContainer(props: Props) {
);
};
const getViewForMessage = message => {
const getViewForMessage = (message: ChatMessage | NameChangeEvent) => {
switch (message.type) {
case MessageType.CHAT:
return (
<ChatUserMessage
message={message}
message={message as ChatMessage}
showModeratorMenu={isModerator} // Moderators have access to an additional menu
highlightString={usernameToHighlight} // What to highlight in the message
renderAsPersonallySent={message.user?.id === chatUserId} // The local user sent this message
@ -47,7 +48,7 @@ export default function ChatContainer(props: Props) { @@ -47,7 +48,7 @@ export default function ChatContainer(props: Props) {
/>
);
case MessageType.NAME_CHANGE:
return getNameChangeViewForMessage(message);
return getNameChangeViewForMessage(message as NameChangeEvent);
default:
return null;
}
@ -55,17 +56,36 @@ export default function ChatContainer(props: Props) { @@ -55,17 +56,36 @@ export default function ChatContainer(props: Props) {
const MessagesTable = useMemo(
() => (
<>
<Virtuoso
style={{ height: '70vh' }}
style={{ height: '75vh' }}
ref={chatContainerRef}
initialTopMostItemIndex={999} // Force alignment to bottom
initialTopMostItemIndex={messages.length - 1} // Force alignment to bottom
data={messages}
itemContent={(index, message) => getViewForMessage(message)}
itemContent={(_, message) => getViewForMessage(message)}
followOutput="auto"
alignToBottom
atBottomStateChange={bottom => setAtBottom(bottom)}
/>
{!atBottom && (
<div className={s.toBottomWrap}>
<Button
ghost
icon={<VerticalAlignBottomOutlined />}
onClick={() =>
chatContainerRef.current.scrollToIndex({
index: messages.length - 1,
behavior: 'smooth',
})
}
>
Go to last message
</Button>
</div>
)}
</>
),
[messages, usernameToHighlight, chatUserId, isModerator],
[messages, usernameToHighlight, chatUserId, isModerator, atBottom],
);
return (

26
web/components/chat/ChatUserMessage/ChatUserMessage.module.scss

@ -1,9 +1,20 @@ @@ -1,9 +1,20 @@
.root {
position: relative;
font-size: 0.9rem;
padding: 5px;
padding: 5px 15px 5px 5px;
padding-left: 1rem;
margin: 8px 5px;
// animation: chatFadeIn .1s ease-in;
.background {
position: absolute;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
background-color: currentColor;
opacity: 0.07;
border-radius: .25rem;
overflow: hidden;
}
.user {
font: var(--theme-header-font-family);
color: var(--color-owncast-grey-100);
@ -56,3 +67,14 @@ @@ -56,3 +67,14 @@
}
}
}
@keyframes chatFadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}

18
web/components/chat/ChatUserMessage/ChatUserMessage.tsx

@ -20,7 +20,6 @@ export default function ChatUserMessage({ @@ -20,7 +20,6 @@ export default function ChatUserMessage({
showModeratorMenu,
renderAsPersonallySent, // Move the border to the right and render a background
}: Props) {
const [bgColor, setBgColor] = useState<string>();
const { body, user, timestamp } = message;
const { displayName, displayColor } = user;
@ -28,21 +27,17 @@ export default function ChatUserMessage({ @@ -28,21 +27,17 @@ export default function ChatUserMessage({
const formattedTimestamp = `Sent at ${formatTimestamp(timestamp)}`;
const [formattedMessage, setFormattedMessage] = useState<string>(body);
useEffect(() => {
if (renderAsPersonallySent) setBgColor(getBgColor(displayColor));
}, []);
useEffect(() => {
setFormattedMessage(he.decode(body));
}, [message]);
return (
<div style={{ padding: 5 }}>
<div
className={cn(s.root, {
[s.ownMessage]: renderAsPersonallySent,
})}
data-display-color={displayColor}
style={{ borderColor: color, backgroundColor: bgColor }}
style={{ borderColor: color }}
title={formattedTimestamp}
>
<div className={s.user} style={{ color }}>
@ -53,13 +48,8 @@ export default function ChatUserMessage({ @@ -53,13 +48,8 @@ export default function ChatUserMessage({
</Highlight>
{showModeratorMenu && <div>Moderator menu</div>}
<div className={s.customBorder} style={{ color }} />
<div className={s.background} style={{ color }} />
</div>
</div>
);
}
function getBgColor(displayColor: number, alpha = 13) {
const root = document.querySelector(':root');
const css = getComputedStyle(root);
const hexColor = css.getPropertyValue(`--theme-user-colors-${displayColor}`);
return hexColor.concat(alpha.toString());
}

Loading…
Cancel
Save