Add moderator status chat message. Closes #1999
This commit is contained in:
@@ -2,10 +2,15 @@ import { Button } from 'antd';
|
|||||||
import { Virtuoso } from 'react-virtuoso';
|
import { Virtuoso } from 'react-virtuoso';
|
||||||
import { useState, useMemo, useRef } from 'react';
|
import { useState, useMemo, useRef } from 'react';
|
||||||
import { EditFilled, VerticalAlignBottomOutlined } from '@ant-design/icons';
|
import { EditFilled, VerticalAlignBottomOutlined } from '@ant-design/icons';
|
||||||
import { MessageType, NameChangeEvent } from '../../../interfaces/socket-events';
|
import {
|
||||||
|
ConnectedClientInfoEvent,
|
||||||
|
MessageType,
|
||||||
|
NameChangeEvent,
|
||||||
|
} from '../../../interfaces/socket-events';
|
||||||
import s from './ChatContainer.module.scss';
|
import s from './ChatContainer.module.scss';
|
||||||
import { ChatMessage } from '../../../interfaces/chat-message.model';
|
import { ChatMessage } from '../../../interfaces/chat-message.model';
|
||||||
import { ChatTextField, ChatUserMessage } from '..';
|
import { ChatTextField, ChatUserMessage } from '..';
|
||||||
|
import ChatModeratorNotification from '../ChatModeratorNotification/ChatModeratorNotification';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
messages: ChatMessage[];
|
messages: ChatMessage[];
|
||||||
@@ -43,7 +48,20 @@ export default function ChatContainer(props: Props) {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getViewForMessage = (index: number, message: ChatMessage | NameChangeEvent) => {
|
const getConnectedInfoMessage = (message: ConnectedClientInfoEvent) => {
|
||||||
|
const modStatusUpdate = checkIsModerator(message);
|
||||||
|
if (!modStatusUpdate) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Alert the user that they are a moderator.
|
||||||
|
return <ChatModeratorNotification />;
|
||||||
|
};
|
||||||
|
|
||||||
|
const getViewForMessage = (
|
||||||
|
index: number,
|
||||||
|
message: ChatMessage | NameChangeEvent | ConnectedClientInfoEvent,
|
||||||
|
) => {
|
||||||
switch (message.type) {
|
switch (message.type) {
|
||||||
case MessageType.CHAT:
|
case MessageType.CHAT:
|
||||||
return (
|
return (
|
||||||
@@ -58,6 +76,9 @@ export default function ChatContainer(props: Props) {
|
|||||||
);
|
);
|
||||||
case MessageType.NAME_CHANGE:
|
case MessageType.NAME_CHANGE:
|
||||||
return getNameChangeViewForMessage(message as NameChangeEvent);
|
return getNameChangeViewForMessage(message as NameChangeEvent);
|
||||||
|
case MessageType.CONNECTED_USER_INFO:
|
||||||
|
return getConnectedInfoMessage(message);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -120,3 +141,14 @@ function isSameUserAsLast(messages: ChatMessage[], index: number) {
|
|||||||
|
|
||||||
return id === lastMessage?.user.id;
|
return id === lastMessage?.user.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function checkIsModerator(message) {
|
||||||
|
const { user } = message;
|
||||||
|
const { scopes } = user;
|
||||||
|
|
||||||
|
if (!scopes || scopes.length === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return scopes.includes('MODERATOR');
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
@import 'styles/mixins.scss';
|
||||||
|
|
||||||
|
.chatModerationNotification {
|
||||||
|
background-color: var(--theme-background-primary);
|
||||||
|
margin: 5px;
|
||||||
|
border-radius: 15px;
|
||||||
|
border-color: rgba(0, 0, 0, 0.3);
|
||||||
|
border-width: 1px;
|
||||||
|
border-style: solid;
|
||||||
|
padding: 10px 10px;
|
||||||
|
max-width: 400px;
|
||||||
|
@include flexCenter;
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
margin-right: 10px;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
import s from './ChatModeratorNotification.module.scss';
|
||||||
|
import Icon from '../../../assets/images/moderator.svg';
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export default function ModeratorNotification() {
|
||||||
|
return (
|
||||||
|
<div className={s.chatModerationNotification}>
|
||||||
|
<Icon className={s.icon} />
|
||||||
|
You are now a moderator.
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -258,6 +258,7 @@ export function ClientConfigStore() {
|
|||||||
setChatUserId,
|
setChatUserId,
|
||||||
setIsChatModerator,
|
setIsChatModerator,
|
||||||
);
|
);
|
||||||
|
setChatMessages(currentState => [...currentState, message as ChatEvent]);
|
||||||
break;
|
break;
|
||||||
case MessageType.CHAT:
|
case MessageType.CHAT:
|
||||||
setChatMessages(currentState => [...currentState, message as ChatEvent]);
|
setChatMessages(currentState => [...currentState, message as ChatEvent]);
|
||||||
|
|||||||
17
web/stories/ChatModeratorNotification.stories.tsx
Normal file
17
web/stories/ChatModeratorNotification.stories.tsx
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { ComponentStory, ComponentMeta } from '@storybook/react';
|
||||||
|
import ChatModeratorNotification from '../components/chat/ChatModeratorNotification/ChatModeratorNotification';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: 'owncast/Chat/Messages/Moderation Role Notification',
|
||||||
|
component: ChatModeratorNotification,
|
||||||
|
parameters: {},
|
||||||
|
} as ComponentMeta<typeof ChatModeratorNotification>;
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
const Template: ComponentStory<typeof ChatModeratorNotification> = args => (
|
||||||
|
<ChatModeratorNotification {...args} />
|
||||||
|
);
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
export const Basic = Template.bind({});
|
||||||
5
web/styles/mixins.scss
Normal file
5
web/styles/mixins.scss
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
@mixin flexCenter {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user