mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-01-02 18:39:05 +01:00
Clean up the input model's auxiliary view logic (#553)
* Clean up the input model's auxiliary view logic * fix * save work * rename appconst * fix keybindings * remove debugs * Add comments * fix focus order * givefocus whenever focus var is updated, don't update if nothign changes * remove debug statements * one more debug * revert unnecessary newline * remove cmdinput placeholder to allow for better window resizing
This commit is contained in:
parent
eed234a131
commit
455790416d
@ -64,3 +64,7 @@ export enum StatusIndicatorLevel {
|
||||
|
||||
// matches packet.go
|
||||
export const ErrorCode_InvalidCwd = "ERRCWD";
|
||||
|
||||
export const InputAuxView_History = "history";
|
||||
export const InputAuxView_Info = "info";
|
||||
export const InputAuxView_AIChat = "aichat";
|
||||
|
@ -27,7 +27,7 @@ class AIChatKeybindings extends React.Component<{ AIChatObject: AIChat }, {}> {
|
||||
return true;
|
||||
});
|
||||
keybindManager.registerKeybinding("pane", "aichat", "generic:cancel", (waveEvent) => {
|
||||
inputModel.closeAIAssistantChat(true);
|
||||
inputModel.closeAuxView();
|
||||
return true;
|
||||
});
|
||||
keybindManager.registerKeybinding("pane", "aichat", "aichat:clearHistory", (waveEvent) => {
|
||||
@ -70,7 +70,7 @@ class AIChat extends React.Component<{}, {}> {
|
||||
|
||||
componentDidMount() {
|
||||
const inputModel = GlobalModel.inputModel;
|
||||
if (this.chatWindowScrollRef != null && this.chatWindowScrollRef.current != null) {
|
||||
if (this.chatWindowScrollRef?.current != null) {
|
||||
this.chatWindowScrollRef.current.scrollTop = this.chatWindowScrollRef.current.scrollHeight;
|
||||
}
|
||||
if (this.textAreaRef.current != null) {
|
||||
@ -82,7 +82,7 @@ class AIChat extends React.Component<{}, {}> {
|
||||
}
|
||||
|
||||
componentDidUpdate() {
|
||||
if (this.chatWindowScrollRef != null && this.chatWindowScrollRef.current != null) {
|
||||
if (this.chatWindowScrollRef?.current != null) {
|
||||
this.chatWindowScrollRef.current.scrollTop = this.chatWindowScrollRef.current.scrollHeight;
|
||||
}
|
||||
}
|
||||
@ -252,7 +252,7 @@ class AIChat extends React.Component<{}, {}> {
|
||||
<AuxiliaryCmdView
|
||||
title="Wave AI"
|
||||
className="cmd-aichat"
|
||||
onClose={() => GlobalModel.inputModel.closeAIAssistantChat(true)}
|
||||
onClose={() => GlobalModel.inputModel.closeAuxView()}
|
||||
iconClass="fa-sharp fa-solid fa-sparkles"
|
||||
>
|
||||
<If condition={renderKeybindings}>
|
||||
|
@ -4,12 +4,11 @@
|
||||
max-height: max(300px, 40%);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
z-index: 100;
|
||||
border-top: 2px solid var(--app-border-color);
|
||||
background-color: var(--app-bg-color);
|
||||
position: relative;
|
||||
|
||||
// Apply a border between the base cmdinput and any views shown above it
|
||||
// TODO: use a generic selector for this
|
||||
|
@ -5,7 +5,7 @@ import * as React from "react";
|
||||
import * as mobxReact from "mobx-react";
|
||||
import * as mobx from "mobx";
|
||||
import { boundMethod } from "autobind-decorator";
|
||||
import { If } from "tsx-control-statements/components";
|
||||
import { Choose, If, When } from "tsx-control-statements/components";
|
||||
import cn from "classnames";
|
||||
import dayjs from "dayjs";
|
||||
import localizedFormat from "dayjs/plugin/localizedFormat";
|
||||
@ -18,6 +18,7 @@ import { Prompt } from "@/common/prompt/prompt";
|
||||
import { CenteredIcon, RotateIcon } from "@/common/icons/icons";
|
||||
import { AIChat } from "./aichat";
|
||||
import * as util from "@/util/util";
|
||||
import * as appconst from "@/app/appconst";
|
||||
|
||||
import "./cmdinput.less";
|
||||
|
||||
@ -71,7 +72,7 @@ class CmdInput extends React.Component<{}, {}> {
|
||||
e.stopPropagation();
|
||||
return;
|
||||
}
|
||||
GlobalModel.inputModel.setHistoryFocus(false);
|
||||
GlobalModel.inputModel.setAuxViewFocus(false);
|
||||
GlobalModel.inputModel.giveFocus();
|
||||
}
|
||||
|
||||
@ -80,8 +81,8 @@ class CmdInput extends React.Component<{}, {}> {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const inputModel = GlobalModel.inputModel;
|
||||
if (inputModel.aIChatShow.get()) {
|
||||
inputModel.closeAIAssistantChat(true);
|
||||
if (inputModel.getActiveAuxView() === appconst.InputAuxView_AIChat) {
|
||||
inputModel.closeAuxView();
|
||||
} else {
|
||||
inputModel.openAIAssistantChat();
|
||||
}
|
||||
@ -93,7 +94,7 @@ class CmdInput extends React.Component<{}, {}> {
|
||||
e.stopPropagation();
|
||||
|
||||
const inputModel = GlobalModel.inputModel;
|
||||
if (inputModel.historyShow.get()) {
|
||||
if (inputModel.getActiveAuxView() === appconst.InputAuxView_History) {
|
||||
inputModel.resetHistory();
|
||||
} else {
|
||||
inputModel.openHistory();
|
||||
@ -155,9 +156,6 @@ class CmdInput extends React.Component<{}, {}> {
|
||||
remote = GlobalModel.getRemote(rptr.remoteid);
|
||||
}
|
||||
feState = feState || {};
|
||||
const infoShow = inputModel.infoShow.get();
|
||||
const historyShow = !infoShow && inputModel.historyShow.get();
|
||||
const aiChatShow = inputModel.aIChatShow.get();
|
||||
const focusVal = inputModel.physicalInputFocused.get();
|
||||
const inputMode: string = inputModel.inputMode.get();
|
||||
const textAreaInputKey = screen == null ? "null" : screen.screenId;
|
||||
@ -170,7 +168,7 @@ class CmdInput extends React.Component<{}, {}> {
|
||||
let shellInitMsg: string = null;
|
||||
let hidePrompt = false;
|
||||
|
||||
const openView = inputModel.getOpenView();
|
||||
const openView = inputModel.getActiveAuxView();
|
||||
const hasOpenView = openView ? `has-${openView}` : null;
|
||||
if (ri == null) {
|
||||
let shellStr = "shell";
|
||||
@ -185,15 +183,19 @@ class CmdInput extends React.Component<{}, {}> {
|
||||
}
|
||||
return (
|
||||
<div ref={this.cmdInputRef} className={cn("cmd-input", hasOpenView, { active: focusVal })}>
|
||||
<If condition={historyShow}>
|
||||
<div className="cmd-input-grow-spacer"></div>
|
||||
<HistoryInfo />
|
||||
</If>
|
||||
<If condition={aiChatShow}>
|
||||
<div className="cmd-input-grow-spacer"></div>
|
||||
<AIChat />
|
||||
</If>
|
||||
<InfoMsg key="infomsg" />
|
||||
<Choose>
|
||||
<When condition={openView === appconst.InputAuxView_History}>
|
||||
<div className="cmd-input-grow-spacer"></div>
|
||||
<HistoryInfo />
|
||||
</When>
|
||||
<When condition={openView === appconst.InputAuxView_AIChat}>
|
||||
<div className="cmd-input-grow-spacer"></div>
|
||||
<AIChat />
|
||||
</When>
|
||||
<When condition={openView === appconst.InputAuxView_Info}>
|
||||
<InfoMsg key="infomsg" />
|
||||
</When>
|
||||
</Choose>
|
||||
<If condition={remote && remote.status != "connected"}>
|
||||
<div className="remote-status-warning">
|
||||
WARNING:
|
||||
|
@ -167,14 +167,14 @@ class HistoryInfo extends React.Component<{}, {}> {
|
||||
|
||||
@boundMethod
|
||||
handleClose() {
|
||||
GlobalModel.inputModel.toggleInfoMsg();
|
||||
GlobalModel.inputModel.closeAuxView();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
handleItemClick(hitem: HistoryItem) {
|
||||
const inputModel = GlobalModel.inputModel;
|
||||
const selItem = inputModel.getHistorySelectedItem();
|
||||
inputModel.setHistoryFocus(true);
|
||||
inputModel.setAuxViewFocus(false);
|
||||
if (this.lastClickHNum == hitem.historynum && selItem != null && selItem.historynum == hitem.historynum) {
|
||||
inputModel.grabSelectedHistoryItem();
|
||||
return;
|
||||
@ -194,14 +194,14 @@ class HistoryInfo extends React.Component<{}, {}> {
|
||||
@boundMethod
|
||||
handleClickType() {
|
||||
const inputModel = GlobalModel.inputModel;
|
||||
inputModel.setHistoryFocus(true);
|
||||
inputModel.setAuxViewFocus(true);
|
||||
inputModel.toggleHistoryType();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
handleClickRemote() {
|
||||
const inputModel = GlobalModel.inputModel;
|
||||
inputModel.setHistoryFocus(true);
|
||||
inputModel.setAuxViewFocus(true);
|
||||
inputModel.toggleRemoteType();
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ class InfoMsg extends React.Component<{}, {}> {
|
||||
render() {
|
||||
const inputModel = GlobalModel.inputModel;
|
||||
const infoMsg: InfoType = inputModel.infoMsg.get();
|
||||
const infoShow: boolean = inputModel.infoShow.get();
|
||||
const infoShow = inputModel.getActiveAuxView() == appconst.InputAuxView_Info;
|
||||
let line: string = null;
|
||||
let istr: string = null;
|
||||
let idx: number = 0;
|
||||
|
@ -152,11 +152,7 @@ class CmdInputKeybindings extends React.Component<{ inputObject: TextAreaInput }
|
||||
});
|
||||
keybindManager.registerKeybinding("pane", "cmdinput", "generic:cancel", (waveEvent) => {
|
||||
GlobalModel.closeTabSettings();
|
||||
inputModel.toggleInfoMsg();
|
||||
if (inputModel.inputMode.get() != null) {
|
||||
inputModel.resetInputMode();
|
||||
}
|
||||
inputModel.closeAIAssistantChat(true);
|
||||
inputModel.closeAuxView();
|
||||
return true;
|
||||
});
|
||||
keybindManager.registerKeybinding("pane", "cmdinput", "cmdinput:expandInput", (waveEvent) => {
|
||||
@ -254,8 +250,6 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
|
||||
lastHeight: number = 0;
|
||||
lastSP: StrWithPos = { str: "", pos: appconst.NoStrPos };
|
||||
version: OV<number> = mobx.observable.box(0, { name: "textAreaInput-version" }); // forces render updates
|
||||
mainInputFocused: OV<boolean> = mobx.observable.box(true, { name: "textAreaInput-mainInputFocused" });
|
||||
historyFocused: OV<boolean> = mobx.observable.box(false, { name: "textAreaInput-historyFocused" });
|
||||
|
||||
incVersion(): void {
|
||||
const v = this.version.get();
|
||||
@ -286,16 +280,7 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
|
||||
}
|
||||
|
||||
setFocus(): void {
|
||||
const inputModel = GlobalModel.inputModel;
|
||||
if (inputModel.historyFocus.get()) {
|
||||
if (this.historyInputRef.current != null && document.activeElement != this.historyInputRef.current) {
|
||||
this.historyInputRef.current.focus();
|
||||
}
|
||||
} else {
|
||||
if (this.mainInputRef.current != null && document.activeElement != this.mainInputRef.current) {
|
||||
this.mainInputRef.current.focus();
|
||||
}
|
||||
}
|
||||
GlobalModel.inputModel.giveFocus();
|
||||
}
|
||||
|
||||
getTextAreaMaxCols(): number {
|
||||
@ -536,7 +521,7 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
|
||||
if (selStart > value.length || selEnd > value.length) {
|
||||
return;
|
||||
}
|
||||
const newValue = value.substr(0, selStart) + clipText + value.substr(selEnd);
|
||||
const newValue = value.substring(0, selStart) + clipText + value.substring(selEnd);
|
||||
const cmdLineUpdate = { str: newValue, pos: selStart + clipText.length };
|
||||
GlobalModel.inputModel.updateCmdLine(cmdLineUpdate);
|
||||
});
|
||||
@ -553,19 +538,9 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
handleMainFocus(e: any) {
|
||||
const inputModel = GlobalModel.inputModel;
|
||||
if (inputModel.historyFocus.get()) {
|
||||
e.preventDefault();
|
||||
if (this.historyInputRef.current != null) {
|
||||
this.historyInputRef.current.focus();
|
||||
}
|
||||
return;
|
||||
}
|
||||
inputModel.setPhysicalInputFocused(true);
|
||||
mobx.action(() => {
|
||||
this.mainInputFocused.set(true);
|
||||
})();
|
||||
handleFocus(e: any) {
|
||||
e.preventDefault();
|
||||
GlobalModel.inputModel.giveFocus();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
@ -574,25 +549,6 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
|
||||
return;
|
||||
}
|
||||
GlobalModel.inputModel.setPhysicalInputFocused(false);
|
||||
mobx.action(() => {
|
||||
this.mainInputFocused.set(false);
|
||||
})();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
handleHistoryFocus(e: any) {
|
||||
const inputModel = GlobalModel.inputModel;
|
||||
if (!inputModel.historyFocus.get()) {
|
||||
e.preventDefault();
|
||||
if (this.mainInputRef.current != null) {
|
||||
this.mainInputRef.current.focus();
|
||||
}
|
||||
return;
|
||||
}
|
||||
inputModel.setPhysicalInputFocused(true);
|
||||
mobx.action(() => {
|
||||
this.historyFocused.set(true);
|
||||
})();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
@ -601,9 +557,6 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
|
||||
return;
|
||||
}
|
||||
GlobalModel.inputModel.setPhysicalInputFocused(false);
|
||||
mobx.action(() => {
|
||||
this.historyFocused.set(false);
|
||||
})();
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -621,9 +574,8 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
|
||||
displayLines = 5;
|
||||
}
|
||||
|
||||
// TODO: invert logic here. We should track focus on the main textarea and assume aux view is focused if not.
|
||||
const disabled = inputModel.historyFocus.get();
|
||||
if (disabled) {
|
||||
const auxViewFocused = inputModel.getAuxViewFocus();
|
||||
if (auxViewFocused) {
|
||||
displayLines = 1;
|
||||
}
|
||||
const activeScreen = GlobalModel.getActiveScreen();
|
||||
@ -639,7 +591,7 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
|
||||
const screen = GlobalModel.getActiveScreen();
|
||||
if (screen != null) {
|
||||
const ri = screen.getCurRemoteInstance();
|
||||
if (ri != null && ri.shelltype != null) {
|
||||
if (ri?.shelltype != null) {
|
||||
shellType = ri.shelltype;
|
||||
}
|
||||
if (shellType == "") {
|
||||
@ -652,15 +604,14 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
|
||||
}
|
||||
}
|
||||
}
|
||||
const isMainInputFocused = inputModel.hasFocus() && this.mainInputFocused.get();
|
||||
const isHistoryFocused = this.historyFocused.get();
|
||||
const isHistoryFocused = auxViewFocused && inputModel.getActiveAuxView() == appconst.InputAuxView_History;
|
||||
return (
|
||||
<div
|
||||
className="textareainput-div control is-expanded"
|
||||
ref={this.controlRef}
|
||||
style={{ height: computedOuterHeight }}
|
||||
>
|
||||
<If condition={isMainInputFocused}>
|
||||
<If condition={!auxViewFocused}>
|
||||
<CmdInputKeybindings inputObject={this}></CmdInputKeybindings>
|
||||
</If>
|
||||
<If condition={isHistoryFocused}>
|
||||
@ -677,7 +628,7 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
id="main-cmd-input"
|
||||
onFocus={this.handleMainFocus}
|
||||
onFocus={this.handleFocus}
|
||||
onBlur={this.handleMainBlur}
|
||||
style={{ height: computedInnerHeight, minHeight: computedInnerHeight, fontSize: termFontSize }}
|
||||
value={curLine}
|
||||
@ -685,7 +636,7 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
|
||||
onChange={this.onChange}
|
||||
onSelect={this.onSelect}
|
||||
placeholder="Type here..."
|
||||
className={cn("textarea", { "display-disabled": disabled })}
|
||||
className={cn("textarea", { "display-disabled": auxViewFocused })}
|
||||
></textarea>
|
||||
<input
|
||||
key="history"
|
||||
@ -695,7 +646,7 @@ class TextAreaInput extends React.Component<{ screen: Screen; onHeightChange: ()
|
||||
autoCorrect="off"
|
||||
className="history-input"
|
||||
type="text"
|
||||
onFocus={this.handleHistoryFocus}
|
||||
onFocus={this.handleFocus}
|
||||
onBlur={this.handleHistoryBlur}
|
||||
onKeyDown={this.onHistoryKeyDown}
|
||||
onChange={this.handleHistoryInput}
|
||||
|
@ -318,7 +318,6 @@ class WorkspaceView extends React.Component<{}, {}> {
|
||||
session={session}
|
||||
screen={activeScreen}
|
||||
/>
|
||||
<div className="cmdinput-height-placeholder" style={{ height: cmdInputHeight }}></div>
|
||||
<If condition={activeScreen != null}>
|
||||
<CmdInput key={"cmdinput-" + sessionId} />
|
||||
</If>
|
||||
|
@ -8,6 +8,7 @@ import { isBlank } from "@/util/util";
|
||||
import * as appconst from "@/app/appconst";
|
||||
import { Model } from "./model";
|
||||
import { GlobalCommandRunner } from "./global";
|
||||
import { app } from "electron";
|
||||
|
||||
function getDefaultHistoryQueryOpts(): HistoryQueryOpts {
|
||||
return {
|
||||
@ -24,10 +25,8 @@ function getDefaultHistoryQueryOpts(): HistoryQueryOpts {
|
||||
|
||||
class InputModel {
|
||||
globalModel: Model;
|
||||
historyShow: OV<boolean> = mobx.observable.box(false);
|
||||
historyFocus: OV<boolean> = mobx.observable.box(false);
|
||||
infoShow: OV<boolean> = mobx.observable.box(false);
|
||||
aIChatShow: OV<boolean> = mobx.observable.box(false);
|
||||
activeAuxView: OV<InputAuxViewType> = mobx.observable.box(null);
|
||||
auxViewFocus: OV<boolean> = mobx.observable.box(false);
|
||||
cmdInputHeight: OV<number> = mobx.observable.box(0);
|
||||
aiChatTextAreaRef: React.RefObject<HTMLTextAreaElement>;
|
||||
aiChatWindowRef: React.RefObject<HTMLDivElement>;
|
||||
@ -139,26 +138,39 @@ class InputModel {
|
||||
})();
|
||||
}
|
||||
|
||||
_focusCmdInput(): void {
|
||||
const elem = document.getElementById("main-cmd-input");
|
||||
if (elem != null) {
|
||||
elem.focus();
|
||||
}
|
||||
}
|
||||
|
||||
_focusHistoryInput(): void {
|
||||
const elem: HTMLElement = document.querySelector(".cmd-input input.history-input");
|
||||
if (elem != null) {
|
||||
elem.focus();
|
||||
}
|
||||
}
|
||||
|
||||
// Focuses the main input or the auxiliary view, depending on the active auxiliary view
|
||||
giveFocus(): void {
|
||||
if (this.historyFocus.get()) {
|
||||
this._focusHistoryInput();
|
||||
} else {
|
||||
this._focusCmdInput();
|
||||
}
|
||||
// Override active view to the main input if aux view does not have focus
|
||||
const activeAuxView = this.getAuxViewFocus() ? this.getActiveAuxView() : null;
|
||||
mobx.action(() => {
|
||||
switch (activeAuxView) {
|
||||
case appconst.InputAuxView_History: {
|
||||
const elem: HTMLElement = document.querySelector(".cmd-input input.history-input");
|
||||
if (elem != null) {
|
||||
elem.focus();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "aichat":
|
||||
this.setAIChatFocus();
|
||||
break;
|
||||
case null: {
|
||||
const elem = document.getElementById("main-cmd-input");
|
||||
if (elem != null) {
|
||||
elem.focus();
|
||||
}
|
||||
this.setPhysicalInputFocused(true);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
const elem: HTMLElement = document.querySelector(".cmd-input .auxview");
|
||||
if (elem != null) {
|
||||
elem.focus();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
setPhysicalInputFocused(isFocused: boolean): void {
|
||||
@ -191,19 +203,6 @@ class InputModel {
|
||||
return false;
|
||||
}
|
||||
|
||||
getOpenView(): string {
|
||||
if (this.historyShow.get()) {
|
||||
return "history";
|
||||
}
|
||||
if (this.aIChatShow.get()) {
|
||||
return "aichat";
|
||||
}
|
||||
if (this.infoShow.get()) {
|
||||
return "info";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
setHistoryType(htype: HistoryTypeStrs): void {
|
||||
if (this.historyQueryOpts.get().queryType == htype) {
|
||||
return;
|
||||
@ -244,45 +243,11 @@ class InputModel {
|
||||
})();
|
||||
}
|
||||
|
||||
setInputPopUpType(type: string) {
|
||||
this.inputPopUpType = type;
|
||||
this.aIChatShow.set(type == "aichat");
|
||||
this.historyShow.set(type == "history");
|
||||
}
|
||||
|
||||
setOpenAICmdInfoChat(chat: OpenAICmdInfoChatMessageType[]): void {
|
||||
this.AICmdInfoChatItems.replace(chat);
|
||||
this.codeSelectBlockRefArray = [];
|
||||
}
|
||||
|
||||
setHistoryShow(show: boolean): void {
|
||||
if (this.historyShow.get() == show) {
|
||||
return;
|
||||
}
|
||||
mobx.action(() => {
|
||||
if (show) {
|
||||
this.setInputPopUpType("history");
|
||||
} else {
|
||||
this.setInputPopUpType("none");
|
||||
}
|
||||
this.historyShow.set(show);
|
||||
this.historyFocus.set(show);
|
||||
if (this.hasFocus()) {
|
||||
this.giveFocus();
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
setHistoryFocus(focus: boolean): void {
|
||||
if (this.historyFocus.get() == focus) {
|
||||
return;
|
||||
}
|
||||
mobx.action(() => {
|
||||
this.historyFocus.set(focus);
|
||||
this.giveFocus();
|
||||
})();
|
||||
}
|
||||
|
||||
isHistoryLoaded(): boolean {
|
||||
if (this.historyLoading.get()) {
|
||||
return false;
|
||||
@ -315,14 +280,9 @@ class InputModel {
|
||||
this.loadHistory(true, 0, "screen");
|
||||
return;
|
||||
}
|
||||
if (!this.historyShow.get()) {
|
||||
mobx.action(() => {
|
||||
this.setHistoryShow(true);
|
||||
this.aIChatShow.set(false);
|
||||
this.infoShow.set(false);
|
||||
this.dropModHistory(true);
|
||||
this.giveFocus();
|
||||
})();
|
||||
if (this.getActiveAuxView() != appconst.InputAuxView_History) {
|
||||
this.dropModHistory(true);
|
||||
this.setActiveAuxView(appconst.InputAuxView_History);
|
||||
}
|
||||
}
|
||||
|
||||
@ -495,6 +455,51 @@ class InputModel {
|
||||
})();
|
||||
}
|
||||
|
||||
// Closes the auxiliary view if it is open, focuses the main input
|
||||
closeAuxView(): void {
|
||||
if (this.activeAuxView.get() == null) {
|
||||
return;
|
||||
}
|
||||
this.setActiveAuxView(null);
|
||||
}
|
||||
|
||||
// Gets the active auxiliary view, or null if none
|
||||
getActiveAuxView(): InputAuxViewType {
|
||||
return this.activeAuxView.get();
|
||||
}
|
||||
|
||||
// Sets the active auxiliary view
|
||||
setActiveAuxView(view: InputAuxViewType): void {
|
||||
if (view == this.activeAuxView.get()) {
|
||||
return;
|
||||
}
|
||||
mobx.action(() => {
|
||||
this.auxViewFocus.set(view != null);
|
||||
this.activeAuxView.set(view);
|
||||
})();
|
||||
this.giveFocus();
|
||||
}
|
||||
|
||||
// Gets the focus state of the auxiliary view. If true, the view will get focus. Otherwise, the main input will get focus.
|
||||
// If the auxiliary view is not open, this will return false.
|
||||
getAuxViewFocus(): boolean {
|
||||
if (this.getActiveAuxView() == null) {
|
||||
return false;
|
||||
}
|
||||
return this.auxViewFocus.get();
|
||||
}
|
||||
|
||||
// Sets the focus state of the auxiliary view. If true, the view will get focus. Otherwise, the main input will get focus.
|
||||
setAuxViewFocus(focus: boolean): void {
|
||||
if (this.getAuxViewFocus() == focus) {
|
||||
return;
|
||||
}
|
||||
mobx.action(() => {
|
||||
this.auxViewFocus.set(focus);
|
||||
})();
|
||||
this.giveFocus();
|
||||
}
|
||||
|
||||
setHistoryIndex(hidx: number, force?: boolean): void {
|
||||
if (hidx < 0) {
|
||||
return;
|
||||
@ -504,7 +509,7 @@ class InputModel {
|
||||
}
|
||||
mobx.action(() => {
|
||||
this.historyIndex.set(hidx);
|
||||
if (this.historyShow.get()) {
|
||||
if (this.getActiveAuxView() == appconst.InputAuxView_History) {
|
||||
let hitem = this.getHistorySelectedItem();
|
||||
if (hitem == null) {
|
||||
hitem = this.getFirstHistoryItem();
|
||||
@ -538,16 +543,18 @@ class InputModel {
|
||||
this._clearInfoTimeout();
|
||||
mobx.action(() => {
|
||||
this.infoMsg.set(info);
|
||||
if (info == null) {
|
||||
this.infoShow.set(false);
|
||||
} else {
|
||||
this.infoShow.set(true);
|
||||
this.setHistoryShow(false);
|
||||
}
|
||||
})();
|
||||
|
||||
if (info == null && this.getActiveAuxView() == appconst.InputAuxView_Info) {
|
||||
this.setActiveAuxView(null);
|
||||
} else {
|
||||
this.setActiveAuxView(appconst.InputAuxView_Info);
|
||||
}
|
||||
|
||||
if (info != null && timeoutMs) {
|
||||
this.infoTimeoutId = setTimeout(() => {
|
||||
if (this.historyShow.get()) {
|
||||
console.log("clearing info msg");
|
||||
if (this.activeAuxView.get() != appconst.InputAuxView_Info) {
|
||||
return;
|
||||
}
|
||||
this.clearInfoMsg(false);
|
||||
@ -683,28 +690,7 @@ class InputModel {
|
||||
}
|
||||
|
||||
openAIAssistantChat(): void {
|
||||
mobx.action(() => {
|
||||
this.setInputPopUpType("aichat");
|
||||
this.aIChatShow.set(true);
|
||||
this.historyShow.set(false);
|
||||
this.infoShow.set(false);
|
||||
this.setAIChatFocus();
|
||||
})();
|
||||
}
|
||||
|
||||
// pass true to give focus to the input (e.g. if this is an 'active' close of the chat)
|
||||
// when resetting the input (when switching screens, don't give focus)
|
||||
closeAIAssistantChat(giveFocus: boolean): void {
|
||||
if (!this.aIChatShow.get()) {
|
||||
return;
|
||||
}
|
||||
mobx.action(() => {
|
||||
this.setInputPopUpType("none");
|
||||
this.aIChatShow.set(false);
|
||||
if (giveFocus) {
|
||||
this.giveFocus();
|
||||
}
|
||||
})();
|
||||
this.setActiveAuxView(appconst.InputAuxView_AIChat);
|
||||
}
|
||||
|
||||
clearAIAssistantChat(): void {
|
||||
@ -719,7 +705,7 @@ class InputModel {
|
||||
}
|
||||
|
||||
hasScrollingInfoMsg(): boolean {
|
||||
if (!this.infoShow.get()) {
|
||||
if (this.activeAuxView.get() !== appconst.InputAuxView_Info) {
|
||||
return false;
|
||||
}
|
||||
const info = this.infoMsg.get();
|
||||
@ -742,9 +728,11 @@ class InputModel {
|
||||
|
||||
clearInfoMsg(setNull: boolean): void {
|
||||
this._clearInfoTimeout();
|
||||
|
||||
if (this.getActiveAuxView() == appconst.InputAuxView_Info) {
|
||||
this.setActiveAuxView(null);
|
||||
}
|
||||
mobx.action(() => {
|
||||
this.setHistoryShow(false);
|
||||
this.infoShow.set(false);
|
||||
if (setNull) {
|
||||
this.infoMsg.set(null);
|
||||
}
|
||||
@ -753,20 +741,11 @@ class InputModel {
|
||||
|
||||
toggleInfoMsg(): void {
|
||||
this._clearInfoTimeout();
|
||||
mobx.action(() => {
|
||||
if (this.historyShow.get()) {
|
||||
this.setHistoryShow(false);
|
||||
return;
|
||||
}
|
||||
const isShowing = this.infoShow.get();
|
||||
if (isShowing) {
|
||||
this.infoShow.set(false);
|
||||
} else {
|
||||
if (this.infoMsg.get() != null) {
|
||||
this.infoShow.set(true);
|
||||
}
|
||||
}
|
||||
})();
|
||||
if (this.activeAuxView.get() == appconst.InputAuxView_Info) {
|
||||
this.setActiveAuxView(null);
|
||||
} else if (this.infoMsg.get() != null) {
|
||||
this.setActiveAuxView(appconst.InputAuxView_Info);
|
||||
}
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
@ -804,9 +783,7 @@ class InputModel {
|
||||
|
||||
resetInput(): void {
|
||||
mobx.action(() => {
|
||||
this.setHistoryShow(false);
|
||||
this.closeAIAssistantChat(false);
|
||||
this.infoShow.set(false);
|
||||
this.setActiveAuxView(null);
|
||||
this.inputMode.set(null);
|
||||
this.resetHistory();
|
||||
this.dropModHistory(false);
|
||||
@ -854,7 +831,9 @@ class InputModel {
|
||||
|
||||
resetHistory(): void {
|
||||
mobx.action(() => {
|
||||
this.setHistoryShow(false);
|
||||
if (this.getActiveAuxView() == appconst.InputAuxView_History) {
|
||||
this.setActiveAuxView(null);
|
||||
}
|
||||
this.historyLoading.set(false);
|
||||
this.historyType.set("screen");
|
||||
this.historyItems.set(null);
|
||||
|
@ -1082,7 +1082,7 @@ class Model {
|
||||
this.ws.watchScreen(newActiveSessionId, newActiveScreenId);
|
||||
this.closeTabSettings();
|
||||
const activeScreen = this.getActiveScreen();
|
||||
if (activeScreen != null && activeScreen.getCurRemoteInstance() != null) {
|
||||
if (activeScreen?.getCurRemoteInstance() != null) {
|
||||
setTimeout(() => {
|
||||
GlobalCommandRunner.syncShellState();
|
||||
}, 100);
|
||||
|
1
src/types/custom.d.ts
vendored
1
src/types/custom.d.ts
vendored
@ -15,6 +15,7 @@ declare global {
|
||||
type LineContainerStrs = "main" | "sidebar" | "history";
|
||||
type AppUpdateStatusType = "unavailable" | "ready";
|
||||
type NativeThemeSource = "system" | "light" | "dark";
|
||||
type InputAuxViewType = null | "history" | "info" | "aichat";
|
||||
|
||||
type OV<V> = mobx.IObservableValue<V>;
|
||||
type OArr<V> = mobx.IObservableArray<V>;
|
||||
|
Loading…
Reference in New Issue
Block a user