Skip to content

Commit fc3c40d

Browse files
committed
wip
1 parent fb3b625 commit fc3c40d

File tree

4 files changed

+43
-39
lines changed

4 files changed

+43
-39
lines changed

webapp/src/components/MessageList.tsx

Lines changed: 19 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ import {useSelector} from 'react-redux';
33
import {useTheme} from '../hooks/useTheme';
44
import {RootState} from '../store';
55
import {isArchive} from '../services/appConfig';
6-
import WebSocketService from '../services/websocket';
6+
7+
import {debounce, resetTabState, updateTabs} from '../utils/tabHandling';
8+
import WebSocketService from "../services/websocket";
79
import Prism from 'prismjs';
8-
import {Message} from '../types/messages';
10+
import {Message} from "../types/messages";
911
import Spinner from './common/Spinner';
1012
import './MessageList.css';
11-
import mermaid from 'mermaid';
12-
import {debouncedUpdate} from '../store/slices/messageSlice';
1313

1414
const DEBUG_LOGGING = process.env.NODE_ENV === 'development';
1515
const CONTAINER_ID = 'message-list-' + Math.random().toString(36).substr(2, 9);
@@ -237,37 +237,24 @@ const MessageList: React.FC<MessageListProps> = ({messages: propMessages}) => {
237237
mounted = false;
238238
};
239239
}, [messages, verboseMode]);
240-
241-
useTheme();
242-
243-
244-
console.log('[MessageList]: Rendering component');
245-
246-
// --- Mermaid and Tabs Effect ---
247-
React.useLayoutEffect(() => {
248-
// Always update tabs after DOM update
249-
debouncedUpdate();
250-
if (!messageListRef.current) {
251-
console.error(`[MessageList ${CONTAINER_ID}] Critical: messageListRef is null`);
252-
return;
253-
}
240+
const debouncedUpdateTabs = React.useCallback(
241+
debounce(() => {
254242
try {
255-
// Always re-render all mermaid blocks, not just unprocessed ones, to avoid disappearing diagrams
256-
const mermaidBlocks = messageListRef.current.querySelectorAll('.mermaid');
257-
if (mermaidBlocks.length > 0) {
258-
console.info("[MessageList] Rendering mermaid diagrams");
259-
mermaid.initialize({ startOnLoad: true });
260-
mermaidBlocks.forEach((el) => {
261-
el.classList.add('mermaid-processed');
262-
el.classList.remove('mermaid');
263-
});
264-
console.info("[MessageList] Mermaid diagrams rendered successfully");
265-
}
243+
updateTabs();
266244
} catch (error) {
267-
console.error(`[MessageList ${CONTAINER_ID}] Failed to render mermaid diagram`, error);
245+
console.error(`[MessageList ${CONTAINER_ID}] Failed to update tabs`, error);
246+
resetTabState();
268247
}
269-
// Use only dependencies that affect DOM: finalMessages, verboseMode, theme, etc.
270-
}, [finalMessages, verboseMode, currentTheme]);
248+
}, 250),
249+
[]
250+
);
251+
252+
useTheme();
253+
console.log('MessageList', 'Rendering component', {hasPropMessages: !!propMessages});
254+
255+
React.useEffect(() => {
256+
debouncedUpdateTabs();
257+
}, [finalMessages]);
271258

272259
return (
273260
<div

webapp/src/services/websocket.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -326,10 +326,18 @@ export class WebSocketService implements WebSocketLike {
326326
}
327327

328328
private getWebSocketPath(): string {
329-
// Use window.location.pathname as the base, ensuring trailing slash
330-
let basePath = window.location.pathname;
331-
if (!basePath.endsWith('/')) basePath += '/';
332-
return basePath;
329+
const path = window.location.pathname;
330+
// Simplify path handling to use the base path
331+
let wsPath = '/';
332+
// If we're in a subdirectory, use that as the base path
333+
if (path !== '/' && path.length > 0) {
334+
// Extract the first path segment
335+
const match = path.match(/^\/([^/]+)/);
336+
if (match && match[1]) {
337+
wsPath = `/${match[1]}/`;
338+
}
339+
}
340+
return wsPath;
333341
}
334342

335343
private setupEventHandlers(): () => void {

webapp/src/store/slices/messageSlice.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ import { createSlice, PayloadAction } from '@reduxjs/toolkit';
22
import { Message, MessageState, MessageUpdate } from '../../types/messages';
33
import DOMPurify from 'dompurify';
44
import { debounce, getAllTabStates, restoreTabStates, updateTabs } from '../../utils/tabHandling';
5-
import Prism from 'prismjs';
5+
import Prism from "prismjs";
6+
import mermaid from "mermaid";
7+
68

79
const initialState: MessageState = {
810
messages: [],
@@ -23,10 +25,16 @@ const sanitizeHtmlContent = (content: string): string => {
2325
});
2426
};
2527

26-
export const debouncedUpdate = debounce(() => {
28+
const debouncedUpdate = debounce(() => {
2729
restoreTabStates(getAllTabStates());
2830
updateTabs();
2931
Prism.highlightAll();
32+
try {
33+
mermaid.init(undefined, document.querySelectorAll('.mermaid:not(.mermaid-processed)'));
34+
document.querySelectorAll('.mermaid').forEach(el => el.classList.add('mermaid-processed'));
35+
} catch (error) {
36+
console.error('Failed to render mermaid diagram:', error);
37+
}
3038
}, 100);
3139

3240
const messageSlice = createSlice({

webapp/src/utils/tabHandling.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,8 @@ export const updateTabs = debounce(() => {
360360
isMutating = false;
361361
}
362362
}, 250);
363-
// Do NOT call updateTabs() immediately here! It causes infinite loops and breaks tab system.
363+
// Wrap updateTabs in requestAnimationFrame to batch DOM updates
364+
requestAnimationFrame(() => updateTabs());
364365

365366

366367
function setupTabContainer(container: Element) {

0 commit comments

Comments
 (0)