Skip to content

Commit e72b4db

Browse files
committed
fix(): try it out with commands or mentions
1 parent c2400f3 commit e72b4db

File tree

6 files changed

+85
-98
lines changed

6 files changed

+85
-98
lines changed

bricks/ai-portal/src/chat-box/index.tsx

Lines changed: 61 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import React, {
66
useState,
77
useImperativeHandle,
88
createRef,
9-
useMemo,
109
} from "react";
1110
import { createPortal } from "react-dom";
1211
import { createDecorators, type EventEmitter } from "@next-core/element";
@@ -25,6 +24,7 @@ import styleText from "./styles.shadow.css";
2524
import {
2625
getChatCommand,
2726
setChatCommand,
27+
type ChatCommand,
2828
} from "../data-providers/set-chat-command.js";
2929
import type {
3030
ChatPayload,
@@ -40,6 +40,7 @@ import UploadedFilesStyleText from "../shared/FileUpload/UploadedFiles.shadow.cs
4040
import { WrappedActions, WrappedIcon } from "./bricks.js";
4141
import { useFilesUploading } from "../shared/useFilesUploading.js";
4242
import GlobalDragOverlay from "../shared/FileUpload/GlobalDragOverlay.js";
43+
import { getInitialContent } from "../shared/ReadableCommand/ReadableCommand.js";
4344

4445
initializeI18n(NS, locales);
4546

@@ -132,13 +133,6 @@ class ChatBox extends ReactNextElement implements ChatBoxProps {
132133
this.#chatSubmit.emit(payload);
133134
};
134135

135-
@event({ type: "command.select" })
136-
accessor #commandSelect!: EventEmitter<CommandPayload | null>;
137-
138-
#handleCommandSelect = (command: CommandPayload | null) => {
139-
this.#commandSelect.emit(command);
140-
};
141-
142136
@method()
143137
setValue(value: string) {
144138
this.ref.current?.setValue(value);
@@ -165,7 +159,6 @@ class ChatBox extends ReactNextElement implements ChatBoxProps {
165159
uploadOptions={this.uploadOptions}
166160
onMessageSubmit={this.#handleMessageSubmit}
167161
onChatSubmit={this.#handleChatSubmit}
168-
onCommandSelect={this.#handleCommandSelect}
169162
root={this}
170163
ref={this.ref}
171164
/>
@@ -177,7 +170,6 @@ interface ChatBoxComponentProps extends ChatBoxProps {
177170
root: HTMLElement;
178171
onMessageSubmit: (value: string) => void;
179172
onChatSubmit: (payload: ChatPayload) => void;
180-
onCommandSelect: (command: CommandPayload | null) => void;
181173
ref?: React.Ref<ChatBoxRef>;
182174
}
183175

@@ -201,7 +193,6 @@ function LegacyChatBoxComponent(
201193
uploadOptions,
202194
onMessageSubmit,
203195
onChatSubmit,
204-
onCommandSelect,
205196
}: ChatBoxComponentProps,
206197
ref: React.Ref<ChatBoxRef>
207198
) {
@@ -254,6 +245,18 @@ function LegacyChatBoxComponent(
254245
}
255246
}, [uploadEnabled, resetFiles]);
256247

248+
const [initialMention, setInitialMention] = useState<string | null>(null);
249+
const [initialCommand, setInitialCommand] = useState<ChatCommand | null>(
250+
null
251+
);
252+
useEffect(() => {
253+
const command = getChatCommand();
254+
if (command) {
255+
setChatCommand(null);
256+
}
257+
setInitialCommand(command);
258+
}, []);
259+
257260
useEffect(() => {
258261
const store = window.__elevo_try_it_out;
259262
if (store) {
@@ -262,6 +265,13 @@ function LegacyChatBoxComponent(
262265
if (typeof store?.content === "string") {
263266
valueRef.current = store.content;
264267
setValue(store.content);
268+
if (store?.cmd) {
269+
setInitialCommand({
270+
payload: store.cmd,
271+
});
272+
} else if (store?.mentionedAiEmployeeId) {
273+
setInitialMention(store.mentionedAiEmployeeId);
274+
}
265275
}
266276
}, []);
267277

@@ -473,12 +483,11 @@ function LegacyChatBoxComponent(
473483
) {
474484
setCommandText("");
475485
setCommand(null);
476-
onCommandSelect(null);
477486
setCommands(propCommands);
478487
setCommandPrefix("/");
479488
setCommandPopover(null);
480489
}
481-
}, [commandPrefix, commandText, onCommandSelect, value, propCommands]);
490+
}, [commandPrefix, commandText, value, propCommands]);
482491

483492
const handleSubmitClick = useCallback(() => {
484493
doSubmit(valueRef.current);
@@ -503,20 +512,7 @@ function LegacyChatBoxComponent(
503512
setMentionOverlay(null);
504513
return;
505514
}
506-
const rects = getContentRectsInTextarea(
507-
element,
508-
"",
509-
// Ignore the last space
510-
mentionedText.slice(0, -1)
511-
);
512-
setMentionOverlay(
513-
rects.map((rect) => ({
514-
left: rect.left - 1,
515-
top: rect.top - 1,
516-
width: rect.width + 4,
517-
height: rect.height + 4,
518-
}))
519-
);
515+
setMentionOverlay(getOverlayRects(element, mentionedText));
520516
}, [mentionedText, hasFiles]);
521517

522518
useEffect(() => {
@@ -525,55 +521,15 @@ function LegacyChatBoxComponent(
525521
setCommandOverlay(null);
526522
return;
527523
}
528-
const rects = getContentRectsInTextarea(
529-
element,
530-
"",
531-
// Ignore the last space
532-
commandText.slice(0, -1)
533-
);
534-
setCommandOverlay(
535-
rects.map((rect) => ({
536-
left: rect.left - 1,
537-
top: rect.top - 1,
538-
width: rect.width + 4,
539-
height: rect.height + 4,
540-
}))
541-
);
524+
setCommandOverlay(getOverlayRects(element, commandText));
542525
}, [commandText, hasFiles]);
543526

544-
const chatCommand = useMemo(() => {
545-
const command = getChatCommand();
546-
if (command) {
547-
setChatCommand(null);
548-
}
549-
return command;
550-
}, []);
551-
552-
useEffect(() => {
553-
if (chatCommand) {
554-
setCommand(chatCommand.payload);
555-
onCommandSelect(chatCommand.payload);
556-
}
557-
}, [chatCommand, onCommandSelect]);
558-
559527
useEffect(() => {
560528
const element = textareaRef.current?.element;
561-
if (chatCommand && element) {
562-
const commandStr = `/${chatCommand.command} `;
563-
const rects = getContentRectsInTextarea(
564-
element,
565-
"",
566-
// Ignore the last space
567-
commandStr.slice(0, -1)
568-
);
569-
setCommandOverlay(
570-
rects.map((rect) => ({
571-
left: rect.left - 1,
572-
top: rect.top - 1,
573-
width: rect.width + 4,
574-
height: rect.height + 4,
575-
}))
576-
);
529+
if (initialCommand && element) {
530+
setCommand(initialCommand.payload);
531+
const commandStr = `${getInitialContent(initialCommand.payload)} `;
532+
setCommandOverlay(getOverlayRects(element, commandStr));
577533
valueRef.current = commandStr;
578534
selectionRef.current = {
579535
start: commandStr.length,
@@ -582,7 +538,23 @@ function LegacyChatBoxComponent(
582538
setValue(commandStr);
583539
setCommandText(commandStr);
584540
}
585-
}, [chatCommand]);
541+
}, [initialCommand]);
542+
543+
useEffect(() => {
544+
const element = textareaRef.current?.element;
545+
if (initialMention && element) {
546+
setMentioned(initialMention);
547+
const mentionStr = `${getInitialContent(undefined, initialMention)} `;
548+
setMentionOverlay(getOverlayRects(element, mentionStr));
549+
valueRef.current = mentionStr;
550+
selectionRef.current = {
551+
start: mentionStr.length,
552+
end: mentionStr.length,
553+
};
554+
setValue(mentionStr);
555+
setMentionedText(mentionStr);
556+
}
557+
}, [initialMention]);
586558

587559
const handleMention = useCallback(
588560
(action: SimpleAction) => {
@@ -632,11 +604,10 @@ function LegacyChatBoxComponent(
632604
setCommand(action.payload!);
633605
setCommandPopover(null);
634606
setCommandPrefix("/");
635-
onCommandSelect(action.payload!);
636607
}
637608
textareaRef.current?.focus();
638609
},
639-
[commandPopover, commandPrefix, onCommandSelect]
610+
[commandPopover, commandPrefix]
640611
);
641612

642613
const handleKeyDown = useCallback(
@@ -882,6 +853,21 @@ function getActiveActionKeys(
882853
return [meaningfulActions[index].key!];
883854
}
884855

856+
function getOverlayRects(element: HTMLTextAreaElement, content: string) {
857+
const rects = getContentRectsInTextarea(
858+
element,
859+
"",
860+
// Ignore the last space
861+
content.slice(0, -1)
862+
);
863+
return rects.map((rect) => ({
864+
left: rect.left - 1,
865+
top: rect.top - 1,
866+
width: rect.width + 4,
867+
height: rect.height + 4,
868+
}));
869+
}
870+
885871
function getCommandPopover(
886872
commands: Command[],
887873
textarea: HTMLTextAreaElement,

bricks/ai-portal/src/chat-stream/ChatStream.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -220,12 +220,8 @@ export function ChatStreamComponent(
220220
[humanInputRef]
221221
);
222222

223-
const requirementMessage = messages[0];
224-
const userInput = useMemo(() => {
225-
if (requirementMessage?.role === "user") {
226-
return requirementMessage.content;
227-
}
228-
}, [requirementMessage]);
223+
const firstMessage = messages[0];
224+
const userMessage = firstMessage?.role === "user" ? firstMessage : null;
229225

230226
const [activeImages, setActiveImages] = useState<ActiveImages | null>(null);
231227

@@ -272,9 +268,13 @@ export function ChatStreamComponent(
272268
"_blank"
273269
);
274270
if (win) {
275-
win.__elevo_try_it_out = {
276-
content: userInput,
277-
};
271+
win.__elevo_try_it_out = userMessage
272+
? {
273+
content: userMessage.content,
274+
cmd: userMessage.cmd,
275+
mentionedAiEmployeeId: userMessage.mentionedAiEmployeeId,
276+
}
277+
: {};
278278
}
279279
},
280280
activeFile,
@@ -312,7 +312,7 @@ export function ChatStreamComponent(
312312

313313
skipToResults,
314314
watchAgain,
315-
userInput,
315+
userMessage,
316316
tryItOutUrl,
317317
activeFile,
318318
activeImages,

bricks/ai-portal/src/cruise-canvas/CruiseCanvas.tsx

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -610,13 +610,8 @@ export function CruiseCanvasComponent(
610610
});
611611
}, []);
612612

613-
const requirementNode = rawNodes?.[0];
614-
615-
const userInput = useMemo(() => {
616-
if (requirementNode?.type === "requirement") {
617-
return requirementNode.content;
618-
}
619-
}, [requirementNode]);
613+
const firstNode = rawNodes?.[0];
614+
const requirementNode = firstNode?.type === "requirement" ? firstNode : null;
620615

621616
const [activeImages, setActiveImages] = useState<ActiveImages | null>(null);
622617

@@ -672,9 +667,13 @@ export function CruiseCanvasComponent(
672667
"_blank"
673668
);
674669
if (win) {
675-
win.__elevo_try_it_out = {
676-
content: userInput,
677-
};
670+
win.__elevo_try_it_out = requirementNode
671+
? {
672+
content: requirementNode.content,
673+
cmd: requirementNode.cmd,
674+
mentionedAiEmployeeId: requirementNode.mentionedAiEmployeeId,
675+
}
676+
: {};
678677
}
679678
},
680679
separateInstructions,
@@ -719,7 +718,7 @@ export function CruiseCanvasComponent(
719718
skipToResults,
720719
watchAgain,
721720
setCentered,
722-
userInput,
721+
requirementNode,
723722
tryItOutUrl,
724723
separateInstructions,
725724
activeFile,

bricks/ai-portal/src/data-providers/set-chat-command.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { createProviderClass } from "@next-core/utils/general";
22
import type { CommandPayload } from "../shared/interfaces.js";
33

44
export interface ChatCommand {
5-
command: string;
5+
command?: string;
66
payload: CommandPayload;
77
}
88

bricks/ai-portal/src/shared/ReadableCommand/ReadableCommand.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export function ReadableCommand({
4646
);
4747
}
4848

49-
function getInitialContent(
49+
export function getInitialContent(
5050
cmd?: CommandPayload,
5151
mentionedAiEmployeeId?: string
5252
): string {

declarations/global.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,8 @@ interface Window {
192192

193193
__elevo_try_it_out?: {
194194
content?: string;
195+
cmd?: any;
196+
mentionedAiEmployeeId?: string;
195197
};
196198

197199
// for File System Access Api

0 commit comments

Comments
 (0)