mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-01-02 18:39:05 +01:00
aichat improvements (#667)
This commit is contained in:
parent
1234919229
commit
d7173c970c
@ -313,6 +313,10 @@
|
|||||||
"command": "aichat:clearHistory",
|
"command": "aichat:clearHistory",
|
||||||
"keys": ["Ctrl:l"]
|
"keys": ["Ctrl:l"]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"command": "aichat:setCmdInputValue",
|
||||||
|
"keys": ["Ctrl:Shift:e"]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"command": "terminal:copy",
|
"command": "terminal:copy",
|
||||||
"keys": ["Ctrl:Shift:c"]
|
"keys": ["Ctrl:Shift:c"]
|
||||||
|
@ -31,12 +31,20 @@ class App extends React.Component<{}, {}> {
|
|||||||
dcWait: OV<boolean> = mobx.observable.box(false, { name: "dcWait" });
|
dcWait: OV<boolean> = mobx.observable.box(false, { name: "dcWait" });
|
||||||
mainContentRef: React.RefObject<HTMLDivElement> = React.createRef();
|
mainContentRef: React.RefObject<HTMLDivElement> = React.createRef();
|
||||||
termThemesLoaded: OV<boolean> = mobx.observable.box(false, { name: "termThemesLoaded" });
|
termThemesLoaded: OV<boolean> = mobx.observable.box(false, { name: "termThemesLoaded" });
|
||||||
|
chatFocusTimeoutId: NodeJS.Timeout = null;
|
||||||
|
|
||||||
constructor(props: {}) {
|
constructor(props: {}) {
|
||||||
super(props);
|
super(props);
|
||||||
if (GlobalModel.isDev) document.body.classList.add("is-dev");
|
if (GlobalModel.isDev) document.body.classList.add("is-dev");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
if (this.chatFocusTimeoutId) {
|
||||||
|
clearTimeout(this.chatFocusTimeoutId);
|
||||||
|
this.chatFocusTimeoutId = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@boundMethod
|
@boundMethod
|
||||||
handleContextMenu(e: any) {
|
handleContextMenu(e: any) {
|
||||||
let isInNonTermInput = false;
|
let isInNonTermInput = false;
|
||||||
@ -68,16 +76,15 @@ class App extends React.Component<{}, {}> {
|
|||||||
|
|
||||||
@boundMethod
|
@boundMethod
|
||||||
openMainSidebar() {
|
openMainSidebar() {
|
||||||
const mainSidebarModel = GlobalModel.mainSidebarModel;
|
GlobalModel.mainSidebarModel.setCollapsed(false);
|
||||||
const width = mainSidebarModel.getWidth(true);
|
|
||||||
mainSidebarModel.saveState(width, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@boundMethod
|
@boundMethod
|
||||||
openRightSidebar() {
|
openRightSidebar() {
|
||||||
const rightSidebarModel = GlobalModel.rightSidebarModel;
|
GlobalModel.rightSidebarModel.setCollapsed(false);
|
||||||
const width = rightSidebarModel.getWidth(true);
|
this.chatFocusTimeoutId = setTimeout(() => {
|
||||||
rightSidebarModel.saveState(width, false);
|
GlobalModel.inputModel.setChatSidebarFocus();
|
||||||
|
}, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
@boundMethod
|
@boundMethod
|
||||||
|
@ -128,7 +128,8 @@ class LineActions extends React.Component<{ screen: LineContainerType; line: Lin
|
|||||||
screen.getUsedRows(lineutil.getRendererContext(line), line, cmd, 300) * 2,
|
screen.getUsedRows(lineutil.getRendererContext(line), line, cmd, 300) * 2,
|
||||||
cmdShouldMarkError(cmd)
|
cmdShouldMarkError(cmd)
|
||||||
);
|
);
|
||||||
GlobalModel.sidebarchatModel.setFocus("input", true);
|
GlobalModel.inputModel.setChatSidebarFocus();
|
||||||
|
GlobalModel.sidebarchatModel.resetSelectedCodeBlockIndex();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,11 @@
|
|||||||
.filler {
|
.filler {
|
||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
> * {
|
||||||
|
cursor: default;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-msg {
|
.chat-msg {
|
||||||
@ -78,6 +83,7 @@
|
|||||||
font-family: var(--termfontfamily);
|
font-family: var(--termfontfamily);
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
line-height: var(--termlineheight);
|
line-height: var(--termlineheight);
|
||||||
|
height: 21px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ import "./aichat.less";
|
|||||||
|
|
||||||
const outline = "2px solid var(--markdown-outline-color)";
|
const outline = "2px solid var(--markdown-outline-color)";
|
||||||
|
|
||||||
class ChatKeyBindings extends React.Component<{ component: ChatSidebar; bindArrowUpDownKeys: boolean }, {}> {
|
class ChatKeyBindings extends React.Component<{ component: ChatSidebar }, {}> {
|
||||||
componentDidMount(): void {
|
componentDidMount(): void {
|
||||||
const { component } = this.props;
|
const { component } = this.props;
|
||||||
const keybindManager = GlobalModel.keybindManager;
|
const keybindManager = GlobalModel.keybindManager;
|
||||||
@ -34,26 +34,19 @@ class ChatKeyBindings extends React.Component<{ component: ChatSidebar; bindArro
|
|||||||
inputModel.clearAIAssistantChat();
|
inputModel.clearAIAssistantChat();
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
keybindManager.registerKeybinding("pane", "aichat", "generic:selectAbove", (waveEvent) => {
|
||||||
|
return component.onArrowUpPressed();
|
||||||
componentDidUpdate(): void {
|
});
|
||||||
const { component, bindArrowUpDownKeys } = this.props;
|
keybindManager.registerKeybinding("pane", "aichat", "generic:selectBelow", (waveEvent) => {
|
||||||
const keybindManager = GlobalModel.keybindManager;
|
return component.onArrowDownPressed();
|
||||||
if (bindArrowUpDownKeys) {
|
});
|
||||||
keybindManager.registerKeybinding("pane", "aichat:arrowupdown", "generic:selectAbove", (waveEvent) => {
|
keybindManager.registerKeybinding("pane", "aichat", "aichat:setCmdInputValue", (waveEvent) => {
|
||||||
return component.onArrowUpPressed();
|
return component.onSetCmdInputValue();
|
||||||
});
|
});
|
||||||
keybindManager.registerKeybinding("pane", "aichat:arrowupdown", "generic:selectBelow", (waveEvent) => {
|
|
||||||
return component.onArrowDownPressed();
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
GlobalModel.keybindManager.unregisterDomain("aichat:arrowupdown");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount(): void {
|
componentWillUnmount(): void {
|
||||||
GlobalModel.keybindManager.unregisterDomain("aichat");
|
GlobalModel.keybindManager.unregisterDomain("aichat");
|
||||||
GlobalModel.keybindManager.unregisterDomain("aichat:arrowupdown");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
@ -62,20 +55,16 @@ class ChatKeyBindings extends React.Component<{ component: ChatSidebar; bindArro
|
|||||||
}
|
}
|
||||||
|
|
||||||
@mobxReact.observer
|
@mobxReact.observer
|
||||||
class ChatItem extends React.Component<{ chatItem: OpenAICmdInfoChatMessageType; itemCount: number }, {}> {
|
class ChatItem extends React.Component<
|
||||||
handleExecuteCommand(cmd: string) {
|
{ chatItem: OpenAICmdInfoChatMessageType; itemCount: number; onSetCmdInputValue: (cmd: string) => void },
|
||||||
GlobalModel.sidebarchatModel.setCmdToExec(cmd);
|
{}
|
||||||
GlobalModel.sidebarchatModel.resetFocus();
|
> {
|
||||||
GlobalModel.inputModel.curLine = cmd;
|
|
||||||
GlobalModel.inputModel.giveFocus();
|
|
||||||
}
|
|
||||||
|
|
||||||
renderError(err: string): any {
|
renderError(err: string): any {
|
||||||
return <div className="chat-msg-error">{err}</div>;
|
return <div className="chat-msg-error">{err}</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { chatItem, itemCount } = this.props;
|
const { chatItem, itemCount, onSetCmdInputValue } = this.props;
|
||||||
const { isassistantresponse, assistantresponse } = chatItem;
|
const { isassistantresponse, assistantresponse } = chatItem;
|
||||||
const curKey = "chatmsg-" + itemCount;
|
const curKey = "chatmsg-" + itemCount;
|
||||||
const senderClassName = isassistantresponse ? "chat-msg-assistant" : "chat-msg-user";
|
const senderClassName = isassistantresponse ? "chat-msg-assistant" : "chat-msg-user";
|
||||||
@ -108,7 +97,7 @@ class ChatItem extends React.Component<{ chatItem: OpenAICmdInfoChatMessageType;
|
|||||||
<div className="chat-msg-header">
|
<div className="chat-msg-header">
|
||||||
<i className="fa-sharp fa-solid fa-sparkles"></i>
|
<i className="fa-sharp fa-solid fa-sparkles"></i>
|
||||||
</div>
|
</div>
|
||||||
<Markdown2 text={assistantresponse.message} onClickExecute={this.handleExecuteCommand} />
|
<Markdown2 text={assistantresponse.message} onClickExecute={onSetCmdInputValue} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -130,7 +119,14 @@ class ChatItem extends React.Component<{ chatItem: OpenAICmdInfoChatMessageType;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@mobxReact.observer
|
@mobxReact.observer
|
||||||
class ChatWindow extends React.Component<{ chatWindowRef; onRendered }, {}> {
|
class ChatWindow extends React.Component<
|
||||||
|
{
|
||||||
|
chatWindowRef: React.RefObject<HTMLDivElement>;
|
||||||
|
onRendered: (osInstance: OverlayScrollbars) => void;
|
||||||
|
onSetCmdInputValue: (cmd: string) => void;
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
> {
|
||||||
itemCount: number = 0;
|
itemCount: number = 0;
|
||||||
containerRef: React.RefObject<OverlayScrollbarsComponentRef> = React.createRef();
|
containerRef: React.RefObject<OverlayScrollbarsComponentRef> = React.createRef();
|
||||||
osInstance: OverlayScrollbars = null;
|
osInstance: OverlayScrollbars = null;
|
||||||
@ -164,6 +160,7 @@ class ChatWindow extends React.Component<{ chatWindowRef; onRendered }, {}> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
const { onSetCmdInputValue } = this.props;
|
||||||
const chatMessageItems = GlobalModel.inputModel.AICmdInfoChatItems.slice();
|
const chatMessageItems = GlobalModel.inputModel.AICmdInfoChatItems.slice();
|
||||||
const chitem: OpenAICmdInfoChatMessageType = null;
|
const chitem: OpenAICmdInfoChatMessageType = null;
|
||||||
let idx;
|
let idx;
|
||||||
@ -177,7 +174,12 @@ class ChatWindow extends React.Component<{ chatWindowRef; onRendered }, {}> {
|
|||||||
<div ref={this.props.chatWindowRef} className="chat-window">
|
<div ref={this.props.chatWindowRef} className="chat-window">
|
||||||
<div className="filler"></div>
|
<div className="filler"></div>
|
||||||
<For each="chitem" index="idx" of={chatMessageItems}>
|
<For each="chitem" index="idx" of={chatMessageItems}>
|
||||||
<ChatItem key={idx} chatItem={chitem} itemCount={idx + 1} />
|
<ChatItem
|
||||||
|
key={idx}
|
||||||
|
chatItem={chitem}
|
||||||
|
itemCount={idx + 1}
|
||||||
|
onSetCmdInputValue={onSetCmdInputValue}
|
||||||
|
/>
|
||||||
</For>
|
</For>
|
||||||
</div>
|
</div>
|
||||||
</OverlayScrollbarsComponent>
|
</OverlayScrollbarsComponent>
|
||||||
@ -190,11 +192,11 @@ class ChatSidebar extends React.Component<{}, {}> {
|
|||||||
sidebarRef: React.RefObject<HTMLDivElement> = React.createRef<HTMLDivElement>();
|
sidebarRef: React.RefObject<HTMLDivElement> = React.createRef<HTMLDivElement>();
|
||||||
textAreaRef: React.RefObject<HTMLTextAreaElement> = React.createRef<HTMLTextAreaElement>();
|
textAreaRef: React.RefObject<HTMLTextAreaElement> = React.createRef<HTMLTextAreaElement>();
|
||||||
chatWindowRef: React.RefObject<HTMLDivElement> = React.createRef<HTMLDivElement>();
|
chatWindowRef: React.RefObject<HTMLDivElement> = React.createRef<HTMLDivElement>();
|
||||||
bindArrowUpDownKeys: OV<boolean> = mobx.observable.box(false, { name: "bindArrowUpDownKeys" });
|
|
||||||
value: OV<string> = mobx.observable.box("", { deep: false, name: "value" });
|
value: OV<string> = mobx.observable.box("", { deep: false, name: "value" });
|
||||||
osInstance: OverlayScrollbars;
|
osInstance: OverlayScrollbars;
|
||||||
termFontSize: number = 14;
|
termFontSize: number = 14;
|
||||||
blockIndex: number;
|
blockIndex: number;
|
||||||
|
disposeReaction: () => void;
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
@ -202,27 +204,32 @@ class ChatSidebar extends React.Component<{}, {}> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate() {
|
componentDidUpdate() {
|
||||||
if (GlobalModel.sidebarchatModel.focused == "input") {
|
|
||||||
this.textAreaRef.current.focus();
|
|
||||||
}
|
|
||||||
if (GlobalModel.sidebarchatModel.hasCmdAndOutput()) {
|
|
||||||
const newCmdAndOutput = GlobalModel.sidebarchatModel.getCmdAndOutput();
|
|
||||||
const newValue = this.formChatMessage(newCmdAndOutput);
|
|
||||||
if (newValue !== this.value.get()) {
|
|
||||||
this.value.set(newValue);
|
|
||||||
GlobalModel.sidebarchatModel.resetCmdAndOutput();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.adjustTextAreaHeight();
|
this.adjustTextAreaHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
GlobalModel.sidebarchatModel.setFocus("input", true);
|
this.disposeReaction = mobx.reaction(
|
||||||
this.textAreaRef.current.focus();
|
() => [
|
||||||
|
GlobalModel.sidebarchatModel.hasCmdAndOutput(),
|
||||||
|
GlobalModel.sidebarchatModel.getSelectedCodeBlockIndex(),
|
||||||
|
],
|
||||||
|
([hasCmdAndOutput, selectedCodeBlockIndex]) => {
|
||||||
|
if (hasCmdAndOutput) {
|
||||||
|
const newCmdAndOutput = GlobalModel.sidebarchatModel.getCmdAndOutput();
|
||||||
|
const newValue = this.formChatMessage(newCmdAndOutput);
|
||||||
|
this.value.set(newValue);
|
||||||
|
GlobalModel.sidebarchatModel.resetCmdAndOutput();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedCodeBlockIndex == null) {
|
||||||
|
this.updatePreTagOutline();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
if (this.sidebarRef.current) {
|
if (this.sidebarRef.current) {
|
||||||
this.sidebarRef.current.addEventListener("click", this.handleSidebarClick);
|
this.sidebarRef.current.addEventListener("click", this.handleSidebarClick);
|
||||||
}
|
}
|
||||||
document.addEventListener("mousedown", this.handleClickOutside);
|
document.addEventListener("click", this.handleClickOutside);
|
||||||
this.requestChatUpdate();
|
this.requestChatUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -230,13 +237,19 @@ class ChatSidebar extends React.Component<{}, {}> {
|
|||||||
if (this.sidebarRef.current) {
|
if (this.sidebarRef.current) {
|
||||||
this.sidebarRef.current.removeEventListener("click", this.handleSidebarClick);
|
this.sidebarRef.current.removeEventListener("click", this.handleSidebarClick);
|
||||||
}
|
}
|
||||||
document.removeEventListener("mousedown", this.handleClickOutside);
|
document.removeEventListener("click", this.handleClickOutside);
|
||||||
|
GlobalModel.sidebarchatModel.resetFocus();
|
||||||
|
if (this.disposeReaction) {
|
||||||
|
this.disposeReaction();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@mobx.action.bound
|
@mobx.action.bound
|
||||||
handleClickOutside(event) {
|
handleClickOutside(e: MouseEvent) {
|
||||||
if (this.sidebarRef.current && !this.sidebarRef.current.contains(event.target)) {
|
const sidebar = this.sidebarRef.current;
|
||||||
this.onClickOutsideSidebar();
|
if (sidebar && !sidebar.contains(e.target as Node)) {
|
||||||
|
GlobalModel.sidebarchatModel.resetFocus();
|
||||||
|
GlobalModel.inputModel.giveFocus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -281,20 +294,20 @@ class ChatSidebar extends React.Component<{}, {}> {
|
|||||||
}).catch((_) => {});
|
}).catch((_) => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
onClickOutsideSidebar() {
|
@mobx.action.bound
|
||||||
GlobalModel.sidebarchatModel.resetFocus();
|
onTextAreaFocus() {
|
||||||
|
GlobalModel.inputModel.setChatSidebarFocus();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@mobx.action.bound
|
@mobx.action.bound
|
||||||
onTextAreaFocused(e) {
|
onTextAreaMouseDown(e) {
|
||||||
GlobalModel.sidebarchatModel.setFocus("input", true);
|
|
||||||
this.bindArrowUpDownKeys.set(false);
|
|
||||||
const pres = this.chatWindowRef.current?.querySelectorAll("pre");
|
|
||||||
this.blockIndex = pres.length - 1;
|
|
||||||
this.onTextAreaChange(e);
|
|
||||||
this.updatePreTagOutline();
|
this.updatePreTagOutline();
|
||||||
|
// Reset blockIndex to null
|
||||||
|
GlobalModel.sidebarchatModel.resetSelectedCodeBlockIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@mobx.action.bound
|
||||||
onEnterKeyPressed() {
|
onEnterKeyPressed() {
|
||||||
const messageStr = this.value.get();
|
const messageStr = this.value.get();
|
||||||
this.submitChatMessage(messageStr);
|
this.submitChatMessage(messageStr);
|
||||||
@ -302,6 +315,7 @@ class ChatSidebar extends React.Component<{}, {}> {
|
|||||||
GlobalModel.sidebarchatModel.resetCmdAndOutput();
|
GlobalModel.sidebarchatModel.resetCmdAndOutput();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@mobx.action.bound
|
||||||
onExpandInputPressed() {
|
onExpandInputPressed() {
|
||||||
const currentRef = this.textAreaRef.current;
|
const currentRef = this.textAreaRef.current;
|
||||||
if (currentRef == null) {
|
if (currentRef == null) {
|
||||||
@ -317,7 +331,7 @@ class ChatSidebar extends React.Component<{}, {}> {
|
|||||||
}
|
}
|
||||||
pres.forEach((preElement, idx) => {
|
pres.forEach((preElement, idx) => {
|
||||||
if (preElement === clickedPre) {
|
if (preElement === clickedPre) {
|
||||||
this.blockIndex = idx;
|
GlobalModel.sidebarchatModel.setSelectedCodeBlockIndex(idx);
|
||||||
preElement.style.outline = outline;
|
preElement.style.outline = outline;
|
||||||
} else {
|
} else {
|
||||||
preElement.style.outline = "none";
|
preElement.style.outline = "none";
|
||||||
@ -327,28 +341,28 @@ class ChatSidebar extends React.Component<{}, {}> {
|
|||||||
|
|
||||||
@mobx.action.bound
|
@mobx.action.bound
|
||||||
handleSidebarClick(event) {
|
handleSidebarClick(event) {
|
||||||
let detection = 0;
|
|
||||||
const target = event.target as HTMLElement;
|
const target = event.target as HTMLElement;
|
||||||
|
if (
|
||||||
if (target.closest(".copy-button") || target.closest(".fa-square-terminal")) {
|
target.closest(".copy-button") ||
|
||||||
|
target.closest(".fa-square-terminal") ||
|
||||||
|
target.closest(".chat-textarea")
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const chatWindow = target.closest(".chat-window");
|
|
||||||
if (chatWindow) {
|
|
||||||
detection++;
|
|
||||||
}
|
|
||||||
|
|
||||||
const pre = target.closest("pre");
|
const pre = target.closest("pre");
|
||||||
if (pre) {
|
if (pre) {
|
||||||
detection++;
|
const pres = this.chatWindowRef.current?.querySelectorAll("pre");
|
||||||
this.updatePreTagOutline(pre);
|
if (pres) {
|
||||||
}
|
pres.forEach((preElement, idx) => {
|
||||||
|
if (preElement === pre) {
|
||||||
if (detection > 0) {
|
GlobalModel.sidebarchatModel.setSelectedCodeBlockIndex(idx);
|
||||||
this.bindArrowUpDownKeys.set(true);
|
this.updatePreTagOutline(pre);
|
||||||
GlobalModel.sidebarchatModel.setFocus("block", true);
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
GlobalModel.inputModel.setChatSidebarFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
updateScrollTop() {
|
updateScrollTop() {
|
||||||
@ -356,7 +370,7 @@ class ChatSidebar extends React.Component<{}, {}> {
|
|||||||
if (pres == null) {
|
if (pres == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const block = pres[this.blockIndex];
|
const block = pres[GlobalModel.sidebarchatModel.getSelectedCodeBlockIndex()];
|
||||||
if (block == null) {
|
if (block == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -387,42 +401,100 @@ class ChatSidebar extends React.Component<{}, {}> {
|
|||||||
this.osInstance = osInstance;
|
this.osInstance = osInstance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@mobx.action.bound
|
||||||
onArrowUpPressed() {
|
onArrowUpPressed() {
|
||||||
const pres = this.chatWindowRef.current?.querySelectorAll("pre");
|
if (this.onTextAreaKeyDown("ArrowUp")) {
|
||||||
if (pres == null) {
|
const pres = this.chatWindowRef.current?.querySelectorAll("pre");
|
||||||
return;
|
let blockIndex = GlobalModel.sidebarchatModel.getSelectedCodeBlockIndex();
|
||||||
|
if (pres == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (blockIndex == null) {
|
||||||
|
GlobalModel.sidebarchatModel.setSelectedCodeBlockIndex(pres.length - 1);
|
||||||
|
} else if (blockIndex > 0) {
|
||||||
|
blockIndex--;
|
||||||
|
GlobalModel.sidebarchatModel.setSelectedCodeBlockIndex(blockIndex);
|
||||||
|
}
|
||||||
|
blockIndex = GlobalModel.sidebarchatModel.getSelectedCodeBlockIndex();
|
||||||
|
this.updatePreTagOutline(pres[blockIndex]);
|
||||||
|
this.updateScrollTop();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
if (this.blockIndex == null) {
|
return false;
|
||||||
this.blockIndex = pres.length - 1;
|
|
||||||
} else if (this.blockIndex > 0) {
|
|
||||||
this.blockIndex--;
|
|
||||||
}
|
|
||||||
this.updatePreTagOutline(pres[this.blockIndex]);
|
|
||||||
this.updateScrollTop();
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@mobx.action.bound
|
@mobx.action.bound
|
||||||
onArrowDownPressed() {
|
onArrowDownPressed() {
|
||||||
const pres = this.chatWindowRef.current?.querySelectorAll("pre");
|
if (this.onTextAreaKeyDown("ArrowDown")) {
|
||||||
if (pres == null) {
|
const pres = this.chatWindowRef.current?.querySelectorAll("pre");
|
||||||
return;
|
let blockIndex = GlobalModel.sidebarchatModel.getSelectedCodeBlockIndex();
|
||||||
|
if (pres == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (blockIndex == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (blockIndex < pres.length - 1 && blockIndex >= 0) {
|
||||||
|
GlobalModel.sidebarchatModel.setSelectedCodeBlockIndex(blockIndex++);
|
||||||
|
this.updatePreTagOutline(pres[blockIndex]);
|
||||||
|
} else {
|
||||||
|
GlobalModel.sidebarchatModel.setFocus(true);
|
||||||
|
this.textAreaRef.current.focus();
|
||||||
|
this.updatePreTagOutline();
|
||||||
|
GlobalModel.sidebarchatModel.setSelectedCodeBlockIndex(null);
|
||||||
|
}
|
||||||
|
this.updateScrollTop();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
if (this.blockIndex == null) {
|
return false;
|
||||||
return;
|
}
|
||||||
|
|
||||||
|
@mobx.action.bound
|
||||||
|
onTextAreaKeyDown(key: "ArrowUp" | "ArrowDown") {
|
||||||
|
const textarea = this.textAreaRef.current;
|
||||||
|
const cursorPosition = textarea.selectionStart;
|
||||||
|
const textBeforeCursor = textarea.value.slice(0, cursorPosition);
|
||||||
|
const blockIndex = GlobalModel.sidebarchatModel.getSelectedCodeBlockIndex();
|
||||||
|
|
||||||
|
// Check if the cursor is at the first line for ArrowUp
|
||||||
|
if ((textBeforeCursor.indexOf("\n") == -1 && cursorPosition == 0 && key == "ArrowUp") || blockIndex != null) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
if (this.blockIndex < pres.length && this.blockIndex >= 0) {
|
GlobalModel.sidebarchatModel.setFocus(true);
|
||||||
this.blockIndex++;
|
return false;
|
||||||
this.updatePreTagOutline(pres[this.blockIndex]);
|
}
|
||||||
|
|
||||||
|
@mobx.action.bound
|
||||||
|
onSetCmdInputValue(cmd?: string) {
|
||||||
|
console.log("got here");
|
||||||
|
if (cmd) {
|
||||||
|
this.setCmdInputValue(cmd);
|
||||||
} else {
|
} else {
|
||||||
this.bindArrowUpDownKeys.set(false);
|
const pres = this.chatWindowRef.current?.querySelectorAll("pre");
|
||||||
this.textAreaRef.current.focus();
|
if (pres) {
|
||||||
this.updatePreTagOutline();
|
const selectedIdx = GlobalModel.sidebarchatModel.getSelectedCodeBlockIndex();
|
||||||
|
pres.forEach((preElement, idx) => {
|
||||||
|
if (selectedIdx === idx) {
|
||||||
|
const codeElement = preElement.querySelector("code");
|
||||||
|
if (codeElement) {
|
||||||
|
const command = codeElement.textContent.replace(/\n$/, "");
|
||||||
|
this.setCmdInputValue(command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.updateScrollTop();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@mobx.action.bound
|
||||||
|
setCmdInputValue(cmd: string) {
|
||||||
|
GlobalModel.sidebarchatModel.setCmdToExec(cmd);
|
||||||
|
GlobalModel.sidebarchatModel.resetFocus();
|
||||||
|
GlobalModel.inputModel.curLine = cmd;
|
||||||
|
GlobalModel.inputModel.giveFocus();
|
||||||
|
}
|
||||||
|
|
||||||
@mobx.action.bound
|
@mobx.action.bound
|
||||||
formChatMessage(cmdAndOutput) {
|
formChatMessage(cmdAndOutput) {
|
||||||
const { cmd, output, usedRows, isError } = cmdAndOutput;
|
const { cmd, output, usedRows, isError } = cmdAndOutput;
|
||||||
@ -430,7 +502,7 @@ class ChatSidebar extends React.Component<{}, {}> {
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
// Escape backticks in the output
|
// Escape backticks in the output
|
||||||
let escapedOutput = output ? output.replace(/```/g, "\\`\\`\\`") : "";
|
let escapedOutput = output ? output.replace(/`/g, "\\`") : "";
|
||||||
// Truncate the output if usedRows is over 100
|
// Truncate the output if usedRows is over 100
|
||||||
if (usedRows > 100) {
|
if (usedRows > 100) {
|
||||||
const outputLines = escapedOutput.split("\n");
|
const outputLines = escapedOutput.split("\n");
|
||||||
@ -450,38 +522,22 @@ class ChatSidebar extends React.Component<{}, {}> {
|
|||||||
return chatMessage;
|
return chatMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
@mobx.action.bound
|
|
||||||
handleKeyDown(e) {
|
|
||||||
if (e.key === "ArrowUp" || e.key === "ArrowDown") {
|
|
||||||
if (this.bindArrowUpDownKeys.get()) {
|
|
||||||
GlobalModel.sidebarchatModel.setFocus("block", true);
|
|
||||||
this.textAreaRef.current.blur();
|
|
||||||
}
|
|
||||||
|
|
||||||
const textarea = this.textAreaRef.current;
|
|
||||||
const cursorPosition = textarea.selectionStart;
|
|
||||||
const textBeforeCursor = textarea.value.slice(0, cursorPosition);
|
|
||||||
|
|
||||||
// Check if the cursor is at the first line
|
|
||||||
if (textBeforeCursor.indexOf("\n") === -1 && cursorPosition === 0 && e.key === "ArrowUp") {
|
|
||||||
this.bindArrowUpDownKeys.set(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const chatMessageItems = GlobalModel.inputModel.AICmdInfoChatItems.slice();
|
const chatMessageItems = GlobalModel.inputModel.AICmdInfoChatItems.slice();
|
||||||
const renderAIChatKeybindings = GlobalModel.sidebarchatModel.hasFocus;
|
const renderAIChatKeybindings = GlobalModel.sidebarchatModel.hasFocus();
|
||||||
const textAreaValue = this.value.get();
|
const textAreaValue = this.value.get();
|
||||||
const bindArrowUpDownKeys = this.bindArrowUpDownKeys.get();
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={this.sidebarRef} className="sidebarchat">
|
<div ref={this.sidebarRef} className="sidebarchat">
|
||||||
<If condition={renderAIChatKeybindings}>
|
<If condition={renderAIChatKeybindings}>
|
||||||
<ChatKeyBindings component={this} bindArrowUpDownKeys={bindArrowUpDownKeys} />
|
<ChatKeyBindings component={this} />
|
||||||
</If>
|
</If>
|
||||||
{chatMessageItems.length > 0 && (
|
{chatMessageItems.length > 0 && (
|
||||||
<ChatWindow chatWindowRef={this.chatWindowRef} onRendered={this.onChatWindowRendered} />
|
<ChatWindow
|
||||||
|
chatWindowRef={this.chatWindowRef}
|
||||||
|
onRendered={this.onChatWindowRendered}
|
||||||
|
onSetCmdInputValue={this.onSetCmdInputValue}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
<div className="sidebarchat-input-wrapper">
|
<div className="sidebarchat-input-wrapper">
|
||||||
<textarea
|
<textarea
|
||||||
@ -490,8 +546,8 @@ class ChatSidebar extends React.Component<{}, {}> {
|
|||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
autoCorrect="off"
|
autoCorrect="off"
|
||||||
className="sidebarchat-input chat-textarea"
|
className="sidebarchat-input chat-textarea"
|
||||||
onKeyDown={this.handleKeyDown}
|
onFocus={this.onTextAreaFocus}
|
||||||
onMouseDown={this.onTextAreaFocused}
|
onMouseDown={this.onTextAreaMouseDown} // When the user clicks on the textarea
|
||||||
onChange={this.onTextAreaChange}
|
onChange={this.onTextAreaChange}
|
||||||
style={{ fontSize: this.termFontSize }}
|
style={{ fontSize: this.termFontSize }}
|
||||||
placeholder="Send a Message..."
|
placeholder="Send a Message..."
|
||||||
|
@ -53,16 +53,12 @@ class KeybindDevPane extends React.Component<{}, {}> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SidebarKeyBindings extends React.Component<{ component: RightSideBar; isOpen: boolean }, {}> {
|
class SidebarKeyBindings extends React.Component<{ component: RightSideBar }, {}> {
|
||||||
componentDidMount(): void {
|
componentDidMount(): void {
|
||||||
const { component } = this.props;
|
const { component } = this.props;
|
||||||
const keybindManager = GlobalModel.keybindManager;
|
const keybindManager = GlobalModel.keybindManager;
|
||||||
keybindManager.registerKeybinding("pane", "rightsidebar", "rightsidebar:toggle", (waveEvent) => {
|
keybindManager.registerKeybinding("pane", "rightsidebar", "rightsidebar:toggle", (waveEvent) => {
|
||||||
if (this.props.isOpen) {
|
return component.toggleCollapse();
|
||||||
return component.onClose();
|
|
||||||
} else {
|
|
||||||
return component.onOpen();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,13 +83,21 @@ class RightSideBar extends React.Component<
|
|||||||
{}
|
{}
|
||||||
> {
|
> {
|
||||||
mode: OV<string> = mobx.observable.box("aichat", { name: "RightSideBar-mode" });
|
mode: OV<string> = mobx.observable.box("aichat", { name: "RightSideBar-mode" });
|
||||||
|
timeoutId: NodeJS.Timeout = null;
|
||||||
|
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
mobx.makeObservable(this);
|
mobx.makeObservable(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@mobx.action
|
componentWillUnmount() {
|
||||||
|
if (this.timeoutId) {
|
||||||
|
clearTimeout(this.timeoutId);
|
||||||
|
this.timeoutId = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mobx.action.bound
|
||||||
setMode(mode: string) {
|
setMode(mode: string) {
|
||||||
if (mode == this.mode.get()) {
|
if (mode == this.mode.get()) {
|
||||||
return;
|
return;
|
||||||
@ -101,15 +105,19 @@ class RightSideBar extends React.Component<
|
|||||||
this.mode.set(mode);
|
this.mode.set(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@boundMethod
|
@mobx.action.bound
|
||||||
onOpen() {
|
toggleCollapse() {
|
||||||
GlobalModel.rightSidebarModel.setCollapsed(false);
|
const isCollapsed = GlobalModel.rightSidebarModel.getCollapsed();
|
||||||
return true;
|
GlobalModel.rightSidebarModel.setCollapsed(!isCollapsed);
|
||||||
}
|
if (this.mode.get() == "aichat") {
|
||||||
|
if (isCollapsed) {
|
||||||
@boundMethod
|
this.timeoutId = setTimeout(() => {
|
||||||
onClose() {
|
GlobalModel.inputModel.setChatSidebarFocus();
|
||||||
GlobalModel.rightSidebarModel.setCollapsed(true);
|
}, 100);
|
||||||
|
} else {
|
||||||
|
GlobalModel.inputModel.setChatSidebarFocus(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -124,9 +132,9 @@ class RightSideBar extends React.Component<
|
|||||||
enableSnap={true}
|
enableSnap={true}
|
||||||
parentRef={this.props.parentRef}
|
parentRef={this.props.parentRef}
|
||||||
>
|
>
|
||||||
{(toggleCollapse) => (
|
{() => (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<SidebarKeyBindings component={this} isOpen={!isCollapsed} />
|
<SidebarKeyBindings component={this} />
|
||||||
<div className="header">
|
<div className="header">
|
||||||
<div className="rsb-modes">
|
<div className="rsb-modes">
|
||||||
<div
|
<div
|
||||||
@ -148,7 +156,7 @@ class RightSideBar extends React.Component<
|
|||||||
</div>
|
</div>
|
||||||
</If>
|
</If>
|
||||||
</div>
|
</div>
|
||||||
<Button className="secondary ghost close" onClick={toggleCollapse}>
|
<Button className="secondary ghost close" onClick={this.toggleCollapse}>
|
||||||
<i className="fa-sharp fa-solid fa-xmark-large" />
|
<i className="fa-sharp fa-solid fa-xmark-large" />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -139,6 +139,7 @@ class InputModel {
|
|||||||
const activeAuxView = this.getAuxViewFocus() ? this.getActiveAuxView() : null;
|
const activeAuxView = this.getAuxViewFocus() ? this.getActiveAuxView() : null;
|
||||||
switch (activeAuxView) {
|
switch (activeAuxView) {
|
||||||
case appconst.InputAuxView_History:
|
case appconst.InputAuxView_History:
|
||||||
|
console.log("focus history");
|
||||||
const elem: HTMLElement = document.querySelector(".cmd-input input.history-input");
|
const elem: HTMLElement = document.querySelector(".cmd-input input.history-input");
|
||||||
if (elem) {
|
if (elem) {
|
||||||
elem.focus();
|
elem.focus();
|
||||||
@ -148,8 +149,12 @@ class InputModel {
|
|||||||
this.setAIChatFocus();
|
this.setAIChatFocus();
|
||||||
break;
|
break;
|
||||||
case null:
|
case null:
|
||||||
if (GlobalModel.sidebarchatModel.hasFocus) {
|
if (GlobalModel.sidebarchatModel.hasFocus()) {
|
||||||
this.auxViewFocus.set(false);
|
this.auxViewFocus.set(false);
|
||||||
|
const elem: HTMLElement = document.querySelector(".sidebarchat-input");
|
||||||
|
if (elem != null) {
|
||||||
|
elem.focus();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const elem = document.getElementById("main-cmd-input");
|
const elem = document.getElementById("main-cmd-input");
|
||||||
if (elem) {
|
if (elem) {
|
||||||
@ -159,6 +164,7 @@ class InputModel {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default: {
|
default: {
|
||||||
|
console.log("focus auxview");
|
||||||
const elem: HTMLElement = document.querySelector(".cmd-input .auxview");
|
const elem: HTMLElement = document.querySelector(".cmd-input .auxview");
|
||||||
if (elem != null) {
|
if (elem != null) {
|
||||||
elem.focus();
|
elem.focus();
|
||||||
@ -282,6 +288,12 @@ class InputModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@mobx.action
|
||||||
|
setChatSidebarFocus(focus = true): void {
|
||||||
|
GlobalModel.sidebarchatModel.setFocus(focus);
|
||||||
|
this.giveFocus();
|
||||||
|
}
|
||||||
|
|
||||||
@mobx.action
|
@mobx.action
|
||||||
updateCmdLine(cmdLine: StrWithPos): void {
|
updateCmdLine(cmdLine: StrWithPos): void {
|
||||||
this.curLine = cmdLine.str;
|
this.curLine = cmdLine.str;
|
||||||
@ -468,7 +480,7 @@ class InputModel {
|
|||||||
}
|
}
|
||||||
// (view == null) means standard cmdinput keybindings
|
// (view == null) means standard cmdinput keybindings
|
||||||
if (view == null) {
|
if (view == null) {
|
||||||
return !this.getAuxViewFocus() && !GlobalModel.sidebarchatModel.hasFocus;
|
return !this.getAuxViewFocus() && !GlobalModel.sidebarchatModel.hasFocus();
|
||||||
} else {
|
} else {
|
||||||
return this.getAuxViewFocus() && view == this.getActiveAuxView();
|
return this.getAuxViewFocus() && view == this.getActiveAuxView();
|
||||||
}
|
}
|
||||||
|
@ -82,6 +82,11 @@ class MainSidebarModel {
|
|||||||
return collapsed;
|
return collapsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setCollapsed(collapsed: boolean): void {
|
||||||
|
const width = this.getWidth(true);
|
||||||
|
this.saveState(width, collapsed);
|
||||||
|
}
|
||||||
|
|
||||||
saveState(width: number, collapsed: boolean): void {
|
saveState(width: number, collapsed: boolean): void {
|
||||||
GlobalCommandRunner.clientSetMainSidebar(width, collapsed).finally(() => {
|
GlobalCommandRunner.clientSetMainSidebar(width, collapsed).finally(() => {
|
||||||
mobx.action(() => {
|
mobx.action(() => {
|
||||||
|
@ -738,10 +738,12 @@ class Model {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// allows for the session view to load
|
// allows for the session view to load
|
||||||
this.inputModel.setAuxViewFocus(false);
|
this.inputModel.setAuxViewFocus(false);
|
||||||
|
this.inputModel.setChatSidebarFocus(false);
|
||||||
}, 100);
|
}, 100);
|
||||||
})();
|
})();
|
||||||
} else {
|
} else {
|
||||||
this.inputModel.setAuxViewFocus(false);
|
this.inputModel.setAuxViewFocus(false);
|
||||||
|
this.inputModel.setChatSidebarFocus(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,104 +1,91 @@
|
|||||||
import * as mobx from "mobx";
|
import * as mobx from "mobx";
|
||||||
import { Model } from "./model";
|
import { Model } from "./model";
|
||||||
|
|
||||||
type SidebarChatFocus = {
|
|
||||||
input: boolean;
|
|
||||||
block: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
class SidebarChatModel {
|
class SidebarChatModel {
|
||||||
globalModel: Model;
|
globalModel: Model;
|
||||||
sidebarChatFocus: SidebarChatFocus;
|
sidebarChatFocused: OV<boolean> = mobx.observable.box(false, { name: "SidebarChatModel-sidebarChatFocused" });
|
||||||
cmdAndOutput: CmdAndOutput;
|
cmdAndOutput: OV<{ cmd: string; output: string; usedRows: number; isError: boolean }> = mobx.observable.box(
|
||||||
cmdFromChat: string;
|
{ cmd: "", output: "", usedRows: 0, isError: false },
|
||||||
|
{ name: "SidebarChatModel-cmdAndOutput" }
|
||||||
|
);
|
||||||
|
cmdFromChat: OV<string> = mobx.observable.box("", { name: "SidebarChatModel-cmdFromChat" });
|
||||||
|
selectedCodeBlockIndex: OV<number> = mobx.observable.box(null, { name: "SidebarChatModel-codeBlockIndex" });
|
||||||
|
|
||||||
constructor(globalModel: Model) {
|
constructor(globalModel: Model) {
|
||||||
this.globalModel = globalModel;
|
this.globalModel = globalModel;
|
||||||
mobx.makeObservable(this, {
|
mobx.makeObservable(this);
|
||||||
sidebarChatFocus: mobx.observable,
|
}
|
||||||
cmdAndOutput: mobx.observable,
|
|
||||||
setFocus: mobx.action,
|
// block can be the chat-window in terms of focus
|
||||||
resetFocus: mobx.action,
|
@mobx.action
|
||||||
setCmdAndOutput: mobx.action,
|
setFocus(focus: boolean): void {
|
||||||
resetCmdAndOutput: mobx.action,
|
this.resetFocus();
|
||||||
setCmdToExec: mobx.action,
|
this.sidebarChatFocused.set(focus);
|
||||||
resetCmdToExec: mobx.action,
|
}
|
||||||
hasFocus: mobx.computed,
|
|
||||||
focused: mobx.computed,
|
hasFocus(): boolean {
|
||||||
cmdToExec: mobx.computed,
|
return this.sidebarChatFocused.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@mobx.action
|
||||||
|
resetFocus(): void {
|
||||||
|
this.sidebarChatFocused.set(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@mobx.action
|
||||||
|
setCmdAndOutput(cmd: string, output: string, usedRows: number, isError: boolean): void {
|
||||||
|
console.log("cmd", cmd);
|
||||||
|
this.cmdAndOutput.set({
|
||||||
|
cmd: cmd,
|
||||||
|
output: output,
|
||||||
|
usedRows: usedRows,
|
||||||
|
isError: isError,
|
||||||
});
|
});
|
||||||
this.sidebarChatFocus = {
|
}
|
||||||
input: false,
|
|
||||||
block: false,
|
getCmdAndOutput(): { cmd: string; output: string; usedRows: number; isError: boolean } {
|
||||||
};
|
return this.cmdAndOutput.get();
|
||||||
this.cmdAndOutput = {
|
}
|
||||||
|
|
||||||
|
@mobx.action
|
||||||
|
resetCmdAndOutput(): void {
|
||||||
|
this.cmdAndOutput.set({
|
||||||
cmd: "",
|
cmd: "",
|
||||||
output: "",
|
output: "",
|
||||||
usedRows: 0,
|
usedRows: 0,
|
||||||
isError: false,
|
isError: false,
|
||||||
};
|
});
|
||||||
this.cmdFromChat = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// block can be the chat-window in terms of focus
|
|
||||||
setFocus(section: "input" | "block", focus: boolean): void {
|
|
||||||
document.querySelector(".sidebarchat .sidebarchat-input");
|
|
||||||
this.resetFocus();
|
|
||||||
this.sidebarChatFocus[section] = focus;
|
|
||||||
}
|
|
||||||
|
|
||||||
get hasFocus(): boolean {
|
|
||||||
return this.sidebarChatFocus.input || this.sidebarChatFocus.block;
|
|
||||||
}
|
|
||||||
|
|
||||||
get focused(): "input" | "block" | null {
|
|
||||||
if (this.sidebarChatFocus.input) return "input";
|
|
||||||
if (this.sidebarChatFocus.block) return "block";
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
resetFocus(): void {
|
|
||||||
this.sidebarChatFocus.input = false;
|
|
||||||
this.sidebarChatFocus.block = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
setCmdAndOutput(cmd: string, output: string, usedRows: number, isError: boolean): void {
|
|
||||||
this.cmdAndOutput.cmd = cmd;
|
|
||||||
this.cmdAndOutput.output = output;
|
|
||||||
this.cmdAndOutput.usedRows = usedRows;
|
|
||||||
this.cmdAndOutput.isError = isError;
|
|
||||||
}
|
|
||||||
|
|
||||||
getCmdAndOutput(): CmdAndOutput {
|
|
||||||
return {
|
|
||||||
cmd: this.cmdAndOutput.cmd,
|
|
||||||
output: this.cmdAndOutput.output,
|
|
||||||
usedRows: this.cmdAndOutput.usedRows,
|
|
||||||
isError: this.cmdAndOutput.isError,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
resetCmdAndOutput(): void {
|
|
||||||
this.cmdAndOutput.cmd = "";
|
|
||||||
this.cmdAndOutput.output = "";
|
|
||||||
this.cmdAndOutput.usedRows = 0;
|
|
||||||
this.cmdAndOutput.isError = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hasCmdAndOutput(): boolean {
|
hasCmdAndOutput(): boolean {
|
||||||
return this.cmdAndOutput.cmd.length > 0 || this.cmdAndOutput.output.length > 0;
|
const { cmd, output } = this.cmdAndOutput.get();
|
||||||
|
return cmd.length > 0 || output.length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@mobx.action
|
||||||
setCmdToExec(cmd: string): void {
|
setCmdToExec(cmd: string): void {
|
||||||
this.cmdFromChat = cmd;
|
this.cmdFromChat.set(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@mobx.action
|
||||||
resetCmdToExec(): void {
|
resetCmdToExec(): void {
|
||||||
this.cmdFromChat = "";
|
this.cmdFromChat.set("");
|
||||||
}
|
}
|
||||||
|
|
||||||
get cmdToExec(): string {
|
getCmdToExec(): string {
|
||||||
return this.cmdFromChat;
|
return this.cmdFromChat.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
getSelectedCodeBlockIndex(): number {
|
||||||
|
return this.selectedCodeBlockIndex.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
setSelectedCodeBlockIndex(index: number): void {
|
||||||
|
this.selectedCodeBlockIndex.set(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
resetSelectedCodeBlockIndex(): void {
|
||||||
|
this.selectedCodeBlockIndex.set(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
7
src/types/custom.d.ts
vendored
7
src/types/custom.d.ts
vendored
@ -990,13 +990,6 @@ declare global {
|
|||||||
click?: () => void; // not required if role is set
|
click?: () => void; // not required if role is set
|
||||||
submenu?: ContextMenuItem[];
|
submenu?: ContextMenuItem[];
|
||||||
};
|
};
|
||||||
|
|
||||||
type CmdAndOutput = {
|
|
||||||
cmd: string;
|
|
||||||
output: string;
|
|
||||||
usedRows: number;
|
|
||||||
isError: boolean;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export {};
|
export {};
|
||||||
|
Loading…
Reference in New Issue
Block a user