mirror of
https://github.com/wavetermdev/backup.git
synced 2026-08-05 13:57:07 -07:00
Merge branch 'main' of github.com:wavetermdev/waveterm into red/aichat-sidebar
This commit is contained in:
@@ -1,24 +1,28 @@
|
||||
name: TestDriver.ai Regression Testing (test)
|
||||
|
||||
name: TestDriver.ai Regression Testing
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
branches: ["main"]
|
||||
branches:
|
||||
- main
|
||||
schedule:
|
||||
- cron: "0 21 * * *" # every day at 9pm
|
||||
workflow_dispatch:
|
||||
- cron: 0 21 * * *
|
||||
workflow_dispatch: null
|
||||
|
||||
permissions:
|
||||
contents: read # To allow the action to read repository contents
|
||||
pull-requests: write # To allow the action to create/update pull request comments
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: "TestDriver"
|
||||
name: TestDriver
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: dashcamio/testdriver@main
|
||||
id: testdriver
|
||||
# note that .testdriver/prerun.sh runs before this, so the app has launched already
|
||||
with:
|
||||
version: v2.9.4
|
||||
version: v2.10.2
|
||||
prerun: |
|
||||
rm ~/Desktop/WITH-LOVE-FROM-AMERICA.txt
|
||||
cd ~/actions-runner/_work/testdriver/testdriver/
|
||||
@@ -38,8 +42,24 @@ jobs:
|
||||
echo "Electron Done"
|
||||
exit
|
||||
prompt: |
|
||||
2. click "Create new tab"
|
||||
2. focus the Wave input with the keyboard shorcut Command + I
|
||||
3. type 'ls' into the input
|
||||
4. press return
|
||||
5. validate Wave shows the result of 'ls'
|
||||
1. wait 10 seconds
|
||||
1. click "Continue"
|
||||
1. click "Create new tab"
|
||||
1. validate that overlapping text does not appear in the application
|
||||
1. focus the Wave input with the keyboard shorcut Command + I
|
||||
1. type 'ls' into the input
|
||||
1. press return
|
||||
1. validate Wave shows the result of 'ls'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- uses: peter-evans/create-or-update-comment@v4
|
||||
if: ${{always()}}
|
||||
with:
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
body: |
|
||||
## TestDriver Summary
|
||||
${{ steps.testdriver.outputs.markdown }}
|
||||
${{ steps.testdriver.outputs.summary }}
|
||||
reactions: |
|
||||
+1
|
||||
-1
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
|
||||
# Wave Terminal
|
||||
|
||||
[](https://app.fossa.com/projects/git%2Bgithub.com%2Fwavetermdev%2Fwaveterm?ref=badge_shield)
|
||||
|
||||
Wave is an open-source AI-native terminal built for seamless workflows.
|
||||
|
||||
Wave isn't just another terminal emulator; it's a rethink on how terminals are built. Wave combines command line with the power of the open web to help veteran CLI users and new developers alike.
|
||||
@@ -56,3 +58,7 @@ Find more information in our [Contributions Guide](CONTRIBUTING.md), which inclu
|
||||
|
||||
- [Ways to contribute](CONTRIBUTING.md#contributing-to-wave-terminal)
|
||||
- [Contribution guidelines](CONTRIBUTING.md#before-you-start)
|
||||
|
||||
## License
|
||||
|
||||
Wave Terminal is licensed under the Apache-2.0 License. For more information on our dependencies, see [here](./acknowledgements/README.md).
|
||||
|
||||
@@ -1,20 +1,5 @@
|
||||
# Open-Source Acknowledgements
|
||||
|
||||
We make use of many amazing open-source projects to build Wave Terminal. Here are the links to the latest acknowledgements for each of our components, including license disclaimers for each dependency:
|
||||
We make use of many amazing open-source projects to build Wave Terminal. We automatically generate license reports via FOSSA to comply with the license distribution requirements of our dependencies. Below is a summary of the licenses used by our product. Clicking on the image will take you to the full report on FOSSA's website.
|
||||
|
||||
- [Frontend](./disclaimers/frontend.md)
|
||||
- [Backend](./disclaimers/backend.md)
|
||||
|
||||
## Generating license disclaimers
|
||||
|
||||
The license disclaimers for the backend are generated using the [go-licenses](https://github.com/google/go-licenses) tool. We supply a template file ([`go_licenses_report.tpl`](./go_licenses_report.tpl)) to generate a pretty print of the disclaimers for each dependency. This outputs to the file [`backend.md`](./disclaimers/backend.md).
|
||||
|
||||
The license disclaimers for the frontend are generated using the [`yarn licenses` tool](https://classic.yarnpkg.com/lang/en/docs/cli/licenses/). This outputs to the file [`frontend.md`](./disclaimers/frontend.md).
|
||||
|
||||
These disclaimer files linked above will be periodically regenerated to reflect new dependencies.
|
||||
|
||||
The [`scripthaus.md` file](../scripthaus.md) contains scripts to generate the disclaimers and package them. To manually generate the disclaimers, run the following from the repository root directory:
|
||||
|
||||
```bash
|
||||
scripthaus run generate-license-disclaimers
|
||||
```
|
||||
[](https://app.fossa.com/projects/git%2Bgithub.com%2Fwavetermdev%2Fwaveterm?ref=badge_large)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -1,16 +0,0 @@
|
||||
# Wave Terminal Backend Acknowledgements
|
||||
|
||||
The following sets forth attribution notices for third party software that may be contained in portions of the Wave Terminal product.
|
||||
{{ range . }}
|
||||
## {{ .Name }}
|
||||
|
||||
* Name: {{ .Name }}
|
||||
* Version: {{ .Version }}
|
||||
* License: [{{ .LicenseName }}]({{ .LicenseURL }})
|
||||
|
||||
```txt
|
||||
{{ .LicenseText }}
|
||||
```
|
||||
|
||||
-----
|
||||
{{ end }}
|
||||
@@ -156,7 +156,7 @@
|
||||
--table-border-color: rgba(241, 246, 243, 0.15);
|
||||
--table-thead-border-top-color: rgba(250, 250, 250, 0.1);
|
||||
--table-thead-bright-border-color: rgb(204, 204, 204);
|
||||
--table-thead-bg-color: rgba(250, 250, 250, 0.02);
|
||||
--table-thead-bg-color: rgb(5, 5, 5);
|
||||
--table-tr-border-bottom-color: rgba(241, 246, 243, 0.15);
|
||||
--table-tr-hover-bg-color: rgba(255, 255, 255, 0.06);
|
||||
--table-tr-selected-bg-color: rgb(34, 34, 34);
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
--app-accent-color: rgb(75, 166, 57);
|
||||
--app-accent-bg-color: rgba(75, 166, 57, 0.2);
|
||||
--app-text-color: rgb(0, 0, 0);
|
||||
--app-text-primary-color: rgb(0, 0, 0, 0.9);
|
||||
--app-text-secondary-color: rgb(0, 0, 0, 0.7);
|
||||
--app-text-primary-color: rgb(23, 23, 23);
|
||||
--app-text-secondary-color: rgb(76, 76, 76);
|
||||
--app-border-color: rgb(139 145 138);
|
||||
--app-panel-bg-color: rgb(224, 224, 224);
|
||||
--app-panel-bg-color-dev: rgb(224, 224, 224);
|
||||
@@ -57,6 +57,10 @@
|
||||
--scrollbar-thumb-hover-color: rgba(0, 0, 0, 0.4);
|
||||
--scrollbar-thumb-active-color: rgba(0, 0, 0, 0.5);
|
||||
|
||||
/* table colors */
|
||||
--table-thead-bg-color: rgb(253, 253, 253);
|
||||
--table-tr-selected-bg-color: rgb(216, 216, 216);
|
||||
|
||||
/* line color */
|
||||
--line-actions-bg-color: rgba(0, 0, 0, 0.1);
|
||||
--line-actions-inactive-color: rgba(0, 0, 0, 0.3);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
.clientsettings-view {
|
||||
.content {
|
||||
padding: 14px 18px 0 30px;
|
||||
padding: 14px 18px 14px 30px;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.wave-dropdown {
|
||||
|
||||
@@ -14,6 +14,7 @@ import * as appconst from "@/app/appconst";
|
||||
|
||||
import "./clientsettings.less";
|
||||
import { MainView } from "../common/elements/mainview";
|
||||
import { OverlayScrollbarsComponent } from "overlayscrollbars-react";
|
||||
|
||||
class ClientSettingsKeybindings extends React.Component<{}, {}> {
|
||||
componentDidMount() {
|
||||
@@ -251,7 +252,12 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
|
||||
const curSudoPwClearOnSleep = GlobalModel.getSudoPwClearOnSleep();
|
||||
|
||||
return (
|
||||
<MainView className="clientsettings-view" title="Client Settings" onClose={this.handleClose}>
|
||||
<MainView
|
||||
className="clientsettings-view"
|
||||
title="Client Settings"
|
||||
onClose={this.handleClose}
|
||||
scrollable={true}
|
||||
>
|
||||
<If condition={!isHidden}>
|
||||
<ClientSettingsKeybindings></ClientSettingsKeybindings>
|
||||
</If>
|
||||
|
||||
@@ -40,7 +40,8 @@
|
||||
}
|
||||
|
||||
.mainview-content {
|
||||
padding-top: 14px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ import cn from "classnames";
|
||||
import { GlobalModel } from "@/models";
|
||||
|
||||
import "./mainview.less";
|
||||
import { Choose, If, Otherwise, When } from "tsx-control-statements/components";
|
||||
import { OverlayScrollbarsComponent } from "overlayscrollbars-react";
|
||||
|
||||
@mobxReact.observer
|
||||
class MainView extends React.Component<{
|
||||
@@ -14,6 +16,8 @@ class MainView extends React.Component<{
|
||||
onClose: () => void;
|
||||
children: React.ReactNode;
|
||||
className?: string;
|
||||
scrollable?: boolean;
|
||||
onScrollbarInitialized?: () => void;
|
||||
}> {
|
||||
render() {
|
||||
const sidebarModel = GlobalModel.mainSidebarModel;
|
||||
@@ -31,7 +35,21 @@ class MainView extends React.Component<{
|
||||
</div>
|
||||
</header>
|
||||
</div>
|
||||
<div className="mainview-content">{this.props.children}</div>
|
||||
<Choose>
|
||||
<When condition={this.props.scrollable}>
|
||||
<OverlayScrollbarsComponent
|
||||
className="mainview-content"
|
||||
options={{ scrollbars: { autoHide: "leave" } }}
|
||||
defer={true}
|
||||
events={{ initialized: this.props.onScrollbarInitialized }}
|
||||
>
|
||||
{this.props.children}
|
||||
</OverlayScrollbarsComponent>
|
||||
</When>
|
||||
<Otherwise>
|
||||
<div className="mainview-content">{this.props.children}</div>
|
||||
</Otherwise>
|
||||
</Choose>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
}
|
||||
|
||||
button {
|
||||
padding-right: 4px !important;
|
||||
i {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ const ModalHeader: React.FC<ModalHeaderProps> = ({ onClose, keybindings, title }
|
||||
</If>
|
||||
{<div className="wave-modal-title">{title}</div>}
|
||||
<If condition={onClose}>
|
||||
<Button className="secondary ghost" onClick={onClose}>
|
||||
<Button className="secondary ghost" onClick={() => onClose()} title="Close (ESC)">
|
||||
<i className="fa-sharp fa-solid fa-xmark"></i>
|
||||
</Button>
|
||||
</If>
|
||||
|
||||
@@ -1,25 +1,24 @@
|
||||
.rconndetail-modal {
|
||||
width: auto;
|
||||
max-width: 80vw;
|
||||
min-height: 565px;
|
||||
|
||||
.wave-modal-content {
|
||||
display: flex;
|
||||
padding-bottom: 0px;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
flex-shrink: 0;
|
||||
width: auto;
|
||||
max-width: 80vw;
|
||||
max-height: 90vh;
|
||||
|
||||
.wave-modal-body {
|
||||
display: flex;
|
||||
padding: 0px 20px;
|
||||
padding: 20px;
|
||||
align-items: flex-start;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
align-self: stretch;
|
||||
overflow-y: scroll;
|
||||
|
||||
.name-header-actions-wrapper {
|
||||
display: flex;
|
||||
@@ -53,6 +52,7 @@
|
||||
|
||||
.remote-detail {
|
||||
width: 100%;
|
||||
padding-top: 16px;
|
||||
|
||||
.settings-field {
|
||||
display: flex;
|
||||
|
||||
@@ -15,6 +15,7 @@ import * as appconst from "@/app/appconst";
|
||||
|
||||
import "./viewremoteconndetail.less";
|
||||
import { ModalKeybindings } from "../elements/modal";
|
||||
import { OverlayScrollbarsComponent } from "overlayscrollbars-react";
|
||||
|
||||
@mobxReact.observer
|
||||
class ViewRemoteConnDetailModal extends React.Component<{}, {}> {
|
||||
@@ -299,15 +300,33 @@ class ViewRemoteConnDetailModal extends React.Component<{}, {}> {
|
||||
|
||||
return (
|
||||
<Modal className="rconndetail-modal">
|
||||
<ModalKeybindings
|
||||
onOk={() => {
|
||||
if (selectedRemoteStatus == "connecting") {
|
||||
return;
|
||||
}
|
||||
this.handleClose();
|
||||
}}
|
||||
onCancel={() => {
|
||||
if (selectedRemoteStatus == "connecting") {
|
||||
return;
|
||||
}
|
||||
this.handleClose();
|
||||
}}
|
||||
></ModalKeybindings>
|
||||
<Modal.Header title="Connection" onClose={this.handleClose} />
|
||||
<div className="wave-modal-body">
|
||||
<OverlayScrollbarsComponent
|
||||
className="wave-modal-body"
|
||||
options={{ scrollbars: { autoHide: "leave" } }}
|
||||
defer={true}
|
||||
>
|
||||
<div className="name-header-actions-wrapper">
|
||||
<div className="name text-primary name-wrapper">
|
||||
{util.getRemoteName(remote)} {getImportTooltip(remote)}
|
||||
</div>
|
||||
<div className="header-actions">{this.renderHeaderBtns(remote)}</div>
|
||||
</div>
|
||||
<div className="remote-detail" style={{ overflow: "hidden" }}>
|
||||
<div className="remote-detail">
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">Conn Id</div>
|
||||
<div className="settings-input">{remote.remoteid}</div>
|
||||
@@ -381,33 +400,7 @@ class ViewRemoteConnDetailModal extends React.Component<{}, {}> {
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="wave-modal-footer">
|
||||
<ModalKeybindings
|
||||
onOk={() => {
|
||||
if (selectedRemoteStatus == "connecting") {
|
||||
return;
|
||||
}
|
||||
this.handleClose();
|
||||
}}
|
||||
onCancel={() => {
|
||||
if (selectedRemoteStatus == "connecting") {
|
||||
return;
|
||||
}
|
||||
this.handleClose();
|
||||
}}
|
||||
></ModalKeybindings>
|
||||
<Button
|
||||
className="secondary"
|
||||
disabled={selectedRemoteStatus == "connecting"}
|
||||
onClick={this.handleClose}
|
||||
>
|
||||
Cancel
|
||||
</Button>
|
||||
<Button disabled={selectedRemoteStatus == "connecting"} onClick={this.handleClose}>
|
||||
Done
|
||||
</Button>
|
||||
</div>
|
||||
</OverlayScrollbarsComponent>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -9,10 +9,20 @@
|
||||
margin: 20px 50px 20px 20px;
|
||||
}
|
||||
|
||||
.connections-table-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
overflow-y: scroll;
|
||||
max-height: 85vh;
|
||||
width: fit-content;
|
||||
max-width: 970px;
|
||||
}
|
||||
|
||||
.connections-table {
|
||||
margin: 0px 10px 10px 10px;
|
||||
table-layout: fixed;
|
||||
max-width: 970px;
|
||||
position: relative;
|
||||
|
||||
colgroup {
|
||||
.first-col {
|
||||
@@ -28,13 +38,16 @@
|
||||
|
||||
thead {
|
||||
border-radius: var(--sizing-2-xs, 4px);
|
||||
border-bottom: 2px solid var(--table-thead-bright-border-color);
|
||||
user-select: none;
|
||||
|
||||
th {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
height: 32px;
|
||||
padding: 5px 15px 5px 10px;
|
||||
color: var(--app-text-color);
|
||||
border-bottom: 2px solid var(--table-thead-bright-border-color);
|
||||
background: var(--table-thead-bg-color);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,8 +91,10 @@
|
||||
|
||||
footer {
|
||||
margin-left: 10px;
|
||||
margin-top: 10px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-shrink: 0;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import * as util from "@/util/util";
|
||||
|
||||
import "./connections.less";
|
||||
import { MainView } from "../common/elements/mainview";
|
||||
import { OverlayScrollbarsComponent } from "overlayscrollbars-react";
|
||||
|
||||
class ConnectionsKeybindings extends React.Component<{}, {}> {
|
||||
componentDidMount() {
|
||||
@@ -149,57 +150,63 @@ class ConnectionsView extends React.Component<{ model: RemotesModel }, { hovered
|
||||
<If condition={!isHidden}>
|
||||
<ConnectionsKeybindings></ConnectionsKeybindings>
|
||||
</If>
|
||||
<table
|
||||
className="connections-table"
|
||||
cellSpacing="0"
|
||||
cellPadding="0"
|
||||
border={0}
|
||||
ref={this.tableRef}
|
||||
onMouseLeave={this.handleTableHoverLeave}
|
||||
<OverlayScrollbarsComponent
|
||||
className="connections-table-container"
|
||||
options={{ scrollbars: { autoHide: "leave" } }}
|
||||
defer={true}
|
||||
>
|
||||
<colgroup>
|
||||
<col className="first-col" />
|
||||
<col className="second-col" />
|
||||
<col className="third-col" />
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="text-standard col-name">
|
||||
<div>Name</div>
|
||||
</th>
|
||||
<th className="text-standard col-type">
|
||||
<div>Type</div>
|
||||
</th>
|
||||
<th className="text-standard col-status">
|
||||
<div>Status</div>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<For index="idx" each="item" of={items}>
|
||||
<tr
|
||||
key={item.remoteid}
|
||||
className={cn("connections-item", {
|
||||
hovered: this.state.hoveredItemId === item.remoteid,
|
||||
})}
|
||||
onClick={() => this.handleRead(item.remoteid)} // Moved onClick here
|
||||
>
|
||||
<td className="col-name">
|
||||
<Status status={this.getStatus(item.status)} text=""></Status>
|
||||
{this.getName(item)} {this.getImportSymbol(item)}
|
||||
</td>
|
||||
<td className="col-type">
|
||||
<div>{item.remotetype}</div>
|
||||
</td>
|
||||
<td className="col-status">
|
||||
<div>
|
||||
<Status status={this.getStatus(item.status)} text={item.status} />
|
||||
</div>
|
||||
</td>
|
||||
<table
|
||||
className="connections-table"
|
||||
cellSpacing="0"
|
||||
cellPadding="0"
|
||||
border={0}
|
||||
ref={this.tableRef}
|
||||
onMouseLeave={this.handleTableHoverLeave}
|
||||
>
|
||||
<colgroup>
|
||||
<col className="first-col" />
|
||||
<col className="second-col" />
|
||||
<col className="third-col" />
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="text-standard col-name">
|
||||
<div>Name</div>
|
||||
</th>
|
||||
<th className="text-standard col-type">
|
||||
<div>Type</div>
|
||||
</th>
|
||||
<th className="text-standard col-status">
|
||||
<div>Status</div>
|
||||
</th>
|
||||
</tr>
|
||||
</For>
|
||||
</tbody>
|
||||
</table>
|
||||
</thead>
|
||||
<tbody>
|
||||
<For index="idx" each="item" of={items}>
|
||||
<tr
|
||||
key={item.remoteid}
|
||||
className={cn("connections-item", {
|
||||
hovered: this.state.hoveredItemId === item.remoteid,
|
||||
})}
|
||||
onClick={() => this.handleRead(item.remoteid)} // Moved onClick here
|
||||
>
|
||||
<td className="col-name">
|
||||
<Status status={this.getStatus(item.status)} text=""></Status>
|
||||
{this.getName(item)} {this.getImportSymbol(item)}
|
||||
</td>
|
||||
<td className="col-type">
|
||||
<div>{item.remotetype}</div>
|
||||
</td>
|
||||
<td className="col-status">
|
||||
<div>
|
||||
<Status status={this.getStatus(item.status)} text={item.status} />
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</For>
|
||||
</tbody>
|
||||
</table>
|
||||
</OverlayScrollbarsComponent>
|
||||
<footer>
|
||||
<Button
|
||||
className="secondary"
|
||||
|
||||
@@ -260,8 +260,8 @@ class MainSideBar extends React.Component<MainSideBarProps, {}> {
|
||||
<div className="logo">
|
||||
<WaveLogo />
|
||||
</div>
|
||||
<div className="close-button">
|
||||
<i className="fa-sharp fa-solid fa-xmark-large" onClick={toggleCollapse} />
|
||||
<div className="close-button" onClick={toggleCollapse}>
|
||||
<i className="fa-sharp fa-solid fa-xmark-large" />
|
||||
</div>
|
||||
</div>
|
||||
<div className="contents">
|
||||
|
||||
@@ -61,9 +61,11 @@ class AIChat extends React.Component<{}, {}> {
|
||||
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
mobx.makeObservable(this);
|
||||
this.chatWindowScrollRef = React.createRef();
|
||||
this.textAreaRef = React.createRef();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
const inputModel = GlobalModel.inputModel;
|
||||
if (this.chatWindowScrollRef?.current != null) {
|
||||
@@ -88,7 +90,7 @@ class AIChat extends React.Component<{}, {}> {
|
||||
}
|
||||
|
||||
submitChatMessage(messageStr: string) {
|
||||
const curLine = GlobalModel.inputModel.getCurLine();
|
||||
const curLine = GlobalModel.inputModel.curLine;
|
||||
const prtn = GlobalModel.submitChatInfoCommand(messageStr, curLine, false);
|
||||
prtn.then((rtn) => {
|
||||
if (!rtn.success) {
|
||||
@@ -103,15 +105,19 @@ class AIChat extends React.Component<{}, {}> {
|
||||
return { numLines, linePos };
|
||||
}
|
||||
|
||||
@mobx.action.bound
|
||||
onTextAreaFocused(e: any) {
|
||||
GlobalModel.inputModel.setAuxViewFocus(true);
|
||||
this.onTextAreaChange(e);
|
||||
}
|
||||
|
||||
@mobx.action.bound
|
||||
onTextAreaBlur(e: any) {
|
||||
GlobalModel.inputModel.setAuxViewFocus(false);
|
||||
//GlobalModel.inputModel.setAuxViewFocus(false);
|
||||
}
|
||||
|
||||
// Adjust the height of the textarea to fit the text
|
||||
@boundMethod
|
||||
onTextAreaChange(e: any) {
|
||||
// Calculate the bounding height of the text area
|
||||
const textAreaMaxLines = 4;
|
||||
@@ -126,6 +132,9 @@ class AIChat extends React.Component<{}, {}> {
|
||||
// Set the new height of the text area, bounded by the min and max height.
|
||||
const newHeight = Math.min(Math.max(scrollHeight, textAreaMinHeight), textAreaMaxHeight);
|
||||
this.textAreaRef.current.style.height = newHeight + "px";
|
||||
}
|
||||
|
||||
onTextAreaInput(e: any) {
|
||||
GlobalModel.inputModel.codeSelectDeselectAll();
|
||||
}
|
||||
|
||||
@@ -140,8 +149,10 @@ class AIChat extends React.Component<{}, {}> {
|
||||
this.submitChatMessage(messageStr);
|
||||
currentRef.value = "";
|
||||
} else {
|
||||
inputModel.grabCodeSelectSelection();
|
||||
inputModel.setAuxViewFocus(false);
|
||||
mobx.action(() => {
|
||||
inputModel.grabCodeSelectSelection();
|
||||
inputModel.setAuxViewFocus(false);
|
||||
})();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,7 +193,6 @@ class AIChat extends React.Component<{}, {}> {
|
||||
return true;
|
||||
}
|
||||
|
||||
@mobx.action
|
||||
@boundMethod
|
||||
onKeyDown(e: any) {}
|
||||
|
||||
@@ -254,9 +264,10 @@ class AIChat extends React.Component<{}, {}> {
|
||||
autoComplete="off"
|
||||
autoCorrect="off"
|
||||
id="chat-cmd-input"
|
||||
onFocus={this.onTextAreaFocused.bind(this)}
|
||||
onBlur={this.onTextAreaBlur.bind(this)}
|
||||
onChange={this.onTextAreaChange.bind(this)}
|
||||
onFocus={this.onTextAreaFocused}
|
||||
onBlur={this.onTextAreaBlur}
|
||||
onChange={this.onTextAreaChange}
|
||||
onInput={this.onTextAreaInput}
|
||||
onKeyDown={this.onKeyDown}
|
||||
style={{ fontSize: this.termFontSize }}
|
||||
className="chat-textarea"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user