Compare commits

...

110 Commits

Author SHA1 Message Date
Evan Simkowitz e4d3bfd90a save work 2024-04-25 14:48:30 -07:00
Evan Simkowitz 9073b9b31e add utils to assist in fs lookups 2024-04-25 14:47:44 -07:00
Evan Simkowitz cf28bb53ca fix path recommendations 2024-04-25 14:47:18 -07:00
Evan Simkowitz e59f70d26b fix option suggestions not showing if there's a complete match for one option and a partial for others 2024-04-25 11:01:37 -07:00
Evan Simkowitz deb9e23d53 Add ability to enabling autocomplete logging in clientsettings 2024-04-24 17:17:50 -07:00
Evan Simkowitz 3a9aa5813f fix file completion display 2024-04-24 16:41:37 -07:00
Evan Simkowitz c3aa027cc8 fix cwd resolution 2024-04-24 15:41:19 -07:00
Evan Simkowitz 7bdf332ce0 fix insertValue calculation 2024-04-24 15:22:39 -07:00
Evan Simkowitz 9483b43afa add default icon case, though it should never be hit 2024-04-23 18:22:16 -07:00
Evan Simkowitz 3fc4eb40cc remove unused log utils 2024-04-23 18:19:48 -07:00
Evan Simkowitz b142940a4c update import 2024-04-23 18:14:36 -07:00
Evan Simkowitz 3e4a22e7b8 handle -- argument properly 2024-04-23 18:08:01 -07:00
Evan Simkowitz b4928780d2 Merge branch 'main' into evan/inshellisense-newton-merge 2024-04-23 17:50:04 -07:00
Evan Simkowitz a5e092e6c5 move pos to {cursor} if present 2024-04-23 17:45:25 -07:00
Mike Sawka 8f93b3e263 activity updates for v0.7.3 (#600)
* adding more activity updates, tabs, workspaces, startup/shutdown

* name change, allow activity updates from FE.  aichat + history opens

* activity updates for non-standard renderers
2024-04-23 17:40:14 -07:00
Evan Simkowitz 6a7ee12c10 Pull in loadSpec functions from evan/inshellisense branch 2024-04-23 17:32:45 -07:00
Evan Simkowitz f5af7ad283 Merge branch 'main' into evan/inshellisense-newton-merge 2024-04-23 17:05:45 -07:00
Evan Simkowitz eadfb92f94 Fix regression in the order of messages in the AI chat auxview (#597) 2024-04-23 16:35:33 -07:00
Evan Simkowitz a50db14b3e Fix improper formatting when AuxiliaryCmdView titlebar is missing (#596)
* Fix improper formatting when AuxiliaryCmdView titlebar is missing

* fix bad save
2024-04-23 16:16:41 -07:00
Evan Simkowitz 6308c6c4b0 Simplify scrollHistoryItemIntoView method (#595)
* Simplify scrollHistoryItemIntoView

* remove unnecessary block argument

* actually the block nearest is necessary, otherwise the scroll will jump even if the item is already in view
2024-04-23 15:38:02 -07:00
Red J Adaya cdfc446763 Improved tab settings pull down (#592)
* add label to tab settings terminal theme dropdown

* add connection label. add New Conection item

* fix wrong prop

* simplify logic

* fix conflicts
2024-04-23 13:14:56 -07:00
Cole Lashley b08aaa03fb Remove log for duplicate key register (#540)
* removed log for duplicate keybindings

* changed dumplogs to GlobalModel.isDev, and re added back log

* added back dumplogs

* one last dump logs
2024-04-23 12:30:03 -07:00
Cole Lashley 64244626a1 auxview focus + keybindings (#575)
* first draft of figuring out auxviews and focus

* added more focus logic

* fixed aichat focus issue

* fixed artifacts

* removed command

* addressed review comments
2024-04-23 11:47:55 -07:00
Cole Lashley c683d10008 Keybinding fixes (#591)
* keybinding fixes

* changed screen and session commands to functions rather than slash commands to avoid printing errors

* added a static wait for console commands

* added sleep hardcode

* add an isArray check for commandStr
2024-04-23 11:18:39 -07:00
Evan Simkowitz b115d04876 Merge branch 'main' into evan/inshellisense-newton-merge 2024-04-23 11:08:39 -07:00
Evan Simkowitz 265cc30347 Update electron-rebuild reference to @electron/rebuild as recommended by Yarn (#593) 2024-04-23 11:07:52 -07:00
Evan Simkowitz 5f755e6574 Merge branch 'main' into evan/inshellisense-newton-merge 2024-04-23 10:51:25 -07:00
Evan Simkowitz e04c5af41d Make the AuxiliaryCmdView title bar optional and more flexible (#588)
* Make the auxView tilebar optional and make sure it flows as part of the flexbox

* simplify condition

* fix ai chat scroll direction

* remove unnecessary change

* remove unused class
2024-04-23 10:50:56 -07:00
Yiheng Li 2b0b206614 fix: inline text edit button use onMouseDown (#579) 2024-04-23 10:44:15 -07:00
Mikael Eklund 7c63e24525 Issue #584 fix in package.json (#589) 2024-04-22 23:12:24 -07:00
Evan Simkowitz 0b74f4afcf bad merge 2024-04-22 19:48:02 -07:00
Evan Simkowitz 77706bf21e Merge branch 'evan/auxview-fix' into evan/inshellisense-newton-merge 2024-04-22 19:45:47 -07:00
Evan Simkowitz 6bd5931056 remove unused class 2024-04-22 19:40:48 -07:00
Evan Simkowitz e5ee4e4069 remove unnecessary change 2024-04-22 19:38:44 -07:00
Evan Simkowitz f05cb30dca fix ai chat scroll direction 2024-04-22 19:35:59 -07:00
Evan Simkowitz 260b29167d simplify condition 2024-04-22 19:32:44 -07:00
Evan Simkowitz e543538bae Make the auxView tilebar optional and make sure it flows as part of the flexbox 2024-04-22 19:30:30 -07:00
Evan Simkowitz bd7a83ba0e making auxview more flexible 2024-04-22 19:21:57 -07:00
Evan Simkowitz 5d1c92d643 prefix is pushing through well for option args with separators 2024-04-22 17:57:13 -07:00
Evan Simkowitz c6f187d65d support arg separators 2024-04-22 17:14:33 -07:00
Evan Simkowitz b476ab31c6 fixing more display issues 2024-04-22 15:46:40 -07:00
Evan Simkowitz 20b25a9272 Merge branch 'evan/inshellisense' into evan/inshellisense-newton-merge 2024-04-22 13:54:53 -07:00
Evan Simkowitz 35cf4b6a3b Merge branch 'main' into evan/inshellisense 2024-04-22 13:54:42 -07:00
Evan Simkowitz ff50e89156 save 2024-04-22 13:53:07 -07:00
Evan Simkowitz 024f46bf7b save work 2024-04-22 13:44:40 -07:00
Evan Simkowitz 73164e0152 almost there, just need to fix icon displays and reimplement the cached imports 2024-04-22 12:58:42 -07:00
Evan Simkowitz 0d40d6fff3 looking good 2024-04-22 12:15:47 -07:00
Evan Simkowitz 86cbba1f79 Got the results up to parity, next step is to work on performance 2024-04-19 19:01:11 -07:00
Sylvie Crowe 8fdcf10cae fix: ignore computer sleep for telemetry clock (#577)
* fix: ignore computer sleep for telemetry clock

This uses unix time with regular integer comparisons to prevent the
telemetry clock from needing to wait for 8 hours of the program running.
Now, it only needs to wait 8 real-time hours instead.

* drop telemetry time to 4 hours, tick every 10 minutes
2024-04-19 18:26:31 -07:00
Mike Sawka 6336f87cf2 tab context menu (w/ close tab option) (#583)
* create tab context menu (for close tab)

* small update to ctx menu, also make all tab deletes (including keybinding) not popup confirm modal if less than 10 blocks
2024-04-19 18:25:26 -07:00
Evan Simkowitz bdf17f0133 move Newton parser to its own file 2024-04-19 16:27:19 -07:00
Evan Simkowitz f5f0791b32 Merge branch 'evan/inshellisense' into evan/inshellisense-newton 2024-04-19 15:08:40 -07:00
Evan Simkowitz 899347e90f Merge branch 'main' into evan/inshellisense 2024-04-19 15:08:27 -07:00
Evan Simkowitz fbc5e1606b added suggestions for options 2024-04-19 15:06:26 -07:00
Sylvie Crowe 39ee41921f fix: add a new line when writing to knownhosts (#582)
This fixes issue #476 by ensuring that when waveterm writes to a
knownhosts file, a newline character is appended at the end.
2024-04-18 14:51:11 -07:00
Evan Simkowitz fde2ce97d2 save work 2024-04-17 10:29:32 -07:00
Evan Simkowitz 93845c405d Got mostly to parity with suggestions in the parser! 2024-04-16 18:01:18 -07:00
Sylvie Crowe 2913babea7 Sudo Caching (#573)
* feat: share sudo between pty sessions

This is a first pass at a feature to cache the sudo password and share
it between different pty sessions. This makes it possible to not require
manual password entry every time sudo is used.

* feat: allow error handling and canceling sudo cmds

This adds the missing functionality that prevented failed sudo commands
from automatically closing.

* feat: restrict sudo caching to dev mode for now

* modify fullCmdStr not pk.Command

* refactor: condense ecdh encryptor creation

This refactors the common pieces needed to create an encryptor from an
ecdh key pair into a common function.

* refactor: rename promptenc to waveenc

* feat: add command to clear sudo password

We currently do not provide use of the sudo -k and sudo -K commands to
clear the sudo password. This adds a /sudo:clear command to handle it in
the meantime.

* feat: add kwarg to force sudo

In cases where parsing for sudo doesn't work, this provides an alternate
wave kwarg to use instead. It can be used with [sudo=1] at the beginning
of a command.

* refactor: simplify sudoArg parsing

* feat: allow user to clear all sudo passwords

This introduces the "all" kwarg for the sudo:clear command in order to
clear all sudo passwords.

* fix: handle deadline with real time

Golang's time module uses monatomic time by default, but that is not
desired for the password timeout since we want the timer to continue
even if the computer is asleep. We now avoid this by directly comparing
the unix timestamps.

* fix: remove sudo restriction to dev mode

This allows it to be used in regular builds as well.

* fix: switch to password timeout without wait group

This removes an unnecessary waiting period for sudo password entry.

* fix: update deadline in sudo:clear

This allows sudo:clear to cancel the goroutine for watching the password
timer.

* fix: pluralize sudo:clear message when all=1

This changes the output message for /sudo:clear to indicate multiple
passwords cleared if the all=1 kwarg is used.

* fix: use GetRemoteMap for getting remotes in clear

The sudo:clear command was directly looping over the GlobalStore.Map
which is not thread safe. Switched to GetRemoteMap which uses a lock
internally.

* fix: allow sudo metacmd to set sudo false

This fixes the logic for resolving if a command is a sudo command. This
change makes it possible for the sudo metacmd kwarg to force sudo to be
false.
2024-04-16 16:58:17 -07:00
Mike Sawka a787a1a934 add k8s context/namespace to prompt (#576)
* k8s in prompt

* test/fix formatting
2024-04-16 13:22:58 -07:00
Cole Lashley bf447c60ce Custom keybind commands (#574)
* added custom keybindings

* removed logs
2024-04-16 12:46:27 -07:00
Evan Simkowitz f2b322c7d7 working to merge my parser into the inshellisense model 2024-04-15 20:22:47 -07:00
Evan Simkowitz c1bd5f5765 fix command execution 2024-04-15 17:22:25 -07:00
Evan Simkowitz b97c7e186d remove unnecessary debugs 2024-04-12 16:07:49 -07:00
Evan Simkowitz 0442fc84d4 update debugs to be more helpful 2024-04-12 16:04:05 -07:00
Evan Simkowitz 27efae3ad5 make the logic less gross 2024-04-12 16:03:27 -07:00
Evan Simkowitz 4d8c2cd242 remove unused import 2024-04-12 15:57:17 -07:00
Evan Simkowitz a560499b58 return filepaths when in doubt 2024-04-12 15:53:54 -07:00
Evan Simkowitz e8b489bcd9 add history and root spec 2024-04-12 15:35:45 -07:00
Evan Simkowitz 31c12c4705 remove and modify debugs 2024-04-11 18:25:35 -07:00
Evan Simkowitz 787bcbc9d8 replace logs with debugs 2024-04-11 18:23:34 -07:00
Evan Simkowitz 985304c9aa demote dotfiles and dotdirs 2024-04-11 18:19:00 -07:00
Evan Simkowitz 13cbfdeb6e fix isEnabled 2024-04-11 18:16:28 -07:00
Evan Simkowitz 53290b47e1 fix bad merge 2024-04-11 18:14:05 -07:00
Evan Simkowitz 4bdd092d33 remove lastCurLine from textareainput 2024-04-11 18:09:28 -07:00
Evan Simkowitz fb2b3dfc6a move import 2024-04-11 18:07:56 -07:00
Evan Simkowitz fa27964d49 move import 2024-04-11 18:06:58 -07:00
Evan Simkowitz 95132011e4 remove import 2024-04-11 18:06:43 -07:00
Evan Simkowitz dae4210b72 rename stuff and add comments 2024-04-11 18:03:04 -07:00
Evan Simkowitz e394ba70a6 move keybinding 2024-04-11 17:55:28 -07:00
Evan Simkowitz 483b2eff6f add right arrow to apply suggestion 2024-04-11 17:54:54 -07:00
Evan Simkowitz 2f4a6fa6e2 Merge branch 'main' into evan/inshellisense 2024-04-11 17:45:24 -07:00
Evan Simkowitz 4af1b19ffd fix lastCurLine 2024-04-11 17:41:11 -07:00
Evan Simkowitz 8b1d930cd6 move import 2024-04-11 17:38:24 -07:00
Evan Simkowitz a4e8648968 add placeholder div if no suggestions 2024-04-11 17:37:50 -07:00
Evan Simkowitz 429ea37419 change onclose 2024-04-11 17:23:16 -07:00
Evan Simkowitz a8f3e356f6 add keybindings 2024-04-11 17:22:51 -07:00
Evan Simkowitz 85235aaad8 move autocomplete to its own model, add more styling to suggestion view 2024-04-11 17:16:22 -07:00
Evan Simkowitz 619cfe4931 rudimentary show all autocomplete 2024-04-11 16:00:52 -07:00
Evan Simkowitz 11f1c3bb70 remove finished todos 2024-04-11 15:50:46 -07:00
Evan Simkowitz 8d140c9920 Add file and folder completions 2024-04-11 15:49:46 -07:00
Mike Sawka d923de412a add submenu support, add signal submenu to line context menu (#572) 2024-04-11 10:57:14 -07:00
Mike Sawka 15485d7235 New Context Menu Model (and implement custom block context menu) (#569)
* starting work on new dynamic context menu system

* untested contextmenu model integrated with electron api

* implement custom line context menu, copy visible output + copy full output

* implement minimize/maximize, restart, and delete
2024-04-10 23:47:33 -07:00
dependabot[bot] 59aef86e77 Bump tar from 6.2.0 to 6.2.1 (#568)
Bumps [tar](https://github.com/isaacs/node-tar) from 6.2.0 to 6.2.1.
- [Release notes](https://github.com/isaacs/node-tar/releases)
- [Changelog](https://github.com/isaacs/node-tar/blob/main/CHANGELOG.md)
- [Commits](https://github.com/isaacs/node-tar/compare/v6.2.0...v6.2.1)

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-04-10 23:46:43 -07:00
Evan Simkowitz 205a9d1e2e Merge branch 'main' into evan/inshellisense 2024-04-10 23:11:14 -07:00
Mike Sawka 5353f40a20 new sidebar UI (#567) 2024-04-10 22:15:11 -07:00
Evan Simkowitz d3139d51cf add new license 2024-04-10 22:08:08 -07:00
Evan Simkowitz 5c931de40c fix caching 2024-04-10 21:48:23 -07:00
Evan Simkowitz 497a96bfc2 adds trigger and begins to add caching 2024-04-10 17:20:51 -07:00
Knox Lively f86f010a34 updated the OpenAICloudCompletionTelemetryOffErrorMsg to include instructions for enabling telemetry (#564) 2024-04-09 22:14:42 -06:00
Evan Simkowitz 427447c592 Merge branch 'main' into evan/inshellisense 2024-04-09 17:11:25 -07:00
Evan Simkowitz 1fe5d425da set non-transparent colors for light mode, fix fuzzy letters issue with ghost prompt 2024-04-09 17:07:15 -07:00
Evan Simkowitz a395043a1c enforce setting 2024-04-09 16:40:47 -07:00
Evan Simkowitz ff9f9b43b6 Add client setting for autocomplete 2024-04-09 16:29:59 -07:00
Evan Simkowitz 98ba0b46ac clear suggestions in more places 2024-04-09 12:33:16 -07:00
Evan Simkowitz fb3253d018 cache last command 2024-04-09 12:22:27 -07:00
Evan Simkowitz 8d91d156aa handle flicker when deleting chars 2024-04-09 12:09:42 -07:00
Evan Simkowitz b7eec15853 Adding ghost text 2024-04-09 11:57:07 -07:00
Mike Sawka 73e5515e17 when the window gets focus, if our mainview is session (and no modals are open), refocus either the cmdinput or the cmd (#562) 2024-04-09 11:48:34 -07:00
Mike Sawka 6919dbfb5f force our exit trap to always run (for rtnstate commands) (#556)
* add command validation to shellapi.  mock out bash/zsh versions

* implement validate command fn bash and zsh

* test validate command

* change rtnstate commands to always end with a builtin, so we always get our exit trap to run

* simplify the rtnstate modification, don't add the 'wait' (as this is a different problem/feature)

* update schema
2024-04-09 11:33:23 -07:00
Evan Simkowitz 38ff6183a2 get suggestions on typing 2024-04-08 18:47:35 -07:00
87 changed files with 4898 additions and 1365 deletions
+22 -40
View File
@@ -107,12 +107,12 @@
{
"command": "app:openConnectionsView",
"keys": [],
"commandStr": "/mainview connections"
"commandStr": ["/mainview connections"]
},
{
"command": "app:openSettingsView",
"keys": [],
"commandStr": "/mainview clientsettings"
"commandStr": ["/mainview clientsettings"]
},
{
"command": "app:newTab",
@@ -149,48 +149,39 @@
},
{
"command": "app:selectTab-1",
"keys": ["Cmd:1"],
"commandStr":"/screen 1"
"keys": ["Cmd:1"]
},
{
"command": "app:selectTab-2",
"keys": ["Cmd:2"],
"commandStr":"/screen 2"
"keys": ["Cmd:2"]
},
{
"command": "app:selectTab-3",
"keys": ["Cmd:3"],
"commandStr":"/screen 3"
"keys": ["Cmd:3"]
},
{
"command": "app:selectTab-4",
"keys": ["Cmd:4"],
"commandStr":"/screen 4"
"keys": ["Cmd:4"]
},
{
"command": "app:selectTab-5",
"keys": ["Cmd:5"],
"commandStr":"/screen 5"
"keys": ["Cmd:5"]
},
{
"command": "app:selectTab-6",
"keys": ["Cmd:6"],
"commandStr":"/screen 6"
"keys": ["Cmd:6"]
},
{
"command": "app:selectTab-7",
"keys": ["Cmd:7"],
"commandStr":"/screen 7"
"keys": ["Cmd:7"]
},
{
"command": "app:selectTab-8",
"keys": ["Cmd:8"],
"commandStr":"/screen 8"
"keys": ["Cmd:8"]
},
{
"command": "app:selectTab-9",
"keys": ["Cmd:9"],
"commandStr":"/screen 9"
"keys": ["Cmd:9"]
},
{
"command": "app:selectTabLeft",
@@ -202,48 +193,39 @@
},
{
"command": "app:selectWorkspace-1",
"keys": ["Cmd:Ctrl:1"],
"commandStr": "/session 1"
"keys": ["Cmd:Ctrl:1"]
},
{
"command": "app:selectWorkspace-2",
"keys": ["Cmd:Ctrl:2"],
"commandStr": "/session 2"
"keys": ["Cmd:Ctrl:2"]
},
{
"command": "app:selectWorkspace-3",
"keys": ["Cmd:Ctrl:3"],
"commandStr": "/session 3"
"keys": ["Cmd:Ctrl:3"]
},
{
"command": "app:selectWorkspace-4",
"keys": ["Cmd:Ctrl:4"],
"commandStr": "/session 4"
"keys": ["Cmd:Ctrl:4"]
},
{
"command": "app:selectWorkspace-5",
"keys": ["Cmd:Ctrl:5"],
"commandStr": "/session 5"
"keys": ["Cmd:Ctrl:5"]
},
{
"command": "app:selectWorkspace-6",
"keys": ["Cmd:Ctrl:6"],
"commandStr": "/session 6"
"keys": ["Cmd:Ctrl:6"]
},
{
"command": "app:selectWorkspace-7",
"keys": ["Cmd:Ctrl:7"],
"commandStr": "/session 7"
"keys": ["Cmd:Ctrl:7"]
},
{
"command": "app:selectWorkspace-8",
"keys": ["Cmd:Ctrl:8"],
"commandStr": "/session 8"
"keys": ["Cmd:Ctrl:8"]
},
{
"command": "app:selectWorkspace-9",
"keys": ["Cmd:Ctrl:9"],
"commandStr": "/session 9"
"keys": ["Cmd:Ctrl:9"]
},
{
"command": "app:toggleSidebar",
@@ -256,7 +238,7 @@
{
"command": "app:openBookmarksView",
"keys": ["Cmd:b"],
"commandStr": "/bookmarks:show"
"commandStr": ["/bookmarks:show"]
},
{
"command": "bookmarks:edit",
@@ -301,7 +283,7 @@
{
"command": "cmdinput:openHistory",
"keys": ["Ctrl:r"],
"commandStr": "/history"
"commandStr": ["/history"]
},
{
"command": "cmdinput:openAIChat",
+6 -1
View File
@@ -18,6 +18,7 @@
"appId": "dev.commandline.waveterm"
},
"dependencies": {
"@lexical/react": "^0.14.3",
"@monaco-editor/react": "^4.5.1",
"@table-nav/core": "^0.0.7",
"@table-nav/react": "^0.0.7",
@@ -32,6 +33,7 @@
"electron-squirrel-startup": "^1.0.0",
"electron-updater": "^6.1.8",
"framer-motion": "^10.16.16",
"lexical": "^0.14.3",
"mobx": "6.12",
"mobx-react": "^7.5.0",
"monaco-editor": "^0.44.0",
@@ -45,14 +47,15 @@
"react-markdown": "^9.0.0",
"remark": "^15.0.1",
"remark-gfm": "^4.0.0",
"shell-quote": "^1.8.1",
"sprintf-js": "^1.1.2",
"throttle-debounce": "^5.0.0",
"tsx-control-statements": "^5.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-web-links": "^0.9.0",
"xterm-addon-webgl": "^0.16.0"
},
"devDependencies": {
@@ -67,6 +70,7 @@
"@babel/preset-env": "^7.18.2",
"@babel/preset-react": "^7.23.3",
"@babel/preset-typescript": "^7.17.12",
"@electron/rebuild": "^3.6.0",
"@svgr/webpack": "^8.1.0",
"@types/classnames": "^2.3.1",
"@types/electron": "^1.6.10",
@@ -74,6 +78,7 @@
"@types/papaparse": "^5.3.10",
"@types/react": "^18.0.12",
"@types/semver": "^7.5.6",
"@types/shell-quote": "^1.7.5",
"@types/sprintf-js": "^1.1.3",
"@types/throttle-debounce": "^5.0.1",
"@types/uuid": "^9.0.7",
+2 -2
View File
@@ -9,8 +9,8 @@
--app-accent-color: rgb(75, 166, 57);
--app-accent-bg-color: rgba(75, 166, 57, 0.2);
--app-text-color: rgb(0, 0, 0);
--app-text-primary-color: rgb(0, 0, 0, 0.9);
--app-text-secondary-color: rgb(0, 0, 0, 0.7);
--app-text-primary-color: rgb(23, 23, 23);
--app-text-secondary-color: rgb(76, 76, 76);
--app-border-color: rgb(139 145 138);
--app-panel-bg-color: rgb(224, 224, 224);
--app-panel-bg-color-dev: rgb(224, 224, 224);
+1 -1
View File
@@ -146,7 +146,7 @@ class App extends React.Component<{}, {}> {
<If condition={GlobalModel.isDev && rightSidebarCollapsed && activeMainView == "session"}>
<div className="right-sidebar-triggers">
<Button className="secondary ghost right-sidebar-trigger" onClick={this.openRightSidebar}>
<i className="fa-sharp fa-regular fa-lightbulb"></i>
<i className="fa-sharp fa-solid fa-sidebar-flip"></i>
</Button>
</div>
</If>
+1
View File
@@ -68,3 +68,4 @@ export const ErrorCode_InvalidCwd = "ERRCWD";
export const InputAuxView_History = "history";
export const InputAuxView_Info = "info";
export const InputAuxView_AIChat = "aichat";
export const InputAuxView_Suggestions = "suggestions";
+36 -5
View File
@@ -6,14 +6,14 @@ import * as mobxReact from "mobx-react";
import * as mobx from "mobx";
import { boundMethod } from "autobind-decorator";
import { If } from "tsx-control-statements/components";
import { GlobalModel, GlobalCommandRunner, RemotesModel, getApi } from "@/models";
import { Toggle, InlineSettingsTextEdit, SettingsError, Dropdown, Button } from "@/common/elements";
import { GlobalModel, GlobalCommandRunner, RemotesModel } 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 { MainView } from "@/common/elements/mainview";
import "./clientsettings.less";
import { MainView } from "@/common/elements/mainview";
class ClientSettingsKeybindings extends React.Component<{}, {}> {
componentDidMount() {
@@ -70,7 +70,7 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
return;
}
const prtn = GlobalCommandRunner.setTheme(themeSource, false);
getApi().setNativeThemeSource(themeSource);
GlobalModel.getElectronApi().setNativeThemeSource(themeSource);
commandRtnHandler(prtn, this.errorMessage);
}
@@ -107,7 +107,20 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
prtn = GlobalCommandRunner.releaseCheckAutoOff(false);
}
commandRtnHandler(prtn, this.errorMessage);
getApi().changeAutoUpdate(val);
GlobalModel.getElectronApi().changeAutoUpdate(val);
}
@boundMethod
handleChangeAutocompleteEnabled(val: boolean): void {
const prtn: Promise<CommandRtnType> = GlobalCommandRunner.setAutocompleteEnabled(val);
commandRtnHandler(prtn, this.errorMessage);
}
@boundMethod
handleChangeAutocompleteDebuggingEnabled(val: boolean): void {
mobx.action(() => {
GlobalModel.autocompleteModel.loggingEnabled = val;
})();
}
getFontSizes(): DropdownItem[] {
@@ -354,6 +367,24 @@ class ClientSettingsView extends React.Component<{ model: RemotesModel }, { hove
/>
</div>
</div>
<div className="settings-field">
<div className="settings-label">Command Autocomplete</div>
<div className="settings-input">
<Toggle
checked={cdata.clientopts.autocompleteenabled ?? false}
onChange={this.handleChangeAutocompleteEnabled}
/>
</div>
</div>
<div className="settings-field">
<div className="settings-label">Command Autocomplete Debugging</div>
<div className="settings-input">
<Toggle
checked={GlobalModel.autocompleteModel.loggingEnabled}
onChange={this.handleChangeAutocompleteDebuggingEnabled}
/>
</div>
</div>
<SettingsError errorMessage={this.errorMessage} />
</div>
</MainView>
+5 -2
View File
@@ -5,7 +5,7 @@
width: 100%;
border: 2px solid var(--form-element-border-color);
border-radius: 6px;
line-height: 22px;
line-height: 20px;
background: var(--form-element-bg-color);
&.no-label {
@@ -63,11 +63,14 @@
display: flex;
min-width: 120px;
padding: 5px 8px;
justify-content: space-between;
align-items: center;
align-self: stretch;
border-radius: 6px;
i {
margin-right: 8px;
}
&-highlighted,
&:hover {
background: rgba(241, 246, 243, 0.08);
+8 -6
View File
@@ -163,7 +163,7 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
if (isOpen) {
const option = options[highlightedIndex];
if (option) {
this.handleSelect(option.value, undefined);
this.handleSelect(option, undefined);
}
} else {
this.toggleDropdown();
@@ -185,18 +185,19 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
handleKeyDown(event: React.KeyboardEvent) {}
@boundMethod
handleSelect(value: string, event?: React.MouseEvent | React.KeyboardEvent) {
handleSelect({ value, noop }: DropdownItem, event?: React.MouseEvent | React.KeyboardEvent) {
const { onChange } = this.props;
if (event) {
event.stopPropagation(); // This stops the event from bubbling up to the wrapper
}
if (!("value" in this.props)) {
this.setState({ internalValue: value });
}
onChange(value);
this.setState({ isOpen: false, isTouched: true });
this.unregisterKeybindings();
if (!("value" in this.props) && !noop) {
this.setState({ internalValue: value });
}
}
@boundMethod
@@ -245,10 +246,11 @@ class Dropdown extends React.Component<DropdownProps, DropdownState> {
className={cn("wave-dropdown-item unselectable", {
"wave-dropdown-item-highlighted": index === highlightedIndex,
})}
onClick={(e) => this.handleSelect(option.value, e)}
onClick={(e) => this.handleSelect(option, e)}
onMouseEnter={() => this.setState({ highlightedIndex: index })}
onMouseLeave={() => this.setState({ highlightedIndex: -1 })}
>
{option.icon && <span className="wave-dropdown-item-icon">{option.icon}</span>}
{option.label}
</div>
))}
@@ -131,7 +131,7 @@ class InlineSettingsTextEdit extends React.Component<
</div>
<div className="control">
<div
onClick={this.cancelChange}
onMouseDown={this.cancelChange}
title="Cancel (Esc)"
className="button is-prompt-danger is-outlined is-small"
>
@@ -142,7 +142,7 @@ class InlineSettingsTextEdit extends React.Component<
</div>
<div className="control">
<div
onClick={this.confirmChange}
onMouseDown={this.confirmChange}
title="Confirm (Enter)"
className="button is-wave-green is-outlined is-small"
>
+2 -2
View File
@@ -5,7 +5,7 @@ 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";
@@ -26,7 +26,7 @@ class AboutModal extends React.Component<{}, {}> {
@boundMethod
updateApp(): void {
getApi().installAppUpdate();
GlobalModel.getElectronApi().installAppUpdate();
}
@boundMethod
+4
View File
@@ -58,4 +58,8 @@
.term-prompt-python {
color: var(--term-magenta);
}
.term-prompt-k8s {
color: var(--term-magenta);
}
}
+12 -1
View File
@@ -146,6 +146,7 @@ class Prompt extends React.Component<
let branchElem = null;
let pythonElem = null;
let condaElem = null;
let k8sElem = null;
if (!isBlank(festate["PROMPTVAR_GITBRANCH"])) {
const branchName = festate["PROMPTVAR_GITBRANCH"];
branchElem = (
@@ -171,9 +172,19 @@ class Prompt extends React.Component<
</span>
);
}
if (!isBlank(festate["K8SCONTEXT"])) {
const k8sContext = festate["K8SCONTEXT"];
const k8sNs = festate["K8SNAMESPACE"];
k8sElem = (
<span title="k8s context:namespace" className="term-prompt-k8s">
k8s:({k8sContext}
{isBlank(k8sNs) ? "" : ":" + k8sNs}){" "}
</span>
);
}
return (
<span className={termClassNames}>
{remoteElem} {cwdElem} {branchElem} {condaElem} {pythonElem}
{remoteElem} {cwdElem} {branchElem} {condaElem} {pythonElem} {k8sElem}
</span>
);
}
+78
View File
@@ -665,6 +665,83 @@ class LineCmd extends React.Component<
};
};
@boundMethod
handleContextMenu(e: React.MouseEvent) {
e.preventDefault();
e.stopPropagation();
let { line, screen } = this.props;
const containerType = screen.getContainerType();
const isMainContainer = containerType == appconst.LineContainer_Main;
const cmd = screen.getCmd(line);
let menu: ContextMenuItem[] = [
{ role: "copy", label: "Copy", type: "normal" },
{ role: "paste", label: "Paste", type: "normal" },
{ type: "separator" },
{ label: "Copy Command", click: () => this.copyCommandStr() },
];
const isTerminal = isBlank(line.renderer) || line.renderer == "terminal";
if (isTerminal) {
menu.push({ label: "Copy Visible Output", click: () => this.copyOutput(false) });
menu.push({ label: "Copy Full Output", click: () => this.copyOutput(true) });
}
if (isMainContainer) {
menu.push({ type: "separator" });
const isMinimized = line.linestate["wave:min"];
if (isMinimized) {
menu.push({
label: "Show Block Output",
click: () => GlobalCommandRunner.lineMinimize(line.lineid, false, true),
});
} else {
menu.push({
label: "Hide Block Output",
click: () => GlobalCommandRunner.lineMinimize(line.lineid, true, true),
});
}
if (cmd?.isRunning()) {
menu.push({ type: "separator" });
menu.push({
label: "Send Signal",
type: "submenu",
submenu: [
{ label: "SIGINT", click: () => GlobalCommandRunner.lineSignal(line.lineid, "SIGINT", true) },
{ label: "SIGTERM", click: () => GlobalCommandRunner.lineSignal(line.lineid, "SIGTERM", true) },
{ label: "SIGKILL", click: () => GlobalCommandRunner.lineSignal(line.lineid, "SIGKILL", true) },
{ type: "separator" },
{ label: "SIGUSR1", click: () => GlobalCommandRunner.lineSignal(line.lineid, "SIGUSR1", true) },
{ label: "SIGUSR2", click: () => GlobalCommandRunner.lineSignal(line.lineid, "SIGUSR2", true) },
],
});
}
menu.push({ type: "separator" });
menu.push({ label: "Restart Line", click: () => GlobalCommandRunner.lineRestart(line.lineid, true) });
menu.push({ type: "separator" });
menu.push({ label: "Delete Block", click: () => GlobalCommandRunner.lineDelete(line.lineid, true) });
}
GlobalModel.contextMenuModel.showContextMenu(menu, { x: e.clientX, y: e.clientY });
}
copyCommandStr() {
const { line, screen } = this.props;
const cmd: Cmd = screen.getCmd(line);
if (cmd != null) {
navigator.clipboard.writeText(cmd.getCmdStr());
}
}
copyOutput(fullOutput: boolean) {
const { line, screen } = this.props;
let termWrap = screen.getTermWrap(line.lineid);
if (termWrap == null) {
return;
}
let outputStr = termWrap.getOutput(fullOutput);
if (fullOutput != null) {
navigator.clipboard.writeText(outputStr);
}
}
render() {
const { screen, line, width, staticRender, visible } = this.props;
const isVisible = visible.get();
@@ -750,6 +827,7 @@ class LineCmd extends React.Component<
data-lineid={line.lineid}
data-linenum={line.linenum}
data-screenid={line.screenid}
onContextMenu={this.handleContextMenu}
>
<If condition={isSelected || cmdError}>
<div key="mask" className={cn("line-mask", { "error-mask": cmdError })}></div>
+17
View File
@@ -22,6 +22,23 @@
border-bottom: 1px solid var(--app-border-color);
}
.rsb-modes {
display: flex;
flex-direction: row;
padding: 5px 10px;
gap: 5px;
border-bottom: 1px solid var(--app-border-color);
.icon-container {
padding: 2px;
cursor: pointer;
}
.icon-container:hover {
background-color: var(--app-selected-mask-color);
}
}
&.collapsed {
display: none;
}
+34 -2
View File
@@ -1,14 +1,16 @@
// Copyright 2023, Command Line Inc.
// Copyright 2023-2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
import * as React from "react";
import * as mobxReact from "mobx-react";
import * as mobx from "mobx";
import dayjs from "dayjs";
import { If, For } from "tsx-control-statements/components";
import localizedFormat from "dayjs/plugin/localizedFormat";
import { GlobalModel } from "@/models";
import { ResizableSidebar, Button } from "@/elements";
import { WaveBookDisplay } from "./wavebook";
import "./right.less";
@@ -55,6 +57,14 @@ class KeybindDevPane extends React.Component<{}, {}> {
@mobxReact.observer
class RightSideBar extends React.Component<RightSideBarProps, {}> {
mode: OV<string> = mobx.observable.box(null, { name: "RightSideBar-mode" });
setMode(mode: string) {
mobx.action(() => {
this.mode.set(mode);
})();
}
render() {
return (
<ResizableSidebar
@@ -71,9 +81,31 @@ class RightSideBar extends React.Component<RightSideBarProps, {}> {
<i className="fa-sharp fa-regular fa-xmark"></i>
</Button>
</div>
<If condition={GlobalModel.isDev}>
<div className="rsb-modes">
<div className="flex-spacer" />
<If condition={GlobalModel.isDev}>
<div
className="icon-container"
title="Show Keybinding Debugger"
onClick={() => this.setMode("keybind")}
>
<i className="fa-fw fa-sharp fa-keyboard fa-solid" />
</div>
</If>
<div
className="icon-container"
title="Show Keybinding Debugger"
onClick={() => this.setMode("wavebook")}
>
<i className="fa-sharp fa-solid fa-book-sparkles"></i>
</div>
</div>
<If condition={this.mode.get() == "keybind"}>
<KeybindDevPane></KeybindDevPane>
</If>
<If condition={this.mode.get() == "wavebook"}>
<WaveBookDisplay></WaveBookDisplay>
</If>
</React.Fragment>
)}
</ResizableSidebar>
+53
View File
@@ -0,0 +1,53 @@
// Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
import * as React from "react";
import * as mobxReact from "mobx-react";
import * as mobx from "mobx";
import { If, For } from "tsx-control-statements/components";
import { GlobalModel } from "@/models";
import * as lexical from "lexical";
import { AutoFocusPlugin } from "@lexical/react/LexicalAutoFocusPlugin";
import { LexicalComposer } from "@lexical/react/LexicalComposer";
import { RichTextPlugin } from "@lexical/react/LexicalRichTextPlugin";
import { ContentEditable } from "@lexical/react/LexicalContentEditable";
import { HistoryPlugin } from "@lexical/react/LexicalHistoryPlugin";
import LexicalErrorBoundary from "@lexical/react/LexicalErrorBoundary";
import { MarkdownShortcutPlugin } from "@lexical/react/LexicalMarkdownShortcutPlugin";
import { $convertFromMarkdownString, $convertToMarkdownString, TRANSFORMERS } from "@lexical/markdown";
import { CodeNode, CodeHighlightNode } from "@lexical/code";
import { LinkNode } from "@lexical/link";
import { ListNode, ListItemNode } from "@lexical/list";
import { HeadingNode, QuoteNode } from "@lexical/rich-text";
import { HorizontalRuleNode } from "@lexical/react/LexicalHorizontalRuleNode";
import { KeybindManager } from "@/util/keyutil";
const theme = {
// Theme styling goes here
};
class WaveBookKeybindings extends React.Component<{}, {}> {
componentDidMount(): void {
const keybindManager = GlobalModel.keybindManager;
keybindManager.registerKeybinding("pane", "wavebook", "generic:confirm", (waveEvent) => {
return true;
});
}
componentWillUnmount(): void {
const keybindManager = GlobalModel.keybindManager;
keybindManager.unregisterDomain("wavebook");
}
render() {
return null;
}
}
@mobxReact.observer
class WaveBookDisplay extends React.Component<{}, {}> {
render() {
return "playbooks";
}
}
export { WaveBookDisplay };
+64 -62
View File
@@ -1,70 +1,72 @@
.cmd-aichat {
padding-bottom: 0 !important;
.auxview-content {
flex-flow: column nowrap;
.chat-window {
display: flex;
overflow-y: auto;
margin-bottom: 5px;
flex-direction: column;
height: 100%;
.chat-window {
overflow-y: auto;
margin-bottom: 5px;
// This is the filler that will push the chat messages to the bottom until the chat window is full
.filler {
flex: 1 1 auto;
flex-direction: column-reverse;
}
.chat-input {
padding: 0.5em 0.5em 0.5em 0.5em;
flex: 1 0 auto;
.chat-textarea {
color: var(--app-text-primary-color);
background-color: var(--cmdinput-textarea-bg);
resize: none;
width: 100%;
border: transparent;
outline: none;
overflow: auto;
overflow-wrap: anywhere;
font-family: var(--termfontfamily);
font-weight: normal;
line-height: var(--termlineheight);
}
}
.chat-msg {
margin-top: calc(var(--termpad) * 2);
margin-bottom: calc(var(--termpad) * 2);
.chat-msg-header {
display: flex;
margin-bottom: 2px;
i {
margin-right: 0.5em;
}
.chat-username {
font-weight: bold;
margin-right: 5px;
}
}
}
.chat-msg-assistant {
color: var(--app-text-color);
}
.chat-msg-user {
.msg-text {
font-family: var(--markdown-font);
font-size: 14px;
white-space: pre-wrap;
}
}
.chat-msg-error {
color: var(--cmdinput-text-error);
font-family: var(--markdown-font);
font-size: 14px;
}
}
.chat-input {
padding: 0.5em 0.5em 0.5em 0.5em;
flex: 0 0 auto;
.chat-textarea {
color: var(--app-text-primary-color);
background-color: var(--cmdinput-textarea-bg);
resize: none;
width: 100%;
border: transparent;
outline: none;
overflow: auto;
overflow-wrap: anywhere;
font-family: var(--termfontfamily);
font-weight: normal;
line-height: var(--termlineheight);
}
}
.chat-msg {
margin-top: calc(var(--termpad) * 2);
margin-bottom: calc(var(--termpad) * 2);
.chat-msg-header {
display: flex;
margin-bottom: 2px;
i {
margin-right: 0.5em;
}
.chat-username {
font-weight: bold;
margin-right: 5px;
}
}
}
.chat-msg-assistant {
color: var(--app-text-color);
}
.chat-msg-user {
.msg-text {
font-family: var(--markdown-font);
font-size: 14px;
white-space: pre-wrap;
}
}
.chat-msg-error {
color: var(--cmdinput-text-error);
font-family: var(--markdown-font);
font-size: 14px;
}
}
+7 -19
View File
@@ -9,6 +9,7 @@ import { boundMethod } from "autobind-decorator";
import { If, For } from "tsx-control-statements/components";
import { Markdown } from "@/elements";
import { AuxiliaryCmdView } from "./auxview";
import * as appconst from "@/app/appconst";
import "./aichat.less";
@@ -56,18 +57,13 @@ class AIChat extends React.Component<{}, {}> {
chatListKeyCount: number = 0;
chatWindowScrollRef: React.RefObject<HTMLDivElement>;
textAreaRef: React.RefObject<HTMLTextAreaElement>;
isFocused: OV<boolean>;
termFontSize: number = 14;
constructor(props: any) {
super(props);
this.chatWindowScrollRef = React.createRef();
this.textAreaRef = React.createRef();
this.isFocused = mobx.observable.box(false, {
name: "aichat-isfocused",
});
}
componentDidMount() {
const inputModel = GlobalModel.inputModel;
if (this.chatWindowScrollRef?.current != null) {
@@ -92,7 +88,7 @@ class AIChat extends React.Component<{}, {}> {
}
submitChatMessage(messageStr: string) {
const curLine = GlobalModel.inputModel.getCurLine();
const curLine = GlobalModel.inputModel.curLine;
const prtn = GlobalModel.submitChatInfoCommand(messageStr, curLine, false);
prtn.then((rtn) => {
if (!rtn.success) {
@@ -109,13 +105,14 @@ class AIChat extends React.Component<{}, {}> {
onTextAreaFocused(e: any) {
mobx.action(() => {
this.isFocused.set(true);
GlobalModel.inputModel.setAuxViewFocus(true);
})();
this.onTextAreaChange(e);
}
onTextAreaBlur(e: any) {
mobx.action(() => {
this.isFocused.set(false);
GlobalModel.inputModel.setAuxViewFocus(false);
})();
}
@@ -237,17 +234,7 @@ class AIChat extends React.Component<{}, {}> {
render() {
const chatMessageItems = GlobalModel.inputModel.AICmdInfoChatItems.slice();
const chitem: OpenAICmdInfoChatMessageType = null;
const renderKeybindings = mobx
.computed(() => {
return (
this.isFocused.get() ||
GlobalModel.inputModel.hasFocus() ||
(GlobalModel.getActiveScreen().getFocusType() == "input" &&
GlobalModel.activeMainView.get() == "session")
);
})
.get();
const renderKeybindings = GlobalModel.inputModel.shouldRenderAuxViewKeybindings(appconst.InputAuxView_AIChat);
return (
<AuxiliaryCmdView
title="Wave AI"
@@ -259,6 +246,7 @@ class AIChat extends React.Component<{}, {}> {
<AIChatKeybindings AIChatObject={this}></AIChatKeybindings>
</If>
<div className="chat-window" ref={this.chatWindowScrollRef}>
<div className="filler"></div>
<For each="chitem" index="idx" of={chatMessageItems}>
{this.renderChatMessage(chitem)}
</For>
+10 -9
View File
@@ -1,21 +1,18 @@
// For the additonal views, we want less padding on the top and bottom than we want for the base-cmdinput div
.auxview {
padding: var(--termpad) calc(var(--termpad) * 2) var(--termpad) calc(var(--termpad) * 3 - 1px);
overflow: auto;
flex-shrink: 1;
width: 100%;
display: flex;
flex-direction: column;
overflow: hidden;
height: 100%;
--auxview-titlebar-height: 18px;
.auxview-titlebar {
position: absolute;
z-index: 22;
top: 0;
left: 0;
background-color: var(--app-panel-bg-color);
color: var(--term-blue);
padding: 6px 10px 6px 10px;
display: flex;
flex: 0 0 auto;
flex-direction: row;
width: 100%;
border-bottom: 1px solid var(--app-border-color);
@@ -23,6 +20,7 @@
user-select: none;
cursor: default;
line-height: var(--auxview-titlebar-height);
overflow: hidden;
.title-string {
font-weight: bold;
@@ -46,6 +44,9 @@
.auxview-content {
display: flex;
padding-top: calc(var(--auxview-titlebar-height) + 6px);
flex-flow: column nowrap;
flex: 1 1 auto;
padding: var(--termpad) calc(var(--termpad) * 2) var(--termpad) calc(var(--termpad) * 3 - 1px);
overflow-y: auto;
}
}
+37 -23
View File
@@ -3,26 +3,28 @@
import * as React from "react";
import cn from "classnames";
import { If } from "tsx-control-statements/components";
import { Choose, If, Otherwise, When } from "tsx-control-statements/components";
import { observer } from "mobx-react";
import "./auxview.less";
import { OverlayScrollbarsComponent } from "overlayscrollbars-react";
export class AuxiliaryCmdView extends React.Component<
{
title: string;
className?: string;
iconClass?: string;
titleBarContents?: React.ReactElement[];
children?: React.ReactNode;
onClose?: React.MouseEventHandler<HTMLDivElement>;
},
{}
> {
render() {
const { title, className, iconClass, titleBarContents, children, onClose } = this.props;
interface AuxiliaryCmdViewProps {
title: string;
className?: string;
iconClass?: string;
titleBarContents?: React.ReactElement[];
children?: React.ReactNode;
onClose?: React.MouseEventHandler<HTMLDivElement>;
scrollable?: boolean;
}
return (
<div className={cn("auxview", className)}>
export const AuxiliaryCmdView: React.FC<AuxiliaryCmdViewProps> = observer((props) => {
const { title, className, iconClass, titleBarContents, children, onClose } = props;
return (
<div className={cn("auxview", className)}>
<If condition={title || onClose || titleBarContents || iconClass}>
<div className="auxview-titlebar">
<If condition={iconClass != null}>
<div className="title-icon">
@@ -41,10 +43,22 @@ export class AuxiliaryCmdView extends React.Component<
</div>
</If>
</div>
<If condition={children != null}>
<div className="auxview-content">{children}</div>
</If>
</div>
);
}
}
</If>
<If condition={children != null}>
<Choose>
<When condition={props.scrollable}>
<OverlayScrollbarsComponent
className="auxview-content"
options={{ scrollbars: { autoHide: "leave" } }}
>
{children}
</OverlayScrollbarsComponent>
</When>
<Otherwise>
<div className="auxview-content">{children}</div>
</Otherwise>
</Choose>
</If>
</div>
);
});

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