merge into sylvie/entirely-internal-connection

This commit is contained in:
Sylvia Crowe 2024-12-11 14:44:04 -08:00
commit 13933ed51b
25 changed files with 205 additions and 120 deletions

View File

@ -63,9 +63,14 @@ jobs:
with:
node-version: ${{env.NODE_VERSION}}
- name: Install Yarn
run: |
corepack enable
yarn install
uses: nick-fields/retry@v3
with:
command: |
corepack enable
yarn install
timeout_minutes: 5
retry_on: error
max_attempts: 3
- name: Install Task
uses: arduino/setup-task@v2
with:

View File

@ -47,9 +47,14 @@ jobs:
with:
node-version: ${{env.NODE_VERSION}}
- name: Install Yarn
run: |
corepack enable
yarn install
uses: nick-fields/retry@v3
with:
command: |
corepack enable
yarn install
timeout_minutes: 5
retry_on: error
max_attempts: 3
- name: Install Task
uses: arduino/setup-task@v2
with:

View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 27.8.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
version="1.1"
id="Layer_1"
x="0px"
y="0px"
viewBox="0 0 600 500"
xml:space="preserve"
width="600"
height="500"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs2">
</defs>
<style
type="text/css"
id="style1">
.st0{fill:url(#SVGID_1_);}
.st1{fill:url(#SVGID_00000123405442604648655120000000636425700907447225_);}
.st2{fill:#FFFFFF;}
.st3{fill:#58C142;}
.st4{fill:url(#SVGID_00000100361222533905006500000012948355425597525920_);}
.st5{fill:url(#SVGID_00000039098984540155201650000005728924474174226367_);}
.st6{fill:url(#SVGID_00000065066116668922763670000009055193333651929737_);}
.st7{fill:url(#SVGID_00000046310373342220590360000000833566212213317053_);}
.st8{fill:url(#SVGID_00000067914870925445215340000010520730682335284873_);}
.st9{fill:url(#SVGID_00000139972009352615321800000011748188400644384138_);}
.st10{fill:url(#SVGID_00000137813723102203423940000002281677718566419372_);}
.st11{fill:url(#SVGID_00000117658585713214366330000001759073570098750902_);}
.st12{fill:url(#SVGID_00000075146307645666362690000001517567647835044244_);}
.st13{fill:url(#SVGID_00000169553343881037582000000012883033354483876241_);}
</style>
<path
id="path1"
style="opacity:0.5"
d="M 422.51172 66.083984 L 421.53516 70.652344 C 417.33083 90.353994 411.35644 104.70464 403.55469 113.80273 C 395.75293 122.90082 386.35602 127.19727 373.125 127.19727 C 357.05867 127.19727 328.16184 112.92204 294.49219 98.072266 C 260.82253 83.222496 221.69145 68.097656 181.52539 68.097656 C 127.92402 68.097656 86.532969 85.316144 57.154297 120.12109 C 27.775625 154.92604 10.372512 206.67398 2.359375 275.61719 L 1.7988281 280.44531 L 56.220703 288.37109 L 57.820312 285.08594 C 65.25609 269.82303 73.831666 256.48454 83.539062 244.92969 C 115.47278 207.26926 160.3376 188.19727 218.22461 188.19727 C 267.79258 188.19727 315.46055 209.65071 354.36328 227.25195 C 364.9643 232.05241 375.79071 236.95346 385.39453 240.70312 C 394.99835 244.45279 403.07423 247.19727 409.82617 247.19727 C 413.82609 247.19727 421.48246 246.93422 428.1582 240.54688 C 434.83282 234.1606 440.60643 222.69513 445.21289 201.15234 L 445.21484 201.14062 L 448.83008 184.4082 L 465.81445 186.8457 L 536.40039 197.00391 L 537.86523 193.35938 C 549.29245 164.89336 556.96239 130.75308 561.09766 90.8125 L 561.59375 86.029297 L 422.51172 66.083984 z M 430.16992 77.285156 L 550.5293 94.546875 C 546.54141 130.02571 539.65046 160.47664 529.87305 185.96094 L 467.23633 176.94727 L 441.02148 173.18555 L 435.4375 199.04688 L 435.4375 199.05273 C 431.04434 219.60293 425.5684 229.18482 421.24414 233.32227 C 416.91988 237.45972 413.82625 237.19727 409.82617 237.19727 C 406.27811 237.19727 398.25262 234.99096 389.03125 231.39062 C 379.80988 227.79029 369.08726 222.94212 358.48828 218.14258 L 358.48633 218.14258 C 319.58934 200.54395 270.65598 178.19727 218.22461 178.19727 C 158.11161 178.19727 109.77644 198.52332 75.910156 238.46289 L 75.904297 238.47266 L 75.896484 238.48047 C 66.334868 249.85786 57.917521 262.87758 50.539062 277.43945 L 12.957031 271.96484 C 21.093315 206.62731 37.997403 158.32164 64.796875 126.57227 C 92.267813 94.027406 130.02676 78.097656 181.52539 78.097656 C 219.15933 78.097656 257.12688 92.522626 290.45703 107.22266 C 323.78718 121.92269 351.79133 137.19727 373.125 137.19727 C 388.69398 137.19727 401.64785 131.39136 411.14648 120.31445 C 419.90416 110.10161 425.83921 95.599976 430.16992 77.285156 z " /><path
id="path2"
d="M 459.22266 199.48242 L 458.23828 204.04102 C 453.98366 223.74923 448.00562 238.11003 440.21484 247.20898 C 432.42406 256.30792 423.05719 260.59766 409.82617 260.59766 C 393.75984 260.59766 364.8635 246.32243 331.19336 231.47266 C 297.52322 216.62289 258.39067 201.49609 218.22461 201.49609 C 164.62324 201.49609 123.21048 218.7172 93.806641 253.52148 C 64.402803 288.32575 46.972258 340.07318 38.958984 409.01758 L 38.398438 413.85156 L 177.46289 433.91602 L 178.41992 429.31641 C 182.67718 408.86198 188.65729 394.54154 196.40625 385.66016 C 204.15521 376.77878 213.50835 372.79687 226.82617 372.79688 C 243.74405 372.79688 272.14189 387.06214 305.43945 401.91406 C 338.73701 416.76597 377.53367 431.89648 418.42578 431.89648 C 472.02715 431.89648 513.79622 414.69411 543.39648 379.88672 C 572.99675 345.07936 590.43695 293.29532 597.69727 224.32227 L 598.20117 219.53516 L 459.22266 199.48242 z M 466.85938 210.68945 L 587.14062 228.04492 C 579.69967 293.3732 562.78246 341.65675 535.7793 373.41016 C 508.10515 405.95259 469.92441 421.89648 418.42578 421.89648 C 380.01789 421.89648 342.46592 407.48109 309.51367 392.7832 C 276.56143 378.08531 248.80829 362.79687 226.82617 362.79688 C 211.344 362.79688 198.39753 368.16536 188.87109 379.08398 C 180.07127 389.1698 174.12897 403.7467 169.75977 422.70312 L 49.556641 405.35742 C 57.694304 340.025 74.622873 291.72143 101.44531 259.97266 C 128.94089 227.42713 166.72598 211.49609 218.22461 211.49609 C 255.85855 211.49609 293.82756 225.92105 327.1582 240.62109 C 360.48884 255.32113 388.4925 270.59766 409.82617 270.59766 C 425.39515 270.59766 438.32691 264.787 447.81055 253.71094 C 456.55539 243.49774 462.49009 229.00119 466.85938 210.68945 z " />
</svg>

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 27.8.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
version="1.1"
id="Layer_1"
x="0px"
y="0px"
viewBox="0 0 600 500"
xml:space="preserve"
width="600"
height="500"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs2">
</defs>
<style
type="text/css"
id="style1">
.st0{fill:url(#SVGID_1_);}
.st1{fill:url(#SVGID_00000123405442604648655120000000636425700907447225_);}
.st2{fill:#FFFFFF;}
.st3{fill:#58C142;}
.st4{fill:url(#SVGID_00000100361222533905006500000012948355425597525920_);}
.st5{fill:url(#SVGID_00000039098984540155201650000005728924474174226367_);}
.st6{fill:url(#SVGID_00000065066116668922763670000009055193333651929737_);}
.st7{fill:url(#SVGID_00000046310373342220590360000000833566212213317053_);}
.st8{fill:url(#SVGID_00000067914870925445215340000010520730682335284873_);}
.st9{fill:url(#SVGID_00000139972009352615321800000011748188400644384138_);}
.st10{fill:url(#SVGID_00000137813723102203423940000002281677718566419372_);}
.st11{fill:url(#SVGID_00000117658585713214366330000001759073570098750902_);}
.st12{fill:url(#SVGID_00000075146307645666362690000001517567647835044244_);}
.st13{fill:url(#SVGID_00000169553343881037582000000012883033354483876241_);}
</style>
<path
id="path1"
d="M 422.51172 66.083984 L 421.53516 70.652344 C 417.33083 90.353994 411.35644 104.70464 403.55469 113.80273 C 395.75293 122.90082 386.35602 127.19727 373.125 127.19727 C 357.05867 127.19727 328.16184 112.92204 294.49219 98.072266 C 260.82253 83.222496 221.69145 68.097656 181.52539 68.097656 C 127.92402 68.097656 86.532969 85.316144 57.154297 120.12109 C 27.775625 154.92604 10.372511 206.67398 2.359375 275.61719 L 1.7988281 280.44531 L 56.220703 288.37109 L 57.820312 285.08594 C 65.25609 269.82303 73.831666 256.48454 83.539062 244.92969 C 115.47278 207.26926 160.3376 188.19727 218.22461 188.19727 C 267.79258 188.19727 315.46055 209.65071 354.36328 227.25195 C 364.9643 232.05241 375.79071 236.95346 385.39453 240.70312 C 394.99835 244.45279 403.07423 247.19727 409.82617 247.19727 C 413.82609 247.19727 421.48246 246.93422 428.1582 240.54688 C 434.83282 234.1606 440.60643 222.69513 445.21289 201.15234 L 445.21484 201.14062 L 448.83008 184.4082 L 465.81445 186.8457 L 536.40039 197.00391 L 537.86523 193.35938 C 549.29245 164.89336 556.96239 130.75308 561.09766 90.8125 L 561.59375 86.029297 L 422.51172 66.083984 z M 430.16992 77.285156 L 550.5293 94.546875 C 546.54141 130.02571 539.65046 160.47664 529.87305 185.96094 L 467.23633 176.94727 L 441.02148 173.18555 L 435.4375 199.04688 L 435.4375 199.05273 C 431.04434 219.60293 425.5684 229.18482 421.24414 233.32227 C 416.91988 237.45972 413.82625 237.19727 409.82617 237.19727 C 406.27811 237.19727 398.25262 234.99096 389.03125 231.39062 C 379.80988 227.79029 369.08726 222.94212 358.48828 218.14258 L 358.48633 218.14258 C 319.58934 200.54395 270.65598 178.19727 218.22461 178.19727 C 158.11161 178.19727 109.77644 198.52332 75.910156 238.46289 L 75.904297 238.47266 L 75.896484 238.48047 C 66.334868 249.85786 57.917521 262.87758 50.539062 277.43945 L 12.957031 271.96484 C 21.093315 206.62731 37.997403 158.32164 64.796875 126.57227 C 92.267813 94.027406 130.02676 78.097656 181.52539 78.097656 C 219.15933 78.097656 257.12688 92.522626 290.45703 107.22266 C 323.78718 121.92269 351.79133 137.19727 373.125 137.19727 C 388.69398 137.19727 401.64785 131.39136 411.14648 120.31445 C 419.90416 110.10161 425.83921 95.599976 430.16992 77.285156 z M 459.22266 199.48242 L 458.23828 204.04102 C 453.98366 223.74923 448.00562 238.11003 440.21484 247.20898 C 432.42406 256.30792 423.05719 260.59766 409.82617 260.59766 C 393.75984 260.59766 364.8635 246.32243 331.19336 231.47266 C 297.52322 216.62289 258.39067 201.49609 218.22461 201.49609 C 164.62324 201.49609 123.21048 218.7172 93.806641 253.52148 C 64.402803 288.32575 46.972258 340.07318 38.958984 409.01758 L 38.398438 413.85156 L 177.46289 433.91602 L 178.41992 429.31641 C 182.67718 408.86198 188.65729 394.54154 196.40625 385.66016 C 204.15521 376.77878 213.50835 372.79687 226.82617 372.79688 C 243.74405 372.79688 272.14189 387.06214 305.43945 401.91406 C 338.73701 416.76597 377.53367 431.89648 418.42578 431.89648 C 472.02715 431.89648 513.79622 414.69411 543.39648 379.88672 C 572.99675 345.07936 590.43695 293.29532 597.69727 224.32227 L 598.20117 219.53516 L 459.22266 199.48242 z M 466.85938 210.68945 L 587.14062 228.04492 C 579.69967 293.3732 562.78246 341.65675 535.7793 373.41016 C 508.10515 405.95259 469.92441 421.89648 418.42578 421.89648 C 380.01789 421.89648 342.46592 407.48109 309.51367 392.7832 C 276.56143 378.08531 248.80829 362.79687 226.82617 362.79688 C 211.344 362.79688 198.39753 368.16536 188.87109 379.08398 C 180.07127 389.1698 174.12897 403.7467 169.75977 422.70312 L 49.556641 405.35742 C 57.694304 340.025 74.622873 291.72143 101.44531 259.97266 C 128.94089 227.42713 166.72598 211.49609 218.22461 211.49609 C 255.85855 211.49609 293.82756 225.92105 327.1582 240.62109 C 360.48884 255.32113 388.4925 270.59766 409.82617 270.59766 C 425.39515 270.59766 438.32691 264.787 447.81055 253.71094 C 456.55539 243.49774 462.49009 229.00119 466.85938 210.68945 z " />
</svg>

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

@ -1,8 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 27.8.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 600 400" style="enable-background:new 0 0 600 400;" xml:space="preserve">
<style type="text/css">
<svg
version="1.1"
id="Layer_1"
x="0px"
y="0px"
viewBox="0 0 600 500"
xml:space="preserve"
width="600"
height="500"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs2">
</defs>
<style
type="text/css"
id="style1">
.st0{fill:url(#SVGID_1_);}
.st1{fill:url(#SVGID_00000123405442604648655120000000636425700907447225_);}
.st2{fill:#FFFFFF;}
@ -18,11 +34,9 @@
.st12{fill:url(#SVGID_00000075146307645666362690000001517567647835044244_);}
.st13{fill:url(#SVGID_00000169553343881037582000000012883033354483876241_);}
</style>
<g>
<path d="M218.2,133.2c51,0,99.3,21.9,138.2,39.5c21.2,9.6,43.1,19.5,53.4,19.5c8,0,21.5,0,30.5-42.1l4.6-21.3l21.6,3.1l66.7,9.6
c11.2-27.9,18.8-61.6,22.9-101.2L426.4,21.7c-8.6,40.3-24.5,60.5-53.3,60.5c-37.4,0-113.8-59.1-191.6-59.1
C76.4,23.1,23.2,89.4,7.3,226.2l46,6.7c7.6-15.6,16.4-29.3,26.4-41.2C112.6,152.9,159.2,133.2,218.2,133.2z"/>
<path d="M409.8,215.6c-37.4,0-113.8-59.1-191.6-59.1c-105.1,0-158.4,66.3-174.3,203.1l129.6,18.7c8.7-41.8,24.5-60.5,53.3-60.5
c38.9,0,112.3,59.1,191.6,59.1c105.1,0,159.9-66.3,174.3-203.1l-129.6-18.7C454.4,195.4,438.6,215.6,409.8,215.6z"/>
</g>
<path
d="m 218.2,183.2 c 51,0 99.3,21.9 138.2,39.5 21.2,9.6 43.1,19.5 53.4,19.5 8,0 21.5,0 30.5,-42.1 l 4.6,-21.3 21.6,3.1 66.7,9.6 C 544.4,163.6 552,129.9 556.1,90.3 L 426.4,71.7 C 417.8,112 401.9,132.2 373.1,132.2 335.7,132.2 259.3,73.1 181.5,73.1 76.4,73.1 23.2,139.4 7.3,276.2 l 46,6.7 c 7.6,-15.6 16.4,-29.3 26.4,-41.2 32.9,-38.8 79.5,-58.5 138.5,-58.5 z"
id="path1" /><path
d="m 409.8,265.6 c -37.4,0 -113.8,-59.1 -191.6,-59.1 -105.1,0 -158.4,66.3 -174.3,203.1 l 129.6,18.7 c 8.7,-41.8 24.5,-60.5 53.3,-60.5 38.9,0 112.3,59.1 191.6,59.1 105.1,0 159.9,-66.3 174.3,-203.1 L 463.1,205.1 c -8.7,40.3 -24.5,60.5 -53.3,60.5 z"
id="path2" />
</svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
build/icons/48x48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

BIN
build/icons/64x64.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -6,26 +6,27 @@ sidebar_position: 200
# Release Notes
### v0.10.0 &mdash; Dec 10, 2024
### v0.10.0 &mdash; Dec 11, 2024
Wave Terminal v0.10.0 introduces workspaces, making it easier to manage multiple work environments. We've added powerful new command execution capabilities with `wsh run`, allowing you to launch and control commands in dedicated blocks. This release also brings significant improvements to SSH with a new connections configuration system for managing your remote environments.
- **Workspaces**: Organize your work into separate environments, each with their own tabs, layouts, and settings
- **Command Blocks**: New `wsh run` command for launching terminal commands in dedicated blocks, with support for magnification, auto-closing, and execution control ([docs](/wsh-reference#run))
- **Connections**: New configuration system for managing SSH connections, with support for wsh-free operation, per-connection themes, and more ([docs](/connections))
- **Command Blocks**: New `wsh run` command for launching terminal commands in dedicated blocks, with support for magnification, auto-closing, and execution control ([docs](https://docs.waveterm.dev/wsh-reference#run))
- **Connections**: New configuration system for managing SSH connections, with support for wsh-free operation, per-connection themes, and more ([docs](https://docs.waveterm.dev/connections))
- Improved tab management with better switching behavior and context menus (many bug fixes)
- New tab features including pinned tabs and drag-and-drop improvements
- Create, rename, and delete files/directories directly in directory preview
- Attempt wsh-free connection as a fallback if wsh installation or execution fails
- New `-i` flag to add identity files with the `wsh ssh` command
- Added Perplexity API integration ([docs](/faq#perplexity))
- `wsh setbg` command for background handling ([docs](/wsh-reference#setbg))
- Added Perplexity API integration ([docs](https://docs.waveterm.dev/faq#perplexity))
- `wsh setbg` command for background handling ([docs](https://docs.waveterm.dev/wsh-reference#setbg))
- Switched from Less to SCSS for styling
- [bugfix] Fixed tab flickering issues during tab switches
- [bugfix] Corrected WaveAI text area resize behavior
- [bugfix] Fixed concurrent block controller start issues
- [bugfix] Fixed Preview Blocks for uninitialized connections
- Upgraded Go toolchain to 1.23.4
- Lots of new documentation, including new pages for [Getting Started](https://docs.waveterm.dev/gettingstarted), [AI Presets](https://docs.waveterm.dev/ai-presets), and [wsh overview](https://docs.waveterm.dev/wsh).
- Other bug fixes, performance improvements, and dependency updates
### v0.9.3 &mdash; Nov 20, 2024

View File

@ -49,13 +49,8 @@ async function getWorkspaceMenu(ww?: WaveBrowserWindow): Promise<Electron.MenuIt
},
];
function getWorkspaceSwitchAccelerator(i: number): string {
if (i < 10) {
if (i == 9) {
i = 0;
} else {
i++;
}
return unamePlatform == "darwin" ? `Command+Control+${i}` : `Alt+Control+${i}`;
if (i < 9) {
return unamePlatform == "darwin" ? `Command+Control+${i}` : `Alt+Control+${i + 1}`;
}
}
workspaceList?.length &&

View File

@ -46,6 +46,7 @@ class ContextMenuModelType {
}
showContextMenu(menu: ContextMenuItem[], ev: React.MouseEvent<any>): void {
ev.stopPropagation();
this.handlers.clear();
const electronMenuItems = this._convertAndRegisterMenu(menu);
getApi().showContextMenu(globalStore.get(atoms.workspace).oid, electronMenuItems);

View File

@ -142,6 +142,10 @@ function switchTab(offset: number) {
}
function handleCmdI() {
globalRefocus();
}
function globalRefocus() {
const layoutModel = getLayoutModelForStaticTab();
const focusedNode = globalStore.get(layoutModel.focusedNode);
if (focusedNode == null) {
@ -345,6 +349,7 @@ export {
appHandleKeyDown,
getAllGlobalKeyBindings,
getSimpleControlShiftAtom,
globalRefocus,
registerControlShiftStateUpdateHandler,
registerElectronReinjectKeyHandler,
registerGlobalKeys,

View File

@ -27,12 +27,12 @@
user-select: none;
display: flex;
flex-direction: row;
width: env(titlebar-area-width);
-webkit-app-region: drag;
width: 100vw;
-webkit-app-region: drag;
* {
-webkit-app-region: no-drag;
}
* {
-webkit-app-region: no-drag;
}
.tabs-wrapper {
transition: var(--tabs-wrapper-transition);
@ -40,7 +40,7 @@
}
.tab-bar {
margin-top: 6px;
margin-top: 6px;
position: relative; // Needed for absolute positioning of child tabs
display: flex;
flex-direction: row;
@ -61,7 +61,7 @@
display: flex;
align-items: center;
justify-content: center;
margin: 6px 6px 0 0;
padding: 6px 6px 0 0;
}
.app-menu-button {

View File

@ -19,7 +19,6 @@ import { WorkspaceSwitcher } from "./workspaceswitcher";
const TAB_DEFAULT_WIDTH = 130;
const TAB_MIN_WIDTH = 100;
const DRAGGER_RIGHT_MIN_WIDTH = 74;
const OS_OPTIONS = {
overflow: {
x: "scroll",
@ -168,7 +167,7 @@ const TabBar = memo(({ workspace }: TabBarProps) => {
const appMenuButtonRef = useRef<HTMLDivElement>(null);
const tabWidthRef = useRef<number>(TAB_DEFAULT_WIDTH);
const scrollableRef = useRef<boolean>(false);
const updateStatusButtonRef = useRef<HTMLButtonElement>(null);
const updateStatusBannerRef = useRef<HTMLDivElement>(null);
const configErrorButtonRef = useRef<HTMLElement>(null);
const prevAllLoadedRef = useRef<boolean>(false);
const activeTabId = useAtomValue(atoms.staticTabId);
@ -227,8 +226,9 @@ const TabBar = memo(({ workspace }: TabBarProps) => {
const tabbarWrapperWidth = tabbarWrapperRef.current.getBoundingClientRect().width;
const windowDragLeftWidth = draggerLeftRef.current.getBoundingClientRect().width;
const windowDragRightWidth = draggerRightRef.current.getBoundingClientRect().width;
const addBtnWidth = addBtnRef.current.getBoundingClientRect().width;
const updateStatusLabelWidth = updateStatusButtonRef.current?.getBoundingClientRect().width ?? 0;
const updateStatusLabelWidth = updateStatusBannerRef.current?.getBoundingClientRect().width ?? 0;
const configErrorWidth = configErrorButtonRef.current?.getBoundingClientRect().width ?? 0;
const appMenuButtonWidth = appMenuButtonRef.current?.getBoundingClientRect().width ?? 0;
const workspaceSwitcherWidth = workspaceSwitcherRef.current?.getBoundingClientRect().width ?? 0;
@ -236,7 +236,7 @@ const TabBar = memo(({ workspace }: TabBarProps) => {
const nonTabElementsWidth =
windowDragLeftWidth +
DRAGGER_RIGHT_MIN_WIDTH +
windowDragRightWidth +
addBtnWidth +
updateStatusLabelWidth +
configErrorWidth +
@ -653,7 +653,7 @@ const TabBar = memo(({ workspace }: TabBarProps) => {
<WindowDrag ref={draggerLeftRef} className="left" />
{appMenuButton}
{devLabel}
<WorkspaceSwitcher />
<WorkspaceSwitcher ref={workspaceSwitcherRef} />
<div className="tab-bar" ref={tabBarRef} data-overlayscrollbars-initialize>
<div className="tabs-wrapper" ref={tabsWrapperRef} style={{ width: `${tabsWrapperWidth}px` }}>
{tabIds.map((tabId, index) => {
@ -683,8 +683,8 @@ const TabBar = memo(({ workspace }: TabBarProps) => {
<div ref={addBtnRef} className="add-tab-btn" onClick={handleAddTab}>
<i className="fa fa-solid fa-plus fa-fw" />
</div>
<WindowDrag ref={draggerRightRef} className="right" style={{ minWidth: DRAGGER_RIGHT_MIN_WIDTH }} />
<UpdateStatusBanner buttonRef={updateStatusButtonRef} />
<WindowDrag ref={draggerRightRef} className="right" />
<UpdateStatusBanner ref={updateStatusBannerRef} />
<ConfigErrorIcon buttonRef={configErrorButtonRef} />
</div>
);

View File

@ -1,11 +1,15 @@
.update-available-button {
height: 80%;
margin: auto 4px;
color: black;
background-color: var(--accent-color);
flex: 0 0 fit-content;
.update-available-banner {
display: flex;
height: 100%;
.button {
color: black;
height: 80%;
margin: auto 4px;
background-color: var(--accent-color);
flex: 0 0 fit-content;
&:disabled {
opacity: unset !important;
&:disabled {
opacity: unset !important;
}
}
}

View File

@ -1,10 +1,10 @@
import { Button } from "@/element/button";
import { atoms, getApi } from "@/store/global";
import { useAtomValue } from "jotai";
import { memo, useEffect, useState } from "react";
import { forwardRef, memo, useEffect, useState } from "react";
import "./updatebanner.scss";
const UpdateStatusBannerComponent = ({ buttonRef }: { buttonRef: React.RefObject<HTMLButtonElement> }) => {
const UpdateStatusBannerComponent = forwardRef<HTMLDivElement>((_, ref) => {
const appUpdateStatus = useAtomValue(atoms.updaterStatusAtom);
let [updateStatusMessage, setUpdateStatusMessage] = useState<string>();
const [dismissBannerTimeout, setDismissBannerTimeout] = useState<NodeJS.Timeout>();
@ -54,17 +54,18 @@ const UpdateStatusBannerComponent = ({ buttonRef }: { buttonRef: React.RefObject
}
if (updateStatusMessage) {
return (
<Button
ref={buttonRef}
className="update-available-button"
title={appUpdateStatus === "ready" ? "Click to Install Update" : updateStatusMessage}
onClick={onClick}
disabled={appUpdateStatus !== "ready"}
>
{updateStatusMessage}
</Button>
<div className="update-available-banner" ref={ref}>
<Button
className="update-available-button"
title={appUpdateStatus === "ready" ? "Click to Install Update" : updateStatusMessage}
onClick={onClick}
disabled={appUpdateStatus !== "ready"}
>
{updateStatusMessage}
</Button>
</div>
);
}
};
});
export const UpdateStatusBanner = memo(UpdateStatusBannerComponent) as typeof UpdateStatusBannerComponent;

View File

@ -17,7 +17,7 @@ import clsx from "clsx";
import { atom, PrimitiveAtom, useAtom, useAtomValue, useSetAtom } from "jotai";
import { splitAtom } from "jotai/utils";
import { OverlayScrollbarsComponent } from "overlayscrollbars-react";
import { CSSProperties, memo, useCallback, useEffect, useRef } from "react";
import { CSSProperties, forwardRef, memo, useCallback, useEffect, useRef } from "react";
import WorkspaceSVG from "../asset/workspace.svg";
import { IconButton } from "../element/iconbutton";
import { atoms, getApi } from "../store/global";
@ -167,7 +167,7 @@ type WorkspaceList = WorkspaceListEntry[];
const workspaceMapAtom = atom<WorkspaceList>([]);
const workspaceSplitAtom = splitAtom(workspaceMapAtom);
const editingWorkspaceAtom = atom<string>();
const WorkspaceSwitcher = () => {
const WorkspaceSwitcher = forwardRef<HTMLDivElement>((_, ref) => {
const setWorkspaceList = useSetAtom(workspaceMapAtom);
const activeWorkspace = useAtomValueSafe(atoms.workspace);
const workspaceList = useAtomValue(workspaceSplitAtom);
@ -231,6 +231,7 @@ const WorkspaceSwitcher = () => {
className="workspace-switcher-popover"
placement="bottom-start"
onDismiss={() => setEditingWorkspace(null)}
ref={ref}
>
<PopoverButton
className="workspace-switcher-button grey"
@ -271,7 +272,7 @@ const WorkspaceSwitcher = () => {
</PopoverContent>
</Popover>
);
};
});
const WorkspaceSwitcherItem = ({
entryAtom,

View File

@ -45,7 +45,7 @@ class TermViewModel implements ViewModel {
viewType: string;
nodeModel: BlockNodeModel;
connected: boolean;
termRef: React.RefObject<TermWrap>;
termRef: React.MutableRefObject<TermWrap> = { current: null };
blockAtom: jotai.Atom<Block>;
termMode: jotai.Atom<string>;
blockId: string;
@ -317,12 +317,6 @@ class TermViewModel implements ViewModel {
const curStatus = globalStore.get(this.shellProcFullStatus);
if (curStatus == null || curStatus.version < fullStatus.version) {
globalStore.set(this.shellProcFullStatus, fullStatus);
const status = fullStatus?.shellprocstatus ?? "init";
if (status == "running") {
this.termRef.current?.setIsRunning?.(true);
} else {
this.termRef.current?.setIsRunning?.(false);
}
}
}
@ -724,8 +718,6 @@ const TermToolbarVDomNode = ({ blockId, model }: TerminalViewProps) => {
const TerminalView = ({ blockId, model }: TerminalViewProps) => {
const viewRef = React.useRef<HTMLDivElement>(null);
const connectElemRef = React.useRef<HTMLDivElement>(null);
const termRef = React.useRef<TermWrap>(null);
model.termRef = termRef;
const [blockData] = WOS.useWaveObjectValue<Block>(WOS.makeORef("block", blockId));
const termSettingsAtom = useSettingsPrefixAtom("term");
const termSettings = jotai.useAtomValue(termSettingsAtom);
@ -756,7 +748,7 @@ const TerminalView = ({ blockId, model }: TerminalViewProps) => {
if (termScrollback > 10000) {
termScrollback = 10000;
}
const wasFocused = termRef.current != null && globalStore.get(model.nodeModel.isFocused);
const wasFocused = model.termRef.current != null && globalStore.get(model.nodeModel.isFocused);
const termWrap = new TermWrap(
blockId,
connectElemRef.current,
@ -775,14 +767,8 @@ const TerminalView = ({ blockId, model }: TerminalViewProps) => {
useWebGl: !termSettings?.["term:disablewebgl"],
}
);
const shellProcStatus = globalStore.get(model.shellProcStatus);
if (shellProcStatus == "running") {
termWrap.setIsRunning(true);
} else if (shellProcStatus == "done") {
termWrap.setIsRunning(false);
}
(window as any).term = termWrap;
termRef.current = termWrap;
model.termRef.current = termWrap;
const rszObs = new ResizeObserver(() => {
termWrap.handleResize_debounced();
});
@ -810,14 +796,14 @@ const TerminalView = ({ blockId, model }: TerminalViewProps) => {
let stickerConfig = {
charWidth: 8,
charHeight: 16,
rows: termRef.current?.terminal.rows ?? 24,
cols: termRef.current?.terminal.cols ?? 80,
rows: model.termRef.current?.terminal.rows ?? 24,
cols: model.termRef.current?.terminal.cols ?? 80,
blockId: blockId,
};
return (
<div className={clsx("view-term", "term-mode-" + termMode)} ref={viewRef}>
<TermResyncHandler blockId={blockId} model={model} />
<TermThemeUpdater blockId={blockId} model={model} termRef={termRef} />
<TermThemeUpdater blockId={blockId} model={model} termRef={model.termRef} />
<TermStickers config={stickerConfig} />
<TermToolbarVDomNode key="vdom-toolbar" blockId={blockId} model={model} />
<TermVDomNode key="vdom" blockId={blockId} model={model} />

View File

@ -55,7 +55,6 @@ export class TermWrap {
loaded: boolean;
heldData: Uint8Array[];
handleResize_debounced: () => void;
isRunning: boolean;
hasResized: boolean;
constructor(
@ -134,7 +133,6 @@ export class TermWrap {
this.handleResize_debounced = debounce(50, this.handleResize.bind(this));
this.terminal.open(this.connectElem);
this.handleResize();
this.isRunning = true;
}
async initTerminal() {
@ -161,10 +159,6 @@ export class TermWrap {
this.runProcessIdleTimeout();
}
setIsRunning(isRunning: boolean) {
this.isRunning = isRunning;
}
dispose() {
this.terminal.dispose();
this.mainFileSubject.release();

View File

@ -3,6 +3,7 @@
import { App } from "@/app/app";
import {
globalRefocus,
registerControlShiftStateUpdateHandler,
registerElectronReinjectKeyHandler,
registerGlobalKeys,
@ -106,6 +107,9 @@ async function reinitWave() {
getApi().setWindowInitStatus("wave-ready");
globalStore.set(atoms.reinitVersion, globalStore.get(atoms.reinitVersion) + 1);
globalStore.set(atoms.updaterStatusAtom, getApi().getUpdaterStatus());
setTimeout(() => {
globalRefocus();
}, 50);
}
function reloadAllWorkspaceTabs(ws: Workspace) {

View File

@ -7,7 +7,7 @@
"productName": "Wave",
"description": "Open-Source AI-Native Terminal Built for Seamless Workflows",
"license": "Apache-2.0",
"version": "0.10.0-beta.4",
"version": "0.10.0-beta.6",
"homepage": "https://waveterm.dev",
"build": {
"appId": "dev.commandline.waveterm"

View File

@ -177,7 +177,7 @@ func CheckAndFixWindow(ctx context.Context, windowId string) *waveobj.Window {
CloseWindow(ctx, windowId, false)
return nil
}
if len(ws.TabIds) == 0 {
if len(ws.TabIds) == 0 && len(ws.PinnedTabIds) == 0 {
log.Printf("fixing workspace with no tabs %q (in checkAndFixWindow)\n", ws.OID)
_, err = CreateTab(ctx, ws.OID, "", true, false, false)
if err != nil {

View File

@ -156,11 +156,19 @@ func resolveTabNum(ctx context.Context, data wshrpc.CommandResolveIdsData, value
return nil, fmt.Errorf("error getting workspace: %v", err)
}
if tabNum < 1 || tabNum > len(ws.TabIds) {
return nil, fmt.Errorf("tab num out of range, workspace has %d tabs", len(ws.TabIds))
numPinnedTabs := len(ws.PinnedTabIds)
numTabs := len(ws.TabIds) + numPinnedTabs
if tabNum < 1 || tabNum > numTabs {
return nil, fmt.Errorf("tab num out of range, workspace has %d tabs", numTabs)
}
resolvedTabId := ws.TabIds[tabNum-1]
tabIdx := tabNum - 1
var resolvedTabId string
if tabIdx < numPinnedTabs {
resolvedTabId = ws.PinnedTabIds[tabIdx]
} else {
resolvedTabId = ws.TabIds[tabIdx-numPinnedTabs]
}
return &waveobj.ORef{OType: waveobj.OType_Tab, OID: resolvedTabId}, nil
}

View File

@ -31,28 +31,6 @@ func UpdateTabName(ctx context.Context, tabId, name string) error {
})
}
// must delete all blocks individually first
// also deletes LayoutState
func DeleteTab(ctx context.Context, workspaceId string, tabId string) error {
return WithTx(ctx, func(tx *TxWrap) error {
tab, _ := DBGet[*waveobj.Tab](tx.Context(), tabId)
if tab == nil {
return nil
}
if len(tab.BlockIds) != 0 {
return fmt.Errorf("tab has blocks, must delete blocks first")
}
ws, _ := DBGet[*waveobj.Workspace](tx.Context(), workspaceId)
if ws != nil {
ws.TabIds = utilfn.RemoveElemFromSlice(ws.TabIds, tabId)
DBUpdate(tx.Context(), ws)
}
DBDelete(tx.Context(), waveobj.OType_Tab, tabId)
DBDelete(tx.Context(), waveobj.OType_LayoutState, tab.LayoutState)
return nil
})
}
func UpdateObjectMeta(ctx context.Context, oref waveobj.ORef, meta waveobj.MetaMapType, mergeSpecial bool) error {
return WithTx(ctx, func(tx *TxWrap) error {
if oref.IsEmpty() {

View File

@ -1 +1 @@
@charset "utf-8";.fak.fa-wave-logo-solid,.fa-kit.fa-wave-logo-solid{--fa:"";--fa--fa:""}.fak,.fa-kit{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:var(--fa-display,inline-block);font-variant:normal;text-rendering:auto;font-family:Font Awesome Kit;font-style:normal;font-weight:400;line-height:1}.fak:before,.fa-kit:before{content:var(--fa)}@font-face{font-family:Font Awesome Kit;font-style:normal;font-display:block;src:url(../webfonts/custom-icons.woff2)format("woff2"),url(../webfonts/custom-icons.ttf)format("truetype")}
@charset "utf-8";.fak.fa-wave-logo-outline,.fa-kit.fa-wave-logo-outline{--fa:"";--fa--fa:""}.fak.fa-wave-logo-solid,.fa-kit.fa-wave-logo-solid{--fa:"";--fa--fa:""}.fak,.fa-kit{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;display:var(--fa-display,inline-block);font-variant:normal;text-rendering:auto;font-family:Font Awesome Kit;font-style:normal;font-weight:400;line-height:1}.fak:before,.fa-kit:before{content:var(--fa)}@font-face{font-family:Font Awesome Kit;font-style:normal;font-display:block;src:url(../webfonts/custom-icons.woff2)format("woff2"),url(../webfonts/custom-icons.ttf)format("truetype")}