feat: update codex live chat workflow

This commit is contained in:
2026-04-22 20:00:38 +09:00
parent 9e4b70f1f1
commit b0b9980a6c
70 changed files with 5178 additions and 2401 deletions

View File

@@ -1,14 +1,25 @@
import { DownloadOutlined, EyeOutlined } from '@ant-design/icons';
import {
CodeOutlined,
DownloadOutlined,
EyeOutlined,
FileMarkdownOutlined,
FilePdfOutlined,
FileTextOutlined,
LinkOutlined,
PictureOutlined,
VideoCameraOutlined,
} from '@ant-design/icons';
import { Alert, Button, Empty, Space, Spin, Typography } from 'antd';
import { InlineImage } from '../../../components/common/InlineImage';
import { MarkdownPreviewContent } from '../../../components/markdownPreview/MarkdownPreviewContent';
import { CodexDiffBlock } from '../../../components/previewer';
import { inferCodeLanguage, renderEditorBlock } from '../../../components/previewer/renderers';
import { triggerResourceDownload } from './downloadUtils';
import '../../../components/previewer/PreviewerUI.css';
const { Paragraph, Text } = Typography;
export type ChatPreviewKind = 'image' | 'video' | 'markdown' | 'code' | 'document' | 'pdf' | 'file';
export type ChatPreviewKind = 'image' | 'video' | 'markdown' | 'code' | 'diff' | 'document' | 'pdf' | 'file';
export type ChatPreviewTarget = {
label: string;
@@ -16,6 +27,47 @@ export type ChatPreviewTarget = {
kind: ChatPreviewKind;
};
export function resolveChatPreviewGlyph(kind: ChatPreviewKind) {
switch (kind) {
case 'image':
return <PictureOutlined />;
case 'video':
return <VideoCameraOutlined />;
case 'markdown':
return <FileMarkdownOutlined />;
case 'code':
case 'diff':
return <CodeOutlined />;
case 'document':
return <FileTextOutlined />;
case 'pdf':
return <FilePdfOutlined />;
default:
return <LinkOutlined />;
}
}
export function resolveChatPreviewKindLabel(kind: ChatPreviewKind) {
switch (kind) {
case 'image':
return 'image preview';
case 'video':
return 'video preview';
case 'markdown':
return 'markdown preview';
case 'code':
return 'code preview';
case 'diff':
return 'diff preview';
case 'document':
return 'document preview';
case 'pdf':
return 'pdf preview';
default:
return 'resource preview';
}
}
function resolvePreviewErrorMessage(previewError: string) {
const normalized = previewError.trim();
@@ -247,10 +299,10 @@ export function ChatPreviewBody({
);
}
if (target.kind === 'code' || target.kind === 'document') {
if (target.kind === 'code' || target.kind === 'diff' || target.kind === 'document') {
const resolvedLanguage = resolveCodeLanguage(target, previewText);
if (resolvedLanguage === 'diff') {
if (target.kind === 'diff' || resolvedLanguage === 'diff') {
return (
<div className="app-chat-panel__preview-rich app-chat-panel__preview-rich--code">
<CodexDiffBlock
@@ -291,12 +343,16 @@ export function ChatPreviewBody({
. .
</Paragraph>
<Space wrap>
<Button href={target.url} target="_blank" rel="noreferrer" icon={<EyeOutlined />}>
</Button>
<Button href={target.url} download icon={<DownloadOutlined />}>
</Button>
<Button type="text" href={target.url} target="_blank" rel="noreferrer" aria-label="새 탭 열기" icon={<EyeOutlined />} />
<Button
type="text"
aria-label="다운로드"
icon={<DownloadOutlined />}
onClick={() => {
const fileName = target.url.split('/').pop()?.trim() || target.label;
triggerResourceDownload(target.url, fileName);
}}
/>
</Space>
</div>
);