Chats move

This commit is contained in:
Bill 2021-06-30 06:10:19 -04:00
parent dfaf239052
commit 37d614e168
6 changed files with 140 additions and 70 deletions

View File

@ -0,0 +1,41 @@
import { NitroPoint, NitroRectangle } from 'nitro-renderer';
import { RoomWidgetUpdateEvent } from './RoomWidgetUpdateEvent';
export class RoomWidgetRoomViewUpdateEvent extends RoomWidgetUpdateEvent
{
public static SIZE_CHANGED: string = 'RWRVUE_ROOM_VIEW_SIZE_CHANGED';
public static SCALE_CHANGED: string = 'RWRVUE_ROOM_VIEW_SCALE_CHANGED';
public static POSITION_CHANGED: string = 'RWRVUE_ROOM_VIEW_POSITION_CHANGED';
private _roomViewRectangle: NitroRectangle;
private _positionDelta: NitroPoint;
private _scale: number;
constructor(type: string, view: NitroRectangle = null, position: NitroPoint = null, scale: number = 0)
{
super(type);
this._roomViewRectangle = view;
this._positionDelta = position;
this._scale = scale;
}
public get roomViewRectangle(): NitroRectangle
{
if(!this._roomViewRectangle) return null;
return this._roomViewRectangle.clone();
}
public get positionDelta(): NitroPoint
{
if(!this._positionDelta) return null;
return this._positionDelta.clone();
}
public get scale(): number
{
return this._scale;
}
}

View File

@ -2,6 +2,7 @@ export * from './RoomWidgetAvatarInfoEvent';
export * from './RoomWidgetObjectNameEvent';
export * from './RoomWidgetRoomEngineUpdateEvent';
export * from './RoomWidgetRoomObjectUpdateEvent';
export * from './RoomWidgetRoomViewUpdateEvent';
export * from './RoomWidgetUpdateDanceStatusEvent';
export * from './RoomWidgetUpdateEvent';
export * from './RoomWidgetUpdateInfostandEvent';

View File

@ -1,6 +1,7 @@
import { RoomObjectCategory, RoomSessionChatEvent } from 'nitro-renderer';
import { RoomDragEvent, RoomObjectCategory, RoomSessionChatEvent } from 'nitro-renderer';
import { FC, useCallback, useEffect, useRef, useState } from 'react';
import { GetRoomEngine, GetRoomSession } from '../../../../api';
import { useRoomEngineEvent } from '../../../../hooks/events';
import { useRoomSessionManagerEvent } from '../../../../hooks/events/nitro/session/room-session-manager-event';
import { useRoomContext } from '../../context/RoomContext';
import { ChatWidgetViewProps } from './ChatWidgetView.types';
@ -10,8 +11,8 @@ import { GetBubbleLocation } from './utils/ChatWidgetUtilities';
export const ChatWidgetView: FC<ChatWidgetViewProps> = props =>
{
const { eventDispatcher = null, widgetHandler = null } = useRoomContext();
const [ chatMessages, setChatMessages ] = useState<ChatBubbleMessage[]>([]);
const { roomSession = null } = useRoomContext();
const elementRef = useRef<HTMLDivElement>();
const removeFirstHiddenChat = useCallback(() =>
@ -20,7 +21,7 @@ export const ChatWidgetView: FC<ChatWidgetViewProps> = props =>
const lastChat = chatMessages[0];
if((lastChat.lastTop > (-(lastChat.height) * 2))) return;
if((lastChat.top > (-(lastChat.height) * 2))) return;
setChatMessages(prevValue =>
{
@ -34,9 +35,7 @@ export const ChatWidgetView: FC<ChatWidgetViewProps> = props =>
const moveChatUp = useCallback((chat: ChatBubbleMessage, amount: number) =>
{
chat.lastTop -= amount;
if(chat.elementRef) chat.elementRef.style.top = (chat.lastTop + 'px');
chat.top -= amount;
}, []);
const moveAllChatsUp = useCallback((amount: number) =>
@ -48,7 +47,7 @@ export const ChatWidgetView: FC<ChatWidgetViewProps> = props =>
const makeRoom = useCallback((chat: ChatBubbleMessage) =>
{
const lowestPoint = ((chat.lastTop + chat.height) - 1);
const lowestPoint = ((chat.top + chat.height) - 1);
const requiredSpace = (chat.height + 1);
const spaceAvailable = (elementRef.current.offsetHeight - lowestPoint);
@ -56,11 +55,11 @@ export const ChatWidgetView: FC<ChatWidgetViewProps> = props =>
{
const amount = (requiredSpace - spaceAvailable);
chatMessages.forEach((existingChat, index) =>
chatMessages.forEach(existingChat =>
{
if(existingChat === chat) return;
moveChatUp(existingChat, amount)
moveChatUp(existingChat, amount);
});
}
}, [ chatMessages, moveChatUp ]);
@ -69,7 +68,7 @@ export const ChatWidgetView: FC<ChatWidgetViewProps> = props =>
{
setChatMessages(prevValue =>
{
return [ ...prevValue, chat ]
return [ ...prevValue, chat ];
});
}, []);
@ -80,11 +79,6 @@ export const ChatWidgetView: FC<ChatWidgetViewProps> = props =>
if(!roomObject) return;
const canvasId = 1;
const roomGeometry = GetRoomEngine().getRoomInstanceGeometry(event.session.roomId, canvasId);
if(!roomGeometry) return;
const objectLocation = roomObject.getLocation();
const bubbleLocation = GetBubbleLocation(event.session.roomId, objectLocation, canvasId);
const userData = GetRoomSession().userDataManager.getUserDataByIndex(event.objectId);
@ -138,31 +132,37 @@ export const ChatWidgetView: FC<ChatWidgetViewProps> = props =>
useRoomSessionManagerEvent(RoomSessionChatEvent.CHAT_EVENT, onRoomSessionChatEvent);
// useEffect(() =>
// {
// const interval = setInterval(() => moveAllChatsUp(15), 500);
const onRoomDragEvent = useCallback((event: RoomDragEvent) =>
{
if(!chatMessages.length) return;
// return () =>
// {
// if(interval) clearInterval(interval);
// }
// }, [ chatMessages, moveAllChatsUp ]);
if(event.roomId !== roomSession.roomId) return;
chatMessages.forEach(chat =>
{
if(!chat.elementRef) return;
chat.left = (chat.elementRef.offsetLeft + event.offsetX);
});
}, [ roomSession, chatMessages ]);
useRoomEngineEvent(RoomDragEvent.ROOM_DRAG, onRoomDragEvent);
useEffect(() =>
{
const interval = setInterval(() => removeFirstHiddenChat(), 1000);
const interval = setInterval(() => moveAllChatsUp(15), 4500);
return () =>
{
if(interval) clearInterval(interval);
}
}, [ removeFirstHiddenChat ]);
}, [ chatMessages, moveAllChatsUp ]);
return (
<div ref={ elementRef } className="nitro-chat-widget">
{ chatMessages && (chatMessages.length > 0) && chatMessages.map((chat, index) =>
{ chatMessages.map(chat =>
{
return <ChatWidgetMessageView key={ index } chat={ chat } makeRoom={ makeRoom } />
return <ChatWidgetMessageView key={ chat.id } chat={ chat } makeRoom={ makeRoom } />
})}
</div>
);

View File

@ -1,11 +1,10 @@
import { FC, MouseEvent, useCallback, useEffect, useRef, useState } from 'react';
import { GetSessionDataManager } from '../../../../../api';
import { ChatWidgetMessageViewProps } from './ChatWidgetMessageView.types';
export const ChatWidgetMessageView: FC<ChatWidgetMessageViewProps> = props =>
{
const { chat = null, makeRoom = null } = props;
const [ isVisible, setIsVisible ] = useState(true);
const [ isVisible, setIsVisible ] = useState(false);
const [ messageParts, setMessageParts ] = useState<{text: string, className?: string, style?: any, onClick?: () => void}[]>(null);
const elementRef = useRef<HTMLDivElement>();
@ -14,37 +13,37 @@ export const ChatWidgetMessageView: FC<ChatWidgetMessageViewProps> = props =>
}, []);
useEffect(() =>
{
if(messageParts) return;
// useEffect(() =>
// {
// if(messageParts) return;
const userNameMention = '@' + GetSessionDataManager().userName;
// const userNameMention = '@' + GetSessionDataManager().userName;
const matches = [...chat.text.matchAll(new RegExp(userNameMention + '\\b', 'gi'))];
// const matches = [...chat.text.matchAll(new RegExp(userNameMention + '\\b', 'gi'))];
if(matches.length > 0)
{
const prevText = chat.text.substr(0, matches[0].index);
const postText = chat.text.substring(matches[0].index + userNameMention.length, chat.text.length);
// if(matches.length > 0)
// {
// const prevText = chat.text.substr(0, matches[0].index);
// const postText = chat.text.substring(matches[0].index + userNameMention.length, chat.text.length);
setMessageParts(
[
{ text: prevText },
{ text: userNameMention, className: 'chat-mention', onClick: () => {alert('I clicked in the mention')}},
{ text: postText }
]
);
}
else
{
setMessageParts(
[
{ text: chat.text }
]
);
}
// setMessageParts(
// [
// { text: prevText },
// { text: userNameMention, className: 'chat-mention', onClick: () => {alert('I clicked in the mention')}},
// { text: postText }
// ]
// );
// }
// else
// {
// setMessageParts(
// [
// { text: chat.text }
// ]
// );
// }
}, [ chat ]);
// }, [ chat ]);
useEffect(() =>
{
@ -59,34 +58,35 @@ export const ChatWidgetMessageView: FC<ChatWidgetMessageViewProps> = props =>
chat.height = height;
chat.elementRef = element;
let left = chat.lastLeft;
let top = chat.lastTop;
let left = chat.left;
let top = chat.top;
if(!left && !top)
{
left = (chat.location.x - (width / 2));
top = (element.parentElement.offsetHeight - height);
chat.lastLeft = left;
chat.lastTop = top;
chat.left = left;
chat.top = top;
}
element.style.left = (left + 'px');
element.style.top = (top + 'px');
if(!chat.visible)
{
makeRoom(chat);
}
chat.visible = true;
//setIsVisible(true);
chat.visible = true;
}
return () =>
{
chat.elementRef = null;
}
}, [ elementRef, isVisible, chat, makeRoom ]);
}, [ elementRef, chat, makeRoom ]);
useEffect(() =>
{
setIsVisible(chat.visible);
}, [ chat.visible ]);
return (
<div ref={ elementRef } className="bubble-container" style={ { visibility: (isVisible ? 'visible' : 'hidden') } }>
@ -96,7 +96,9 @@ export const ChatWidgetMessageView: FC<ChatWidgetMessageViewProps> = props =>
{ (chat.imageUrl && (chat.imageUrl !== '')) && <div className="user-image" style={ { backgroundImage: 'url(' + chat.imageUrl + ')' } } /> }
</div>
<div className="chat-content">
<b className="username mr-1">{ chat.username }</b><span className="message"> {
<b className="username mr-1">{ chat.username }</b>
{ chat.text }
<span className="message"> {
messageParts && messageParts.map((part, index) =>
{
return <span key={ index } className={ part.className } style={ part.style } onClick={ part.onClick }>{ part.text }</span>

View File

@ -2,15 +2,16 @@ import { INitroPoint } from 'nitro-renderer';
export class ChatBubbleMessage
{
public static BUBBLE_COUNTER: number = -1;
public static BUBBLE_COUNTER: number = 0;
public id: number = -1;
public width: number = 0;
public height: number = 0;
public lastTop: number = 0;
public lastLeft: number = 0;
public elementRef: HTMLDivElement = null;
public visible: boolean = false;
private _top: number = 0;
private _left: number = 0;
constructor(
public text: string = '',
@ -23,4 +24,28 @@ export class ChatBubbleMessage
) {
this.id = ++ChatBubbleMessage.BUBBLE_COUNTER;
}
public get top(): number
{
return this._top;
}
public set top(value: number)
{
this._top = value;
if(this.elementRef) this.elementRef.style.top = (this._top + 'px');
}
public get left(): number
{
return this._top;
}
public set left(value: number)
{
this._left = value;
if(this.elementRef) this.elementRef.style.left = (this._left + 'px');
}
}

View File

@ -6,6 +6,7 @@
border: 2px solid rgba($white, 0.5);
border-radius: $border-radius;
font-size: $font-size-sm;
z-index: $context-menu-zindex;
&.name-only {
background-color: rgba($black, 0.7);