mirror of
https://github.com/billsonnn/nitro-react.git
synced 2024-11-26 07:30:51 +01:00
Update chat
This commit is contained in:
parent
1d782ebbf5
commit
1a8bf75a0d
@ -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;
|
||||
|
@ -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) }>
|
||||
|
@ -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,17 +76,50 @@ 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(() =>
|
||||
{
|
||||
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user