mirror of
https://github.com/billsonnn/nitro-react.git
synced 2025-01-19 05:46:27 +01:00
Chats move
This commit is contained in:
parent
dfaf239052
commit
37d614e168
41
src/views/room/events/RoomWidgetRoomViewUpdateEvent.ts
Normal file
41
src/views/room/events/RoomWidgetRoomViewUpdateEvent.ts
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@ export * from './RoomWidgetAvatarInfoEvent';
|
|||||||
export * from './RoomWidgetObjectNameEvent';
|
export * from './RoomWidgetObjectNameEvent';
|
||||||
export * from './RoomWidgetRoomEngineUpdateEvent';
|
export * from './RoomWidgetRoomEngineUpdateEvent';
|
||||||
export * from './RoomWidgetRoomObjectUpdateEvent';
|
export * from './RoomWidgetRoomObjectUpdateEvent';
|
||||||
|
export * from './RoomWidgetRoomViewUpdateEvent';
|
||||||
export * from './RoomWidgetUpdateDanceStatusEvent';
|
export * from './RoomWidgetUpdateDanceStatusEvent';
|
||||||
export * from './RoomWidgetUpdateEvent';
|
export * from './RoomWidgetUpdateEvent';
|
||||||
export * from './RoomWidgetUpdateInfostandEvent';
|
export * from './RoomWidgetUpdateInfostandEvent';
|
||||||
|
@ -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 { FC, useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { GetRoomEngine, GetRoomSession } from '../../../../api';
|
import { GetRoomEngine, GetRoomSession } from '../../../../api';
|
||||||
|
import { useRoomEngineEvent } from '../../../../hooks/events';
|
||||||
import { useRoomSessionManagerEvent } from '../../../../hooks/events/nitro/session/room-session-manager-event';
|
import { useRoomSessionManagerEvent } from '../../../../hooks/events/nitro/session/room-session-manager-event';
|
||||||
import { useRoomContext } from '../../context/RoomContext';
|
import { useRoomContext } from '../../context/RoomContext';
|
||||||
import { ChatWidgetViewProps } from './ChatWidgetView.types';
|
import { ChatWidgetViewProps } from './ChatWidgetView.types';
|
||||||
@ -10,8 +11,8 @@ import { GetBubbleLocation } from './utils/ChatWidgetUtilities';
|
|||||||
|
|
||||||
export const ChatWidgetView: FC<ChatWidgetViewProps> = props =>
|
export const ChatWidgetView: FC<ChatWidgetViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { eventDispatcher = null, widgetHandler = null } = useRoomContext();
|
|
||||||
const [ chatMessages, setChatMessages ] = useState<ChatBubbleMessage[]>([]);
|
const [ chatMessages, setChatMessages ] = useState<ChatBubbleMessage[]>([]);
|
||||||
|
const { roomSession = null } = useRoomContext();
|
||||||
const elementRef = useRef<HTMLDivElement>();
|
const elementRef = useRef<HTMLDivElement>();
|
||||||
|
|
||||||
const removeFirstHiddenChat = useCallback(() =>
|
const removeFirstHiddenChat = useCallback(() =>
|
||||||
@ -20,7 +21,7 @@ export const ChatWidgetView: FC<ChatWidgetViewProps> = props =>
|
|||||||
|
|
||||||
const lastChat = chatMessages[0];
|
const lastChat = chatMessages[0];
|
||||||
|
|
||||||
if((lastChat.lastTop > (-(lastChat.height) * 2))) return;
|
if((lastChat.top > (-(lastChat.height) * 2))) return;
|
||||||
|
|
||||||
setChatMessages(prevValue =>
|
setChatMessages(prevValue =>
|
||||||
{
|
{
|
||||||
@ -34,9 +35,7 @@ export const ChatWidgetView: FC<ChatWidgetViewProps> = props =>
|
|||||||
|
|
||||||
const moveChatUp = useCallback((chat: ChatBubbleMessage, amount: number) =>
|
const moveChatUp = useCallback((chat: ChatBubbleMessage, amount: number) =>
|
||||||
{
|
{
|
||||||
chat.lastTop -= amount;
|
chat.top -= amount;
|
||||||
|
|
||||||
if(chat.elementRef) chat.elementRef.style.top = (chat.lastTop + 'px');
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const moveAllChatsUp = useCallback((amount: number) =>
|
const moveAllChatsUp = useCallback((amount: number) =>
|
||||||
@ -48,7 +47,7 @@ export const ChatWidgetView: FC<ChatWidgetViewProps> = props =>
|
|||||||
|
|
||||||
const makeRoom = useCallback((chat: ChatBubbleMessage) =>
|
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 requiredSpace = (chat.height + 1);
|
||||||
const spaceAvailable = (elementRef.current.offsetHeight - lowestPoint);
|
const spaceAvailable = (elementRef.current.offsetHeight - lowestPoint);
|
||||||
|
|
||||||
@ -56,11 +55,11 @@ export const ChatWidgetView: FC<ChatWidgetViewProps> = props =>
|
|||||||
{
|
{
|
||||||
const amount = (requiredSpace - spaceAvailable);
|
const amount = (requiredSpace - spaceAvailable);
|
||||||
|
|
||||||
chatMessages.forEach((existingChat, index) =>
|
chatMessages.forEach(existingChat =>
|
||||||
{
|
{
|
||||||
if(existingChat === chat) return;
|
if(existingChat === chat) return;
|
||||||
|
|
||||||
moveChatUp(existingChat, amount)
|
moveChatUp(existingChat, amount);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [ chatMessages, moveChatUp ]);
|
}, [ chatMessages, moveChatUp ]);
|
||||||
@ -69,7 +68,7 @@ export const ChatWidgetView: FC<ChatWidgetViewProps> = props =>
|
|||||||
{
|
{
|
||||||
setChatMessages(prevValue =>
|
setChatMessages(prevValue =>
|
||||||
{
|
{
|
||||||
return [ ...prevValue, chat ]
|
return [ ...prevValue, chat ];
|
||||||
});
|
});
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@ -80,11 +79,6 @@ export const ChatWidgetView: FC<ChatWidgetViewProps> = props =>
|
|||||||
if(!roomObject) return;
|
if(!roomObject) return;
|
||||||
|
|
||||||
const canvasId = 1;
|
const canvasId = 1;
|
||||||
|
|
||||||
const roomGeometry = GetRoomEngine().getRoomInstanceGeometry(event.session.roomId, canvasId);
|
|
||||||
|
|
||||||
if(!roomGeometry) return;
|
|
||||||
|
|
||||||
const objectLocation = roomObject.getLocation();
|
const objectLocation = roomObject.getLocation();
|
||||||
const bubbleLocation = GetBubbleLocation(event.session.roomId, objectLocation, canvasId);
|
const bubbleLocation = GetBubbleLocation(event.session.roomId, objectLocation, canvasId);
|
||||||
const userData = GetRoomSession().userDataManager.getUserDataByIndex(event.objectId);
|
const userData = GetRoomSession().userDataManager.getUserDataByIndex(event.objectId);
|
||||||
@ -138,31 +132,37 @@ export const ChatWidgetView: FC<ChatWidgetViewProps> = props =>
|
|||||||
|
|
||||||
useRoomSessionManagerEvent(RoomSessionChatEvent.CHAT_EVENT, onRoomSessionChatEvent);
|
useRoomSessionManagerEvent(RoomSessionChatEvent.CHAT_EVENT, onRoomSessionChatEvent);
|
||||||
|
|
||||||
// useEffect(() =>
|
const onRoomDragEvent = useCallback((event: RoomDragEvent) =>
|
||||||
// {
|
{
|
||||||
// const interval = setInterval(() => moveAllChatsUp(15), 500);
|
if(!chatMessages.length) return;
|
||||||
|
|
||||||
// return () =>
|
if(event.roomId !== roomSession.roomId) return;
|
||||||
// {
|
|
||||||
// if(interval) clearInterval(interval);
|
chatMessages.forEach(chat =>
|
||||||
// }
|
{
|
||||||
// }, [ chatMessages, moveAllChatsUp ]);
|
if(!chat.elementRef) return;
|
||||||
|
|
||||||
|
chat.left = (chat.elementRef.offsetLeft + event.offsetX);
|
||||||
|
});
|
||||||
|
}, [ roomSession, chatMessages ]);
|
||||||
|
|
||||||
|
useRoomEngineEvent(RoomDragEvent.ROOM_DRAG, onRoomDragEvent);
|
||||||
|
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
const interval = setInterval(() => removeFirstHiddenChat(), 1000);
|
const interval = setInterval(() => moveAllChatsUp(15), 4500);
|
||||||
|
|
||||||
return () =>
|
return () =>
|
||||||
{
|
{
|
||||||
if(interval) clearInterval(interval);
|
if(interval) clearInterval(interval);
|
||||||
}
|
}
|
||||||
}, [ removeFirstHiddenChat ]);
|
}, [ chatMessages, moveAllChatsUp ]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={ elementRef } className="nitro-chat-widget">
|
<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>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
import { FC, MouseEvent, useCallback, useEffect, useRef, useState } from 'react';
|
import { FC, MouseEvent, useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { GetSessionDataManager } from '../../../../../api';
|
|
||||||
import { ChatWidgetMessageViewProps } from './ChatWidgetMessageView.types';
|
import { ChatWidgetMessageViewProps } from './ChatWidgetMessageView.types';
|
||||||
|
|
||||||
export const ChatWidgetMessageView: FC<ChatWidgetMessageViewProps> = props =>
|
export const ChatWidgetMessageView: FC<ChatWidgetMessageViewProps> = props =>
|
||||||
{
|
{
|
||||||
const { chat = null, makeRoom = null } = 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 [ messageParts, setMessageParts ] = useState<{text: string, className?: string, style?: any, onClick?: () => void}[]>(null);
|
||||||
const elementRef = useRef<HTMLDivElement>();
|
const elementRef = useRef<HTMLDivElement>();
|
||||||
|
|
||||||
@ -14,37 +13,37 @@ export const ChatWidgetMessageView: FC<ChatWidgetMessageViewProps> = props =>
|
|||||||
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() =>
|
// useEffect(() =>
|
||||||
{
|
// {
|
||||||
if(messageParts) return;
|
// 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)
|
// if(matches.length > 0)
|
||||||
{
|
// {
|
||||||
const prevText = chat.text.substr(0, matches[0].index);
|
// const prevText = chat.text.substr(0, matches[0].index);
|
||||||
const postText = chat.text.substring(matches[0].index + userNameMention.length, chat.text.length);
|
// const postText = chat.text.substring(matches[0].index + userNameMention.length, chat.text.length);
|
||||||
|
|
||||||
setMessageParts(
|
// setMessageParts(
|
||||||
[
|
// [
|
||||||
{ text: prevText },
|
// { text: prevText },
|
||||||
{ text: userNameMention, className: 'chat-mention', onClick: () => {alert('I clicked in the mention')}},
|
// { text: userNameMention, className: 'chat-mention', onClick: () => {alert('I clicked in the mention')}},
|
||||||
{ text: postText }
|
// { text: postText }
|
||||||
]
|
// ]
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
setMessageParts(
|
// setMessageParts(
|
||||||
[
|
// [
|
||||||
{ text: chat.text }
|
// { text: chat.text }
|
||||||
]
|
// ]
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
|
|
||||||
}, [ chat ]);
|
// }, [ chat ]);
|
||||||
|
|
||||||
useEffect(() =>
|
useEffect(() =>
|
||||||
{
|
{
|
||||||
@ -59,34 +58,35 @@ export const ChatWidgetMessageView: FC<ChatWidgetMessageViewProps> = props =>
|
|||||||
chat.height = height;
|
chat.height = height;
|
||||||
chat.elementRef = element;
|
chat.elementRef = element;
|
||||||
|
|
||||||
let left = chat.lastLeft;
|
let left = chat.left;
|
||||||
let top = chat.lastTop;
|
let top = chat.top;
|
||||||
|
|
||||||
if(!left && !top)
|
if(!left && !top)
|
||||||
{
|
{
|
||||||
left = (chat.location.x - (width / 2));
|
left = (chat.location.x - (width / 2));
|
||||||
top = (element.parentElement.offsetHeight - height);
|
top = (element.parentElement.offsetHeight - height);
|
||||||
|
|
||||||
chat.lastLeft = left;
|
chat.left = left;
|
||||||
chat.lastTop = top;
|
chat.top = top;
|
||||||
}
|
}
|
||||||
|
|
||||||
element.style.left = (left + 'px');
|
|
||||||
element.style.top = (top + 'px');
|
|
||||||
|
|
||||||
if(!chat.visible)
|
if(!chat.visible)
|
||||||
{
|
{
|
||||||
makeRoom(chat);
|
makeRoom(chat);
|
||||||
}
|
|
||||||
|
|
||||||
chat.visible = true;
|
chat.visible = true;
|
||||||
//setIsVisible(true);
|
}
|
||||||
|
|
||||||
return () =>
|
return () =>
|
||||||
{
|
{
|
||||||
chat.elementRef = null;
|
chat.elementRef = null;
|
||||||
}
|
}
|
||||||
}, [ elementRef, isVisible, chat, makeRoom ]);
|
}, [ elementRef, chat, makeRoom ]);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
setIsVisible(chat.visible);
|
||||||
|
}, [ chat.visible ]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={ elementRef } className="bubble-container" style={ { visibility: (isVisible ? 'visible' : 'hidden') } }>
|
<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 + ')' } } /> }
|
{ (chat.imageUrl && (chat.imageUrl !== '')) && <div className="user-image" style={ { backgroundImage: 'url(' + chat.imageUrl + ')' } } /> }
|
||||||
</div>
|
</div>
|
||||||
<div className="chat-content">
|
<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) =>
|
messageParts && messageParts.map((part, index) =>
|
||||||
{
|
{
|
||||||
return <span key={ index } className={ part.className } style={ part.style } onClick={ part.onClick }>{ part.text }</span>
|
return <span key={ index } className={ part.className } style={ part.style } onClick={ part.onClick }>{ part.text }</span>
|
||||||
|
@ -2,15 +2,16 @@ import { INitroPoint } from 'nitro-renderer';
|
|||||||
|
|
||||||
export class ChatBubbleMessage
|
export class ChatBubbleMessage
|
||||||
{
|
{
|
||||||
public static BUBBLE_COUNTER: number = -1;
|
public static BUBBLE_COUNTER: number = 0;
|
||||||
|
|
||||||
public id: number = -1;
|
public id: number = -1;
|
||||||
public width: number = 0;
|
public width: number = 0;
|
||||||
public height: number = 0;
|
public height: number = 0;
|
||||||
public lastTop: number = 0;
|
|
||||||
public lastLeft: number = 0;
|
|
||||||
public elementRef: HTMLDivElement = null;
|
public elementRef: HTMLDivElement = null;
|
||||||
public visible: boolean = false;
|
public visible: boolean = false;
|
||||||
|
|
||||||
|
private _top: number = 0;
|
||||||
|
private _left: number = 0;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
public text: string = '',
|
public text: string = '',
|
||||||
@ -23,4 +24,28 @@ export class ChatBubbleMessage
|
|||||||
) {
|
) {
|
||||||
this.id = ++ChatBubbleMessage.BUBBLE_COUNTER;
|
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');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
border: 2px solid rgba($white, 0.5);
|
border: 2px solid rgba($white, 0.5);
|
||||||
border-radius: $border-radius;
|
border-radius: $border-radius;
|
||||||
font-size: $font-size-sm;
|
font-size: $font-size-sm;
|
||||||
|
z-index: $context-menu-zindex;
|
||||||
|
|
||||||
&.name-only {
|
&.name-only {
|
||||||
background-color: rgba($black, 0.7);
|
background-color: rgba($black, 0.7);
|
||||||
|
Loading…
Reference in New Issue
Block a user