Skip to content

Commit 1a54781

Browse files
integrate into sidebar
1 parent 9bb3d3a commit 1a54781

File tree

4 files changed

+32
-89
lines changed

4 files changed

+32
-89
lines changed

ui/src/App.tsx

Lines changed: 9 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,36 @@
11
// Copyright (C) 2025 AIDC-AI
22
// Licensed under the MIT License.
33

4-
import React, { useRef, useState, useEffect } from "react";
5-
import { DRAWER_Z_INDEX } from "./const";
4+
import React, { useState, useEffect, Suspense } from "react";
65
import { COPILOT_EVENTS } from "./constants/events";
7-
import logoImage from '../../assets/logo.png';
86
import { ChatProvider } from './context/ChatContext';
9-
import { useDraggable } from './hooks/useDraggable';
107

118
const WorkflowChat = React.lazy(() => import("./workflowChat/workflowChat").then(module => ({
129
default: module.default
1310
})));
1411

1512
export default function App() {
16-
const workspaceContainerRef = useRef(null);
17-
const [showChat, setShowChat] = useState(false);
1813
const [shouldTriggerUsage, setShouldTriggerUsage] = useState(false);
1914

20-
const { position, isDragging, handleMouseDown } = useDraggable({
21-
boundaryPadding: { right: 100, bottom: 40 },
22-
onClick: () => setShowChat(true)
23-
});
24-
2515
useEffect(() => {
2616
const handleExplainNode = () => {
27-
setShowChat(true);
2817
setShouldTriggerUsage(true);
2918
};
3019

3120
window.addEventListener(COPILOT_EVENTS.EXPLAIN_NODE, handleExplainNode);
3221
return () => window.removeEventListener(COPILOT_EVENTS.EXPLAIN_NODE, handleExplainNode);
3322
}, []);
3423

35-
if (!position) return null;
36-
3724
return (
3825
<ChatProvider>
39-
<div ref={workspaceContainerRef}>
40-
<div
41-
className="fixed"
42-
style={{
43-
zIndex: DRAWER_Z_INDEX,
44-
left: position.x,
45-
top: position.y,
46-
cursor: isDragging ? 'grabbing' : 'grab'
47-
}}
48-
>
49-
<button
50-
onMouseDown={handleMouseDown}
51-
className="px-2 py-1 border border-gray-300 rounded-md bg-white text-black hover:bg-blue-300 hover:font-bold transition-colors select-none w-40 flex items-center space-x-1"
52-
style={{ marginLeft: "-40px" }}
53-
>
54-
<img
55-
src={logoImage}
56-
alt="ComfyUI-Copilot Logo"
57-
className="h-8 w-8"
58-
/>
59-
<span className="text-[14px] font-medium text-gray-800">ComfyUI-Copilot</span>
60-
</button>
61-
62-
<React.Suspense fallback={<div>Loading...</div>}>
63-
<WorkflowChat
64-
onClose={() => {
65-
setShowChat(false);
66-
setShouldTriggerUsage(false);
67-
}}
68-
visible={showChat}
69-
triggerUsage={shouldTriggerUsage}
70-
onUsageTriggered={() => setShouldTriggerUsage(false)}
71-
/>
72-
</React.Suspense>
73-
</div>
26+
<div className="h-full w-full">
27+
<Suspense fallback={<div>Loading...</div>}>
28+
<WorkflowChat
29+
visible={true}
30+
triggerUsage={shouldTriggerUsage}
31+
onUsageTriggered={() => setShouldTriggerUsage(false)}
32+
/>
33+
</Suspense>
7434
</div>
7535
</ChatProvider>
7636
);

ui/src/components/chat/ChatHeader.tsx

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,6 @@ export function ChatHeader({
6969

7070
return (
7171
<>
72-
<div
73-
className="absolute top-0 left-0 right-0 h-2 bg-gray-100 hover:bg-gray-300
74-
transition-colors duration-200 cursor-ns-resize z-20"
75-
onMouseDown={handleMouseDown}
76-
style={{
77-
borderBottom: '1px solid #e5e7eb',
78-
}}
79-
/>
8072
<div className="flex items-center justify-between border-b px-4 py-3
8173
bg-white border-gray-200 sticky top-2 z-10">
8274
<div className="flex items-center space-x-2">

ui/src/main.tsx

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// Copyright (C) 2025 AIDC-AI
1010
// Licensed under the MIT License.
1111

12-
import React from "react";
12+
import React, { Suspense } from "react";
1313
import ReactDOM from "react-dom/client";
1414
import { waitForApp } from "./utils/comfyapp.ts";
1515
import "./scoped-tailwind.css";
@@ -35,13 +35,23 @@ function waitForDocumentBody() {
3535
waitForDocumentBody()
3636
.then(() => waitForApp())
3737
.then(() => {
38-
// todo: 创建一个web component
39-
const topbar = document.createElement("div");
40-
topbar.id = "comfyui-copilot-plugin";
41-
document.body.append(topbar);
42-
ReactDOM.createRoot(topbar).render(
43-
<React.StrictMode>
44-
<App />
45-
</React.StrictMode>,
46-
);
38+
app.extensionManager.registerSidebarTab({
39+
id: "comfyui-copilot",
40+
icon: "mdi mdi-robot-excited-outline",
41+
title: "ComfyUI Copilot",
42+
tooltip: "ComfyUI Copilot",
43+
type: "custom",
44+
render: (el: HTMLElement) => {
45+
const container = document.createElement("div");
46+
container.id = "comfyui-copilot-plugin";
47+
el.appendChild(container);
48+
ReactDOM.createRoot(container).render(
49+
<React.StrictMode>
50+
<Suspense fallback={<div>Loading...</div>}>
51+
<App />
52+
</Suspense>
53+
</React.StrictMode>,
54+
);
55+
},
56+
});
4757
});

ui/src/workflowChat/workflowChat.tsx

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
import { ChangeEvent, KeyboardEvent, useEffect, useRef, useState } from "react";
1313
import { Message } from "../types/types";
1414
import { WorkflowChatAPI } from "../apis/workflowChatApi";
15-
import { app } from "../utils/comfyapp";
1615
import { ChatHeader } from "../components/chat/ChatHeader";
1716
import { ChatInput } from "../components/chat/ChatInput";
1817
import { SelectedNodeInfo } from "../components/chat/SelectedNodeInfo";
@@ -24,7 +23,6 @@ import React from "react";
2423
import { debounce } from "lodash";
2524
import { useChatContext } from '../context/ChatContext';
2625
import { useMousePosition } from '../hooks/useMousePosition';
27-
import { useResizable } from '../hooks/useResizable';
2826
import { useNodeSelection } from '../hooks/useNodeSelection';
2927
import { MemoizedReactMarkdown } from "../components/markdown";
3028
import remarkGfm from 'remark-gfm';
@@ -172,17 +170,6 @@ export default function WorkflowChat({ onClose, visible = true, triggerUsage = f
172170
useNodeSelection(visible);
173171

174172
// 使用自定义 hooks
175-
const {
176-
isResizing: resizableIsResizing,
177-
setIsResizing: resizableSetIsResizing,
178-
dimensions,
179-
handleHeightResize
180-
} = useResizable({
181-
minWidth: 300,
182-
maxWidth: window.innerWidth * 0.8,
183-
minHeight: 300,
184-
maxHeight: window.innerHeight
185-
}, visible);
186173

187174
useEffect(() => {
188175
if (messageDivRef.current) {
@@ -579,30 +566,24 @@ export default function WorkflowChat({ onClose, visible = true, triggerUsage = f
579566
<ParameterDebugTab />
580567
), []);
581568

569+
if (!visible) return null;
570+
582571
return (
583572
<div
584-
className="fixed right-0 shadow-lg bg-white duration-200 ease-out"
573+
className="flex flex-col h-full w-full bg-white"
585574
style={{
586575
display: visible ? 'block' : 'none',
587-
width: `${dimensions.width}px`,
588-
height: `${dimensions.height}px`,
589-
top: `${dimensions.top}px`
590576
}}
591577
>
592578
<div
593579
className="absolute left-0 top-0 bottom-0 w-1 cursor-ew-resize hover:bg-gray-300"
594-
onMouseDown={(e) => {
595-
resizableSetIsResizing(true);
596-
e.preventDefault();
597-
}}
598580
/>
599581

600582
<div className="flex h-full flex-col">
601583
<ChatHeader
602584
onClose={onClose}
603585
onClear={handleClearMessages}
604586
hasMessages={messages.length > 0}
605-
onHeightResize={handleHeightResize}
606587
title={`ComfyUI-Copilot`}
607588
/>
608589

0 commit comments

Comments
 (0)