|
@@ -2,7 +2,7 @@ import { useEffect, useMemo, useRef, useState } from 'react';
|
|
|
import { CallbackGeneratedChunk, useAppContext } from '../utils/app.context';
|
|
import { CallbackGeneratedChunk, useAppContext } from '../utils/app.context';
|
|
|
import ChatMessage from './ChatMessage';
|
|
import ChatMessage from './ChatMessage';
|
|
|
import { CanvasType, Message, PendingMessage } from '../utils/types';
|
|
import { CanvasType, Message, PendingMessage } from '../utils/types';
|
|
|
-import { classNames, throttle } from '../utils/misc';
|
|
|
|
|
|
|
+import { classNames, cleanCurrentUrl, throttle } from '../utils/misc';
|
|
|
import CanvasPyInterpreter from './CanvasPyInterpreter';
|
|
import CanvasPyInterpreter from './CanvasPyInterpreter';
|
|
|
import StorageUtils from '../utils/storage';
|
|
import StorageUtils from '../utils/storage';
|
|
|
import { useVSCodeContext } from '../utils/llama-vscode';
|
|
import { useVSCodeContext } from '../utils/llama-vscode';
|
|
@@ -18,6 +18,24 @@ export interface MessageDisplay {
|
|
|
isPending?: boolean;
|
|
isPending?: boolean;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * If the current URL contains "?m=...", prefill the message input with the value.
|
|
|
|
|
+ * If the current URL contains "?q=...", prefill and SEND the message.
|
|
|
|
|
+ */
|
|
|
|
|
+const prefilledMsg = {
|
|
|
|
|
+ content() {
|
|
|
|
|
+ const url = new URL(window.location.href);
|
|
|
|
|
+ return url.searchParams.get('m') ?? url.searchParams.get('q') ?? '';
|
|
|
|
|
+ },
|
|
|
|
|
+ shouldSend() {
|
|
|
|
|
+ const url = new URL(window.location.href);
|
|
|
|
|
+ return url.searchParams.has('q');
|
|
|
|
|
+ },
|
|
|
|
|
+ clear() {
|
|
|
|
|
+ cleanCurrentUrl(['m', 'q']);
|
|
|
|
|
+ },
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
function getListMessageDisplay(
|
|
function getListMessageDisplay(
|
|
|
msgs: Readonly<Message[]>,
|
|
msgs: Readonly<Message[]>,
|
|
|
leafNodeId: Message['id']
|
|
leafNodeId: Message['id']
|
|
@@ -81,7 +99,7 @@ export default function ChatScreen() {
|
|
|
canvasData,
|
|
canvasData,
|
|
|
replaceMessageAndGenerate,
|
|
replaceMessageAndGenerate,
|
|
|
} = useAppContext();
|
|
} = useAppContext();
|
|
|
- const [inputMsg, setInputMsg] = useState('');
|
|
|
|
|
|
|
+ const [inputMsg, setInputMsg] = useState(prefilledMsg.content());
|
|
|
const inputRef = useRef<HTMLTextAreaElement>(null);
|
|
const inputRef = useRef<HTMLTextAreaElement>(null);
|
|
|
|
|
|
|
|
const { extraContext, clearExtraContext } = useVSCodeContext(
|
|
const { extraContext, clearExtraContext } = useVSCodeContext(
|
|
@@ -172,6 +190,22 @@ export default function ChatScreen() {
|
|
|
|
|
|
|
|
const hasCanvas = !!canvasData;
|
|
const hasCanvas = !!canvasData;
|
|
|
|
|
|
|
|
|
|
+ useEffect(() => {
|
|
|
|
|
+ if (prefilledMsg.shouldSend()) {
|
|
|
|
|
+ // send the prefilled message if needed
|
|
|
|
|
+ sendNewMessage();
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // otherwise, focus on the input and move the cursor to the end
|
|
|
|
|
+ if (inputRef.current) {
|
|
|
|
|
+ inputRef.current.focus();
|
|
|
|
|
+ inputRef.current.selectionStart = inputRef.current.value.length;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ prefilledMsg.clear();
|
|
|
|
|
+ // no need to keep track of sendNewMessage
|
|
|
|
|
+ // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
|
|
+ }, [inputRef]);
|
|
|
|
|
+
|
|
|
// due to some timing issues of StorageUtils.appendMsg(), we need to make sure the pendingMsg is not duplicated upon rendering (i.e. appears once in the saved conversation and once in the pendingMsg)
|
|
// due to some timing issues of StorageUtils.appendMsg(), we need to make sure the pendingMsg is not duplicated upon rendering (i.e. appears once in the saved conversation and once in the pendingMsg)
|
|
|
const pendingMsgDisplay: MessageDisplay[] =
|
|
const pendingMsgDisplay: MessageDisplay[] =
|
|
|
pendingMsg && messages.at(-1)?.msg.id !== pendingMsg.id
|
|
pendingMsg && messages.at(-1)?.msg.id !== pendingMsg.id
|