From 370ea132fe94bda32a234fa1d06d728bf9b74b88 Mon Sep 17 00:00:00 2001 From: Evan Simkowitz Date: Thu, 19 Sep 2024 11:04:18 -0700 Subject: [PATCH] Save update channel to user setting automatically (#401) When a user first launches Wave, we will read the updater config and store the channel as a user setting for use on future launches. This should ensure that if a user on a beta channel gets updated to a latest release, they will still be subscribed to beta releases going forward. If a user manually updates the user setting, it will be honored. --------- Co-authored-by: sawka --- emain/emain-wsh.ts | 6 ++++++ emain/emain.ts | 9 ++++----- emain/updater.ts | 31 +++++++++++++++++++++++++++---- frontend/app/store/ws.ts | 13 +++++++++---- package.json | 3 ++- yarn.lock | 10 ++++++++++ 6 files changed, 58 insertions(+), 14 deletions(-) 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 dbc26ac0e..9447e90c9 100644 --- a/emain/emain.ts +++ b/emain/emain.ts @@ -12,7 +12,6 @@ import { sprintf } from "sprintf-js"; import { debounce } from "throttle-debounce"; import * as util from "util"; import winston from "winston"; -import { WebSocket as NodeWebSocket } from "ws"; import { initGlobal } from "../frontend/app/store/global"; import * as services from "../frontend/app/store/services"; import { initElectronWshrpc } from "../frontend/app/store/wshrpcutil"; @@ -21,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, @@ -36,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 @@ -859,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: AuthKey, wsImpl: NodeWebSocket }); + initElectronWshClient(); + initElectronWshrpc(ElectronWshClient, { authKey: AuthKey }); } catch (e) { console.log("error initializing wshrpc", e); } + await configureAutoUpdater(); globalIsStarting = false; diff --git a/emain/updater.ts b/emain/updater.ts index f04f2753f..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 updater. - const channel = settings["autoupdate:channel"]; - if (channel) { - autoUpdater.channel = channel; - } + autoUpdater.channel = getUpdateChannel(settings); autoUpdater.removeAllListeners(); diff --git a/frontend/app/store/ws.ts b/frontend/app/store/ws.ts index 31ec28109..258d2f6bf 100644 --- a/frontend/app/store/ws.ts +++ b/frontend/app/store/ws.ts @@ -66,9 +66,14 @@ class WSControl { this.lastReconnectTime = Date.now(); dlog("try reconnect:", desc); this.opening = true; - this.wsConn = newWebSocket(this.baseHostPort + "/ws?windowid=" + this.windowId, { - [AuthKeyHeader]: this.eoOpts.authKey, - }); + this.wsConn = newWebSocket( + this.baseHostPort + "/ws?windowid=" + this.windowId, + this.eoOpts + ? { + [AuthKeyHeader]: this.eoOpts.authKey, + } + : null + ); this.wsConn.onopen = this.onopen.bind(this); this.wsConn.onmessage = this.onmessage.bind(this); this.wsConn.onclose = this.onclose.bind(this); @@ -204,4 +209,4 @@ class WSControl { } } -export { WSControl, addWSReconnectHandler, removeWSReconnectHandler }; +export { WSControl, addWSReconnectHandler, removeWSReconnectHandler, type ElectronOverrideOpts }; diff --git a/package.json b/package.json index 855071128..21b16d011 100644 --- a/package.json +++ b/package.json @@ -131,7 +131,8 @@ "use-device-pixel-ratio": "^1.1.2", "utf-8-validate": "^6.0.4", "winston": "^3.14.2", - "ws": "^8.18.0" + "ws": "^8.18.0", + "yaml": "^2.5.1" }, "packageManager": "yarn@4.4.1" } diff --git a/yarn.lock b/yarn.lock index ff58aebf6..1e86a7f0a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10311,6 +10311,7 @@ __metadata: vitest: "npm:^2.1.1" winston: "npm:^3.14.2" ws: "npm:^8.18.0" + yaml: "npm:^2.5.1" languageName: unknown linkType: soft @@ -11305,6 +11306,15 @@ __metadata: languageName: node linkType: hard +"yaml@npm:^2.5.1": + version: 2.5.1 + resolution: "yaml@npm:2.5.1" + bin: + yaml: bin.mjs + checksum: 10c0/40fba5682898dbeeb3319e358a968fe886509fab6f58725732a15f8dda3abac509f91e76817c708c9959a15f786f38ff863c1b88062d7c1162c5334a7d09cb4a + languageName: node + linkType: hard + "yargs-parser@npm:^21.1.1": version: 21.1.1 resolution: "yargs-parser@npm:21.1.1"