Skip to content

Commit a4b2617

Browse files
committed
etc
1 parent 071d6e2 commit a4b2617

File tree

14 files changed

+697
-348
lines changed

14 files changed

+697
-348
lines changed

webapp/chat-app/src/App.tsx

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import {Provider} from 'react-redux';
33
import {store} from './store';
44
import ErrorBoundary from './components/ErrorBoundary/ErrorBoundary';
55
import ErrorFallback from './components/ErrorBoundary/ErrorFallback';
6-
import LoadingSpinner from './components/LoadingSpinner/LoadingSpinner';
76
import './App.css';
87
import websocket from './services/websocket';
98
import {GlobalStyles} from './styles/GlobalStyles';
@@ -29,31 +28,14 @@ import 'prismjs/plugins/toolbar/prism-toolbar.css';
2928
import 'prismjs/plugins/copy-to-clipboard/prism-copy-to-clipboard';
3029
import 'prismjs/plugins/line-numbers/prism-line-numbers';
3130
import 'prismjs/plugins/line-numbers/prism-line-numbers.css';
32-
import mermaid from 'mermaid';
3331
import QRCode from 'qrcode-generator';
3432

3533
const APP_VERSION = '1.0.0';
3634
const LOG_PREFIX = '[App]';
37-
// Configure Prism
3835
Prism.manual = true;
3936

4037

4138
const App: React.FC = () => {
42-
const [isLoading, setIsLoading] = React.useState(true);
43-
React.useEffect(() => {
44-
// Highlight code blocks after component mounts
45-
Promise.all([
46-
new Promise(resolve => {
47-
requestAnimationFrame(() => {
48-
Prism.highlightAllUnder(document.body);
49-
resolve(true);
50-
});
51-
}),
52-
mermaid.run()
53-
]).finally(() => {
54-
setIsLoading(false);
55-
});
56-
}, []);
5739
console.group(`${LOG_PREFIX} Initializing v${APP_VERSION}`);
5840
console.log('Starting component render');
5941

@@ -64,21 +46,13 @@ const App: React.FC = () => {
6446
isConnected
6547
});
6648

67-
// Initialize UI handlers and message handling
6849
React.useEffect(() => {
6950
console.log(`${LOG_PREFIX} Setting up handlers`);
7051
setupUIHandlers();
7152
}, []);
7253

7354
React.useEffect(() => {
7455
console.log(`${LOG_PREFIX} Component mounted, initializing libraries`);
75-
// Initialize syntax highlighting
76-
Prism.highlightAll();
77-
console.log(`${LOG_PREFIX} Prism initialized`);
78-
// Initialize mermaid diagrams
79-
mermaid.run();
80-
console.log(`${LOG_PREFIX} Mermaid initialized`);
81-
// Initialize QR code generator
8256
const qr = QRCode(0, 'L');
8357
qr.addData('https://example.com');
8458
qr.make();
@@ -101,8 +75,7 @@ const App: React.FC = () => {
10175
return (
10276
<>
10377
<GlobalStyles/>
104-
<div className={`App ${isLoading ? 'loading' : ''}`}>
105-
{isLoading && <LoadingSpinner/>}
78+
<div className={`App`}>
10679
<Menu/>
10780
<ChatInterface
10881
sessionId={sessionId}
@@ -121,7 +94,6 @@ const App: React.FC = () => {
12194
</ErrorBoundary>
12295
);
12396
};
124-
// Close the logging group when component is loaded
12597
console.groupEnd();
12698
console.log(`${LOG_PREFIX} v${APP_VERSION} loaded successfully`);
12799

webapp/chat-app/src/components/LoadingSpinner/LoadingSpinner.tsx

Lines changed: 0 additions & 41 deletions
This file was deleted.

webapp/chat-app/src/components/MessageList.tsx

Lines changed: 44 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, {useCallback} from 'react';
1+
import React, {useCallback, useEffect, useRef} from 'react';
22
import styled from 'styled-components';
33
import {useSelector} from 'react-redux';
44
import {useTheme} from '../hooks/useTheme';
@@ -11,48 +11,28 @@ import Prism from 'prismjs';
1111

1212
export const expandMessageReferences = (content: string, messages: Message[]): string => {
1313
if (!content) return '';
14-
// Create a temporary div to parse HTML content
1514
const tempDiv = document.createElement('div');
1615
tempDiv.innerHTML = content;
17-
// Helper to highlight code blocks in content
18-
const highlightCodeBlocks = (element: HTMLElement) => {
19-
const codeBlocks = element.querySelectorAll('pre code');
20-
codeBlocks.forEach(block => {
21-
if (block instanceof HTMLElement) {
22-
Prism.highlightElement(block);
23-
}
24-
});
25-
};
26-
// Process all elements with IDs that match message references
2716
const processNode = (node: HTMLElement) => {
2817
const messageID = node.getAttribute("message-id");
2918
if (messageID) {
30-
// if(node.getAttribute("filled") === "true") {
31-
// logger.debug('Skipping filled node', {id: node.id});
32-
// return;
33-
// }
3419
if (messageID?.startsWith('z')) {
3520
const referencedMessage = messages.find(m => m.id === messageID);
3621
if (referencedMessage) {
3722
logger.debug('Expanding referenced message', {id: messageID, contentLength: referencedMessage.content.length});
3823
node.innerHTML = expandMessageReferences(referencedMessage.content, messages);
39-
node.setAttribute("filled", "true");
40-
highlightCodeBlocks(node);
4124
} else {
4225
logger.debug('Referenced message not found', {id: node.id});
4326
}
4427
}
4528
}
46-
// Recursively process child elements
4729
Array.from(node.children).forEach(child => {
4830
if (child instanceof HTMLElement) {
4931
processNode(child);
5032
}
5133
});
5234
};
53-
// logger.debug('Expanding message references', {content});
5435
processNode(tempDiv);
55-
highlightCodeBlocks(tempDiv);
5636
return tempDiv.innerHTML;
5737
};
5838

@@ -85,8 +65,7 @@ const MessageContent = styled.div`
8565
color: var(--theme-text);
8666
font-family: var(--theme-code-font);
8767
}
88-
89-
68+
9069
.href-link, .play-button, .regen-button, .cancel-button, .text-submit-button {
9170
cursor: pointer;
9271
user-select: none;
@@ -119,8 +98,6 @@ const MessageContent = styled.div`
11998
}
12099
}
121100
122-
/* Style code blocks according to theme */
123-
124101
pre[class*="language-"] {
125102
background: ${({theme}) => theme.colors.surface};
126103
margin: 1em 0;
@@ -137,8 +114,6 @@ const MessageContent = styled.div`
137114
font-family: ${({theme}) => theme.typography.console.fontFamily};
138115
}
139116
140-
/* Style inline code differently from code blocks */
141-
142117
:not(pre) > code {
143118
background: ${({theme}) => theme.colors.surface};
144119
color: ${({theme}) => theme.colors.text.primary};
@@ -150,14 +125,12 @@ const MessageContent = styled.div`
150125
`;
151126

152127
const extractMessageAction = (target: HTMLElement): { messageId: string | undefined, action: string | undefined } => {
153-
// Check for data attributes
154128
const messageId = target.getAttribute('data-message-id') ??
155129
target.getAttribute('data-id') ??
156130
undefined;
157131
let action = target.getAttribute('data-message-action') ??
158132
target.getAttribute('data-action') ??
159133
undefined;
160-
// Check element classes
161134
if (!action) {
162135
if (target.classList.contains('href-link')) action = 'link';
163136
else if (target.classList.contains('play-button')) action = 'run';
@@ -249,29 +222,27 @@ const MessageList: React.FC<MessageListProps> = ({messages: propMessages}) => {
249222
const storeMessages = useSelector((state: RootState) => state.messages.messages);
250223
const messages = Array.isArray(propMessages) ? propMessages :
251224
Array.isArray(storeMessages) ? storeMessages : [];
252-
253-
// Memoize message processing
254-
const memoizedProcessMessageContent = React.useMemo(() => {
255-
return (content: string) => {
256-
if (!content) return '';
257-
return expandMessageReferences(content, messages);
258-
};
259-
}, [messages]);
260-
261-
// Optimize message filtering
262-
const filteredMessages = React.useMemo(() => {
263-
return messages
264-
.filter((message) => message.id && !message.id.startsWith("z"))
265-
.filter((message) => message.content?.length > 0);
266-
}, [messages]);
267-
const theme = useTheme();
225+
const messageListRef = useRef<HTMLDivElement>(null);
226+
227+
// Effect to handle syntax highlighting after render
228+
useEffect(() => {
229+
if (messageListRef.current) {
230+
const codeBlocks = messageListRef.current.querySelectorAll('pre code');
231+
logger.debug('Highlighting code blocks:', {count: codeBlocks.length});
232+
codeBlocks.forEach(block => {
233+
Prism.highlightElement(block);
234+
});
235+
}
236+
}, [messages]); // Re-run when messages change
237+
useTheme();
268238
logger.component('MessageList', 'Rendering component', {hasPropMessages: !!propMessages});
239+
269240
// Store tab states on mount
270241
React.useEffect(() => {
271242
logger.debug('MessageList - Initial tab state setup');
272243
const containers = document.querySelectorAll('.tabs-container');
273244
containers.forEach(container => {
274-
if (container instanceof HTMLElement) { // Ensure container is HTMLElement
245+
if (container instanceof HTMLElement) { // Ensure container is HTMLElement
275246
const activeTab = container.querySelector('.tab-button.active');
276247
if (activeTab instanceof HTMLElement) {
277248
const forTab = activeTab.getAttribute('data-for-tab');
@@ -288,7 +259,7 @@ const MessageList: React.FC<MessageListProps> = ({messages: propMessages}) => {
288259
}
289260
});
290261
}, []);
291-
// Store current tab states before update
262+
292263
const preserveTabStates = useCallback(() => {
293264
const containers = document.querySelectorAll('.tabs-container');
294265
containers.forEach(container => {
@@ -302,8 +273,6 @@ const MessageList: React.FC<MessageListProps> = ({messages: propMessages}) => {
302273
});
303274
}, []);
304275

305-
306-
// Log when component is mounted/unmounted
307276
React.useEffect(() => {
308277
logger.component('MessageList', 'Component mounted', {timestamp: new Date().toISOString()});
309278
return () => {
@@ -326,12 +295,12 @@ const MessageList: React.FC<MessageListProps> = ({messages: propMessages}) => {
326295
// Preserve current tab states
327296
preserveTabStates();
328297

329-
330298
// Process tabs after messages update
331299
requestAnimationFrame(() => {
332300
try {
333301
logger.debug('MessageList - Updating tabs after message change');
334302
updateTabs();
303+
Prism.highlightAll();
335304
} catch (error) {
336305
logger.error('Error processing tabs:', error);
337306
// Reset tab state on error
@@ -340,32 +309,31 @@ const MessageList: React.FC<MessageListProps> = ({messages: propMessages}) => {
340309
});
341310
}, [messages]);
342311

343-
return (
344-
<MessageListContainer>
345-
{filteredMessages.map((message) => {
346-
logger.debug('MessageList - Rendering message', {
347-
id: message.id,
348-
type: message.type,
349-
timestamp: message.timestamp,
350-
contentLength: message.content?.length || 0
351-
});
352-
return (
353-
<MessageItem
354-
key={message.id} // Changed key to use only message.id
355-
type={message.type}
356-
>
357-
<MessageContent
358-
className="message-body"
359-
onClick={handleClick}
360-
dangerouslySetInnerHTML={{
361-
__html: memoizedProcessMessageContent(message.content)
362-
}}
363-
/>
364-
</MessageItem>
365-
);
366-
})}
367-
</MessageListContainer>
368-
);
312+
return <MessageListContainer ref={messageListRef}>
313+
{React.useMemo(() => messages
314+
.filter((message) => message.id && !message.id.startsWith("z"))
315+
.filter((message) => message.content?.length > 0),
316+
[messages]).map((message) => {
317+
logger.debug('MessageList - Rendering message', {
318+
id: message.id,
319+
type: message.type,
320+
timestamp: message.timestamp,
321+
contentLength: message.content?.length || 0
322+
});
323+
return <MessageItem
324+
key={message.id} // Changed key to use only message.id
325+
type={message.type}
326+
>
327+
{<MessageContent
328+
className="message-body"
329+
onClick={handleClick}
330+
dangerouslySetInnerHTML={{
331+
__html: expandMessageReferences(message.content, messages)
332+
}}
333+
/>}
334+
</MessageItem>;
335+
})}
336+
</MessageListContainer>;
369337
};
370338

371339

webapp/chat-app/src/index.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,10 @@ import App from './App';
55
import {store} from './store';
66
import './index.css';
77
import mermaid from 'mermaid';
8-
import QRCodeGenerator from 'qrcode-generator';
98

109
console.log('[App] Starting application initialization...');
1110
console.log('[App] Redux store:', store);
1211

13-
1412
const rootElement = document.getElementById('root');
1513
if (!rootElement) {
1614
console.error('[App] Critical Error: Failed to find root element in DOM');
@@ -22,8 +20,6 @@ const root = createRoot(rootElement);
2220
console.log('[App] React root created successfully');
2321
console.log('[App] Initializing mermaid...');
2422
mermaid.initialize({startOnLoad: true});
25-
window.mermaid = mermaid; // Make mermaid globally accessible
26-
window.QRCode = QRCodeGenerator; // Make QRCode globally accessible
2723
console.log('[App] Mermaid initialized, QRCode ready');
2824

2925
try {

0 commit comments

Comments
 (0)