mirror of
https://github.com/billsonnn/nitro-react.git
synced 2024-11-27 08:00:51 +01:00
Update chat history
This commit is contained in:
parent
3ee74e2a04
commit
fceabc0aaa
21
src/components/chat-history/ChatHistoryContext.tsx
Normal file
21
src/components/chat-history/ChatHistoryContext.tsx
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { createContext, FC, ProviderProps, useContext } from 'react';
|
||||||
|
import { IChatHistoryState } from './common/IChatHistoryState';
|
||||||
|
import { IRoomHistoryState } from './common/IRoomHistoryState';
|
||||||
|
|
||||||
|
export interface IChatHistoryContext
|
||||||
|
{
|
||||||
|
chatHistoryState: IChatHistoryState;
|
||||||
|
roomHistoryState: IRoomHistoryState;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ChatHistoryContext = createContext<IChatHistoryContext>({
|
||||||
|
chatHistoryState: null,
|
||||||
|
roomHistoryState: null
|
||||||
|
});
|
||||||
|
|
||||||
|
export const ChatHistoryContextProvider: FC<ProviderProps<IChatHistoryContext>> = props =>
|
||||||
|
{
|
||||||
|
return <ChatHistoryContext.Provider value={ props.value }>{ props.children }</ChatHistoryContext.Provider>
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useChatHistoryContext = () => useContext(ChatHistoryContext);
|
@ -2,9 +2,14 @@ import { GetGuestRoomResultEvent, RoomSessionChatEvent, RoomSessionEvent } from
|
|||||||
import { FC, useCallback, useState } from 'react';
|
import { FC, useCallback, useState } from 'react';
|
||||||
import { GetRoomSession } from '../../api';
|
import { GetRoomSession } from '../../api';
|
||||||
import { CreateMessageHook, useRoomSessionManagerEvent } from '../../hooks';
|
import { CreateMessageHook, useRoomSessionManagerEvent } from '../../hooks';
|
||||||
import { useChatHistoryContext } from './context/ChatHistoryContext';
|
import { useChatHistoryContext } from './ChatHistoryContext';
|
||||||
import { ChatEntryType, CHAT_HISTORY_MAX, IChatEntry, IRoomHistoryEntry, ROOM_HISTORY_MAX } from './context/ChatHistoryContext.types';
|
import { ChatEntryType } from './common/ChatEntryType';
|
||||||
import { currentDate } from './utils/Utilities';
|
import { IChatEntry } from './common/IChatEntry';
|
||||||
|
import { IRoomHistoryEntry } from './common/IRoomHistoryEntry';
|
||||||
|
import { currentDate } from './common/Utilities';
|
||||||
|
|
||||||
|
const CHAT_HISTORY_MAX = 1000;
|
||||||
|
const ROOM_HISTORY_MAX = 10;
|
||||||
|
|
||||||
export const ChatHistoryMessageHandler: FC<{}> = props =>
|
export const ChatHistoryMessageHandler: FC<{}> = props =>
|
||||||
{
|
{
|
8
src/components/chat-history/ChatHistoryView.scss
Normal file
8
src/components/chat-history/ChatHistoryView.scss
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
.nitro-chat-history {
|
||||||
|
width: $chat-history-width;
|
||||||
|
height: $chat-history-height;
|
||||||
|
|
||||||
|
.content-area {
|
||||||
|
min-height: 200px;
|
||||||
|
}
|
||||||
|
}
|
155
src/components/chat-history/ChatHistoryView.tsx
Normal file
155
src/components/chat-history/ChatHistoryView.tsx
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
import { ILinkEventTracker } from '@nitrots/nitro-renderer';
|
||||||
|
import { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||||
|
import { AutoSizer, CellMeasurer, CellMeasurerCache, List, ListRowProps, ListRowRenderer, Size } from 'react-virtualized';
|
||||||
|
import { RenderedRows } from 'react-virtualized/dist/es/List';
|
||||||
|
import { AddEventLinkTracker, LocalizeText, RemoveLinkEventTracker } from '../../api';
|
||||||
|
import { Flex, Text } from '../../common';
|
||||||
|
import { BatchUpdates } from '../../hooks';
|
||||||
|
import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../layout';
|
||||||
|
import { ChatHistoryContextProvider } from './ChatHistoryContext';
|
||||||
|
import { ChatHistoryMessageHandler } from './ChatHistoryMessageHandler';
|
||||||
|
import { ChatEntryType } from './common/ChatEntryType';
|
||||||
|
import { ChatHistoryState } from './common/ChatHistoryState';
|
||||||
|
import { SetChatHistory } from './common/GetChatHistory';
|
||||||
|
import { RoomHistoryState } from './common/RoomHistoryState';
|
||||||
|
|
||||||
|
export const ChatHistoryView: FC<{}> = props =>
|
||||||
|
{
|
||||||
|
const [ isVisible, setIsVisible ] = useState(false);
|
||||||
|
const [ needsScroll, setNeedsScroll ] = useState(false);
|
||||||
|
const [ chatHistoryUpdateId, setChatHistoryUpdateId ] = useState(-1);
|
||||||
|
const [ roomHistoryUpdateId, setRoomHistoryUpdateId ] = useState(-1);
|
||||||
|
const [ chatHistoryState, setChatHistoryState ] = useState(new ChatHistoryState());
|
||||||
|
const [ roomHistoryState, setRoomHistoryState ] = useState(new RoomHistoryState());
|
||||||
|
const elementRef = useRef<List>(null);
|
||||||
|
|
||||||
|
const cache = useMemo(() => new CellMeasurerCache({ defaultHeight: 25, fixedWidth: true }), []);
|
||||||
|
|
||||||
|
const RowRenderer: ListRowRenderer = (props: ListRowProps) =>
|
||||||
|
{
|
||||||
|
const item = chatHistoryState.chats[props.index];
|
||||||
|
|
||||||
|
const isDark = (props.index % 2 === 0);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<CellMeasurer cache={ cache } columnIndex={ 0 } key={ props.key } parent={ props.parent } rowIndex={ props.index }>
|
||||||
|
<Flex key={ props.key } style={ props.style } className="p-1" gap={ 1 }>
|
||||||
|
<Text variant="muted">{ item.timestamp }</Text>
|
||||||
|
{ (item.type === ChatEntryType.TYPE_CHAT) &&
|
||||||
|
<>
|
||||||
|
<Text pointer noWrap dangerouslySetInnerHTML={ { __html: (item.name + ':') }} />
|
||||||
|
<Text textBreak wrap grow>{ item.message }</Text>
|
||||||
|
</> }
|
||||||
|
{ (item.type === ChatEntryType.TYPE_ROOM_INFO) &&
|
||||||
|
<>
|
||||||
|
<i className="icon icon-small-room" />
|
||||||
|
<Text textBreak wrap grow>{ item.name }</Text>
|
||||||
|
</> }
|
||||||
|
</Flex>
|
||||||
|
</CellMeasurer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const onResize = (info: Size) => cache.clearAll();
|
||||||
|
|
||||||
|
const onRowsRendered = (info: RenderedRows) =>
|
||||||
|
{
|
||||||
|
if(elementRef && elementRef.current && isVisible && needsScroll)
|
||||||
|
{
|
||||||
|
elementRef.current.scrollToRow(chatHistoryState.chats.length);
|
||||||
|
|
||||||
|
setNeedsScroll(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const linkReceived = useCallback((url: string) =>
|
||||||
|
{
|
||||||
|
const parts = url.split('/');
|
||||||
|
|
||||||
|
if(parts.length < 2) return;
|
||||||
|
|
||||||
|
switch(parts[1])
|
||||||
|
{
|
||||||
|
case 'show':
|
||||||
|
setIsVisible(true);
|
||||||
|
return;
|
||||||
|
case 'hide':
|
||||||
|
setIsVisible(false);
|
||||||
|
return;
|
||||||
|
case 'toggle':
|
||||||
|
setIsVisible(prevValue => !prevValue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
const linkTracker: ILinkEventTracker = {
|
||||||
|
linkReceived,
|
||||||
|
eventUrlPrefix: 'chat-history/'
|
||||||
|
};
|
||||||
|
|
||||||
|
AddEventLinkTracker(linkTracker);
|
||||||
|
|
||||||
|
return () => RemoveLinkEventTracker(linkTracker);
|
||||||
|
}, [ linkReceived ]);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
const chatState = new ChatHistoryState();
|
||||||
|
const roomState = new RoomHistoryState();
|
||||||
|
|
||||||
|
SetChatHistory(chatState);
|
||||||
|
|
||||||
|
chatState.notifier = () => setChatHistoryUpdateId(prevValue => (prevValue + 1));
|
||||||
|
roomState.notifier = () => setRoomHistoryUpdateId(prevValue => (prevValue + 1));
|
||||||
|
|
||||||
|
BatchUpdates(() =>
|
||||||
|
{
|
||||||
|
setChatHistoryState(chatState);
|
||||||
|
setRoomHistoryState(roomState);
|
||||||
|
});
|
||||||
|
|
||||||
|
return () =>
|
||||||
|
{
|
||||||
|
chatState.notifier = null;
|
||||||
|
roomState.notifier = null;
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() =>
|
||||||
|
{
|
||||||
|
if(elementRef && elementRef.current && isVisible) elementRef.current.scrollToRow(chatHistoryState.chats.length);
|
||||||
|
|
||||||
|
setNeedsScroll(true);
|
||||||
|
}, [ isVisible, chatHistoryState.chats, chatHistoryUpdateId ]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ChatHistoryContextProvider value={ { chatHistoryState, roomHistoryState } }>
|
||||||
|
<ChatHistoryMessageHandler />
|
||||||
|
{ isVisible &&
|
||||||
|
<NitroCardView uniqueKey="chat-history" className="nitro-chat-history">
|
||||||
|
<NitroCardHeaderView headerText={ LocalizeText('room.chathistory.button.text') } onCloseClick={ event => setIsVisible(false) }/>
|
||||||
|
<NitroCardContentView>
|
||||||
|
<AutoSizer defaultWidth={ 300 } defaultHeight={ 200 } onResize={ onResize }>
|
||||||
|
{ ({ height, width }) =>
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<List
|
||||||
|
ref={ elementRef }
|
||||||
|
width={ width }
|
||||||
|
height={ height }
|
||||||
|
rowCount={ chatHistoryState.chats.length }
|
||||||
|
rowHeight={ cache.rowHeight }
|
||||||
|
className={ 'chat-history-list' }
|
||||||
|
rowRenderer={ RowRenderer }
|
||||||
|
onRowsRendered={ onRowsRendered }
|
||||||
|
deferredMeasurementCache={ cache } />
|
||||||
|
)
|
||||||
|
} }
|
||||||
|
</AutoSizer>
|
||||||
|
</NitroCardContentView>
|
||||||
|
</NitroCardView> }
|
||||||
|
</ChatHistoryContextProvider>
|
||||||
|
);
|
||||||
|
}
|
5
src/components/chat-history/common/ChatEntryType.ts
Normal file
5
src/components/chat-history/common/ChatEntryType.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export class ChatEntryType
|
||||||
|
{
|
||||||
|
public static TYPE_CHAT = 1;
|
||||||
|
public static TYPE_ROOM_INFO = 2;
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
import { IChatEntry, IChatHistoryState } from '../context/ChatHistoryContext.types';
|
import { IChatEntry } from './IChatEntry';
|
||||||
|
import { IChatHistoryState } from './IChatHistoryState';
|
||||||
|
|
||||||
export class ChatHistoryState implements IChatHistoryState
|
export class ChatHistoryState implements IChatHistoryState
|
||||||
{
|
{
|
||||||
@ -10,6 +11,11 @@ export class ChatHistoryState implements IChatHistoryState
|
|||||||
this._chats = [];
|
this._chats = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public notify(): void
|
||||||
|
{
|
||||||
|
if(this._notifier) this._notifier();
|
||||||
|
}
|
||||||
|
|
||||||
public get chats(): IChatEntry[]
|
public get chats(): IChatEntry[]
|
||||||
{
|
{
|
||||||
return this._chats;
|
return this._chats;
|
||||||
@ -24,9 +30,4 @@ export class ChatHistoryState implements IChatHistoryState
|
|||||||
{
|
{
|
||||||
this._notifier = notifier;
|
this._notifier = notifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
notify(): void
|
|
||||||
{
|
|
||||||
if(this._notifier) this._notifier();
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
import { IChatHistoryState } from '../context/ChatHistoryContext.types';
|
import { IChatHistoryState } from './IChatHistoryState';
|
||||||
|
|
||||||
let GLOBAL_CHATS: IChatHistoryState = null;
|
let GLOBAL_CHATS: IChatHistoryState = null;
|
||||||
|
|
12
src/components/chat-history/common/IChatEntry.ts
Normal file
12
src/components/chat-history/common/IChatEntry.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
export interface IChatEntry
|
||||||
|
{
|
||||||
|
id: number;
|
||||||
|
entityId: number;
|
||||||
|
name: string;
|
||||||
|
look?: string;
|
||||||
|
message?: string;
|
||||||
|
entityType?: number;
|
||||||
|
roomId: number;
|
||||||
|
timestamp: string;
|
||||||
|
type: number;
|
||||||
|
}
|
8
src/components/chat-history/common/IChatHistoryState.ts
Normal file
8
src/components/chat-history/common/IChatHistoryState.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { IChatEntry } from './IChatEntry';
|
||||||
|
|
||||||
|
export interface IChatHistoryState
|
||||||
|
{
|
||||||
|
chats: IChatEntry[];
|
||||||
|
notifier: () => void
|
||||||
|
notify(): void;
|
||||||
|
}
|
4
src/components/chat-history/common/IRoomHistoryEntry.ts
Normal file
4
src/components/chat-history/common/IRoomHistoryEntry.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export interface IRoomHistoryEntry {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
}
|
8
src/components/chat-history/common/IRoomHistoryState.ts
Normal file
8
src/components/chat-history/common/IRoomHistoryState.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { IRoomHistoryEntry } from './IRoomHistoryEntry';
|
||||||
|
|
||||||
|
export interface IRoomHistoryState
|
||||||
|
{
|
||||||
|
roomHistory: IRoomHistoryEntry[];
|
||||||
|
notifier: () => void;
|
||||||
|
notify: () => void;
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
import { IRoomHistoryEntry, IRoomHistoryState } from '../context/ChatHistoryContext.types';
|
import { IRoomHistoryEntry } from './IRoomHistoryEntry';
|
||||||
|
import { IRoomHistoryState } from './IRoomHistoryState';
|
||||||
|
|
||||||
export class RoomHistoryState implements IRoomHistoryState
|
export class RoomHistoryState implements IRoomHistoryState
|
||||||
{
|
{
|
@ -1,6 +1,7 @@
|
|||||||
import { IChatEntry } from '../../../views/chat-history/context/ChatHistoryContext.types';
|
import { IChatEntry } from '../../chat-history/common/IChatEntry';
|
||||||
|
|
||||||
export interface IHelpReportState {
|
export interface IHelpReportState
|
||||||
|
{
|
||||||
reportedUserId: number;
|
reportedUserId: number;
|
||||||
reportedChats: IChatEntry[];
|
reportedChats: IChatEntry[];
|
||||||
cfhCategory: number;
|
cfhCategory: number;
|
||||||
|
@ -2,8 +2,9 @@ import { RoomObjectType } from '@nitrots/nitro-renderer';
|
|||||||
import { FC, useMemo, useState } from 'react';
|
import { FC, useMemo, useState } from 'react';
|
||||||
import { LocalizeText } from '../../../api';
|
import { LocalizeText } from '../../../api';
|
||||||
import { Button, Column, Flex, Grid, LayoutGridItem, Text } from '../../../common';
|
import { Button, Column, Flex, Grid, LayoutGridItem, Text } from '../../../common';
|
||||||
import { GetChatHistory } from '../../../views/chat-history/common/GetChatHistory';
|
import { ChatEntryType } from '../../chat-history/common/ChatEntryType';
|
||||||
import { ChatEntryType, IChatEntry } from '../../../views/chat-history/context/ChatHistoryContext.types';
|
import { GetChatHistory } from '../../chat-history/common/GetChatHistory';
|
||||||
|
import { IChatEntry } from '../../chat-history/common/IChatEntry';
|
||||||
import { useHelpContext } from '../HelpContext';
|
import { useHelpContext } from '../HelpContext';
|
||||||
|
|
||||||
export const SelectReportedChatsView: FC<{}> = props =>
|
export const SelectReportedChatsView: FC<{}> = props =>
|
||||||
|
@ -2,8 +2,8 @@ import { RoomObjectType } from '@nitrots/nitro-renderer';
|
|||||||
import { FC, useMemo, useState } from 'react';
|
import { FC, useMemo, useState } from 'react';
|
||||||
import { GetSessionDataManager, LocalizeText } from '../../../api';
|
import { GetSessionDataManager, LocalizeText } from '../../../api';
|
||||||
import { Button, Column, Flex, Grid, LayoutGridItem, Text } from '../../../common';
|
import { Button, Column, Flex, Grid, LayoutGridItem, Text } from '../../../common';
|
||||||
import { GetChatHistory } from '../../../views/chat-history/common/GetChatHistory';
|
import { ChatEntryType } from '../../chat-history/common/ChatEntryType';
|
||||||
import { ChatEntryType } from '../../../views/chat-history/context/ChatHistoryContext.types';
|
import { GetChatHistory } from '../../chat-history/common/GetChatHistory';
|
||||||
import { IReportedUser } from '../common/IReportedUser';
|
import { IReportedUser } from '../common/IReportedUser';
|
||||||
import { useHelpContext } from '../HelpContext';
|
import { useHelpContext } from '../HelpContext';
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
@import './avatar-editor/AvatarEditorView';
|
@import './avatar-editor/AvatarEditorView';
|
||||||
@import './camera/CameraWidgetView';
|
@import './camera/CameraWidgetView';
|
||||||
@import './catalog/CatalogView';
|
@import './catalog/CatalogView';
|
||||||
|
@import './chat-history/ChatHistoryView';
|
||||||
@import './groups/GroupView';
|
@import './groups/GroupView';
|
||||||
@import './help/HelpView';
|
@import './help/HelpView';
|
||||||
@import './inventory/InventoryView';
|
@import './inventory/InventoryView';
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
import { NitroEvent } from '@nitrots/nitro-renderer';
|
|
||||||
|
|
||||||
export class ChatHistoryEvent extends NitroEvent
|
|
||||||
{
|
|
||||||
public static SHOW_CHAT_HISTORY: string = 'CHE_SHOW_CHAT_HISTORY';
|
|
||||||
public static HIDE_CHAT_HISTORY: string = 'CHE_HIDE_CHAT_HISTORY';
|
|
||||||
public static TOGGLE_CHAT_HISTORY: string = 'CHE_TOGGLE_CHAT_HISTORY';
|
|
||||||
}
|
|
@ -8,7 +8,6 @@
|
|||||||
@import "./right-side/RightSideView";
|
@import "./right-side/RightSideView";
|
||||||
@import "./room/RoomView";
|
@import "./room/RoomView";
|
||||||
@import "./room-host/RoomHostView";
|
@import "./room-host/RoomHostView";
|
||||||
@import "./chat-history/ChatHistoryView";
|
|
||||||
@import "./floorplan-editor/FloorplanEditorView";
|
@import "./floorplan-editor/FloorplanEditorView";
|
||||||
@import "./nitropedia/NitropediaView";
|
@import "./nitropedia/NitropediaView";
|
||||||
@import "./hc-center/HcCenterView.scss";
|
@import "./hc-center/HcCenterView.scss";
|
||||||
|
@ -1,30 +0,0 @@
|
|||||||
.nitro-chat-history {
|
|
||||||
width: $chat-history-width;
|
|
||||||
height: $chat-history-height;
|
|
||||||
|
|
||||||
background-color: #1C323F;
|
|
||||||
border: 2px solid rgba(255, 255, 255, 0.5);
|
|
||||||
|
|
||||||
.nitro-card-header-container {
|
|
||||||
background-color: #3d5f6e;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-history-content {
|
|
||||||
.chat-history-container {
|
|
||||||
min-height: 200px;
|
|
||||||
|
|
||||||
.chat-history-list {
|
|
||||||
.chathistory-entry {
|
|
||||||
.light {
|
|
||||||
background-color: #121f27;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark {
|
|
||||||
background-color: #0d171d;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,167 +0,0 @@
|
|||||||
import { FC, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
||||||
import { AutoSizer, CellMeasurer, CellMeasurerCache, List, ListRowProps, ListRowRenderer, Size } from 'react-virtualized';
|
|
||||||
import { RenderedRows } from 'react-virtualized/dist/es/List';
|
|
||||||
import { ChatHistoryEvent } from '../../events/chat-history/ChatHistoryEvent';
|
|
||||||
import { useUiEvent } from '../../hooks';
|
|
||||||
import { NitroCardContentView, NitroCardHeaderView, NitroCardView } from '../../layout';
|
|
||||||
import { ChatHistoryMessageHandler } from './ChatHistoryMessageHandler';
|
|
||||||
import { ChatHistoryState } from './common/ChatHistoryState';
|
|
||||||
import { SetChatHistory } from './common/GetChatHistory';
|
|
||||||
import { RoomHistoryState } from './common/RoomHistoryState';
|
|
||||||
import { ChatHistoryContextProvider } from './context/ChatHistoryContext';
|
|
||||||
import { ChatEntryType } from './context/ChatHistoryContext.types';
|
|
||||||
|
|
||||||
export const ChatHistoryView: FC<{}> = props =>
|
|
||||||
{
|
|
||||||
const [ isVisible, setIsVisible ] = useState(false);
|
|
||||||
const [ needsScroll, setNeedsScroll ] = useState(false);
|
|
||||||
const [ chatHistoryUpdateId, setChatHistoryUpdateId ] = useState(-1);
|
|
||||||
const [ roomHistoryUpdateId, setRoomHistoryUpdateId ] = useState(-1);
|
|
||||||
const [ chatHistoryState, setChatHistoryState ] = useState(new ChatHistoryState());
|
|
||||||
const [ roomHistoryState, setRoomHistoryState ] = useState(new RoomHistoryState());
|
|
||||||
const elementRef = useRef<List>(null);
|
|
||||||
|
|
||||||
useEffect(() =>
|
|
||||||
{
|
|
||||||
const chatState = new ChatHistoryState();
|
|
||||||
const roomState = new RoomHistoryState();
|
|
||||||
|
|
||||||
SetChatHistory(chatState);
|
|
||||||
|
|
||||||
chatState.notifier = () => setChatHistoryUpdateId(prevValue => (prevValue + 1));
|
|
||||||
roomState.notifier = () => setRoomHistoryUpdateId(prevValue => (prevValue + 1));
|
|
||||||
|
|
||||||
setChatHistoryState(chatState);
|
|
||||||
setRoomHistoryState(roomState);
|
|
||||||
|
|
||||||
return () => {chatState.notifier = null; roomState.notifier = null;};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const onChatHistoryEvent = useCallback((event: ChatHistoryEvent) =>
|
|
||||||
{
|
|
||||||
switch(event.type)
|
|
||||||
{
|
|
||||||
case ChatHistoryEvent.SHOW_CHAT_HISTORY:
|
|
||||||
setIsVisible(true);
|
|
||||||
break;
|
|
||||||
case ChatHistoryEvent.HIDE_CHAT_HISTORY:
|
|
||||||
setIsVisible(false);
|
|
||||||
break;
|
|
||||||
case ChatHistoryEvent.TOGGLE_CHAT_HISTORY:
|
|
||||||
setIsVisible(!isVisible);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}, [isVisible]);
|
|
||||||
|
|
||||||
useUiEvent(ChatHistoryEvent.HIDE_CHAT_HISTORY, onChatHistoryEvent);
|
|
||||||
useUiEvent(ChatHistoryEvent.SHOW_CHAT_HISTORY, onChatHistoryEvent);
|
|
||||||
useUiEvent(ChatHistoryEvent.TOGGLE_CHAT_HISTORY, onChatHistoryEvent);
|
|
||||||
|
|
||||||
const cache = useMemo(() =>
|
|
||||||
{
|
|
||||||
return new CellMeasurerCache({
|
|
||||||
defaultHeight: 25,
|
|
||||||
fixedWidth: true,
|
|
||||||
//keyMapper: (index) => chatHistoryState.chats[index].id
|
|
||||||
});
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const RowRenderer: ListRowRenderer = (props: ListRowProps) =>
|
|
||||||
{
|
|
||||||
const item = chatHistoryState.chats[props.index];
|
|
||||||
|
|
||||||
const isDark = (props.index % 2 === 0);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<CellMeasurer
|
|
||||||
cache={cache}
|
|
||||||
columnIndex={0}
|
|
||||||
key={props.key}
|
|
||||||
parent={props.parent}
|
|
||||||
rowIndex={props.index}
|
|
||||||
>
|
|
||||||
<div key={props.key} style={props.style} className="chathistory-entry justify-content-start">
|
|
||||||
{(item.type === ChatEntryType.TYPE_CHAT) &&
|
|
||||||
<div className={`p-1 d-flex gap-1 ${isDark ? 'dark' : 'light'}`}>
|
|
||||||
<div className="text-muted">{item.timestamp}</div>
|
|
||||||
<div className="cursor-pointer d-flex text-nowrap" dangerouslySetInnerHTML={ { __html: (item.name + ':') }} />
|
|
||||||
<div className="text-break text-wrap flex-grow-1">{item.message}</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
{(item.type === ChatEntryType.TYPE_ROOM_INFO) &&
|
|
||||||
<div className={`p-1 d-flex gap-1 ${isDark ? 'dark' : 'light'}`}>
|
|
||||||
<div className="text-muted">{item.timestamp}</div>
|
|
||||||
<i className="icon icon-small-room" />
|
|
||||||
<div className="cursor-pointer text-break text-wrap">{item.name}</div>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</CellMeasurer>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const onResize = useCallback((info: Size) =>
|
|
||||||
{
|
|
||||||
cache.clearAll();
|
|
||||||
}, [cache]);
|
|
||||||
|
|
||||||
const onRowsRendered = useCallback((info: RenderedRows) =>
|
|
||||||
{
|
|
||||||
if(elementRef && elementRef.current && isVisible && needsScroll)
|
|
||||||
{
|
|
||||||
console.log('stop ' + info.stopIndex);
|
|
||||||
//if(chatHistoryState.chats.length > 0) elementRef.current.measureAllRows();
|
|
||||||
elementRef.current.scrollToRow(chatHistoryState.chats.length);
|
|
||||||
console.log('scroll')
|
|
||||||
setNeedsScroll(false);
|
|
||||||
}
|
|
||||||
}, [chatHistoryState.chats.length, isVisible, needsScroll]);
|
|
||||||
|
|
||||||
useEffect(() =>
|
|
||||||
{
|
|
||||||
|
|
||||||
if(elementRef && elementRef.current && isVisible)
|
|
||||||
{
|
|
||||||
//if(chatHistoryState.chats.length > 0) elementRef.current.measureAllRows();
|
|
||||||
elementRef.current.scrollToRow(chatHistoryState.chats.length);
|
|
||||||
}
|
|
||||||
//console.log(chatHistoryState.chats.length);
|
|
||||||
|
|
||||||
setNeedsScroll(true);
|
|
||||||
}, [chatHistoryState.chats, isVisible, chatHistoryUpdateId]);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ChatHistoryContextProvider value={ { chatHistoryState, roomHistoryState } }>
|
|
||||||
<ChatHistoryMessageHandler />
|
|
||||||
{isVisible &&
|
|
||||||
<NitroCardView uniqueKey="chat-history" className="nitro-chat-history rounded" simple={ false } theme={'dark'} >
|
|
||||||
<NitroCardHeaderView headerText={ 'Chat History' } onCloseClick={ event => setIsVisible(false) } theme={'dark'}/>
|
|
||||||
<NitroCardContentView className="chat-history-content p-0" theme={'dark'}>
|
|
||||||
<div className="row w-100 h-100 chat-history-container">
|
|
||||||
<AutoSizer defaultWidth={300} defaultHeight={200} onResize={onResize}>
|
|
||||||
{({ height, width }) =>
|
|
||||||
{
|
|
||||||
return (
|
|
||||||
<List
|
|
||||||
ref={elementRef}
|
|
||||||
width={width}
|
|
||||||
height={height}
|
|
||||||
rowCount={chatHistoryState.chats.length}
|
|
||||||
rowHeight={cache.rowHeight}
|
|
||||||
className={'chat-history-list'}
|
|
||||||
rowRenderer={RowRenderer}
|
|
||||||
onRowsRendered={onRowsRendered}
|
|
||||||
deferredMeasurementCache={cache}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</AutoSizer>
|
|
||||||
</div>
|
|
||||||
</NitroCardContentView>
|
|
||||||
</NitroCardView>
|
|
||||||
}
|
|
||||||
</ChatHistoryContextProvider>
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,14 +0,0 @@
|
|||||||
import { createContext, FC, useContext } from 'react';
|
|
||||||
import { ChatHistoryContextProps, IChatHistoryContext } from './ChatHistoryContext.types';
|
|
||||||
|
|
||||||
const ChatHistoryContext = createContext<IChatHistoryContext>({
|
|
||||||
chatHistoryState: null,
|
|
||||||
roomHistoryState: null
|
|
||||||
});
|
|
||||||
|
|
||||||
export const ChatHistoryContextProvider: FC<ChatHistoryContextProps> = props =>
|
|
||||||
{
|
|
||||||
return <ChatHistoryContext.Provider value={ props.value }>{ props.children }</ChatHistoryContext.Provider>
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useChatHistoryContext = () => useContext(ChatHistoryContext);
|
|
@ -1,50 +0,0 @@
|
|||||||
import { ProviderProps } from 'react';
|
|
||||||
|
|
||||||
export interface IChatHistoryContext
|
|
||||||
{
|
|
||||||
chatHistoryState: IChatHistoryState;
|
|
||||||
roomHistoryState: IRoomHistoryState;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IChatHistoryState {
|
|
||||||
chats: IChatEntry[];
|
|
||||||
notifier: () => void
|
|
||||||
notify(): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IRoomHistoryState {
|
|
||||||
roomHistory: IRoomHistoryEntry[];
|
|
||||||
notifier: () => void
|
|
||||||
notify(): void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IChatEntry {
|
|
||||||
id: number;
|
|
||||||
entityId: number;
|
|
||||||
name: string;
|
|
||||||
look?: string;
|
|
||||||
message?: string;
|
|
||||||
entityType?: number;
|
|
||||||
roomId: number;
|
|
||||||
timestamp: string;
|
|
||||||
type: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IRoomHistoryEntry {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ChatEntryType
|
|
||||||
{
|
|
||||||
public static TYPE_CHAT = 1;
|
|
||||||
public static TYPE_ROOM_INFO = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const CHAT_HISTORY_MAX = 1000;
|
|
||||||
export const ROOM_HISTORY_MAX = 10;
|
|
||||||
|
|
||||||
export interface ChatHistoryContextProps extends ProviderProps<IChatHistoryContext>
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
@ -5,6 +5,7 @@ import { AchievementsView } from '../../components/achievements/AchievementsView
|
|||||||
import { AvatarEditorView } from '../../components/avatar-editor/AvatarEditorView';
|
import { AvatarEditorView } from '../../components/avatar-editor/AvatarEditorView';
|
||||||
import { CameraWidgetView } from '../../components/camera/CameraWidgetView';
|
import { CameraWidgetView } from '../../components/camera/CameraWidgetView';
|
||||||
import { CatalogView } from '../../components/catalog/CatalogView';
|
import { CatalogView } from '../../components/catalog/CatalogView';
|
||||||
|
import { ChatHistoryView } from '../../components/chat-history/ChatHistoryView';
|
||||||
import { GroupsView } from '../../components/groups/GroupsView';
|
import { GroupsView } from '../../components/groups/GroupsView';
|
||||||
import { HelpView } from '../../components/help/HelpView';
|
import { HelpView } from '../../components/help/HelpView';
|
||||||
import { InventoryView } from '../../components/inventory/InventoryView';
|
import { InventoryView } from '../../components/inventory/InventoryView';
|
||||||
@ -17,7 +18,6 @@ import { WiredView } from '../../components/wired/WiredView';
|
|||||||
import { useRoomSessionManagerEvent } from '../../hooks/events/nitro/session/room-session-manager-event';
|
import { useRoomSessionManagerEvent } from '../../hooks/events/nitro/session/room-session-manager-event';
|
||||||
import { TransitionAnimation, TransitionAnimationTypes } from '../../layout';
|
import { TransitionAnimation, TransitionAnimationTypes } from '../../layout';
|
||||||
import { CampaignView } from '../campaign/CampaignView';
|
import { CampaignView } from '../campaign/CampaignView';
|
||||||
import { ChatHistoryView } from '../chat-history/ChatHistoryView';
|
|
||||||
import { FloorplanEditorView } from '../floorplan-editor/FloorplanEditorView';
|
import { FloorplanEditorView } from '../floorplan-editor/FloorplanEditorView';
|
||||||
import { FriendsView } from '../friends/FriendsView';
|
import { FriendsView } from '../friends/FriendsView';
|
||||||
import { HcCenterView } from '../hc-center/HcCenterView';
|
import { HcCenterView } from '../hc-center/HcCenterView';
|
||||||
|
Loading…
Reference in New Issue
Block a user