mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-20 16:57:46 +00:00
feat(vscode-ide-companion): refactor message components with modular architecture
Refactor UI message rendering by extracting message types into dedicated components. Add ChatHeader component for better session management interface. - Extract message components: UserMessage, AssistantMessage, ThinkingMessage, StreamingMessage, WaitingMessage - Add ChatHeader component with session selector and action buttons - Delete MessageContent.css and consolidate styles into App.scss - Update Tailwind config for component styling - Improve message rendering with proper TypeScript typing
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2025 Qwen Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import type React from 'react';
|
||||
import { MessageContent } from '../MessageContent.js';
|
||||
|
||||
interface FileContext {
|
||||
fileName: string;
|
||||
filePath: string;
|
||||
startLine?: number;
|
||||
endLine?: number;
|
||||
}
|
||||
|
||||
interface UserMessageProps {
|
||||
content: string;
|
||||
timestamp: number;
|
||||
onFileClick?: (path: string) => void;
|
||||
fileContext?: FileContext;
|
||||
}
|
||||
|
||||
export const UserMessage: React.FC<UserMessageProps> = ({
|
||||
content,
|
||||
timestamp: _timestamp,
|
||||
onFileClick,
|
||||
fileContext,
|
||||
}) => {
|
||||
// Generate display text for file context
|
||||
const getFileContextDisplay = () => {
|
||||
if (!fileContext) return null;
|
||||
const { fileName, startLine, endLine } = fileContext;
|
||||
if (startLine && endLine) {
|
||||
return startLine === endLine
|
||||
? `${fileName}#${startLine}`
|
||||
: `${fileName}#${startLine}-${endLine}`;
|
||||
}
|
||||
return fileName;
|
||||
};
|
||||
|
||||
const fileContextDisplay = getFileContextDisplay();
|
||||
|
||||
return (
|
||||
<div className="flex gap-0 items-start text-left py-2 flex-col relative animate-[fadeIn_0.2s_ease-in]">
|
||||
<div
|
||||
className="inline-block my-1 relative whitespace-pre-wrap rounded-md max-w-full overflow-x-auto overflow-y-hidden select-text leading-[1.5]"
|
||||
style={{
|
||||
border: '1px solid var(--app-input-border)',
|
||||
borderRadius: 'var(--corner-radius-medium)',
|
||||
backgroundColor: 'var(--app-input-background)',
|
||||
padding: '4px 6px',
|
||||
color: 'var(--app-primary-foreground)',
|
||||
}}
|
||||
>
|
||||
<MessageContent content={content} onFileClick={onFileClick} />
|
||||
</div>
|
||||
{/* File context indicator */}
|
||||
{fileContextDisplay && (
|
||||
<div>
|
||||
<div
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
className="mr"
|
||||
onClick={() => fileContext && onFileClick?.(fileContext.filePath)}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
fileContext && onFileClick?.(fileContext.filePath);
|
||||
}
|
||||
}}
|
||||
style={{ cursor: 'pointer' }}
|
||||
>
|
||||
<div
|
||||
className="gr"
|
||||
title={fileContextDisplay}
|
||||
style={{
|
||||
fontSize: '12px',
|
||||
color: 'var(--app-secondary-foreground)',
|
||||
opacity: 0.8,
|
||||
}}
|
||||
>
|
||||
{fileContextDisplay}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user