@@ -25,7 +25,7 @@ Install Wave Terminal from: [www.waveterm.dev/download](https://www.waveterm.dev
Also available as a homebrew cask for MacOS:
-```
+```bash
brew install --cask wave
```
diff --git a/RELEASES.md b/RELEASES.md
index 2bc7dc917..1c32cc6cb 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -3,9 +3,14 @@
## Step-by-step guide
1. Go to the [Actions tab](https://github.com/wavetermdev/thenextwave/actions) and select "Bump Version" from the left sidebar.
-2. Click on "Run workflow". You will see two options:
- - "SemVer Bump": This defaults to `none`. Adjust this if you want to increment the version number according to semantic versioning rules (`patch`, `minor`, `major`).
- - "Is Prerelease": This defaults to `true`. If set to `true`, a `-beta.X` version will be appended to the end of the version. If one is already present and the base SemVer is not being incremented, the `-beta` version will be incremented (i.e. `0.1.13-beta.0` to `0.1.13-beta.1`).
+2. Click on "Run workflow".
+ - You will see two options:
+ - "SemVer Bump": This defaults to `none`. Adjust this if you want to increment the version number according to semantic versioning rules (`patch`, `minor`, `major`).
+ - "Is Prerelease": This defaults to `true`. If set to `true`, a `-beta.X` version will be appended to the end of the version. If one is already present and the base SemVer is not being incremented, the `-beta` version will be incremented (i.e. `0.1.13-beta.0` to `0.1.13-beta.1`). If set to `false`, the `-beta.X` suffix will be removed from the version number. If one was not already present, it will remain absent.
+ - Some examples:
+ - If you are creating a new prerelease following an official release, you would set "SemVer Bump" to to the expected version bump (`patch`, `minor`, or `major`) and "Is Prerelease" to `true`.
+ - If you are bumping an existing prerelease to a new prerelease under the same version, you would set "SemVer Bump" to `none` and "Is Prerelease" to `true`.
+ - If you are promoting a prerelease version to an official release, you would set "SemVer Bump" to `none` and "Is Prerelease" to `false`.
3. After "Bump Version" a "Build Helper" run will kick off automatically for the new version. When this completes, it will generate a draft GitHub Release with all the built artifacts.
4. Review the artifacts in the release and test them locally.
5. When you are confident that the build is good, edit the GitHub Release to add a changelog and release summary and publish the release.
@@ -29,7 +34,7 @@ Our release builds are managed by the [Build Helper workflow](https://github.com
Under the hood, this will call the `package` task in [`Taskfile.yml`](../../Taskfile.yml), which will build the `wavesrv` and `wsh` binaries, then the frontend and Electron codebases using Vite, then it will call `electron-builder` to generate the distributable app packages. The configuration for `electron-builder` is defined in [`electron-builder.config.cjs`](../../electron-builder.config.cjs).
-This will also sign and notarize the macOS app package.
+This will also sign and notarize the macOS app packages and sign the Windows packages.
Once a build is complete, it will be placed in `s3://waveterm-github-artifacts/staging-w2/`. It can be downloaded for testing using the `artifacts:download:*` task. When you are ready to publish the artifacts to the public release feed, use the `artifacts:publish:*` task to directly copy the artifacts from the staging bucket to the releases bucket.
diff --git a/Taskfile.yml b/Taskfile.yml
index 8e4884821..280d632f7 100644
--- a/Taskfile.yml
+++ b/Taskfile.yml
@@ -203,16 +203,7 @@ tasks:
- frontend/app/store/wshserver.ts
version:
- desc: Get the current package version, or bump version if args are present. To pass args to `version.cjs`, add them after `--`.
- summary: |
- If no arguments are present, the current version will be returned.
- If only a single argument is given, the following are valid inputs:
- - `none`: No-op.
- - `patch`: Bumps the patch version.
- - `minor`: Bumps the minor version.
- - `major`: Bumps the major version.
- - '1', 'true': Bumps the prerelease version.
- If two arguments are given, the first argument must be either `none`, `patch`, `minor`, or `major`. The second argument must be `1` or `true` to bump the prerelease version.
+ desc: Get the current package version, or bump version if args are present. To pass args to `version.cjs`, add them after `--`. See `version.cjs` for usage definitions for the arguments.
cmd: node version.cjs {{.CLI_ARGS}}
artifacts:upload:
diff --git a/assets/wave-dark.png b/assets/wave-dark.png
new file mode 100644
index 000000000..e9cf7cb36
Binary files /dev/null and b/assets/wave-dark.png differ
diff --git a/assets/wave-light.png b/assets/wave-light.png
new file mode 100644
index 000000000..ab3d58b88
Binary files /dev/null and b/assets/wave-light.png differ
diff --git a/assets/waveterm-logo-horizontal-dark.png b/assets/waveterm-logo-horizontal-dark.png
new file mode 100644
index 000000000..904d56357
Binary files /dev/null and b/assets/waveterm-logo-horizontal-dark.png differ
diff --git a/assets/waveterm-logo-horizontal-light.png b/assets/waveterm-logo-horizontal-light.png
new file mode 100644
index 000000000..bb6ce4dbd
Binary files /dev/null and b/assets/waveterm-logo-horizontal-light.png differ
diff --git a/electron.vite.config.ts b/electron.vite.config.ts
index 2a7ab6fe0..dc5f95daa 100644
--- a/electron.vite.config.ts
+++ b/electron.vite.config.ts
@@ -26,6 +26,10 @@ export default defineConfig({
"@": "frontend",
},
},
+ define: {
+ "process.env.WS_NO_BUFFER_UTIL": "true",
+ "process.env.WS_NO_UTF_8_VALIDATE": "true",
+ },
},
preload: {
root: ".",
diff --git a/emain/emain-wsh.ts b/emain/emain-wsh.ts
index 45812456e..6c95ad0d3 100644
--- a/emain/emain-wsh.ts
+++ b/emain/emain-wsh.ts
@@ -29,3 +29,9 @@ export class ElectronWshClientType extends WshClient {
return rtn;
}
}
+
+export let ElectronWshClient: ElectronWshClientType;
+
+export function initElectronWshClient() {
+ ElectronWshClient = new ElectronWshClientType();
+}
diff --git a/emain/emain.ts b/emain/emain.ts
index 5138cb19a..9447e90c9 100644
--- a/emain/emain.ts
+++ b/emain/emain.ts
@@ -20,7 +20,7 @@ import { fetch } from "../frontend/util/fetchutil";
import * as keyutil from "../frontend/util/keyutil";
import { fireAndForget } from "../frontend/util/util";
import { AuthKey, AuthKeyEnv, configureAuthKeyRequestInjection } from "./authkey";
-import { ElectronWshClientType } from "./emain-wsh";
+import { ElectronWshClient, initElectronWshClient } from "./emain-wsh";
import { getAppMenu } from "./menu";
import {
getElectronAppBasePath,
@@ -35,7 +35,6 @@ import {
} from "./platform";
import { configureAutoUpdater, updater } from "./updater";
-let ElectronWshClient = new ElectronWshClientType();
const electronApp = electron.app;
let WaveVersion = "unknown"; // set by WAVESRV-ESTART
let WaveBuildTime = 0; // set by WAVESRV-ESTART
@@ -858,13 +857,14 @@ async function appMain() {
await electronApp.whenReady();
configureAuthKeyRequestInjection(electron.session.defaultSession);
await relaunchBrowserWindows();
- await configureAutoUpdater();
setTimeout(runActiveTimer, 5000); // start active timer, wait 5s just to be safe
try {
- initElectronWshrpc(ElectronWshClient, AuthKey);
+ initElectronWshClient();
+ initElectronWshrpc(ElectronWshClient, { authKey: AuthKey });
} catch (e) {
console.log("error initializing wshrpc", e);
}
+ await configureAutoUpdater();
globalIsStarting = false;
diff --git a/emain/preload.ts b/emain/preload.ts
index e92972923..96881a369 100644
--- a/emain/preload.ts
+++ b/emain/preload.ts
@@ -27,6 +27,7 @@ contextBridge.exposeInMainWorld("api", {
ipcRenderer.on("fullscreen-change", (_event, isFullScreen) => callback(isFullScreen)),
onUpdaterStatusChange: (callback) => ipcRenderer.on("app-update-status", (_event, status) => callback(status)),
getUpdaterStatus: () => ipcRenderer.sendSync("get-app-update-status"),
+ getUpdaterChannel: () => ipcRenderer.sendSync("get-updater-channel"),
installAppUpdate: () => ipcRenderer.send("install-app-update"),
onMenuItemAbout: (callback) => ipcRenderer.on("menu-item-about", callback),
updateWindowControlsOverlay: (rect) => ipcRenderer.send("update-window-controls-overlay", rect),
diff --git a/emain/updater.ts b/emain/updater.ts
index f9784d933..d68ff1752 100644
--- a/emain/updater.ts
+++ b/emain/updater.ts
@@ -1,14 +1,37 @@
// Copyright 2024, Command Line Inc.
// SPDX-License-Identifier: Apache-2.0
+import { RpcApi } from "@/app/store/wshclientapi";
import { BrowserWindow, dialog, ipcMain, Notification } from "electron";
import { autoUpdater } from "electron-updater";
+import { readFileSync } from "fs";
+import path from "path";
+import YAML from "yaml";
import { FileService } from "../frontend/app/store/services";
import { isDev } from "../frontend/util/isdev";
import { fireAndForget } from "../frontend/util/util";
+import { ElectronWshClient } from "./emain-wsh";
export let updater: Updater;
+function getUpdateChannel(settings: SettingsType): string {
+ const updaterConfigPath = path.join(process.resourcesPath!, "app-update.yml");
+ const updaterConfig = YAML.parse(readFileSync(updaterConfigPath, { encoding: "utf8" }).toString());
+ console.log("Updater config from binary:", updaterConfig);
+ const updaterChannel: string = updaterConfig.channel ?? "latest";
+ const settingsChannel = settings["autoupdate:channel"];
+ let retVal = settingsChannel;
+
+ // If the user setting doesn't exist yet, set it to the value of the updater config.
+ if (!settingsChannel) {
+ console.log("Update channel setting does not exist, setting to value from updater config.");
+ RpcApi.SetConfigCommand(ElectronWshClient, { "autoupdate:channel": updaterChannel });
+ retVal = updaterChannel;
+ }
+ console.log("Update channel:", retVal);
+ return retVal;
+}
+
export class Updater {
autoCheckInterval: NodeJS.Timeout | null;
intervalms: number;
@@ -20,7 +43,9 @@ export class Updater {
constructor(settings: SettingsType) {
this.intervalms = settings["autoupdate:intervalms"];
+ console.log("Update check interval in milliseconds:", this.intervalms);
this.autoCheckEnabled = settings["autoupdate:enabled"];
+ console.log("Update check enabled:", this.autoCheckEnabled);
this._status = "up-to-date";
this.lastUpdateCheck = new Date(0);
@@ -28,12 +53,10 @@ export class Updater {
this.availableUpdateReleaseName = null;
autoUpdater.autoInstallOnAppQuit = settings["autoupdate:installonquit"];
+ console.log("Install update on quit:", settings["autoupdate:installonquit"]);
- // Only update the release channel if it's specified, otherwise use the one configured in the artifact.
- const channel = settings["autoupdate:channel"];
- if (channel) {
- autoUpdater.channel = channel;
- }
+ // Only update the release channel if it's specified, otherwise use the one configured in the updater.
+ autoUpdater.channel = getUpdateChannel(settings);
autoUpdater.removeAllListeners();
@@ -50,10 +73,12 @@ export class Updater {
autoUpdater.on("update-available", () => {
console.log("update-available; downloading...");
+ this.status = "downloading";
});
autoUpdater.on("update-not-available", () => {
console.log("update-not-available");
+ this.status = "up-to-date";
});
autoUpdater.on("update-downloaded", (event) => {
@@ -180,6 +205,9 @@ ipcMain.on("install-app-update", () => fireAndForget(() => updater?.promptToInst
ipcMain.on("get-app-update-status", (event) => {
event.returnValue = updater?.status;
});
+ipcMain.on("get-updater-channel", (event) => {
+ event.returnValue = isDev() ? "dev" : (autoUpdater.channel ?? "latest");
+});
let autoUpdateLock = false;
diff --git a/frontend/app/element/button.less b/frontend/app/element/button.less
index 8d74b84b9..dc383dbe2 100644
--- a/frontend/app/element/button.less
+++ b/frontend/app/element/button.less
@@ -1,5 +1,5 @@
-/* Copyright 2024, Command Line Inc. */
-/* SPDX-License-Identifier: Apache-2.0 */
+// Copyright 2024, Command Line Inc.
+// SPDX-License-Identifier: Apache-2.0
.button {
// override default button appearance
@@ -26,41 +26,41 @@
&.solid {
&.green {
- color: #000000;
+ color: var(--button-text-color);
background-color: var(--accent-color);
- border: 1px solid #29f200;
+ border: 1px solid var(--button-green-border-color);
&:hover {
- color: #000000;
- background-color: #29f200;
+ color: var(--button-text-color);
+ background-color: var(--button-green-border-color);
}
}
&.grey {
- background-color: rgba(255, 255, 255, 0.04);
- border: 1px solid rgba(255, 255, 255, 0.1);
+ background-color: var(--button-grey-bg);
+ border: 1px solid var(--button-grey-bg);
color: var(--main-text-color);
&:hover {
color: var(--main-text-color);
- background-color: rgba(255, 255, 255, 0.09);
+ background-color: var(--button-grey-hover-bg);
}
}
&.red {
- background-color: #cc0000;
- border: 1px solid #fc3131;
+ background-color: var(--button-red-bg);
+ border: 1px solid var(--button-red-border-color);
color: var(--main-text-color);
&:hover {
- background-color: #f93939;
+ background-color: var(--button-red-hover-bg);
}
}
&.yellow {
- color: #000000;
- background-color: #c4a000;
- border: 1px solid #fce94f;
+ color: var(--button-text-color);
+ background-color: var(--button-yellow-bg);
+ border: 1px solid var(--button-yellow-hover-bg);
&:hover {
- color: #000000;
- background-color: #fce94f;
+ color: var(--button-text-color);
+ background-color: var(--button-yellow-hover-bg);
}
}
}
@@ -71,14 +71,14 @@
color: var(--accent-color);
border: 1px solid var(--accent-color);
&:hover {
- color: #29f200;
- border: 1px solid #29f200;
+ color: var(--button-green-border-color);
+ border: 1px solid var(--button-green-border-color);
}
}
&.grey {
- border: 1px solid rgba(255, 255, 255, 0.6);
- color: rgba(255, 255, 255, 0.6);
+ border: 1px solid var(--button-grey-outlined-color);
+ color: var(--button-grey-outlined-color);
&:hover {
color: var(--main-text-color);
border: 1px solid var(--main-text-color);
@@ -86,20 +86,20 @@
}
&.red {
- border: 1px solid #cc0000;
- color: #cc0000;
+ border: 1px solid var(--button-red-bg);
+ color: var(--button-red-bg);
&:hover {
- color: #ff3c3c;
- border: 1px solid #ff3c3c;
+ color: var(--button-red-outlined-color);
+ border: 1px solid var(--button-red-outlined-color);
}
}
&.yellow {
- color: #c4a000;
- border: 1px solid #c4a000;
+ color: var(--button-yellow-bg);
+ border: 1px solid var(--button-yellow-bg);
&:hover {
- color: #fce94f;
- border: 1px solid #fce94f;
+ color: var(--button-yellow-hover-bg);
+ border: 1px solid var(--button-yellow-hover-bg);
}
}
}
@@ -115,13 +115,13 @@
border: none;
color: var(--accent-color);
&:hover {
- color: #29f200;
+ color: var(--button-green-border-color);
}
}
&.grey {
border: none;
- color: rgba(255, 255, 255, 0.6);
+ color: var(--button-grey-outlined-color);
&:hover {
color: var(--main-text-color);
}
@@ -129,24 +129,25 @@
&.red {
border: none;
- color: #cc0000;
+ color: var(--button-red-bg);
&:hover {
- color: #fc3131;
+ color: var(--button-red-border-color);
}
}
&.yellow {
border: none;
- color: #c4a000;
+ color: var(--button-yellow-bg);
&:hover {
- color: #fce94f;
+ color: var(--button-yellow-hover-bg);
}
}
}
- &.disabled {
+ &:disabled {
cursor: default;
opacity: 0.5;
+ pointer-events: none;
}
&:focus,
diff --git a/frontend/app/element/button.tsx b/frontend/app/element/button.tsx
index 75403e34b..964671c47 100644
--- a/frontend/app/element/button.tsx
+++ b/frontend/app/element/button.tsx
@@ -35,9 +35,7 @@ const Button = memo(