import { observer } from 'mobx-react-lite'; import React from 'react'; import { useStore } from 'App/mstore'; import { debounce } from 'App/utils'; import { IResourceRequest, IResourceTiming } from 'App/player'; import { WsChannel } from 'App/player/web/messages'; import { PlayerContext } from 'App/components/Session/playerContext'; let debounceUpdate: any = () => {}; const boldLine = /\*\*(.*?)\*\*/i; function isTitleLine(line: string): boolean { return boldLine.test(line); } function SummaryBlock({ sessionId }: { sessionId: string }) { const { store } = React.useContext(PlayerContext); const { tabStates } = store.get(); const { aiSummaryStore, uiPlayerStore, sessionStore } = useStore(); const duration = sessionStore.current.durationSeconds; const zoomEnabled = uiPlayerStore.timelineZoom.enabled; const zoomStartTs = uiPlayerStore.timelineZoom.startTs; const zoomEndTs = uiPlayerStore.timelineZoom.endTs; const { zoomTab } = uiPlayerStore; React.useEffect(() => { debounceUpdate = debounce( ( sessionId: string, events: any[], feat: 'journey' | 'issues' | 'errors', startTs: number, endTs: number, ) => aiSummaryStore.getDetailedSummary( sessionId, events, feat, startTs, endTs, ), 500, ); }, []); React.useEffect(() => { if (zoomTab === 'overview') { void aiSummaryStore.getSummary(sessionId); } else { const totalFetchList: IResourceRequest[] = []; const totalResourceList: IResourceTiming[] = []; const totalWebsocketList: WsChannel[] = []; Object.values(tabStates).forEach( ({ fetchList, resourceList, websocketList }) => { totalFetchList.push(...fetchList); totalResourceList.push(...resourceList); totalWebsocketList.push(...websocketList); }, ); const resultingEvents = [ ...totalFetchList, ...totalResourceList, ...totalWebsocketList, ]; const range = !zoomEnabled ? [0, duration] : [zoomStartTs, zoomEndTs]; void debounceUpdate( sessionId, resultingEvents, zoomTab, range[0], range[1], ); } }, [zoomTab]); const formattedText = aiSummaryStore.text.split('\n').map((line) => { if (isTitleLine(line)) { return (
{line.replace(/\*/g, '')}
); } if (line.startsWith('*')) { return (
  • ); } return (
    ); }); return (
    {aiSummaryStore.text ? (
    {formattedText.map((v) => v)}
    ) : ( )}
    ); } function TextPlaceholder() { return (
    ); } function CodeStringFormatter({ text }: { text: string }) { const parts = text.split(/(`[^`]*`)/).map((part, index) => part.startsWith('`') && part.endsWith('`') ? (
    {part.substring(1, part.length - 1)}
    ) : ( {part} ), ); return <>{parts}; } const summaryBlockStyle: React.CSSProperties = { background: 'linear-gradient(180deg, #E8EBFF -24.14%, rgba(236, 254, 255, 0.00) 100%)', width: '100%', maxHeight: '25vh', overflow: 'auto', display: 'flex', flexDirection: 'column', gap: '0.5rem', padding: '1rem', }; export default observer(SummaryBlock);