mirror of
https://github.com/wavetermdev/backup.git
synced 2026-04-22 15:26:58 -07:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 406afe4a4f |
@@ -1,8 +1,7 @@
|
||||
[
|
||||
{
|
||||
"command": "system:toggleDeveloperTools",
|
||||
"keys": ["Cmd:Option:i"],
|
||||
"info": "Opens the chrome developer tool menu"
|
||||
"keys": ["Cmd:Option:i"]
|
||||
},
|
||||
{
|
||||
"command": "system:hideWindow",
|
||||
@@ -16,62 +15,10 @@
|
||||
"command": "generic:confirm",
|
||||
"keys": ["Enter"]
|
||||
},
|
||||
{
|
||||
"command": "generic:expandTextInput",
|
||||
"keys": ["Shift:Enter", "Ctrl:Enter"]
|
||||
},
|
||||
{
|
||||
"command": "generic:deleteItem",
|
||||
"keys": ["Backspace", "Delete"]
|
||||
},
|
||||
{
|
||||
"command": "generic:space",
|
||||
"keys": ["Space"]
|
||||
},
|
||||
{
|
||||
"command": "generic:tab",
|
||||
"keys": ["Tab"]
|
||||
},
|
||||
{
|
||||
"command": "generic:numpad-0",
|
||||
"keys": ["0"]
|
||||
},
|
||||
{
|
||||
"command": "generic:numpad-1",
|
||||
"keys": ["1"]
|
||||
},
|
||||
{
|
||||
"command": "generic:numpad-2",
|
||||
"keys": ["2"]
|
||||
},
|
||||
{
|
||||
"command": "generic:numpad-3",
|
||||
"keys": ["3"]
|
||||
},
|
||||
{
|
||||
"command": "generic:numpad-4",
|
||||
"keys": ["4"]
|
||||
},
|
||||
{
|
||||
"command": "generic:numpad-5",
|
||||
"keys": ["5"]
|
||||
},
|
||||
{
|
||||
"command": "generic:numpad-6",
|
||||
"keys": ["6"]
|
||||
},
|
||||
{
|
||||
"command": "generic:numpad-7",
|
||||
"keys": ["7"]
|
||||
},
|
||||
{
|
||||
"command": "generic:numpad-8",
|
||||
"keys": ["8"]
|
||||
},
|
||||
{
|
||||
"command": "generic:numpad-9",
|
||||
"keys": ["9"]
|
||||
},
|
||||
{
|
||||
"command": "generic:selectAbove",
|
||||
"keys": ["ArrowUp"]
|
||||
@@ -80,14 +27,6 @@
|
||||
"command": "generic:selectBelow",
|
||||
"keys": ["ArrowDown"]
|
||||
},
|
||||
{
|
||||
"command": "generic:selectLeft",
|
||||
"keys": ["ArrowLeft"]
|
||||
},
|
||||
{
|
||||
"command": "generic:selectRight",
|
||||
"keys": ["ArrowRight"]
|
||||
},
|
||||
{
|
||||
"command": "generic:selectPageAbove",
|
||||
"keys": ["PageUp"]
|
||||
@@ -128,8 +67,7 @@
|
||||
},
|
||||
{
|
||||
"command": "app:restartCommand",
|
||||
"keys": ["Cmd:r"],
|
||||
"info": "Restarts the command running in the current selected line"
|
||||
"keys": ["Cmd:r"]
|
||||
},
|
||||
{
|
||||
"command": "app:restartLastCommand",
|
||||
|
||||
+12
-16
@@ -6,7 +6,7 @@
|
||||
},
|
||||
"productName": "Wave",
|
||||
"description": "An Open-Source, AI-Native, Terminal Built for Seamless Workflows",
|
||||
"version": "0.7.2",
|
||||
"version": "0.7.1",
|
||||
"main": "dist/emain.js",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
@@ -23,6 +23,7 @@
|
||||
"@table-nav/react": "^0.0.7",
|
||||
"@tanstack/match-sorter-utils": "^8.8.4",
|
||||
"@tanstack/react-table": "^8.10.3",
|
||||
"@types/semver": "^7.5.6",
|
||||
"autobind-decorator": "^2.4.0",
|
||||
"base64-js": "^1.5.1",
|
||||
"classnames": "^2.3.1",
|
||||
@@ -36,8 +37,6 @@
|
||||
"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",
|
||||
@@ -46,13 +45,11 @@
|
||||
"remark-gfm": "^4.0.0",
|
||||
"sprintf-js": "^1.1.2",
|
||||
"throttle-debounce": "^5.0.0",
|
||||
"tsx-control-statements": "^5.1.1",
|
||||
"tsx-control-statements": "^4.1.1",
|
||||
"uuid": "^9.0.0",
|
||||
"winston": "^3.8.2",
|
||||
"xterm": "^5.3.0",
|
||||
"xterm-addon-web-links": "^0.9.0",
|
||||
"xterm-addon-serialize": "^0.11.0",
|
||||
"xterm-addon-webgl": "^0.16.0"
|
||||
"xterm": "^5.0.0",
|
||||
"xterm-addon-web-links": "^0.9.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.17.10",
|
||||
@@ -69,25 +66,24 @@
|
||||
"@svgr/webpack": "^8.1.0",
|
||||
"@types/classnames": "^2.3.1",
|
||||
"@types/electron": "^1.6.10",
|
||||
"@types/node": "^20.11.0",
|
||||
"@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",
|
||||
"@types/uuid": "^9.0.7",
|
||||
"@types/uuid": "9.0.7",
|
||||
"@types/webpack-env": "^1.18.3",
|
||||
"babel-loader": "^9.1.3",
|
||||
"babel-plugin-jsx-control-statements": "^4.1.2",
|
||||
"copy-webpack-plugin": "^12.0.0",
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
"css-loader": "^6.7.1",
|
||||
"electron": "^29.0.1",
|
||||
"electron": "29.0.1",
|
||||
"electron-builder": "^24.13.3",
|
||||
"electron-builder-squirrel-windows": "^24.13.3",
|
||||
"file-loader": "^6.2.0",
|
||||
"http-server": "^14.1.1",
|
||||
"less": "^4.1.2",
|
||||
"less-loader": "^12.0.0",
|
||||
"less-loader": "^11.0.0",
|
||||
"lodash-webpack-plugin": "^0.11.6",
|
||||
"mini-css-extract-plugin": "^2.6.0",
|
||||
"prettier": "^2.8.8",
|
||||
@@ -98,11 +94,11 @@
|
||||
"webpack": "^5.73.0",
|
||||
"webpack-bundle-analyzer": "^4.10.1",
|
||||
"webpack-cli": "^5.1.4",
|
||||
"webpack-dev-server": "^5.0.4",
|
||||
"webpack-dev-server": "^4.9.1",
|
||||
"webpack-merge": "^5.8.0",
|
||||
"yaml": "^2.4.0"
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "electron-builder install-app-deps"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@
|
||||
<link rel="stylesheet" href="public/fontawesome/css/sharp-regular.min.css" />
|
||||
<link rel="stylesheet" href="dist-dev/waveterm.css" />
|
||||
|
||||
<link rel="stylesheet" id="theme-stylesheet" href="public/themes/themequery.css" />
|
||||
<link rel="stylesheet" id="theme-stylesheet" href="public/themes/default.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="measure"></div>
|
||||
|
||||
+6
-6
@@ -5,14 +5,14 @@
|
||||
<base href="../" />
|
||||
<script charset="UTF-8" src="dist/waveterm.js"></script>
|
||||
<link rel="stylesheet" href="public/bulma-0.9.4.min.css" />
|
||||
<link rel="stylesheet" href="public/fontawesome/css/fontawesome.min.css" />
|
||||
<link rel="stylesheet" href="public/fontawesome/css/brands.min.css" />
|
||||
<link rel="stylesheet" href="public/fontawesome/css/solid.min.css" />
|
||||
<link rel="stylesheet" href="public/fontawesome/css/sharp-solid.min.css" />
|
||||
<link rel="stylesheet" href="public/fontawesome/css/sharp-regular.min.css" />
|
||||
<link rel="stylesheet" href="public/fontawesome/css/fontawesome.min.css">
|
||||
<link rel="stylesheet" href="public/fontawesome/css/brands.min.css">
|
||||
<link rel="stylesheet" href="public/fontawesome/css/solid.min.css">
|
||||
<link rel="stylesheet" href="public/fontawesome/css/sharp-solid.min.css">
|
||||
<link rel="stylesheet" href="public/fontawesome/css/sharp-regular.min.css">
|
||||
<link rel="stylesheet" href="dist/waveterm.css" />
|
||||
|
||||
<link rel="stylesheet" id="theme-stylesheet" href="public/themes/themequery.css" />
|
||||
<link rel="stylesheet" id="theme-stylesheet" href="public/themes/default.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="measure"></div>
|
||||
|
||||
@@ -67,7 +67,6 @@
|
||||
--scrollbar-background-color: var(--app-bg-color);
|
||||
--scrollbar-thumb-color: rgba(255, 255, 255, 0.3);
|
||||
--scrollbar-thumb-hover-color: rgba(255, 255, 255, 0.5);
|
||||
--scrollbar-thumb-active-color: rgba(255, 255, 255, 0.6);
|
||||
|
||||
/* code color */
|
||||
--pre-bg-color: rgb(0, 0, 0);
|
||||
@@ -87,7 +86,6 @@
|
||||
--form-element-border-color: rgba(241, 246, 243, 0.15);
|
||||
--form-element-bg-color: var(--app-bg-color);
|
||||
--form-element-text-color: var(--app-text-primary-color);
|
||||
--form-element-primary-text-color: var(--app-text-primary-color);
|
||||
--form-element-label-color: var(--app-text-secondary-color);
|
||||
--form-element-primary-color: var(--app-accent-color);
|
||||
--form-element-secondary-color: rgba(255, 255, 255, 0.2);
|
||||
@@ -114,7 +112,7 @@
|
||||
--hotkey-text-color: var(--app-text-secondary-color);
|
||||
|
||||
/* sidebar colors */
|
||||
--sidebar-highlight-color: var(--app-accent-bg-color);
|
||||
--sidebar-highlight-color: rgba(241, 246, 243, 0.08);
|
||||
--sidebar-font-size: 15px;
|
||||
--sidebar-line-height: 1.5;
|
||||
--sidebar-font-weight: normal;
|
||||
@@ -188,11 +186,4 @@
|
||||
--datepicker-header-fade-color: rgba(255, 255, 255, 0.4);
|
||||
--datepicker-year-header-bg-color: rgba(255, 255, 255, 0.2); /* Light grey background */
|
||||
--datepicker-year-header-border-color: rgba(241, 246, 243, 0.15); /* Light grey border */
|
||||
|
||||
/* OverlayScrollbars styling */
|
||||
.os-scrollbar {
|
||||
--os-handle-bg: var(--scrollbar-thumb-color);
|
||||
--os-handle-bg-hover: var(--scrollbar-thumb-hover-color);
|
||||
--os-handle-bg-active: var(--scrollbar-thumb-active-color);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
/* Copyright 2024, Command Line Inc.
|
||||
SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
@import url("./term-default.css");
|
||||
@import url("./term-light.css");
|
||||
@import "./default.css";
|
||||
@import "./term-default.css";
|
||||
@import "./term-light.css";
|
||||
|
||||
:root {
|
||||
--app-bg-color: #fefefe;
|
||||
@@ -24,6 +25,11 @@
|
||||
--tab-white: rgb(0, 0, 0, 0.6);
|
||||
--tab-mint: rgb(70, 235, 156);
|
||||
|
||||
/* button colors */
|
||||
--button-text-color: rgb(50, 50, 50); /* Dark gray for light theme */
|
||||
--button-primary-color: #fefefe;
|
||||
--button-secondary-bg-color: rgba(200, 200, 200, 0.3); /* Semi-transparent light gray */
|
||||
|
||||
/* table colors */
|
||||
--table-thead-border-top-color: rgba(0, 0, 0, 0.2);
|
||||
--table-thead-border-bottom-color: rgba(0, 0, 0, 0.3);
|
||||
@@ -36,8 +42,7 @@
|
||||
/* form colors */
|
||||
--form-element-border-color: rgba(0, 0, 0, 0.3);
|
||||
--form-element-bg-color: var(--app-bg-color);
|
||||
--form-element-text-color: var(--app-text-primary-color);
|
||||
--form-element-primary-text-color: var(--app-text-primary-color);
|
||||
--form-element-text-color: var(--app-text-color);
|
||||
--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);
|
||||
@@ -57,7 +62,6 @@
|
||||
--scrollbar-background-color: var(--app-bg-color);
|
||||
--scrollbar-thumb-color: rgba(0, 0, 0, 0.2);
|
||||
--scrollbar-thumb-hover-color: rgba(0, 0, 0, 0.4);
|
||||
--scrollbar-thumb-active-color: rgba(0, 0, 0, 0.5);
|
||||
|
||||
/* line color */
|
||||
--line-actions-bg-color: rgba(0, 0, 0, 0.1);
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
@import url("./default.css") screen;
|
||||
|
||||
@import url("./light.css") screen and (prefers-color-scheme: light);
|
||||
+3
-3
@@ -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.6
|
||||
WAVESHELL_VERSION=v0.5
|
||||
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.6
|
||||
WAVESHELL_VERSION=v0.5
|
||||
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.6
|
||||
WAVESHELL_VERSION=v0.5
|
||||
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)
|
||||
|
||||
+39
-77
@@ -251,13 +251,6 @@ input[type="checkbox"] {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.flex-centered-column {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
a.a-block {
|
||||
display: block;
|
||||
}
|
||||
@@ -793,75 +786,6 @@ a.a-block {
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.conn-dropdown {
|
||||
width: 412px;
|
||||
|
||||
.lefticon {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 16px;
|
||||
transform: translateY(-50%);
|
||||
|
||||
.globe-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
flex-shrink: 0;
|
||||
fill: var(--app-text-secondary-color);
|
||||
}
|
||||
|
||||
.status-icon {
|
||||
position: absolute;
|
||||
left: 7px;
|
||||
top: 8px;
|
||||
circle {
|
||||
stroke: var(--app-bg-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.wave-dropdown-display {
|
||||
bottom: 7px;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-colors,
|
||||
.tab-icons {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
.tab-color-sep,
|
||||
.tab-icon-sep {
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
font-weight: bold;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.tab-color-icon,
|
||||
.tab-icon-icon {
|
||||
width: 1.1em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.tab-color-name,
|
||||
.tab-icon-name {
|
||||
display: inline-block;
|
||||
margin-left: 1em;
|
||||
min-width: 70px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.tab-color-select,
|
||||
.tab-icon-select {
|
||||
cursor: pointer;
|
||||
margin: 3px;
|
||||
&:hover {
|
||||
outline: 2px solid white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.settings-field {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@@ -923,7 +847,7 @@ a.a-block {
|
||||
}
|
||||
}
|
||||
|
||||
input:not(.wave-input) {
|
||||
input {
|
||||
padding: 4px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
@@ -934,6 +858,44 @@ a.a-block {
|
||||
}
|
||||
}
|
||||
|
||||
.tab-colors,
|
||||
.tab-icons {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
.tab-color-sep,
|
||||
.tab-icon-sep {
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
font-weight: bold;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.tab-color-icon,
|
||||
.tab-icon-icon {
|
||||
width: 1.1em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.tab-color-name,
|
||||
.tab-icon-name {
|
||||
display: inline-block;
|
||||
margin-left: 1em;
|
||||
min-width: 70px;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.tab-color-select,
|
||||
.tab-icon-select {
|
||||
cursor: pointer;
|
||||
margin: 3px;
|
||||
&:hover {
|
||||
outline: 2px solid white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.action-text {
|
||||
margin-left: 20px;
|
||||
|
||||
|
||||
+5
-5
@@ -8,7 +8,7 @@ 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 { GlobalCommandRunner, GlobalModel } from "@/models";
|
||||
import { isBlank } from "@/util/util";
|
||||
import { WorkspaceView } from "./workspace/workspaceview";
|
||||
import { PluginsView } from "./pluginsview/pluginsview";
|
||||
@@ -101,7 +101,7 @@ class App extends React.Component<{}, {}> {
|
||||
return (
|
||||
<div id="main" className={"platform-" + platform} onContextMenu={this.handleContextMenu}>
|
||||
<div ref={this.mainContentRef} className="main-content">
|
||||
<MainSideBar parentRef={this.mainContentRef} />
|
||||
<MainSideBar parentRef={this.mainContentRef} clientData={clientData} />
|
||||
<div className="session-view" />
|
||||
</div>
|
||||
<If condition={dcWait}>
|
||||
@@ -123,7 +123,7 @@ class App extends React.Component<{}, {}> {
|
||||
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 lightDarkClass = GlobalModel.isThemeDark() ? "is-dark" : "is-light";
|
||||
return (
|
||||
<div
|
||||
key={"version-" + renderVersion}
|
||||
@@ -151,7 +151,7 @@ class App extends React.Component<{}, {}> {
|
||||
</div>
|
||||
</If>
|
||||
<div ref={this.mainContentRef} className="main-content">
|
||||
<MainSideBar parentRef={this.mainContentRef} />
|
||||
<MainSideBar parentRef={this.mainContentRef} clientData={clientData} />
|
||||
<ErrorBoundary>
|
||||
<PluginsView />
|
||||
<WorkspaceView />
|
||||
@@ -160,7 +160,7 @@ class App extends React.Component<{}, {}> {
|
||||
<ConnectionsView model={remotesModel} />
|
||||
<ClientSettingsView model={remotesModel} />
|
||||
</ErrorBoundary>
|
||||
<RightSideBar parentRef={this.mainContentRef} />
|
||||
<RightSideBar parentRef={this.mainContentRef} clientData={clientData} />
|
||||
</div>
|
||||
<ModalsProvider />
|
||||
</div>
|
||||
|
||||
@@ -64,12 +64,11 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
handleChangeThemeSource(themeSource: NativeThemeSource): void {
|
||||
if (GlobalModel.getThemeSource() == themeSource) {
|
||||
handleChangeTheme(theme: string): void {
|
||||
if (GlobalModel.getTheme() == theme) {
|
||||
return;
|
||||
}
|
||||
const prtn = GlobalCommandRunner.setTheme(themeSource, false);
|
||||
getApi().setNativeThemeSource(themeSource);
|
||||
const prtn = GlobalCommandRunner.setTheme(theme, false);
|
||||
commandRtnHandler(prtn, this.errorMessage);
|
||||
}
|
||||
|
||||
@@ -112,12 +111,11 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
|
||||
return availableFontFamilies;
|
||||
}
|
||||
|
||||
getThemeSources(): DropdownItem[] {
|
||||
const themeSources: DropdownItem[] = [];
|
||||
themeSources.push({ label: "Dark", value: "dark" });
|
||||
themeSources.push({ label: "Light", value: "light" });
|
||||
themeSources.push({ label: "System", value: "system" });
|
||||
return themeSources;
|
||||
getThemes(): DropdownItem[] {
|
||||
const themes: DropdownItem[] = [];
|
||||
themes.push({ label: "Dark", value: "dark" });
|
||||
themes.push({ label: "Light", value: "light" });
|
||||
return themes;
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
@@ -192,7 +190,7 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
|
||||
);
|
||||
const curFontSize = GlobalModel.getTermFontSize();
|
||||
const curFontFamily = GlobalModel.getTermFontFamily();
|
||||
const curTheme = GlobalModel.getThemeSource();
|
||||
const curTheme = GlobalModel.getTheme();
|
||||
|
||||
return (
|
||||
<MainView className="clientsettings-view" title="Client Settings" onClose={this.handleClose}>
|
||||
@@ -227,9 +225,9 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
|
||||
<div className="settings-input">
|
||||
<Dropdown
|
||||
className="theme-dropdown"
|
||||
options={this.getThemeSources()}
|
||||
options={this.getThemes()}
|
||||
defaultValue={curTheme}
|
||||
onChange={this.handleChangeThemeSource}
|
||||
onChange={this.handleChangeTheme}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -283,7 +281,7 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
|
||||
text={isBlank(openAIOpts.baseurl) ? "openai default" : openAIOpts.baseurl}
|
||||
value={openAIOpts.baseurl ?? ""}
|
||||
onChange={this.inlineUpdateOpenAIBaseURL}
|
||||
maxLength={200}
|
||||
maxLength={10}
|
||||
showIcon={true}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
border-radius: 6px;
|
||||
height: auto;
|
||||
line-height: 1.5;
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
user-select: none;
|
||||
|
||||
@@ -20,17 +21,13 @@
|
||||
}
|
||||
|
||||
&.primary {
|
||||
color: var(--form-element-primary-text-color);
|
||||
color: var(--form-element-text-color);
|
||||
background: var(--form-element-primary-color);
|
||||
i {
|
||||
fill: var(--form-element-text-color);
|
||||
}
|
||||
}
|
||||
|
||||
&.primary.danger {
|
||||
background: var(--app-error-color);
|
||||
}
|
||||
|
||||
&.primary.outlined {
|
||||
background: none;
|
||||
border: 1px solid var(--form-element-primary-color);
|
||||
@@ -40,37 +37,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
&.primary.greyoutlined {
|
||||
background: none;
|
||||
border: 1px solid var(--app-text-secondary-color);
|
||||
|
||||
i {
|
||||
fill: var(--app-text-secondary-color);
|
||||
}
|
||||
}
|
||||
|
||||
&.primary.outlined,
|
||||
&.primary.greyoutlined {
|
||||
&.hover-danger:hover {
|
||||
color: var(--form-element-primary-text-color);
|
||||
border: 1px solid var(--app-error-color);
|
||||
background: var(--app-error-color);
|
||||
}
|
||||
}
|
||||
|
||||
&.primary.outlined.danger {
|
||||
background: none;
|
||||
border: 1px solid var(--app-error-color);
|
||||
|
||||
i {
|
||||
fill: var(--app-error-color);
|
||||
}
|
||||
}
|
||||
|
||||
&.greytext {
|
||||
color: var(--app-text-secondary-color);
|
||||
}
|
||||
|
||||
&.primary.ghost {
|
||||
background: none;
|
||||
i {
|
||||
@@ -78,13 +44,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
&.primary.ghost.danger {
|
||||
background: none;
|
||||
i {
|
||||
fill: var(--app-error-color);
|
||||
}
|
||||
}
|
||||
|
||||
&.secondary {
|
||||
color: var(--form-element-text-color);
|
||||
background: var(--form-element-secondary-color);
|
||||
@@ -98,11 +57,6 @@
|
||||
border: 1px solid var(--form-element-text-color);
|
||||
}
|
||||
|
||||
&.secondary.outlined.danger {
|
||||
background: none;
|
||||
border: 1px solid var(--app-error-color);
|
||||
}
|
||||
|
||||
&.secondary.ghost {
|
||||
background: none;
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: var(--form-element-bg-color);
|
||||
|
||||
input {
|
||||
outline: none !important;
|
||||
@@ -30,7 +29,6 @@
|
||||
height: 100%;
|
||||
padding: 0 !important;
|
||||
cursor: default !important;
|
||||
background-color: inherit !important;
|
||||
}
|
||||
|
||||
.fa-calendar {
|
||||
@@ -101,7 +99,6 @@
|
||||
background-color: var(--datepicker-cell-hover-bg-color);
|
||||
}
|
||||
&.selected {
|
||||
color: var(--form-element-primary-text-color);
|
||||
background-color: var(--form-element-primary-color);
|
||||
font-weight: bold;
|
||||
}
|
||||
@@ -160,7 +157,6 @@
|
||||
}
|
||||
|
||||
&.selected {
|
||||
color: var(--form-element-primary-text-color);
|
||||
background-color: var(--form-element-primary-color);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import React, { useState, useEffect, useRef, createRef } from "react";
|
||||
import * as mobx from "mobx";
|
||||
import ReactDOM from "react-dom";
|
||||
import dayjs from "dayjs";
|
||||
import cn from "classnames";
|
||||
import cs from "classnames";
|
||||
import { Button } from "@/elements";
|
||||
import { If } from "tsx-control-statements/components";
|
||||
import { GlobalModel } from "@/models";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
import "./datepicker.less";
|
||||
|
||||
@@ -39,10 +36,6 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
|
||||
MM: selDate.format("MM"),
|
||||
DD: selDate.format("DD"),
|
||||
});
|
||||
const curUuid = uuidv4();
|
||||
const keybindsRegistered = mobx.observable.box(false, {
|
||||
name: "datepicker-keybinds-registered",
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
inputRefs.current = {
|
||||
@@ -90,6 +83,7 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
|
||||
const newDate = dayjs(date);
|
||||
setSelDate(newDate); // Update selDate with the new dayjs object
|
||||
onSelectDate && onSelectDate(date); // Call parent's onSelectDate
|
||||
setIsOpen(false); // Close the picker
|
||||
};
|
||||
|
||||
const changeMonth = (delta: number) => {
|
||||
@@ -102,7 +96,7 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
|
||||
return (
|
||||
<div className="day-picker-header">
|
||||
<div
|
||||
className={cn({ fade: showYearAccordion })}
|
||||
className={cs({ fade: showYearAccordion })}
|
||||
onClick={() => {
|
||||
if (!showYearAccordion) {
|
||||
setExpandedYear(selDate.year()); // Set expandedYear when opening accordion
|
||||
@@ -111,7 +105,7 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
|
||||
}}
|
||||
>
|
||||
{selDate.format("MMMM YYYY")}
|
||||
<span className={cn("dropdown-arrow", { fade: showYearAccordion })}></span>
|
||||
<span className={cs("dropdown-arrow", { fade: showYearAccordion })}></span>
|
||||
</div>
|
||||
<If condition={!showYearAccordion}>
|
||||
<div className="arrows">
|
||||
@@ -182,9 +176,9 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
|
||||
}
|
||||
|
||||
// Next month's filler days
|
||||
let overFlowIndex = 1;
|
||||
while (days.length < 42) {
|
||||
const dayDate = endDay.add(overFlowIndex++, "day");
|
||||
const fillerDayCount = days.length - daysInPreviousMonth - endDay.date();
|
||||
const dayDate = endDay.add(fillerDayCount + 1, "day");
|
||||
days.push(
|
||||
<div
|
||||
key={`next-month-day-${dayDate.format("YYYY-MM-DD")}`}
|
||||
@@ -250,14 +244,14 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
|
||||
</div>
|
||||
<If condition={expandedYear === year}>
|
||||
<div
|
||||
className={cn("month-container", {
|
||||
className={cs("month-container", {
|
||||
expanded: expandedYear === year,
|
||||
})}
|
||||
>
|
||||
{Array.from({ length: 12 }, (_, i) => i + 1).map((month) => (
|
||||
<div
|
||||
key={month}
|
||||
className={cn("month", {
|
||||
className={cs("month", {
|
||||
selected: year === currentYear && month === selDate.month() + 1,
|
||||
})}
|
||||
onClick={() => handleMonthYearSelect(month, year)}
|
||||
@@ -279,11 +273,6 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
|
||||
setShowYearAccordion(false);
|
||||
};
|
||||
|
||||
const closeModal = () => {
|
||||
setIsOpen(false);
|
||||
setShowYearAccordion(false);
|
||||
};
|
||||
|
||||
const dayPickerModal = isOpen
|
||||
? ReactDOM.createPortal(
|
||||
<div ref={modalRef} className="day-picker-modal" style={calculatePosition()}>
|
||||
@@ -300,7 +289,7 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
|
||||
)
|
||||
: null;
|
||||
|
||||
const handleDatePartChange = (part: string, value: string) => {
|
||||
const handleDatePartChange = (part, value) => {
|
||||
const newDateParts = { ...dateParts, [part]: value };
|
||||
setDateParts(newDateParts);
|
||||
|
||||
@@ -311,13 +300,13 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
|
||||
}
|
||||
};
|
||||
|
||||
const handleArrowNavigation = (key: string, currentPart: string) => {
|
||||
const handleArrowNavigation = (event, currentPart) => {
|
||||
const currentIndex = formatParts.indexOf(currentPart);
|
||||
let targetInput;
|
||||
|
||||
if (key == "ArrowLeft" && currentIndex > 0) {
|
||||
if (event.key === "ArrowLeft" && currentIndex > 0) {
|
||||
targetInput = inputRefs.current[formatParts[currentIndex - 1]].current;
|
||||
} else if (key == "ArrowRight" && currentIndex < formatParts.length - 1) {
|
||||
} else if (event.key === "ArrowRight" && currentIndex < formatParts.length - 1) {
|
||||
targetInput = inputRefs.current[formatParts[currentIndex + 1]].current;
|
||||
}
|
||||
|
||||
@@ -326,86 +315,51 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
|
||||
}
|
||||
};
|
||||
|
||||
const handleKeyDown = (event, currentPart: string) => {};
|
||||
const handleKeyDown = (event, currentPart) => {
|
||||
const key = event.key;
|
||||
|
||||
const handleFocus = (event, part: string) => {
|
||||
event.target.select();
|
||||
registerKeybindings(event, part);
|
||||
};
|
||||
|
||||
const registerKeybindings = (event: any, part: string) => {
|
||||
if (keybindsRegistered.get() == true) {
|
||||
if (key === "ArrowLeft" || key === "ArrowRight") {
|
||||
// Handle arrow navigation without selecting text
|
||||
handleArrowNavigation(event, currentPart);
|
||||
return;
|
||||
}
|
||||
mobx.action(() => {
|
||||
keybindsRegistered.set(true);
|
||||
})();
|
||||
const keybindManager = GlobalModel.keybindManager;
|
||||
const domain = "datepicker-" + curUuid + "-" + part;
|
||||
keybindManager.registerKeybinding("control", domain, "generic:selectLeft", (_) => {
|
||||
handleArrowNavigation("ArrowLeft", part);
|
||||
return true;
|
||||
});
|
||||
keybindManager.registerKeybinding("control", domain, "generic:selectRight", (_) => {
|
||||
handleArrowNavigation("ArrowRight", part);
|
||||
return true;
|
||||
});
|
||||
keybindManager.registerKeybinding("control", domain, "generic:space", (_) => {
|
||||
toggleModal();
|
||||
return true;
|
||||
});
|
||||
keybindManager.registerKeybinding("control", domain, "generic:confirm", (_) => {
|
||||
toggleModal();
|
||||
return true;
|
||||
});
|
||||
keybindManager.registerKeybinding("control", domain, "generic:cancel", (_) => {
|
||||
closeModal();
|
||||
return true;
|
||||
});
|
||||
keybindManager.registerKeybinding("control", domain, "generic:tab", (_) => {
|
||||
handleArrowNavigation("ArrowRight", part);
|
||||
return true;
|
||||
});
|
||||
for (let numpadKey = 0; numpadKey <= 9; numpadKey++) {
|
||||
keybindManager.registerKeybinding("control", domain, "generic:numpad-" + numpadKey.toString(), (_) => {
|
||||
const currentPart = part;
|
||||
const maxLength = currentPart === "YYYY" ? 4 : 2;
|
||||
const newValue = event.target.value.length < maxLength ? event.target.value + numpadKey : numpadKey;
|
||||
let selectionTimeoutId = null;
|
||||
handleDatePartChange(currentPart, newValue);
|
||||
|
||||
// Clear any existing timeout
|
||||
if (selectionTimeoutId !== null) {
|
||||
clearTimeout(selectionTimeoutId);
|
||||
}
|
||||
if (key === " ") {
|
||||
// Handle spacebar press to toggle the modal
|
||||
toggleModal();
|
||||
return;
|
||||
}
|
||||
|
||||
// Re-focus and select the input after state update
|
||||
selectionTimeoutId = setTimeout(() => {
|
||||
event.target.focus();
|
||||
event.target.select();
|
||||
}, 0);
|
||||
return true;
|
||||
});
|
||||
if (key.match(/[0-9]/)) {
|
||||
// Handle numeric keys
|
||||
event.preventDefault();
|
||||
const maxLength = currentPart === "YYYY" ? 4 : 2;
|
||||
const newValue = event.target.value.length < maxLength ? event.target.value + key : key;
|
||||
let selectionTimeoutId = null;
|
||||
handleDatePartChange(currentPart, newValue);
|
||||
|
||||
// Clear any existing timeout
|
||||
if (selectionTimeoutId !== null) {
|
||||
clearTimeout(selectionTimeoutId);
|
||||
}
|
||||
|
||||
// Re-focus and select the input after state update
|
||||
selectionTimeoutId = setTimeout(() => {
|
||||
event.target.focus();
|
||||
event.target.select();
|
||||
}, 0);
|
||||
}
|
||||
};
|
||||
|
||||
const handleBlur = (event, part: string) => {
|
||||
unregisterKeybindings(part);
|
||||
};
|
||||
|
||||
const unregisterKeybindings = (part: string) => {
|
||||
mobx.action(() => {
|
||||
keybindsRegistered.set(false);
|
||||
})();
|
||||
const domain = "datepicker-" + curUuid + "-" + part;
|
||||
GlobalModel.keybindManager.unregisterDomain(domain);
|
||||
const handleFocus = (event) => {
|
||||
event.target.select();
|
||||
};
|
||||
|
||||
// Prevent use from selecting text in the input
|
||||
const handleMouseDown = (event, part: string) => {
|
||||
const handleMouseDown = (event) => {
|
||||
event.preventDefault();
|
||||
|
||||
handleFocus(event, part);
|
||||
handleFocus(event);
|
||||
};
|
||||
|
||||
const handleIconKeyDown = (event) => {
|
||||
@@ -459,9 +413,8 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
|
||||
value={dateParts[part]}
|
||||
onChange={(e) => handleDatePartChange(part, e.target.value)}
|
||||
onKeyDown={(e) => handleKeyDown(e, part)}
|
||||
onMouseDown={(e) => handleMouseDown(e, part)}
|
||||
onFocus={(e) => handleFocus(e, part)}
|
||||
onBlur={(e) => handleBlur(e, part)}
|
||||
onMouseDown={handleMouseDown}
|
||||
onFocus={handleFocus}
|
||||
maxLength={part === "YYYY" ? 4 : 2}
|
||||
className="date-input"
|
||||
placeholder={part}
|
||||
|
||||
@@ -7,8 +7,6 @@ import { boundMethod } from "autobind-decorator";
|
||||
import cn from "classnames";
|
||||
import { If } from "tsx-control-statements/components";
|
||||
import ReactDOM from "react-dom";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { GlobalModel } from "@/models";
|
||||
|
||||
import "./dropdown.less";
|
||||
|
||||
@@ -41,7 +39,6 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
|
||||
wrapperRef: React.RefObject<HTMLDivElement>;
|
||||
menuRef: React.RefObject<HTMLDivElement>;
|
||||
timeoutId: any;
|
||||
curUuid: string;
|
||||
|
||||
constructor(props: DropdownProps) {
|
||||
super(props);
|
||||
@@ -53,7 +50,6 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
|
||||
};
|
||||
this.wrapperRef = React.createRef();
|
||||
this.menuRef = React.createRef();
|
||||
this.curUuid = uuidv4();
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@@ -100,90 +96,56 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
|
||||
|
||||
@boundMethod
|
||||
handleClick() {
|
||||
if (!this.state.isOpen || !this.state.isTouched) {
|
||||
this.registerKeybindings();
|
||||
}
|
||||
this.toggleDropdown();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
handleFocus() {
|
||||
this.setState({ isTouched: true });
|
||||
this.registerKeybindings();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
registerKeybindings() {
|
||||
let keybindManager = GlobalModel.keybindManager;
|
||||
let domain = "dropdown-" + this.curUuid;
|
||||
keybindManager.registerKeybinding("control", domain, "generic:confirm", (waveEvent) => {
|
||||
this.handleConfirm();
|
||||
return true;
|
||||
});
|
||||
keybindManager.registerKeybinding("control", domain, "generic:space", (waveEvent) => {
|
||||
this.handleConfirm();
|
||||
return true;
|
||||
});
|
||||
keybindManager.registerKeybinding("control", domain, "generic:cancel", (waveEvent) => {
|
||||
this.setState({ isOpen: false });
|
||||
this.unregisterKeybindings();
|
||||
return true;
|
||||
});
|
||||
keybindManager.registerKeybinding("control", domain, "generic:selectAbove", (waveEvent) => {
|
||||
const { isOpen } = this.state;
|
||||
const { options } = this.props;
|
||||
if (isOpen) {
|
||||
this.setState((prevState) => ({
|
||||
highlightedIndex:
|
||||
prevState.highlightedIndex > 0 ? prevState.highlightedIndex - 1 : options.length - 1,
|
||||
}));
|
||||
}
|
||||
return true;
|
||||
});
|
||||
keybindManager.registerKeybinding("control", domain, "generic:selectBelow", (waveEvent) => {
|
||||
const { isOpen } = this.state;
|
||||
const { options } = this.props;
|
||||
if (isOpen) {
|
||||
this.setState((prevState) => ({
|
||||
highlightedIndex:
|
||||
prevState.highlightedIndex < options.length - 1 ? prevState.highlightedIndex + 1 : 0,
|
||||
}));
|
||||
}
|
||||
return true;
|
||||
});
|
||||
keybindManager.registerKeybinding("control", domain, "generic:tab", (waveEvent) => {
|
||||
this.setState({ isOpen: false });
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
handleConfirm() {
|
||||
handleKeyDown(event: React.KeyboardEvent) {
|
||||
const { options } = this.props;
|
||||
const { isOpen, highlightedIndex } = this.state;
|
||||
if (isOpen) {
|
||||
const option = options[highlightedIndex];
|
||||
if (option) {
|
||||
this.handleSelect(option.value, undefined);
|
||||
}
|
||||
} else {
|
||||
this.toggleDropdown();
|
||||
|
||||
switch (event.key) {
|
||||
case "Enter":
|
||||
case " ":
|
||||
if (isOpen) {
|
||||
const option = options[highlightedIndex];
|
||||
if (option) {
|
||||
this.handleSelect(option.value, undefined);
|
||||
}
|
||||
} else {
|
||||
this.toggleDropdown();
|
||||
}
|
||||
break;
|
||||
case "Escape":
|
||||
this.setState({ isOpen: false });
|
||||
break;
|
||||
case "ArrowUp":
|
||||
if (isOpen) {
|
||||
this.setState((prevState) => ({
|
||||
highlightedIndex:
|
||||
prevState.highlightedIndex > 0 ? prevState.highlightedIndex - 1 : options.length - 1,
|
||||
}));
|
||||
}
|
||||
break;
|
||||
case "ArrowDown":
|
||||
if (isOpen) {
|
||||
this.setState((prevState) => ({
|
||||
highlightedIndex:
|
||||
prevState.highlightedIndex < options.length - 1 ? prevState.highlightedIndex + 1 : 0,
|
||||
}));
|
||||
}
|
||||
break;
|
||||
case "Tab":
|
||||
this.setState({ isOpen: false });
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
handleBlur() {
|
||||
this.unregisterKeybindings();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
unregisterKeybindings() {
|
||||
let domain = "dropdown-" + this.curUuid;
|
||||
GlobalModel.keybindManager.unregisterDomain(domain);
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
handleKeyDown(event: React.KeyboardEvent) {}
|
||||
|
||||
@boundMethod
|
||||
handleSelect(value: string, event?: React.MouseEvent | React.KeyboardEvent) {
|
||||
const { onChange } = this.props;
|
||||
@@ -196,7 +158,6 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
|
||||
}
|
||||
onChange(value);
|
||||
this.setState({ isOpen: false, isTouched: true });
|
||||
this.unregisterKeybindings();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
@@ -267,8 +228,7 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
|
||||
tabIndex={0}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
onClick={this.handleClick}
|
||||
onFocus={this.handleFocus.bind(this)}
|
||||
onBlur={this.handleBlur.bind(this)}
|
||||
onFocus={this.handleFocus}
|
||||
>
|
||||
{decoration?.startDecoration && <>{decoration.startDecoration}</>}
|
||||
<If condition={label}>
|
||||
|
||||
@@ -8,8 +8,6 @@ import { boundMethod } from "autobind-decorator";
|
||||
import cn from "classnames";
|
||||
import { If } from "tsx-control-statements/components";
|
||||
import { checkKeyPressed, adaptFromReactOrNativeKeyEvent } from "@/util/keyutil";
|
||||
import { GlobalModel } from "@/models";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
|
||||
import "./inlinesettingstextedit.less";
|
||||
|
||||
@@ -29,11 +27,6 @@ class InlineSettingsTextEdit extends React.Component<
|
||||
tempText: OV<string>;
|
||||
shouldFocus: boolean = false;
|
||||
inputRef: React.RefObject<any> = React.createRef();
|
||||
curId: string;
|
||||
|
||||
componentDidMount(): void {
|
||||
this.curId = uuidv4();
|
||||
}
|
||||
|
||||
componentDidUpdate(): void {
|
||||
if (this.shouldFocus) {
|
||||
@@ -59,7 +52,6 @@ class InlineSettingsTextEdit extends React.Component<
|
||||
this.tempText = null;
|
||||
this.props.onChange(newText);
|
||||
})();
|
||||
this.unregisterKeybindings();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
@@ -68,38 +60,24 @@ class InlineSettingsTextEdit extends React.Component<
|
||||
this.isEditing.set(false);
|
||||
this.tempText = null;
|
||||
})();
|
||||
this.unregisterKeybindings();
|
||||
}
|
||||
|
||||
handleFocus() {
|
||||
this.registerKeybindings();
|
||||
}
|
||||
|
||||
registerKeybindings() {
|
||||
let keybindManager = GlobalModel.keybindManager;
|
||||
let domain = "inline-settings" + this.curId;
|
||||
keybindManager.registerKeybinding("control", domain, "generic:confirm", (waveEvent) => {
|
||||
@boundMethod
|
||||
handleKeyDown(e: any): void {
|
||||
let waveEvent = adaptFromReactOrNativeKeyEvent(e);
|
||||
if (checkKeyPressed(waveEvent, "Enter")) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.confirmChange();
|
||||
return true;
|
||||
});
|
||||
keybindManager.registerKeybinding("control", domain, "generic:cancel", (waveEvent) => {
|
||||
return;
|
||||
}
|
||||
if (checkKeyPressed(waveEvent, "Escape")) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.cancelChange();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
unregisterKeybindings() {
|
||||
let domain = "inline-settings" + this.curId;
|
||||
GlobalModel.keybindManager.unregisterDomain(domain);
|
||||
}
|
||||
|
||||
handleBlur() {
|
||||
this.unregisterKeybindings();
|
||||
this.cancelChange();
|
||||
}
|
||||
|
||||
componentWillUnmount(): void {
|
||||
this.unregisterKeybindings();
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
@@ -121,8 +99,7 @@ class InlineSettingsTextEdit extends React.Component<
|
||||
ref={this.inputRef}
|
||||
className="input"
|
||||
type="text"
|
||||
onFocus={this.handleFocus.bind(this)}
|
||||
onBlur={this.handleBlur.bind(this)}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
placeholder={this.props.placeholder}
|
||||
onChange={this.handleChangeText}
|
||||
value={this.tempText.get()}
|
||||
|
||||
@@ -2,26 +2,20 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
import * as React from "react";
|
||||
import * as mobx from "mobx";
|
||||
import { If } from "tsx-control-statements/components";
|
||||
import ReactDOM from "react-dom";
|
||||
import { Button } from "./button";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { GlobalModel } from "@/models";
|
||||
|
||||
import "./modal.less";
|
||||
import { boundMethod } from "autobind-decorator";
|
||||
|
||||
interface ModalHeaderProps {
|
||||
onClose?: () => void;
|
||||
keybindings?: boolean;
|
||||
title: string;
|
||||
}
|
||||
|
||||
const ModalHeader: React.FC<ModalHeaderProps> = ({ onClose, keybindings, title }) => (
|
||||
const ModalHeader: React.FC<ModalHeaderProps> = ({ onClose, title }) => (
|
||||
<div className="wave-modal-header">
|
||||
<If condition={keybindings && onClose}>
|
||||
<ModalKeybindings onCancel={onClose}></ModalKeybindings>
|
||||
</If>
|
||||
{<div className="wave-modal-title">{title}</div>}
|
||||
<If condition={onClose}>
|
||||
<Button className="secondary ghost" onClick={onClose}>
|
||||
@@ -36,56 +30,10 @@ interface ModalFooterProps {
|
||||
onOk?: () => void;
|
||||
cancelLabel?: string;
|
||||
okLabel?: string;
|
||||
keybindings?: boolean;
|
||||
}
|
||||
|
||||
class ModalKeybindings extends React.Component<{ onOk?: () => void; onCancel?: () => void }, {}> {
|
||||
curId: string;
|
||||
|
||||
@boundMethod
|
||||
componentDidMount(): void {
|
||||
this.curId = uuidv4();
|
||||
const domain = "modal-" + this.curId;
|
||||
const keybindManager = GlobalModel.keybindManager;
|
||||
if (this.props.onOk) {
|
||||
keybindManager.registerKeybinding("modal", domain, "generic:confirm", (waveEvent) => {
|
||||
if (this.props.onOk) {
|
||||
this.props.onOk();
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
if (this.props.onCancel) {
|
||||
keybindManager.registerKeybinding("modal", domain, "generic:cancel", (waveEvent) => {
|
||||
if (this.props.onCancel) {
|
||||
this.props.onCancel();
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
componentWillUnmount(): void {
|
||||
GlobalModel.keybindManager.unregisterDomain("modal-" + this.curId);
|
||||
}
|
||||
|
||||
render(): React.ReactNode {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
const ModalFooter: React.FC<ModalFooterProps> = ({
|
||||
onCancel,
|
||||
onOk,
|
||||
cancelLabel = "Cancel",
|
||||
okLabel = "Ok",
|
||||
keybindings,
|
||||
}) => (
|
||||
const ModalFooter: React.FC<ModalFooterProps> = ({ onCancel, onOk, cancelLabel = "Cancel", okLabel = "Ok" }) => (
|
||||
<div className="wave-modal-footer">
|
||||
<If condition={keybindings}>
|
||||
<ModalKeybindings onOk={onOk} onCancel={onCancel}></ModalKeybindings>
|
||||
</If>
|
||||
{onCancel && (
|
||||
<Button className="secondary" onClick={onCancel}>
|
||||
{cancelLabel}
|
||||
@@ -131,4 +79,4 @@ class Modal extends React.Component<ModalProps> {
|
||||
}
|
||||
}
|
||||
|
||||
export { Modal, ModalKeybindings };
|
||||
export { Modal };
|
||||
|
||||
@@ -18,8 +18,6 @@ interface TextFieldProps {
|
||||
className?: string;
|
||||
onChange?: (value: string) => void;
|
||||
onKeyDown?: (event: React.KeyboardEvent<HTMLInputElement>) => void;
|
||||
onFocus?: () => void;
|
||||
onBlur?: () => void;
|
||||
placeholder?: string;
|
||||
defaultValue?: string;
|
||||
decoration?: TextFieldDecorationProps;
|
||||
@@ -80,9 +78,6 @@ class TextField extends React.Component<TextFieldProps, TextFieldState> {
|
||||
@boundMethod
|
||||
handleFocus() {
|
||||
this.setState({ focused: true });
|
||||
if (this.props.onFocus) {
|
||||
this.props.onFocus();
|
||||
}
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
@@ -96,9 +91,6 @@ class TextField extends React.Component<TextFieldProps, TextFieldState> {
|
||||
this.setState({ error: false, focused: false });
|
||||
}
|
||||
}
|
||||
if (this.props.onBlur) {
|
||||
this.props.onBlur();
|
||||
}
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
@@ -159,9 +151,7 @@ class TextField extends React.Component<TextFieldProps, TextFieldState> {
|
||||
</label>
|
||||
</If>
|
||||
<input
|
||||
className={cn("wave-textfield-inner-input", "wave-input", {
|
||||
"offset-left": decoration?.startDecoration,
|
||||
})}
|
||||
className={cn("wave-textfield-inner-input", { "offset-left": decoration?.startDecoration })}
|
||||
ref={this.inputRef}
|
||||
id={label}
|
||||
value={inputValue}
|
||||
|
||||
@@ -63,6 +63,18 @@
|
||||
}
|
||||
}
|
||||
|
||||
.status.updated {
|
||||
div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 5px;
|
||||
|
||||
i {
|
||||
color: var(--app-success-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.status.outdated {
|
||||
div {
|
||||
i {
|
||||
|
||||
@@ -5,12 +5,10 @@ import * as React from "react";
|
||||
import * as mobxReact from "mobx-react";
|
||||
import * as mobx from "mobx";
|
||||
import { boundMethod } from "autobind-decorator";
|
||||
import { GlobalModel, getApi } from "@/models";
|
||||
import { GlobalModel } from "@/models";
|
||||
import { Modal, LinkButton } from "@/elements";
|
||||
import * as util from "@/util/util";
|
||||
import * as appconst from "@/app/appconst";
|
||||
import cn from "classnames";
|
||||
import { If } from "tsx-control-statements/components";
|
||||
|
||||
import logo from "@/assets/waveterm-logo-with-bg.svg";
|
||||
import "./about.less";
|
||||
@@ -25,34 +23,53 @@ class AboutModal extends React.Component<{}, {}> {
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
updateApp(): void {
|
||||
getApi().installAppUpdate();
|
||||
isUpToDate(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
getClientVersion(): JSX.Element {
|
||||
const clientData: ClientDataType = GlobalModel.clientData.get();
|
||||
const showUpdateStatus = clientData.clientopts.noreleasecheck !== true;
|
||||
const isUpToDate = !showUpdateStatus || GlobalModel.appUpdateStatus.get() !== "ready";
|
||||
updateApp(): void {
|
||||
// GlobalCommandRunner.updateApp();
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
getStatus(isUpToDate: boolean): JSX.Element {
|
||||
// TODO no up-to-date status reporting
|
||||
return (
|
||||
<div className={cn("status", { outdated: !isUpToDate })}>
|
||||
<If condition={!isUpToDate}>
|
||||
<div className="status updated">
|
||||
<div className="text-selectable">
|
||||
Client Version {appconst.VERSION} ({appconst.BUILD})
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
if (isUpToDate) {
|
||||
return (
|
||||
<div className="status updated">
|
||||
<div>
|
||||
<i className="fa-sharp fa-solid fa-triangle-exclamation" />
|
||||
<span>Outdated Version</span>
|
||||
<i className="fa-sharp fa-solid fa-circle-check" />
|
||||
<span>Up to Date</span>
|
||||
</div>
|
||||
</If>
|
||||
<div className="selectable">
|
||||
Client Version {appconst.VERSION} ({appconst.BUILD})
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className="status outdated">
|
||||
<div>
|
||||
<i className="fa-sharp fa-solid fa-triangle-exclamation" />
|
||||
<span>Outdated Version</span>
|
||||
</div>
|
||||
<div className="selectable">
|
||||
Client Version {appconst.VERSION} ({appconst.BUILD})
|
||||
</div>
|
||||
<If condition={!isUpToDate}>
|
||||
<div>
|
||||
<button onClick={this.updateApp} className="button color-green text-secondary">
|
||||
Restart to Update
|
||||
</button>
|
||||
</div>
|
||||
</If>
|
||||
<div>
|
||||
<button onClick={this.updateApp} className="button color-green text-secondary">
|
||||
Update
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -61,7 +78,7 @@ class AboutModal extends React.Component<{}, {}> {
|
||||
const currentDate = new Date();
|
||||
return (
|
||||
<Modal className="about-modal">
|
||||
<Modal.Header onClose={this.closeModal} title="About" keybindings={true} />
|
||||
<Modal.Header onClose={this.closeModal} title="About" />
|
||||
<div className="wave-modal-body">
|
||||
<div className="about-section">
|
||||
<div className="logo-wrapper">
|
||||
@@ -76,7 +93,7 @@ class AboutModal extends React.Component<{}, {}> {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="about-section text-standard">{this.getClientVersion()}</div>
|
||||
<div className="about-section text-standard">{this.getStatus(this.isUpToDate())}</div>
|
||||
<div className="about-section">
|
||||
<LinkButton
|
||||
className="secondary solid"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user