mirror of
https://github.com/wavetermdev/waveterm.git
synced 2024-12-22 16:48:23 +01:00
save work
This commit is contained in:
parent
5e6cbf30e7
commit
de81464082
@ -38,7 +38,7 @@
|
|||||||
"monaco-editor": "0.48.0",
|
"monaco-editor": "0.48.0",
|
||||||
"mustache": "^4.2.0",
|
"mustache": "^4.2.0",
|
||||||
"node-fetch": "^3.2.10",
|
"node-fetch": "^3.2.10",
|
||||||
"overlayscrollbars": "^2.6.1",
|
"overlayscrollbars": "^2.7.3",
|
||||||
"overlayscrollbars-react": "^0.5.5",
|
"overlayscrollbars-react": "^0.5.5",
|
||||||
"papaparse": "^5.4.1",
|
"papaparse": "^5.4.1",
|
||||||
"react": "^18.1.0",
|
"react": "^18.1.0",
|
||||||
|
@ -8,8 +8,7 @@ import { GlobalModel } from "@/models";
|
|||||||
import { boundMethod } from "autobind-decorator";
|
import { boundMethod } from "autobind-decorator";
|
||||||
import { If, For } from "tsx-control-statements/components";
|
import { If, For } from "tsx-control-statements/components";
|
||||||
import { Markdown } from "@/elements";
|
import { Markdown } from "@/elements";
|
||||||
import * as appconst from "@/app/appconst";
|
import { OverlayScrollbars } from "overlayscrollbars";
|
||||||
import { OverlayScrollbarsComponent, OverlayScrollbarsComponentRef } from "overlayscrollbars-react";
|
|
||||||
|
|
||||||
import "./aichat.less";
|
import "./aichat.less";
|
||||||
|
|
||||||
@ -53,22 +52,141 @@ class AIChatKeybindings extends React.Component<{ AIChatObject: AIChat }, {}> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@mobxReact.observer
|
@mobxReact.observer
|
||||||
class AIChat extends React.Component<{}, {}> {
|
class ChatContent extends React.Component<{}, {}> {
|
||||||
chatListKeyCount: number = 0;
|
chatListKeyCount: number = 0;
|
||||||
chatWindowScrollRef: React.RefObject<any>;
|
containerRef: React.RefObject<HTMLDivElement> = React.createRef();
|
||||||
textAreaRef: React.RefObject<HTMLTextAreaElement>;
|
chatWindowRef: React.RefObject<HTMLDivElement> = React.createRef();
|
||||||
|
osInstance: OverlayScrollbars = null;
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
if (this.containerRef.current) {
|
||||||
|
this.osInstance = OverlayScrollbars(
|
||||||
|
this.containerRef.current,
|
||||||
|
{
|
||||||
|
scrollbars: { autoHide: "leave" },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
initialized: (instance) => {
|
||||||
|
const { viewport } = instance.elements();
|
||||||
|
viewport.scrollTo({
|
||||||
|
behavior: "auto",
|
||||||
|
top: this.chatWindowRef.current.scrollHeight,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate() {
|
||||||
|
if (this.containerRef?.current && this.osInstance) {
|
||||||
|
const { overflowAmount } = this.osInstance.state();
|
||||||
|
const { viewport } = this.osInstance.elements();
|
||||||
|
viewport.scrollTo({
|
||||||
|
behavior: "auto",
|
||||||
|
top: overflowAmount.y,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
if (this.osInstance) {
|
||||||
|
this.osInstance.destroy();
|
||||||
|
this.osInstance = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
submitChatMessage(messageStr: string) {
|
||||||
|
const curLine = GlobalModel.inputModel.getCurLine();
|
||||||
|
const prtn = GlobalModel.submitChatInfoCommand(messageStr, curLine, false);
|
||||||
|
prtn.then((rtn) => {
|
||||||
|
if (!rtn.success) {
|
||||||
|
console.log("submit chat command error: " + rtn.error);
|
||||||
|
}
|
||||||
|
}).catch((_) => {});
|
||||||
|
}
|
||||||
|
|
||||||
|
getLinePos(elem: any): { numLines: number; linePos: number } {
|
||||||
|
const numLines = elem.value.split("\n").length;
|
||||||
|
const linePos = elem.value.substr(0, elem.selectionStart).split("\n").length;
|
||||||
|
return { numLines, linePos };
|
||||||
|
}
|
||||||
|
|
||||||
|
onTextAreaFocused(e: any) {
|
||||||
|
console.log("focused=====");
|
||||||
|
mobx.action(() => {
|
||||||
|
GlobalModel.inputModel.setAuxViewFocus(true);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
|
onTextAreaBlur(e: any) {
|
||||||
|
mobx.action(() => {
|
||||||
|
GlobalModel.inputModel.setAuxViewFocus(false);
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
|
||||||
|
renderError(err: string): any {
|
||||||
|
return <div className="chat-msg-error">{err}</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderChatMessage(chatItem: OpenAICmdInfoChatMessageType): any {
|
||||||
|
const curKey = "chatmsg-" + this.chatListKeyCount;
|
||||||
|
this.chatListKeyCount++;
|
||||||
|
const senderClassName = chatItem.isassistantresponse ? "chat-msg-assistant" : "chat-msg-user";
|
||||||
|
const msgClassName = "chat-msg " + senderClassName;
|
||||||
|
let innerHTML: React.JSX.Element = (
|
||||||
|
<>
|
||||||
|
<div className="chat-msg-header">
|
||||||
|
<i className="fa-sharp fa-solid fa-user"></i>
|
||||||
|
</div>
|
||||||
|
<div className="msg-text">{chatItem.userquery}</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
if (chatItem.isassistantresponse) {
|
||||||
|
if (chatItem.assistantresponse.error != null && chatItem.assistantresponse.error != "") {
|
||||||
|
innerHTML = this.renderError(chatItem.assistantresponse.error);
|
||||||
|
} else {
|
||||||
|
innerHTML = (
|
||||||
|
<>
|
||||||
|
<div className="chat-msg-header">
|
||||||
|
<i className="fa-sharp fa-solid fa-sparkles"></i>
|
||||||
|
</div>
|
||||||
|
<Markdown text={chatItem.assistantresponse.message} codeSelect />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={msgClassName} key={curKey}>
|
||||||
|
{innerHTML}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const chatMessageItems = GlobalModel.inputModel.AICmdInfoChatItems.slice();
|
||||||
|
const chitem: OpenAICmdInfoChatMessageType = null;
|
||||||
|
return (
|
||||||
|
<div ref={this.containerRef} className="content">
|
||||||
|
<div ref={this.chatWindowRef} className="chat-window">
|
||||||
|
<div className="filler"></div>
|
||||||
|
<For each="chitem" index="idx" of={chatMessageItems}>
|
||||||
|
{this.renderChatMessage(chitem)}
|
||||||
|
</For>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mobxReact.observer
|
||||||
|
class AIChat extends React.Component<{}, {}> {
|
||||||
|
textAreaRef: React.RefObject<HTMLTextAreaElement> = React.createRef();
|
||||||
termFontSize: number = 14;
|
termFontSize: number = 14;
|
||||||
|
|
||||||
constructor(props: any) {
|
|
||||||
super(props);
|
|
||||||
this.chatWindowScrollRef = React.createRef();
|
|
||||||
this.textAreaRef = React.createRef();
|
|
||||||
}
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
const inputModel = GlobalModel.inputModel;
|
const inputModel = GlobalModel.inputModel;
|
||||||
if (this.chatWindowScrollRef?.current != null) {
|
|
||||||
this.chatWindowScrollRef.current.scrollTop = this.chatWindowScrollRef.current.scrollHeight;
|
|
||||||
}
|
|
||||||
if (this.textAreaRef.current != null) {
|
if (this.textAreaRef.current != null) {
|
||||||
this.textAreaRef.current.focus();
|
this.textAreaRef.current.focus();
|
||||||
// inputModel.setCmdInfoChatRefs(this.textAreaRef, this.chatWindowScrollRef);
|
// inputModel.setCmdInfoChatRefs(this.textAreaRef, this.chatWindowScrollRef);
|
||||||
@ -77,13 +195,6 @@ class AIChat extends React.Component<{}, {}> {
|
|||||||
this.onTextAreaChange(null);
|
this.onTextAreaChange(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate() {
|
|
||||||
if (this.chatWindowScrollRef?.current != null) {
|
|
||||||
console.log("scrolling to bottom", this.chatWindowScrollRef.current.osInstance().scrollHeight);
|
|
||||||
this.chatWindowScrollRef.current.scrollTop = this.chatWindowScrollRef.current.scrollHeight;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
requestChatUpdate() {
|
requestChatUpdate() {
|
||||||
this.submitChatMessage("");
|
this.submitChatMessage("");
|
||||||
}
|
}
|
||||||
@ -195,62 +306,18 @@ class AIChat extends React.Component<{}, {}> {
|
|||||||
return <div className="chat-msg-error">{err}</div>;
|
return <div className="chat-msg-error">{err}</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
renderChatMessage(chatItem: OpenAICmdInfoChatMessageType): any {
|
|
||||||
const curKey = "chatmsg-" + this.chatListKeyCount;
|
|
||||||
this.chatListKeyCount++;
|
|
||||||
const senderClassName = chatItem.isassistantresponse ? "chat-msg-assistant" : "chat-msg-user";
|
|
||||||
const msgClassName = "chat-msg " + senderClassName;
|
|
||||||
let innerHTML: React.JSX.Element = (
|
|
||||||
<>
|
|
||||||
<div className="chat-msg-header">
|
|
||||||
<i className="fa-sharp fa-solid fa-user"></i>
|
|
||||||
</div>
|
|
||||||
<div className="msg-text">{chatItem.userquery}</div>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
if (chatItem.isassistantresponse) {
|
|
||||||
if (chatItem.assistantresponse.error != null && chatItem.assistantresponse.error != "") {
|
|
||||||
innerHTML = this.renderError(chatItem.assistantresponse.error);
|
|
||||||
} else {
|
|
||||||
innerHTML = (
|
|
||||||
<>
|
|
||||||
<div className="chat-msg-header">
|
|
||||||
<i className="fa-sharp fa-solid fa-sparkles"></i>
|
|
||||||
</div>
|
|
||||||
<Markdown text={chatItem.assistantresponse.message} codeSelect />
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className={msgClassName} key={curKey}>
|
|
||||||
{innerHTML}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const chatMessageItems = GlobalModel.inputModel.AICmdInfoChatItems.slice();
|
const chatMessageItems = GlobalModel.inputModel.AICmdInfoChatItems.slice();
|
||||||
const chitem: OpenAICmdInfoChatMessageType = null;
|
console.log("chatMessageItems", chatMessageItems);
|
||||||
return (
|
return (
|
||||||
<div className="sidebar-aichat">
|
<div className="sidebar-aichat">
|
||||||
<AIChatKeybindings AIChatObject={this}></AIChatKeybindings>
|
<AIChatKeybindings AIChatObject={this}></AIChatKeybindings>
|
||||||
<div className="titlebar">
|
<div className="titlebar">
|
||||||
<div className="title-string">Wave AI</div>
|
<div className="title-string">Wave AI</div>
|
||||||
</div>
|
</div>
|
||||||
<OverlayScrollbarsComponent
|
<If condition={chatMessageItems.length > 0}>
|
||||||
ref={this.chatWindowScrollRef}
|
<ChatContent />
|
||||||
className="content"
|
</If>
|
||||||
options={{ scrollbars: { autoHide: "leave" } }}
|
|
||||||
>
|
|
||||||
<div className="chat-window">
|
|
||||||
<div className="filler"></div>
|
|
||||||
<For each="chitem" index="idx" of={chatMessageItems}>
|
|
||||||
{this.renderChatMessage(chitem)}
|
|
||||||
</For>
|
|
||||||
</div>
|
|
||||||
</OverlayScrollbarsComponent>
|
|
||||||
<div className="chat-input">
|
<div className="chat-input">
|
||||||
<textarea
|
<textarea
|
||||||
key="main"
|
key="main"
|
||||||
|
@ -6938,7 +6938,7 @@ overlayscrollbars-react@^0.5.5:
|
|||||||
resolved "https://registry.yarnpkg.com/overlayscrollbars-react/-/overlayscrollbars-react-0.5.6.tgz#e9779f9fc2c1a3288570a45c83f8e42518bfb8c1"
|
resolved "https://registry.yarnpkg.com/overlayscrollbars-react/-/overlayscrollbars-react-0.5.6.tgz#e9779f9fc2c1a3288570a45c83f8e42518bfb8c1"
|
||||||
integrity sha512-E5To04bL5brn9GVCZ36SnfGanxa2I2MDkWoa4Cjo5wol7l+diAgi4DBc983V7l2nOk/OLJ6Feg4kySspQEGDBw==
|
integrity sha512-E5To04bL5brn9GVCZ36SnfGanxa2I2MDkWoa4Cjo5wol7l+diAgi4DBc983V7l2nOk/OLJ6Feg4kySspQEGDBw==
|
||||||
|
|
||||||
overlayscrollbars@^2.6.1:
|
overlayscrollbars@^2.7.3:
|
||||||
version "2.7.3"
|
version "2.7.3"
|
||||||
resolved "https://registry.yarnpkg.com/overlayscrollbars/-/overlayscrollbars-2.7.3.tgz#68c18096c563391e37a2c7ca7463fbd03a945271"
|
resolved "https://registry.yarnpkg.com/overlayscrollbars/-/overlayscrollbars-2.7.3.tgz#68c18096c563391e37a2c7ca7463fbd03a945271"
|
||||||
integrity sha512-HmNo8RPtuGUjBhUbVpZBHH7SHci5iSAdg5zSekCZVsjzaM6z8MIr3F9RXrzf4y7m+fOY0nx0+y0emr1fqQmfoA==
|
integrity sha512-HmNo8RPtuGUjBhUbVpZBHH7SHci5iSAdg5zSekCZVsjzaM6z8MIr3F9RXrzf4y7m+fOY0nx0+y0emr1fqQmfoA==
|
||||||
|
Loading…
Reference in New Issue
Block a user