Compare commits

..

5 Commits

Author SHA1 Message Date
sawka f1a6dfb249 testing frame component 2024-04-15 22:59:13 -07:00
sawka 6319b26924 basic waveapp json -> react/html functionality sorta working 2024-04-12 16:25:52 -07:00
sawka 41fe49a54c implement ijson commands 2024-04-12 13:16:26 -07:00
sawka e044487489 tested ts ijson 2024-04-12 12:58:53 -07:00
sawka 0fdcd27fee go ijson implementation (tested), ts ijson implemented (untested) 2024-04-12 01:18:05 -07:00
106 changed files with 24194 additions and 5393 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",
+7 -7
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": {
@@ -32,10 +32,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",
@@ -43,6 +43,7 @@
"papaparse": "^5.4.1",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"react-frame-component": "^5.2.6",
"react-markdown": "^9.0.0",
"remark": "^15.0.1",
"remark-gfm": "^4.0.0",
@@ -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",
@@ -83,8 +83,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 +96,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);
+2 -6
View File
@@ -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(23, 23, 23);
--app-text-secondary-color: rgb(76, 76, 76);
--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);
@@ -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>
);
}
}
-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__;
+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 {
+7 -100
View File
@@ -14,7 +14,6 @@ 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() {
@@ -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);
}
@@ -158,12 +158,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 +192,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 +204,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 +343,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 +354,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>
+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