Compare commits

...

47 Commits

Author SHA1 Message Date
Evan Simkowitz 4d95d45a45 save 2024-04-05 10:46:07 -07:00
Evan Simkowitz 1c23701181 Clean up styling and focus behavior for cmdinput (#546)
* Clean up cmdinput

* Remove unused css styles, clicking on textarea will focus back to textarea without closing history

* cleanup logic for activating textarea

* actions buttons should always show, should properly disable inactive views

* clicking actions toggles the view

* remove titlebar spacer, clean up padding

* Make AIChat and HistoryInfo share a common layout

* fix ai chat scroll

* clean up formatting

* fix chat textarea resizing

* align prompt and input

* update infomsg to use auxview

* update comments

* fix widths and key error

* add todo

* adjust padding for input, remove debug

* Don't capture clicks on the prompt area
2024-04-04 19:29:43 -07:00
Cole Lashley 0fe767cdf3 Bugfixes for ai chat code select (#537)
* added uuid to code select to fix some render related bugs

* added input popup type, and fixed aichat computed condition

* fixed stash artifacts
2024-04-04 16:58:26 -07:00
Mike Sawka 097623ab51 have initial run-command return faster to the frontend for quicker updating (#549)
* have initial run-command return faster to the frontend for quicker updating.  cuts time from 70-80ms down to 20ms for an average command

* remove wlogs

* more logging cleanup

* fix focus for when start cmd returns an error
2024-04-04 15:08:45 -07:00
Red J Adaya 9de25e4869 truncate labels (#544) 2024-04-03 09:55:36 -07:00
Evan Simkowitz a139633375 Send NumRunningCommands updates via the main bus, regardless of where other updates are being sent (#545) 2024-04-02 18:47:54 -07:00
Evan Simkowitz ccc63937b6 Support running ephemeral commands (#543)
* initial

* save work, starting to add backend types

* save work

* save work

* Add EphemeralWriteCloser

* Command pipes thru, triggers infinite loop

* save debugging

* fix bad merge

* save debug statements

* fixing spaghetti

* clean up code

* got cwd override working

* Add separate paths for stdout and stderr writers

* fix stdout/stderr

* env vars are now working

* revert waveshell changes

* Making EphemeralWriteCloser into a more generic BufferedPipe

* formatting

* comment

* delete unused package

* more naming changes

* add package comment

* add UsePty to EphemeralRunOpts

* document UsePty

* ensure only one downstream writer can read from the buffer

* store pointer to syncs

* remove inshellisense stuff for now

* remove debugs

* revert yarn

* remove unnecessary debugs in main-server

* more debugging removed

* revert tsconfig
2024-04-02 15:46:32 -07:00
Evan Simkowitz dc7fc2c823 Pull in linting fixes from preact branch (#538)
* Pull in linting fixes from preact branch

* more consts

* one more const

* Revert PureComponent

* revert preact artifavt

* revert another change
2024-04-02 12:30:17 -07:00
Red J Adaya ca5117cda0 Terminal theming (#485)
* init

* use setStyleVar

* backend implementation. scrope level terminal theming.

* only invoke this.applyTermTheme for keys that are updated. command runner for global term theme

* invoke applyTermTheme for global terminal themes as well

* fix nil error

* fix issue were theme can't be found

* fix issue where selected termtheme is not set as default value

* term theme switcher for session

* do not force reload after setting css vars

* fix issues. screenview terminal theme switcher

* remove debugging code

* move getTermThemes to util

* fix global theme reset

* fix workspace theme reset

* fix screenview terminal theme reset issue

* cleanup

* do not apply theme if theme hasn't changed

* do not apply theme if theme hasn't changed in workspace view

* cleanup

* cleanup

* force reload terminal

* fix inconsistency

* fix reset issue

* add a mobx reaction so that theming working when switching sessions

* workig reset

* simplify and cleanup

* refactor

* working global and session terminal theming

* add check

* perf improvement

* more perf improvements

* put reaction componentDidUpdate to make sure ref is already associated to the element

* cleanup

* fix issue where session theme is overriden by global theme on reload

* reduce flickering on reload

* more on reducing flickering on reload

* cleanup

* more cleanup

* fix file not found when no global theme is set

* screen level terminal theming

* update comment

* re-render terminal in history view. cleanup.

* cleanup

* merge main
2024-04-01 23:41:24 -07:00
Cole Lashley f41ac1d5e3 Added this.lastHistoryUpDown = false to cmdinput domain callback (#533)
* added more cmdinput-anykey behavior

* fixed lasthistoryupdown

* more bug fixes

* fixed history bugs hopefully fully fixed
2024-03-29 13:28:49 -07:00
Mike Sawka 0024f0f3e8 fix xterm.js versions and addon versions (#534)
* make xterm packages consistent

* add serializeAddon, fix varsUpdated
2024-03-29 10:52:18 -07:00
Mike Sawka 8a3d9628ba add addons-webgl, protected with clientsettings flag (#532) 2024-03-28 23:19:39 -07:00
Mike Sawka 7c2265f3e3 add debug command to see remote-instance state (#531) 2024-03-28 18:53:16 -07:00
Cole Lashley 4f6c2ee39b Other key bind bug fixes (#529) 2024-03-28 17:53:03 -07:00
Mike Sawka a1e4e807cc update statediff algorithm for wavesrv / remote instances (#530)
* remote statemap from waveshell server (diff against initial state)

* move ShellStatePtr from sstore to packet so it can be passed over the wire

* add finalstatebaseptr to cmddone

* much improved diff computation code on wavesrv side

* fix displayname -- now using hash

* add comments, change a couple msh.WriteToPtyBuffer calls to log.Printfs
2024-03-28 16:56:39 -07:00
Cole Lashley 5c85b2b786 Cmdinput keybinding bug fixes (#524)
* added domain callback for every layer

* added domain callback for every layer

* switched dump logs to false

* dropdown fixes

* moved uuid back to constructor
2024-03-28 13:19:20 -07:00
Cole Lashley 4879e90e91 fixed 2 more switches for baseurl (#527) 2024-03-28 13:14:05 -07:00
Evan Simkowitz a61310afc3 Remove datepicker from history until we have a proper date range selection (#526) 2024-03-28 12:21:58 -07:00
Cole Lashley 80c781bf4c added check for no baseurl (#525) 2024-03-28 12:20:58 -07:00
Mike Sawka 33400e65ff restore delete screen button (#522) 2024-03-27 22:42:37 -07:00
Sylvie Crowe 7b58949027 fix: this prevents possible loops while connecting (#521)
A recent change made it possible to get stuck in a loop when connecting
to a remote. This reverts the part of it that caused this while
retaining the other behavior. This makes it possible to add to blank
known_host files again. It also adds a printout to display when a
connection is complete.
2024-03-27 21:19:35 -07:00
Cole Lashley 3be96c949d Debug pane and lookup key (#518)
* added new util functions for logging keyutils and added debug pane

* clean up the formatting
2024-03-27 18:33:29 -07:00
Evan Simkowitz 052645e0df Remove debug statement (#520) 2024-03-27 17:03:01 -07:00
Evan Simkowitz 3abc1ac3d7 Fix display of overflow dates in datepicker (#519)
* save work

* Fix overflow days
2024-03-27 16:59:45 -07:00
Evan Simkowitz e7ed962944 Remove unused button colors from light.css (#517) 2024-03-27 16:05:32 -07:00
Evan Simkowitz d99102b8e3 Make all modal keybindings off by default, fix contrast issues with inputs in light mode (#516)
* Make all modal keybindings opt in

* Fix some contrast issues with inputs in light Mode
2024-03-27 16:02:43 -07:00
Evan Simkowitz abe6d6a6ba Add esc keybinding to all modals, add update button in About modal (#514)
* Add esc keybinding to all modals, add update button in About modal

* move import
2024-03-27 15:35:14 -07:00
Mike Sawka 4eb215b99d disable right sidebar in production (#515) 2024-03-27 15:33:00 -07:00
Cole Lashley 404f7eaac0 Ensure config dir and keybindings.json file to remove 404 keybindings file not found console error (#513)
* added ensure dir to config dir

* removed extraneous slashes
2024-03-27 14:55:03 -07:00
Sylvie Crowe 28dd9410fe fix: properly handle missing knownhosts case (#510)
A bug prevented waveterm from being able to create missing knownhosts
files. This change corrects that.
2024-03-27 14:29:21 -07:00
Sylvie Crowe b308334038 fix: use flex for .wave-button instead of block (#511)
Previously, .wave-button had `display: block;` overwriting the expected
`display: flex;`. This resulted in buttons with an icon being aligned
vertically instead of horizontally. This change removes the undesired
`display: block;` so the buttons are formatted horizontally again.
2024-03-27 14:28:36 -07:00
Mike Sawka 964751aae1 bump version to v0.7.2, bump waveshell version to 0.6 (#512) 2024-03-27 14:27:55 -07:00
Mike Sawka d3c771efb1 fix codeedit (#509) 2024-03-27 14:08:31 -07:00
Cole Lashley aca197037d Up baseurl max length to 50 (#496)
* upped max length

* added client:get and client:info, upped max length of baseurl

* added openai prefix for consistency

* updated client:show command and removed client:get and client:info
2024-03-27 14:00:52 -07:00
Mike Sawka 5734a7bc7a add offsite icon to sidebar links that take you off the app (#508) 2024-03-27 13:17:56 -07:00
Mike Sawka bed191186c allow empty pvars (important to *unset* the git directory when you leave it) (#507) 2024-03-27 13:07:24 -07:00
Evan Simkowitz 9809ca634d Remove App item, remove bolding from active auxiliary views (#506) 2024-03-27 12:54:53 -07:00
Evan Simkowitz e867bcb398 Add overlay scrollbar for main sidebar, adjust active session display behavior (#505)
* Add overlay scrollbar to left sidebar

* Keep active session bolded when mainview is not session

* fix color of scrollbar

* swap expression args

* add active color for scrollbar

* add active/highlight to history, connections, and settings
2024-03-27 12:47:57 -07:00
Evan Simkowitz 3e4ba1bf72 Remove unnecessary debug statement (#504) 2024-03-27 11:30:34 -07:00
dependabot[bot] d21182f7e0 Bump express from 4.18.2 to 4.19.2 (#502)
Bumps [express](https://github.com/expressjs/express) from 4.18.2 to 4.19.2.
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.18.2...4.19.2)

---
updated-dependencies:
- dependency-name: express
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-27 09:59:43 -07:00
Evan Simkowitz 49e1fc9133 Remove redundant default.css import (#503) 2024-03-27 09:53:08 -07:00
Mike Sawka 195ee98424 dependency updates (#501) 2024-03-27 09:44:28 -07:00
Mike Sawka 3c3eec73aa reinit updates (#500)
* working on re-init when you create a tab.  some refactoring of existing reinit to make the messaging clearer.  auto-connect, etc.

* working to remove the 'default' shell states out of MShellProc.  each tab should have its own state that gets set on open.

* refactor newtab settings into individual components (and move to a new file)

* more refactoring of tab settings -- use same control in settings and newtab

* have screensettings use the same newtab settings components

* use same conn dropdown, fix classes, update some of the confirm messages to be less confusing (replace screen with tab)

* force a cr on a new tab to initialize state in a new line.  poc right now, need to add to new workspace workflow as well

* small fixups

* remove nohist from GetRawStr, make const

* update hover behavior for tabs

* fix interaction between change remote dropdown, cmdinput, error handling, and selecting a remote

* only switch screen remote if the activemainview is session (new remote flow).  don't switch it if we're on the connections page which is confusing.  also make it interactive

* fix wording on tos modal

* allow empty workspaces. also allow the last workspace to be deleted.  (prep for new startup sequence where we initialize the first session after tos modal)

* add some dead code that might come in use later (when we change how we show connection in cmdinput)

* working a cople different angles.  new settings tab-pulldown (likely orphaned).  and then allowing null activeScreen and null activeSession in workspaceview (show appropriate messages, and give buttons to create new tabs/workspaces).  prep for new startup flow

* don't call initActiveShells anymore.  also call ensureWorkspace() on TOS close

* trying to use new pulldown screen settings

* experiment with an escape keybinding

* working on tab settings close triggers

* close tab settings on tab switch

* small updates to tos popup, reorder, update button text/size, small wording updates

* when deleting a screen, send SIGHUP to all running commands

* not sure how this happened, lineid should not be passed to setLineFocus

* remove context timeouts for ReInit (it is now interactive, so it gets canceled like a normal command -- via ^C, and should not timeout on its own)

* deal with screen/session tombstones updates (ignore to quite warning)

* remove defaultfestate from remote

* fix issue with removing default ris

* remove dead code

* open the settings pulldown for new screens

* update prompt to show when the shell is still initializing (or if it failed)

* switch buttons to use wave button class, update messages, and add warning for no shell state

* all an override of rptr for dyncmds.  needed for the 'connect' command (we need to set the rptr to the *new* connection rather than the old one)

* remove old commented out code
2024-03-27 00:22:57 -07:00
Evan Simkowitz 6065ee931f Support os-native theming (#495)
* save work

* Add native theme support

* update index

* update var name

* remove comment

* fix code setting

* bump render version on change

* remove themeutil
2024-03-26 19:14:03 -07:00
Cole Lashley 69b9ce33b3 User input keybindings fix (#494)
* added user input fix and focusVal optoinal in footer

* small fixes and removed focusVal for now
2024-03-26 15:05:18 -07:00
Evan Simkowitz a121bd4bb5 Move bookmarks, history, playbook, and telemetry code out of sstore (#493)
* break out telemetry and playbook

* break out bookmarks

* add license disclaimers
2024-03-25 20:20:52 -07:00
dependabot[bot] dcc7b2943e Bump webpack-dev-middleware from 5.3.3 to 5.3.4 (#490)
Bumps [webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware) from 5.3.3 to 5.3.4.
- [Release notes](https://github.com/webpack/webpack-dev-middleware/releases)
- [Changelog](https://github.com/webpack/webpack-dev-middleware/blob/v5.3.4/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-dev-middleware/compare/v5.3.3...v5.3.4)

---
updated-dependencies:
- dependency-name: webpack-dev-middleware
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-25 09:55:15 -07:00
113 changed files with 6861 additions and 4320 deletions
+16 -12
View File
@@ -6,7 +6,7 @@
},
"productName": "Wave",
"description": "An Open-Source, AI-Native, Terminal Built for Seamless Workflows",
"version": "0.7.1",
"version": "0.7.2",
"main": "dist/emain.js",
"license": "Apache-2.0",
"repository": {
@@ -23,7 +23,6 @@
"@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",
@@ -37,6 +36,8 @@
"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",
@@ -45,11 +46,13 @@
"remark-gfm": "^4.0.0",
"sprintf-js": "^1.1.2",
"throttle-debounce": "^5.0.0",
"tsx-control-statements": "^4.1.1",
"tsx-control-statements": "^5.1.1",
"uuid": "^9.0.0",
"winston": "^3.8.2",
"xterm": "^5.0.0",
"xterm-addon-web-links": "^0.9.0"
"xterm": "^5.3.0",
"xterm-addon-web-links": "^0.9.0",
"xterm-addon-serialize": "^0.11.0",
"xterm-addon-webgl": "^0.16.0"
},
"devDependencies": {
"@babel/cli": "^7.17.10",
@@ -66,24 +69,25 @@
"@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": "^11.0.0",
"copy-webpack-plugin": "^12.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": "^11.0.0",
"less-loader": "^12.0.0",
"lodash-webpack-plugin": "^0.11.6",
"mini-css-extract-plugin": "^2.6.0",
"prettier": "^2.8.8",
@@ -94,11 +98,11 @@
"webpack": "^5.73.0",
"webpack-bundle-analyzer": "^4.10.1",
"webpack-cli": "^5.1.4",
"webpack-dev-server": "^4.9.1",
"webpack-dev-server": "^5.0.4",
"webpack-merge": "^5.8.0",
"yaml": "^2.4.0"
},
"scripts": {
"postinstall": "electron-builder install-app-deps"
}
}
}
+6 -6
View File
@@ -5,14 +5,14 @@
<base href="../" />
<script charset="UTF-8" src="dist-dev/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-dev/waveterm.css" />
<link rel="stylesheet" id="theme-stylesheet" href="public/themes/default.css">
<link rel="stylesheet" id="theme-stylesheet" href="public/themes/themequery.css" />
</head>
<body>
<div id="measure"></div>
+6 -6
View File
@@ -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/default.css" />
<link rel="stylesheet" id="theme-stylesheet" href="public/themes/themequery.css" />
</head>
<body>
<div id="measure"></div>
+27 -16
View File
@@ -42,16 +42,19 @@
--app-bg-color: black;
--app-accent-color: rgb(88, 193, 66);
--app-accent-bg-color: rgba(88, 193, 66, 0.25);
--app-accent-bg-darker-color: rgba(88, 193, 66, 0.5);
--app-text-color: rgb(211, 215, 207);
--app-text-primary-color: rgb(255, 255, 255);
--app-text-secondary-color: rgb(195, 200, 194);
--app-text-disabled-color: rgb(173, 173, 173);
--app-text-bg-color: rgb(23, 23, 23);
--app-text-bg-disabled-color: rgb(51, 51, 51);
--app-border-color: rgb(51, 51, 51);
--app-maincontent-bg-color: #333;
--app-maincontent-bg-color: rgb(51, 51, 51);
--app-panel-bg-color: rgba(21, 23, 21, 1);
--app-panel-bg-color-dev: rgb(21, 23, 48);
--app-icon-color: rgb(139, 145, 138);
--app-icon-hover-color: #fff;
--app-icon-hover-color: rgb(255, 255, 255);
--app-selected-mask-color: rgba(255, 255, 255, 0.06);
/* global status colors */
@@ -67,6 +70,7 @@
--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);
@@ -86,6 +90,7 @@
--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);
@@ -112,7 +117,7 @@
--hotkey-text-color: var(--app-text-secondary-color);
/* sidebar colors */
--sidebar-highlight-color: rgba(241, 246, 243, 0.08);
--sidebar-highlight-color: var(--app-accent-bg-color);
--sidebar-font-size: 15px;
--sidebar-line-height: 1.5;
--sidebar-font-weight: normal;
@@ -120,18 +125,18 @@
/* line colors */
--line-sidebar-message-color: rgb(196, 160, 0);
--line-background: rgba(21, 23, 21, 1);
--line-avatar-color: #eceeec;
--line-background: var(--app-panel-bg-color);
--line-avatar-color: rgb(236, 238, 236);
--line-text-color: rgb(211, 215, 207);
--line-svg-fill-color: rgb(150, 152, 150);
--line-svg-hover-fill-color: #eceeec;
--line-svg-hover-fill-color: rgb(236, 238, 236);
--line-separator-color: rgb(126, 126, 126);
--line-error-color: var(--app-error-color);
--line-warning-color: var(--app-warning-color);
--line-base-soft-blue-color: #729fcf;
--line-base-soft-blue-color: rgb(114, 159, 207);
--line-active-border-color: var(--app-accent-color);
--line-selected-bg-color: rgba(255, 255, 255, 0.05);
--line-selected-border-left-color: #777777;
--line-selected-border-left-color: rgb(119, 119, 119);
--line-selected-error-border-color: rgba(204, 0, 0, 0.8);
--line-selected-error-bg-color: rgb(19, 4, 3);
--line-error-bg-color: rgba(200, 0, 0, 0.1);
@@ -150,22 +155,21 @@
/* table colors */
--table-border-color: rgba(241, 246, 243, 0.15);
--table-thead-border-top-color: rgba(250, 250, 250, 0.1);
--table-thead-bright-border-color: #ccc;
--table-thead-bright-border-color: rgb(204, 204, 204);
--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: #222;
--table-tr-selected-hover-bg-color: #333;
--table-tr-selected-bg-color: rgb(34, 34, 34);
--table-tr-selected-hover-bg-color: var(--app-maincontent-bg-color);
/* cmdinput colors */
--cmdinput-textarea-bg-color: #171717;
--cmdinput-bg-color: var(--app-text-bg-color);
--cmdinput-text-error-color: var(--term-red);
--cmdinput-history-item-error-color: var(--term-bright-red);
--cmdinput-history-item-selected-error-color: var(--term-bright-red);
--cmdinput-button-bg-color: rgb(88, 193, 66);
--cmdinput-comment-button-bg-color: rgb(57, 113, 255);
--cmdinput-disabled-icon-color: rgb(76, 81, 75, 1);
--cmdinput-history-bg-color: rgb(21, 23, 21, 1);
--cmdinput-button-bg-color: var(--tab-green);
--cmdinput-disabled-bg-color: var(--app-text-bg-disabled-color);
--cmdinput-history-bg-color: var(--app-bg-color);
/* screen view color */
--screen-view-text-caption-color: rgb(139, 145, 138);
@@ -186,4 +190,11 @@
--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);
}
}
+20 -26
View File
@@ -1,53 +1,48 @@
/* Copyright 2024, Command Line Inc.
SPDX-License-Identifier: Apache-2.0 */
@import "./default.css";
@import "./term-default.css";
@import "./term-light.css";
@import url("./term-default.css");
@import url("./term-light.css");
:root {
--app-bg-color: #fefefe;
--app-bg-color: rgb(254, 254, 254);
--app-accent-color: rgb(75, 166, 57);
--app-accent-bg-color: rgba(75, 166, 57, 0.2);
--app-text-color: #000;
--app-text-color: rgb(0, 0, 0);
--app-text-primary-color: rgb(0, 0, 0, 0.9);
--app-text-secondary-color: rgb(0, 0, 0, 0.7);
--app-border-color: rgb(139 145 138);
--app-panel-bg-color: #e0e0e0;
--app-panel-bg-color-dev: #e0e0e0;
--app-icon-color: rgb(80, 80, 80);
--app-icon-hover-color: rgb(100, 100, 100);
--app-panel-bg-color: rgb(224, 224, 224);
--app-panel-bg-color-dev: rgb(224, 224, 224);
--app-icon-color: rgb(110, 110, 110);
--app-icon-hover-color: rgb(80, 80, 80);
--app-selected-mask-color: rgba(0, 0, 0, 0.06);
--input-bg-color: #eeeeee;
--input-bg-color: rgb(238, 238, 238);
/* tab color */
--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);
--table-thead-bg-color: rgba(250, 250, 250, 0.15);
--table-tr-border-bottom-color: rgba(0, 0, 0, 0.15);
--table-tr-hover-bg-color: rgba(0, 0, 0, 0.15);
--table-tr-selected-bg-color: #dddddd;
--table-tr-selected-hover-bg-color: #cccccc;
--table-tr-selected-bg-color: rgb(221, 221, 221);
--table-tr-selected-hover-bg-color: rgb(204, 204, 204);
/* 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-color);
--form-element-text-color: var(--app-text-primary-color);
--form-element-primary-text-color: var(--app-text-primary-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);
--form-element-disabled-text-color: #b7b7b7;
--form-element-placeholder-color: #b7b7b7;
--form-element-disabled-text-color: rgb(183, 183, 183);
--form-element-placeholder-color: rgb(183, 183, 183);
--markdown-bg-color: rgb(0, 0, 0, 0.1);
@@ -55,28 +50,27 @@
--modal-header-bottom-border-color: rgba(0, 0, 0, 0.3);
/* cmd input */
--cmdinput-textarea-bg-color: rgba(0, 0, 0, 0.1);
--cmdinput-textarea-border-color: var(--form-element-border-color);
/* scroll colors */
--scrollbar-background-color: var(--app-bg-color);
--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);
--line-actions-inactive-color: rgba(0, 0, 0, 0.3);
--line-actions-active-color: rgba(0, 0, 0, 1);
--logo-button-hover-bg-color: #f0f0f0;
--logo-button-hover-bg-color: rgb(240, 240, 240);
--xterm-viewport-border-color: rgba(0, 0, 0, 0.3);
--datepicker-cell-hover-bg-color: #f0f0f0;
--datepicker-cell-hover-bg-color: rgb(240, 240, 240);
--datepicker-cell-other-text-color: rgba(0, 0, 0, 0.3);
--datepicker-header-fade-color: rgba(0, 0, 0, 0.4);
--datepicker-year-header-bg-color: #f5f5f5;
--datepicker-year-header-border-color: #dcdcdc;
--datepicker-year-header-bg-color: rgb(245, 245, 245);
--datepicker-year-header-border-color: rgb(220, 220, 220);
/* toggle colors */
--toggle-thumb-color: var(--app-bg-color);
+3
View File
@@ -0,0 +1,3 @@
@import url("./default.css") screen;
@import url("./light.css") screen and (prefers-color-scheme: light);
+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.5
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.5
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.5
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)
+77 -39
View File
@@ -251,6 +251,13 @@ 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;
}
@@ -786,6 +793,75 @@ 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;
@@ -847,7 +923,7 @@ a.a-block {
}
}
input {
input:not(.wave-input) {
padding: 4px;
border-radius: 3px;
}
@@ -858,44 +934,6 @@ 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
View File
@@ -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 { GlobalCommandRunner, GlobalModel } from "@/models";
import { 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} clientData={clientData} />
<MainSideBar parentRef={this.mainContentRef} />
<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.isThemeDark() ? "is-dark" : "is-light";
const lightDarkClass = GlobalModel.isDarkTheme.get() ? "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} clientData={clientData} />
<MainSideBar parentRef={this.mainContentRef} />
<ErrorBoundary>
<PluginsView />
<WorkspaceView />
@@ -160,7 +160,7 @@ class App extends React.Component<{}, {}> {
<ConnectionsView model={remotesModel} />
<ClientSettingsView model={remotesModel} />
</ErrorBoundary>
<RightSideBar parentRef={this.mainContentRef} clientData={clientData} />
<RightSideBar parentRef={this.mainContentRef} />
</div>
<ModalsProvider />
</div>
+43 -12
View File
@@ -9,6 +9,7 @@ import { If } from "tsx-control-statements/components";
import { GlobalModel, GlobalCommandRunner, RemotesModel, getApi } from "@/models";
import { Toggle, InlineSettingsTextEdit, SettingsError, Dropdown } from "@/common/elements";
import { commandRtnHandler, isBlank } from "@/util/util";
import { getTermThemes } from "@/util/themeutil";
import * as appconst from "@/app/appconst";
import "./clientsettings.less";
@@ -64,11 +65,25 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
}
@boundMethod
handleChangeTheme(theme: string): void {
if (GlobalModel.getTheme() == theme) {
handleChangeThemeSource(themeSource: NativeThemeSource): void {
if (GlobalModel.getThemeSource() == themeSource) {
return;
}
const prtn = GlobalCommandRunner.setTheme(theme, false);
const prtn = GlobalCommandRunner.setTheme(themeSource, false);
getApi().setNativeThemeSource(themeSource);
commandRtnHandler(prtn, this.errorMessage);
}
@boundMethod
handleChangeTermTheme(theme: string): void {
// For global terminal theme, the key is global, otherwise it's either
// sessionId or screenId.
const currTheme = GlobalModel.getTermTheme()["global"];
if (currTheme == theme) {
return;
}
const prtn = GlobalCommandRunner.setGlobalTermTheme(theme, false);
commandRtnHandler(prtn, this.errorMessage);
}
@@ -111,11 +126,12 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
return availableFontFamilies;
}
getThemes(): DropdownItem[] {
const themes: DropdownItem[] = [];
themes.push({ label: "Dark", value: "dark" });
themes.push({ label: "Light", value: "light" });
return themes;
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;
}
@boundMethod
@@ -190,7 +206,9 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
);
const curFontSize = GlobalModel.getTermFontSize();
const curFontFamily = GlobalModel.getTermFontFamily();
const curTheme = GlobalModel.getTheme();
const curTheme = GlobalModel.getThemeSource();
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}>
@@ -225,12 +243,25 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
<div className="settings-input">
<Dropdown
className="theme-dropdown"
options={this.getThemes()}
options={this.getThemeSources()}
defaultValue={curTheme}
onChange={this.handleChangeTheme}
onChange={this.handleChangeThemeSource}
/>
</div>
</div>
<If condition={termThemes.length > 0}>
<div className="settings-field">
<div className="settings-label">Terminal Theme</div>
<div className="settings-input">
<Dropdown
className="terminal-theme-dropdown"
options={termThemes}
defaultValue={currTermTheme}
onChange={this.handleChangeTermTheme}
/>
</div>
</div>
</If>
<div className="settings-field">
<div className="settings-label">Client ID</div>
<div className="settings-input">{cdata.clientid}</div>
@@ -281,7 +312,7 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
text={isBlank(openAIOpts.baseurl) ? "openai default" : openAIOpts.baseurl}
value={openAIOpts.baseurl ?? ""}
onChange={this.inlineUpdateOpenAIBaseURL}
maxLength={10}
maxLength={200}
showIcon={true}
/>
</div>
+48 -2
View File
@@ -10,7 +10,6 @@
border-radius: 6px;
height: auto;
line-height: 1.5;
display: block;
white-space: nowrap;
user-select: none;
@@ -21,13 +20,17 @@
}
&.primary {
color: var(--form-element-text-color);
color: var(--form-element-primary-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);
@@ -37,6 +40,37 @@
}
}
&.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 {
@@ -44,6 +78,13 @@
}
}
&.primary.ghost.danger {
background: none;
i {
fill: var(--app-error-color);
}
}
&.secondary {
color: var(--form-element-text-color);
background: var(--form-element-secondary-color);
@@ -57,6 +98,11 @@
border: 1px solid var(--form-element-text-color);
}
&.secondary.outlined.danger {
background: none;
border: 1px solid var(--app-error-color);
}
&.secondary.ghost {
background: none;
}
+4
View File
@@ -22,6 +22,7 @@
display: flex;
align-items: center;
justify-content: center;
background-color: var(--form-element-bg-color);
input {
outline: none !important;
@@ -29,6 +30,7 @@
height: 100%;
padding: 0 !important;
cursor: default !important;
background-color: inherit !important;
}
.fa-calendar {
@@ -99,6 +101,7 @@
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;
}
@@ -157,6 +160,7 @@
}
&.selected {
color: var(--form-element-primary-text-color);
background-color: var(--form-element-primary-color);
}
}
+42 -48
View File
@@ -2,7 +2,7 @@ import React, { useState, useEffect, useRef, createRef } from "react";
import * as mobx from "mobx";
import ReactDOM from "react-dom";
import dayjs from "dayjs";
import cs from "classnames";
import cn from "classnames";
import { Button } from "@/elements";
import { If } from "tsx-control-statements/components";
import { GlobalModel } from "@/models";
@@ -39,8 +39,8 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
MM: selDate.format("MM"),
DD: selDate.format("DD"),
});
let curUuid = uuidv4();
let keybindsRegistered = mobx.observable.box(false, {
const curUuid = uuidv4();
const keybindsRegistered = mobx.observable.box(false, {
name: "datepicker-keybinds-registered",
});
@@ -90,7 +90,6 @@ 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) => {
@@ -103,7 +102,7 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
return (
<div className="day-picker-header">
<div
className={cs({ fade: showYearAccordion })}
className={cn({ fade: showYearAccordion })}
onClick={() => {
if (!showYearAccordion) {
setExpandedYear(selDate.year()); // Set expandedYear when opening accordion
@@ -112,7 +111,7 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
}}
>
{selDate.format("MMMM YYYY")}
<span className={cs("dropdown-arrow", { fade: showYearAccordion })}></span>
<span className={cn("dropdown-arrow", { fade: showYearAccordion })}></span>
</div>
<If condition={!showYearAccordion}>
<div className="arrows">
@@ -183,9 +182,9 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
}
// Next month's filler days
let overFlowIndex = 1;
while (days.length < 42) {
const fillerDayCount = days.length - daysInPreviousMonth - endDay.date();
const dayDate = endDay.add(fillerDayCount + 1, "day");
const dayDate = endDay.add(overFlowIndex++, "day");
days.push(
<div
key={`next-month-day-${dayDate.format("YYYY-MM-DD")}`}
@@ -251,14 +250,14 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
</div>
<If condition={expandedYear === year}>
<div
className={cs("month-container", {
className={cn("month-container", {
expanded: expandedYear === year,
})}
>
{Array.from({ length: 12 }, (_, i) => i + 1).map((month) => (
<div
key={month}
className={cs("month", {
className={cn("month", {
selected: year === currentYear && month === selDate.month() + 1,
})}
onClick={() => handleMonthYearSelect(month, year)}
@@ -301,7 +300,7 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
)
: null;
const handleDatePartChange = (part, value) => {
const handleDatePartChange = (part: string, value: string) => {
const newDateParts = { ...dateParts, [part]: value };
setDateParts(newDateParts);
@@ -312,7 +311,7 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
}
};
const handleArrowNavigation = (key, currentPart) => {
const handleArrowNavigation = (key: string, currentPart: string) => {
const currentIndex = formatParts.indexOf(currentPart);
let targetInput;
@@ -327,9 +326,9 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
}
};
const handleKeyDown = (event, currentPart) => {};
const handleKeyDown = (event, currentPart: string) => {};
const handleFocus = (event, part) => {
const handleFocus = (event, part: string) => {
event.target.select();
registerKeybindings(event, part);
};
@@ -341,74 +340,69 @@ const DatePicker: React.FC<DatePickerProps> = ({ selectedDate, format = "MM/DD/Y
mobx.action(() => {
keybindsRegistered.set(true);
})();
let keybindManager = GlobalModel.keybindManager;
let domain = "datepicker-" + curUuid + "-" + part;
keybindManager.registerKeybinding("control", domain, "generic:selectLeft", (waveEvent) => {
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", (waveEvent) => {
keybindManager.registerKeybinding("control", domain, "generic:selectRight", (_) => {
handleArrowNavigation("ArrowRight", part);
return true;
});
keybindManager.registerKeybinding("control", domain, "generic:space", (waveEvent) => {
keybindManager.registerKeybinding("control", domain, "generic:space", (_) => {
toggleModal();
return true;
});
keybindManager.registerKeybinding("control", domain, "generic:confirm", (waveEvent) => {
keybindManager.registerKeybinding("control", domain, "generic:confirm", (_) => {
toggleModal();
return true;
});
keybindManager.registerKeybinding("control", domain, "generic:cancel", (waveEvent) => {
keybindManager.registerKeybinding("control", domain, "generic:cancel", (_) => {
closeModal();
return true;
});
keybindManager.registerKeybinding("control", domain, "generic:tab", (waveEvent) => {
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(),
(waveEvent) => {
let 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);
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);
}
// Re-focus and select the input after state update
selectionTimeoutId = setTimeout(() => {
event.target.focus();
event.target.select();
}, 0);
return true;
// 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);
return true;
});
}
};
const handleBlur = (event, part) => {
const handleBlur = (event, part: string) => {
unregisterKeybindings(part);
};
const unregisterKeybindings = (part) => {
const unregisterKeybindings = (part: string) => {
mobx.action(() => {
keybindsRegistered.set(false);
})();
let domain = "datepicker-" + curUuid + "-" + part;
const domain = "datepicker-" + curUuid + "-" + part;
GlobalModel.keybindManager.unregisterDomain(domain);
};
// Prevent use from selecting text in the input
const handleMouseDown = (event, part) => {
const handleMouseDown = (event, part: string) => {
event.preventDefault();
handleFocus(event, part);
+9 -1
View File
@@ -53,7 +53,7 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
};
this.wrapperRef = React.createRef();
this.menuRef = React.createRef();
this.curUuid == uuidv4();
this.curUuid = uuidv4();
}
componentDidMount() {
@@ -100,6 +100,9 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
@boundMethod
handleClick() {
if (!this.state.isOpen || !this.state.isTouched) {
this.registerKeybindings();
}
this.toggleDropdown();
}
@@ -109,6 +112,7 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
this.registerKeybindings();
}
@boundMethod
registerKeybindings() {
let keybindManager = GlobalModel.keybindManager;
let domain = "dropdown-" + this.curUuid;
@@ -122,6 +126,7 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
});
keybindManager.registerKeybinding("control", domain, "generic:cancel", (waveEvent) => {
this.setState({ isOpen: false });
this.unregisterKeybindings();
return true;
});
keybindManager.registerKeybinding("control", domain, "generic:selectAbove", (waveEvent) => {
@@ -165,10 +170,12 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
}
}
@boundMethod
handleBlur() {
this.unregisterKeybindings();
}
@boundMethod
unregisterKeybindings() {
let domain = "dropdown-" + this.curUuid;
GlobalModel.keybindManager.unregisterDomain(domain);
@@ -189,6 +196,7 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
}
onChange(value);
this.setState({ isOpen: false, isTouched: true });
this.unregisterKeybindings();
}
@boundMethod
+22 -5
View File
@@ -7,8 +7,10 @@ import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import cn from "classnames";
import { GlobalModel } from "@/models";
import { v4 as uuidv4 } from "uuid";
import "./markdown.less";
import { boundMethod } from "autobind-decorator";
function LinkRenderer(props: any): any {
let newUrl = "https://extern?" + encodeURIComponent(props.href);
@@ -28,14 +30,17 @@ function CodeRenderer(props: any): any {
}
@mobxReact.observer
class CodeBlockMarkdown extends React.Component<{ children: React.ReactNode; codeSelectSelectedIndex?: number }, {}> {
class CodeBlockMarkdown extends React.Component<
{ children: React.ReactNode; codeSelectSelectedIndex?: number; uuid: string },
{}
> {
blockIndex: number;
blockRef: React.RefObject<HTMLPreElement>;
constructor(props) {
super(props);
this.blockRef = React.createRef();
this.blockIndex = GlobalModel.inputModel.addCodeBlockToCodeSelect(this.blockRef);
this.blockIndex = GlobalModel.inputModel.addCodeBlockToCodeSelect(this.blockRef, this.props.uuid);
}
render() {
@@ -62,9 +67,21 @@ class Markdown extends React.Component<
{ text: string; style?: any; extraClassName?: string; codeSelect?: boolean },
{}
> {
CodeBlockRenderer(props: any, codeSelect: boolean, codeSelectIndex: number): any {
curUuid: string;
constructor(props) {
super(props);
this.curUuid = uuidv4();
}
@boundMethod
CodeBlockRenderer(props: any, codeSelect: boolean, codeSelectIndex: number, curUuid: string): any {
if (codeSelect) {
return <CodeBlockMarkdown codeSelectSelectedIndex={codeSelectIndex}>{props.children}</CodeBlockMarkdown>;
return (
<CodeBlockMarkdown codeSelectSelectedIndex={codeSelectIndex} uuid={curUuid}>
{props.children}
</CodeBlockMarkdown>
);
} else {
const clickHandler = (e: React.MouseEvent<HTMLElement>) => {
let blockText = (e.target as HTMLElement).innerText;
@@ -90,7 +107,7 @@ class Markdown extends React.Component<
h5: (props) => HeaderRenderer(props, 5),
h6: (props) => HeaderRenderer(props, 6),
code: (props) => CodeRenderer(props),
pre: (props) => this.CodeBlockRenderer(props, codeSelect, curCodeSelectIndex),
pre: (props) => this.CodeBlockRenderer(props, codeSelect, curCodeSelectIndex, this.curUuid),
};
return (
<div className={cn("markdown content", this.props.extraClassName)} style={this.props.style}>
+15 -8
View File
@@ -2,7 +2,6 @@
// 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";
@@ -14,11 +13,15 @@ import { boundMethod } from "autobind-decorator";
interface ModalHeaderProps {
onClose?: () => void;
keybindings?: boolean;
title: string;
}
const ModalHeader: React.FC<ModalHeaderProps> = ({ onClose, title }) => (
const ModalHeader: React.FC<ModalHeaderProps> = ({ onClose, keybindings, 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,23 +39,27 @@ interface ModalFooterProps {
keybindings?: boolean;
}
class ModalKeybindings extends React.Component<{ onOk; onCancel }, {}> {
class ModalKeybindings extends React.Component<{ onOk?: () => void; onCancel?: () => void }, {}> {
curId: string;
@boundMethod
componentDidMount(): void {
this.curId = uuidv4();
let domain = "modal-" + this.curId;
let keybindManager = GlobalModel.keybindManager;
const domain = "modal-" + this.curId;
const keybindManager = GlobalModel.keybindManager;
if (this.props.onOk) {
keybindManager.registerKeybinding("modal", domain, "generic:confirm", (waveEvent) => {
this.props.onOk();
if (this.props.onOk) {
this.props.onOk();
}
return true;
});
}
if (this.props.onCancel) {
keybindManager.registerKeybinding("modal", domain, "generic:cancel", (waveEvent) => {
this.props.onCancel();
if (this.props.onCancel) {
this.props.onCancel();
}
return true;
});
}
@@ -73,7 +80,7 @@ const ModalFooter: React.FC<ModalFooterProps> = ({
onOk,
cancelLabel = "Cancel",
okLabel = "Ok",
keybindings = true,
keybindings,
}) => (
<div className="wave-modal-footer">
<If condition={keybindings}>
+16
View File
@@ -0,0 +1,16 @@
import { OverlayScrollbarsComponentProps, useOverlayScrollbars } from "overlayscrollbars-react";
import React from "react";
export const ScrollbarsComponent = (props: {
options?: OverlayScrollbarsComponentProps["options"];
children: React.ReactNode;
childrenRef: React.RefObject<any>;
}) => {
const [initialize, instance] = useOverlayScrollbars({ options: props.options });
React.useEffect(() => {
initialize(props.childrenRef.current);
}, [initialize, props.childrenRef.current]);
return <div ref={props.childrenRef}>{props.children}</div>;
};
+3 -1
View File
@@ -159,7 +159,9 @@ class TextField extends React.Component<TextFieldProps, TextFieldState> {
</label>
</If>
<input
className={cn("wave-textfield-inner-input", { "offset-left": decoration?.startDecoration })}
className={cn("wave-textfield-inner-input", "wave-input", {
"offset-left": decoration?.startDecoration,
})}
ref={this.inputRef}
id={label}
value={inputValue}
-12
View File
@@ -63,18 +63,6 @@
}
}
.status.updated {
div {
display: flex;
align-items: center;
margin-bottom: 5px;
i {
color: var(--app-success-color);
}
}
}
.status.outdated {
div {
i {
+24 -41
View File
@@ -5,10 +5,12 @@ import * as React from "react";
import * as mobxReact from "mobx-react";
import * as mobx from "mobx";
import { boundMethod } from "autobind-decorator";
import { GlobalModel } from "@/models";
import { GlobalModel, getApi } 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";
@@ -22,54 +24,35 @@ class AboutModal extends React.Component<{}, {}> {
})();
}
@boundMethod
isUpToDate(): boolean {
return true;
}
@boundMethod
updateApp(): void {
// GlobalCommandRunner.updateApp();
getApi().installAppUpdate();
}
@boundMethod
getStatus(isUpToDate: boolean): JSX.Element {
// TODO no up-to-date status reporting
return (
<div className="status updated">
<div className="text-selectable">
Client Version {appconst.VERSION} ({appconst.BUILD})
</div>
</div>
);
getClientVersion(): JSX.Element {
const clientData: ClientDataType = GlobalModel.clientData.get();
const showUpdateStatus = clientData.clientopts.noreleasecheck !== true;
const isUpToDate = !showUpdateStatus || GlobalModel.appUpdateStatus.get() !== "ready";
if (isUpToDate) {
return (
<div className="status updated">
<div>
<i className="fa-sharp fa-solid fa-circle-check" />
<span>Up to Date</span>
</div>
<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={cn("status", { outdated: !isUpToDate })}>
<If condition={!isUpToDate}>
<div>
<i className="fa-sharp fa-solid fa-triangle-exclamation" />
<span>Outdated Version</span>
</div>
</If>
<div className="selectable">
Client Version {appconst.VERSION} ({appconst.BUILD})
</div>
<div>
<button onClick={this.updateApp} className="button color-green text-secondary">
Update
</button>
</div>
<If condition={!isUpToDate}>
<div>
<button onClick={this.updateApp} className="button color-green text-secondary">
Restart to Update
</button>
</div>
</If>
</div>
);
}
@@ -78,7 +61,7 @@ class AboutModal extends React.Component<{}, {}> {
const currentDate = new Date();
return (
<Modal className="about-modal">
<Modal.Header onClose={this.closeModal} title="About" />
<Modal.Header onClose={this.closeModal} title="About" keybindings={true} />
<div className="wave-modal-body">
<div className="about-section">
<div className="logo-wrapper">
@@ -93,7 +76,7 @@ class AboutModal extends React.Component<{}, {}> {
</div>
</div>
</div>
<div className="about-section text-standard">{this.getStatus(this.isUpToDate())}</div>
<div className="about-section text-standard">{this.getClientVersion()}</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