1
1
// client/packages/lowcoder/src/comps/comps/chatComp/components/ChatCoreMain.tsx
2
2
3
- import React , { useState , useEffect } from "react" ;
3
+ import React , { useState , useEffect , useRef , useContext } from "react" ;
4
4
import {
5
5
useExternalStoreRuntime ,
6
6
ThreadMessageLike ,
@@ -19,6 +19,10 @@ import {
19
19
import { MessageHandler } from "../types/chatTypes" ;
20
20
import styled from "styled-components" ;
21
21
import { trans } from "i18n" ;
22
+ import { EditorContext , EditorState } from "@lowcoder-ee/comps/editorState" ;
23
+ import { configureComponentAction } from "../../preLoadComp/actions/componentConfiguration" ;
24
+ import { addComponentAction , moveComponentAction , nestComponentAction , resizeComponentAction } from "../../preLoadComp/actions/componentManagement" ;
25
+ import { applyThemeAction , configureAppMetaAction , setCanvasSettingsAction } from "../../preLoadComp/actions/appConfiguration" ;
22
26
23
27
// ============================================================================
24
28
// STYLED COMPONENTS (same as your current ChatMain)
@@ -78,6 +82,14 @@ export function ChatCoreMain({
78
82
} :ChatCoreMainProps ) {
79
83
const { state, actions} = useChatContext ( ) ;
80
84
const [ isRunning , setIsRunning ] = useState ( false ) ;
85
+ const editorState = useContext ( EditorContext ) ;
86
+ const editorStateRef = useRef ( editorState ) ;
87
+
88
+ // Keep the ref updated with the latest editorState
89
+ useEffect ( ( ) => {
90
+ // console.log("EDITOR STATE CHANGE ---> ", editorState);
91
+ editorStateRef . current = editorState ;
92
+ } , [ editorState ] ) ;
81
93
82
94
// Get messages for current thread
83
95
const currentMessages = actions . getCurrentMessages ( ) ;
@@ -92,6 +104,143 @@ export function ChatCoreMain({
92
104
onEvent ?.( "componentLoad" ) ;
93
105
} , [ onEvent ] ) ;
94
106
107
+ const performAction = async ( actions :any [ ] ) => {
108
+ if ( ! editorStateRef . current ) {
109
+ console . error ( "No editorStateRef found" ) ;
110
+ return ;
111
+ }
112
+
113
+ const comp = editorStateRef . current . getUIComp ( ) . children . comp ;
114
+ if ( ! comp ) {
115
+ console . error ( "No comp found" ) ;
116
+ return ;
117
+ }
118
+ // const layout = comp.children.layout.getView();
119
+ // console.log("LAYOUT", layout);
120
+
121
+ for ( const actionItem of actions ) {
122
+ const { action, component, ...action_payload } = actionItem ;
123
+
124
+ switch ( action ) {
125
+ case "place_component" :
126
+ await addComponentAction . execute ( {
127
+ actionKey :action ,
128
+ actionValue :"" ,
129
+ actionPayload :action_payload ,
130
+ selectedComponent :component ,
131
+ selectedEditorComponent :null ,
132
+ selectedNestComponent :null ,
133
+ editorState :editorStateRef . current ,
134
+ selectedDynamicLayoutIndex :null ,
135
+ selectedTheme :null ,
136
+ selectedCustomShortcutAction :null
137
+ } ) ;
138
+ break ;
139
+ case "nest_component" :
140
+ await nestComponentAction . execute ( {
141
+ actionKey :action ,
142
+ actionValue :"" ,
143
+ actionPayload :action_payload ,
144
+ selectedComponent :component ,
145
+ selectedEditorComponent :null ,
146
+ selectedNestComponent :null ,
147
+ editorState :editorStateRef . current ,
148
+ selectedDynamicLayoutIndex :null ,
149
+ selectedTheme :null ,
150
+ selectedCustomShortcutAction :null
151
+ } ) ;
152
+ break ;
153
+ case "move_component" :
154
+ await moveComponentAction . execute ( {
155
+ actionKey :action ,
156
+ actionValue :"" ,
157
+ actionPayload :action_payload ,
158
+ selectedComponent :component ,
159
+ selectedEditorComponent :null ,
160
+ selectedNestComponent :null ,
161
+ editorState :editorStateRef . current ,
162
+ selectedDynamicLayoutIndex :null ,
163
+ selectedTheme :null ,
164
+ selectedCustomShortcutAction :null
165
+ } ) ;
166
+ break ;
167
+ case "resize_component" :
168
+ await resizeComponentAction . execute ( {
169
+ actionKey :action ,
170
+ actionValue :"" ,
171
+ actionPayload :action_payload ,
172
+ selectedComponent :component ,
173
+ selectedEditorComponent :null ,
174
+ selectedNestComponent :null ,
175
+ editorState :editorStateRef . current ,
176
+ selectedDynamicLayoutIndex :null ,
177
+ selectedTheme :null ,
178
+ selectedCustomShortcutAction :null
179
+ } ) ;
180
+ break ;
181
+ case "set_properties" :
182
+ await configureComponentAction . execute ( {
183
+ actionKey :action ,
184
+ actionValue :component ,
185
+ actionPayload :action_payload ,
186
+ selectedEditorComponent :null ,
187
+ selectedComponent :null ,
188
+ selectedNestComponent :null ,
189
+ editorState :editorStateRef . current ,
190
+ selectedDynamicLayoutIndex :null ,
191
+ selectedTheme :null ,
192
+ selectedCustomShortcutAction :null
193
+ } ) ;
194
+ break ;
195
+ case "set_theme" :
196
+ await applyThemeAction . execute ( {
197
+ actionKey :action ,
198
+ actionValue :component ,
199
+ actionPayload :action_payload ,
200
+ selectedEditorComponent :null ,
201
+ selectedComponent :null ,
202
+ selectedNestComponent :null ,
203
+ editorState :editorStateRef . current ,
204
+ selectedDynamicLayoutIndex :null ,
205
+ selectedTheme :null ,
206
+ selectedCustomShortcutAction :null
207
+ } ) ;
208
+ break ;
209
+ case "set_app_metadata" :
210
+ await configureAppMetaAction . execute ( {
211
+ actionKey :action ,
212
+ actionValue :component ,
213
+ actionPayload :action_payload ,
214
+ selectedEditorComponent :null ,
215
+ selectedComponent :null ,
216
+ selectedNestComponent :null ,
217
+ editorState :editorStateRef . current ,
218
+ selectedDynamicLayoutIndex :null ,
219
+ selectedTheme :null ,
220
+ selectedCustomShortcutAction :null
221
+ } ) ;
222
+ break ;
223
+ case "set_canvas_setting" :
224
+ await setCanvasSettingsAction . execute ( {
225
+ actionKey :action ,
226
+ actionValue :component ,
227
+ actionPayload :action_payload ,
228
+ selectedEditorComponent :null ,
229
+ selectedComponent :null ,
230
+ selectedNestComponent :null ,
231
+ editorState :editorStateRef . current ,
232
+ selectedDynamicLayoutIndex :null ,
233
+ selectedTheme :null ,
234
+ selectedCustomShortcutAction :null
235
+ } ) ;
236
+ break ;
237
+ default :
238
+ break ;
239
+ }
240
+ await new Promise ( resolve => setTimeout ( resolve , 1000 ) ) ;
241
+ }
242
+ } ;
243
+
95
244
// Convert custom format to ThreadMessageLike (same as your current implementation)
96
245
const convertMessage = ( message :ChatMessage ) :ThreadMessageLike => ( {
97
246
role :message . role ,
@@ -123,9 +272,15 @@ export function ChatCoreMain({
123
272
setIsRunning ( true ) ;
124
273
125
274
try {
126
-
127
275
// Use the message handler (no more complex logic here!)
128
- const response = await messageHandler . sendMessage ( userMessage . text ) ;
276
+ const response = await messageHandler . sendMessage (
277
+ userMessage . text ,
278
+ state . currentThreadId ,
279
+ ) ;
280
+
281
+ if ( response ?. actions ?. length ) {
282
+ performAction ( response . actions ) ;
283
+ }
129
284
130
285
const assistantMessage :ChatMessage = {
131
286
id :generateId ( ) ,
@@ -182,8 +337,15 @@ export function ChatCoreMain({
182
337
183
338
try {
184
339
// Use the message handler (clean!)
185
- const response = await messageHandler . sendMessage ( editedMessage . text ) ;
340
+ const response = await messageHandler . sendMessage (
341
+ editedMessage . text ,
342
+ state . currentThreadId ,
343
+ ) ;
186
344
345
+ if ( response ?. actions ?. length ) {
346
+ performAction ( response . actions ) ;
347
+ }
348
+
187
349
const assistantMessage :ChatMessage = {
188
350
id :generateId ( ) ,
189
351
role :"assistant" ,