Update chat

This commit is contained in:
Bill 2022-11-13 20:59:55 -05:00
parent 1d782ebbf5
commit 1a8bf75a0d
4 changed files with 90 additions and 29 deletions

View File

@ -8,7 +8,6 @@ export class ChatBubbleMessage
public width: number = 0;
public height: number = 0;
public elementRef: HTMLDivElement = null;
public visible: boolean = false;
public skipMovement: boolean = false;
private _top: number = 0;

View File

@ -6,13 +6,15 @@ interface ChatWidgetMessageViewProps
{
chat: ChatBubbleMessage;
makeRoom: (chat: ChatBubbleMessage) => void;
onBubbleReady?: () => void;
bubbleWidth?: number;
}
export const ChatWidgetMessageView: FC<ChatWidgetMessageViewProps> = props =>
{
const { chat = null, makeRoom = null, bubbleWidth = RoomChatSettings.CHAT_BUBBLE_WIDTH_NORMAL } = props;
const { chat = null, makeRoom = null, onBubbleReady = null, bubbleWidth = RoomChatSettings.CHAT_BUBBLE_WIDTH_NORMAL } = props;
const [ isVisible, setIsVisible ] = useState(false);
const [ isReady, setIsReady ] = useState<boolean>(false);
const elementRef = useRef<HTMLDivElement>();
const getBubbleWidth = useMemo(() =>
@ -30,6 +32,8 @@ export const ChatWidgetMessageView: FC<ChatWidgetMessageViewProps> = props =>
useEffect(() =>
{
setIsVisible(false);
const element = elementRef.current;
if(!element) return;
@ -53,20 +57,26 @@ export const ChatWidgetMessageView: FC<ChatWidgetMessageViewProps> = props =>
chat.top = top;
}
if(!chat.visible)
{
makeRoom(chat);
chat.visible = true;
}
setIsReady(true);
return () =>
{
chat.elementRef = null;
}
}, [ elementRef, chat, makeRoom ]);
useEffect(() => setIsVisible(chat.visible), [ chat.visible ]);
setIsReady(false);
}
}, [ chat ]);
useEffect(() =>
{
if(!isReady || !chat || isVisible) return;
if(makeRoom) makeRoom(chat);
if(onBubbleReady) onBubbleReady();
setIsVisible(true);
}, [ chat, isReady, isVisible, makeRoom, onBubbleReady ]);
return (
<div ref={ elementRef } className={ `bubble-container ${ isVisible ? 'visible' : 'invisible' }` } onClick={ event => GetRoomEngine().selectRoomObject(chat.roomId, chat.senderId, RoomObjectCategory.UNIT) }>

View File

@ -1,5 +1,5 @@
import { IWorkerEventTracker, RoomChatSettings } from '@nitrots/nitro-renderer';
import { FC, useEffect, useRef, useState } from 'react';
import { FC, useCallback, useEffect, useRef, useState } from 'react';
import { AddWorkerEventTracker, ChatBubbleMessage, DoChatsOverlap, GetConfiguration, RemoveWorkerEventTracker, SendWorkerEvent } from '../../../../api';
import { useChatWidget } from '../../../../hooks';
import { ChatWidgetMessageView } from './ChatWidgetMessageView';
@ -9,18 +9,35 @@ let TIMER_TRACKER: number = 0;
export const ChatWidgetView: FC<{}> = props =>
{
const [ timerId, setTimerId ] = useState(TIMER_TRACKER++);
const { chatMessages = [], setChatMessages = null, chatSettings = null, getScrollSpeed = 6000, removeHiddenChats = null, moveAllChatsUp = null } = useChatWidget();
const { pendingChats = null, chatSettings = null, getScrollSpeed = 6000, moveAllChatsUp = null } = useChatWidget();
const [ renderedChats, setRenderedChats ] = useState<ChatBubbleMessage[]>([]);
const elementRef = useRef<HTMLDivElement>();
const isProcessing = useRef<boolean>(false);
const checkOverlappingChats = (chat: ChatBubbleMessage, moved: number, tempChats: ChatBubbleMessage[]) =>
const removeHiddenChats = useCallback(() =>
{
const totalChats = chatMessages.length;
setRenderedChats(prevValue =>
{
if(prevValue)
{
const newMessages = prevValue.filter(chat => ((chat.top > (-(chat.height) * 2))));
if(newMessages.length !== prevValue.length) return newMessages;
}
return prevValue;
})
}, []);
const checkOverlappingChats = useCallback((chat: ChatBubbleMessage, moved: number, tempChats: ChatBubbleMessage[]) =>
{
const totalChats = renderedChats.length;
if(!totalChats) return;
for(let i = (totalChats - 1); i >= 0; i--)
{
const collides = chatMessages[i];
const collides = renderedChats[i];
if(!collides || (chat === collides) || (tempChats.indexOf(collides) >= 0) || (((collides.top + collides.height) - moved) > (chat.top + chat.height))) continue;
@ -38,9 +55,9 @@ export const ChatWidgetView: FC<{}> = props =>
checkOverlappingChats(collides, amount, tempChats);
}
}
}
}, [ renderedChats ]);
const makeRoom = (chat: ChatBubbleMessage) =>
const makeRoom = useCallback((chat: ChatBubbleMessage) =>
{
if(chatSettings.mode === RoomChatSettings.CHAT_MODE_FREE_FLOW)
{
@ -59,18 +76,51 @@ export const ChatWidgetView: FC<{}> = props =>
if(spaceAvailable < requiredSpace)
{
chatMessages.forEach(existingChat =>
setRenderedChats(prevValue =>
{
if(existingChat === chat) return;
prevValue.forEach(prevChat =>
{
if(prevChat === chat) return;
existingChat.top -= amount;
prevChat.top -= amount;
});
return prevValue;
});
removeHiddenChats();
}
}
}, [ chatSettings, checkOverlappingChats, removeHiddenChats ]);
const onBubbleReady = useCallback(() =>
{
isProcessing.current = false;
}, []);
useEffect(() =>
{
const processNextChat = () =>
{
if(isProcessing.current) return;
const chat = pendingChats?.current?.shift();
if(!chat) return;
isProcessing.current = true;
setRenderedChats(prevValue => [ ...prevValue, chat ]);
}
const interval = setInterval(() => processNextChat(), 50);
return () =>
{
clearInterval(interval);
}
}, [ pendingChats ]);
useEffect(() =>
{
const resize = (event: UIEvent = null) =>
@ -82,7 +132,7 @@ export const ChatWidgetView: FC<{}> = props =>
elementRef.current.style.height = `${ newHeight }px`;
setChatMessages(prevValue =>
setRenderedChats(prevValue =>
{
if(prevValue)
{
@ -101,7 +151,7 @@ export const ChatWidgetView: FC<{}> = props =>
{
window.removeEventListener('resize', resize);
}
}, [ setChatMessages ]);
}, []);
useEffect(() =>
{
@ -139,7 +189,7 @@ export const ChatWidgetView: FC<{}> = props =>
return (
<div ref={ elementRef } className="nitro-chat-widget">
{ chatMessages.map(chat => <ChatWidgetMessageView key={ chat.id } chat={ chat } makeRoom={ makeRoom } bubbleWidth={ chatSettings.weight } />) }
{ renderedChats.map(chat => <ChatWidgetMessageView key={ chat.id } chat={ chat } makeRoom={ makeRoom } onBubbleReady={ onBubbleReady } bubbleWidth={ chatSettings.weight } />) }
</div>
);
}

View File

@ -1,5 +1,5 @@
import { AvatarFigurePartType, AvatarScaleType, AvatarSetType, GetGuestRoomResultEvent, NitroPoint, PetFigureData, RoomChatSettings, RoomChatSettingsEvent, RoomDragEvent, RoomObjectCategory, RoomObjectType, RoomObjectVariable, RoomSessionChatEvent, RoomUserData, SystemChatStyleEnum, TextureUtils, Vector3d } from '@nitrots/nitro-renderer';
import { useEffect, useMemo, useRef, useState } from 'react';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { ChatBubbleMessage, ChatEntryType, ChatHistoryCurrentDate, GetAvatarRenderManager, GetConfiguration, GetRoomEngine, GetRoomObjectScreenLocation, IRoomChatSettings, LocalizeText, PlaySound, RoomChatFormatter } from '../../../api';
import { useMessageEvent, useRoomEngineEvent, useRoomSessionManagerEvent } from '../../events';
import { useRoom } from '../useRoom';
@ -22,6 +22,7 @@ const useChatWidgetState = () =>
const { roomSession = null } = useRoom();
const { addChatEntry } = useChatHistory();
const isDisposed = useRef(false);
const pendingChats = useRef<ChatBubbleMessage[]>([]);
const getScrollSpeed = useMemo(() =>
{
@ -95,7 +96,7 @@ const useChatWidgetState = () =>
return existing;
}
const removeHiddenChats = () =>
const removeHiddenChats = useCallback(() =>
{
setChatMessages(prevValue =>
{
@ -108,7 +109,7 @@ const useChatWidgetState = () =>
return prevValue;
})
}
}, []);
const moveAllChatsUp = (amount: number) =>
{
@ -248,6 +249,7 @@ const useChatWidgetState = () =>
color);
setChatMessages(prevValue => [ ...prevValue, chatMessage ]);
pendingChats?.current?.push(chatMessage);
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 });
});
@ -286,7 +288,7 @@ const useChatWidgetState = () =>
}
}, []);
return { chatMessages, setChatMessages, chatSettings, getScrollSpeed, removeHiddenChats, moveAllChatsUp };
return { chatMessages, setChatMessages, chatSettings, getScrollSpeed, removeHiddenChats, moveAllChatsUp, pendingChats };
}
export const useChatWidget = useChatWidgetState;