Chat & reporting updates

This commit is contained in:
Bill 2022-11-15 20:18:24 -05:00
parent 47daf16872
commit e589fb7539
8 changed files with 28 additions and 78 deletions

View File

@ -1,6 +1,7 @@
export interface IChatEntry export interface IChatEntry
{ {
id: number; id: number;
webId: number;
entityId: number; entityId: number;
name: string; name: string;
look?: string; look?: string;

View File

@ -19,13 +19,13 @@ export const ReportSummaryView: FC<{}> = props =>
case ReportType.ROOM: { case ReportType.ROOM: {
const reportedRoomId = ((activeReport.roomId <= 0) ? activeReport.reportedChats[0].roomId : activeReport.roomId); const reportedRoomId = ((activeReport.roomId <= 0) ? activeReport.reportedChats[0].roomId : activeReport.roomId);
activeReport.reportedChats.forEach(entry => chats.push(entry.entityId, entry.message)); activeReport.reportedChats.forEach(entry => chats.push(entry.webId, entry.message));
SendMessageComposer(new CallForHelpMessageComposer(activeReport.message, activeReport.cfhTopic, activeReport.reportedUserId, reportedRoomId, chats)); SendMessageComposer(new CallForHelpMessageComposer(activeReport.message, activeReport.cfhTopic, activeReport.reportedUserId, reportedRoomId, chats));
break; break;
} }
case ReportType.IM: case ReportType.IM:
activeReport.reportedChats.forEach(entry => chats.push(entry.entityId, entry.message)); activeReport.reportedChats.forEach(entry => chats.push(entry.webId, entry.message));
SendMessageComposer(new CallForHelpFromIMMessageComposer(activeReport.message, activeReport.cfhTopic, activeReport.reportedUserId, chats)); SendMessageComposer(new CallForHelpFromIMMessageComposer(activeReport.message, activeReport.cfhTopic, activeReport.reportedUserId, chats));
break; break;

View File

@ -16,9 +16,9 @@ export const SelectReportedChatsView: FC<{}> = props =>
{ {
case ReportType.BULLY: case ReportType.BULLY:
case ReportType.EMERGENCY: case ReportType.EMERGENCY:
return chatHistory.filter(chat => (chat.type === ChatEntryType.TYPE_CHAT) && (chat.entityId === activeReport.reportedUserId) && (chat.entityType === RoomObjectType.USER)); return chatHistory.filter(chat => (chat.type === ChatEntryType.TYPE_CHAT) && (chat.webId === activeReport.reportedUserId) && (chat.entityType === RoomObjectType.USER));
case ReportType.IM: case ReportType.IM:
return messengerHistory.filter(chat => (chat.entityId === activeReport.reportedUserId) && (chat.type === ChatEntryType.TYPE_IM)); return messengerHistory.filter(chat => (chat.webId === activeReport.reportedUserId) && (chat.type === ChatEntryType.TYPE_IM));
} }
return []; return [];

View File

@ -16,7 +16,7 @@ export const SelectReportedUserView: FC<{}> = props =>
chatHistory.forEach(chat => chatHistory.forEach(chat =>
{ {
if((chat.type === ChatEntryType.TYPE_CHAT) && (chat.entityType === RoomObjectType.USER) && (chat.entityId !== GetSessionDataManager().userId) && !users.has(chat.entityId)) users.set(chat.entityId, { id: chat.entityId, username: chat.name }); if((chat.type === ChatEntryType.TYPE_CHAT) && (chat.entityType === RoomObjectType.USER) && (chat.webId !== GetSessionDataManager().userId) && !users.has(chat.webId)) users.set(chat.webId, { id: chat.webId, username: chat.name });
}); });
return Array.from(users.values()); return Array.from(users.values());

View File

@ -6,13 +6,12 @@ interface ChatWidgetMessageViewProps
{ {
chat: ChatBubbleMessage; chat: ChatBubbleMessage;
makeRoom: (chat: ChatBubbleMessage) => void; makeRoom: (chat: ChatBubbleMessage) => void;
onBubbleReady?: () => void;
bubbleWidth?: number; bubbleWidth?: number;
} }
export const ChatWidgetMessageView: FC<ChatWidgetMessageViewProps> = props => export const ChatWidgetMessageView: FC<ChatWidgetMessageViewProps> = props =>
{ {
const { chat = null, makeRoom = null, onBubbleReady = null, bubbleWidth = RoomChatSettings.CHAT_BUBBLE_WIDTH_NORMAL } = props; const { chat = null, makeRoom = null, bubbleWidth = RoomChatSettings.CHAT_BUBBLE_WIDTH_NORMAL } = props;
const [ isVisible, setIsVisible ] = useState(false); const [ isVisible, setIsVisible ] = useState(false);
const [ isReady, setIsReady ] = useState<boolean>(false); const [ isReady, setIsReady ] = useState<boolean>(false);
const elementRef = useRef<HTMLDivElement>(); const elementRef = useRef<HTMLDivElement>();
@ -73,10 +72,8 @@ export const ChatWidgetMessageView: FC<ChatWidgetMessageViewProps> = props =>
if(makeRoom) makeRoom(chat); if(makeRoom) makeRoom(chat);
if(onBubbleReady) onBubbleReady();
setIsVisible(true); setIsVisible(true);
}, [ chat, isReady, isVisible, makeRoom, onBubbleReady ]); }, [ chat, isReady, isVisible, makeRoom ]);
return ( return (
<div ref={ elementRef } className={ `bubble-container ${ isVisible ? 'visible' : 'invisible' }` } onClick={ event => GetRoomEngine().selectRoomObject(chat.roomId, chat.senderId, RoomObjectCategory.UNIT) }> <div ref={ elementRef } className={ `bubble-container ${ isVisible ? 'visible' : 'invisible' }` } onClick={ event => GetRoomEngine().selectRoomObject(chat.roomId, chat.senderId, RoomObjectCategory.UNIT) }>

View File

@ -1,24 +1,19 @@
import { RoomChatSettings } from '@nitrots/nitro-renderer'; import { RoomChatSettings } from '@nitrots/nitro-renderer';
import { FC, useCallback, useEffect, useRef, useState } from 'react'; import { FC, useCallback, useEffect, useRef } from 'react';
import { ChatBubbleMessage, DoChatsOverlap, GetConfiguration } from '../../../../api'; import { ChatBubbleMessage, DoChatsOverlap, GetConfiguration } from '../../../../api';
import { useChatWidget } from '../../../../hooks'; import { useChatWidget } from '../../../../hooks';
import IntervalWebWorker from '../../../../workers/IntervalWebWorker'; import IntervalWebWorker from '../../../../workers/IntervalWebWorker';
import { WorkerBuilder } from '../../../../workers/WorkerBuilder'; import { WorkerBuilder } from '../../../../workers/WorkerBuilder';
import { ChatWidgetMessageView } from './ChatWidgetMessageView'; import { ChatWidgetMessageView } from './ChatWidgetMessageView';
let TIMER_TRACKER: number = 0;
export const ChatWidgetView: FC<{}> = props => export const ChatWidgetView: FC<{}> = props =>
{ {
const [ timerId, setTimerId ] = useState(TIMER_TRACKER++); const { chatMessages = [], setChatMessages = null, chatSettings = null, getScrollSpeed = 6000 } = useChatWidget();
const { pendingChats = null, chatSettings = null, getScrollSpeed = 6000 } = useChatWidget();
const [ renderedChats, setRenderedChats ] = useState<ChatBubbleMessage[]>([]);
const elementRef = useRef<HTMLDivElement>(); const elementRef = useRef<HTMLDivElement>();
const isProcessing = useRef<boolean>(false);
const removeHiddenChats = useCallback(() => const removeHiddenChats = useCallback(() =>
{ {
setRenderedChats(prevValue => setChatMessages(prevValue =>
{ {
if(prevValue) if(prevValue)
{ {
@ -29,22 +24,16 @@ export const ChatWidgetView: FC<{}> = props =>
return prevValue; return prevValue;
}) })
}, []); }, [ setChatMessages ]);
const checkOverlappingChats = useCallback((chat: ChatBubbleMessage, moved: number, tempChats: ChatBubbleMessage[]) => const checkOverlappingChats = useCallback((chat: ChatBubbleMessage, moved: number, tempChats: ChatBubbleMessage[]) =>
{ {
const totalChats = renderedChats.length; for(let i = (chatMessages.indexOf(chat) - 1); i >= 0; i--)
if(!totalChats) return;
for(let i = (totalChats - 1); i >= 0; i--)
{ {
const collides = renderedChats[i]; const collides = chatMessages[i];
if(!collides || (chat === collides) || (tempChats.indexOf(collides) >= 0) || (((collides.top + collides.height) - moved) > (chat.top + chat.height))) continue; if(!collides || (chat === collides) || (tempChats.indexOf(collides) >= 0) || (((collides.top + collides.height) - moved) > (chat.top + chat.height))) continue;
chat.skipMovement = true;
if(DoChatsOverlap(chat, collides, -moved, 0)) if(DoChatsOverlap(chat, collides, -moved, 0))
{ {
const amount = Math.abs((collides.top + collides.height) - chat.top); const amount = Math.abs((collides.top + collides.height) - chat.top);
@ -57,7 +46,7 @@ export const ChatWidgetView: FC<{}> = props =>
checkOverlappingChats(collides, amount, tempChats); checkOverlappingChats(collides, amount, tempChats);
} }
} }
}, [ renderedChats ]); }, [ chatMessages ]);
const makeRoom = useCallback((chat: ChatBubbleMessage) => const makeRoom = useCallback((chat: ChatBubbleMessage) =>
{ {
@ -78,7 +67,7 @@ export const ChatWidgetView: FC<{}> = props =>
if(spaceAvailable < requiredSpace) if(spaceAvailable < requiredSpace)
{ {
setRenderedChats(prevValue => setChatMessages(prevValue =>
{ {
prevValue.forEach(prevChat => prevValue.forEach(prevChat =>
{ {
@ -93,12 +82,7 @@ export const ChatWidgetView: FC<{}> = props =>
removeHiddenChats(); removeHiddenChats();
} }
} }
}, [ chatSettings, checkOverlappingChats, removeHiddenChats ]); }, [ chatSettings, checkOverlappingChats, removeHiddenChats, setChatMessages ]);
const onBubbleReady = useCallback(() =>
{
isProcessing.current = false;
}, []);
useEffect(() => useEffect(() =>
{ {
@ -111,7 +95,7 @@ export const ChatWidgetView: FC<{}> = props =>
elementRef.current.style.height = `${ newHeight }px`; elementRef.current.style.height = `${ newHeight }px`;
setRenderedChats(prevValue => setChatMessages(prevValue =>
{ {
if(prevValue) if(prevValue)
{ {
@ -130,40 +114,13 @@ export const ChatWidgetView: FC<{}> = props =>
{ {
window.removeEventListener('resize', resize); window.removeEventListener('resize', resize);
} }
}, []); }, [ setChatMessages ]);
useEffect(() =>
{
const processNextChat = () =>
{
if(isProcessing.current) return;
const chat = pendingChats?.current?.shift();
if(!chat) return;
isProcessing.current = true;
setRenderedChats(prevValue => [ ...prevValue, chat ]);
}
const worker = new WorkerBuilder(IntervalWebWorker);
worker.onmessage = () => processNextChat();
worker.postMessage({ action: 'START', content: 50 });
return () =>
{
worker.postMessage({ action: 'STOP' });
}
}, [ pendingChats ]);
useEffect(() => useEffect(() =>
{ {
const moveAllChatsUp = (amount: number) => const moveAllChatsUp = (amount: number) =>
{ {
setRenderedChats(prevValue => setChatMessages(prevValue =>
{ {
prevValue.forEach(chat => prevValue.forEach(chat =>
{ {
@ -185,10 +142,7 @@ export const ChatWidgetView: FC<{}> = props =>
const worker = new WorkerBuilder(IntervalWebWorker); const worker = new WorkerBuilder(IntervalWebWorker);
worker.onmessage = () => worker.onmessage = () => moveAllChatsUp(15);
{
moveAllChatsUp(15);
}
worker.postMessage({ action: 'START', content: getScrollSpeed }); worker.postMessage({ action: 'START', content: getScrollSpeed });
@ -196,11 +150,11 @@ export const ChatWidgetView: FC<{}> = props =>
{ {
worker.postMessage({ action: 'STOP' }); worker.postMessage({ action: 'STOP' });
} }
}, [ getScrollSpeed, removeHiddenChats ]); }, [ getScrollSpeed, removeHiddenChats, setChatMessages ]);
return ( return (
<div ref={ elementRef } className="nitro-chat-widget"> <div ref={ elementRef } className="nitro-chat-widget">
{ renderedChats.map(chat => <ChatWidgetMessageView key={ chat.id } chat={ chat } makeRoom={ makeRoom } onBubbleReady={ onBubbleReady } bubbleWidth={ chatSettings.weight } />) } { chatMessages.map(chat => <ChatWidgetMessageView key={ chat.id } chat={ chat } makeRoom={ makeRoom } bubbleWidth={ chatSettings.weight } />) }
</div> </div>
); );
} }

View File

@ -77,7 +77,7 @@ const useChatHistoryState = () =>
if(roomHistory[(roomHistory.length - 1)].id === parser.data.roomId) return; if(roomHistory[(roomHistory.length - 1)].id === parser.data.roomId) return;
} }
addChatEntry({ id: -1, entityId: parser.data.roomId, name: parser.data.roomName, timestamp: ChatHistoryCurrentDate(), type: ChatEntryType.TYPE_ROOM_INFO, roomId: parser.data.roomId }); addChatEntry({ id: -1, webId: -1, entityId: -1, name: parser.data.roomName, timestamp: ChatHistoryCurrentDate(), type: ChatEntryType.TYPE_ROOM_INFO, roomId: parser.data.roomId });
addRoomHistoryEntry({ id: parser.data.roomId, name: parser.data.roomName }); addRoomHistoryEntry({ id: parser.data.roomId, name: parser.data.roomName });
@ -88,14 +88,14 @@ const useChatHistoryState = () =>
{ {
const parser = event.getParser(); const parser = event.getParser();
addMessengerEntry({ id: -1, entityId: parser.senderId, name: '', message: parser.messageText, roomId: -1, timestamp: MessengerHistoryCurrentDate(parser.secondsSinceSent), type: ChatEntryType.TYPE_IM }); addMessengerEntry({ id: -1, webId: parser.senderId, entityId: -1, name: '', message: parser.messageText, roomId: -1, timestamp: MessengerHistoryCurrentDate(parser.secondsSinceSent), type: ChatEntryType.TYPE_IM });
}); });
useMessageEvent<RoomInviteEvent>(RoomInviteEvent, event => useMessageEvent<RoomInviteEvent>(RoomInviteEvent, event =>
{ {
const parser = event.getParser(); const parser = event.getParser();
addMessengerEntry({ id: -1, entityId: parser.senderId, name: '', message: parser.messageText, roomId: -1, timestamp: MessengerHistoryCurrentDate(), type: ChatEntryType.TYPE_IM }); addMessengerEntry({ id: -1, webId: parser.senderId, entityId: -1, name: '', message: parser.messageText, roomId: -1, timestamp: MessengerHistoryCurrentDate(), type: ChatEntryType.TYPE_IM });
}); });
return { addChatEntry, chatHistory, roomHistory, messengerHistory }; return { addChatEntry, chatHistory, roomHistory, messengerHistory };

View File

@ -22,7 +22,6 @@ const useChatWidgetState = () =>
const { roomSession = null } = useRoom(); const { roomSession = null } = useRoom();
const { addChatEntry } = useChatHistory(); const { addChatEntry } = useChatHistory();
const isDisposed = useRef(false); const isDisposed = useRef(false);
const pendingChats = useRef<ChatBubbleMessage[]>([]);
const getScrollSpeed = useMemo(() => const getScrollSpeed = useMemo(() =>
{ {
@ -209,8 +208,7 @@ const useChatWidgetState = () =>
color); color);
setChatMessages(prevValue => [ ...prevValue, chatMessage ]); setChatMessages(prevValue => [ ...prevValue, chatMessage ]);
pendingChats?.current?.push(chatMessage); addChatEntry({ id: -1, webId: userData.webID, entityId: userData.roomIndex, name: username, imageUrl, style: styleId, chatType: chatType, entityType: userData.type, message: formattedText, timestamp: ChatHistoryCurrentDate(), type: ChatEntryType.TYPE_CHAT, roomId: roomSession.roomId, color });
addChatEntry({ id: -1, entityId: userData.roomIndex, name: username, imageUrl, style: styleId, chatType: chatType, entityType: userData.type, message: formattedText, timestamp: ChatHistoryCurrentDate(), type: ChatEntryType.TYPE_CHAT, roomId: roomSession.roomId, color });
}); });
useRoomEngineEvent<RoomDragEvent>(RoomDragEvent.ROOM_DRAG, event => useRoomEngineEvent<RoomDragEvent>(RoomDragEvent.ROOM_DRAG, event =>
@ -248,7 +246,7 @@ const useChatWidgetState = () =>
} }
}, []); }, []);
return { chatMessages, setChatMessages, chatSettings, getScrollSpeed, pendingChats }; return { chatMessages, setChatMessages, chatSettings, getScrollSpeed };
} }
export const useChatWidget = useChatWidgetState; export const useChatWidget = useChatWidgetState;