Compare commits

..

6 Commits

Author SHA1 Message Date
Evan Simkowitz 9835d3ecd3 save work 2024-04-01 12:19:20 -07:00
Evan Simkowitz 919639a2c4 let crusade 2024-03-29 20:03:58 -07:00
Evan Simkowitz c4589c4cff Save work, everything working except tab bar reorder group 2024-03-29 20:00:04 -07:00
Evan Simkowitz 664db7ff6c save work 2024-03-29 19:55:53 -07:00
Evan Simkowitz 22338d8249 save work 2024-03-29 19:05:45 -07:00
Evan Simkowitz 630e46d4ba It works 2024-03-29 17:13:06 -07:00
167 changed files with 24289 additions and 8567 deletions
+12 -51
View File
@@ -1,65 +1,26 @@
name: TestDriver.ai Regression Testing
on:
push:
branches:
- main
branches: ["main"]
pull_request:
branches:
- main
branches: ["main"]
schedule:
- 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
- cron: "0 21 * * *" # every day at 9pm
workflow_dispatch:
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.10.2
prerun: |
rm ~/Desktop/WITH-LOVE-FROM-AMERICA.txt
cd ~/actions-runner/_work/testdriver/testdriver/
brew install go
brew tap scripthaus-dev/scripthaus
brew install scripthaus
npm install -g yarn
scripthaus run build-backend
echo "Yarn"
yarn
echo "Rebuild"
scripthaus run electron-rebuild
echo "Webpack"
scripthaus run webpack-build
echo "Starting Electron"
scripthaus run electron 1>/dev/null 2>&1 &
echo "Electron Done"
exit
prompt: |
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
2. click "Continue"
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'
-6
View File
@@ -9,8 +9,6 @@
# Wave Terminal
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fwavetermdev%2Fwaveterm.svg?type=shield)](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.
@@ -58,7 +56,3 @@ 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).
+17 -2
View File
@@ -1,5 +1,20 @@
# Open-Source Acknowledgements
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.
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:
[![FOSSA Status](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fwavetermdev%2Fwaveterm.svg?type=large)](https://app.fossa.com/projects/git%2Bgithub.com%2Fwavetermdev%2Fwaveterm?ref=badge_large)
- [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
```
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+16
View File
@@ -0,0 +1,16 @@
# 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 }}
+40 -22
View File
@@ -107,12 +107,12 @@
{
"command": "app:openConnectionsView",
"keys": [],
"commandStr": ["/mainview connections"]
"commandStr": "/mainview connections"
},
{
"command": "app:openSettingsView",
"keys": [],
"commandStr": ["/mainview clientsettings"]
"commandStr": "/mainview clientsettings"
},
{
"command": "app:newTab",
@@ -149,39 +149,48 @@
},
{
"command": "app:selectTab-1",
"keys": ["Cmd:1"]
"keys": ["Cmd:1"],
"commandStr":"/screen 1"
},
{
"command": "app:selectTab-2",
"keys": ["Cmd:2"]
"keys": ["Cmd:2"],
"commandStr":"/screen 2"
},
{
"command": "app:selectTab-3",
"keys": ["Cmd:3"]
"keys": ["Cmd:3"],
"commandStr":"/screen 3"
},
{
"command": "app:selectTab-4",
"keys": ["Cmd:4"]
"keys": ["Cmd:4"],
"commandStr":"/screen 4"
},
{
"command": "app:selectTab-5",
"keys": ["Cmd:5"]
"keys": ["Cmd:5"],
"commandStr":"/screen 5"
},
{
"command": "app:selectTab-6",
"keys": ["Cmd:6"]
"keys": ["Cmd:6"],
"commandStr":"/screen 6"
},
{
"command": "app:selectTab-7",
"keys": ["Cmd:7"]
"keys": ["Cmd:7"],
"commandStr":"/screen 7"
},
{
"command": "app:selectTab-8",
"keys": ["Cmd:8"]
"keys": ["Cmd:8"],
"commandStr":"/screen 8"
},
{
"command": "app:selectTab-9",
"keys": ["Cmd:9"]
"keys": ["Cmd:9"],
"commandStr":"/screen 9"
},
{
"command": "app:selectTabLeft",
@@ -193,39 +202,48 @@
},
{
"command": "app:selectWorkspace-1",
"keys": ["Cmd:Ctrl:1"]
"keys": ["Cmd:Ctrl:1"],
"commandStr": "/session 1"
},
{
"command": "app:selectWorkspace-2",
"keys": ["Cmd:Ctrl:2"]
"keys": ["Cmd:Ctrl:2"],
"commandStr": "/session 2"
},
{
"command": "app:selectWorkspace-3",
"keys": ["Cmd:Ctrl:3"]
"keys": ["Cmd:Ctrl:3"],
"commandStr": "/session 3"
},
{
"command": "app:selectWorkspace-4",
"keys": ["Cmd:Ctrl:4"]
"keys": ["Cmd:Ctrl:4"],
"commandStr": "/session 4"
},
{
"command": "app:selectWorkspace-5",
"keys": ["Cmd:Ctrl:5"]
"keys": ["Cmd:Ctrl:5"],
"commandStr": "/session 5"
},
{
"command": "app:selectWorkspace-6",
"keys": ["Cmd:Ctrl:6"]
"keys": ["Cmd:Ctrl:6"],
"commandStr": "/session 6"
},
{
"command": "app:selectWorkspace-7",
"keys": ["Cmd:Ctrl:7"]
"keys": ["Cmd:Ctrl:7"],
"commandStr": "/session 7"
},
{
"command": "app:selectWorkspace-8",
"keys": ["Cmd:Ctrl:8"]
"keys": ["Cmd:Ctrl:8"],
"commandStr": "/session 8"
},
{
"command": "app:selectWorkspace-9",
"keys": ["Cmd:Ctrl:9"]
"keys": ["Cmd:Ctrl:9"],
"commandStr": "/session 9"
},
{
"command": "app:toggleSidebar",
@@ -238,7 +256,7 @@
{
"command": "app:openBookmarksView",
"keys": ["Cmd:b"],
"commandStr": ["/bookmarks:show"]
"commandStr": "/bookmarks:show"
},
{
"command": "bookmarks:edit",
@@ -283,7 +301,7 @@
{
"command": "cmdinput:openHistory",
"keys": ["Ctrl:r"],
"commandStr": ["/history"]
"commandStr": "/history"
},
{
"command": "cmdinput:openAIChat",
+10 -13
View File
@@ -6,7 +6,7 @@
},
"productName": "Wave",
"description": "An Open-Source, AI-Native, Terminal Built for Seamless Workflows",
"version": "0.7.4",
"version": "0.7.2",
"main": "dist/emain.js",
"license": "Apache-2.0",
"repository": {
@@ -18,7 +18,6 @@
"appId": "dev.commandline.waveterm"
},
"dependencies": {
"@lexical/react": "^0.14.3",
"@monaco-editor/react": "^4.5.1",
"@table-nav/core": "^0.0.7",
"@table-nav/react": "^0.0.7",
@@ -32,17 +31,17 @@
"electron-squirrel-startup": "^1.0.0",
"electron-updater": "^6.1.8",
"framer-motion": "^10.16.16",
"lexical": "0.14.5",
"mobx": "6.12",
"mobx-react": "^7.5.0",
"monaco-editor": "0.48.0",
"mobx-react": "^9.1.1",
"monaco-editor": "^0.44.0",
"mustache": "^4.2.0",
"node-fetch": "^3.2.10",
"overlayscrollbars": "^2.6.1",
"overlayscrollbars-react": "^0.5.5",
"papaparse": "^5.4.1",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"preact": "^10.20.1",
"react": "npm:@preact/compat",
"react-dom": "npm:@preact/compat",
"react-markdown": "^9.0.0",
"remark": "^15.0.1",
"remark-gfm": "^4.0.0",
@@ -68,13 +67,11 @@
"@babel/preset-env": "^7.18.2",
"@babel/preset-react": "^7.23.3",
"@babel/preset-typescript": "^7.17.12",
"@electron/rebuild": "^3.6.0",
"@svgr/webpack": "^8.1.0",
"@types/classnames": "^2.3.1",
"@types/electron": "^1.6.10",
"@types/node": "^20.11.0",
"@types/papaparse": "^5.3.10",
"@types/react": "^18.0.12",
"@types/semver": "^7.5.6",
"@types/sprintf-js": "^1.1.3",
"@types/throttle-debounce": "^5.0.1",
@@ -83,8 +80,8 @@
"babel-loader": "^9.1.3",
"babel-plugin-jsx-control-statements": "^4.1.2",
"copy-webpack-plugin": "^12.0.0",
"css-loader": "^7.1.0",
"electron": "^30.0.1",
"css-loader": "^6.7.1",
"electron": "^29.0.1",
"electron-builder": "^24.13.3",
"electron-builder-squirrel-windows": "^24.13.3",
"file-loader": "^6.2.0",
@@ -96,7 +93,7 @@
"prettier": "^2.8.8",
"raw-loader": "^4.0.2",
"react-split-it": "^2.0.0",
"style-loader": "4.0.0",
"style-loader": "^3.3.1",
"typescript": "^5.0.0",
"webpack": "^5.73.0",
"webpack-bundle-analyzer": "^4.10.1",
@@ -108,4 +105,4 @@
"scripts": {
"postinstall": "electron-builder install-app-deps"
}
}
}
+16 -18
View File
@@ -42,19 +42,16 @@
--app-bg-color: black;
--app-accent-color: rgb(88, 193, 66);
--app-accent-bg-color: rgba(88, 193, 66, 0.25);
--app-accent-bg-darker-color: rgba(88, 193, 66, 0.5);
--app-text-color: rgb(211, 215, 207);
--app-text-primary-color: rgb(255, 255, 255);
--app-text-secondary-color: rgb(195, 200, 194);
--app-text-disabled-color: rgb(173, 173, 173);
--app-text-bg-color: rgb(23, 23, 23);
--app-text-bg-disabled-color: rgb(51, 51, 51);
--app-border-color: rgb(51, 51, 51);
--app-maincontent-bg-color: rgb(51, 51, 51);
--app-maincontent-bg-color: #333;
--app-panel-bg-color: rgba(21, 23, 21, 1);
--app-panel-bg-color-dev: rgb(21, 23, 48);
--app-icon-color: rgb(139, 145, 138);
--app-icon-hover-color: rgb(255, 255, 255);
--app-icon-hover-color: #fff;
--app-selected-mask-color: rgba(255, 255, 255, 0.06);
/* global status colors */
@@ -125,18 +122,18 @@
/* line colors */
--line-sidebar-message-color: rgb(196, 160, 0);
--line-background: var(--app-panel-bg-color);
--line-avatar-color: rgb(236, 238, 236);
--line-background: rgba(21, 23, 21, 1);
--line-avatar-color: #eceeec;
--line-text-color: rgb(211, 215, 207);
--line-svg-fill-color: rgb(150, 152, 150);
--line-svg-hover-fill-color: rgb(236, 238, 236);
--line-svg-hover-fill-color: #eceeec;
--line-separator-color: rgb(126, 126, 126);
--line-error-color: var(--app-error-color);
--line-warning-color: var(--app-warning-color);
--line-base-soft-blue-color: rgb(114, 159, 207);
--line-base-soft-blue-color: #729fcf;
--line-active-border-color: var(--app-accent-color);
--line-selected-bg-color: rgba(255, 255, 255, 0.05);
--line-selected-border-left-color: rgb(119, 119, 119);
--line-selected-border-left-color: #777777;
--line-selected-error-border-color: rgba(204, 0, 0, 0.8);
--line-selected-error-bg-color: rgb(19, 4, 3);
--line-error-bg-color: rgba(200, 0, 0, 0.1);
@@ -155,21 +152,22 @@
/* table colors */
--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: rgb(5, 5, 5);
--table-thead-bright-border-color: #ccc;
--table-thead-bg-color: rgba(250, 250, 250, 0.02);
--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);
--table-tr-selected-hover-bg-color: var(--app-maincontent-bg-color);
--table-tr-selected-bg-color: #222;
--table-tr-selected-hover-bg-color: #333;
/* cmdinput colors */
--cmdinput-bg-color: var(--app-text-bg-color);
--cmdinput-textarea-bg-color: #171717;
--cmdinput-text-error-color: var(--term-red);
--cmdinput-history-item-error-color: var(--term-bright-red);
--cmdinput-history-item-selected-error-color: var(--term-bright-red);
--cmdinput-button-bg-color: var(--tab-green);
--cmdinput-disabled-bg-color: var(--app-text-bg-disabled-color);
--cmdinput-history-bg-color: var(--app-bg-color);
--cmdinput-button-bg-color: rgb(88, 193, 66);
--cmdinput-comment-button-bg-color: rgb(57, 113, 255);
--cmdinput-disabled-icon-color: rgb(76, 81, 75, 1);
--cmdinput-history-bg-color: rgb(21, 23, 21, 1);
/* screen view color */
--screen-view-text-caption-color: rgb(139, 145, 138);
+19 -21
View File
@@ -5,20 +5,20 @@
@import url("./term-light.css");
:root {
--app-bg-color: rgb(254, 254, 254);
--app-bg-color: #fefefe;
--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(23, 23, 23);
--app-text-secondary-color: rgb(76, 76, 76);
--app-text-color: #000;
--app-text-primary-color: rgb(0, 0, 0, 0.9);
--app-text-secondary-color: rgb(0, 0, 0, 0.7);
--app-border-color: rgb(139 145 138);
--app-panel-bg-color: rgb(224, 224, 224);
--app-panel-bg-color-dev: rgb(224, 224, 224);
--app-icon-color: rgb(110, 110, 110);
--app-icon-hover-color: rgb(80, 80, 80);
--app-panel-bg-color: #e0e0e0;
--app-panel-bg-color-dev: #e0e0e0;
--app-icon-color: rgb(80, 80, 80);
--app-icon-hover-color: rgb(100, 100, 100);
--app-selected-mask-color: rgba(0, 0, 0, 0.06);
--input-bg-color: rgb(238, 238, 238);
--input-bg-color: #eeeeee;
/* tab color */
--tab-white: rgb(0, 0, 0, 0.6);
@@ -30,8 +30,8 @@
--table-thead-bg-color: rgba(250, 250, 250, 0.15);
--table-tr-border-bottom-color: rgba(0, 0, 0, 0.15);
--table-tr-hover-bg-color: rgba(0, 0, 0, 0.15);
--table-tr-selected-bg-color: rgb(221, 221, 221);
--table-tr-selected-hover-bg-color: rgb(204, 204, 204);
--table-tr-selected-bg-color: #dddddd;
--table-tr-selected-hover-bg-color: #cccccc;
/* form colors */
--form-element-border-color: rgba(0, 0, 0, 0.3);
@@ -41,8 +41,8 @@
--form-element-label-color: rgba(0, 0, 0, 0.6);
--form-element-secondary-color: rgba(0, 0, 0, 0.09);
--form-element-icon-color: rgb(0, 0, 0, 0.6);
--form-element-disabled-text-color: rgb(183, 183, 183);
--form-element-placeholder-color: rgb(183, 183, 183);
--form-element-disabled-text-color: #b7b7b7;
--form-element-placeholder-color: #b7b7b7;
--markdown-bg-color: rgb(0, 0, 0, 0.1);
@@ -50,6 +50,8 @@
--modal-header-bottom-border-color: rgba(0, 0, 0, 0.3);
/* cmd input */
--cmdinput-textarea-bg-color: rgba(0, 0, 0, 0.1);
--cmdinput-textarea-border-color: var(--form-element-border-color);
/* scroll colors */
--scrollbar-background-color: var(--app-bg-color);
@@ -57,24 +59,20 @@
--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);
--line-actions-active-color: rgba(0, 0, 0, 1);
--logo-button-hover-bg-color: rgb(240, 240, 240);
--logo-button-hover-bg-color: #f0f0f0;
--xterm-viewport-border-color: rgba(0, 0, 0, 0.3);
--datepicker-cell-hover-bg-color: rgb(240, 240, 240);
--datepicker-cell-hover-bg-color: #f0f0f0;
--datepicker-cell-other-text-color: rgba(0, 0, 0, 0.3);
--datepicker-header-fade-color: rgba(0, 0, 0, 0.4);
--datepicker-year-header-bg-color: rgb(245, 245, 245);
--datepicker-year-header-border-color: rgb(220, 220, 220);
--datepicker-year-header-bg-color: #f5f5f5;
--datepicker-year-header-border-color: #dcdcdc;
/* toggle colors */
--toggle-thumb-color: var(--app-bg-color);
+3 -3
View File
@@ -44,7 +44,7 @@ rm -rf bin/
rm -rf build/
node_modules/.bin/webpack --env prod
WAVESRV_VERSION=$(node -e 'console.log(require("./version.js"))')
WAVESHELL_VERSION=v0.7
WAVESHELL_VERSION=v0.6
GO_LDFLAGS="-s -w -X main.BuildTime=$(date +'%Y%m%d%H%M')"
function buildWaveShell {
(cd waveshell; CGO_ENABLED=0 GOOS=$1 GOARCH=$2 go build -ldflags="$GO_LDFLAGS" -o ../bin/mshell/mshell-$WAVESHELL_VERSION-$1.$2 main-waveshell.go)
@@ -69,7 +69,7 @@ rm -rf bin/
rm -rf build/
node_modules/.bin/webpack --env prod
WAVESRV_VERSION=$(node -e 'console.log(require("./version.js"))')
WAVESHELL_VERSION=v0.7
WAVESHELL_VERSION=v0.6
GO_LDFLAGS="-s -w -X main.BuildTime=$(date +'%Y%m%d%H%M')"
function buildWaveShell {
(cd waveshell; CGO_ENABLED=0 GOOS=$1 GOARCH=$2 go build -ldflags="$GO_LDFLAGS" -o ../bin/mshell/mshell-$WAVESHELL_VERSION-$1.$2 main-waveshell.go)
@@ -96,7 +96,7 @@ CGO_ENABLED=1 go build -tags "osusergo,netgo,sqlite_omit_load_extension" -ldflag
```bash
# @scripthaus command fullbuild-waveshell
set -e
WAVESHELL_VERSION=v0.7
WAVESHELL_VERSION=v0.6
GO_LDFLAGS="-s -w -X main.BuildTime=$(date +'%Y%m%d%H%M')"
function buildWaveShell {
(cd waveshell; CGO_ENABLED=0 GOOS=$1 GOARCH=$2 go build -ldflags="$GO_LDFLAGS" -o ../bin/mshell/mshell-$WAVESHELL_VERSION-$1.$2 main-waveshell.go)
+44 -65
View File
@@ -4,10 +4,10 @@
import * as React from "react";
import * as mobxReact from "mobx-react";
import * as mobx from "mobx";
import cn from "classnames";
import { boundMethod } from "autobind-decorator";
import { If } from "tsx-control-statements/components";
import dayjs from "dayjs";
import localizedFormat from "dayjs/plugin/localizedFormat";
import { GlobalModel } from "@/models";
import { isBlank } from "@/util/util";
import { WorkspaceView } from "./workspace/workspaceview";
@@ -22,15 +22,15 @@ import { DisconnectedModal, ClientStopModal } from "@/modals";
import { ModalsProvider } from "@/modals/provider";
import { Button } from "@/elements";
import { ErrorBoundary } from "@/common/error/errorboundary";
import { TermStyleList } from "@/elements";
import cn from "classnames";
import "./app.less";
dayjs.extend(localizedFormat);
@mobxReact.observer
class App extends React.Component<{}, {}> {
class App extends React.PureComponent<{}, {}> {
dcWait: OV<boolean> = mobx.observable.box(false, { name: "dcWait" });
mainContentRef: React.RefObject<HTMLDivElement> = React.createRef();
termThemesLoaded: OV<boolean> = mobx.observable.box(false, { name: "termThemesLoaded" });
constructor(props: {}) {
super(props);
@@ -80,13 +80,6 @@ class App extends React.Component<{}, {}> {
rightSidebarModel.saveState(width, false);
}
@boundMethod
handleTermThemesRendered() {
mobx.action(() => {
this.termThemesLoaded.set(true);
})();
}
render() {
const remotesModel = GlobalModel.remotesModel;
const disconnected = !GlobalModel.ws.open.get() || !GlobalModel.waveSrvRunning.get();
@@ -97,8 +90,7 @@ class App extends React.Component<{}, {}> {
// Previously, this is done in sidebar.tsx but it causes flicker when clientData is null cos screen-view shifts around.
// Doing it here fixes the flicker cos app is not rendered until clientData is populated.
// wait for termThemes as well (this actually means that the "connect" packet has been received)
if (clientData == null || GlobalModel.termThemes.get() == null) {
if (clientData == null) {
return null;
}
@@ -126,65 +118,52 @@ class App extends React.Component<{}, {}> {
if (dcWait) {
setTimeout(() => this.updateDcWait(false), 0);
}
// used to force a full reload of the application
const renderVersion = GlobalModel.renderVersion.get();
const mainSidebarCollapsed = GlobalModel.mainSidebarModel.getCollapsed();
const rightSidebarCollapsed = GlobalModel.rightSidebarModel.getCollapsed();
const activeMainView = GlobalModel.activeMainView.get();
const lightDarkClass = GlobalModel.isDarkTheme.get() ? "is-dark" : "is-light";
const mainClassName = cn(
"platform-" + platform,
{
"mainsidebar-collapsed": mainSidebarCollapsed,
"rightsidebar-collapsed": rightSidebarCollapsed,
},
lightDarkClass
);
return (
<>
<TermStyleList onRendered={this.handleTermThemesRendered} />
<div
key={`version- + ${renderVersion}`}
id="main"
className={mainClassName}
onContextMenu={this.handleContextMenu}
>
<If condition={this.termThemesLoaded.get()}>
<If condition={mainSidebarCollapsed}>
<div key="logo-button" className="logo-button-container">
<div className="logo-button-spacer" />
<div className="logo-button" onClick={this.openMainSidebar}>
<img src="public/logos/wave-logo.png" alt="logo" />
</div>
</div>
</If>
<If condition={GlobalModel.isDev && rightSidebarCollapsed && activeMainView == "session"}>
<div className="right-sidebar-triggers">
<Button
className="secondary ghost right-sidebar-trigger"
onClick={this.openRightSidebar}
>
<i className="fa-sharp fa-solid fa-sidebar-flip"></i>
</Button>
</div>
</If>
<div ref={this.mainContentRef} className="main-content">
<MainSideBar parentRef={this.mainContentRef} />
<ErrorBoundary>
<PluginsView />
<WorkspaceView />
<HistoryView />
<BookmarksView />
<ConnectionsView model={remotesModel} />
<ClientSettingsView model={remotesModel} />
</ErrorBoundary>
<RightSideBar parentRef={this.mainContentRef} />
<div
key={"version-" + renderVersion}
id="main"
className={cn(
"platform-" + platform,
{ "mainsidebar-collapsed": mainSidebarCollapsed, "rightsidebar-collapsed": rightSidebarCollapsed },
lightDarkClass
)}
onContextMenu={this.handleContextMenu}
>
<If condition={mainSidebarCollapsed}>
<div key="logo-button" className="logo-button-container">
<div className="logo-button-spacer" />
<div className="logo-button" onClick={this.openMainSidebar}>
<img src="public/logos/wave-logo.png" alt="logo" />
</div>
<ModalsProvider />
</If>
</div>
</If>
<If condition={GlobalModel.isDev && rightSidebarCollapsed && activeMainView == "session"}>
<div className="right-sidebar-triggers">
<Button className="secondary ghost right-sidebar-trigger" onClick={this.openRightSidebar}>
<i className="fa-sharp fa-regular fa-lightbulb"></i>
</Button>
</div>
</If>
<div ref={this.mainContentRef} className="main-content">
<MainSideBar parentRef={this.mainContentRef} />
<ErrorBoundary>
<PluginsView />
<WorkspaceView />
<HistoryView />
<BookmarksView />
<ConnectionsView model={remotesModel} />
<ClientSettingsView model={remotesModel} />
</ErrorBoundary>
<RightSideBar parentRef={this.mainContentRef} />
</div>
</>
<ModalsProvider />
</div>
);
}
}
-8
View File
@@ -46,10 +46,6 @@ export const TabIcons = [
"heart",
"file",
];
export const DefaultSudoPwStore = "on";
export const DefaultSudoPwTimeoutMs = 5 * 60 * 1000;
export const MaxWebSocketSendSize = 64 * 1024 - 100;
// @ts-ignore
export const VERSION = __WAVETERM_VERSION__;
@@ -68,7 +64,3 @@ 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";
+3 -3
View File
@@ -22,7 +22,7 @@ type BookmarkProps = {
bookmark: BookmarkType;
};
class BookmarkKeybindings extends React.Component<{}, {}> {
class BookmarkKeybindings extends React.PureComponent<{}, {}> {
@boundMethod
componentDidMount(): void {
let keybindManager = GlobalModel.keybindManager;
@@ -76,7 +76,7 @@ class BookmarkKeybindings extends React.Component<{}, {}> {
}
@mobxReact.observer
class Bookmark extends React.Component<BookmarkProps, {}> {
class Bookmark extends React.PureComponent<BookmarkProps, {}> {
@boundMethod
handleDeleteClick(): void {
let { bookmark } = this.props;
@@ -232,7 +232,7 @@ class Bookmark extends React.Component<BookmarkProps, {}> {
}
@mobxReact.observer
class BookmarksView extends React.Component<{}, {}> {
class BookmarksView extends React.PureComponent<{}, {}> {
@boundMethod
handleClose() {
GlobalModel.bookmarksModel.closeView();
+1 -2
View File
@@ -1,7 +1,6 @@
.clientsettings-view {
.content {
padding: 14px 18px 14px 30px;
overflow-y: scroll;
padding: 14px 18px 0 30px;
}
.wave-dropdown {
+6 -128
View File
@@ -6,17 +6,15 @@ import * as mobxReact from "mobx-react";
import * as mobx from "mobx";
import { boundMethod } from "autobind-decorator";
import { If } from "tsx-control-statements/components";
import { GlobalModel, GlobalCommandRunner, RemotesModel } from "@/models";
import { GlobalModel, GlobalCommandRunner, RemotesModel, getApi } from "@/models";
import { Toggle, InlineSettingsTextEdit, SettingsError, Dropdown } from "@/common/elements";
import { commandRtnHandler, isBlank } from "@/util/util";
import { getTermThemes } from "@/util/themeutil";
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<{}, {}> {
class ClientSettingsKeybindings extends React.PureComponent<{}, {}> {
componentDidMount() {
let clientSettingsViewModel = GlobalModel.clientSettingsViewModel;
let keybindManager = GlobalModel.keybindManager;
@@ -36,7 +34,7 @@ class ClientSettingsKeybindings extends React.Component<{}, {}> {
}
@mobxReact.observer
class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hoveredItemId: string }> {
class ClientSettingsView extends React.PureComponent<{ model: RemotesModel }, { hoveredItemId: string }> {
errorMessage: OV<string> = mobx.observable.box(null, { name: "ClientSettings-errorMessage" });
@boundMethod
@@ -71,19 +69,7 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
return;
}
const prtn = GlobalCommandRunner.setTheme(themeSource, false);
GlobalModel.getElectronApi().setNativeThemeSource(themeSource);
commandRtnHandler(prtn, this.errorMessage);
}
@boundMethod
handleChangeTermTheme(theme: string): void {
// For root terminal theme, the key is root, otherwise it's either
// sessionId or screenId.
const currTheme = GlobalModel.getTermThemeSettings()["root"];
if (currTheme == theme) {
return;
}
const prtn = GlobalCommandRunner.setRootTermTheme(theme, false);
getApi().setNativeThemeSource(themeSource);
commandRtnHandler(prtn, this.errorMessage);
}
@@ -107,7 +93,7 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
prtn = GlobalCommandRunner.releaseCheckAutoOff(false);
}
commandRtnHandler(prtn, this.errorMessage);
GlobalModel.getElectronApi().changeAutoUpdate(val);
getApi().changeAutoUpdate(val);
}
getFontSizes(): DropdownItem[] {
@@ -158,12 +144,6 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
commandRtnHandler(prtn, this.errorMessage);
}
@boundMethod
inlineUpdateOpenAITimeout(newTimeout: string): void {
const prtn = GlobalCommandRunner.setClientOpenAISettings({ timeout: newTimeout });
commandRtnHandler(prtn, this.errorMessage);
}
@boundMethod
setErrorMessage(msg: string): void {
mobx.action(() => {
@@ -198,35 +178,6 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
GlobalModel.clientSettingsViewModel.closeView();
}
@boundMethod
getSudoPwStoreOptions(): DropdownItem[] {
const sudoCacheSources: DropdownItem[] = [];
sudoCacheSources.push({ label: "On", value: "on" });
sudoCacheSources.push({ label: "Off", value: "off" });
sudoCacheSources.push({ label: "On Without Timeout", value: "notimeout" });
return sudoCacheSources;
}
@boundMethod
handleChangeSudoPwStoreConfig(store: string) {
const prtn = GlobalCommandRunner.setSudoPwStore(store);
commandRtnHandler(prtn, this.errorMessage);
}
@boundMethod
handleChangeSudoPwTimeoutConfig(timeout: string) {
if (Number(timeout) != 0) {
const prtn = GlobalCommandRunner.setSudoPwTimeout(timeout);
commandRtnHandler(prtn, this.errorMessage);
}
}
@boundMethod
handleChangeSudoPwClearOnSleepConfig(clearOnSleep: boolean) {
const prtn = GlobalCommandRunner.setSudoPwClearOnSleep(clearOnSleep);
commandRtnHandler(prtn, this.errorMessage);
}
render() {
const isHidden = GlobalModel.activeMainView.get() != "clientsettings";
if (isHidden) {
@@ -239,25 +190,12 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
const maxTokensStr = String(
openAIOpts.maxtokens == null || openAIOpts.maxtokens == 0 ? 1000 : openAIOpts.maxtokens
);
const aiTimeoutStr = String(
openAIOpts.timeout == null || openAIOpts.timeout == 0 ? 10 : openAIOpts.timeout / 1000
);
const curFontSize = GlobalModel.getTermFontSize();
const curFontFamily = GlobalModel.getTermFontFamily();
const curTheme = GlobalModel.getThemeSource();
const termThemes = getTermThemes(GlobalModel.termThemes.get(), "Wave Default");
const currTermTheme = GlobalModel.getTermThemeSettings()["root"] ?? termThemes[0].label;
const curSudoPwStore = GlobalModel.getSudoPwStore();
const curSudoPwTimeout = String(GlobalModel.getSudoPwTimeout());
const curSudoPwClearOnSleep = GlobalModel.getSudoPwClearOnSleep();
return (
<MainView
className="clientsettings-view"
title="Client Settings"
onClose={this.handleClose}
scrollable={true}
>
<MainView className="clientsettings-view" title="Client Settings" onClose={this.handleClose}>
<If condition={!isHidden}>
<ClientSettingsKeybindings></ClientSettingsKeybindings>
</If>
@@ -295,19 +233,6 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
/>
</div>
</div>
<If condition={termThemes.length > 0}>
<div className="settings-field">
<div className="settings-label">Terminal Theme</div>
<div className="settings-input">
<Dropdown
className="terminal-theme-dropdown"
options={termThemes}
defaultValue={currTermTheme}
onChange={this.handleChangeTermTheme}
/>
</div>
</div>
</If>
<div className="settings-field">
<div className="settings-label">Client ID</div>
<div className="settings-input">{cdata.clientid}</div>
@@ -389,19 +314,6 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
/>
</div>
</div>
<div className="settings-field">
<div className="settings-label">AI Timeout (seconds)</div>
<div className="settings-input">
<InlineSettingsTextEdit
placeholder=""
text={aiTimeoutStr}
value={aiTimeoutStr}
onChange={this.inlineUpdateOpenAITimeout}
maxLength={10}
showIcon={true}
/>
</div>
</div>
<div className="settings-field">
<div className="settings-label">Global Hotkey</div>
<div className="settings-input">
@@ -413,40 +325,6 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
/>
</div>
</div>
<div className="settings-field">
<div className="settings-label">Remember Sudo Password</div>
<div className="settings-input">
<Dropdown
className="hotkey-dropdown"
options={this.getSudoPwStoreOptions()}
defaultValue={curSudoPwStore}
onChange={this.handleChangeSudoPwStoreConfig}
/>
</div>
</div>
<div className="settings-field">
<div className="settings-label">Sudo Timeout (Minutes)</div>
<div className="settings-input">
<InlineSettingsTextEdit
placeholder=""
text={curSudoPwTimeout}
value={curSudoPwTimeout}
onChange={this.handleChangeSudoPwTimeoutConfig}
maxLength={6}
showIcon={true}
isNumber={true}
/>
</div>
</div>
<div className="settings-field">
<div className="settings-label">Clear Sudo Password on Sleep</div>
<div className="settings-input">
<Toggle
checked={curSudoPwClearOnSleep}
onChange={this.handleChangeSudoPwClearOnSleepConfig}
/>
</div>
</div>
<SettingsError errorMessage={this.errorMessage} />
</div>
</MainView>
+5 -7
View File
@@ -6,7 +6,7 @@ import "./button.less";
interface ButtonProps {
children: React.ReactNode;
onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;
onClick?: () => void;
disabled?: boolean;
leftIcon?: React.ReactNode;
rightIcon?: React.ReactNode;
@@ -14,24 +14,23 @@ interface ButtonProps {
autoFocus?: boolean;
className?: string;
termInline?: boolean;
title?: string;
}
class Button extends React.Component<ButtonProps> {
class Button extends React.PureComponent<ButtonProps> {
static defaultProps = {
style: {},
className: "primary",
};
@boundMethod
handleClick(e) {
handleClick() {
if (this.props.onClick && !this.props.disabled) {
this.props.onClick(e);
this.props.onClick();
}
}
render() {
const { leftIcon, rightIcon, children, disabled, style, autoFocus, termInline, className, title } = this.props;
const { leftIcon, rightIcon, children, disabled, style, autoFocus, termInline, className } = this.props;
return (
<button
@@ -40,7 +39,6 @@ class Button extends React.Component<ButtonProps> {
disabled={disabled}
style={style}
autoFocus={autoFocus}
title={title}
>
{leftIcon && <span className="icon-left">{leftIcon}</span>}
{children}
+1 -1
View File
@@ -7,7 +7,7 @@ import cn from "classnames";
import "./checkbox.less";
class Checkbox extends React.Component<
class Checkbox extends React.PureComponent<
{
checked?: boolean;
defaultChecked?: boolean;
+1 -1
View File
@@ -11,7 +11,7 @@ import { ReactComponent as CopyIcon } from "@/assets/icons/history/copy.svg";
import "./cmdstrcode.less";
class CmdStrCode extends React.Component<
class CmdStrCode extends React.PureComponent<
{
cmdstr: string;
onUse: () => void;
-7
View File
@@ -1,7 +0,0 @@
.copy-button {
padding: 5px 5px;
.fa-check {
color: var(--app-success-color);
}
}

Some files were not shown because too many files have changed in this diff Show More