Compare commits

..

86 Commits

Author SHA1 Message Date
Evan Simkowitz 35cf4b6a3b Merge branch 'main' into evan/inshellisense 2024-04-22 13:54:42 -07:00
Evan Simkowitz 899347e90f Merge branch 'main' into evan/inshellisense 2024-04-19 15:08:27 -07:00
Evan Simkowitz c1bd5f5765 fix command execution 2024-04-15 17:22:25 -07:00
Evan Simkowitz b97c7e186d remove unnecessary debugs 2024-04-12 16:07:49 -07:00
Evan Simkowitz 0442fc84d4 update debugs to be more helpful 2024-04-12 16:04:05 -07:00
Evan Simkowitz 27efae3ad5 make the logic less gross 2024-04-12 16:03:27 -07:00
Evan Simkowitz 4d8c2cd242 remove unused import 2024-04-12 15:57:17 -07:00
Evan Simkowitz a560499b58 return filepaths when in doubt 2024-04-12 15:53:54 -07:00
Evan Simkowitz e8b489bcd9 add history and root spec 2024-04-12 15:35:45 -07:00
Evan Simkowitz 31c12c4705 remove and modify debugs 2024-04-11 18:25:35 -07:00
Evan Simkowitz 787bcbc9d8 replace logs with debugs 2024-04-11 18:23:34 -07:00
Evan Simkowitz 985304c9aa demote dotfiles and dotdirs 2024-04-11 18:19:00 -07:00
Evan Simkowitz 13cbfdeb6e fix isEnabled 2024-04-11 18:16:28 -07:00
Evan Simkowitz 53290b47e1 fix bad merge 2024-04-11 18:14:05 -07:00
Evan Simkowitz 4bdd092d33 remove lastCurLine from textareainput 2024-04-11 18:09:28 -07:00
Evan Simkowitz fb2b3dfc6a move import 2024-04-11 18:07:56 -07:00
Evan Simkowitz fa27964d49 move import 2024-04-11 18:06:58 -07:00
Evan Simkowitz 95132011e4 remove import 2024-04-11 18:06:43 -07:00
Evan Simkowitz dae4210b72 rename stuff and add comments 2024-04-11 18:03:04 -07:00
Evan Simkowitz e394ba70a6 move keybinding 2024-04-11 17:55:28 -07:00
Evan Simkowitz 483b2eff6f add right arrow to apply suggestion 2024-04-11 17:54:54 -07:00
Evan Simkowitz 2f4a6fa6e2 Merge branch 'main' into evan/inshellisense 2024-04-11 17:45:24 -07:00
Evan Simkowitz 4af1b19ffd fix lastCurLine 2024-04-11 17:41:11 -07:00
Evan Simkowitz 8b1d930cd6 move import 2024-04-11 17:38:24 -07:00
Evan Simkowitz a4e8648968 add placeholder div if no suggestions 2024-04-11 17:37:50 -07:00
Evan Simkowitz 429ea37419 change onclose 2024-04-11 17:23:16 -07:00
Evan Simkowitz a8f3e356f6 add keybindings 2024-04-11 17:22:51 -07:00
Evan Simkowitz 85235aaad8 move autocomplete to its own model, add more styling to suggestion view 2024-04-11 17:16:22 -07:00
Evan Simkowitz 619cfe4931 rudimentary show all autocomplete 2024-04-11 16:00:52 -07:00
Evan Simkowitz 11f1c3bb70 remove finished todos 2024-04-11 15:50:46 -07:00
Evan Simkowitz 8d140c9920 Add file and folder completions 2024-04-11 15:49:46 -07:00
Evan Simkowitz 205a9d1e2e Merge branch 'main' into evan/inshellisense 2024-04-10 23:11:14 -07:00
Evan Simkowitz d3139d51cf add new license 2024-04-10 22:08:08 -07:00
Evan Simkowitz 5c931de40c fix caching 2024-04-10 21:48:23 -07:00
Evan Simkowitz 497a96bfc2 adds trigger and begins to add caching 2024-04-10 17:20:51 -07:00
Evan Simkowitz 427447c592 Merge branch 'main' into evan/inshellisense 2024-04-09 17:11:25 -07:00
Evan Simkowitz 1fe5d425da set non-transparent colors for light mode, fix fuzzy letters issue with ghost prompt 2024-04-09 17:07:15 -07:00
Evan Simkowitz a395043a1c enforce setting 2024-04-09 16:40:47 -07:00
Evan Simkowitz ff9f9b43b6 Add client setting for autocomplete 2024-04-09 16:29:59 -07:00
Evan Simkowitz 98ba0b46ac clear suggestions in more places 2024-04-09 12:33:16 -07:00
Evan Simkowitz fb3253d018 cache last command 2024-04-09 12:22:27 -07:00
Evan Simkowitz 8d91d156aa handle flicker when deleting chars 2024-04-09 12:09:42 -07:00
Evan Simkowitz b7eec15853 Adding ghost text 2024-04-09 11:57:07 -07:00
Evan Simkowitz 38ff6183a2 get suggestions on typing 2024-04-08 18:47:35 -07:00
Evan Simkowitz 1b1e6edaee Merge branch 'main' into evan/inshellisense 2024-04-08 13:47:17 -07:00
Evan Simkowitz f4aeb92d32 Merge branch 'main' into evan/inshellisense 2024-04-08 13:16:01 -07:00
Evan Simkowitz b780d5b244 Merge branch 'main' into evan/inshellisense 2024-04-08 11:19:25 -07:00
Evan Simkowitz d81a6ed480 Merge branch 'main' into evan/inshellisense 2024-04-05 10:49:22 -07:00
Evan Simkowitz d8393ae50b Merge branch 'main' into evan/inshellisense 2024-04-02 18:48:59 -07:00
Evan Simkowitz 79deb01ea4 save work 2024-04-02 18:48:38 -07:00
Evan Simkowitz 12f9a50686 beginning to add autocomplete to textareainput 2024-04-02 18:35:12 -07:00
Evan Simkowitz 239933be3e Got autocomplete working! 2024-04-02 18:14:49 -07:00
Evan Simkowitz 4692cf698b hook up runtime 2024-04-02 17:13:54 -07:00
Evan Simkowitz 907e87c217 expand cwd 2024-04-02 17:05:14 -07:00
Evan Simkowitz f97bb699a1 plumb timeout to waveshell 2024-04-02 16:57:34 -07:00
Evan Simkowitz 077545ed93 bad merrge 2024-04-02 15:50:46 -07:00
Evan Simkowitz 60d0f0e976 Merge branch 'main' into evan/inshellisense 2024-04-02 15:49:32 -07:00
Evan Simkowitz cd4671e5bb store pointer to syncs 2024-04-02 14:58:39 -07:00
Evan Simkowitz d8a714dd4a ensure only one downstream writer can read from the buffer 2024-04-02 14:28:15 -07:00
Evan Simkowitz e0fa1b2560 document UsePty 2024-04-02 14:19:46 -07:00
Evan Simkowitz 2dffcc9237 add UsePty to EphemeralRunOpts 2024-04-02 14:17:12 -07:00
Evan Simkowitz 70090b8684 add package comment 2024-04-02 14:08:10 -07:00
Evan Simkowitz 3f8952caf4 more naming changes 2024-04-02 14:06:51 -07:00
Evan Simkowitz 15a2486e94 delete unused package 2024-04-02 14:01:57 -07:00
Evan Simkowitz 38aa7016b8 comment 2024-04-02 14:01:03 -07:00
Evan Simkowitz cff353ca94 formatting 2024-04-02 13:59:59 -07:00
Evan Simkowitz 5b440ace65 Making EphemeralWriteCloser into a more generic BufferedPipe 2024-04-02 13:58:56 -07:00
Evan Simkowitz 87de0dbc44 revert waveshell changes 2024-04-01 22:17:44 -07:00
Evan Simkowitz 74839b8e1b env vars are now working 2024-04-01 22:12:58 -07:00
Evan Simkowitz 8a24953a88 fix stdout/stderr 2024-04-01 20:55:23 -07:00
Evan Simkowitz a95854514a Add separate paths for stdout and stderr writers 2024-04-01 20:51:26 -07:00
Evan Simkowitz 229fcf8cd4 got cwd override working 2024-04-01 18:27:18 -07:00
Evan Simkowitz 83542ddab8 clean up code 2024-04-01 17:42:03 -07:00
Evan Simkowitz b520242f04 fixing spaghetti 2024-04-01 17:12:51 -07:00
Evan Simkowitz bc73ed1b6c save debug statements 2024-04-01 16:04:42 -07:00
Evan Simkowitz c4647945a4 fix bad merge 2024-04-01 14:22:23 -07:00
Evan Simkowitz 3db40b1c63 Merge branch 'main' into evan/inshellisense 2024-04-01 14:22:17 -07:00
Evan Simkowitz f6d7c37915 save debugging 2024-03-29 16:54:29 -07:00
Evan Simkowitz a41e866b1f Command pipes thru, triggers infinite loop 2024-03-28 18:44:37 -07:00
Evan Simkowitz a772715ae4 Add EphemeralWriteCloser 2024-03-28 18:02:27 -07:00
Evan Simkowitz d32e2aae05 Merge branch 'main' into evan/inshellisense 2024-03-28 16:24:27 -07:00
Evan Simkowitz 3f9d52a7e4 save work 2024-03-26 16:04:37 -07:00
Evan Simkowitz a239a8d70e Merge branch 'main' into evan/inshellisense 2024-03-26 13:00:21 -07:00
Evan Simkowitz a1bddd971f save work 2024-03-25 17:43:02 -07:00
Evan Simkowitz 722318f57d save work, starting to add backend types 2024-03-25 10:54:27 -07:00
Evan Simkowitz 3b633328a1 initial 2024-03-22 16:01:08 -07:00
106 changed files with 24858 additions and 4795 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",
+8 -7
View File
@@ -6,7 +6,7 @@
},
"productName": "Wave",
"description": "An Open-Source, AI-Native, Terminal Built for Seamless Workflows",
"version": "0.7.5",
"version": "0.7.2",
"main": "dist/emain.js",
"license": "Apache-2.0",
"repository": {
@@ -24,6 +24,7 @@
"@table-nav/react": "^0.0.7",
"@tanstack/match-sorter-utils": "^8.8.4",
"@tanstack/react-table": "^8.10.3",
"@withfig/autocomplete": "^2.652.3",
"autobind-decorator": "^2.4.0",
"base64-js": "^1.5.1",
"classnames": "^2.3.1",
@@ -32,10 +33,10 @@
"electron-squirrel-startup": "^1.0.0",
"electron-updater": "^6.1.8",
"framer-motion": "^10.16.16",
"lexical": "0.14.5",
"lexical": "^0.14.3",
"mobx": "6.12",
"mobx-react": "^7.5.0",
"monaco-editor": "0.48.0",
"monaco-editor": "^0.44.0",
"mustache": "^4.2.0",
"node-fetch": "^3.2.10",
"overlayscrollbars": "^2.6.1",
@@ -68,7 +69,6 @@
"@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",
@@ -80,11 +80,12 @@
"@types/throttle-debounce": "^5.0.1",
"@types/uuid": "^9.0.7",
"@types/webpack-env": "^1.18.3",
"@withfig/autocomplete-types": "^1.30.0",
"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 +97,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",
+1 -1
View File
@@ -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: rgb(5, 5, 5);
--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);
-4
View File
@@ -57,10 +57,6 @@
--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);
+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)
+43 -64
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<{}, {}> {
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-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>
</>
<ModalsProvider />
</div>
);
}
}
+1 -4
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__;
@@ -72,3 +68,4 @@ export const ErrorCode_InvalidCwd = "ERRCWD";
export const InputAuxView_History = "history";
export const InputAuxView_Info = "info";
export const InputAuxView_AIChat = "aichat";
export const InputAuxView_Suggestions = "suggestions";
+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 {
+17 -95
View File
@@ -11,10 +11,9 @@ import { Toggle, InlineSettingsTextEdit, SettingsError, Dropdown } from "@/commo
import { commandRtnHandler, isBlank } from "@/util/util";
import { getTermThemes } from "@/util/themeutil";
import * as appconst from "@/app/appconst";
import { MainView } from "@/common/elements/mainview";
import "./clientsettings.less";
import { MainView } from "../common/elements/mainview";
import { OverlayScrollbarsComponent } from "overlayscrollbars-react";
class ClientSettingsKeybindings extends React.Component<{}, {}> {
componentDidMount() {
@@ -77,13 +76,14 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
@boundMethod
handleChangeTermTheme(theme: string): void {
// For root terminal theme, the key is root, otherwise it's either
// For global terminal theme, the key is global, otherwise it's either
// sessionId or screenId.
const currTheme = GlobalModel.getTermThemeSettings()["root"];
const currTheme = GlobalModel.getTermTheme()["global"];
if (currTheme == theme) {
return;
}
const prtn = GlobalCommandRunner.setRootTermTheme(theme, false);
const prtn = GlobalCommandRunner.setGlobalTermTheme(theme, false);
commandRtnHandler(prtn, this.errorMessage);
}
@@ -110,6 +110,12 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
GlobalModel.getElectronApi().changeAutoUpdate(val);
}
@boundMethod
handleChangeAutocompleteEnabled(val: boolean): void {
const prtn: Promise<CommandRtnType> = GlobalCommandRunner.setAutocompleteEnabled(val);
commandRtnHandler(prtn, this.errorMessage);
}
getFontSizes(): DropdownItem[] {
const availableFontSizes: DropdownItem[] = [];
for (let s = appconst.MinFontSize; s <= appconst.MaxFontSize; s++) {
@@ -158,12 +164,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 +198,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 +210,14 @@ 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();
const termThemes = getTermThemes(GlobalModel.termThemes, "Wave Default");
const currTermTheme = GlobalModel.getTermTheme()["global"] ?? termThemes[0].label;
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>
@@ -389,19 +349,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">
@@ -414,36 +361,11 @@ 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-label">Command Autocomplete</div>
<div className="settings-input">
<Toggle
checked={curSudoPwClearOnSleep}
onChange={this.handleChangeSudoPwClearOnSleepConfig}
checked={cdata.clientopts.autocompleteenabled ?? false}
onChange={this.handleChangeAutocompleteEnabled}
/>
</div>
</div>
+2 -5
View File
@@ -5,7 +5,7 @@
width: 100%;
border: 2px solid var(--form-element-border-color);
border-radius: 6px;
line-height: 20px;
line-height: 22px;
background: var(--form-element-bg-color);
&.no-label {
@@ -63,14 +63,11 @@
display: flex;
min-width: 120px;
padding: 5px 8px;
justify-content: space-between;
align-items: center;
align-self: stretch;
border-radius: 6px;
i {
margin-right: 8px;
}
&-highlighted,
&:hover {
background: rgba(241, 246, 243, 0.08);
+8 -17
View File
@@ -163,7 +163,7 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
if (isOpen) {
const option = options[highlightedIndex];
if (option) {
this.handleSelect(option, undefined);
this.handleSelect(option.value, undefined);
}
} else {
this.toggleDropdown();
@@ -185,19 +185,18 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
handleKeyDown(event: React.KeyboardEvent) {}
@boundMethod
handleSelect({ value, noop }: DropdownItem, event?: React.MouseEvent | React.KeyboardEvent) {
handleSelect(value: string, event?: React.MouseEvent | React.KeyboardEvent) {
const { onChange } = this.props;
if (event) {
event.stopPropagation(); // This stops the event from bubbling up to the wrapper
}
if (!("value" in this.props)) {
this.setState({ internalValue: value });
}
onChange(value);
this.setState({ isOpen: false, isTouched: true });
this.unregisterKeybindings();
if (!("value" in this.props) && !noop) {
this.setState({ internalValue: value });
}
}
@boundMethod
@@ -246,11 +245,10 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
className={cn("wave-dropdown-item unselectable", {
"wave-dropdown-item-highlighted": index === highlightedIndex,
})}
onClick={(e) => this.handleSelect(option, e)}
onClick={(e) => this.handleSelect(option.value, e)}
onMouseEnter={() => this.setState({ highlightedIndex: index })}
onMouseLeave={() => this.setState({ highlightedIndex: -1 })}
>
{option.icon && <span className="wave-dropdown-item-icon">{option.icon}</span>}
{option.label}
</div>
))}
@@ -258,11 +256,7 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
document.getElementById("app")!
)
: null;
let selectedOptionLabelStyle = {};
const wrapperClientWidth = this.wrapperRef.current?.clientWidth;
if ((wrapperClientWidth ?? 0) > 0) {
selectedOptionLabelStyle["width"] = Math.max(wrapperClientWidth - 55, 0);
}
return (
<div
className={cn("wave-dropdown", className, {
@@ -288,10 +282,7 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
</div>
</If>
<div
className={cn("wave-dropdown-display unselectable truncate", {
"offset-left": decoration?.startDecoration,
})}
style={selectedOptionLabelStyle}
className={cn("wave-dropdown-display unselectable", { "offset-left": decoration?.startDecoration })}
>
{selectedOptionLabel}
</div>
+1 -1
View File
@@ -8,6 +8,7 @@ export { InputDecoration } from "./inputdecoration";
export { LinkButton } from "./linkbutton";
export { Markdown } from "./markdown";
export { Modal } from "./modal";
export { NumberField } from "./numberfield";
export { PasswordField } from "./passwordfield";
export { ResizableSidebar } from "./resizablesidebar";
export { SettingsError } from "./settingserror";
@@ -17,5 +18,4 @@ export { Toggle } from "./toggle";
export { Tooltip } from "./tooltip";
export { TabIcon } from "./tabicon";
export { DatePicker } from "./datepicker";
export { TermStyleList } from "./termstyle";
export { CopyButton } from "./copybutton";
@@ -22,7 +22,6 @@ class InlineSettingsTextEdit extends React.Component<
maxLength: number;
placeholder: string;
showIcon?: boolean;
isNumber?: boolean;
},
{}
> {
@@ -47,12 +46,6 @@ class InlineSettingsTextEdit extends React.Component<
@boundMethod
handleChangeText(e: any): void {
const isNumber = this.props.isNumber ?? false;
const value = e.target.value;
if (isNumber && value !== "" && !/^\d*$/.test(value)) {
return;
}
mobx.action(() => {
this.tempText.set(e.target.value);
})();
@@ -138,7 +131,7 @@ class InlineSettingsTextEdit extends React.Component<
</div>
<div className="control">
<div
onMouseDown={this.cancelChange}
onClick={this.cancelChange}
title="Cancel (Esc)"
className="button is-prompt-danger is-outlined is-small"
>
@@ -149,7 +142,7 @@ class InlineSettingsTextEdit extends React.Component<
</div>
<div className="control">
<div
onMouseDown={this.confirmChange}
onClick={this.confirmChange}
title="Confirm (Enter)"
className="button is-wave-green is-outlined is-small"
>
+1 -2
View File
@@ -40,8 +40,7 @@
}
.mainview-content {
display: flex;
flex-direction: column;
padding-top: 14px;
}
}

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