mirror of
https://github.com/wavetermdev/waveterm.git
synced 2025-03-11 13:23:06 +01:00
Add sidebar banner when new release is available (#147)
* Server impl * add update check setting * add commands * fix capitalization of commands * apply suggestions * add migration and fix backend bugs * Add sidebar banner * remove installedversion, add 5s timeout * add icon, capture and log errors from release check * missing return nil * remove highlight * remove commented less * do not fail releasecheckoncommand if release check operation fails * remove debug condition * fix update on auto check, move banner display logic into frontend * remove unnecessary import * simplify null check * clean up the invoking of the releasechecker
This commit is contained in:
parent
4ff5dcf1e0
commit
b733724c7d
@ -1,3 +1,4 @@
|
||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -11,6 +11,7 @@
|
||||
"@table-nav/react": "^0.0.7",
|
||||
"@tanstack/match-sorter-utils": "^8.8.4",
|
||||
"@tanstack/react-table": "^8.10.3",
|
||||
"@types/semver": "^7.5.6",
|
||||
"autobind-decorator": "^2.4.0",
|
||||
"classnames": "^2.3.1",
|
||||
"dayjs": "^1.11.3",
|
||||
|
@ -693,6 +693,17 @@ class ClientSettingsModal extends React.Component<{}, {}> {
|
||||
commandRtnHandler(prtn, this.errorMessage);
|
||||
}
|
||||
|
||||
@boundMethod
|
||||
handleChangeReleaseCheck(val: boolean): void {
|
||||
let prtn: Promise<CommandRtnType> = null;
|
||||
if (val) {
|
||||
prtn = GlobalCommandRunner.releaseCheckAutoOn(false);
|
||||
} else {
|
||||
prtn = GlobalCommandRunner.releaseCheckAutoOff(false);
|
||||
}
|
||||
commandRtnHandler(prtn, this.errorMessage);
|
||||
}
|
||||
|
||||
getFontSizes(): any {
|
||||
let availableFontSizes: { label: string; value: number }[] = [];
|
||||
for (let s = MinFontSize; s <= MaxFontSize; s++) {
|
||||
@ -769,6 +780,12 @@ class ClientSettingsModal extends React.Component<{}, {}> {
|
||||
<Toggle checked={!cdata.clientopts.notelemetry} onChange={this.handleChangeTelemetry} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">Check for Updates Automatically</div>
|
||||
<div className="settings-input">
|
||||
<Toggle checked={!cdata.clientopts.noreleasecheck} onChange={this.handleChangeReleaseCheck} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="settings-field">
|
||||
<div className="settings-label">OpenAI Token</div>
|
||||
<div className="settings-input">
|
||||
|
@ -320,4 +320,13 @@
|
||||
top: -3px;
|
||||
}
|
||||
}
|
||||
|
||||
.updateBanner {
|
||||
font-weight: bold;
|
||||
|
||||
.icon {
|
||||
font-weight: normal;
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,7 +8,8 @@ import { boundMethod } from "autobind-decorator";
|
||||
import cn from "classnames";
|
||||
import dayjs from "dayjs";
|
||||
import type { RemoteType } from "../../types/types";
|
||||
import { If, For } from "tsx-control-statements/components";
|
||||
import { If } from "tsx-control-statements/components";
|
||||
import { compareLoose } from "semver";
|
||||
|
||||
import { ReactComponent as LeftChevronIcon } from "../assets/icons/chevron_left.svg";
|
||||
import { ReactComponent as HelpIcon } from "../assets/icons/help.svg";
|
||||
@ -22,7 +23,7 @@ import { ReactComponent as AddIcon } from "../assets/icons/add.svg";
|
||||
import { ReactComponent as ActionsIcon } from "../assets/icons/tab/actions.svg";
|
||||
|
||||
import localizedFormat from "dayjs/plugin/localizedFormat";
|
||||
import { GlobalModel, GlobalCommandRunner, Session } from "../../model/model";
|
||||
import { GlobalModel, GlobalCommandRunner, Session, VERSION } from "../../model/model";
|
||||
import { sortAndFilterRemotes, isBlank, openLink } from "../../util/util";
|
||||
import * as constants from "../appconst";
|
||||
|
||||
@ -195,6 +196,7 @@ class MainSideBar extends React.Component<{}, {}> {
|
||||
}
|
||||
let isCollapsed = this.collapsed.get();
|
||||
let mainView = GlobalModel.activeMainView.get();
|
||||
let clientData = GlobalModel.clientData.get();
|
||||
return (
|
||||
<div className={cn("main-sidebar", { collapsed: isCollapsed }, { "is-dev": GlobalModel.isDev })}>
|
||||
<div className="title-bar-drag" />
|
||||
@ -242,6 +244,15 @@ class MainSideBar extends React.Component<{}, {}> {
|
||||
</div>
|
||||
<div className="middle hideScrollbarUntillHover">{this.getSessions()}</div>
|
||||
<div className="bottom">
|
||||
<If condition = {!clientData?.clientopts.noreleasecheck && clientData?.releaseinfo && compareLoose(VERSION, clientData.releaseinfo.latestversion) < 0} >
|
||||
<div
|
||||
className="item hoverEffect unselectable updateBanner"
|
||||
onClick={() => openLink("https://www.waveterm.dev/download")}
|
||||
>
|
||||
<i className="fa-sharp fa-regular fa-circle-up icon" />
|
||||
Update Available
|
||||
</div>
|
||||
</If>
|
||||
<If condition={GlobalModel.isDev}>
|
||||
<div className="item hoverEffect unselectable" onClick={this.handlePluginsClick}>
|
||||
<AppsIcon className="icon" />
|
||||
|
@ -4312,6 +4312,14 @@ class CommandRunner {
|
||||
return GlobalModel.submitCommand("telemetry", "on", null, { nohist: "1" }, interactive);
|
||||
}
|
||||
|
||||
releaseCheckAutoOff(interactive: boolean): Promise<CommandRtnType> {
|
||||
return GlobalModel.submitCommand("releasecheck", "autooff", null, { nohist: "1" }, interactive);
|
||||
}
|
||||
|
||||
releaseCheckAutoOn(interactive: boolean): Promise<CommandRtnType> {
|
||||
return GlobalModel.submitCommand("releasecheck", "autoon", null, { nohist: "1" }, interactive);
|
||||
}
|
||||
|
||||
setTermFontSize(fsize: number, interactive: boolean): Promise<CommandRtnType> {
|
||||
let kwargs = {
|
||||
nohist: "1",
|
||||
@ -4459,5 +4467,6 @@ export {
|
||||
RemotesModel,
|
||||
MinFontSize,
|
||||
MaxFontSize,
|
||||
VERSION
|
||||
};
|
||||
export type { LineContainerModel };
|
||||
|
@ -454,9 +454,14 @@ type FeOptsType = {
|
||||
|
||||
type ClientOptsType = {
|
||||
notelemetry: boolean;
|
||||
noreleasecheck: boolean;
|
||||
acceptedtos: number;
|
||||
};
|
||||
|
||||
type ReleaseInfoType = {
|
||||
latestversion: string;
|
||||
};
|
||||
|
||||
type ClientDataType = {
|
||||
clientid: string;
|
||||
userid: string;
|
||||
@ -465,6 +470,7 @@ type ClientDataType = {
|
||||
cmdstoretype: "session" | "screen";
|
||||
dbversion: number;
|
||||
openaiopts?: OpenAIOptsType;
|
||||
releaseinfo?: ReleaseInfoType;
|
||||
};
|
||||
|
||||
type OpenAIOptsType = {
|
||||
|
@ -33,6 +33,7 @@ import (
|
||||
"github.com/wavetermdev/waveterm/waveshell/pkg/server"
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/cmdrunner"
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/pcloud"
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/releasechecker"
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/remote"
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/rtnstate"
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/scbase"
|
||||
@ -715,7 +716,6 @@ func sendTelemetryWrapper() {
|
||||
}
|
||||
log.Printf("[error] in sendTelemetryWrapper: %v\n", r)
|
||||
debug.PrintStack()
|
||||
return
|
||||
}()
|
||||
ctx, cancelFn := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancelFn()
|
||||
@ -725,14 +725,35 @@ func sendTelemetryWrapper() {
|
||||
}
|
||||
}
|
||||
|
||||
func checkNewReleaseWrapper() {
|
||||
defer func() {
|
||||
r := recover()
|
||||
if r == nil {
|
||||
return
|
||||
}
|
||||
log.Printf("[error] in checkNewReleaseWrapper: %v\n", r)
|
||||
debug.PrintStack()
|
||||
}()
|
||||
|
||||
ctx, cancelFn := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancelFn()
|
||||
|
||||
_, err := releasechecker.CheckNewRelease(ctx, false)
|
||||
if err != nil {
|
||||
log.Printf("[error] checking for new release: %v\n", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func telemetryLoop() {
|
||||
var lastSent time.Time
|
||||
time.Sleep(InitialTelemetryWait)
|
||||
for {
|
||||
dur := time.Now().Sub(lastSent)
|
||||
dur := time.Since(lastSent)
|
||||
if lastSent.IsZero() || dur >= TelemetryInterval {
|
||||
lastSent = time.Now()
|
||||
sendTelemetryWrapper()
|
||||
checkNewReleaseWrapper()
|
||||
}
|
||||
time.Sleep(TelemetryTick)
|
||||
}
|
||||
|
1
wavesrv/db/migrations/000025_releaseinfo.down.sql
Normal file
1
wavesrv/db/migrations/000025_releaseinfo.down.sql
Normal file
@ -0,0 +1 @@
|
||||
ALTER TABLE client DROP COLUMN releaseinfo;
|
1
wavesrv/db/migrations/000025_releaseinfo.up.sql
Normal file
1
wavesrv/db/migrations/000025_releaseinfo.up.sql
Normal file
@ -0,0 +1 @@
|
||||
ALTER TABLE client ADD COLUMN releaseinfo json NOT NULL DEFAULT '{}';
|
@ -22,6 +22,7 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/google/go-github/v57 v57.0.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
go.uber.org/atomic v1.7.0 // indirect
|
||||
|
@ -13,6 +13,9 @@ github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB
|
||||
github.com/golang-migrate/migrate/v4 v4.16.2 h1:8coYbMKUyInrFk1lfGfRovTLAW7PhWp8qQDT2iKfuoA=
|
||||
github.com/golang-migrate/migrate/v4 v4.16.2/go.mod h1:pfcJX4nPHaVdc5nmdCikFBWtm+UBpiZjRNNsyBbp0/o=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-github/v57 v57.0.0 h1:L+Y3UPTY8ALM8x+TV0lg+IEBI+upibemtBD8Q9u7zHs=
|
||||
github.com/google/go-github/v57 v57.0.0/go.mod h1:s0omdnye0hvK/ecLvpsGfJMiRt85PimQh4oygmLIxHw=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||
@ -51,6 +54,7 @@ golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
|
||||
golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
|
||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
mvdan.cc/sh/v3 v3.7.0 h1:lSTjdP/1xsddtaKfGg7Myu7DnlHItd3/M2tomOcNNBg=
|
||||
mvdan.cc/sh/v3 v3.7.0/go.mod h1:K2gwkaesF/D7av7Kxl0HbF5kGOd2ArupNTX3X44+8l8=
|
||||
|
@ -28,12 +28,14 @@ import (
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/comp"
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/dbutil"
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/pcloud"
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/releasechecker"
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/remote"
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/remote/openai"
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/scbase"
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/scpacket"
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/sstore"
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/utilfn"
|
||||
"golang.org/x/mod/semver"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -207,6 +209,10 @@ func init() {
|
||||
registerCmdFn("telemetry:send", TelemetrySendCommand)
|
||||
registerCmdFn("telemetry:show", TelemetryShowCommand)
|
||||
|
||||
registerCmdFn("releasecheck", ReleaseCheckCommand)
|
||||
registerCmdFn("releasecheck:autoon", ReleaseCheckOnCommand)
|
||||
registerCmdFn("releasecheck:autooff", ReleaseCheckOffCommand)
|
||||
|
||||
registerCmdFn("history", HistoryCommand)
|
||||
registerCmdFn("history:viewall", HistoryViewAllCommand)
|
||||
registerCmdFn("history:purge", HistoryPurgeCommand)
|
||||
@ -3716,6 +3722,7 @@ func ClientShowCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (s
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %s\n", "userid", clientData.UserId))
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %s\n", "clientid", clientData.ClientId))
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %s\n", "telemetry", boolToStr(clientData.ClientOpts.NoTelemetry, "off", "on")))
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %s\n", "release-check", boolToStr(clientData.ClientOpts.NoReleaseCheck, "off", "on")))
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %d\n", "db-version", dbVersion))
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %s\n", "client-version", clientVersion))
|
||||
buf.WriteString(fmt.Sprintf(" %-15s %s %s\n", "server-version", scbase.WaveVersion, scbase.BuildTime))
|
||||
@ -3832,6 +3839,102 @@ func TelemetrySendCommand(ctx context.Context, pk *scpacket.FeCommandPacketType)
|
||||
return sstore.InfoMsgUpdate("telemetry sent"), nil
|
||||
}
|
||||
|
||||
func runReleaseCheck(ctx context.Context, force bool) error {
|
||||
rslt, err := releasechecker.CheckNewRelease(ctx, force)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("error checking for new release: %v", err)
|
||||
}
|
||||
|
||||
if rslt == releasechecker.Failure {
|
||||
return fmt.Errorf("error checking for new release, see log for details")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func setNoReleaseCheck(ctx context.Context, clientData *sstore.ClientData, noReleaseCheckValue bool) error {
|
||||
clientOpts := clientData.ClientOpts
|
||||
clientOpts.NoReleaseCheck = noReleaseCheckValue
|
||||
err := sstore.SetClientOpts(ctx, clientOpts)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error trying to update client releaseCheck setting: %v", err)
|
||||
}
|
||||
log.Printf("client no-release-check setting updated to %v\n", noReleaseCheckValue)
|
||||
return nil
|
||||
}
|
||||
|
||||
func ReleaseCheckOnCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||
clientData, err := sstore.EnsureClientData(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot retrieve client data: %v", err)
|
||||
}
|
||||
if !clientData.ClientOpts.NoReleaseCheck {
|
||||
return sstore.InfoMsgUpdate("release check is already on"), nil
|
||||
}
|
||||
err = setNoReleaseCheck(ctx, clientData, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = runReleaseCheck(ctx, true)
|
||||
if err != nil {
|
||||
log.Printf("error checking for new release after enabling auto release check: %v\n", err)
|
||||
}
|
||||
|
||||
clientData, err = sstore.EnsureClientData(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot retrieve updated client data: %v", err)
|
||||
}
|
||||
update := sstore.InfoMsgUpdate("automatic release checking is now on")
|
||||
update.ClientData = clientData
|
||||
return update, nil
|
||||
}
|
||||
|
||||
func ReleaseCheckOffCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||
clientData, err := sstore.EnsureClientData(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot retrieve client data: %v", err)
|
||||
}
|
||||
if clientData.ClientOpts.NoReleaseCheck {
|
||||
return sstore.InfoMsgUpdate("release check is already off"), nil
|
||||
}
|
||||
err = setNoReleaseCheck(ctx, clientData, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
clientData, err = sstore.EnsureClientData(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot retrieve updated client data: %v", err)
|
||||
}
|
||||
update := sstore.InfoMsgUpdate("automatic release checking is now off")
|
||||
update.ClientData = clientData
|
||||
return update, nil
|
||||
}
|
||||
|
||||
func ReleaseCheckCommand(ctx context.Context, pk *scpacket.FeCommandPacketType) (sstore.UpdatePacket, error) {
|
||||
err := runReleaseCheck(ctx, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
clientData, err := sstore.EnsureClientData(ctx)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot retrieve updated client data: %v", err)
|
||||
}
|
||||
|
||||
var rsp string
|
||||
if semver.Compare(scbase.WaveVersion, clientData.ReleaseInfo.LatestVersion) < 0 {
|
||||
rsp = "new release available to download: https://www.waveterm.dev/download"
|
||||
} else {
|
||||
rsp = "no new release available"
|
||||
}
|
||||
|
||||
update := sstore.InfoMsgUpdate(rsp)
|
||||
update.ClientData = clientData
|
||||
return update, nil
|
||||
}
|
||||
|
||||
func formatTermOpts(termOpts sstore.TermOpts) string {
|
||||
if termOpts.Cols == 0 {
|
||||
return "???"
|
||||
|
75
wavesrv/pkg/releasechecker/releasechecker.go
Normal file
75
wavesrv/pkg/releasechecker/releasechecker.go
Normal file
@ -0,0 +1,75 @@
|
||||
package releasechecker
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/go-github/v57/github"
|
||||
"golang.org/x/mod/semver"
|
||||
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/scbase"
|
||||
"github.com/wavetermdev/waveterm/wavesrv/pkg/sstore"
|
||||
)
|
||||
|
||||
type ReleaseCheckResult int
|
||||
|
||||
const (
|
||||
NotNeeded ReleaseCheckResult = 0
|
||||
Success ReleaseCheckResult = 1
|
||||
Failure ReleaseCheckResult = 2
|
||||
Disabled ReleaseCheckResult = 3
|
||||
)
|
||||
|
||||
// CheckNewRelease checks for a new release and updates the release info in the DB.
|
||||
// If force is true, the release info is updated even if it is fresh or if the automatic release check is disabled.
|
||||
func CheckNewRelease(ctx context.Context, force bool) (ReleaseCheckResult, error) {
|
||||
clientData, err := sstore.EnsureClientData(ctx)
|
||||
if err != nil {
|
||||
return Failure, fmt.Errorf("error getting client data: %w", err)
|
||||
}
|
||||
|
||||
if !force && clientData.ClientOpts.NoReleaseCheck {
|
||||
return Disabled, nil
|
||||
}
|
||||
|
||||
if !force && semver.Compare(scbase.WaveVersion, clientData.ReleaseInfo.LatestVersion) < 0 {
|
||||
// We have already notified the frontend about a new release and the record is fresh. There is no need to check again.
|
||||
return NotNeeded, nil
|
||||
}
|
||||
// Initialize an unauthenticated client
|
||||
client := github.NewClient(nil)
|
||||
// Get the latest release from the repository
|
||||
release, rsp, err := client.Repositories.GetLatestRelease(ctx, "wavetermdev", "waveterm")
|
||||
|
||||
releaseInfoLatest := sstore.ReleaseInfoType{
|
||||
LatestVersion: scbase.WaveVersion,
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return Failure, fmt.Errorf("error getting latest release: %w", err)
|
||||
}
|
||||
|
||||
if rsp.StatusCode != 200 {
|
||||
return Failure, fmt.Errorf("response from Github is not success: %v", rsp)
|
||||
}
|
||||
|
||||
releaseInfoLatest.LatestVersion = *release.TagName
|
||||
|
||||
// Update the release info in the DB
|
||||
err = sstore.SetReleaseInfo(ctx, releaseInfoLatest)
|
||||
if err != nil {
|
||||
return Failure, fmt.Errorf("error updating release info: %w", err)
|
||||
}
|
||||
|
||||
clientData, err = sstore.EnsureClientData(ctx)
|
||||
if err != nil {
|
||||
return Failure, fmt.Errorf("error getting updated client data: %w", err)
|
||||
}
|
||||
|
||||
update := &sstore.ModelUpdate{
|
||||
ClientData: clientData,
|
||||
}
|
||||
sstore.MainBus.SendUpdate(update)
|
||||
|
||||
return Success, nil
|
||||
}
|
@ -22,7 +22,7 @@ import (
|
||||
"github.com/golang-migrate/migrate/v4"
|
||||
)
|
||||
|
||||
const MaxMigration = 24
|
||||
const MaxMigration = 25
|
||||
const MigratePrimaryScreenVersion = 9
|
||||
const CmdScreenSpecialMigration = 13
|
||||
const CmdLineSpecialMigration = 20
|
||||
|
@ -261,14 +261,19 @@ func (tdata *TelemetryData) Scan(val interface{}) error {
|
||||
}
|
||||
|
||||
type ClientOptsType struct {
|
||||
NoTelemetry bool `json:"notelemetry,omitempty"`
|
||||
AcceptedTos int64 `json:"acceptedtos,omitempty"`
|
||||
NoTelemetry bool `json:"notelemetry,omitempty"`
|
||||
NoReleaseCheck bool `json:"noreleasecheck,omitempty"`
|
||||
AcceptedTos int64 `json:"acceptedtos,omitempty"`
|
||||
}
|
||||
|
||||
type FeOptsType struct {
|
||||
TermFontSize int `json:"termfontsize,omitempty"`
|
||||
}
|
||||
|
||||
type ReleaseInfoType struct {
|
||||
LatestVersion string `json:"latestversion,omitempty"`
|
||||
}
|
||||
|
||||
type ClientData struct {
|
||||
ClientId string `json:"clientid"`
|
||||
UserId string `json:"userid"`
|
||||
@ -283,6 +288,7 @@ type ClientData struct {
|
||||
CmdStoreType string `json:"cmdstoretype"`
|
||||
DBVersion int `json:"dbversion" dbmap:"-"`
|
||||
OpenAIOpts *OpenAIOptsType `json:"openaiopts,omitempty" dbmap:"openaiopts"`
|
||||
ReleaseInfo ReleaseInfoType `json:"releaseinfo"`
|
||||
}
|
||||
|
||||
func (ClientData) UseDBMap() {}
|
||||
@ -1248,9 +1254,10 @@ func createClientData(tx *TxWrap) error {
|
||||
ActiveSessionId: "",
|
||||
WinSize: ClientWinSizeType{},
|
||||
CmdStoreType: CmdStoreTypeScreen,
|
||||
ReleaseInfo: ReleaseInfoType{},
|
||||
}
|
||||
query := `INSERT INTO client ( clientid, userid, activesessionid, userpublickeybytes, userprivatekeybytes, winsize, cmdstoretype)
|
||||
VALUES (:clientid,:userid,:activesessionid,:userpublickeybytes,:userprivatekeybytes,:winsize,:cmdstoretype)`
|
||||
query := `INSERT INTO client ( clientid, userid, activesessionid, userpublickeybytes, userprivatekeybytes, winsize, cmdstoretype, releaseinfo)
|
||||
VALUES (:clientid,:userid,:activesessionid,:userpublickeybytes,:userprivatekeybytes,:winsize,:cmdstoretype,:releaseinfo)`
|
||||
tx.NamedExec(query, dbutil.ToDBMap(c, false))
|
||||
log.Printf("create new clientid[%s] userid[%s] with public/private keypair\n", c.ClientId, c.UserId)
|
||||
return nil
|
||||
@ -1310,3 +1317,12 @@ func SetClientOpts(ctx context.Context, clientOpts ClientOptsType) error {
|
||||
})
|
||||
return txErr
|
||||
}
|
||||
|
||||
func SetReleaseInfo(ctx context.Context, releaseInfo ReleaseInfoType) error {
|
||||
txErr := WithTx(ctx, func(tx *TxWrap) error {
|
||||
query := `UPDATE client SET releaseinfo = ?`
|
||||
tx.Exec(query, quickJson(releaseInfo))
|
||||
return nil
|
||||
})
|
||||
return txErr
|
||||
}
|
||||
|
@ -2247,6 +2247,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.16.8.tgz#ce5ace04cfeabe7ef87c0091e50752e36707deff"
|
||||
integrity sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==
|
||||
|
||||
"@types/semver@^7.5.6":
|
||||
version "7.5.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.6.tgz#c65b2bfce1bec346582c07724e3f8c1017a20339"
|
||||
integrity sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==
|
||||
|
||||
"@types/send@*":
|
||||
version "0.17.2"
|
||||
resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.2.tgz#af78a4495e3c2b79bfbdac3955fdd50e03cc98f2"
|
||||
|
Loading…
Reference in New Issue
Block a user