nitro-react/src/components/chat-history/ChatHistoryView.tsx

104 lines
4.0 KiB
TypeScript
Raw Normal View History

2022-02-21 17:52:11 +01:00
import { ILinkEventTracker } from '@nitrots/nitro-renderer';
2022-07-19 17:29:13 +02:00
import { FC, useEffect, useMemo, useRef, useState } from 'react';
2022-02-21 17:52:11 +01:00
import { AutoSizer, CellMeasurer, CellMeasurerCache, List, ListRowProps, ListRowRenderer, Size } from 'react-virtualized';
2022-07-19 17:29:13 +02:00
import { AddEventLinkTracker, ChatEntryType, LocalizeText, RemoveLinkEventTracker } from '../../api';
2022-03-03 08:23:01 +01:00
import { Flex, NitroCardContentView, NitroCardHeaderView, NitroCardView, Text } from '../../common';
2022-07-19 17:29:13 +02:00
import { useChatHistory } from '../../hooks';
2022-02-21 17:52:11 +01:00
export const ChatHistoryView: FC<{}> = props =>
{
const [ isVisible, setIsVisible ] = useState(false);
2022-07-19 17:29:13 +02:00
const { chatHistory = [] } = useChatHistory();
2022-02-21 17:52:11 +01:00
const elementRef = useRef<List>(null);
const cache = useMemo(() => new CellMeasurerCache({ defaultHeight: 25, fixedWidth: true }), []);
const RowRenderer: ListRowRenderer = (props: ListRowProps) =>
{
2022-07-19 17:29:13 +02:00
const item = chatHistory[props.index];
2022-02-21 17:52:11 +01:00
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) &&
<>
2022-04-04 02:52:34 +02:00
<Text pointer noWrap dangerouslySetInnerHTML={ { __html: (item.name + ':') } } />
2022-02-21 17:52:11 +01:00
<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();
useEffect(() =>
{
const linkTracker: ILinkEventTracker = {
2022-07-19 17:29:13 +02:00
linkReceived: (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;
}
},
2022-02-21 17:52:11 +01:00
eventUrlPrefix: 'chat-history/'
};
AddEventLinkTracker(linkTracker);
return () => RemoveLinkEventTracker(linkTracker);
}, []);
useEffect(() =>
{
2022-03-17 03:19:54 +01:00
if(elementRef && elementRef.current && isVisible) elementRef.current.scrollToRow(-1);
}, [ isVisible ]);
2022-02-21 17:52:11 +01:00
2022-07-19 17:29:13 +02:00
if(!isVisible) return null;
2022-02-21 17:52:11 +01:00
return (
2022-07-19 17:29:13 +02:00
<NitroCardView uniqueKey="chat-history" className="nitro-chat-history" theme="primary-slim">
<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={ chatHistory.length }
rowHeight={ cache.rowHeight }
className={ 'chat-history-list' }
rowRenderer={ RowRenderer }
deferredMeasurementCache={ cache } />
)
} }
</AutoSizer>
</NitroCardContentView>
</NitroCardView>
2022-02-21 17:52:11 +01:00
);
}