feat(chat): add support for chat part messages. Closes #3201 (#3291)

This commit is contained in:
Gabe Kangas
2023-09-10 10:58:11 -07:00
committed by GitHub
parent fb0ac492b2
commit 169c11596c
15 changed files with 205 additions and 21 deletions

View File

@ -14,6 +14,7 @@ import { ChatTextField } from '../ChatTextField/ChatTextField';
import { ChatModeratorNotification } from '../ChatModeratorNotification/ChatModeratorNotification';
import { ChatSystemMessage } from '../ChatSystemMessage/ChatSystemMessage';
import { ChatJoinMessage } from '../ChatJoinMessage/ChatJoinMessage';
import { ChatPartMessage } from '../ChatPartMessage/ChatPartMessage';
import { ScrollToBotBtn } from './ScrollToBotBtn';
import { ChatActionMessage } from '../ChatActionMessage/ChatActionMessage';
import { ChatSocialMessage } from '../ChatSocialMessage/ChatSocialMessage';
@ -137,6 +138,20 @@ export const ChatContainer: FC<ChatContainerProps> = ({
);
};
const getUserPartMessage = (message: ChatMessage) => {
const {
user: { displayName, displayColor },
} = message;
const isAuthorModerator = checkIsModerator(message);
return (
<ChatPartMessage
displayName={displayName}
userColor={displayColor}
isAuthorModerator={isAuthorModerator}
/>
);
};
const getActionMessage = (message: ChatMessage) => {
const { body } = message;
return <ChatActionMessage body={body} />;
@ -185,6 +200,8 @@ export const ChatContainer: FC<ChatContainerProps> = ({
return getConnectedInfoMessage(message as ConnectedClientInfoEvent);
case MessageType.USER_JOINED:
return getUserJoinedMessage(message as ChatMessage);
case MessageType.USER_PARTED:
return getUserPartMessage(message as ChatMessage);
case MessageType.CHAT_ACTION:
return getActionMessage(message as ChatMessage);
case MessageType.SYSTEM:

View File

@ -0,0 +1,16 @@
.root {
display: inline-flex;
padding: 10px 0;
color: var(--theme-color-components-chat-text);
font-weight: 400;
font-size: var(--chat-message-text-size);
.moderatorBadge,
.user {
margin-right: 5px;
}
}
.icon {
padding: 0 var(--chat-notification-icon-padding) 0 16px;
}

View File

@ -0,0 +1,42 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import { ChatPartMessage } from './ChatPartMessage';
import Mock from '../../../stories/assets/mocks/chatmessage-action.png';
export default {
title: 'owncast/Chat/Messages/Chat Part',
component: ChatPartMessage,
argTypes: {
userColor: {
options: ['0', '1', '2', '3', '4', '5', '6', '7'],
control: { type: 'select' },
},
},
parameters: {
design: {
type: 'image',
url: Mock,
},
docs: {
description: {
component: `This is shown when a chat participant parts.`,
},
},
},
} as ComponentMeta<typeof ChatPartMessage>;
const Template: ComponentStory<typeof ChatPartMessage> = args => <ChatPartMessage {...args} />;
export const Regular = Template.bind({});
Regular.args = {
displayName: 'RandomChatter',
isAuthorModerator: false,
userColor: 3,
};
export const Moderator = Template.bind({});
Moderator.args = {
displayName: 'RandomChatter',
isAuthorModerator: true,
userColor: 2,
};

View File

@ -0,0 +1,42 @@
import { FC } from 'react';
import dynamic from 'next/dynamic';
import { ModerationBadge } from '../ChatUserBadge/ModerationBadge';
import styles from './ChatPartMessage.module.scss';
// Lazy loaded components
const TeamOutlined = dynamic(() => import('@ant-design/icons/TeamOutlined'), {
ssr: false,
});
export type ChatPartMessageProps = {
isAuthorModerator: boolean;
userColor: number;
displayName: string;
};
export const ChatPartMessage: FC<ChatPartMessageProps> = ({
isAuthorModerator,
userColor,
displayName,
}) => {
const color = `var(--theme-color-users-${userColor})`;
return (
<div className={styles.root}>
<span style={{ color }}>
<span className={styles.icon}>
<TeamOutlined />
</span>
<span className={styles.user}>{displayName}</span>
{isAuthorModerator && (
<span className={styles.moderatorBadge}>
<ModerationBadge userColor={userColor} />
</span>
)}
</span>
left the chat.
</div>
);
};