From 60a9f3dc3214f0b94727cf3d55615ed59f1181b6 Mon Sep 17 00:00:00 2001 From: Haileyesus Date: Thu, 12 Feb 2026 20:50:44 +0300 Subject: [PATCH] refactor(MessageComponent): add types --- .../view/subcomponents/MessageComponent.tsx | 55 +++++++++++-------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/src/components/chat/view/subcomponents/MessageComponent.tsx b/src/components/chat/view/subcomponents/MessageComponent.tsx index 2a46e96..30d85a2 100644 --- a/src/components/chat/view/subcomponents/MessageComponent.tsx +++ b/src/components/chat/view/subcomponents/MessageComponent.tsx @@ -1,8 +1,12 @@ -// @ts-nocheck import React, { memo, useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import SessionProviderLogo from '../../../SessionProviderLogo'; -import type { ChatMessage, Provider } from '../../types/types'; +import type { + ChatMessage, + ClaudePermissionSuggestion, + PermissionGrantResult, + Provider, +} from '../../types/types'; import { Markdown } from './Markdown'; import { formatUsageLimitText } from '../../utils/chatFormatting'; import { getClaudePermissionSuggestion } from '../../utils/chatPermissions'; @@ -20,9 +24,9 @@ interface MessageComponentProps { index: number; prevMessage: ChatMessage | null; createDiff: (oldStr: string, newStr: string) => DiffLine[]; - onFileOpen?: (filePath: string, diffInfo?: any) => void; + onFileOpen?: (filePath: string, diffInfo?: unknown) => void; onShowSettings?: () => void; - onGrantToolPermission?: (suggestion: any) => any; + onGrantToolPermission?: (suggestion: ClaudePermissionSuggestion) => PermissionGrantResult | null | undefined; autoExpandTools?: boolean; showRawParameters?: boolean; showThinking?: boolean; @@ -30,6 +34,14 @@ interface MessageComponentProps { provider: Provider | string; } +type InteractiveOption = { + number: string; + text: string; + isSelected: boolean; +}; + +type PermissionGrantState = 'idle' | 'granted' | 'error'; + const MessageComponent = memo(({ message, index, prevMessage, createDiff, onFileOpen, onShowSettings, onGrantToolPermission, autoExpandTools, showRawParameters, showThinking, selectedProject, provider }: MessageComponentProps) => { const { t } = useTranslation('chat'); const isGrouped = prevMessage && prevMessage.type === message.type && @@ -37,10 +49,10 @@ const MessageComponent = memo(({ message, index, prevMessage, createDiff, onFile (prevMessage.type === 'user') || (prevMessage.type === 'tool') || (prevMessage.type === 'error')); - const messageRef = React.useRef(null); + const messageRef = React.useRef(null); const [isExpanded, setIsExpanded] = React.useState(false); const permissionSuggestion = getClaudePermissionSuggestion(message, provider); - const [permissionGrantState, setPermissionGrantState] = React.useState('idle'); + const [permissionGrantState, setPermissionGrantState] = React.useState('idle'); React.useEffect(() => { @@ -56,8 +68,8 @@ const MessageComponent = memo(({ message, index, prevMessage, createDiff, onFile entries.forEach((entry) => { if (entry.isIntersecting && !isExpanded) { setIsExpanded(true); - const details = node.querySelectorAll('details'); - details.forEach(detail => { + const details = node.querySelectorAll('details'); + details.forEach((detail) => { detail.open = true; }); } @@ -140,13 +152,15 @@ const MessageComponent = memo(({ message, index, prevMessage, createDiff, onFile <>
- {message.displayText} + + {String(message.displayText || '')} +
{message.toolInput && ( )} {/* Tool Result Section */} - {message.toolResult && !shouldHideToolResult(message.toolName, message.toolResult) && ( + {message.toolResult && !shouldHideToolResult(message.toolName || 'UnknownTool', message.toolResult) && ( message.toolResult.isError ? ( // Error results - red error box with content
{(() => { - const lines = (message.content || '').split('\n').filter(line => line.trim()); - const questionLine = lines.find(line => line.includes('?')) || lines[0] || ''; - const options = []; + const lines = (message.content || '').split('\n').filter((line) => line.trim()); + const questionLine = lines.find((line) => line.includes('?')) || lines[0] || ''; + const options: InteractiveOption[] = []; // Parse the menu options - lines.forEach(line => { + lines.forEach((line) => { // Match lines like "❯ 1. Yes" or " 2. No" const optionMatch = line.match(/[❯\s]*(\d+)\.\s+(.+)/); if (optionMatch) { @@ -393,7 +406,7 @@ const MessageComponent = memo(({ message, index, prevMessage, createDiff, onFile
); - } catch (e) { + } catch { // Not valid JSON, fall through to normal rendering } } @@ -424,6 +437,4 @@ const MessageComponent = memo(({ message, index, prevMessage, createDiff, onFile ); }); -export default MessageComponent; - - +export default MessageComponent; \ No newline at end of file