Inline chat moderation UI (#1331)
* - mock detect when user turns into moderator - add moderator indicator to display on messages and username changer * also mock moderator flag in message payload about user to display indicator * add some menu looking icons and a menu of actions * WIP chat moderators * Add support for admin promoting a user to moderator * WIP- open a more info panel of user+message info; add some a11y to buttons * style the details panel * adjust positioning of menus * Merge fixes. ChatClient->Client ChatServer->Server * Remove moderator bool placeholders to use real state * Support inline hiding of messages by moderators * Support inline banning of chat users * Cleanup linter warnings * Puppeteer tests fail after typing take place * Manually resolve conflicts in chat between moderator feature and develop Co-authored-by: Gabe Kangas <gabek@real-ity.com>
This commit is contained in:
@@ -10,12 +10,14 @@ import {
|
||||
import { convertToText } from '../../utils/chat.js';
|
||||
import { SOCKET_MESSAGE_TYPES } from '../../utils/websocket.js';
|
||||
import { getDiffInDaysFromNow } from '../../utils/helpers.js';
|
||||
import ModeratorActions from './moderator-actions.js';
|
||||
|
||||
export default class ChatMessageView extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
formattedMessage: '',
|
||||
moderatorMenuOpen: false,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -37,11 +39,14 @@ export default class ChatMessageView extends Component {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { message } = this.props;
|
||||
const { message, isModerator, accessToken } = this.props;
|
||||
const { user, timestamp } = message;
|
||||
const { displayName, displayColor, createdAt } = user;
|
||||
const { displayName, displayColor, createdAt,
|
||||
isModerator: isAuthorModerator,
|
||||
} = user;
|
||||
|
||||
const isMessageModeratable = isModerator && message.type === SOCKET_MESSAGE_TYPES.CHAT;
|
||||
|
||||
const { formattedMessage } = this.state;
|
||||
if (!formattedMessage) {
|
||||
@@ -61,8 +66,8 @@ export default class ChatMessageView extends Component {
|
||||
? { backgroundColor: '#667eea' }
|
||||
: { backgroundColor: messageBubbleColorForHue(displayColor) };
|
||||
const messageClassString = isSystemMessage
|
||||
? getSystemMessageClassString()
|
||||
: getChatMessageClassString();
|
||||
? 'message flex flex-row items-start p-4 m-2 rounded-lg shadow-l border-solid border-indigo-700 border-2 border-opacity-60 text-l'
|
||||
: `message relative flex flex-row items-start p-3 m-3 rounded-lg shadow-s text-sm ${isMessageModeratable ? 'moderatable' : ''}`;
|
||||
|
||||
return html`
|
||||
<div
|
||||
@@ -73,11 +78,12 @@ export default class ChatMessageView extends Component {
|
||||
<div class="message-content break-words w-full">
|
||||
<div
|
||||
style=${authorTextColor}
|
||||
class="message-author font-bold"
|
||||
class="message-author font-bold${isAuthorModerator ? ' moderator-flag' : ''}"
|
||||
title=${userMetadata}
|
||||
>
|
||||
${displayName}
|
||||
</div>
|
||||
${isMessageModeratable && html`<${ModeratorActions} message=${message} accessToken=${accessToken} />`}
|
||||
<div
|
||||
class="message-text text-gray-300 font-normal overflow-y-hidden pt-2"
|
||||
dangerouslySetInnerHTML=${{ __html: formattedMessage }}
|
||||
@@ -88,14 +94,6 @@ export default class ChatMessageView extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
function getSystemMessageClassString() {
|
||||
return 'message flex flex-row items-start p-4 m-2 rounded-lg shadow-l border-solid border-indigo-700 border-2 border-opacity-60 text-l';
|
||||
}
|
||||
|
||||
function getChatMessageClassString() {
|
||||
return 'message flex flex-row items-start p-3 m-3 rounded-lg shadow-s text-sm';
|
||||
}
|
||||
|
||||
export async function formatMessageText(message, username) {
|
||||
let formattedText = getMessageWithEmbeds(message);
|
||||
formattedText = convertToMarkup(formattedText);
|
||||
|
||||
Reference in New Issue
Block a user