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,5 +1,6 @@
import {
CopyOutlined,
DownloadOutlined,
DownOutlined,
FileImageOutlined,
FileTextOutlined,
@@ -92,7 +93,7 @@ export function CodexDiffPreviewer({
}: CodexDiffPreviewerProps) {
const [messageApi, contextHolder] = message.useMessage();
const [activeMode, setActiveMode] = useState<'source' | 'diff'>(files.length > 0 ? 'source' : 'diff');
const [expandedSourcePaths, setExpandedSourcePaths] = useState<string[]>(() => files.slice(0, 1).map((file) => file.path));
const [expandedSourcePath, setExpandedSourcePath] = useState<string | null>(() => files[0]?.path ?? null);
const [expandedPreviewPath, setExpandedPreviewPath] = useState<string | null>(null);
const statusCount = useMemo(() => buildStatusCount(files), [files]);
const canShowSource = files.length > 0;
@@ -129,6 +130,24 @@ export function CodexDiffPreviewer({
}
}
function handleDownload(path: string, content: string) {
if (typeof document === 'undefined') {
messageApi.error('다운로드를 사용할 수 없습니다.');
return;
}
const fileName = path.split('/').pop() || 'preview.txt';
const blob = new Blob([content], { type: 'text/plain;charset=utf-8' });
const objectUrl = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = objectUrl;
link.download = fileName;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(objectUrl);
}
function handleFullscreen(path: string) {
setExpandedPreviewPath((currentPath) => (currentPath === path ? null : path));
}
@@ -141,15 +160,12 @@ export function CodexDiffPreviewer({
return;
}
setExpandedSourcePaths((currentPaths) => {
const availablePaths = new Set(files.map((file) => file.path));
const nextPaths = currentPaths.filter((path) => availablePaths.has(path));
if (nextPaths.length > 0) {
return nextPaths;
setExpandedSourcePath((currentPath) => {
if (currentPath && files.some((file) => file.path === currentPath)) {
return currentPath;
}
return files[0] ? [files[0].path] : [];
return files[0]?.path ?? null;
});
}, [canShowSource, diffText, files]);
@@ -231,15 +247,15 @@ export function CodexDiffPreviewer({
<Button
size="small"
onClick={() => {
setExpandedSourcePaths(files.map((file) => file.path));
setExpandedSourcePath(files[0]?.path ?? null);
}}
>
</Button>
<Button
size="small"
onClick={() => {
setExpandedSourcePaths([]);
setExpandedSourcePath(null);
}}
>
@@ -248,7 +264,7 @@ export function CodexDiffPreviewer({
</div>
{files.map((file) => {
const isExpanded = expandedSourcePaths.includes(file.path);
const isExpanded = expandedSourcePath === file.path;
const isPreviewExpanded = expandedPreviewPath === file.path;
const displayPath = file.previousPath ? `${file.previousPath} -> ${file.path}` : file.path;
@@ -266,11 +282,7 @@ export function CodexDiffPreviewer({
type="button"
className="codex-diff-previewer__diff-toggle"
onClick={() => {
setExpandedSourcePaths((currentPaths) =>
currentPaths.includes(file.path)
? currentPaths.filter((path) => path !== file.path)
: [...currentPaths, file.path],
);
setExpandedSourcePath((currentPath) => (currentPath === file.path ? null : file.path));
}}
>
<Space align="center" size={10} className="codex-diff-previewer__diff-toggle-main">
@@ -296,6 +308,16 @@ export function CodexDiffPreviewer({
void handleCopy(file.content);
}}
/>
<Button
size="small"
type="text"
aria-label="다운로드"
icon={<DownloadOutlined />}
onClick={(event) => {
event.stopPropagation();
handleDownload(file.path, file.content);
}}
/>
<Button
size="small"
type="text"
@@ -316,6 +338,7 @@ export function CodexDiffPreviewer({
value={file.content}
language={file.language}
imageAlt={file.path.split('/').pop() ?? file.path}
downloadFileName={file.path.split('/').pop() ?? file.path}
height={isPreviewExpanded ? 'calc(100vh - 120px)' : height}
copyable={false}
maximizable={false}